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 DEFAULT_DEBUG_CHANNEL(msvcrt
);
15 unsigned char MSVCRT_mbctype
[257];
16 int MSVCRT___mb_cur_max
= 1;
18 int __cdecl
MSVCRT_isleadbyte(int);
19 char *__cdecl
MSVCRT__strset(char *, int);
20 char *__cdecl
MSVCRT__strnset(char *, int, unsigned int);
21 extern unsigned int MSVCRT_current_lc_all_cp
;
24 /*********************************************************************
25 * __p__mbctype (MSVCRT.@)
27 unsigned char *__cdecl
MSVCRT___p__mbctype(void)
29 return MSVCRT_mbctype
;
32 /*********************************************************************
33 * __p___mb_cur_max(MSVCRT.@)
35 int *__cdecl
MSVCRT___p___mb_cur_max(void)
37 return &MSVCRT___mb_cur_max
;
40 /*********************************************************************
43 unsigned int __cdecl
MSVCRT__mbsnextc(const unsigned char *str
)
45 if(MSVCRT___mb_cur_max
> 1 && MSVCRT_isleadbyte(*str
))
46 return *str
<< 8 | str
[1];
47 return *str
; /* ASCII CP or SB char */
50 /*********************************************************************
53 int __cdecl
MSVCRT__mbscmp(const char *str
, const char *cmp
)
55 if(MSVCRT___mb_cur_max
> 1)
57 unsigned int strc
, cmpc
;
63 strc
= MSVCRT__mbsnextc(str
);
64 cmpc
= MSVCRT__mbsnextc(cmp
);
66 return strc
< cmpc
? -1 : 1;
67 str
+=(strc
> 255) ? 2 : 1;
68 cmp
+=(strc
> 255) ? 2 : 1; /* equal, use same increment */
71 return strcmp(str
, cmp
); /* ASCII CP */
74 /*********************************************************************
77 int __cdecl
MSVCRT__mbsicmp(const char *str
, const char *cmp
)
79 /* FIXME: No tolower() for mb strings yet */
80 if(MSVCRT___mb_cur_max
> 1)
81 return MSVCRT__mbscmp(str
, cmp
);
82 return strcasecmp(str
, cmp
); /* ASCII CP */
85 /*********************************************************************
88 int __cdecl
MSVCRT__mbsncmp(const char *str
, const char *cmp
, unsigned int len
)
93 if(MSVCRT___mb_cur_max
> 1)
95 unsigned int strc
, cmpc
;
102 strc
= MSVCRT__mbsnextc(str
);
103 cmpc
= MSVCRT__mbsnextc(cmp
);
105 return strc
< cmpc
? -1 : 1;
106 str
+=(strc
> 255) ? 2 : 1;
107 cmp
+=(strc
> 255) ? 2 : 1; /* Equal, use same increment */
109 return 0; /* Matched len chars */
111 return strncmp(str
, cmp
, len
); /* ASCII CP */
114 /*********************************************************************
115 * _mbsnicmp(MSVCRT.@)
117 * Compare two multibyte strings case insensitively to 'len' characters.
119 int __cdecl
MSVCRT__mbsnicmp(const char *str
, const char *cmp
, unsigned int len
)
121 /* FIXME: No tolower() for mb strings yet */
122 if(MSVCRT___mb_cur_max
> 1)
123 return MSVCRT__mbsncmp(str
, cmp
, len
);
124 return strncasecmp(str
, cmp
, len
); /* ASCII CP */
127 /*********************************************************************
130 char *__cdecl
MSVCRT__mbsinc(const unsigned char *str
)
132 if(MSVCRT___mb_cur_max
> 1 && MSVCRT_isleadbyte(*str
))
133 return (char *)str
+ 2; /* MB char */
135 return (char *)str
+ 1; /* ASCII CP or SB char */
138 /*********************************************************************
141 char *MSVCRT__mbsninc(const char *str
, unsigned int num
)
145 if(MSVCRT___mb_cur_max
> 1)
148 str
= MSVCRT__mbsinc(str
);
151 return (char *)str
+ num
; /* ASCII CP */
154 /*********************************************************************
155 * _mbslen(MSVCRT.206)
157 int __cdecl
MSVCRT__mbslen(const unsigned char *str
)
159 if(MSVCRT___mb_cur_max
> 1)
164 str
+= MSVCRT_isleadbyte(*str
) ? 2 : 1;
169 return strlen(str
); /* ASCII CP */
172 /*********************************************************************
175 char *__cdecl
MSVCRT__mbsrchr(const char *s
,unsigned int x
)
177 /* FIXME: handle multibyte strings */
181 /*********************************************************************
184 int __cdecl
MSVCRT_mbtowc(WCHAR
*dst
, const unsigned char *str
, unsigned int n
)
188 if(!MultiByteToWideChar(CP_ACP
, 0, str
, n
, dst
, 1))
190 /* return the number of bytes from src that have been used */
193 if(n
>= 2 && MSVCRT_isleadbyte(*str
) && str
[1])
198 /*********************************************************************
201 void __cdecl
MSVCRT__mbccpy(char *dest
, const unsigned char *src
)
204 if(MSVCRT___mb_cur_max
> 1 && MSVCRT_isleadbyte(*src
))
205 *dest
= *++src
; /* MB char */
208 /*********************************************************************
209 * _mbbtombc(MSVCRT.@)
211 unsigned int __cdecl
MSVCRT__mbbtombc(unsigned int c
)
213 if(MSVCRT___mb_cur_max
> 1 &&
214 ((c
>= 0x20 && c
<=0x7e) ||(c
>= 0xa1 && c
<= 0xdf)))
216 /* FIXME: I can't get this function to return anything
217 * different to what I pass it...
220 return c
; /* ASCII CP or no MB char */
223 /*********************************************************************
226 unsigned int __cdecl
MSVCRT__mbclen(const unsigned char *str
)
228 return MSVCRT_isleadbyte(*str
) ? 2 : 1;
231 /*********************************************************************
232 * _ismbbkana(MSVCRT.@)
234 int __cdecl
MSVCRT__ismbbkana(unsigned int c
)
236 /* FIXME: use lc_ctype when supported, not lc_all */
237 if(MSVCRT_current_lc_all_cp
== 932)
239 /* Japanese/Katakana, CP 932 */
240 return (c
>= 0xa1 && c
<= 0xdf);
245 /*********************************************************************
246 * _ismbchira(MSVCRT.@)
248 int __cdecl
MSVCRT__ismbchira(unsigned int c
)
250 /* FIXME: use lc_ctype when supported, not lc_all */
251 if(MSVCRT_current_lc_all_cp
== 932)
253 /* Japanese/Hiragana, CP 932 */
254 return (c
>= 0x829f && c
<= 0x82f1);
259 /*********************************************************************
260 * _ismbckata(MSVCRT.@)
262 int __cdecl
MSVCRT__ismbckata(unsigned int c
)
264 /* FIXME: use lc_ctype when supported, not lc_all */
265 if(MSVCRT_current_lc_all_cp
== 932)
268 return MSVCRT__ismbbkana(c
);
269 /* Japanese/Katakana, CP 932 */
270 return (c
>= 0x8340 && c
<= 0x8396 && c
!= 0x837f);
275 /*********************************************************************
276 * _ismbblead(MSVCRT.@)
278 int __cdecl
MSVCRT__ismbblead(unsigned int c
)
280 /* FIXME: should reference MSVCRT_mbctype */
281 return MSVCRT___mb_cur_max
> 1 && MSVCRT_isleadbyte(c
);
285 /*********************************************************************
286 * _ismbbtrail(MSVCRT.@)
288 int __cdecl
MSVCRT__ismbbtrail(unsigned int c
)
290 /* FIXME: should reference MSVCRT_mbctype */
291 return !MSVCRT__ismbblead(c
);
294 /*********************************************************************
295 * _ismbslead(MSVCRT.@)
297 int __cdecl
MSVCRT__ismbslead(const unsigned char *start
, const unsigned char *str
)
299 /* Lead bytes can also be trail bytes if caller messed up
300 * iterating through the string...
302 if(MSVCRT___mb_cur_max
> 1)
305 start
+= MSVCRT_isleadbyte(*str
) ? 2 : 1;
308 return MSVCRT_isleadbyte(*str
);
310 return 0; /* Must have been a trail, we skipped it */
313 /*********************************************************************
314 * _ismbstrail(MSVCRT.@)
316 int __cdecl
MSVCRT__ismbstrail(const char *start
, const unsigned char *str
)
318 /* Must not be a lead, and must be preceeded by one */
319 return !MSVCRT__ismbslead(start
, str
) && MSVCRT_isleadbyte(str
[-1]);
322 /*********************************************************************
325 char *__cdecl
MSVCRT__mbsdec(const char *start
, const char *cur
)
327 if(MSVCRT___mb_cur_max
> 1)
328 return (char *)(MSVCRT__ismbstrail(start
,cur
-1) ? cur
- 2 : cur
-1);
330 return (char *)cur
- 1; /* ASCII CP or SB char */
333 /*********************************************************************
336 char *__cdecl
MSVCRT__mbsset(char *str
, unsigned int c
)
340 if(MSVCRT___mb_cur_max
== 1 || c
< 256)
341 return MSVCRT__strset(str
, c
); /* ASCII CP or SB char */
343 c
&= 0xffff; /* Strip high bits */
345 while(str
[0] && str
[1])
351 str
[0] = '\0'; /* FIXME: OK to shorten? */
356 /*********************************************************************
359 char *__cdecl
MSVCRT__mbsnset(char *str
, unsigned int c
, unsigned int len
)
366 if(MSVCRT___mb_cur_max
== 1 || c
< 256)
367 return MSVCRT__strnset(str
, c
, len
); /* ASCII CP or SB char */
369 c
&= 0xffff; /* Strip high bits */
371 while(str
[0] && str
[1] && len
--)
377 str
[0] = '\0'; /* FIXME: OK to shorten? */
382 /*********************************************************************
383 * _mbstrlen(MSVCRT.@)
385 int __cdecl
MSVCRT__mbstrlen(const unsigned char *str
)
387 if(MSVCRT___mb_cur_max
> 1)
392 str
+= MSVCRT_isleadbyte(*str
) ? 2 : 1;
397 return strlen(str
); /* ASCII CP */
400 /*********************************************************************
403 char *__cdecl
MSVCRT__mbsncpy(char *dst
, const char *src
, unsigned int len
)
407 if(MSVCRT___mb_cur_max
> 1)
410 while(src
[0] && src
[1] && len
--)
417 *dst
++ = *src
++; /* Last char or '\0' */
423 return strncpy(dst
, src
, len
); /* ASCII CP */
426 /*********************************************************************
429 * Find a multibyte character in a multibyte string.
431 char *__cdecl
MSVCRT__mbschr(const char *str
, unsigned int c
)
433 if(MSVCRT___mb_cur_max
> 1)
436 while((next
= MSVCRT__mbsnextc(str
)))
440 str
+= next
> 255 ? 2 : 1;
442 return c
? NULL
:(char *)str
;
444 return strchr(str
, c
); /* ASCII CP */
447 /*********************************************************************
448 * _mbsnccnt(MSVCRT.@)
450 unsigned int __cdecl
MSVCRT__mbsnccnt(const unsigned char *str
, unsigned int len
)
454 if(MSVCRT___mb_cur_max
> 1)
456 while(*str
&& len
-- > 0)
458 if(MSVCRT_isleadbyte(*str
))
468 return min(strlen(str
), len
); /* ASCII CP */
472 /*********************************************************************
475 char *__cdecl
MSVCRT__mbsncat(char *dst
, const unsigned char *src
, unsigned int len
)
477 if(MSVCRT___mb_cur_max
> 1)
480 dst
+= MSVCRT__mbslen(dst
);
484 if(MSVCRT_isleadbyte(*src
))
492 return strncat(dst
, src
, len
); /* ASCII CP */