2 Basic support for extended character sets.
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,
30 #include <mhl/types.h>
31 #include <mhl/string.h>
37 * String type conversion
40 extern bool ecs_mbstr_to_str(ecs_char
**ret_str
, const char *s
)
42 #ifdef EXTCHARSET_ENABLED
48 str
= g_new(ecs_char
, maxlen
+ 1);
49 len
= mbstowcs(str
, s
, maxlen
+ 1);
50 if (len
== (size_t) -1) {
55 assert(len
<= maxlen
);
56 *ret_str
= g_renew(ecs_char
, str
, len
+ 1);
59 *ret_str
= g_strdup(s
);
64 extern bool ecs_str_to_mbstr(char **ret_str
, const ecs_char
*s
)
66 #ifdef EXTCHARSET_ENABLED
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) {
79 assert(len
<= maxlen
);
80 *ret_str
= g_renew(char, str
, len
+ 1);
83 *ret_str
= g_strdup(s
);
89 * Character classification
92 #ifdef EXTCHARSET_ENABLED
95 # define ECS_CTYPE(wf, cf, c) \
98 # define ECS_CTYPE(wf, cf, c) \
99 (((unsigned char) c != c) ? FALSE : (cf(c)))
102 # define ECS_CTYPE(wf, cf, c) \
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
);
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
)
176 unsigned long ca
, cb
;
178 for (i
= 0; a
[i
] == b
[i
]; i
++) {
179 if (a
[i
] == ECS_CHAR('\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 */
192 ecs_strchr(const ecs_char
*s
, ecs_char c
)
196 for (i
= 0; s
[i
] != c
; i
++) {
197 if (s
[i
] == ECS_CHAR('\0'))
200 return (ecs_char
*) s
+ i
;
204 ecs_strcspn(const ecs_char
*haystack
, const ecs_char
*needles
)
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
])
217 /* left out: ecs_strpbrk */
220 ecs_strrchr(const ecs_char
*s
, ecs_char c
)
225 for (i
= 0, pos
= NULL
;; i
++) {
227 pos
= (ecs_char
*) s
+ i
;
228 if (s
[i
] == ECS_CHAR('\0'))
234 ecs_strspn(const ecs_char
*s
, const ecs_char
*chars
)
238 for (i
= 0; s
[i
] != ECS_CHAR('\0'); i
++) {
239 if (ecs_strchr(chars
, s
[i
]) == NULL
)
246 ecs_strstr(const ecs_char
*s
, const ecs_char
*sub
)
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
])
255 return (ecs_char
*) s
+ i
;
262 /* left out: ecs_strtok */
265 ecs_strlen(const ecs_char
*s
)
269 for (i
= 0; s
[i
] != ECS_CHAR('\0'); i
++)
278 ecs_char
*ecs_xstrdup(const ecs_char
*s
)
284 retval
= g_new(ecs_char
, len
+ 1);
285 memcpy(retval
, s
, (len
+ 1) * sizeof(ecs_char
));
290 ecs_strlcpy(ecs_char
*dst
, const ecs_char
*src
, size_t dstsize
)
292 size_t n
= 0; /* number of copied characters */
295 while (n
< dstsize
- 1 && *src
!= ECS_CHAR('\0')) {
299 *dst
= ECS_CHAR('\0');
302 while (*src
!= ECS_CHAR('\0')) {
311 ecs_strlcat(ecs_char
*dst
, const ecs_char
*src
, size_t dstsize
)
315 while (di
< dstsize
&& dst
[di
] != ECS_CHAR('\0'))
317 return di
+ ecs_strlcpy(dst
+ di
, src
, dstsize
- di
);
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')) {
330 if (!ecs_isprint(s
[i
]))
333 /* FIXME: This code assumes that each printable
334 * character occupies one cell on the screen. */
336 if (colindex
> ncolumns
)
340 *ret_width
= ncolumns
;
341 *ret_height
= nlines
;