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