Correct tests involved with processing the LVIF_DI_SETITEM flag.
[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/mbctype.h"
15 #include "msvcrt/mbstring.h"
16 #include "msvcrt/stdlib.h"
17 #include "msvcrt/string.h"
18 #include "msvcrt/wctype.h"
19
20
21 #include "wine/debug.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
24
25 unsigned char MSVCRT_mbctype[257];
26 int MSVCRT___mb_cur_max = 1;
27
28 /*********************************************************************
29  *              __p__mbctype (MSVCRT.@)
30  */
31 unsigned char* __p__mbctype(void)
32 {
33   return MSVCRT_mbctype;
34 }
35
36 /*********************************************************************
37  *              __p___mb_cur_max(MSVCRT.@)
38  */
39 int* __p___mb_cur_max(void)
40 {
41   return &MSVCRT___mb_cur_max;
42 }
43
44 /*********************************************************************
45  *              _mbsnextc(MSVCRT.@)
46  */
47 unsigned int _mbsnextc(const unsigned char* str)
48 {
49   if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
50     return *str << 8 | str[1];
51   return *str; /* ASCII CP or SB char */
52 }
53
54 /*********************************************************************
55  *              _mbctolower(MSVCRT.@)
56  */
57 unsigned int _mbctolower(unsigned int c)
58 {
59     if (MSVCRT_isleadbyte(c))
60     {
61       FIXME("Handle MBC chars\n");
62       return c;
63     }
64     return tolower(c); /* ASCII CP or SB char */
65 }
66
67 /*********************************************************************
68  *              _mbctoupper(MSVCRT.@)
69  */
70 unsigned int _mbctoupper(unsigned int c)
71 {
72     if (MSVCRT_isleadbyte(c))
73     {
74       FIXME("Handle MBC chars\n");
75       return c;
76     }
77     return toupper(c); /* ASCII CP or SB char */
78 }
79
80 /*********************************************************************
81  *              _mbsdec(MSVCRT.@)
82  */
83 unsigned char* _mbsdec(const unsigned char* start, const unsigned char* cur)
84 {
85   if(MSVCRT___mb_cur_max > 1)
86     return (char *)(_ismbstrail(start,cur-1) ? cur - 2 : cur -1);
87
88   return (char *)cur - 1; /* ASCII CP or SB char */
89 }
90
91 /*********************************************************************
92  *              _mbsinc(MSVCRT.@)
93  */
94 unsigned char* _mbsinc(const unsigned char* str)
95 {
96   if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
97     return (unsigned char*)str + 2; /* MB char */
98
99   return (unsigned char*)str + 1; /* ASCII CP or SB char */
100 }
101
102 /*********************************************************************
103  *              _mbsninc(MSVCRT.@)
104  */
105 unsigned char* _mbsninc(const unsigned char* str, MSVCRT_size_t num)
106 {
107   if(!str || num < 1)
108     return NULL;
109   if(MSVCRT___mb_cur_max > 1)
110   {
111     while(num--)
112       str = _mbsinc(str);
113     return (unsigned char*)str;
114   }
115   return (unsigned char*)str + num; /* ASCII CP */
116 }
117
118 /*********************************************************************
119  *              _mbclen(MSVCRT.@)
120  */
121 unsigned int _mbclen(const unsigned char* str)
122 {
123   return MSVCRT_isleadbyte(*str) ? 2 : 1;
124 }
125
126 /*********************************************************************
127  *              mblen(MSVCRT.@)
128  */
129 int MSVCRT_mblen(const char* str, MSVCRT_size_t size)
130 {
131   if (str && *str && size)
132   {
133     if(MSVCRT___mb_cur_max == 1)
134       return 1; /* ASCII CP */
135
136     return !MSVCRT_isleadbyte(*str) ? 1 : (size>1 ? 2 : -1);
137   }
138   return 0;
139 }
140
141 /*********************************************************************
142  *              _mbslen(MSVCRT.@)
143  */
144 MSVCRT_size_t _mbslen(const unsigned char* str)
145 {
146   if(MSVCRT___mb_cur_max > 1)
147   {
148     MSVCRT_size_t len = 0;
149     while(*str)
150     {
151       str += MSVCRT_isleadbyte(*str) ? 2 : 1;
152       len++;
153     }
154     return len;
155   }
156   return strlen(str); /* ASCII CP */
157 }
158
159 /*********************************************************************
160  *              _mbstrlen(MSVCRT.@)
161  */
162 MSVCRT_size_t _mbstrlen(const char* str)
163 {
164   if(MSVCRT___mb_cur_max > 1)
165   {
166     MSVCRT_size_t len = 0;
167     while(*str)
168     {
169       /* FIXME: According to the documentation we are supposed to test for 
170        * multi-byte character validity. Whatever that means
171        */
172       str += MSVCRT_isleadbyte(*str) ? 2 : 1;
173       len++;
174     }
175     return len;
176   }
177   return strlen(str); /* ASCII CP */
178 }
179
180 /*********************************************************************
181  *              _mbccpy(MSVCRT.@)
182  */
183 void _mbccpy(unsigned char* dest, const unsigned char* src)
184 {
185   *dest++ = *src;
186   if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*src))
187     *dest = *++src; /* MB char */
188   else
189     ERR("failure.. is this ok?\n");
190 }
191
192 /*********************************************************************
193  *              _mbsncpy(MSVCRT.@)
194  */
195 unsigned char* _mbsncpy(unsigned char* dst, const unsigned char* src, MSVCRT_size_t n)
196 {
197   if(!n)
198     return dst;
199   if(MSVCRT___mb_cur_max > 1)
200   {
201     unsigned char* ret = dst;
202     while (*src && n--)
203     {
204       *dst++ = *src;
205       if (MSVCRT_isleadbyte(*src++))
206           *dst++ = *src++;
207     }
208     while(n--)
209       *dst++ = '\0';
210     return ret;
211   }
212   return strncpy(dst, src, n); /* ASCII CP */
213 }
214
215 /*********************************************************************
216  *              _mbsnbcpy(MSVCRT.@)
217  */
218 unsigned char* _mbsnbcpy(unsigned char* dst, const unsigned char* src, MSVCRT_size_t n)
219 {
220   if(!n)
221     return dst;
222   if(MSVCRT___mb_cur_max > 1)
223   {
224     unsigned char* ret = dst;
225     while (*src && (n-- > 1))
226     {
227       *dst++ = *src;
228       if (MSVCRT_isleadbyte(*src++))
229       {
230         *dst++ = *src++;
231         n--;
232       }
233     }
234     if (*src && n && !MSVCRT_isleadbyte(*src))
235     {
236       /* If the last character is a multi-byte character then 
237        * we cannot copy it since we have only one byte left
238        */
239       *dst++ = *src;
240       n--;
241     }
242     while (n--)
243       *dst++ = '\0';
244     return ret;
245   }
246   return strncpy(dst, src, n); /* ASCII CP */
247 }
248
249 /*********************************************************************
250  *              _mbscmp(MSVCRT.@)
251  */
252 int _mbscmp(const unsigned char* str, const unsigned char* cmp)
253 {
254   if(MSVCRT___mb_cur_max > 1)
255   {
256     unsigned int strc, cmpc;
257     do {
258       if(!*str)
259         return *cmp ? -1 : 0;
260       if(!*cmp)
261         return 1;
262       strc = _mbsnextc(str);
263       cmpc = _mbsnextc(cmp);
264       if(strc != cmpc)
265         return strc < cmpc ? -1 : 1;
266       str +=(strc > 255) ? 2 : 1;
267       cmp +=(strc > 255) ? 2 : 1; /* equal, use same increment */
268     } while(1);
269   }
270   return strcmp(str, cmp); /* ASCII CP */
271 }
272
273 /*********************************************************************
274  *              _mbsicmp(MSVCRT.@)
275  */
276 int _mbsicmp(const unsigned char* str, const unsigned char* cmp)
277 {
278   if(MSVCRT___mb_cur_max > 1)
279   {
280     unsigned int strc, cmpc;
281     do {
282       if(!*str)
283         return *cmp ? -1 : 0;
284       if(!*cmp)
285         return 1;
286       strc = _mbctolower(_mbsnextc(str));
287       cmpc = _mbctolower(_mbsnextc(cmp));
288       if(strc != cmpc)
289         return strc < cmpc ? -1 : 1;
290       str +=(strc > 255) ? 2 : 1;
291       cmp +=(strc > 255) ? 2 : 1; /* equal, use same increment */
292     } while(1);
293   }
294   return strcasecmp(str, cmp); /* ASCII CP */
295 }
296
297 /*********************************************************************
298  *              _mbsncmp(MSVCRT.@)
299  */
300 int _mbsncmp(const unsigned char* str, const unsigned char* cmp, MSVCRT_size_t len)
301 {
302   if(!len)
303     return 0;
304
305   if(MSVCRT___mb_cur_max > 1)
306   {
307     unsigned int strc, cmpc;
308     while(len--)
309     {
310       int inc;
311       if(!*str)
312         return *cmp ? -1 : 0;
313       if(!*cmp)
314         return 1;
315       strc = _mbsnextc(str);
316       cmpc = _mbsnextc(cmp);
317       if(strc != cmpc)
318         return strc < cmpc ? -1 : 1;
319       inc=(strc > 255) ? 2 : 1; /* Equal, use same increment */
320       str += inc;
321       cmp += inc;
322     }
323     return 0; /* Matched len chars */
324   }
325   return strncmp(str, cmp, len); /* ASCII CP */
326 }
327
328 /*********************************************************************
329  *              _mbsnbcmp(MSVCRT.@)
330  */
331 int _mbsnbcmp(const unsigned char* str, const unsigned char* cmp, MSVCRT_size_t len)
332 {
333   if (!len)
334     return 0;
335   if(MSVCRT___mb_cur_max > 1)
336   {
337     unsigned int strc, cmpc;
338     while (len)
339     {
340       int clen;
341       if(!*str)
342         return *cmp ? -1 : 0;
343       if(!*cmp)
344         return 1;
345       if (MSVCRT_isleadbyte(*str))
346       {
347         strc=(len>=2)?_mbsnextc(str):0;
348         clen=2;
349       }
350       else
351       {
352         strc=*str;
353         clen=1;
354       }
355       if (MSVCRT_isleadbyte(*cmp))
356         cmpc=(len>=2)?_mbsnextc(cmp):0;
357       else
358         cmpc=*str;
359       if(strc != cmpc)
360         return strc < cmpc ? -1 : 1;
361       len -= clen;
362       str += clen;
363       cmp += clen;
364     }
365     return 0; /* Matched len chars */
366       FIXME("%s %s %d\n",str,cmp,len);
367   }
368   return strncmp(str,cmp,len);
369 }
370
371 /*********************************************************************
372  *              _mbsnicmp(MSVCRT.@)
373  *
374  * Compare two multibyte strings case insensitively to 'len' characters.
375  */
376 int _mbsnicmp(const unsigned char* str, const unsigned char* cmp, MSVCRT_size_t len)
377 {
378   /* FIXME: No tolower() for mb strings yet */
379   if(MSVCRT___mb_cur_max > 1)
380   {
381     unsigned int strc, cmpc;
382     while(len--)
383     {
384       if(!*str)
385         return *cmp ? -1 : 0;
386       if(!*cmp)
387         return 1;
388       strc = _mbctolower(_mbsnextc(str));
389       cmpc = _mbctolower(_mbsnextc(cmp));
390       if(strc != cmpc)
391         return strc < cmpc ? -1 : 1;
392       str +=(strc > 255) ? 2 : 1;
393       cmp +=(strc > 255) ? 2 : 1; /* Equal, use same increment */
394     }
395     return 0; /* Matched len chars */
396   }
397   return strncasecmp(str, cmp, len); /* ASCII CP */
398 }
399
400 /*********************************************************************
401  *              _mbschr(MSVCRT.@)
402  *
403  * Find a multibyte character in a multibyte string.
404  */
405 unsigned char* _mbschr(const unsigned char* s, unsigned int x)
406 {
407   if(MSVCRT___mb_cur_max > 1)
408   {
409     unsigned int c;
410     while (1)
411     {
412       c = _mbsnextc(s);
413       if (c == x)
414         return (unsigned char*)s;
415       if (!c)
416         return NULL;
417       s += c > 255 ? 2 : 1;
418     }
419   }
420   return strchr(s, x); /* ASCII CP */
421 }
422
423 /*********************************************************************
424  *              _mbsrchr(MSVCRT.@)
425  */
426 unsigned char* _mbsrchr(const unsigned char* s, unsigned int x)
427 {
428   if(MSVCRT___mb_cur_max > 1)
429   {
430     unsigned int c;
431     unsigned char* match=NULL;
432     if(!s)
433       return NULL;
434     while (1) {
435       c = _mbsnextc(s);
436       if (c == x)
437         match=(unsigned char*)s;
438       if (!c)
439         return match;
440       s +=(c > 255) ? 2 : 1;
441     }
442   }
443   return strrchr(s,x);
444 }
445
446 /*********************************************************************
447  *              mbtowc(MSVCRT.@)
448  */
449 int MSVCRT_mbtowc(WCHAR *dst, const char* str, MSVCRT_size_t n)
450 {
451   if(n <= 0 || !str)
452     return 0;
453   if(!MultiByteToWideChar(CP_ACP, 0, str, n, dst, 1))
454     return 0;
455   /* return the number of bytes from src that have been used */
456   if(!*str)
457     return 0;
458   if(n >= 2 && MSVCRT_isleadbyte(*str) && str[1])
459     return 2;
460   return 1;
461 }
462
463 /*********************************************************************
464  *              _mbbtombc(MSVCRT.@)
465  */
466 unsigned int _mbbtombc(unsigned int c)
467 {
468   if(MSVCRT___mb_cur_max > 1 &&
469      ((c >= 0x20 && c <=0x7e) ||(c >= 0xa1 && c <= 0xdf)))
470   {
471     /* FIXME: I can't get this function to return anything
472      * different to what I pass it...
473      */
474   }
475   return c;  /* ASCII CP or no MB char */
476 }
477
478 /*********************************************************************
479  *              _ismbbkana(MSVCRT.@)
480  */
481 int _ismbbkana(unsigned int c)
482 {
483   /* FIXME: use lc_ctype when supported, not lc_all */
484   if(MSVCRT_current_lc_all_cp == 932)
485   {
486     /* Japanese/Katakana, CP 932 */
487     return (c >= 0xa1 && c <= 0xdf);
488   }
489   return 0;
490 }
491
492 /*********************************************************************
493  *              _ismbcdigit(MSVCRT.@)
494  */
495 int _ismbcdigit(unsigned int ch)
496 {
497   if (ch <0x100)
498     return isdigit(ch);
499   else
500     {
501       FIXME("Handle MBC chars\n");
502       return 0;
503     }
504 }
505
506 /*********************************************************************
507  *              _ismbcspace (MSVCRT.@)
508  */
509 int _ismbcspace(unsigned int c)
510 {
511
512   if (c<0x100)
513     return isspace(c);
514   FIXME("%c\n",c);
515   return 0;
516 }
517
518 /*********************************************************************
519  *              _ismbchira(MSVCRT.@)
520  */
521 int _ismbchira(unsigned int c)
522 {
523   /* FIXME: use lc_ctype when supported, not lc_all */
524   if(MSVCRT_current_lc_all_cp == 932)
525   {
526     /* Japanese/Hiragana, CP 932 */
527     return (c >= 0x829f && c <= 0x82f1);
528   }
529   return 0;
530 }
531
532 /*********************************************************************
533  *              _ismbckata(MSVCRT.@)
534  */
535 int _ismbckata(unsigned int c)
536 {
537   /* FIXME: use lc_ctype when supported, not lc_all */
538   if(MSVCRT_current_lc_all_cp == 932)
539   {
540     if(c < 256)
541       return _ismbbkana(c);
542     /* Japanese/Katakana, CP 932 */
543     return (c >= 0x8340 && c <= 0x8396 && c != 0x837f);
544   }
545   return 0;
546 }
547
548 /*********************************************************************
549  *              _ismbblead(MSVCRT.@)
550  */
551 int _ismbblead(unsigned int c)
552 {
553   /* FIXME: should reference MSVCRT_mbctype */
554   return MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(c);
555 }
556
557
558 /*********************************************************************
559  *              _ismbbtrail(MSVCRT.@)
560  */
561 int _ismbbtrail(unsigned int c)
562 {
563   /* FIXME: should reference MSVCRT_mbctype */
564   return !_ismbblead(c);
565 }
566
567 /*********************************************************************
568  *              _ismbslead(MSVCRT.@)
569  */
570 int _ismbslead(const unsigned char* start, const unsigned char* str)
571 {
572   /* Lead bytes can also be trail bytes if caller messed up
573    * iterating through the string...
574    */
575   if(MSVCRT___mb_cur_max > 1)
576   {
577     while(start < str)
578       start += MSVCRT_isleadbyte(*str) ? 2 : 1;
579
580     if(start == str)
581       return MSVCRT_isleadbyte(*str);
582   }
583   return 0; /* Must have been a trail, we skipped it */
584 }
585
586 /*********************************************************************
587  *              _ismbstrail(MSVCRT.@)
588  */
589 int _ismbstrail(const unsigned char* start, const unsigned char* str)
590 {
591   /* Must not be a lead, and must be preceeded by one */
592   return !_ismbslead(start, str) && MSVCRT_isleadbyte(str[-1]);
593 }
594
595 /*********************************************************************
596  *              _mbsset(MSVCRT.@)
597  */
598 unsigned char* _mbsset(unsigned char* str, unsigned int c)
599 {
600   unsigned char* ret = str;
601
602   if(MSVCRT___mb_cur_max == 1 || c < 256)
603     return _strset(str, c); /* ASCII CP or SB char */
604
605   c &= 0xffff; /* Strip high bits */
606
607   while(str[0] && str[1])
608   {
609     *str++ = c >> 8;
610     *str++ = c & 0xff;
611   }
612   if(str[0])
613     str[0] = '\0'; /* FIXME: OK to shorten? */
614
615   return ret;
616 }
617
618 /*********************************************************************
619  *              _mbsnset(MSVCRT.@)
620  */
621 unsigned char* _mbsnset(unsigned char* str, unsigned int c, MSVCRT_size_t len)
622 {
623   unsigned char *ret = str;
624
625   if(!len)
626     return ret;
627
628   if(MSVCRT___mb_cur_max == 1 || c < 256)
629     return _strnset(str, c, len); /* ASCII CP or SB char */
630
631   c &= 0xffff; /* Strip high bits */
632
633   while(str[0] && str[1] && len--)
634   {
635     *str++ = c >> 8;
636     *str++ = c & 0xff;
637   }
638   if(len && str[0])
639     str[0] = '\0'; /* FIXME: OK to shorten? */
640
641   return ret;
642 }
643
644 /*********************************************************************
645  *              _mbsnccnt(MSVCRT.@)
646  * 'c' is for 'character'.
647  */
648 MSVCRT_size_t _mbsnccnt(const unsigned char* str, MSVCRT_size_t len)
649 {
650   MSVCRT_size_t ret;
651   if(MSVCRT___mb_cur_max > 1)
652   {
653     ret=0;
654     while(*str && len-- > 0)
655     {
656       if(MSVCRT_isleadbyte(*str))
657       {
658         if (!len)
659           break;
660         len--;
661         str++;
662       }
663       str++;
664       ret++;
665     }
666     return ret;
667   }
668   ret=strlen(str);
669   return min(ret, len); /* ASCII CP */
670 }
671
672 /*********************************************************************
673  *              _mbsnbcnt(MSVCRT.@)
674  * 'b' is for byte count.
675  */
676 MSVCRT_size_t _mbsnbcnt(const unsigned char* str, MSVCRT_size_t len)
677 {
678   MSVCRT_size_t ret;
679   if(MSVCRT___mb_cur_max > 1)
680   {
681     const unsigned char* xstr = str;
682     while(*xstr && len-- > 0)
683     {
684       if (MSVCRT_isleadbyte(*xstr++))
685         xstr++;
686     }
687     return xstr-str;
688   }
689   ret=strlen(str);
690   return min(ret, len); /* ASCII CP */
691 }
692
693
694 /*********************************************************************
695  *              _mbsncat(MSVCRT.@)
696  */
697 unsigned char* _mbsncat(unsigned char* dst, const unsigned char* src, MSVCRT_size_t len)
698 {
699   if(MSVCRT___mb_cur_max > 1)
700   {
701     char *res = dst;
702     while (*dst)
703     {
704       if (MSVCRT_isleadbyte(*dst++))
705         dst++;
706     }
707     while (*src && len--)
708     {
709       *dst++ = *src;
710       if(MSVCRT_isleadbyte(*src++))
711         *dst++ = *src++;
712     }
713     *dst = '\0';
714     return res;
715   }
716   return strncat(dst, src, len); /* ASCII CP */
717 }
718
719
720 /*********************************************************************
721  *              _mbslwr(MSVCRT.@)
722  */
723 unsigned char* _mbslwr(unsigned char* s)
724 {
725   if (!s)
726     return NULL;
727   if (MSVCRT___mb_cur_max > 1)
728   {
729     unsigned int c;
730     unsigned char* p=s;
731     while (*s)
732     {
733       c = _mbctolower(_mbsnextc(s));
734       /* Note that I assume that the size of the character is unchanged */
735       if (c > 255)
736       {
737           *s++=(c>>8);
738           c=c & 0xff;
739       }
740       *s++=c;
741     }
742     return p;
743   }
744   return _strlwr(s);
745 }
746
747
748 /*********************************************************************
749  *              _mbsupr(MSVCRT.@)
750  */
751 unsigned char* _mbsupr(unsigned char* s)
752 {
753   if (!s)
754     return NULL;
755   if (MSVCRT___mb_cur_max > 1)
756   {
757     unsigned int c;
758     unsigned char* p=s;
759     while (*s)
760     {
761       c = _mbctoupper(_mbsnextc(s));
762       /* Note that I assume that the size of the character is unchanged */
763       if (c > 255)
764       {
765           *s++=(c>>8);
766           c=c & 0xff;
767       }
768       *s++=c;
769     }
770     return p;
771   }
772   return _strupr(s);
773 }
774
775
776 /*********************************************************************
777  *              _mbsspn (MSVCRT.@)
778  */
779 MSVCRT_size_t _mbsspn(const unsigned char* string, const unsigned char* set)
780 {
781   const unsigned char *p, *q;
782
783   for (p = string; *p; p++)
784     {
785       if (MSVCRT_isleadbyte(*p))
786         {
787           for (q = set; *q; q++)
788             {
789               if (!q[1])
790                 break;
791               if ((*p == *q) &&  (p[1] == q[1]))
792                 break;
793               q++;
794             }
795           if (*++p == '\0')
796             break;
797         }
798       else
799         for (q = set; *q; q++)
800           if (*p == *q)
801             break;
802     }
803   return p - string;
804 }
805
806 /*********************************************************************
807  *              _mbscspn(MSVCRT.@)
808  */
809 MSVCRT_size_t _mbscspn(const unsigned char* str, const unsigned char* cmp)
810 {
811   if (MSVCRT___mb_cur_max > 1)
812     FIXME("don't handle double character case\n");
813   return strcspn(str, cmp);
814 }
815
816 /*********************************************************************
817  *              _mbsrev (MSVCRT.@)
818  */
819 unsigned char* _mbsrev(unsigned char* str)
820 {
821     int i, len = _mbslen(str);
822     unsigned char *p, *temp=MSVCRT_malloc(len*2);
823
824     if(!temp)
825         return str;
826
827     /* unpack multibyte string to temp buffer */
828     p=str;
829     for(i=0; i<len; i++)
830     {
831         if (MSVCRT_isleadbyte(*p))
832         {
833             temp[i*2]=*p++;
834             temp[i*2+1]=*p++;
835         }
836         else
837         {
838             temp[i*2]=*p++;
839             temp[i*2+1]=0;
840         }
841     }
842
843     /* repack it in the reverse order */
844     p=str;
845     for(i=len-1; i>=0; i--)
846     {
847         if(MSVCRT_isleadbyte(temp[i*2]))
848         {
849             *p++=temp[i*2];
850             *p++=temp[i*2+1];
851         }
852         else
853         {
854             *p++=temp[i*2];
855         }
856     }
857
858     MSVCRT_free(temp);
859
860     return str;
861 }
862
863 /*********************************************************************
864  *              _mbspbrk (MSVCRT.@)
865  */
866 unsigned char* _mbspbrk(const unsigned char* str, const unsigned char* accept)
867 {
868     const unsigned char* p;
869
870     while(*str)
871     {
872         for(p = accept; *p; p += (MSVCRT_isleadbyte(*p)?2:1) )
873         {
874             if (*p == *str)
875                 if( !MSVCRT_isleadbyte(*p) || ( *(p+1) == *(str+1) ) )
876                      return (unsigned char*)str;
877         }
878         str += (MSVCRT_isleadbyte(*str)?2:1);
879     }
880     return NULL;
881 }
882