X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fmbswidth.c;h=c9e78d6502356bdaaf925e8f9bd9595c76e1b052;hb=0cba35775b73cee99107fba2be2bf62036ad6c0c;hp=9a0d3a99b165d6faf3627f9db7f3ee3167e85663;hpb=f2c15d342cfe4dbc79c6d7f466e138bfcc89c901;p=gnulib.git diff --git a/lib/mbswidth.c b/lib/mbswidth.c index 9a0d3a99b..c9e78d650 100644 --- a/lib/mbswidth.c +++ b/lib/mbswidth.c @@ -1,5 +1,5 @@ /* Determine the number of screen columns needed for a string. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000-2005 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 @@ -13,7 +13,7 @@ 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. */ + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Bruno Haible . */ @@ -21,78 +21,98 @@ # include #endif -/* Tell GNU libc to declare wcwidth(). */ -#ifndef _XOPEN_SOURCE -# define _XOPEN_SOURCE 500 -#endif - -/* Get MB_LEN_MAX. */ -#if HAVE_LIMITS_H -# include -#endif +/* Specification. */ +#include "mbswidth.h" /* Get MB_CUR_MAX. */ -#if HAVE_STDLIB_H -# include -#endif +#include -#if HAVE_STRING_H -# include -#endif +#include /* Get isprint(). */ #include /* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */ #if HAVE_WCHAR_H +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.1 has a bug: and must be included before + . */ +# include +# include # include #endif -/* Get iswprint(). */ +/* 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 -/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ -#if HAVE_MBRTOWC && defined mbstate_t -# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) -# define mbsinit(ps) 1 +#ifndef mbsinit +# if !HAVE_MBSINIT +# define mbsinit(ps) 1 +# endif #endif -/* If wcwidth() doesn't exist, assume all printable characters have +#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. */ -#if !defined wcwidth && !HAVE_WCWIDTH -# define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1) +# define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1) +# endif #endif /* Get ISPRINT. */ #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) -/* Undefine to protect against the definition in wctype.h of solaris2.6. */ -# undef ISASCII -# define ISASCII(c) 1 +# define IN_CTYPE_DOMAIN(c) 1 #else -# define ISASCII(c) isascii (c) +# define IN_CTYPE_DOMAIN(c) isascii(c) #endif -/* Undefine to protect against the definition in wctype.h of solaris2.6. */ +/* Undefine to protect against the definition in wctype.h of Solaris 2.6. */ #undef ISPRINT -#define ISPRINT(c) (ISASCII (c) && isprint (c)) +#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, -1 is returned. - This is the multibyte analogon of the wcswidth function. */ + occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. + With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is + the multibyte analogue of the wcswidth function. + If STRING is not of length < INT_MAX / 2, integer overflow can occur. */ int -mbswidth (const char *string) +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. + If NBYTES is not < INT_MAX / 2, integer overflow can occur. */ +int +mbsnwidth (const char *string, size_t nbytes, int flags) { const char *p = string; - const char *plimit = p + strlen (p); + const char *plimit = p + nbytes; int width; width = 0; -#if HAVE_MBRTOWC && (MB_LEN_MAX > 1) +#if HAVE_MBRTOWC if (MB_CUR_MAX > 1) { while (p < plimit) @@ -122,8 +142,6 @@ mbswidth (const char *string) p++; width++; break; - case '\0': - break; default: /* If we have a multibyte sequence, scan it up to its end. */ { @@ -132,20 +150,40 @@ mbswidth (const char *string) do { wchar_t wc; - size_t bytes = mbrtowc (&wc, p, plimit - p, &mbstate); + size_t bytes; int w; - if (bytes == 0) - /* A null wide character was encountered. */ - break; + bytes = mbrtowc (&wc, p, plimit - p, &mbstate); if (bytes == (size_t) -1) /* An invalid multibyte sequence was encountered. */ - return -1; + { + if (!(flags & MBSW_REJECT_INVALID)) + { + p++; + width++; + break; + } + else + return -1; + } if (bytes == (size_t) -2) /* An incomplete multibyte character at the end. */ - return -1; + { + 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) @@ -153,7 +191,10 @@ mbswidth (const char *string) width += w; else /* An unprintable multibyte character. */ - return -1; + if (!(flags & MBSW_REJECT_UNPRINTABLE)) + width += (iswcntrl (wc) ? 0 : 1); + else + return -1; p += bytes; } @@ -169,11 +210,10 @@ mbswidth (const char *string) { unsigned char c = (unsigned char) *p++; - if (c == '\0') - break; - if (ISPRINT (c)) width++; + else if (!(flags & MBSW_REJECT_UNPRINTABLE)) + width += (ISCNTRL (c) ? 0 : 1); else return -1; }