Mercurial > hg > octave-lojdl > gnulib-hg
annotate lib/mbswidth.c @ 3689:27e5e0915016
*** empty log message ***
author | Jim Meyering <jim@meyering.net> |
---|---|
date | Wed, 19 Dec 2001 15:05:38 +0000 |
parents | 591c68289197 |
children | 55eb3920b607 |
rev | line source |
---|---|
2757 | 1 /* Determine the number of screen columns needed for a string. |
3326 | 2 Copyright (C) 2000-2001 Free Software Foundation, Inc. |
2757 | 3 |
4 This program is free software; you can redistribute it and/or modify | |
5 it under the terms of the GNU General Public License as published by | |
6 the Free Software Foundation; either version 2, or (at your option) | |
7 any later version. | |
8 | |
9 This program is distributed in the hope that it will be useful, | |
10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 GNU General Public License for more details. | |
13 | |
14 You should have received a copy of the GNU General Public License | |
15 along with this program; if not, write to the Free Software Foundation, | |
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
17 | |
18 /* Written by Bruno Haible <haible@clisp.cons.org>. */ | |
19 | |
20 #ifdef HAVE_CONFIG_H | |
21 # include <config.h> | |
22 #endif | |
23 | |
3326 | 24 /* Get MB_CUR_MAX. */ |
25 #include <stdlib.h> | |
2757 | 26 |
3326 | 27 #include <string.h> |
2757 | 28 |
29 /* Get isprint(). */ | |
30 #include <ctype.h> | |
31 | |
32 /* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */ | |
33 #if HAVE_WCHAR_H | |
34 # include <wchar.h> | |
35 #endif | |
36 | |
3326 | 37 /* Get iswprint(), iswcntrl(). */ |
2757 | 38 #if HAVE_WCTYPE_H |
39 # include <wctype.h> | |
40 #endif | |
41 #if !defined iswprint && !HAVE_ISWPRINT | |
42 # define iswprint(wc) 1 | |
43 #endif | |
3326 | 44 #if !defined iswcntrl && !HAVE_ISWCNTRL |
45 # define iswcntrl(wc) 0 | |
46 #endif | |
47 | |
48 #ifndef mbsinit | |
49 # if !HAVE_MBSINIT | |
50 # define mbsinit(ps) 1 | |
51 # endif | |
52 #endif | |
2757 | 53 |
2772
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
54 #ifndef HAVE_DECL_WCWIDTH |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
55 "this configure-time declaration test was not run" |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
56 #endif |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
57 #if !HAVE_DECL_WCWIDTH |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
58 int wcwidth (); |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
59 #endif |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
60 |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
61 #ifndef wcwidth |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
62 # if !HAVE_WCWIDTH |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
63 /* wcwidth doesn't exist, so assume all printable characters have |
2757 | 64 width 1. */ |
2772
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
65 # define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1) |
ec142580c1ee
(_XOPEN_SOURCE): Don't define; this causes problems on Solaris 7.
Jim Meyering <jim@meyering.net>
parents:
2757
diff
changeset
|
66 # endif |
2757 | 67 #endif |
68 | |
69 /* Get ISPRINT. */ | |
70 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) | |
2856
21b199ffea14
Rename ISASCII to IN_CTYPE_DOMAIN.
Jim Meyering <jim@meyering.net>
parents:
2775
diff
changeset
|
71 # define IN_CTYPE_DOMAIN(c) 1 |
2757 | 72 #else |
2856
21b199ffea14
Rename ISASCII to IN_CTYPE_DOMAIN.
Jim Meyering <jim@meyering.net>
parents:
2775
diff
changeset
|
73 # define IN_CTYPE_DOMAIN(c) isascii(c) |
2757 | 74 #endif |
75 /* Undefine to protect against the definition in wctype.h of solaris2.6. */ | |
76 #undef ISPRINT | |
2856
21b199ffea14
Rename ISASCII to IN_CTYPE_DOMAIN.
Jim Meyering <jim@meyering.net>
parents:
2775
diff
changeset
|
77 #define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) |
3326 | 78 #undef ISCNTRL |
79 #define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c)) | |
2757 | 80 |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
81 #include "mbswidth.h" |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
82 |
2757 | 83 /* Returns the number of columns needed to represent the multibyte |
84 character string pointed to by STRING. If a non-printable character | |
3326 | 85 occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. |
86 With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is | |
87 the multibyte analogon of the wcswidth function. */ | |
2757 | 88 int |
3326 | 89 mbswidth (string, flags) |
90 const char *string; | |
91 int flags; | |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
92 { |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
93 return mbsnwidth (string, strlen (string), flags); |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
94 } |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
95 |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
96 /* Returns the number of columns needed to represent the multibyte |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
97 character string pointed to by STRING of length NBYTES. If a |
3326 | 98 non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is |
99 specified, -1 is returned. */ | |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
100 int |
3326 | 101 mbsnwidth (string, nbytes, flags) |
102 const char *string; | |
103 size_t nbytes; | |
104 int flags; | |
2757 | 105 { |
106 const char *p = string; | |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
107 const char *plimit = p + nbytes; |
2757 | 108 int width; |
109 | |
110 width = 0; | |
3326 | 111 #if HAVE_MBRTOWC |
2757 | 112 if (MB_CUR_MAX > 1) |
113 { | |
114 while (p < plimit) | |
115 switch (*p) | |
116 { | |
117 case ' ': case '!': case '"': case '#': case '%': | |
118 case '&': case '\'': case '(': case ')': case '*': | |
119 case '+': case ',': case '-': case '.': case '/': | |
120 case '0': case '1': case '2': case '3': case '4': | |
121 case '5': case '6': case '7': case '8': case '9': | |
122 case ':': case ';': case '<': case '=': case '>': | |
123 case '?': | |
124 case 'A': case 'B': case 'C': case 'D': case 'E': | |
125 case 'F': case 'G': case 'H': case 'I': case 'J': | |
126 case 'K': case 'L': case 'M': case 'N': case 'O': | |
127 case 'P': case 'Q': case 'R': case 'S': case 'T': | |
128 case 'U': case 'V': case 'W': case 'X': case 'Y': | |
129 case 'Z': | |
130 case '[': case '\\': case ']': case '^': case '_': | |
131 case 'a': case 'b': case 'c': case 'd': case 'e': | |
132 case 'f': case 'g': case 'h': case 'i': case 'j': | |
133 case 'k': case 'l': case 'm': case 'n': case 'o': | |
134 case 'p': case 'q': case 'r': case 's': case 't': | |
135 case 'u': case 'v': case 'w': case 'x': case 'y': | |
136 case 'z': case '{': case '|': case '}': case '~': | |
137 /* These characters are printable ASCII characters. */ | |
138 p++; | |
139 width++; | |
140 break; | |
141 default: | |
142 /* If we have a multibyte sequence, scan it up to its end. */ | |
143 { | |
144 mbstate_t mbstate; | |
145 memset (&mbstate, 0, sizeof mbstate); | |
146 do | |
147 { | |
148 wchar_t wc; | |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
149 size_t bytes; |
2757 | 150 int w; |
151 | |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
152 bytes = mbrtowc (&wc, p, plimit - p, &mbstate); |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
153 |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
154 if (bytes == (size_t) -1) |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
155 /* An invalid multibyte sequence was encountered. */ |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
156 { |
3326 | 157 if (!(flags & MBSW_REJECT_INVALID)) |
3043
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
158 { |
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
159 p++; |
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
160 width++; |
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
161 break; |
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
162 } |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
163 else |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
164 return -1; |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
165 } |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
166 |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
167 if (bytes == (size_t) -2) |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
168 /* An incomplete multibyte character at the end. */ |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
169 { |
3326 | 170 if (!(flags & MBSW_REJECT_INVALID)) |
3043
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
171 { |
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
172 p = plimit; |
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
173 width++; |
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
174 break; |
f37a719abeac
(mbsnwidth): Don't loop endlessly when called with an
Jim Meyering <jim@meyering.net>
parents:
2856
diff
changeset
|
175 } |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
176 else |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
177 return -1; |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
178 } |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
179 |
2757 | 180 if (bytes == 0) |
181 /* A null wide character was encountered. */ | |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
182 bytes = 1; |
2757 | 183 |
184 w = wcwidth (wc); | |
185 if (w >= 0) | |
186 /* A printable multibyte character. */ | |
187 width += w; | |
188 else | |
189 /* An unprintable multibyte character. */ | |
3326 | 190 if (!(flags & MBSW_REJECT_UNPRINTABLE)) |
191 width += (iswcntrl (wc) ? 0 : 1); | |
2775
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
192 else |
afd68d0b9fc1
(mbswidth): Add a flags argument.
Jim Meyering <jim@meyering.net>
parents:
2772
diff
changeset
|
193 return -1; |
2757 | 194 |
195 p += bytes; | |
196 } | |
197 while (! mbsinit (&mbstate)); | |
198 } | |
199 break; | |
200 } | |
201 return width; | |
202 } | |
203 #endif | |
204 | |
205 while (p < plimit) | |
206 { | |
207 unsigned char c = (unsigned char) *p++; | |
208 | |
3326 | 209 if (ISPRINT (c)) |
2757 | 210 width++; |
3326 | 211 else if (!(flags & MBSW_REJECT_UNPRINTABLE)) |
212 width += (ISCNTRL (c) ? 0 : 1); | |
2757 | 213 else |
214 return -1; | |
215 } | |
216 return width; | |
217 } |