- Made sure that the files that contains the declarations
[wine] / dlls / msvcrt / mbcs.c
1 /*
2  * msvcrt.dll mbcs functions
3  *
4  * Copyright 1999 Alexandre Julliard
5  * Copyright 2000 Jon Griffths
6  *
7  * FIXME
8  * Not currently binary compatible with win32. MSVCRT_mbctype must be
9  * populated correctly and the ismb* functions should reference it.
10  */
11
12 #include "msvcrt.h"
13
14 #include "msvcrt/stdlib.h"
15 #include "msvcrt/string.h"
16
17
18 DEFAULT_DEBUG_CHANNEL(msvcrt);
19
20 unsigned char MSVCRT_mbctype[257];
21 int MSVCRT___mb_cur_max = 1;
22
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;
27
28
29 /*********************************************************************
30  *              __p__mbctype (MSVCRT.@)
31  */
32 unsigned char *__p__mbctype(void)
33 {
34   return MSVCRT_mbctype;
35 }
36
37 /*********************************************************************
38  *              __p___mb_cur_max(MSVCRT.@)
39  */
40 int *__p___mb_cur_max(void)
41 {
42   return &MSVCRT___mb_cur_max;
43 }
44
45 /*********************************************************************
46  *              _mbsnextc(MSVCRT.@)
47  */
48 unsigned int _mbsnextc(const unsigned char *str)
49 {
50   if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
51     return *str << 8 | str[1];
52   return *str; /* ASCII CP or SB char */
53 }
54
55 /*********************************************************************
56  *              _mbscmp(MSVCRT.@)
57  */
58 int _mbscmp(const char *str, const char *cmp)
59 {
60   if(MSVCRT___mb_cur_max > 1)
61   {
62     unsigned int strc, cmpc;
63     do {
64       if(!*str)
65         return *cmp ? -1 : 0;
66       if(!*cmp)
67         return 1;
68       strc = _mbsnextc(str);
69       cmpc = _mbsnextc(cmp);
70       if(strc != cmpc)
71         return strc < cmpc ? -1 : 1;
72       str +=(strc > 255) ? 2 : 1;
73       cmp +=(strc > 255) ? 2 : 1; /* equal, use same increment */
74     } while(1);
75   }
76   return strcmp(str, cmp); /* ASCII CP */
77 }
78
79 /*********************************************************************
80  *              _mbsicmp(MSVCRT.@)
81  */
82 int _mbsicmp(const char *str, const char *cmp)
83 {
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 */
88 }
89
90 /*********************************************************************
91  *              _mbsncmp    (MSVCRT.@)
92  */
93 int _mbsncmp(const char *str, const char *cmp, unsigned int len)
94 {
95   if(!len)
96     return 0;
97
98   if(MSVCRT___mb_cur_max > 1)
99   {
100     unsigned int strc, cmpc;
101     while(len--)
102     {
103       if(!*str)
104         return *cmp ? -1 : 0;
105       if(!*cmp)
106         return 1;
107       strc = _mbsnextc(str);
108       cmpc = _mbsnextc(cmp);
109       if(strc != cmpc)
110         return strc < cmpc ? -1 : 1;
111       str +=(strc > 255) ? 2 : 1;
112       cmp +=(strc > 255) ? 2 : 1; /* Equal, use same increment */
113     }
114     return 0; /* Matched len chars */
115   }
116   return strncmp(str, cmp, len); /* ASCII CP */
117 }
118
119 /*********************************************************************
120  *                  _mbsnicmp(MSVCRT.@)
121  *
122  * Compare two multibyte strings case insensitively to 'len' characters.
123  */
124 int _mbsnicmp(const char *str, const char *cmp, unsigned int len)
125 {
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 */
130 }
131
132 /*********************************************************************
133  *              _mbsinc(MSVCRT.@)
134  */
135 char *_mbsinc(const unsigned char *str)
136 {
137   if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
138     return (char *)str + 2; /* MB char */
139
140   return (char *)str + 1; /* ASCII CP or SB char */
141 }
142
143 /*********************************************************************
144  *              _mbsninc(MSVCRT.@)
145  */
146 char *_mbsninc(const char *str, unsigned int num)
147 {
148   if(!str || num < 1)
149     return NULL;
150   if(MSVCRT___mb_cur_max > 1)
151   {
152     while(num--)
153       str = _mbsinc(str);
154     return (char *)str;
155   }
156   return (char *)str + num; /* ASCII CP */
157 }
158
159 /*********************************************************************
160  *              _mbslen(MSVCRT.@)
161  */
162 int _mbslen(const unsigned char *str)
163 {
164   if(MSVCRT___mb_cur_max > 1)
165   {
166     int len = 0;
167     while(*str)
168     {
169       str += MSVCRT_isleadbyte(*str) ? 2 : 1;
170       len++;
171     }
172     return len;
173   }
174   return strlen(str); /* ASCII CP */
175 }
176
177 /*********************************************************************
178  *              _mbsrchr(MSVCRT.@)
179  */
180 char *_mbsrchr(const char *s,unsigned int x)
181 {
182   /* FIXME: handle multibyte strings */
183   return strrchr(s,x);
184 }
185
186 /*********************************************************************
187  *              mbtowc(MSVCRT.@)
188  */
189 int MSVCRT_mbtowc(WCHAR *dst, const char *str, unsigned int n)
190 {
191   if(n <= 0 || !str)
192     return 0;
193   if(!MultiByteToWideChar(CP_ACP, 0, str, n, dst, 1))
194     return 0;
195   /* return the number of bytes from src that have been used */
196   if(!*str)
197     return 0;
198   if(n >= 2 && MSVCRT_isleadbyte(*str) && str[1])
199     return 2;
200   return 1;
201 }
202
203 /*********************************************************************
204  *              _mbccpy(MSVCRT.@)
205  */
206 void _mbccpy(char *dest, const unsigned char *src)
207 {
208   *dest++ = *src;
209   if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*src))
210     *dest = *++src; /* MB char */
211 }
212
213 /*********************************************************************
214  *              _mbbtombc(MSVCRT.@)
215  */
216 unsigned int _mbbtombc(unsigned int c)
217 {
218   if(MSVCRT___mb_cur_max > 1 &&
219      ((c >= 0x20 && c <=0x7e) ||(c >= 0xa1 && c <= 0xdf)))
220   {
221     /* FIXME: I can't get this function to return anything
222      * different to what I pass it...
223      */
224   }
225   return c;  /* ASCII CP or no MB char */
226 }
227
228 /*********************************************************************
229  *              _mbclen(MSVCRT.@)
230  */
231 unsigned int _mbclen(const unsigned char *str)
232 {
233   return MSVCRT_isleadbyte(*str) ? 2 : 1;
234 }
235
236 /*********************************************************************
237  *              _ismbbkana(MSVCRT.@)
238  */
239 int _ismbbkana(unsigned int c)
240 {
241   /* FIXME: use lc_ctype when supported, not lc_all */
242   if(MSVCRT_current_lc_all_cp == 932)
243   {
244     /* Japanese/Katakana, CP 932 */
245     return (c >= 0xa1 && c <= 0xdf);
246   }
247   return 0;
248 }
249
250 /*********************************************************************
251  *              _ismbchira(MSVCRT.@)
252  */
253 int _ismbchira(unsigned int c)
254 {
255   /* FIXME: use lc_ctype when supported, not lc_all */
256   if(MSVCRT_current_lc_all_cp == 932)
257   {
258     /* Japanese/Hiragana, CP 932 */
259     return (c >= 0x829f && c <= 0x82f1);
260   }
261   return 0;
262 }
263
264 /*********************************************************************
265  *              _ismbckata(MSVCRT.@)
266  */
267 int _ismbckata(unsigned int c)
268 {
269   /* FIXME: use lc_ctype when supported, not lc_all */
270   if(MSVCRT_current_lc_all_cp == 932)
271   {
272     if(c < 256)
273       return _ismbbkana(c);
274     /* Japanese/Katakana, CP 932 */
275     return (c >= 0x8340 && c <= 0x8396 && c != 0x837f);
276   }
277   return 0;
278 }
279
280 /*********************************************************************
281  *              _ismbblead(MSVCRT.@)
282  */
283 int _ismbblead(unsigned int c)
284 {
285   /* FIXME: should reference MSVCRT_mbctype */
286   return MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(c);
287 }
288
289
290 /*********************************************************************
291  *              _ismbbtrail(MSVCRT.@)
292  */
293 int _ismbbtrail(unsigned int c)
294 {
295   /* FIXME: should reference MSVCRT_mbctype */
296   return !_ismbblead(c);
297 }
298
299 /*********************************************************************
300  *              _ismbslead(MSVCRT.@)
301  */
302 int _ismbslead(const unsigned char *start, const unsigned char *str)
303 {
304   /* Lead bytes can also be trail bytes if caller messed up
305    * iterating through the string...
306    */
307   if(MSVCRT___mb_cur_max > 1)
308   {
309     while(start < str)
310       start += MSVCRT_isleadbyte(*str) ? 2 : 1;
311
312     if(start == str)
313       return MSVCRT_isleadbyte(*str);
314   }
315   return 0; /* Must have been a trail, we skipped it */
316 }
317
318 /*********************************************************************
319  *              _ismbstrail(MSVCRT.@)
320  */
321 int _ismbstrail(const char *start, const unsigned char *str)
322 {
323   /* Must not be a lead, and must be preceeded by one */
324   return !_ismbslead(start, str) && MSVCRT_isleadbyte(str[-1]);
325 }
326
327 /*********************************************************************
328  *              _mbsdec(MSVCRT.@)
329  */
330 char *_mbsdec(const char *start, const char *cur)
331 {
332   if(MSVCRT___mb_cur_max > 1)
333     return (char *)(_ismbstrail(start,cur-1) ? cur - 2 : cur -1);
334
335   return (char *)cur - 1; /* ASCII CP or SB char */
336 }
337
338 /*********************************************************************
339  *              _mbsset(MSVCRT.@)
340  */
341 char *_mbsset(char *str, unsigned int c)
342 {
343   char *ret = str;
344
345   if(MSVCRT___mb_cur_max == 1 || c < 256)
346     return _strset(str, c); /* ASCII CP or SB char */
347
348   c &= 0xffff; /* Strip high bits */
349
350   while(str[0] && str[1])
351   {
352     *str++ = c >> 8;
353     *str++ = c & 0xff;
354   }
355   if(str[0])
356     str[0] = '\0'; /* FIXME: OK to shorten? */
357
358   return ret;
359 }
360
361 /*********************************************************************
362  *              _mbsnset(MSVCRT.@)
363  */
364 char *_mbsnset(char *str, unsigned int c, unsigned int len)
365 {
366   char *ret = str;
367
368   if(!len)
369     return ret;
370
371   if(MSVCRT___mb_cur_max == 1 || c < 256)
372     return _strnset(str, c, len); /* ASCII CP or SB char */
373
374   c &= 0xffff; /* Strip high bits */
375
376   while(str[0] && str[1] && len--)
377   {
378     *str++ = c >> 8;
379     *str++ = c & 0xff;
380   }
381   if(len && str[0])
382     str[0] = '\0'; /* FIXME: OK to shorten? */
383
384   return ret;
385 }
386
387 /*********************************************************************
388  *              _mbstrlen(MSVCRT.@)
389  */
390 MSVCRT_size_t _mbstrlen(const char *str)
391 {
392   if(MSVCRT___mb_cur_max > 1)
393   {
394     int len = 0;
395     while(*str)
396     {
397       str += MSVCRT_isleadbyte(*str) ? 2 : 1;
398       len++;
399     }
400     return len;
401   }
402   return strlen(str); /* ASCII CP */
403 }
404
405 /*********************************************************************
406  *              _mbsncpy(MSVCRT.@)
407  */
408 char *_mbsncpy(char *dst, const char *src, unsigned int len)
409 {
410   if(!len)
411     return dst;
412   if(MSVCRT___mb_cur_max > 1)
413   {
414     char *ret = dst;
415     while(src[0] && src[1] && len--)
416     {
417       *dst++ = *src++;
418       *dst++ = *src++;
419     }
420     if(len--)
421     {
422       *dst++ = *src++; /* Last char or '\0' */
423       while(len--)
424         *dst++ = '\0';
425     }
426     return ret;
427   }
428   return strncpy(dst, src, len); /* ASCII CP */
429 }
430
431 /*********************************************************************
432  *              _mbschr(MSVCRT.@)
433  *
434  * Find a multibyte character in a multibyte string.
435  */
436 unsigned char* _mbschr(const unsigned char* str, unsigned int c)
437 {
438   if(MSVCRT___mb_cur_max > 1)
439   {
440     unsigned int next;
441     while((next = _mbsnextc(str)))
442     {
443       if(next == c)
444         return (char *)str;
445       str += next > 255 ? 2 : 1;
446     }
447     return c ? NULL :(char *)str;
448   }
449   return strchr(str, c); /* ASCII CP */
450 }
451
452 /*********************************************************************
453  *              _mbsnccnt(MSVCRT.@)
454  */
455 unsigned int _mbsnccnt(const unsigned char *str, unsigned int len)
456 {
457   int ret = 0;
458
459   if(MSVCRT___mb_cur_max > 1)
460   {
461     while(*str && len-- > 0)
462     {
463       if(MSVCRT_isleadbyte(*str))
464       {
465         str++;
466         len--;
467       }
468       ret++;
469       str++;
470     }
471     return ret;
472   }
473   return min(strlen(str), len); /* ASCII CP */
474 }
475
476
477 /*********************************************************************
478  *              _mbsncat(MSVCRT.@)
479  */
480 unsigned char* _mbsncat(unsigned char* dst, const unsigned char* src, MSVCRT_size_t len)
481 {
482   if(MSVCRT___mb_cur_max > 1)
483   {
484     char *res = dst;
485     dst += _mbslen(dst);
486     while(*src && len--)
487     {
488       *dst = *src;
489       if(MSVCRT_isleadbyte(*src))
490         *++dst = *++src;
491       dst++;
492       src++;
493     }
494     *dst++ = '\0';
495     return res;
496   }
497   return strncat(dst, src, len); /* ASCII CP */
498 }
499
500
501 /*********************************************************************
502  *              _ismbcdigit(MSVCRT.@)
503  */
504 int _ismbcdigit( unsigned int ch)
505 {
506   if (ch <0x100)
507     return isdigit(ch);
508   else
509     {
510       FIXME("Handle MBC chars\n");
511       return 0;
512     }
513 }
514
515
516 /*********************************************************************
517  *              _mbsnbcmp(MSVCRT.@)
518  */
519 int _mbsnbcmp( const unsigned char *str,const unsigned char *cmp, MSVCRT_size_t len )
520 {
521   if (!len)
522     return 0;
523   if(MSVCRT___mb_cur_max > 1)
524     {
525       FIXME("%s %s %d\n",str,cmp,len);
526       return 0;
527     }
528   return strncmp(str,cmp,len);
529 }
530
531
532 /*********************************************************************
533  *              _mbslwr(MSVCRT.@)
534  */
535 unsigned char * _mbslwr(  unsigned char *string    )
536 {
537   unsigned char *p;
538
539   if(MSVCRT___mb_cur_max > 1)
540     {
541       FIXME("%s\n",string);
542       return string;
543     }
544   p = string;
545   while (*p)
546     {
547       *p= tolower(*p);
548       p++;
549     }
550   return string;
551 }
552
553
554 /*********************************************************************
555  *              _mbsnbcpy(MSVCRT.@)
556  */
557 unsigned char * _mbsnbcpy(unsigned char *dest,const unsigned char *src,MSVCRT_size_t n)
558 {
559   if(MSVCRT___mb_cur_max > 1)
560     {
561       FIXME("%s %d\n",src,n);
562       return dest;
563     }
564   return strncpy(dest, src, n);
565 }
566
567
568 /*********************************************************************
569  *              _mbsspn (MSVCRT.@)
570  */
571 MSVCRT_size_t _mbsspn(const unsigned char *string, const unsigned char *set)
572 {
573   const unsigned char *p, *q;
574
575   for (p = string; *p; p++)
576     {
577       if (MSVCRT_isleadbyte(*p))
578         {
579           for (q = set; *q; q++)
580             {
581               if (!q[1])
582                 break;
583               if ((*p == *q) &&  (p[1] == q[1]))
584                 break;
585               q++;
586             }
587           if (*++p == '\0')
588             break;
589         }
590       else
591         for (q = set; *q; q++)
592           if (*p == *q)
593             break;
594     }
595   return p - string;
596 }
597
598
599 /*********************************************************************
600  *              _ismbcspace (MSVCRT.@)
601  */
602 int _ismbcspace( unsigned int c)
603 {
604
605   if (c <0x100)
606     return isspace(c);
607   FIXME("%c\n",c);
608   return 0;
609 }