2 * msvcrt.dll mbcs functions
4 * Copyright 1999 Alexandre Julliard
5 * Copyright 2000 Jon Griffths
8 * Not currently binary compatible with win32. MSVCRT_mbctype must be
9 * populated correctly and the ismb* functions should reference it.
13 #include "msvcrt/string.h"
16 DEFAULT_DEBUG_CHANNEL(msvcrt
);
18 unsigned char MSVCRT_mbctype
[257];
19 int MSVCRT___mb_cur_max
= 1;
21 int MSVCRT_isleadbyte(int);
22 char *_strset(char *, int);
23 char *_strnset(char *, int, unsigned int);
24 extern unsigned int MSVCRT_current_lc_all_cp
;
27 /*********************************************************************
28 * __p__mbctype (MSVCRT.@)
30 unsigned char *__p__mbctype(void)
32 return MSVCRT_mbctype
;
35 /*********************************************************************
36 * __p___mb_cur_max(MSVCRT.@)
38 int *__p___mb_cur_max(void)
40 return &MSVCRT___mb_cur_max
;
43 /*********************************************************************
46 unsigned int _mbsnextc(const unsigned char *str
)
48 if(MSVCRT___mb_cur_max
> 1 && MSVCRT_isleadbyte(*str
))
49 return *str
<< 8 | str
[1];
50 return *str
; /* ASCII CP or SB char */
53 /*********************************************************************
56 int _mbscmp(const char *str
, const char *cmp
)
58 if(MSVCRT___mb_cur_max
> 1)
60 unsigned int strc
, cmpc
;
66 strc
= _mbsnextc(str
);
67 cmpc
= _mbsnextc(cmp
);
69 return strc
< cmpc
? -1 : 1;
70 str
+=(strc
> 255) ? 2 : 1;
71 cmp
+=(strc
> 255) ? 2 : 1; /* equal, use same increment */
74 return strcmp(str
, cmp
); /* ASCII CP */
77 /*********************************************************************
80 int _mbsicmp(const char *str
, const char *cmp
)
82 /* FIXME: No tolower() for mb strings yet */
83 if(MSVCRT___mb_cur_max
> 1)
84 return _mbscmp(str
, cmp
);
85 return strcasecmp(str
, cmp
); /* ASCII CP */
88 /*********************************************************************
91 int _mbsncmp(const char *str
, const char *cmp
, unsigned int len
)
96 if(MSVCRT___mb_cur_max
> 1)
98 unsigned int strc
, cmpc
;
102 return *cmp
? -1 : 0;
105 strc
= _mbsnextc(str
);
106 cmpc
= _mbsnextc(cmp
);
108 return strc
< cmpc
? -1 : 1;
109 str
+=(strc
> 255) ? 2 : 1;
110 cmp
+=(strc
> 255) ? 2 : 1; /* Equal, use same increment */
112 return 0; /* Matched len chars */
114 return strncmp(str
, cmp
, len
); /* ASCII CP */
117 /*********************************************************************
118 * _mbsnicmp(MSVCRT.@)
120 * Compare two multibyte strings case insensitively to 'len' characters.
122 int _mbsnicmp(const char *str
, const char *cmp
, unsigned int len
)
124 /* FIXME: No tolower() for mb strings yet */
125 if(MSVCRT___mb_cur_max
> 1)
126 return _mbsncmp(str
, cmp
, len
);
127 return strncasecmp(str
, cmp
, len
); /* ASCII CP */
130 /*********************************************************************
133 char *_mbsinc(const unsigned char *str
)
135 if(MSVCRT___mb_cur_max
> 1 && MSVCRT_isleadbyte(*str
))
136 return (char *)str
+ 2; /* MB char */
138 return (char *)str
+ 1; /* ASCII CP or SB char */
141 /*********************************************************************
144 char *_mbsninc(const char *str
, unsigned int num
)
148 if(MSVCRT___mb_cur_max
> 1)
154 return (char *)str
+ num
; /* ASCII CP */
157 /*********************************************************************
158 * _mbslen(MSVCRT.206)
160 int _mbslen(const unsigned char *str
)
162 if(MSVCRT___mb_cur_max
> 1)
167 str
+= MSVCRT_isleadbyte(*str
) ? 2 : 1;
172 return strlen(str
); /* ASCII CP */
175 /*********************************************************************
178 char *_mbsrchr(const char *s
,unsigned int x
)
180 /* FIXME: handle multibyte strings */
184 /*********************************************************************
187 int MSVCRT_mbtowc(WCHAR
*dst
, const unsigned char *str
, unsigned int n
)
191 if(!MultiByteToWideChar(CP_ACP
, 0, str
, n
, dst
, 1))
193 /* return the number of bytes from src that have been used */
196 if(n
>= 2 && MSVCRT_isleadbyte(*str
) && str
[1])
201 /*********************************************************************
204 void _mbccpy(char *dest
, const unsigned char *src
)
207 if(MSVCRT___mb_cur_max
> 1 && MSVCRT_isleadbyte(*src
))
208 *dest
= *++src
; /* MB char */
211 /*********************************************************************
212 * _mbbtombc(MSVCRT.@)
214 unsigned int _mbbtombc(unsigned int c
)
216 if(MSVCRT___mb_cur_max
> 1 &&
217 ((c
>= 0x20 && c
<=0x7e) ||(c
>= 0xa1 && c
<= 0xdf)))
219 /* FIXME: I can't get this function to return anything
220 * different to what I pass it...
223 return c
; /* ASCII CP or no MB char */
226 /*********************************************************************
229 unsigned int _mbclen(const unsigned char *str
)
231 return MSVCRT_isleadbyte(*str
) ? 2 : 1;
234 /*********************************************************************
235 * _ismbbkana(MSVCRT.@)
237 int _ismbbkana(unsigned int c
)
239 /* FIXME: use lc_ctype when supported, not lc_all */
240 if(MSVCRT_current_lc_all_cp
== 932)
242 /* Japanese/Katakana, CP 932 */
243 return (c
>= 0xa1 && c
<= 0xdf);
248 /*********************************************************************
249 * _ismbchira(MSVCRT.@)
251 int _ismbchira(unsigned int c
)
253 /* FIXME: use lc_ctype when supported, not lc_all */
254 if(MSVCRT_current_lc_all_cp
== 932)
256 /* Japanese/Hiragana, CP 932 */
257 return (c
>= 0x829f && c
<= 0x82f1);
262 /*********************************************************************
263 * _ismbckata(MSVCRT.@)
265 int _ismbckata(unsigned int c
)
267 /* FIXME: use lc_ctype when supported, not lc_all */
268 if(MSVCRT_current_lc_all_cp
== 932)
271 return _ismbbkana(c
);
272 /* Japanese/Katakana, CP 932 */
273 return (c
>= 0x8340 && c
<= 0x8396 && c
!= 0x837f);
278 /*********************************************************************
279 * _ismbblead(MSVCRT.@)
281 int _ismbblead(unsigned int c
)
283 /* FIXME: should reference MSVCRT_mbctype */
284 return MSVCRT___mb_cur_max
> 1 && MSVCRT_isleadbyte(c
);
288 /*********************************************************************
289 * _ismbbtrail(MSVCRT.@)
291 int _ismbbtrail(unsigned int c
)
293 /* FIXME: should reference MSVCRT_mbctype */
294 return !_ismbblead(c
);
297 /*********************************************************************
298 * _ismbslead(MSVCRT.@)
300 int _ismbslead(const unsigned char *start
, const unsigned char *str
)
302 /* Lead bytes can also be trail bytes if caller messed up
303 * iterating through the string...
305 if(MSVCRT___mb_cur_max
> 1)
308 start
+= MSVCRT_isleadbyte(*str
) ? 2 : 1;
311 return MSVCRT_isleadbyte(*str
);
313 return 0; /* Must have been a trail, we skipped it */
316 /*********************************************************************
317 * _ismbstrail(MSVCRT.@)
319 int _ismbstrail(const char *start
, const unsigned char *str
)
321 /* Must not be a lead, and must be preceeded by one */
322 return !_ismbslead(start
, str
) && MSVCRT_isleadbyte(str
[-1]);
325 /*********************************************************************
328 char *_mbsdec(const char *start
, const char *cur
)
330 if(MSVCRT___mb_cur_max
> 1)
331 return (char *)(_ismbstrail(start
,cur
-1) ? cur
- 2 : cur
-1);
333 return (char *)cur
- 1; /* ASCII CP or SB char */
336 /*********************************************************************
339 char *_mbsset(char *str
, unsigned int c
)
343 if(MSVCRT___mb_cur_max
== 1 || c
< 256)
344 return _strset(str
, c
); /* ASCII CP or SB char */
346 c
&= 0xffff; /* Strip high bits */
348 while(str
[0] && str
[1])
354 str
[0] = '\0'; /* FIXME: OK to shorten? */
359 /*********************************************************************
362 char *_mbsnset(char *str
, unsigned int c
, unsigned int len
)
369 if(MSVCRT___mb_cur_max
== 1 || c
< 256)
370 return _strnset(str
, c
, len
); /* ASCII CP or SB char */
372 c
&= 0xffff; /* Strip high bits */
374 while(str
[0] && str
[1] && len
--)
380 str
[0] = '\0'; /* FIXME: OK to shorten? */
385 /*********************************************************************
386 * _mbstrlen(MSVCRT.@)
388 int _mbstrlen(const unsigned char *str
)
390 if(MSVCRT___mb_cur_max
> 1)
395 str
+= MSVCRT_isleadbyte(*str
) ? 2 : 1;
400 return strlen(str
); /* ASCII CP */
403 /*********************************************************************
406 char *_mbsncpy(char *dst
, const char *src
, unsigned int len
)
410 if(MSVCRT___mb_cur_max
> 1)
413 while(src
[0] && src
[1] && len
--)
420 *dst
++ = *src
++; /* Last char or '\0' */
426 return strncpy(dst
, src
, len
); /* ASCII CP */
429 /*********************************************************************
432 * Find a multibyte character in a multibyte string.
434 unsigned char* _mbschr(const unsigned char* str
, unsigned int c
)
436 if(MSVCRT___mb_cur_max
> 1)
439 while((next
= _mbsnextc(str
)))
443 str
+= next
> 255 ? 2 : 1;
445 return c
? NULL
:(char *)str
;
447 return strchr(str
, c
); /* ASCII CP */
450 /*********************************************************************
451 * _mbsnccnt(MSVCRT.@)
453 unsigned int _mbsnccnt(const unsigned char *str
, unsigned int len
)
457 if(MSVCRT___mb_cur_max
> 1)
459 while(*str
&& len
-- > 0)
461 if(MSVCRT_isleadbyte(*str
))
471 return min(strlen(str
), len
); /* ASCII CP */
475 /*********************************************************************
478 unsigned char* _mbsncat(unsigned char* dst
, const unsigned char* src
, MSVCRT_size_t len
)
480 if(MSVCRT___mb_cur_max
> 1)
487 if(MSVCRT_isleadbyte(*src
))
495 return strncat(dst
, src
, len
); /* ASCII CP */