Reverted the use of mhl_str_dup and use g_strdup instead.
[midnight-commander.git] / src / ecs.c
blob62683a6e00100064f9be0eb1b22ce587c8a301a4
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 #include <config.h>
27 #include <assert.h>
28 #include <ctype.h>
30 #include <mhl/types.h>
31 #include <mhl/string.h>
33 #include "global.h"
34 #include "ecs.h"
37 * String type conversion
40 extern bool ecs_mbstr_to_str(ecs_char **ret_str, const char *s)
42 #ifdef EXTCHARSET_ENABLED
43 size_t maxlen, len;
44 ecs_char *str;
46 maxlen = strlen(s);
48 str = g_new(ecs_char, maxlen + 1);
49 len = mbstowcs(str, s, maxlen + 1);
50 if (len == (size_t) -1) {
51 g_free(str);
52 return FALSE;
55 assert(len <= maxlen);
56 *ret_str = g_renew(ecs_char, str, len + 1);
57 return TRUE;
58 #else
59 *ret_str = g_strdup(s);
60 return TRUE;
61 #endif
64 extern bool ecs_str_to_mbstr(char **ret_str, const ecs_char *s)
66 #ifdef EXTCHARSET_ENABLED
67 size_t maxlen, len;
68 char *str;
70 maxlen = ecs_strlen(s) * MB_CUR_MAX;
72 str = g_new(char, maxlen + 1);
73 len = wcstombs(str, s, maxlen + 1);
74 if (len == (size_t) -1) {
75 g_free(str);
76 return FALSE;
79 assert(len <= maxlen);
80 *ret_str = g_renew(char, str, len + 1);
81 return TRUE;
82 #else
83 *ret_str = g_strdup(s);
84 return TRUE;
85 #endif
89 * Character classification
92 #ifdef EXTCHARSET_ENABLED
93 # ifdef HAVE_WCTYPE_H
94 # include <wctype.h>
95 # define ECS_CTYPE(wf, cf, c) \
96 (wf(c))
97 # else
98 # define ECS_CTYPE(wf, cf, c) \
99 (((unsigned char) c != c) ? FALSE : (cf(c)))
100 # endif
101 #else
102 # define ECS_CTYPE(wf, cf, c) \
103 (cf(c))
104 #endif
106 extern bool ecs_isalnum(ecs_char c)
108 return ECS_CTYPE(iswalnum, isalnum, c);
111 extern bool ecs_isalpha(ecs_char c)
113 return ECS_CTYPE(iswalpha, isalpha, c);
116 extern bool ecs_iscntrl(ecs_char c)
118 return ECS_CTYPE(iswcntrl, iscntrl, c);
121 extern bool ecs_isdigit(ecs_char c)
123 return ECS_CTYPE(iswdigit, isdigit, c);
126 extern bool ecs_isgraph(ecs_char c)
128 return ECS_CTYPE(iswgraph, isgraph, c);
131 extern bool ecs_islower(ecs_char c)
133 return ECS_CTYPE(iswlower, islower, c);
136 extern bool ecs_isprint(ecs_char c)
138 return ECS_CTYPE(iswprint, isprint, c);
141 extern bool ecs_ispunct(ecs_char c)
143 return ECS_CTYPE(iswpunct, ispunct, c);
146 extern bool ecs_isspace(ecs_char c)
148 return ECS_CTYPE(iswspace, isspace, c);
151 extern bool ecs_isupper(ecs_char c)
153 return ECS_CTYPE(iswupper, isupper, c);
156 extern bool ecs_isxdigit(ecs_char c)
158 return ECS_CTYPE(iswxdigit, isxdigit, c);
161 #undef ECS_CTYPE
164 * ISO C90 <string.h> functions
167 /* left out: ecs_strcpy */
168 /* left out: ecs_strncpy */
169 /* left out: ecs_strcat */
170 /* left out: ecs_strncat */
173 ecs_strcmp(const ecs_char *a, const ecs_char *b)
175 size_t i;
176 unsigned long ca, cb;
178 for (i = 0; a[i] == b[i]; i++) {
179 if (a[i] == ECS_CHAR('\0'))
180 return 0;
182 ca = (unsigned long) a[i];
183 cb = (unsigned long) b[i];
184 return (ca < cb) ? -1 : (ca > cb) ? 1 : 0;
187 /* left out: ecs_strcoll */
188 /* left out: ecs_strncmp */
189 /* left out: ecs_strxfrm */
191 ecs_char *
192 ecs_strchr(const ecs_char *s, ecs_char c)
194 size_t i;
196 for (i = 0; s[i] != c; i++) {
197 if (s[i] == ECS_CHAR('\0'))
198 return NULL;
200 return (ecs_char *) s + i;
203 size_t
204 ecs_strcspn(const ecs_char *haystack, const ecs_char *needles)
206 size_t i, j;
208 for (i = 0; haystack[i] != ECS_CHAR('\0'); i++) {
209 for (j = 0; needles[j] != ECS_CHAR('\0'); j++) {
210 if (haystack[i] == needles[j])
211 return i;
214 return i;
217 /* left out: ecs_strpbrk */
219 ecs_char *
220 ecs_strrchr(const ecs_char *s, ecs_char c)
222 ecs_char *pos;
223 size_t i;
225 for (i = 0, pos = NULL;; i++) {
226 if (s[i] == c)
227 pos = (ecs_char *) s + i;
228 if (s[i] == ECS_CHAR('\0'))
229 return pos;
233 size_t
234 ecs_strspn(const ecs_char *s, const ecs_char *chars)
236 size_t i;
238 for (i = 0; s[i] != ECS_CHAR('\0'); i++) {
239 if (ecs_strchr(chars, s[i]) == NULL)
240 break;
242 return i;
245 ecs_char *
246 ecs_strstr(const ecs_char *s, const ecs_char *sub)
248 size_t i, j;
250 for (i = 0; s[i] != ECS_CHAR('\0'); i++) {
251 for (j = 0; sub[j] != ECS_CHAR('\0'); j++) {
252 if (s[i + j] != sub[j])
253 goto next_i;
255 return (ecs_char *) s + i;
256 next_i:
257 continue;
259 return NULL;
262 /* left out: ecs_strtok */
264 size_t
265 ecs_strlen(const ecs_char *s)
267 size_t i;
269 for (i = 0; s[i] != ECS_CHAR('\0'); i++)
270 continue;
271 return i;
275 * Other functions
278 ecs_char *ecs_xstrdup(const ecs_char *s)
280 ecs_char *retval;
281 size_t len;
283 len = ecs_strlen(s);
284 retval = g_new(ecs_char, len + 1);
285 memcpy(retval, s, (len + 1) * sizeof(ecs_char));
286 return retval;
289 size_t
290 ecs_strlcpy(ecs_char *dst, const ecs_char *src, size_t dstsize)
292 size_t n = 0; /* number of copied characters */
294 if (dstsize >= 1) {
295 while (n < dstsize - 1 && *src != ECS_CHAR('\0')) {
296 *dst++ = *src++;
297 n++;
299 *dst = ECS_CHAR('\0');
302 while (*src != ECS_CHAR('\0')) {
303 n++;
304 src++;
307 return n;
310 size_t
311 ecs_strlcat(ecs_char *dst, const ecs_char *src, size_t dstsize)
313 size_t di = 0;
315 while (di < dstsize && dst[di] != ECS_CHAR('\0'))
316 di++;
317 return di + ecs_strlcpy(dst + di, src, dstsize - di);
320 bool
321 ecs_strbox(const ecs_char *s, size_t *ret_width, size_t *ret_height)
323 size_t nlines = 0, ncolumns = 0, colindex = 0, i;
325 for (i = 0; s[i] != ECS_CHAR('\0'); i++) {
326 if (s[i] == ECS_CHAR('\n')) {
327 nlines++;
328 colindex = 0;
329 } else {
330 if (!ecs_isprint(s[i]))
331 return FALSE;
333 /* FIXME: This code assumes that each printable
334 * character occupies one cell on the screen. */
335 colindex++;
336 if (colindex > ncolumns)
337 ncolumns = colindex;
340 *ret_width = ncolumns;
341 *ret_height = nlines;
342 return TRUE;