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,
26 * \brief Source: basic support for extended character sets
38 * String type conversion
41 extern gboolean
ecs_mbstr_to_str(ecs_char
**ret_str
, const char *s
)
43 #ifdef EXTCHARSET_ENABLED
49 str
= g_new(ecs_char
, maxlen
+ 1);
50 len
= mbstowcs(str
, s
, maxlen
+ 1);
51 if (len
== (size_t) -1) {
56 assert(len
<= maxlen
);
57 *ret_str
= g_renew(ecs_char
, str
, len
+ 1);
60 *ret_str
= g_strdup(s
);
65 extern gboolean
ecs_str_to_mbstr(char **ret_str
, const ecs_char
*s
)
67 #ifdef EXTCHARSET_ENABLED
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) {
80 assert(len
<= maxlen
);
81 *ret_str
= g_renew(char, str
, len
+ 1);
84 *ret_str
= g_strdup(s
);
90 * Character classification
93 #ifdef EXTCHARSET_ENABLED
96 # define ECS_CTYPE(wf, cf, c) \
99 # define ECS_CTYPE(wf, cf, c) \
100 (((unsigned char) c != c) ? FALSE : (cf(c)))
103 # define ECS_CTYPE(wf, cf, c) \
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
);
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
)
177 unsigned long ca
, cb
;
179 for (i
= 0; a
[i
] == b
[i
]; i
++) {
180 if (a
[i
] == ECS_CHAR('\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 */
193 ecs_strchr(const ecs_char
*s
, ecs_char c
)
197 for (i
= 0; s
[i
] != c
; i
++) {
198 if (s
[i
] == ECS_CHAR('\0'))
201 return (ecs_char
*) s
+ i
;
205 ecs_strcspn(const ecs_char
*haystack
, const ecs_char
*needles
)
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
])
218 /* left out: ecs_strpbrk */
221 ecs_strrchr(const ecs_char
*s
, ecs_char c
)
226 for (i
= 0, pos
= NULL
;; i
++) {
228 pos
= (ecs_char
*) s
+ i
;
229 if (s
[i
] == ECS_CHAR('\0'))
235 ecs_strspn(const ecs_char
*s
, const ecs_char
*chars
)
239 for (i
= 0; s
[i
] != ECS_CHAR('\0'); i
++) {
240 if (ecs_strchr(chars
, s
[i
]) == NULL
)
247 ecs_strstr(const ecs_char
*s
, const ecs_char
*sub
)
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
])
256 return (ecs_char
*) s
+ i
;
263 /* left out: ecs_strtok */
266 ecs_strlen(const ecs_char
*s
)
270 for (i
= 0; s
[i
] != ECS_CHAR('\0'); i
++)
279 ecs_char
*ecs_xstrdup(const ecs_char
*s
)
285 retval
= g_new(ecs_char
, len
+ 1);
286 memcpy(retval
, s
, (len
+ 1) * sizeof(ecs_char
));
291 ecs_strlcpy(ecs_char
*dst
, const ecs_char
*src
, size_t dstsize
)
293 size_t n
= 0; /* number of copied characters */
296 while (n
< dstsize
- 1 && *src
!= ECS_CHAR('\0')) {
300 *dst
= ECS_CHAR('\0');
303 while (*src
!= ECS_CHAR('\0')) {
312 ecs_strlcat(ecs_char
*dst
, const ecs_char
*src
, size_t dstsize
)
316 while (di
< dstsize
&& dst
[di
] != ECS_CHAR('\0'))
318 return di
+ ecs_strlcpy(dst
+ di
, src
, dstsize
- di
);
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')) {
331 if (!ecs_isprint(s
[i
]))
334 /* FIXME: This code assumes that each printable
335 * character occupies one cell on the screen. */
337 if (colindex
> ncolumns
)
341 *ret_width
= ncolumns
;
342 *ret_height
= nlines
;