--- bsd-finger-0.17/finger/finger.c.widechar 2005-12-15 09:14:18.000000000 +0100 +++ bsd-finger-0.17/finger/finger.c 2005-12-15 09:14:18.000000000 +0100 @@ -77,6 +77,7 @@ #include #include #include +#include #include "finger.h" #include "../version.h" @@ -96,6 +96,9 @@ struct sockaddr_in sin; socklen_t slen = sizeof(sin); + if (setlocale (LC_ALL, "") != NULL) + set_haslocale(); + while ((ch = getopt(argc, argv, "lmps")) != EOF) { switch(ch) { case 'l': --- bsd-finger-0.17/finger/finger.h.widechar 2005-12-15 09:14:17.000000000 +0100 +++ bsd-finger-0.17/finger/finger.h 2005-12-15 09:14:18.000000000 +0100 @@ -117,3 +117,8 @@ /* terminal inquiries */ int is8bit(void); int getscreenwidth(void); + +/* locale support */ +extern int has_locale; +void set_haslocale(void); + --- bsd-finger-0.17/finger/display.c.widechar 1999-09-29 00:53:58.000000000 +0200 +++ bsd-finger-0.17/finger/display.c 2005-12-15 10:05:40.000000000 +0100 @@ -40,8 +40,19 @@ #include #include #include +#include #include "finger.h" +#define HAVE_WCHAR_H 1 +#define HAVE_MBRTOWC 1 +#define HAVE_WCWIDTH 1 + +#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) +#include +#include +#include +#endif + int getscreenwidth(void) { @@ -147,9 +158,105 @@ fxputc(stdout, ch); } +int has_locale = 0; + +void +set_haslocale (void) +{ + has_locale = 1; +} + +#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) +static int verifymultibyte(const char *buf) { + mbstate_t state; + wchar_t nextchar; + size_t bytesconsumed; + char *eop, *op; + (void)memset(&state, 0, sizeof(mbstate_t)); + + eop = (char *) (buf + strlen(buf)); + op = (char *) buf; + while (op < eop) { + bytesconsumed = mbrtowc(&nextchar, op, eop - op, &state); + if (bytesconsumed == (size_t)(-1) || + bytesconsumed == (size_t)(-2)) { + return 0; + } + op += bytesconsumed; + } + + return 1; +} + +#define OCTALIFY(n, o) \ + *(n)++ = '\\', \ + *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \ + *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \ + *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \ + (o)++ + +#endif + static void fxputs(FILE *f, const char *buf) { - int i; - for (i=0; buf[i]; i++) fxputc(f, buf[i]); + int widechars; + +#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) + if (has_locale) + widechars = verifymultibyte (buf); + else + widechars = 0; +#else + widechars = 0; +#endif + + /* on 7-bit terminals, without wide-chars support, or string + * isn't parseable, print char * by char */ + if (!is8bit() || !widechars) { + unsigned int i; + char ch; + for (i = 0; i < strlen (buf); i++) { + ch = buf[i]; + fxputc(f, ch); + } + return; + } + +#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) + { + mbstate_t state; + wchar_t nextchar; + size_t bytesconsumed; + char *eop, *op, buffer[256]; + (void)memset(&state, 0, sizeof(mbstate_t)); + char* op1; + eop = (char *) (buf + strlen(buf)); + op = (char *) buf; + op1 = op; + while (op < eop) { + bytesconsumed = mbrtowc(&nextchar, op, + eop - op, &state); + /* This isn't supposed to happen as we verified the + * string before hand */ + assert(bytesconsumed != (size_t)(-1) && bytesconsumed != (size_t)(-2)); + + if (iswprint(nextchar)) { + (void)memcpy(buffer, op, bytesconsumed); + buffer[bytesconsumed] = '\0'; + op += bytesconsumed; + } else if (bytesconsumed == 1) { + op++; + } else { + char *tmp; + tmp = buffer; + buffer[bytesconsumed] = '\0'; + while (bytesconsumed-- > 0) { + OCTALIFY(tmp, op); + } + } + } + fprintf(f,"%s",op1); + } +#endif } int xprintf(const char *fmt, ...) {