From 22e6d965aa95a519d2b5672ee2c888785fc524ee Mon Sep 17 00:00:00 2001 From: Steve Slaven Date: Mon, 21 Mar 2005 20:49:24 +0000 Subject: Wide character (locale) support from Dain, changed output of the compiled options line since there are more compile time options now diff --git a/cmd2.c b/cmd2.c index 301d9ae..06892ed 100644 --- a/cmd2.c +++ b/cmd2.c @@ -1059,7 +1059,7 @@ static int get_one_char __P1 (int,timeout) errmsg("select"); return -1; } - while ((err = tty_read(tty_read_fd, &c, 1)) < 0 && errno == EINTR) + while ((err = tty_read(&c, 1)) < 0 && errno == EINTR) ; if (err != 1) { errmsg("read from tty"); diff --git a/configure b/configure index 913b228..de08f52 100755 --- a/configure +++ b/configure @@ -3869,6 +3869,150 @@ fi done +if test "${ac_cv_header_locale_h+set}" = set; then + echo "$as_me:$LINENO: checking for locale.h" >&5 +echo $ECHO_N "checking for locale.h... $ECHO_C" >&6 +if test "${ac_cv_header_locale_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 +echo "${ECHO_T}$ac_cv_header_locale_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking locale.h usability" >&5 +echo $ECHO_N "checking locale.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking locale.h presence" >&5 +echo $ECHO_N "checking locale.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: locale.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: locale.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: locale.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: locale.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: locale.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: locale.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: locale.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: locale.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for locale.h" >&5 +echo $ECHO_N "checking for locale.h... $ECHO_C" >&6 +if test "${ac_cv_header_locale_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_locale_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 +echo "${ECHO_T}$ac_cv_header_locale_h" >&6 + +fi +if test $ac_cv_header_locale_h = yes; then + cat >>confdefs.h <<\_ACEOF +#define USE_LOCALE 1 +_ACEOF + +fi + + # Checks for typedefs, structures, and compiler characteristics. echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 diff --git a/configure.in b/configure.in index 89f0a27..15da9b6 100644 --- a/configure.in +++ b/configure.in @@ -39,6 +39,7 @@ AC_CHECK_LIB(dl,dlopen) # Checks for header files. AC_CHECK_HEADERS([stdlib.h unistd.h]) +AC_CHECK_HEADER(locale.h,AC_DEFINE(USE_LOCALE)) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST diff --git a/main.c b/main.c index 5afb94f..c160504 100644 --- a/main.c +++ b/main.c @@ -30,9 +30,19 @@ * #define POWWOW_DIR "/home/gustav/powwow" */ -#define POWWOW_VERSION VERSION ", Copyright 2000-2005 by Cosmos\n" \ - " Copyright 2005 by bpk - http://hoopajoo.net\n" \ - "(contributions by Yorick, Vivriel, Thuzzle, Ilie, Fror, Dain)\n" +#ifdef USE_LOCALE + #define POWWOW_HACKERS "Yorick, Vivriel, Thuzzle, Ilie, Fr\363r, D\341in" + #define COPYRIGHT "\251 " +#else + #define POWWOW_HACKERS "Yorick, Vivriel, Thuzzle, Ilie, Fror, Dain" + #define COPYRIGHT "" +#endif + +#define POWWOW_VERSION VERSION \ + ", Copyright 2000-2005 by Cosmos\n" \ + "Copyright 2005 by bpk - http://hoopajoo.net\n" \ + "(contributions by " POWWOW_HACKERS ")\n" + #define HELPNAME "powwow.help" #define COPYNAME "COPYING" @@ -56,6 +66,10 @@ #include #include +#ifdef USE_LOCALE +#include +#endif + /* are these really needed? */ extern int errno; extern int select(); @@ -227,7 +241,13 @@ int main __P2 (int,argc, char **,argv) int i; int read_file = 0; /* GH: if true, powwow was started with * a file argument, and initstr shall be ran */ - + +#ifdef USE_LOCALE + if (!setlocale(LC_ALL, "")) { + fprintf(stderr, "Failed setlocale(LC_ALL, \"C\")\n"); + } +#endif + /* initializations */ initstr[0] = 0; memzero(conn_list, sizeof(conn_list)); @@ -399,26 +419,33 @@ under certain conditions; type \"#help copyright\" for details.\n" */ void printver __P0 (void) { - tty_printf("Powwow version %s\n%s (%s, %s)%s\n", POWWOW_VERSION, -#if __STDC__ - "compiled " __TIME__ " " __DATE__, -#else - "", -#endif + tty_printf("Powwow version %s\nOptions: %s%s\n", POWWOW_VERSION, #ifdef USE_VT100 - "vt100-only", + "vt100-only," #else - "termcaps", + "termcaps," #endif #ifdef USE_SGTTY - "BSD sgtty", + " BSD sgtty," #else - "termios", + " termios," #endif #ifdef USE_REGEXP - "" + " regexp," +#else + " no regexp," +#endif +#ifdef USE_LOCALE + " locale," +#endif +#ifdef HAVE_LIBDL + " modules," +#endif + , +#if __STDC__ + " compiled " __TIME__ " " __DATE__ #else - " no regexp" + " uknown compile date" #endif ); } @@ -1282,7 +1309,7 @@ static void get_user_input __P0 (void) if (!(linemode & (LM_NOECHO | LM_CHAR))) /* line mode, local echo */ chunk = BUFSIZE; - while ((j = tty_read(tty_read_fd, c, chunk)) < 0 && errno == EINTR) + while ((j = tty_read(c, chunk)) < 0 && errno == EINTR) ; if (j <= 0 || (chunk == 1 && j != chunk)) syserr("read from tty"); diff --git a/tty.c b/tty.c index 0ac7b3c..7053407 100644 --- a/tty.c +++ b/tty.c @@ -9,13 +9,22 @@ * (at your option) any later version. * */ +#include +#include +#include +#include #include #include #include -#include #include +#include #include +#ifdef USE_LOCALE +#include +#include +#endif + #include "defines.h" #include "main.h" #include "edit.h" @@ -133,6 +142,9 @@ char *tty_modebold = modebold, *tty_modeblink = modeblink, int tty_read_fd = 0; static int wrapglitch = 0; +#ifdef USE_LOCALE +FILE *tty_read_stream, *tty_write_stream; +#endif #ifdef USE_SGTTY static struct sgttyb ttybsave; @@ -289,6 +301,12 @@ void tty_sig_winch_bottomhalf __P0 (void) */ void tty_bootstrap __P0 (void) { +#ifdef USE_LOCALE + tty_read_stream = stdin; + tty_write_stream = stdout; + fcntl(tty_read_fd, F_SETFL, O_NONBLOCK | fcntl(tty_read_fd, F_GETFL)); +#endif + #ifndef USE_VT100 struct tc_init_node { char cap[4], *buf; @@ -772,3 +790,135 @@ void input_insert_follow_chars __P2 (char *,str, int,n) tty_gotoxy_opt(CURCOL(p), cl, CURCOL(pos), CURLINE(pos)); } +#ifdef USE_LOCALE +/* curses wide character support by Dain */ + +void tty_puts __P ((const char *s)) +{ + while (*s) + putwc((unsigned char)*s++, tty_write_stream); +} + +void tty_putc __P ((char c)) +{ + putwc((unsigned char)c, tty_write_stream); +} + + +void tty_printf __P ((const char *format, ...)) +{ + char buf[1024], *bufp = buf; + va_list va; + int res; + + char *old_locale = strdup(setlocale(LC_ALL, NULL)); + + setlocale(LC_ALL, "C"); + + va_start(va, format); + res = vsnprintf(buf, sizeof buf, format, va); + va_end(va); + + if (res >= sizeof buf) { + bufp = alloca(res + 1); + va_start(va, format); + vsprintf(bufp, format, va); + va_end(va); + } + + setlocale(LC_ALL, old_locale); + free(old_locale); + + tty_puts(bufp); +} + +static char tty_in_buf[MB_LEN_MAX + 1]; +static int tty_in_buf_used = 0; + +int tty_has_chars __P ((void)) +{ + return !!tty_in_buf_used; +} + +int tty_read __P ((char *buf, size_t count)) +{ + int result = 0; + int converted; + wchar_t wc; + + if (count && tty_in_buf_used) { + converted = mbtowc(&wc, tty_in_buf, tty_in_buf_used); + if (converted >= 0) + goto another; + } + + while (count) { + int should_read = sizeof tty_in_buf - tty_in_buf_used; + int did_read = read(tty_read_fd, tty_in_buf + tty_in_buf_used, + should_read); + + if (did_read < 0 && errno == EINTR) + continue; + if (did_read <= 0) + break; + + tty_in_buf_used += did_read; + + converted = mbtowc(&wc, tty_in_buf, tty_in_buf_used); + if (converted < 0) + break; + + another: + if (converted == 0) + converted = 1; + + if (!(wc & ~0xff)) { + *buf++ = (unsigned char)wc; + --count; + ++result; + } + + tty_in_buf_used -= converted; + memmove(tty_in_buf, tty_in_buf + converted, tty_in_buf_used); + + if (count == 0) + break; + + converted = mbtowc(&wc, tty_in_buf, tty_in_buf_used); + if (converted >= 0 && tty_in_buf_used) + goto another; + + if (did_read < should_read) + break; + } + + return result; +} + + +void tty_gets __P ((char *s, int size)) +{ + wchar_t *ws = alloca(size * sizeof *ws); + + if (!fgetws(ws, size, stdin)) + return; + + while (*ws) { + if (!(*ws & ~0xff)) + *s++ = (unsigned char)*ws; + ++ws; + } +} + +void tty_flush __P ((void)) +{ + fflush(tty_write_stream); +} + +void tty_raw_write __P ((char *data, int len)) +{ + tty_flush(); + write(1, data, len); +} + +#endif /* USE_LOCALE */ diff --git a/tty.h b/tty.h index ab22d90..ca4b554 100644 --- a/tty.h +++ b/tty.h @@ -25,28 +25,30 @@ void input_overtype_follow __P ((char c)); void input_insert_follow_chars __P ((char *str, int n)); void input_moveto __P ((int new_pos)); -#if 1 +#ifndef USE_LOCALE #define tty_puts(s) fputs((s), stdout) /* printf("%s", (s)); would be as good */ -#define tty_putc(c) putc((int)(char)(c), stdout) -#define tty_printf printf -#define tty_read read -#define tty_gets(s,size) fgets((s), (size), stdin) -#define tty_flush() fflush(stdout) -#define tty_raw_write(s,size) do { tty_flush(); write(1, (s), (size)); } while (0) -#else /* !1 */ +#define tty_putc(c) putc((unsigned char)(c), stdout) +#define tty_printf printf +#define tty_read(buf, cnt) read(tty_read_fd, (buf), (cnt)) +#define tty_gets(s,size) fgets((s), (size), stdin) +#define tty_flush() fflush(stdout) +#define tty_raw_write(s,size) do { tty_flush(); write(1, (s), (size)); } while (0) -void tty_puts __P ((char *s)); -void tty_putc __P ((char c)); -void tty_printf __P ((const char *format, ...)); -int tty_read __P ((int fd, char *buf, size_t count)); -void tty_gets __P ((char *s, int size)); -void tty_flush __P ((void)); -void tty_raw_write __P ((char *data, int len)); +#else /* USE_LOCALE */ -#endif /* 1 */ +void tty_puts __P ((const char *s)); +void tty_putc __P ((char c)); +void tty_printf __P ((const char *format, ...)); +int tty_read __P ((char *buf, size_t count)); +void tty_gets __P ((char *s, int size)); +void tty_flush __P ((void)); +void tty_raw_write __P ((char *data, int len)); +int tty_has_chars __P ((void)); + +#endif /* USE_LOCALE */ #endif /* _TTY_H_ */ -- cgit v0.10.2