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.
14 #include "msvcrt/stdlib.h"
15 #include "msvcrt/string.h"
18 DEFAULT_DEBUG_CHANNEL(msvcrt);
20 unsigned char MSVCRT_mbctype[257];
21 int MSVCRT___mb_cur_max = 1;
23 int MSVCRT_isleadbyte(int);
24 char *_strset(char *, int);
25 char *_strnset(char *, int, unsigned int);
26 extern unsigned int MSVCRT_current_lc_all_cp;
29 /*********************************************************************
30 * __p__mbctype (MSVCRT.@)
32 unsigned char *__p__mbctype(void)
34 return MSVCRT_mbctype;
37 /*********************************************************************
38 * __p___mb_cur_max(MSVCRT.@)
40 int *__p___mb_cur_max(void)
42 return &MSVCRT___mb_cur_max;
45 /*********************************************************************
48 unsigned int _mbsnextc(const unsigned char *str)
50 if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
51 return *str << 8 | str[1];
52 return *str; /* ASCII CP or SB char */
55 /*********************************************************************
58 int _mbscmp(const char *str, const char *cmp)
60 if(MSVCRT___mb_cur_max > 1)
62 unsigned int strc, cmpc;
68 strc = _mbsnextc(str);
69 cmpc = _mbsnextc(cmp);
71 return strc < cmpc ? -1 : 1;
72 str +=(strc > 255) ? 2 : 1;
73 cmp +=(strc > 255) ? 2 : 1; /* equal, use same increment */
76 return strcmp(str, cmp); /* ASCII CP */
79 /*********************************************************************
82 int _mbsicmp(const char *str, const char *cmp)
84 /* FIXME: No tolower() for mb strings yet */
85 if(MSVCRT___mb_cur_max > 1)
86 return _mbscmp(str, cmp);
87 return strcasecmp(str, cmp); /* ASCII CP */
90 /*********************************************************************
93 int _mbsncmp(const char *str, const char *cmp, unsigned int len)
98 if(MSVCRT___mb_cur_max > 1)
100 unsigned int strc, cmpc;
104 return *cmp ? -1 : 0;
107 strc = _mbsnextc(str);
108 cmpc = _mbsnextc(cmp);
110 return strc < cmpc ? -1 : 1;
111 str +=(strc > 255) ? 2 : 1;
112 cmp +=(strc > 255) ? 2 : 1; /* Equal, use same increment */
114 return 0; /* Matched len chars */
116 return strncmp(str, cmp, len); /* ASCII CP */
119 /*********************************************************************
120 * _mbsnicmp(MSVCRT.@)
122 * Compare two multibyte strings case insensitively to 'len' characters.
124 int _mbsnicmp(const char *str, const char *cmp, unsigned int len)
126 /* FIXME: No tolower() for mb strings yet */
127 if(MSVCRT___mb_cur_max > 1)
128 return _mbsncmp(str, cmp, len);
129 return strncasecmp(str, cmp, len); /* ASCII CP */
132 /*********************************************************************
135 char *_mbsinc(const unsigned char *str)
137 if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
138 return (char *)str + 2; /* MB char */
140 return (char *)str + 1; /* ASCII CP or SB char */
143 /*********************************************************************
146 char *_mbsninc(const char *str, unsigned int num)
150 if(MSVCRT___mb_cur_max > 1)
156 return (char *)str + num; /* ASCII CP */
159 /*********************************************************************
162 int _mbslen(const unsigned char *str)
164 if(MSVCRT___mb_cur_max > 1)
169 str += MSVCRT_isleadbyte(*str) ? 2 : 1;
174 return strlen(str); /* ASCII CP */
177 /*********************************************************************
180 char *_mbsrchr(const char *s,unsigned int x)
182 /* FIXME: handle multibyte strings */
186 /*********************************************************************
189 int MSVCRT_mbtowc(WCHAR *dst, const char *str, unsigned int n)
193 if(!MultiByteToWideChar(CP_ACP, 0, str, n, dst, 1))
195 /* return the number of bytes from src that have been used */
198 if(n >= 2 && MSVCRT_isleadbyte(*str) && str[1])
203 /*********************************************************************
206 void _mbccpy(char *dest, const unsigned char *src)
209 if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*src))
210 *dest = *++src; /* MB char */
213 /*********************************************************************
214 * _mbbtombc(MSVCRT.@)
216 unsigned int _mbbtombc(unsigned int c)
218 if(MSVCRT___mb_cur_max > 1 &&
219 ((c >= 0x20 && c <=0x7e) ||(c >= 0xa1 && c <= 0xdf)))
221 /* FIXME: I can't get this function to return anything
222 * different to what I pass it...
225 return c; /* ASCII CP or no MB char */
228 /*********************************************************************
231 unsigned int _mbclen(const unsigned char *str)
233 return MSVCRT_isleadbyte(*str) ? 2 : 1;
236 /*********************************************************************
237 * _ismbbkana(MSVCRT.@)
239 int _ismbbkana(unsigned int c)
241 /* FIXME: use lc_ctype when supported, not lc_all */
242 if(MSVCRT_current_lc_all_cp == 932)
244 /* Japanese/Katakana, CP 932 */
245 return (c >= 0xa1 && c <= 0xdf);
250 /*********************************************************************
251 * _ismbchira(MSVCRT.@)
253 int _ismbchira(unsigned int c)
255 /* FIXME: use lc_ctype when supported, not lc_all */
256 if(MSVCRT_current_lc_all_cp == 932)
258 /* Japanese/Hiragana, CP 932 */
259 return (c >= 0x829f && c <= 0x82f1);
264 /*********************************************************************
265 * _ismbckata(MSVCRT.@)
267 int _ismbckata(unsigned int c)
269 /* FIXME: use lc_ctype when supported, not lc_all */
270 if(MSVCRT_current_lc_all_cp == 932)
273 return _ismbbkana(c);
274 /* Japanese/Katakana, CP 932 */
275 return (c >= 0x8340 && c <= 0x8396 && c != 0x837f);
280 /*********************************************************************
281 * _ismbblead(MSVCRT.@)
283 int _ismbblead(unsigned int c)
285 /* FIXME: should reference MSVCRT_mbctype */
286 return MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(c);
290 /*********************************************************************
291 * _ismbbtrail(MSVCRT.@)
293 int _ismbbtrail(unsigned int c)
295 /* FIXME: should reference MSVCRT_mbctype */
296 return !_ismbblead(c);
299 /*********************************************************************
300 * _ismbslead(MSVCRT.@)
302 int _ismbslead(const unsigned char *start, const unsigned char *str)
304 /* Lead bytes can also be trail bytes if caller messed up
305 * iterating through the string...
307 if(MSVCRT___mb_cur_max > 1)
310 start += MSVCRT_isleadbyte(*str) ? 2 : 1;
313 return MSVCRT_isleadbyte(*str);
315 return 0; /* Must have been a trail, we skipped it */
318 /*********************************************************************
319 * _ismbstrail(MSVCRT.@)
321 int _ismbstrail(const char *start, const unsigned char *str)
323 /* Must not be a lead, and must be preceeded by one */
324 return !_ismbslead(start, str) && MSVCRT_isleadbyte(str[-1]);
327 /*********************************************************************
330 char *_mbsdec(const char *start, const char *cur)
332 if(MSVCRT___mb_cur_max > 1)
333 return (char *)(_ismbstrail(start,cur-1) ? cur - 2 : cur -1);
335 return (char *)cur - 1; /* ASCII CP or SB char */
338 /*********************************************************************
341 char *_mbsset(char *str, unsigned int c)
345 if(MSVCRT___mb_cur_max == 1 || c < 256)
346 return _strset(str, c); /* ASCII CP or SB char */
348 c &= 0xffff; /* Strip high bits */
350 while(str[0] && str[1])
356 str[0] = '\0'; /* FIXME: OK to shorten? */
361 /*********************************************************************
364 char *_mbsnset(char *str, unsigned int c, unsigned int len)
371 if(MSVCRT___mb_cur_max == 1 || c < 256)
372 return _strnset(str, c, len); /* ASCII CP or SB char */
374 c &= 0xffff; /* Strip high bits */
376 while(str[0] && str[1] && len--)
382 str[0] = '\0'; /* FIXME: OK to shorten? */
387 /*********************************************************************
388 * _mbstrlen(MSVCRT.@)
390 MSVCRT_size_t _mbstrlen(const char *str)
392 if(MSVCRT___mb_cur_max > 1)
397 str += MSVCRT_isleadbyte(*str) ? 2 : 1;
402 return strlen(str); /* ASCII CP */
405 /*********************************************************************
408 char *_mbsncpy(char *dst, const char *src, unsigned int len)
412 if(MSVCRT___mb_cur_max > 1)
415 while(src[0] && src[1] && len--)
422 *dst++ = *src++; /* Last char or '\0' */
428 return strncpy(dst, src, len); /* ASCII CP */
431 /*********************************************************************
434 * Find a multibyte character in a multibyte string.
436 unsigned char* _mbschr(const unsigned char* str, unsigned int c)
438 if(MSVCRT___mb_cur_max > 1)
441 while((next = _mbsnextc(str)))
445 str += next > 255 ? 2 : 1;
447 return c ? NULL :(char *)str;
449 return strchr(str, c); /* ASCII CP */
452 /*********************************************************************
453 * _mbsnccnt(MSVCRT.@)
455 unsigned int _mbsnccnt(const unsigned char *str, unsigned int len)
459 if(MSVCRT___mb_cur_max > 1)
461 while(*str && len-- > 0)
463 if(MSVCRT_isleadbyte(*str))
473 return min(strlen(str), len); /* ASCII CP */
477 /*********************************************************************
480 unsigned char* _mbsncat(unsigned char* dst, const unsigned char* src, MSVCRT_size_t len)
482 if(MSVCRT___mb_cur_max > 1)
489 if(MSVCRT_isleadbyte(*src))
497 return strncat(dst, src, len); /* ASCII CP */
501 /*********************************************************************
502 * _ismbcdigit(MSVCRT.@)
504 int _ismbcdigit( unsigned int ch)
510 FIXME("Handle MBC chars\n");
516 /*********************************************************************
517 * _mbsnbcmp(MSVCRT.@)
519 int _mbsnbcmp( const unsigned char *str,const unsigned char *cmp, MSVCRT_size_t len )
523 if(MSVCRT___mb_cur_max > 1)
525 FIXME("%s %s %d\n",str,cmp,len);
528 return strncmp(str,cmp,len);
532 /*********************************************************************
535 unsigned char * _mbslwr( unsigned char *string )
539 if(MSVCRT___mb_cur_max > 1)
541 FIXME("%s\n",string);
554 /*********************************************************************
555 * _mbsnbcpy(MSVCRT.@)
557 unsigned char * _mbsnbcpy(unsigned char *dest,const unsigned char *src,MSVCRT_size_t n)
559 if(MSVCRT___mb_cur_max > 1)
561 FIXME("%s %d\n",src,n);
564 return strncpy(dest, src, n);
568 /*********************************************************************
571 MSVCRT_size_t _mbsspn(const unsigned char *string, const unsigned char *set)
573 const unsigned char *p, *q;
575 for (p = string; *p; p++)
577 if (MSVCRT_isleadbyte(*p))
579 for (q = set; *q; q++)
583 if ((*p == *q) && (p[1] == q[1]))
591 for (q = set; *q; q++)
599 /*********************************************************************
600 * _ismbcspace (MSVCRT.@)
602 int _ismbcspace( unsigned int c)