Handle the %f case in wsprintf.
[wine.git] / dlls / msvcrt / mbcs.c
blob34517cba4eb111cc0762f2dec0d9960b5ca11484
1 /*
2 * msvcrt.dll mbcs functions
4 * Copyright 1999 Alexandre Julliard
5 * Copyright 2000 Jon Griffths
7 * FIXME
8 * Not currently binary compatible with win32. MSVCRT_mbctype must be
9 * populated correctly and the ismb* functions should reference it.
11 #include "msvcrt.h"
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 /*********************************************************************
44 * _mbsnextc(MSVCRT.@)
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 /*********************************************************************
54 * _mbscmp(MSVCRT.@)
56 int _mbscmp(const char *str, const char *cmp)
58 if(MSVCRT___mb_cur_max > 1)
60 unsigned int strc, cmpc;
61 do {
62 if(!*str)
63 return *cmp ? -1 : 0;
64 if(!*cmp)
65 return 1;
66 strc = _mbsnextc(str);
67 cmpc = _mbsnextc(cmp);
68 if(strc != cmpc)
69 return strc < cmpc ? -1 : 1;
70 str +=(strc > 255) ? 2 : 1;
71 cmp +=(strc > 255) ? 2 : 1; /* equal, use same increment */
72 } while(1);
74 return strcmp(str, cmp); /* ASCII CP */
77 /*********************************************************************
78 * _mbsicmp(MSVCRT.@)
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 /*********************************************************************
89 * _mbsncmp (MSVCRT.@)
91 int _mbsncmp(const char *str, const char *cmp, unsigned int len)
93 if(!len)
94 return 0;
96 if(MSVCRT___mb_cur_max > 1)
98 unsigned int strc, cmpc;
99 while(len--)
101 if(!*str)
102 return *cmp ? -1 : 0;
103 if(!*cmp)
104 return 1;
105 strc = _mbsnextc(str);
106 cmpc = _mbsnextc(cmp);
107 if(strc != cmpc)
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 /*********************************************************************
131 * _mbsinc(MSVCRT.@)
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 /*********************************************************************
142 * _mbsninc(MSVCRT.@)
144 char *_mbsninc(const char *str, unsigned int num)
146 if(!str || num < 1)
147 return NULL;
148 if(MSVCRT___mb_cur_max > 1)
150 while(num--)
151 str = _mbsinc(str);
152 return (char *)str;
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)
164 int len = 0;
165 while(*str)
167 str += MSVCRT_isleadbyte(*str) ? 2 : 1;
168 len++;
170 return len;
172 return strlen(str); /* ASCII CP */
175 /*********************************************************************
176 * _mbsrchr(MSVCRT.@)
178 char *_mbsrchr(const char *s,unsigned int x)
180 /* FIXME: handle multibyte strings */
181 return strrchr(s,x);
184 /*********************************************************************
185 * mbtowc(MSVCRT.@)
187 int MSVCRT_mbtowc(WCHAR *dst, const unsigned char *str, unsigned int n)
189 if(n <= 0 || !str)
190 return 0;
191 if(!MultiByteToWideChar(CP_ACP, 0, str, n, dst, 1))
192 return 0;
193 /* return the number of bytes from src that have been used */
194 if(!*str)
195 return 0;
196 if(n >= 2 && MSVCRT_isleadbyte(*str) && str[1])
197 return 2;
198 return 1;
201 /*********************************************************************
202 * _mbccpy(MSVCRT.@)
204 void _mbccpy(char *dest, const unsigned char *src)
206 *dest++ = *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 /*********************************************************************
227 * _mbclen(MSVCRT.@)
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);
245 return 0;
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);
259 return 0;
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)
270 if(c < 256)
271 return _ismbbkana(c);
272 /* Japanese/Katakana, CP 932 */
273 return (c >= 0x8340 && c <= 0x8396 && c != 0x837f);
275 return 0;
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)
307 while(start < str)
308 start += MSVCRT_isleadbyte(*str) ? 2 : 1;
310 if(start == str)
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 /*********************************************************************
326 * _mbsdec(MSVCRT.@)
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 /*********************************************************************
337 * _mbsset(MSVCRT.@)
339 char *_mbsset(char *str, unsigned int c)
341 char *ret = str;
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])
350 *str++ = c >> 8;
351 *str++ = c & 0xff;
353 if(str[0])
354 str[0] = '\0'; /* FIXME: OK to shorten? */
356 return ret;
359 /*********************************************************************
360 * _mbsnset(MSVCRT.@)
362 char *_mbsnset(char *str, unsigned int c, unsigned int len)
364 char *ret = str;
366 if(!len)
367 return ret;
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--)
376 *str++ = c >> 8;
377 *str++ = c & 0xff;
379 if(len && str[0])
380 str[0] = '\0'; /* FIXME: OK to shorten? */
382 return ret;
385 /*********************************************************************
386 * _mbstrlen(MSVCRT.@)
388 int _mbstrlen(const unsigned char *str)
390 if(MSVCRT___mb_cur_max > 1)
392 int len = 0;
393 while(*str)
395 str += MSVCRT_isleadbyte(*str) ? 2 : 1;
396 len++;
398 return len;
400 return strlen(str); /* ASCII CP */
403 /*********************************************************************
404 * _mbsncpy(MSVCRT.@)
406 char *_mbsncpy(char *dst, const char *src, unsigned int len)
408 if(!len)
409 return dst;
410 if(MSVCRT___mb_cur_max > 1)
412 char *ret = dst;
413 while(src[0] && src[1] && len--)
415 *dst++ = *src++;
416 *dst++ = *src++;
418 if(len--)
420 *dst++ = *src++; /* Last char or '\0' */
421 while(len--)
422 *dst++ = '\0';
424 return ret;
426 return strncpy(dst, src, len); /* ASCII CP */
429 /*********************************************************************
430 * _mbschr(MSVCRT.@)
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)
438 unsigned int next;
439 while((next = _mbsnextc(str)))
441 if(next == c)
442 return (char *)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)
455 int ret = 0;
457 if(MSVCRT___mb_cur_max > 1)
459 while(*str && len-- > 0)
461 if(MSVCRT_isleadbyte(*str))
463 str++;
464 len--;
466 ret++;
467 str++;
469 return ret;
471 return min(strlen(str), len); /* ASCII CP */
475 /*********************************************************************
476 * _mbsncat(MSVCRT.@)
478 unsigned char* _mbsncat(unsigned char* dst, const unsigned char* src, MSVCRT_size_t len)
480 if(MSVCRT___mb_cur_max > 1)
482 char *res = dst;
483 dst += _mbslen(dst);
484 while(*src && len--)
486 *dst = *src;
487 if(MSVCRT_isleadbyte(*src))
488 *++dst = *++src;
489 dst++;
490 src++;
492 *dst++ = '\0';
493 return res;
495 return strncat(dst, src, len); /* ASCII CP */