From b1b41dce461ab21ae9a2bd26d7a00a381a5f81f8 Mon Sep 17 00:00:00 2001 From: Jaakko Heinonen Date: Mon, 26 Jan 2004 09:51:35 +0000 Subject: [PATCH] multibyte update --- ChangeLog | 2 + Makefile.am | 4 +- Makefile.in | 11 +- TODO | 2 +- abook_rl.c | 23 +--- config.h.in | 20 +++- configure | 250 ++++++++++++++++----------------------- configure.in | 49 +++----- edit.c | 3 +- list.c | 13 +- mbswidth.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++++++ mbswidth.h | 41 +++++++ misc.c | 26 ++++ misc.h | 4 + 14 files changed, 555 insertions(+), 219 deletions(-) create mode 100644 mbswidth.c create mode 100644 mbswidth.h diff --git a/ChangeLog b/ChangeLog index af40f12..e307f37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ - five custom fields added - experimental wide character support - fixed a crash bug in mutt filter + - fixed errors in configure.in (especially snprintf-functions were incorrectly + detected) 0.5.1 - sort by field command diff --git a/Makefile.am b/Makefile.am index 46ca605..743c133 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,10 +3,10 @@ bin_PROGRAMS = abook abook_SOURCES = abook.c database.c filter.c list.c misc.c \ options.c edit.c ldif.c ui.c getname.c \ - getopt.c getopt1.c abook_rl.c \ + getopt.c getopt1.c abook_rl.c mbswidth.c \ abook.h database.h filter.h list.h misc.h help.h \ options.h edit.h ldif.h abook_curses.h ui.h getname.h \ - getopt.h abook_rl.h + getopt.h abook_rl.h mbswidth.h EXTRA_DIST = ANNOUNCE BUGS FAQ abook.1 abookrc.5 sample.abookrc abook.spec diff --git a/Makefile.in b/Makefile.in index 4b98e9a..379d195 100644 --- a/Makefile.in +++ b/Makefile.in @@ -118,10 +118,10 @@ bin_PROGRAMS = abook abook_SOURCES = abook.c database.c filter.c list.c misc.c \ options.c edit.c ldif.c ui.c getname.c \ - getopt.c getopt1.c abook_rl.c \ + getopt.c getopt1.c abook_rl.c mbswidth.c \ abook.h database.h filter.h list.h misc.h help.h \ options.h edit.h ldif.h abook_curses.h ui.h getname.h \ - getopt.h abook_rl.h + getopt.h abook_rl.h mbswidth.h EXTRA_DIST = ANNOUNCE BUGS FAQ abook.1 abookrc.5 sample.abookrc abook.spec @@ -136,7 +136,7 @@ PROGRAMS = $(bin_PROGRAMS) am_abook_OBJECTS = abook.$(OBJEXT) database.$(OBJEXT) filter.$(OBJEXT) \ list.$(OBJEXT) misc.$(OBJEXT) options.$(OBJEXT) edit.$(OBJEXT) \ ldif.$(OBJEXT) ui.$(OBJEXT) getname.$(OBJEXT) getopt.$(OBJEXT) \ - getopt1.$(OBJEXT) abook_rl.$(OBJEXT) + getopt1.$(OBJEXT) abook_rl.$(OBJEXT) mbswidth.$(OBJEXT) abook_OBJECTS = $(am_abook_OBJECTS) abook_LDADD = $(LDADD) abook_DEPENDENCIES = @@ -150,8 +150,8 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ ./$(DEPDIR)/filter.Po ./$(DEPDIR)/getname.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/getopt.Po ./$(DEPDIR)/getopt1.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/ldif.Po ./$(DEPDIR)/list.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/misc.Po ./$(DEPDIR)/options.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ui.Po +@AMDEP_TRUE@ ./$(DEPDIR)/mbswidth.Po ./$(DEPDIR)/misc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/options.Po ./$(DEPDIR)/ui.Po COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -248,6 +248,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldif.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbswidth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ui.Po@am__quote@ diff --git a/TODO b/TODO index 5caa798..deda7c3 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,3 @@ - + - grouping - new file format (xml?) - custom views, keybindings diff --git a/abook_rl.c b/abook_rl.c index f9ebba6..00410f4 100644 --- a/abook_rl.c +++ b/abook_rl.c @@ -33,6 +33,7 @@ #ifdef HANDLE_MULTIBYTE # include +# include #endif #define RL_READLINE_NAME "Abook" @@ -53,27 +54,7 @@ rl_refresh() static int rline_calc_point() { - char *p; - int ret = 0; - - mbtowc(NULL, NULL, 0); - for(p = rl_line_buffer;(p - rl_line_buffer) < rl_point;) { - int a, l; - wchar_t wc; - - if((a = mbtowc(&wc, p, MB_CUR_MAX)) == 0) - break; - else if (a == -1) - return rl_point; /* fall back */ - else - p += a; - - l = wcwidth(wc); - if(l > 0) - ret += l; - } - - return ret; + return (int)mbsnwidth(rl_line_buffer, rl_point, 0); } #endif diff --git a/config.h.in b/config.h.in index 7814ddd..1ebd53f 100644 --- a/config.h.in +++ b/config.h.in @@ -3,6 +3,10 @@ /* Handle multibyte characters */ #undef HANDLE_MULTIBYTE +/* Define to 1 if you have the declaration of `wcwidth', and to 0 if you + don't. */ +#undef HAVE_DECL_WCWIDTH + /* Define to 1 if you have the header file. */ #undef HAVE_HISTORY_H @@ -18,15 +22,18 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H +/* Define to 1 if you have the `mbrtowc' function. */ +#undef HAVE_MBRTOWC + +/* Define to 1 if you have the `mbsinit' function. */ +#undef HAVE_MBSINIT + /* Define to 1 if you have the `mbtowc' function. */ #undef HAVE_MBTOWC /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H -/* Define if you have the header file. */ -#undef HAVE_NCURSES - /* Define to 1 if you have the header file. */ #undef HAVE_NCURSES_H @@ -48,7 +55,7 @@ /* Define to 1 if you have the `setlocale' function. */ #undef HAVE_SETLOCALE -/* Define if snprintf is available. */ +/* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* Define if you have the header file. */ @@ -85,9 +92,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define if vsnprintf is available. */ +/* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF +/* Define if you have the header file. */ +#undef HAVE_WCHAR_H + /* Define to 1 if you have the `wcwidth' function. */ #undef HAVE_WCWIDTH diff --git a/configure b/configure index 6f61bd4..fcfb2c5 100755 --- a/configure +++ b/configure @@ -850,7 +850,6 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors - --enable-widec Enable wide character support (experimental) --enable-debug Enable debugging support Optional Packages: @@ -1677,26 +1676,6 @@ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" -cat >>confdefs.h <<\_ACEOF -#define HAVE_SNPRINTF 0 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_VSNPRINTF 0 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_STDARG_H 0 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_NCURSES 0 -_ACEOF - - # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 @@ -4162,7 +4141,8 @@ echo "${ECHO_T}$ac_cv_header_stdarg_h" >&6 fi if test $ac_cv_header_stdarg_h = yes; then - cat >>confdefs.h <<\_ACEOF + +cat >>confdefs.h <<\_ACEOF #define HAVE_STDARG_H 1 _ACEOF @@ -4448,7 +4428,13 @@ echo "${ECHO_T}$ac_cv_header_wchar_h" >&6 fi if test $ac_cv_header_wchar_h = yes; then - ac_have_wchar_h=yes + + ac_have_wchar_h=yes + +cat >>confdefs.h <<\_ACEOF +#define HAVE_WCHAR_H 1 +_ACEOF + else ac_have_wchar_h=no fi @@ -4456,7 +4442,9 @@ fi -for ac_func in mbtowc wcwidth + + +for ac_func in mbtowc wcwidth mbrtowc mbsinit do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -4541,6 +4529,69 @@ else fi done +echo "$as_me:$LINENO: checking whether wcwidth is declared" >&5 +echo $ECHO_N "checking whether wcwidth is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl_wcwidth+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +#ifndef wcwidth + char *p = (char *) wcwidth; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 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_cv_have_decl_wcwidth=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl_wcwidth=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl_wcwidth" >&5 +echo "${ECHO_T}$ac_cv_have_decl_wcwidth" >&6 +if test $ac_cv_have_decl_wcwidth = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_WCWIDTH 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_WCWIDTH 0 +_ACEOF + + +fi + + echo "$as_me:$LINENO: checking for wchar_t" >&5 echo $ECHO_N "checking for wchar_t... $ECHO_C" >&6 if test "${ac_cv_type_wchar_t+set}" = set; then @@ -4601,26 +4652,6 @@ else ac_widec_possible=no fi -# Check whether --enable-widec or --disable-widec was given. -if test "${enable_widec+set}" = set; then - enableval="$enable_widec" - case "${enableval}" in - yes) ac_widec_support=true ;; - no) ac_widec_support=false ;; - *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-widec" >&5 -echo "$as_me: error: bad value ${enableval} for --enable-widec" >&2;} - { (exit 1); exit 1; }; } ;; - esac -else - ac_widec_support=false -fi; - -if test x$ac_widec_support = xtrue -a x$ac_widec_possible != xyes; then - { { echo "$as_me:$LINENO: error: Wide character support is not possible due to missing wide character functions or wchar.h" >&5 -echo "$as_me: error: Wide character support is not possible due to missing wide character functions or wchar.h" >&2;} - { (exit 1); exit 1; }; } -fi - abook_cv_curses=/usr @@ -4636,8 +4667,7 @@ if test "${with_curses+set}" = set; then fi fi; -if test x$ac_widec_support = xtrue; then - echo "$as_me:$LINENO: checking for initscr in -lncursesw" >&5 +echo "$as_me:$LINENO: checking for initscr in -lncursesw" >&5 echo $ECHO_N "checking for initscr in -lncursesw... $ECHO_C" >&6 if test "${ac_cv_lib_ncursesw_initscr+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -4693,9 +4723,9 @@ echo "$as_me:$LINENO: result: $ac_cv_lib_ncursesw_initscr" >&5 echo "${ECHO_T}$ac_cv_lib_ncursesw_initscr" >&6 if test $ac_cv_lib_ncursesw_initscr = yes; then LIBS="$LIBS -lncursesw" - if test x$abook_cv_curses = x/usr -a -d /usr/include/ncursesw; then - CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" - fi + if test x$abook_cv_curses = x/usr -a -d /usr/include/ncursesw; then + CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" + fi for ac_header in ncurses.h do @@ -4840,12 +4870,7 @@ done else - { { echo "$as_me:$LINENO: error: \"Wide character support is not possible due to missing ncursesw library. Please install it or disable wide character support\"" >&5 -echo "$as_me: error: \"Wide character support is not possible due to missing ncursesw library. Please install it or disable wide character support\"" >&2;} - { (exit 1); exit 1; }; } -fi - -else + ac_widec_possible=no echo "$as_me:$LINENO: checking for initscr in -lncurses" >&5 echo $ECHO_N "checking for initscr in -lncurses... $ECHO_C" >&6 if test "${ac_cv_lib_ncurses_initscr+set}" = set; then @@ -5677,10 +5702,12 @@ fi fi + fi + abook_cv_readline=/usr # Check whether --with-readline or --without-readline was given. @@ -6134,7 +6161,7 @@ echo "$as_me: error: *** readline library not found or it doesn't support histor fi -if test x$ac_widec_support = xtrue; then +if test x$ac_widec_possible = xyes; then cat >>confdefs.h <<\_ACEOF #define HANDLE_MULTIBYTE 1 @@ -6227,88 +6254,14 @@ fi done -echo "$as_me:$LINENO: checking for snprintf" >&5 -echo $ECHO_N "checking for snprintf... $ECHO_C" >&6 -if test "${ac_cv_func_snprintf+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char snprintf (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ -#ifdef __STDC__ -# include -#else -# include -#endif -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char snprintf (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_snprintf) || defined (__stub___snprintf) -choke me -#else -char (*f) () = snprintf; -#endif -#ifdef __cplusplus -} -#endif -int -main () -{ -return f != snprintf; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' - { (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_cv_func_snprintf=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 -ac_cv_func_snprintf=no -fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_snprintf" >&5 -echo "${ECHO_T}$ac_cv_func_snprintf" >&6 -if test $ac_cv_func_snprintf = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_SNPRINTF 1 -_ACEOF - -fi - -echo "$as_me:$LINENO: checking for vsnprintf" >&5 -echo $ECHO_N "checking for vsnprintf... $ECHO_C" >&6 -if test "${ac_cv_func_vsnprintf+set}" = set; then +for ac_func in snprintf vsnprintf +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -6319,7 +6272,7 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* System header to define __stub macros and hopefully few prototypes, - which can conflict with char vsnprintf (); below. + which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ @@ -6334,14 +6287,14 @@ extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ -char vsnprintf (); +char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ -#if defined (__stub_vsnprintf) || defined (__stub___vsnprintf) +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else -char (*f) () = vsnprintf; +char (*f) () = $ac_func; #endif #ifdef __cplusplus } @@ -6350,7 +6303,7 @@ char (*f) () = vsnprintf; int main () { -return f != vsnprintf; +return f != $ac_func; ; return 0; } @@ -6367,23 +6320,24 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_func_vsnprintf=yes + eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -ac_cv_func_vsnprintf=no +eval "$as_ac_var=no" fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_func_vsnprintf" >&5 -echo "${ECHO_T}$ac_cv_func_vsnprintf" >&6 -if test $ac_cv_func_vsnprintf = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_VSNPRINTF 1 +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi +done # Check whether --enable-debug or --disable-debug was given. diff --git a/configure.in b/configure.in index 0ba524c..f5d6097 100644 --- a/configure.in +++ b/configure.in @@ -4,10 +4,8 @@ AC_INIT(abook.c) AM_INIT_AUTOMAKE(abook, 0.5.2pre) AM_CONFIG_HEADER(config.h) -AC_DEFINE(HAVE_SNPRINTF, 0, [Define if snprintf is available.]) -AC_DEFINE(HAVE_VSNPRINTF, 0, [Define if vsnprintf is available.]) -AC_DEFINE(HAVE_STDARG_H, 0, [Define if you have the header file.]) -AC_DEFINE(HAVE_NCURSES, 0, [Define if you have the header file.]) +dnl AC_DEFINE(HAVE_STDARG_H, 0, [Define if you have the header file.]) +dnl AC_DEFINE(HAVE_NCURSES_H, 0, [Define if you have the header file.]) AC_CANONICAL_HOST @@ -21,13 +19,17 @@ AC_C_INLINE AC_PROG_INSTALL AC_HEADER_STDC AC_CHECK_HEADERS(unistd.h locale.h termios.h linux/termios.h sys/ioctl.h) -AC_CHECK_HEADER(stdarg.h,AC_DEFINE(HAVE_STDARG_H),AC_MSG_ERROR([*** stdarg.h is missing on your system ***])) +AC_CHECK_HEADER(stdarg.h,AC_DEFINE(HAVE_STDARG_H, 1, [Define if you have the header file.]),AC_MSG_ERROR([*** stdarg.h is missing on your system ***])) AC_FUNC_STRCOLL AC_CHECK_FUNCS(setlocale) ac_widec_funcs=yes -AC_CHECK_HEADER(wchar.h,[ac_have_wchar_h=yes], [ac_have_wchar_h=no]) -AC_CHECK_FUNCS(mbtowc wcwidth,,ac_widec_funcs=no) +AC_CHECK_HEADER(wchar.h,[ + ac_have_wchar_h=yes + AC_DEFINE(HAVE_WCHAR_H, 1, [Define if you have the header file.])], + [ac_have_wchar_h=no]) +AC_CHECK_FUNCS(mbtowc wcwidth mbrtowc mbsinit,,ac_widec_funcs=no) +AC_CHECK_DECLS(wcwidth) AC_CHECK_TYPE(wchar_t,,ac_widec_funcs=no) if test x$ac_widec_funcs = xyes -a x$ac_have_wchar_h = xyes; then @@ -36,16 +38,6 @@ else ac_widec_possible=no fi -AC_ARG_ENABLE(widec, [ --enable-widec Enable wide character support (experimental) ], [case "${enableval}" in - yes) ac_widec_support=true ;; - no) ac_widec_support=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-widec) ;; - esac], [ac_widec_support=false]) - -if test x$ac_widec_support = xtrue -a x$ac_widec_possible != xyes; then - AC_MSG_ERROR(Wide character support is not possible due to missing wide character functions or wchar.h) -fi - dnl ------------------- dnl (n)curses detection dnl ------------------- @@ -60,15 +52,13 @@ AC_ARG_WITH(curses, [ --with-curses=DIR Where ncurses is installed ], CPPFLAGS="$CPPFLAGS -I${abook_cv_curses}/include" fi]) -if test x$ac_widec_support = xtrue; then - AC_CHECK_LIB(ncursesw, initscr, - [LIBS="$LIBS -lncursesw" - if test x$abook_cv_curses = x/usr -a -d /usr/include/ncursesw; then - CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" - fi - AC_CHECK_HEADERS(ncurses.h)],[ - AC_MSG_ERROR("Wide character support is not possible due to missing ncursesw library. Please install it or disable wide character support")]) -else +AC_CHECK_LIB(ncursesw, initscr, + [LIBS="$LIBS -lncursesw" + if test x$abook_cv_curses = x/usr -a -d /usr/include/ncursesw; then + CPPFLAGS="$CPPFLAGS -I/usr/include/ncursesw" + fi + AC_CHECK_HEADERS(ncurses.h)],[ + ac_widec_possible=no AC_CHECK_LIB(ncurses, initscr, [LIBS="$LIBS -lncurses" if test x$abook_cv_curses = x/usr -a -d /usr/include/ncurses; then @@ -76,7 +66,7 @@ else fi AC_CHECK_HEADERS(ncurses.h)], [CF_CURSES_LIBS]) -fi + ]) dnl -------------------------- dnl end of (n)curses detection @@ -106,14 +96,13 @@ dnl ------------------------- dnl end of readline detection dnl ------------------------- -if test x$ac_widec_support = xtrue; then +if test x$ac_widec_possible = xyes; then AC_DEFINE(HANDLE_MULTIBYTE, 1, [Handle multibyte characters]) fi AC_CHECK_FUNCS(resizeterm) -AC_CHECK_FUNC(snprintf, [AC_DEFINE(HAVE_SNPRINTF)],) -AC_CHECK_FUNC(vsnprintf, [AC_DEFINE(HAVE_VSNPRINTF)],) +AC_CHECK_FUNCS(snprintf vsnprintf) AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging support ], [case "${enableval}" in yes) debug=true ;; diff --git a/edit.c b/edit.c index 100488d..7abbb09 100644 --- a/edit.c +++ b/edit.c @@ -147,7 +147,8 @@ print_editor_header(int item) else snprintf(header, EDITW_COLS, "%s", database[item][NAME]); - mvwaddstr(editw, 0, (EDITW_COLS - strlen(header)) / 2, + fprintf(stderr, "%d\n", strwidth(header)); + mvwaddstr(editw, 0, (EDITW_COLS - strwidth(header)) / 2, header); free(header); diff --git a/list.c b/list.c index 7197723..d3a53c3 100644 --- a/list.c +++ b/list.c @@ -128,21 +128,23 @@ print_list_line(int i, int line, int highlight) if(selected[i]) mvwaddch(list, line, 0, '*' ); - mvwaddnstr(list, line, NAMEPOS, database[i][NAME], NAMELEN); + mvwaddnstr(list, line, NAMEPOS, database[i][NAME], + bytes2width(database[i][NAME], NAMELEN)); if(opt_get_bool(BOOL_SHOW_ALL_EMAILS)) mvwaddnstr(list, line, EMAILPOS, database[i][EMAIL], - real_emaillen); + bytes2width(database[i][EMAIL], real_emaillen)); else { get_first_email(tmp, i); - mvwaddnstr(list, line, EMAILPOS, tmp, real_emaillen); + mvwaddnstr(list, line, EMAILPOS, tmp, + bytes2width(tmp, real_emaillen)); } if(extra < 0 || !database[i][extra]) extra = extra_alternative; if(extra >= 0) mvwaddnstr(list, line, EXTRAPOS, - safe_str(database[i][extra]), - EXTRALEN); + safe_str(database[i][extra]), + bytes2width(safe_str(database[i][extra]), EXTRALEN)); scrollok(list, TRUE); if(highlight) @@ -216,7 +218,6 @@ page_down() refresh_list(); } - void select_none() { diff --git a/mbswidth.c b/mbswidth.c new file mode 100644 index 0000000..c6c3ea9 --- /dev/null +++ b/mbswidth.c @@ -0,0 +1,326 @@ +/* Determine the number of screen columns needed for a string. + Copyright (C) 2000-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Bruno Haible . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HANDLE_MULTIBYTE /* for abook */ + +/* Specification. */ +#include "mbswidth.h" + +/* Get MB_CUR_MAX. */ +#include + +#include + +/* Get isprint(). */ +#include + +/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */ +#if HAVE_WCHAR_H +# include +#endif + +/* Get iswprint(), iswcntrl(). */ +#if HAVE_WCTYPE_H +# include +#endif +#if !defined iswprint && !HAVE_ISWPRINT +# define iswprint(wc) 1 +#endif +#if !defined iswcntrl && !HAVE_ISWCNTRL +# define iswcntrl(wc) 0 +#endif + +#ifndef mbsinit +# if !HAVE_MBSINIT +# define mbsinit(ps) 1 +# endif +#endif + +#ifndef HAVE_DECL_WCWIDTH +"this configure-time declaration test was not run" +#endif +#if !HAVE_DECL_WCWIDTH +int wcwidth (); +#endif + +#ifndef wcwidth +# if !HAVE_WCWIDTH +/* wcwidth doesn't exist, so assume all printable characters have + width 1. */ +# define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1) +# endif +#endif + +/* Get ISPRINT. */ +#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) +# define IN_CTYPE_DOMAIN(c) 1 +#else +# define IN_CTYPE_DOMAIN(c) isascii(c) +#endif +/* Undefine to protect against the definition in wctype.h of solaris2.6. */ +#undef ISPRINT +#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) +#undef ISCNTRL +#define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c)) + +/* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING. If a non-printable character + occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. + With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is + the multibyte analogon of the wcswidth function. */ +int +mbswidth (const char *string, int flags) +{ + return mbsnwidth (string, strlen (string), flags); +} + +/* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING of length NBYTES. If a + non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is + specified, -1 is returned. */ +int +mbsnwidth (const char *string, size_t nbytes, int flags) +{ + const char *p = string; + const char *plimit = p + nbytes; + int width; + + width = 0; +#if HAVE_MBRTOWC + if (MB_CUR_MAX > 1) + { + while (p < plimit) + switch (*p) + { + case ' ': case '!': case '"': case '#': case '%': + case '&': case '\'': case '(': case ')': case '*': + case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': + case '?': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '[': case '\\': case ']': case '^': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': case '{': case '|': case '}': case '~': + /* These characters are printable ASCII characters. */ + p++; + width++; + break; + default: + /* If we have a multibyte sequence, scan it up to its end. */ + { + mbstate_t mbstate; + memset (&mbstate, 0, sizeof mbstate); + do + { + wchar_t wc; + size_t bytes; + int w; + + bytes = mbrtowc (&wc, p, plimit - p, &mbstate); + + if (bytes == (size_t) -1) + /* An invalid multibyte sequence was encountered. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p++; + width++; + break; + } + else + return -1; + } + + if (bytes == (size_t) -2) + /* An incomplete multibyte character at the end. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p = plimit; + width++; + break; + } + else + return -1; + } + + if (bytes == 0) + /* A null wide character was encountered. */ + bytes = 1; + + w = wcwidth (wc); + if (w >= 0) + /* A printable multibyte character. */ + width += w; + else + /* An unprintable multibyte character. */ + if (!(flags & MBSW_REJECT_UNPRINTABLE)) + width += (iswcntrl (wc) ? 0 : 1); + else + return -1; + + p += bytes; + } + while (! mbsinit (&mbstate)); + } + break; + } + return width; + } +#endif + + while (p < plimit) + { + unsigned char c = (unsigned char) *p++; + + if (ISPRINT (c)) + width++; + else if (!(flags & MBSW_REJECT_UNPRINTABLE)) + width += (ISCNTRL (c) ? 0 : 1); + else + return -1; + } + return width; +} + +int +mbsnbytes (const char *string, size_t nbytes, int maxwidth, int flags) +{ + const char *p = string, *old_p = string; + const char *plimit = p + nbytes; + int width; + + width = 0; +#if HAVE_MBRTOWC + if (MB_CUR_MAX > 1) + { + while (p < plimit && width < maxwidth) + { + old_p = p; + switch (*p) + { + case ' ': case '!': case '"': case '#': case '%': + case '&': case '\'': case '(': case ')': case '*': + case '+': case ',': case '-': case '.': case '/': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '<': case '=': case '>': + case '?': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case '[': case '\\': case ']': case '^': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': case '{': case '|': case '}': case '~': + /* These characters are printable ASCII characters. */ + p++; + width++; + break; + default: + /* If we have a multibyte sequence, scan it up to its end. */ + { + mbstate_t mbstate; + memset (&mbstate, 0, sizeof mbstate); + do + { + wchar_t wc; + size_t bytes; + int w; + + bytes = mbrtowc (&wc, p, plimit - p, &mbstate); + + if (bytes == (size_t) -1) + /* An invalid multibyte sequence was encountered. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p++; + width++; + break; + } + else + return -1; + } + + if (bytes == (size_t) -2) + /* An incomplete multibyte character at the end. */ + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p = plimit; + width++; + break; + } + else + return -1; + } + + if (bytes == 0) + /* A null wide character was encountered. */ + bytes = 1; + + w = wcwidth (wc); + if (w >= 0) + /* A printable multibyte character. */ + width += w; + else + /* An unprintable multibyte character. */ + if (!(flags & MBSW_REJECT_UNPRINTABLE)) + width += (iswcntrl (wc) ? 0 : 1); + else + return -1; + + p += bytes; + } + while (! mbsinit (&mbstate)); + } + break; + } + } + + return (width > maxwidth) ? (old_p - string) : (p - string); + } +#endif + + return maxwidth; +} + +#endif /* HANDLE_MULTIBYTE */ diff --git a/mbswidth.h b/mbswidth.h new file mode 100644 index 0000000..7047f42 --- /dev/null +++ b/mbswidth.h @@ -0,0 +1,41 @@ +/* Determine the number of screen columns needed for a string. + Copyright (C) 2000-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include + +/* Optional flags to influence mbswidth/mbsnwidth behavior. */ + +/* If this bit is set, return -1 upon finding an invalid or incomplete + character. Otherwise, assume invalid characters have width 1. */ +#define MBSW_REJECT_INVALID 1 + +/* If this bit is set, return -1 upon finding a non-printable character. + Otherwise, assume unprintable characters have width 0 if they are + control characters and 1 otherwise. */ +#define MBSW_REJECT_UNPRINTABLE 2 + +/* Returns the number of screen columns needed for STRING. */ +#define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */ +extern int mbswidth (const char *string, int flags); + +/* Returns the number of screen columns needed for the NBYTES bytes + starting at BUF. */ +extern int mbsnwidth (const char *buf, size_t nbytes, int flags); + + +extern int mbsnbytes (const char *string, size_t nbytes, int maxwidth, int flags); + diff --git a/misc.c b/misc.c index df853bc..a44c9d2 100644 --- a/misc.c +++ b/misc.c @@ -19,6 +19,10 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#ifdef HANDLE_MULTIBYTE +# include +# include "mbswidth.h" +#endif #include "misc.h" #ifdef ABOOK_SRC # include "abook.h" @@ -265,6 +269,28 @@ getaline(FILE *f) return buf; } +int +strwidth(const char *s) +{ + assert(s); +#ifdef HANDLE_MULTIBYTE + return (int)mbswidth(s, 0); +#else + return strlen(s); +#endif +} + +int +bytes2width(const char *s, int width) +{ + assert(s); +#ifdef HANDLE_MULTIBYTE + return mbsnbytes(s, strlen(s), width, 0); +#else + return width; +#endif +} + /************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 diff --git a/misc.h b/misc.h index 384b6cc..9b42d2c 100644 --- a/misc.h +++ b/misc.h @@ -16,6 +16,10 @@ char *my_getcwd(); char *getaline(FILE *f); +int strwidth(const char *s); +int bytes2width(const char *s, int width); + + #ifdef HAVE_CONFIG_H # include "config.h" #endif -- 2.39.2