Merge branch '1921_lslR_fix'
[midnight-commander.git] / src / ecs.c
blob5892f4732f74b214d97fb1f895eed15b85b4955b
1 /*
2 Basic support for extended character sets.
4 Written by:
5 Roland Illig <roland.illig@gmx.de>, 2005.
7 This file is part of the Midnight Commander.
9 The Midnight Commander is free software; you can redistribute it
10 and/or modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
14 The Midnight Commander is distributed in the hope that it will be
15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 MA 02110-1301, USA.
25 /** \file ecs.c
26 * \brief Source: basic support for extended character sets
29 #include <config.h>
31 #include <assert.h>
32 #include <ctype.h>
34 #include "lib/global.h"
35 #include "ecs.h"
38 * String type conversion
41 extern gboolean ecs_mbstr_to_str(ecs_char **ret_str, const char *s)
43 #ifdef EXTCHARSET_ENABLED
44 size_t maxlen, len;
45 ecs_char *str;
47 maxlen = strlen(s);
49 str = g_new(ecs_char, maxlen + 1);
50 len = mbstowcs(str, s, maxlen + 1);
51 if (len == (size_t) -1) {
52 g_free(str);
53 return FALSE;
56 assert(len <= maxlen);
57 *ret_str = g_renew(ecs_char, str, len + 1);
58 return TRUE;
59 #else
60 *ret_str = g_strdup(s);
61 return TRUE;
62 #endif
65 extern gboolean ecs_str_to_mbstr(char **ret_str, const ecs_char *s)
67 #ifdef EXTCHARSET_ENABLED
68 size_t maxlen, len;
69 char *str;
71 maxlen = ecs_strlen(s) * MB_CUR_MAX;
73 str = g_new(char, maxlen + 1);
74 len = wcstombs(str, s, maxlen + 1);
75 if (len == (size_t) -1) {
76 g_free(str);
77 return FALSE;
80 assert(len <= maxlen);
81 *ret_str = g_renew(char, str, len + 1);
82 return TRUE;
83 #else
84 *ret_str = g_strdup(s);
85 return TRUE;
86 #endif
90 * Character classification
93 #ifdef EXTCHARSET_ENABLED
94 # ifdef HAVE_WCTYPE_H
95 # include <wctype.h>
96 # define ECS_CTYPE(wf, cf, c) \
97 (wf(c))
98 # else
99 # define ECS_CTYPE(wf, cf, c) \
100 (((unsigned char) c != c) ? FALSE : (cf(c)))
101 # endif
102 #else
103 # define ECS_CTYPE(wf, cf, c) \
104 (cf(c))
105 #endif
107 extern gboolean ecs_isalnum(ecs_char c)
109 return ECS_CTYPE(iswalnum, isalnum, c);
112 extern gboolean ecs_isalpha(ecs_char c)
114 return ECS_CTYPE(iswalpha, isalpha, c);
117 extern gboolean ecs_iscntrl(ecs_char c)
119 return ECS_CTYPE(iswcntrl, iscntrl, c);
122 extern gboolean ecs_isdigit(ecs_char c)
124 return ECS_CTYPE(iswdigit, isdigit, c);
127 extern gboolean ecs_isgraph(ecs_char c)
129 return ECS_CTYPE(iswgraph, isgraph, c);
132 extern gboolean ecs_islower(ecs_char c)
134 return ECS_CTYPE(iswlower, islower, c);
137 extern gboolean ecs_isprint(ecs_char c)
139 return ECS_CTYPE(iswprint, isprint, c);
142 extern gboolean ecs_ispunct(ecs_char c)
144 return ECS_CTYPE(iswpunct, ispunct, c);
147 extern gboolean ecs_isspace(ecs_char c)
149 return ECS_CTYPE(iswspace, isspace, c);
152 extern gboolean ecs_isupper(ecs_char c)
154 return ECS_CTYPE(iswupper, isupper, c);
157 extern gboolean ecs_isxdigit(ecs_char c)
159 return ECS_CTYPE(iswxdigit, isxdigit, c);
162 #undef ECS_CTYPE
165 * ISO C90 <string.h> functions
168 /* left out: ecs_strcpy */
169 /* left out: ecs_strncpy */
170 /* left out: ecs_strcat */
171 /* left out: ecs_strncat */
174 ecs_strcmp(const ecs_char *a, const ecs_char *b)
176 size_t i;
177 unsigned long ca, cb;
179 for (i = 0; a[i] == b[i]; i++) {
180 if (a[i] == ECS_CHAR('\0'))
181 return 0;
183 ca = (unsigned long) a[i];
184 cb = (unsigned long) b[i];
185 return (ca < cb) ? -1 : (ca > cb) ? 1 : 0;
188 /* left out: ecs_strcoll */
189 /* left out: ecs_strncmp */
190 /* left out: ecs_strxfrm */
192 ecs_char *
193 ecs_strchr(const ecs_char *s, ecs_char c)
195 size_t i;
197 for (i = 0; s[i] != c; i++) {
198 if (s[i] == ECS_CHAR('\0'))
199 return NULL;
201 return (ecs_char *) s + i;
204 size_t
205 ecs_strcspn(const ecs_char *haystack, const ecs_char *needles)
207 size_t i, j;
209 for (i = 0; haystack[i] != ECS_CHAR('\0'); i++) {
210 for (j = 0; needles[j] != ECS_CHAR('\0'); j++) {
211 if (haystack[i] == needles[j])
212 return i;
215 return i;
218 /* left out: ecs_strpbrk */
220 ecs_char *
221 ecs_strrchr(const ecs_char *s, ecs_char c)
223 ecs_char *pos;
224 size_t i;
226 for (i = 0, pos = NULL;; i++) {
227 if (s[i] == c)
228 pos = (ecs_char *) s + i;
229 if (s[i] == ECS_CHAR('\0'))
230 return pos;
234 size_t
235 ecs_strspn(const ecs_char *s, const ecs_char *chars)
237 size_t i;
239 for (i = 0; s[i] != ECS_CHAR('\0'); i++) {
240 if (ecs_strchr(chars, s[i]) == NULL)
241 break;
243 return i;
246 ecs_char *
247 ecs_strstr(const ecs_char *s, const ecs_char *sub)
249 size_t i, j;
251 for (i = 0; s[i] != ECS_CHAR('\0'); i++) {
252 for (j = 0; sub[j] != ECS_CHAR('\0'); j++) {
253 if (s[i + j] != sub[j])
254 goto next_i;
256 return (ecs_char *) s + i;
257 next_i:
258 continue;
260 return NULL;
263 /* left out: ecs_strtok */
265 size_t
266 ecs_strlen(const ecs_char *s)
268 size_t i;
270 for (i = 0; s[i] != ECS_CHAR('\0'); i++)
271 continue;
272 return i;
276 * Other functions
279 ecs_char *ecs_xstrdup(const ecs_char *s)
281 ecs_char *retval;
282 size_t len;
284 len = ecs_strlen(s);
285 retval = g_new(ecs_char, len + 1);
286 memcpy(retval, s, (len + 1) * sizeof(ecs_char));
287 return retval;
290 size_t
291 ecs_strlcpy(ecs_char *dst, const ecs_char *src, size_t dstsize)
293 size_t n = 0; /* number of copied characters */
295 if (dstsize >= 1) {
296 while (n < dstsize - 1 && *src != ECS_CHAR('\0')) {
297 *dst++ = *src++;
298 n++;
300 *dst = ECS_CHAR('\0');
303 while (*src != ECS_CHAR('\0')) {
304 n++;
305 src++;
308 return n;
311 size_t
312 ecs_strlcat(ecs_char *dst, const ecs_char *src, size_t dstsize)
314 size_t di = 0;
316 while (di < dstsize && dst[di] != ECS_CHAR('\0'))
317 di++;
318 return di + ecs_strlcpy(dst + di, src, dstsize - di);
321 gboolean
322 ecs_strbox(const ecs_char *s, size_t *ret_width, size_t *ret_height)
324 size_t nlines = 0, ncolumns = 0, colindex = 0, i;
326 for (i = 0; s[i] != ECS_CHAR('\0'); i++) {
327 if (s[i] == ECS_CHAR('\n')) {
328 nlines++;
329 colindex = 0;
330 } else {
331 if (!ecs_isprint(s[i]))
332 return FALSE;
334 /* FIXME: This code assumes that each printable
335 * character occupies one cell on the screen. */
336 colindex++;
337 if (colindex > ncolumns)
338 ncolumns = colindex;
341 *ret_width = ncolumns;
342 *ret_height = nlines;
343 return TRUE;