source: trunk/src/msvcrt/mbcs.c@ 9667

Last change on this file since 9667 was 9633, checked in by sandervl, 23 years ago

PF: Msvcrt Wine port with GCC

File size: 23.7 KB
Line 
1/*
2 * msvcrt.dll mbcs functions
3 *
4 * Copyright 1999 Alexandre Julliard
5 * Copyright 2000 Jon Griffths
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * FIXME
22 * Not currently binary compatible with win32. MSVCRT_mbctype must be
23 * populated correctly and the ismb* functions should reference it.
24 */
25
26#include "msvcrt.h"
27
28#include "msvcrt/mbctype.h"
29#include "msvcrt/mbstring.h"
30#include "msvcrt/stdlib.h"
31#include "msvcrt/string.h"
32#include "msvcrt/wctype.h"
33
34#include "wine/unicode.h"
35#include "wine/debug.h"
36
37WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
38
39unsigned char MSVCRT_mbctype[257];
40int MSVCRT___mb_cur_max = 1;
41
42static MSVCRT_wchar_t msvcrt_mbc_to_wc(unsigned int ch)
43{
44 MSVCRT_wchar_t chW;
45 char mbch[2];
46 int n_chars;
47
48 if (ch <= 0xff) {
49 mbch[0] = ch;
50 n_chars = 1;
51 } else {
52 mbch[0] = (ch >> 8) & 0xff;
53 mbch[1] = ch & 0xff;
54 n_chars = 2;
55 }
56 if (!MultiByteToWideChar(MSVCRT_current_lc_all_cp, 0, mbch, n_chars, &chW, 1))
57 {
58 WARN("MultiByteToWideChar failed on %x\n", ch);
59 return 0;
60 }
61 return chW;
62}
63
64/*********************************************************************
65 * __p__mbctype (MSVCRT.@)
66 */
67unsigned char* __p__mbctype(void)
68{
69 return MSVCRT_mbctype;
70}
71
72/*********************************************************************
73 * __p___mb_cur_max(MSVCRT.@)
74 */
75int* __p___mb_cur_max(void)
76{
77 return &MSVCRT___mb_cur_max;
78}
79
80/*********************************************************************
81 * _mbsnextc(MSVCRT.@)
82 */
83unsigned int _mbsnextc(const unsigned char* str)
84{
85 if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
86 return *str << 8 | str[1];
87 return *str; /* ASCII CP or SB char */
88}
89
90/*********************************************************************
91 * _mbctolower(MSVCRT.@)
92 */
93unsigned int _mbctolower(unsigned int c)
94{
95 if (MSVCRT_isleadbyte(c))
96 {
97 FIXME("Handle MBC chars\n");
98 return c;
99 }
100 return tolower(c); /* ASCII CP or SB char */
101}
102
103/*********************************************************************
104 * _mbctoupper(MSVCRT.@)
105 */
106unsigned int _mbctoupper(unsigned int c)
107{
108 if (MSVCRT_isleadbyte(c))
109 {
110 FIXME("Handle MBC chars\n");
111 return c;
112 }
113 return toupper(c); /* ASCII CP or SB char */
114}
115
116/*********************************************************************
117 * _mbsdec(MSVCRT.@)
118 */
119unsigned char* _mbsdec(const unsigned char* start, const unsigned char* cur)
120{
121 if(MSVCRT___mb_cur_max > 1)
122 return (char *)(_ismbstrail(start,cur-1) ? cur - 2 : cur -1);
123
124 return (char *)cur - 1; /* ASCII CP or SB char */
125}
126
127/*********************************************************************
128 * _mbsinc(MSVCRT.@)
129 */
130unsigned char* _mbsinc(const unsigned char* str)
131{
132 if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
133 return (unsigned char*)str + 2; /* MB char */
134
135 return (unsigned char*)str + 1; /* ASCII CP or SB char */
136}
137
138/*********************************************************************
139 * _mbsninc(MSVCRT.@)
140 */
141unsigned char* _mbsninc(const unsigned char* str, MSVCRT_size_t num)
142{
143 if(!str || num < 1)
144 return NULL;
145 if(MSVCRT___mb_cur_max > 1)
146 {
147 while(num--)
148 str = _mbsinc(str);
149 return (unsigned char*)str;
150 }
151 return (unsigned char*)str + num; /* ASCII CP */
152}
153
154/*********************************************************************
155 * _mbclen(MSVCRT.@)
156 */
157unsigned int _mbclen(const unsigned char* str)
158{
159 return MSVCRT_isleadbyte(*str) ? 2 : 1;
160}
161
162/*********************************************************************
163 * mblen(MSVCRT.@)
164 */
165int MSVCRT_mblen(const char* str, MSVCRT_size_t size)
166{
167 if (str && *str && size)
168 {
169 if(MSVCRT___mb_cur_max == 1)
170 return 1; /* ASCII CP */
171
172 return !MSVCRT_isleadbyte(*str) ? 1 : (size>1 ? 2 : -1);
173 }
174 return 0;
175}
176
177/*********************************************************************
178 * _mbslen(MSVCRT.@)
179 */
180MSVCRT_size_t _mbslen(const unsigned char* str)
181{
182 if(MSVCRT___mb_cur_max > 1)
183 {
184 MSVCRT_size_t len = 0;
185 while(*str)
186 {
187 str += MSVCRT_isleadbyte(*str) ? 2 : 1;
188 len++;
189 }
190 return len;
191 }
192 return strlen(str); /* ASCII CP */
193}
194
195/*********************************************************************
196 * _mbstrlen(MSVCRT.@)
197 */
198MSVCRT_size_t _mbstrlen(const char* str)
199{
200 if(MSVCRT___mb_cur_max > 1)
201 {
202 MSVCRT_size_t len = 0;
203 while(*str)
204 {
205 /* FIXME: According to the documentation we are supposed to test for
206 * multi-byte character validity. Whatever that means
207 */
208 str += MSVCRT_isleadbyte(*str) ? 2 : 1;
209 len++;
210 }
211 return len;
212 }
213 return strlen(str); /* ASCII CP */
214}
215
216/*********************************************************************
217 * _mbccpy(MSVCRT.@)
218 */
219void _mbccpy(unsigned char* dest, const unsigned char* src)
220{
221 *dest++ = *src;
222 if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*src))
223 *dest = *++src; /* MB char */
224 else
225 ERR("failure.. is this ok?\n");
226}
227
228/*********************************************************************
229 * _mbsncpy(MSVCRT.@)
230 */
231unsigned char* _mbsncpy(unsigned char* dst, const unsigned char* src, MSVCRT_size_t n)
232{
233 if(!n)
234 return dst;
235 if(MSVCRT___mb_cur_max > 1)
236 {
237 unsigned char* ret = dst;
238 while (*src && n--)
239 {
240 *dst++ = *src;
241 if (MSVCRT_isleadbyte(*src++))
242 *dst++ = *src++;
243 }
244 while(n--)
245 *dst++ = '\0';
246 return ret;
247 }
248 return strncpy(dst, src, n); /* ASCII CP */
249}
250
251/*********************************************************************
252 * _mbsnbcpy(MSVCRT.@)
253 */
254unsigned char* _mbsnbcpy(unsigned char* dst, const unsigned char* src, MSVCRT_size_t n)
255{
256 if(!n)
257 return dst;
258 if(MSVCRT___mb_cur_max > 1)
259 {
260 unsigned char* ret = dst;
261 while (*src && (n-- > 1))
262 {
263 *dst++ = *src;
264 if (MSVCRT_isleadbyte(*src++))
265 {
266 *dst++ = *src++;
267 n--;
268 }
269 }
270 if (*src && n && !MSVCRT_isleadbyte(*src))
271 {
272 /* If the last character is a multi-byte character then
273 * we cannot copy it since we have only one byte left
274 */
275 *dst++ = *src;
276 n--;
277 }
278 while (n--)
279 *dst++ = '\0';
280 return ret;
281 }
282 return strncpy(dst, src, n); /* ASCII CP */
283}
284
285/*********************************************************************
286 * _mbscmp(MSVCRT.@)
287 */
288int _mbscmp(const unsigned char* str, const unsigned char* cmp)
289{
290 if(MSVCRT___mb_cur_max > 1)
291 {
292 unsigned int strc, cmpc;
293 do {
294 if(!*str)
295 return *cmp ? -1 : 0;
296 if(!*cmp)
297 return 1;
298 strc = _mbsnextc(str);
299 cmpc = _mbsnextc(cmp);
300 if(strc != cmpc)
301 return strc < cmpc ? -1 : 1;
302 str +=(strc > 255) ? 2 : 1;
303 cmp +=(strc > 255) ? 2 : 1; /* equal, use same increment */
304 } while(1);
305 }
306 return strcmp(str, cmp); /* ASCII CP */
307}
308
309/*********************************************************************
310 * _mbsicmp(MSVCRT.@)
311 */
312int _mbsicmp(const unsigned char* str, const unsigned char* cmp)
313{
314 if(MSVCRT___mb_cur_max > 1)
315 {
316 unsigned int strc, cmpc;
317 do {
318 if(!*str)
319 return *cmp ? -1 : 0;
320 if(!*cmp)
321 return 1;
322 strc = _mbctolower(_mbsnextc(str));
323 cmpc = _mbctolower(_mbsnextc(cmp));
324 if(strc != cmpc)
325 return strc < cmpc ? -1 : 1;
326 str +=(strc > 255) ? 2 : 1;
327 cmp +=(strc > 255) ? 2 : 1; /* equal, use same increment */
328 } while(1);
329 }
330 return strcasecmp(str, cmp); /* ASCII CP */
331}
332
333/*********************************************************************
334 * _mbsncmp(MSVCRT.@)
335 */
336int _mbsncmp(const unsigned char* str, const unsigned char* cmp, MSVCRT_size_t len)
337{
338 if(!len)
339 return 0;
340
341 if(MSVCRT___mb_cur_max > 1)
342 {
343 unsigned int strc, cmpc;
344 while(len--)
345 {
346 int inc;
347 if(!*str)
348 return *cmp ? -1 : 0;
349 if(!*cmp)
350 return 1;
351 strc = _mbsnextc(str);
352 cmpc = _mbsnextc(cmp);
353 if(strc != cmpc)
354 return strc < cmpc ? -1 : 1;
355 inc=(strc > 255) ? 2 : 1; /* Equal, use same increment */
356 str += inc;
357 cmp += inc;
358 }
359 return 0; /* Matched len chars */
360 }
361 return strncmp(str, cmp, len); /* ASCII CP */
362}
363
364/*********************************************************************
365 * _mbsnbcmp(MSVCRT.@)
366 */
367int _mbsnbcmp(const unsigned char* str, const unsigned char* cmp, MSVCRT_size_t len)
368{
369 if (!len)
370 return 0;
371 if(MSVCRT___mb_cur_max > 1)
372 {
373 unsigned int strc, cmpc;
374 while (len)
375 {
376 int clen;
377 if(!*str)
378 return *cmp ? -1 : 0;
379 if(!*cmp)
380 return 1;
381 if (MSVCRT_isleadbyte(*str))
382 {
383 strc=(len>=2)?_mbsnextc(str):0;
384 clen=2;
385 }
386 else
387 {
388 strc=*str;
389 clen=1;
390 }
391 if (MSVCRT_isleadbyte(*cmp))
392 cmpc=(len>=2)?_mbsnextc(cmp):0;
393 else
394 cmpc=*str;
395 if(strc != cmpc)
396 return strc < cmpc ? -1 : 1;
397 len -= clen;
398 str += clen;
399 cmp += clen;
400 }
401 return 0; /* Matched len chars */
402 FIXME("%s %s %d\n",str,cmp,len);
403 }
404 return strncmp(str,cmp,len);
405}
406
407/*********************************************************************
408 * _mbsnicmp(MSVCRT.@)
409 *
410 * Compare two multibyte strings case insensitively to 'len' characters.
411 */
412int _mbsnicmp(const unsigned char* str, const unsigned char* cmp, MSVCRT_size_t len)
413{
414 /* FIXME: No tolower() for mb strings yet */
415 if(MSVCRT___mb_cur_max > 1)
416 {
417 unsigned int strc, cmpc;
418 while(len--)
419 {
420 if(!*str)
421 return *cmp ? -1 : 0;
422 if(!*cmp)
423 return 1;
424 strc = _mbctolower(_mbsnextc(str));
425 cmpc = _mbctolower(_mbsnextc(cmp));
426 if(strc != cmpc)
427 return strc < cmpc ? -1 : 1;
428 str +=(strc > 255) ? 2 : 1;
429 cmp +=(strc > 255) ? 2 : 1; /* Equal, use same increment */
430 }
431 return 0; /* Matched len chars */
432 }
433 return strncasecmp(str, cmp, len); /* ASCII CP */
434}
435
436/*********************************************************************
437 * _mbsnbicmp(MSVCRT.@)
438 */
439int _mbsnbicmp(const unsigned char* str, const unsigned char* cmp, MSVCRT_size_t len)
440{
441 if (!len)
442 return 0;
443 if(MSVCRT___mb_cur_max > 1)
444 {
445 unsigned int strc, cmpc;
446 while (len)
447 {
448 int clen;
449 if(!*str)
450 return *cmp ? -1 : 0;
451 if(!*cmp)
452 return 1;
453 if (MSVCRT_isleadbyte(*str))
454 {
455 strc=(len>=2)?_mbsnextc(str):0;
456 clen=2;
457 }
458 else
459 {
460 strc=*str;
461 clen=1;
462 }
463 if (MSVCRT_isleadbyte(*cmp))
464 cmpc=(len>=2)?_mbsnextc(cmp):0;
465 else
466 cmpc=*str;
467 strc = _mbctolower(strc);
468 cmpc = _mbctolower(cmpc);
469 if(strc != cmpc)
470 return strc < cmpc ? -1 : 1;
471 len -= clen;
472 str += clen;
473 cmp += clen;
474 }
475 return 0; /* Matched len bytes */
476 FIXME("%s %s %d\n",str,cmp,len);
477 }
478 return strncmp(str,cmp,len);
479}
480
481/*********************************************************************
482 * _mbschr(MSVCRT.@)
483 *
484 * Find a multibyte character in a multibyte string.
485 */
486unsigned char* _mbschr(const unsigned char* s, unsigned int x)
487{
488 if(MSVCRT___mb_cur_max > 1)
489 {
490 unsigned int c;
491 while (1)
492 {
493 c = _mbsnextc(s);
494 if (c == x)
495 return (unsigned char*)s;
496 if (!c)
497 return NULL;
498 s += c > 255 ? 2 : 1;
499 }
500 }
501 return strchr(s, x); /* ASCII CP */
502}
503
504/*********************************************************************
505 * _mbsrchr(MSVCRT.@)
506 */
507unsigned char* _mbsrchr(const unsigned char* s, unsigned int x)
508{
509 if(MSVCRT___mb_cur_max > 1)
510 {
511 unsigned int c;
512 unsigned char* match=NULL;
513 if(!s)
514 return NULL;
515 while (1) {
516 c = _mbsnextc(s);
517 if (c == x)
518 match=(unsigned char*)s;
519 if (!c)
520 return match;
521 s +=(c > 255) ? 2 : 1;
522 }
523 }
524 return strrchr(s,x);
525}
526
527/*********************************************************************
528 * mbtowc(MSVCRT.@)
529 */
530int MSVCRT_mbtowc(MSVCRT_wchar_t *dst, const char* str, MSVCRT_size_t n)
531{
532 if(n <= 0 || !str)
533 return 0;
534 if(!MultiByteToWideChar(CP_ACP, 0, str, n, dst, 1))
535 return 0;
536 /* return the number of bytes from src that have been used */
537 if(!*str)
538 return 0;
539 if(n >= 2 && MSVCRT_isleadbyte(*str) && str[1])
540 return 2;
541 return 1;
542}
543
544/*********************************************************************
545 * _mbbtombc(MSVCRT.@)
546 */
547unsigned int _mbbtombc(unsigned int c)
548{
549 if(MSVCRT___mb_cur_max > 1 &&
550 ((c >= 0x20 && c <=0x7e) ||(c >= 0xa1 && c <= 0xdf)))
551 {
552 /* FIXME: I can't get this function to return anything
553 * different to what I pass it...
554 */
555 }
556 return c; /* ASCII CP or no MB char */
557}
558
559/*********************************************************************
560 * _ismbbkana(MSVCRT.@)
561 */
562int _ismbbkana(unsigned int c)
563{
564 /* FIXME: use lc_ctype when supported, not lc_all */
565 if(MSVCRT_current_lc_all_cp == 932)
566 {
567 /* Japanese/Katakana, CP 932 */
568 return (c >= 0xa1 && c <= 0xdf);
569 }
570 return 0;
571}
572
573/*********************************************************************
574 * _ismbcdigit(MSVCRT.@)
575 */
576int _ismbcdigit(unsigned int ch)
577{
578 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
579 return (get_char_typeW( wch ) & C1_DIGIT);
580}
581
582/*********************************************************************
583 * _ismbcgraph(MSVCRT.@)
584 */
585int _ismbcgraph(unsigned int ch)
586{
587 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
588 return (get_char_typeW( wch ) & (C1_UPPER | C1_LOWER | C1_DIGIT | C1_PUNCT | C1_ALPHA));
589}
590
591/*********************************************************************
592 * _ismbcalpha (MSVCRT.@)
593 */
594int _ismbcalpha(unsigned int ch)
595{
596 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
597 return (get_char_typeW( wch ) & C1_ALPHA);
598}
599
600/*********************************************************************
601 * _ismbclower (MSVCRT.@)
602 */
603int _ismbclower(unsigned int ch)
604{
605 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
606 return (get_char_typeW( wch ) & C1_UPPER);
607}
608
609/*********************************************************************
610 * _ismbcupper (MSVCRT.@)
611 */
612int _ismbcupper(unsigned int ch)
613{
614 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
615 return (get_char_typeW( wch ) & C1_LOWER);
616}
617
618/*********************************************************************
619 * _ismbcsymbol(MSVCRT.@)
620 */
621int _ismbcsymbol(unsigned int ch)
622{
623 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
624 WORD ctype;
625 if (!GetStringTypeW(CT_CTYPE3, &wch, 1, &ctype))
626 {
627 WARN("GetStringTypeW failed on %x\n", ch);
628 return 0;
629 }
630 return ((ctype & C3_SYMBOL) != 0);
631}
632
633/*********************************************************************
634 * _ismbcalnum (MSVCRT.@)
635 */
636int _ismbcalnum(unsigned int ch)
637{
638 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
639 return (get_char_typeW( wch ) & (C1_ALPHA | C1_DIGIT));
640}
641
642/*********************************************************************
643 * _ismbcspace (MSVCRT.@)
644 */
645int _ismbcspace(unsigned int ch)
646{
647 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
648 return (get_char_typeW( wch ) & C1_SPACE);
649}
650
651/*********************************************************************
652 * _ismbcprint (MSVCRT.@)
653 */
654int _ismbcprint(unsigned int ch)
655{
656 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
657 return (get_char_typeW( wch ) & (C1_UPPER | C1_LOWER | C1_DIGIT | C1_PUNCT | C1_ALPHA | C1_SPACE));
658}
659
660/*********************************************************************
661 * _ismbcpunct(MSVCRT.@)
662 */
663int _ismbcpunct(unsigned int ch)
664{
665 MSVCRT_wchar_t wch = msvcrt_mbc_to_wc( ch );
666 return (get_char_typeW( wch ) & C1_PUNCT);
667}
668
669/*********************************************************************
670 * _ismbchira(MSVCRT.@)
671 */
672int _ismbchira(unsigned int c)
673{
674 /* FIXME: use lc_ctype when supported, not lc_all */
675 if(MSVCRT_current_lc_all_cp == 932)
676 {
677 /* Japanese/Hiragana, CP 932 */
678 return (c >= 0x829f && c <= 0x82f1);
679 }
680 return 0;
681}
682
683/*********************************************************************
684 * _ismbckata(MSVCRT.@)
685 */
686int _ismbckata(unsigned int c)
687{
688 /* FIXME: use lc_ctype when supported, not lc_all */
689 if(MSVCRT_current_lc_all_cp == 932)
690 {
691 if(c < 256)
692 return _ismbbkana(c);
693 /* Japanese/Katakana, CP 932 */
694 return (c >= 0x8340 && c <= 0x8396 && c != 0x837f);
695 }
696 return 0;
697}
698
699/*********************************************************************
700 * _ismbblead(MSVCRT.@)
701 */
702int _ismbblead(unsigned int c)
703{
704 /* FIXME: should reference MSVCRT_mbctype */
705 return MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(c);
706}
707
708
709/*********************************************************************
710 * _ismbbtrail(MSVCRT.@)
711 */
712int _ismbbtrail(unsigned int c)
713{
714 /* FIXME: should reference MSVCRT_mbctype */
715 return !_ismbblead(c);
716}
717
718/*********************************************************************
719 * _ismbslead(MSVCRT.@)
720 */
721int _ismbslead(const unsigned char* start, const unsigned char* str)
722{
723 /* Lead bytes can also be trail bytes if caller messed up
724 * iterating through the string...
725 */
726 if(MSVCRT___mb_cur_max > 1)
727 {
728 while(start < str)
729 start += MSVCRT_isleadbyte(*str) ? 2 : 1;
730
731 if(start == str)
732 return MSVCRT_isleadbyte(*str);
733 }
734 return 0; /* Must have been a trail, we skipped it */
735}
736
737/*********************************************************************
738 * _ismbstrail(MSVCRT.@)
739 */
740int _ismbstrail(const unsigned char* start, const unsigned char* str)
741{
742 /* Must not be a lead, and must be preceeded by one */
743 return !_ismbslead(start, str) && MSVCRT_isleadbyte(str[-1]);
744}
745
746/*********************************************************************
747 * _mbsset(MSVCRT.@)
748 */
749unsigned char* _mbsset(unsigned char* str, unsigned int c)
750{
751 unsigned char* ret = str;
752
753 if(MSVCRT___mb_cur_max == 1 || c < 256)
754 return _strset(str, c); /* ASCII CP or SB char */
755
756 c &= 0xffff; /* Strip high bits */
757
758 while(str[0] && str[1])
759 {
760 *str++ = c >> 8;
761 *str++ = c & 0xff;
762 }
763 if(str[0])
764 str[0] = '\0'; /* FIXME: OK to shorten? */
765
766 return ret;
767}
768
769/*********************************************************************
770 * _mbsnset(MSVCRT.@)
771 */
772unsigned char* _mbsnset(unsigned char* str, unsigned int c, MSVCRT_size_t len)
773{
774 unsigned char *ret = str;
775
776 if(!len)
777 return ret;
778
779 if(MSVCRT___mb_cur_max == 1 || c < 256)
780 return _strnset(str, c, len); /* ASCII CP or SB char */
781
782 c &= 0xffff; /* Strip high bits */
783
784 while(str[0] && str[1] && len--)
785 {
786 *str++ = c >> 8;
787 *str++ = c & 0xff;
788 }
789 if(len && str[0])
790 str[0] = '\0'; /* FIXME: OK to shorten? */
791
792 return ret;
793}
794
795/*********************************************************************
796 * _mbsnccnt(MSVCRT.@)
797 * 'c' is for 'character'.
798 */
799MSVCRT_size_t _mbsnccnt(const unsigned char* str, MSVCRT_size_t len)
800{
801 MSVCRT_size_t ret;
802 if(MSVCRT___mb_cur_max > 1)
803 {
804 ret=0;
805 while(*str && len-- > 0)
806 {
807 if(MSVCRT_isleadbyte(*str))
808 {
809 if (!len)
810 break;
811 len--;
812 str++;
813 }
814 str++;
815 ret++;
816 }
817 return ret;
818 }
819 ret=strlen(str);
820 return min(ret, len); /* ASCII CP */
821}
822
823/*********************************************************************
824 * _mbsnbcnt(MSVCRT.@)
825 * 'b' is for byte count.
826 */
827MSVCRT_size_t _mbsnbcnt(const unsigned char* str, MSVCRT_size_t len)
828{
829 MSVCRT_size_t ret;
830 if(MSVCRT___mb_cur_max > 1)
831 {
832 const unsigned char* xstr = str;
833 while(*xstr && len-- > 0)
834 {
835 if (MSVCRT_isleadbyte(*xstr++))
836 xstr++;
837 }
838 return xstr-str;
839 }
840 ret=strlen(str);
841 return min(ret, len); /* ASCII CP */
842}
843
844
845/*********************************************************************
846 * _mbsncat(MSVCRT.@)
847 */
848unsigned char* _mbsncat(unsigned char* dst, const unsigned char* src, MSVCRT_size_t len)
849{
850 if(MSVCRT___mb_cur_max > 1)
851 {
852 char *res = dst;
853 while (*dst)
854 {
855 if (MSVCRT_isleadbyte(*dst++))
856 dst++;
857 }
858 while (*src && len--)
859 {
860 *dst++ = *src;
861 if(MSVCRT_isleadbyte(*src++))
862 *dst++ = *src++;
863 }
864 *dst = '\0';
865 return res;
866 }
867 return strncat(dst, src, len); /* ASCII CP */
868}
869
870
871/*********************************************************************
872 * _mbslwr(MSVCRT.@)
873 */
874unsigned char* _mbslwr(unsigned char* s)
875{
876 if (!s)
877 return NULL;
878 if (MSVCRT___mb_cur_max > 1)
879 {
880 unsigned int c;
881 unsigned char* p=s;
882 while (*s)
883 {
884 c = _mbctolower(_mbsnextc(s));
885 /* Note that I assume that the size of the character is unchanged */
886 if (c > 255)
887 {
888 *s++=(c>>8);
889 c=c & 0xff;
890 }
891 *s++=c;
892 }
893 return p;
894 }
895 return _strlwr(s);
896}
897
898
899/*********************************************************************
900 * _mbsupr(MSVCRT.@)
901 */
902unsigned char* _mbsupr(unsigned char* s)
903{
904 if (!s)
905 return NULL;
906 if (MSVCRT___mb_cur_max > 1)
907 {
908 unsigned int c;
909 unsigned char* p=s;
910 while (*s)
911 {
912 c = _mbctoupper(_mbsnextc(s));
913 /* Note that I assume that the size of the character is unchanged */
914 if (c > 255)
915 {
916 *s++=(c>>8);
917 c=c & 0xff;
918 }
919 *s++=c;
920 }
921 return p;
922 }
923 return _strupr(s);
924}
925
926
927/*********************************************************************
928 * _mbsspn (MSVCRT.@)
929 */
930MSVCRT_size_t _mbsspn(const unsigned char* string, const unsigned char* set)
931{
932 const unsigned char *p, *q;
933
934 for (p = string; *p; p++)
935 {
936 if (MSVCRT_isleadbyte(*p))
937 {
938 for (q = set; *q; q++)
939 {
940 if (!q[1])
941 break;
942 if ((*p == *q) && (p[1] == q[1]))
943 break;
944 q++;
945 }
946 if (*++p == '\0')
947 break;
948 }
949 else
950 for (q = set; *q; q++)
951 if (*p == *q)
952 break;
953 }
954 return p - string;
955}
956
957/*********************************************************************
958 * _mbscspn(MSVCRT.@)
959 */
960MSVCRT_size_t _mbscspn(const unsigned char* str, const unsigned char* cmp)
961{
962 if (MSVCRT___mb_cur_max > 1)
963 FIXME("don't handle double character case\n");
964 return strcspn(str, cmp);
965}
966
967/*********************************************************************
968 * _mbsrev (MSVCRT.@)
969 */
970unsigned char* _mbsrev(unsigned char* str)
971{
972 int i, len = _mbslen(str);
973 unsigned char *p, *temp=MSVCRT_malloc(len*2);
974
975 if(!temp)
976 return str;
977
978 /* unpack multibyte string to temp buffer */
979 p=str;
980 for(i=0; i<len; i++)
981 {
982 if (MSVCRT_isleadbyte(*p))
983 {
984 temp[i*2]=*p++;
985 temp[i*2+1]=*p++;
986 }
987 else
988 {
989 temp[i*2]=*p++;
990 temp[i*2+1]=0;
991 }
992 }
993
994 /* repack it in the reverse order */
995 p=str;
996 for(i=len-1; i>=0; i--)
997 {
998 if(MSVCRT_isleadbyte(temp[i*2]))
999 {
1000 *p++=temp[i*2];
1001 *p++=temp[i*2+1];
1002 }
1003 else
1004 {
1005 *p++=temp[i*2];
1006 }
1007 }
1008
1009 MSVCRT_free(temp);
1010
1011 return str;
1012}
1013
1014/*********************************************************************
1015 * _mbspbrk (MSVCRT.@)
1016 */
1017unsigned char* _mbspbrk(const unsigned char* str, const unsigned char* accept)
1018{
1019 const unsigned char* p;
1020
1021 while(*str)
1022 {
1023 for(p = accept; *p; p += (MSVCRT_isleadbyte(*p)?2:1) )
1024 {
1025 if (*p == *str)
1026 if( !MSVCRT_isleadbyte(*p) || ( *(p+1) == *(str+1) ) )
1027 return (unsigned char*)str;
1028 }
1029 str += (MSVCRT_isleadbyte(*str)?2:1);
1030 }
1031 return NULL;
1032}
Note: See TracBrowser for help on using the repository browser.