diff options
| author | Gustav HÃ¥llberg <gustav@gmail.com> | 2008-12-31 18:42:35 (GMT) | 
|---|---|---|
| committer | Gustav HÃ¥llberg <gustav@gmail.com> | 2009-01-16 23:37:02 (GMT) | 
| commit | 83520824ab7339a8565756c0d95823d997788a1c (patch) | |
| tree | 7d2d2ac2e0241af522c04fb8fef5c9a4fd2008e4 | |
| parent | 7d440d48e6465ef859d3a88032b1d5c021ff9894 (diff) | |
| download | powwow-83520824ab7339a8565756c0d95823d997788a1c.zip powwow-83520824ab7339a8565756c0d95823d997788a1c.tar.gz powwow-83520824ab7339a8565756c0d95823d997788a1c.tar.bz2 | |
manually buffer data written to tty with USE_LOCALE; this fixes
buffering problems for some platforms
| -rw-r--r-- | ChangeLog.old | 2 | ||||
| -rw-r--r-- | tty.c | 85 | 
2 files changed, 74 insertions, 13 deletions
| diff --git a/ChangeLog.old b/ChangeLog.old index 2a62a51..19af2e7 100644 --- a/ChangeLog.old +++ b/ChangeLog.old @@ -1,5 +1,7 @@  2008-12-29        dain +	* tty.c: Manually buffer tty output to fix output problems on some +	  platforms with USE_LOCALE.  	* edit.c: Fixed display bug when a partial ANSI code was received  	  in one TCP packet @@ -9,6 +9,7 @@   *  (at your option) any later version.   *   */ +#include <assert.h>  #include <errno.h>  #include <fcntl.h>  #include <limits.h> @@ -143,9 +144,15 @@ int tty_read_fd = 0;  static int wrapglitch = 0;  #ifdef USE_LOCALE -FILE *tty_read_stream, *tty_write_stream; +FILE *tty_read_stream;  static int orig_read_fd_fl; -#endif +static struct { +    mbstate_t mbstate;              /* multibyte output shift state */ +    char      data[4096];           /* buffer for pending data */ +    size_t    used;                 /* bytes used of data */ +    int       fd;                   /* file descriptor to write to */ +} tty_write_state; +#endif  /* USE_LOCALE */  #ifdef USE_SGTTY  static struct sgttyb ttybsave; @@ -198,12 +205,17 @@ void tty_start __P0 (void)      tty_puts(kpadstart);      tty_flush(); -     -#ifdef DEBUG_TTY + +#ifdef USE_LOCALE +    tty_write_state.fd = 1; +    wcrtomb(NULL, L'\0', &tty_write_state.mbstate); +#else  /* ! USE_LOCALE */ + #ifdef DEBUG_TTY      setvbuf(stdout, NULL, _IONBF, BUFSIZ); -#else + #else      setvbuf(stdout, NULL, _IOFBF, BUFSIZ); -#endif + #endif +#endif  /* ! USE_LOCALE */  }  /* @@ -312,7 +324,6 @@ void tty_bootstrap __P0 (void)  {  #ifdef USE_LOCALE      tty_read_stream = stdin; -    tty_write_stream = stdout;  #endif  #ifndef USE_VT100 @@ -804,15 +815,35 @@ void input_insert_follow_chars __P2 (char *,str, int,n)  void tty_puts __P ((const char *s))  {      while (*s) -	putwc((unsigned char)*s++, tty_write_stream); +        tty_putc(*s++);  }  void tty_putc __P ((char c))  { -    putwc((unsigned char)c, tty_write_stream); +    size_t r; +    int ignore_error = 0; +    if (tty_write_state.used + MB_LEN_MAX > sizeof tty_write_state.data) +        tty_flush(); +again: +    r = wcrtomb(tty_write_state.data + tty_write_state.used, (unsigned char)c, +                &tty_write_state.mbstate); +    if (r == (size_t)-1) { +        if (ignore_error) +            return; +        if (errno != EILSEQ) { +            perror("mcrtomb()"); +            abort(); +        } +        /* character cannot be represented; try to write a question +         * mark instead, but ignore any errors */ +        ignore_error = 1; +        c = '?'; +        goto again; +    } +    assert(r <= MB_LEN_MAX); +    tty_write_state.used += r;  } -  void tty_printf __P ((const char *format, ...))  {      char buf[1024], *bufp = buf; @@ -831,6 +862,7 @@ void tty_printf __P ((const char *format, ...))  	bufp = alloca(res + 1);  	va_start(va, format);  	vsprintf(bufp, format, va); +        assert(strlen(bufp) == res);  	va_end(va);      } @@ -921,13 +953,40 @@ void tty_gets __P ((char *s, int size))  void tty_flush __P ((void))  { -    fflush(tty_write_stream); +    size_t n = tty_write_state.used; +    char *data = tty_write_state.data; +    while (n > 0) { +        ssize_t r; +        do { +            r = write(tty_write_state.fd, data, n); +        } while (r < 0 && (errno == EAGAIN || errno == EINTR)); +        if (r < 0) { +            fprintf(stderr, "Cannot write to tty: %s\n", strerror(errno)); +            abort(); +        } +        n -= r; +        data += r; +    } +    tty_write_state.used = 0;  }  void tty_raw_write __P ((char *data, int len))  { -    tty_flush(); -    write(1, data, len); +    assert(len >= 0); + +    if (len == 0) return; + +    for (;;) { +        size_t s = sizeof tty_write_state.data - tty_write_state.used; +        if (s > len) s = len; +        memcpy(tty_write_state.data + tty_write_state.used, data, s); +        len -= s; +        tty_write_state.used += s; +        if (len == 0) +            break; +        data += s; +        tty_flush(); +    }  }  #endif /* USE_LOCALE */ | 
