msvcrt: Use the msvcrt ctype functions internally.
[wine.git] / dlls / msvcrt / ctype.c
blob1334a514788fe55f2de8e74b18af66e445be7a52
1 /*
2 * msvcrt.dll ctype functions
4 * Copyright 2000 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "msvcrt.h"
22 #include "winnls.h"
24 /* Some abbreviations to make the following table readable */
25 #define _C_ MSVCRT__CONTROL
26 #define _S_ MSVCRT__SPACE
27 #define _P_ MSVCRT__PUNCT
28 #define _D_ MSVCRT__DIGIT
29 #define _H_ MSVCRT__HEX
30 #define _U_ MSVCRT__UPPER
31 #define _L_ MSVCRT__LOWER
33 WORD MSVCRT__ctype [257] = {
34 0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_,
35 _S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_,
36 _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|MSVCRT__BLANK,
37 _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_,
38 _P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_,
39 _D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_,
40 _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_,
41 _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_,
42 _U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_,
43 _L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_,
44 _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_,
45 _C_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
53 #if _MSVCR_VER <= 110
54 # define B110 MSVCRT__BLANK
55 #else
56 # define B110 0
57 #endif
59 #if _MSVCR_VER == 120
60 # define D120 0
61 #else
62 # define D120 4
63 #endif
65 #if _MSVCR_VER >= 140
66 # define S140 MSVCRT__SPACE
67 # define L140 MSVCRT__LOWER | 0x100
68 # define C140 MSVCRT__CONTROL
69 #else
70 # define S140 0
71 # define L140 0
72 # define C140 0
73 #endif
74 WORD MSVCRT__wctype[257] =
77 /* 00 */
78 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
79 0x0020, 0x0028 | B110, 0x0028, 0x0028, 0x0028, 0x0028, 0x0020, 0x0020,
80 /* 10 */
81 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
82 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
83 /* 20 */
84 0x0048, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
85 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
86 /* 30 */
87 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
88 0x0084, 0x0084, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
89 /* 40 */
90 0x0010, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0101,
91 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
92 /* 50 */
93 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
94 0x0101, 0x0101, 0x0101, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
95 /* 60 */
96 0x0010, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0102,
97 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
98 /* 70 */
99 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
100 0x0102, 0x0102, 0x0102, 0x0010, 0x0010, 0x0010, 0x0010, 0x0020,
101 /* 80 */
102 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 | S140, 0x0020, 0x0020,
103 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
104 /* 90 */
105 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
106 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
107 /* a0 */
108 0x0008 | B110, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
109 0x0010, 0x0010, 0x0010 | L140, 0x0010, 0x0010, 0x0010 | C140, 0x0010, 0x0010,
110 /* b0 */
111 0x0010, 0x0010, 0x0010 | D120, 0x0010 | D120, 0x0010, 0x0010 | L140, 0x0010, 0x0010,
112 0x0010, 0x0010 | D120, 0x0010 | L140, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
113 /* c0 */
114 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
115 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
116 /* d0 */
117 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0010,
118 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0102,
119 /* e0 */
120 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
121 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
122 /* f0 */
123 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0010,
124 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102
127 WORD *MSVCRT__pwctype = MSVCRT__wctype + 1;
129 /*********************************************************************
130 * __p__pctype (MSVCRT.@)
132 unsigned short** CDECL MSVCRT___p__pctype(void)
134 return &get_locinfo()->pctype;
137 /*********************************************************************
138 * __pctype_func (MSVCRT.@)
140 const unsigned short* CDECL MSVCRT___pctype_func(void)
142 return get_locinfo()->pctype;
145 /*********************************************************************
146 * _isctype_l (MSVCRT.@)
148 int CDECL MSVCRT__isctype_l(int c, int type, MSVCRT__locale_t locale)
150 MSVCRT_pthreadlocinfo locinfo;
152 if(!locale)
153 locinfo = get_locinfo();
154 else
155 locinfo = locale->locinfo;
157 if (c >= -1 && c <= 255)
158 return locinfo->pctype[c] & type;
160 if (locinfo->mb_cur_max != 1 && c > 0)
162 /* FIXME: Is there a faster way to do this? */
163 WORD typeInfo;
164 char convert[3], *pconv = convert;
166 if (locinfo->pctype[(UINT)c >> 8] & MSVCRT__LEADBYTE)
167 *pconv++ = (UINT)c >> 8;
168 *pconv++ = c & 0xff;
169 *pconv = 0;
171 if (GetStringTypeExA(locinfo->lc_handle[MSVCRT_LC_CTYPE],
172 CT_CTYPE1, convert, convert[1] ? 2 : 1, &typeInfo))
173 return typeInfo & type;
175 return 0;
178 /*********************************************************************
179 * _isctype (MSVCRT.@)
181 int CDECL MSVCRT__isctype(int c, int type)
183 return MSVCRT__isctype_l(c, type, NULL);
186 /*********************************************************************
187 * _isalnum_l (MSVCRT.@)
189 int CDECL MSVCRT__isalnum_l(int c, MSVCRT__locale_t locale)
191 return MSVCRT__isctype_l( c, MSVCRT__ALPHA | MSVCRT__DIGIT, locale );
194 /*********************************************************************
195 * isalnum (MSVCRT.@)
197 int CDECL MSVCRT_isalnum(int c)
199 return MSVCRT__isctype( c, MSVCRT__ALPHA | MSVCRT__DIGIT );
202 /*********************************************************************
203 * _isalpha_l (MSVCRT.@)
205 int CDECL MSVCRT__isalpha_l(int c, MSVCRT__locale_t locale)
207 return MSVCRT__isctype_l( c, MSVCRT__ALPHA, locale );
210 /*********************************************************************
211 * isalpha (MSVCRT.@)
213 int CDECL MSVCRT_isalpha(int c)
215 return MSVCRT__isctype( c, MSVCRT__ALPHA );
218 /*********************************************************************
219 * _iscntrl_l (MSVCRT.@)
221 int CDECL MSVCRT__iscntrl_l(int c, MSVCRT__locale_t locale)
223 return MSVCRT__isctype_l( c, MSVCRT__CONTROL, locale );
226 /*********************************************************************
227 * iscntrl (MSVCRT.@)
229 int CDECL MSVCRT_iscntrl(int c)
231 return MSVCRT__isctype( c, MSVCRT__CONTROL );
234 /*********************************************************************
235 * _isdigit_l (MSVCRT.@)
237 int CDECL MSVCRT__isdigit_l(int c, MSVCRT__locale_t locale)
239 return MSVCRT__isctype_l( c, MSVCRT__DIGIT, locale );
242 /*********************************************************************
243 * isdigit (MSVCRT.@)
245 int CDECL MSVCRT_isdigit(int c)
247 return MSVCRT__isctype( c, MSVCRT__DIGIT );
250 /*********************************************************************
251 * _isgraph_l (MSVCRT.@)
253 int CDECL MSVCRT__isgraph_l(int c, MSVCRT__locale_t locale)
255 return MSVCRT__isctype_l( c, MSVCRT__ALPHA | MSVCRT__DIGIT | MSVCRT__PUNCT, locale );
258 /*********************************************************************
259 * isgraph (MSVCRT.@)
261 int CDECL MSVCRT_isgraph(int c)
263 return MSVCRT__isctype( c, MSVCRT__ALPHA | MSVCRT__DIGIT | MSVCRT__PUNCT );
266 /*********************************************************************
267 * _isleadbyte_l (MSVCRT.@)
269 int CDECL MSVCRT__isleadbyte_l(int c, MSVCRT__locale_t locale)
271 return MSVCRT__isctype_l( c, MSVCRT__LEADBYTE, locale );
274 /*********************************************************************
275 * isleadbyte (MSVCRT.@)
277 int CDECL MSVCRT_isleadbyte(int c)
279 return MSVCRT__isctype( c, MSVCRT__LEADBYTE );
282 /*********************************************************************
283 * _islower_l (MSVCRT.@)
285 int CDECL MSVCRT__islower_l(int c, MSVCRT__locale_t locale)
287 return MSVCRT__isctype_l( c, MSVCRT__LOWER, locale );
290 /*********************************************************************
291 * islower (MSVCRT.@)
293 int CDECL MSVCRT_islower(int c)
295 return MSVCRT__isctype( c, MSVCRT__LOWER );
298 /*********************************************************************
299 * _isprint_l (MSVCRT.@)
301 int CDECL MSVCRT__isprint_l(int c, MSVCRT__locale_t locale)
303 return MSVCRT__isctype_l( c, MSVCRT__ALPHA | MSVCRT__DIGIT | MSVCRT__BLANK | MSVCRT__PUNCT, locale );
306 /*********************************************************************
307 * isprint (MSVCRT.@)
309 int CDECL MSVCRT_isprint(int c)
311 return MSVCRT__isctype( c, MSVCRT__ALPHA | MSVCRT__DIGIT | MSVCRT__BLANK | MSVCRT__PUNCT );
314 /*********************************************************************
315 * ispunct (MSVCRT.@)
317 int CDECL MSVCRT_ispunct(int c)
319 return MSVCRT__isctype( c, MSVCRT__PUNCT );
322 /*********************************************************************
323 * _ispunct_l (MSVCR80.@)
325 int CDECL MSVCRT__ispunct_l(int c, MSVCRT__locale_t locale)
327 return MSVCRT__isctype_l( c, MSVCRT__PUNCT, locale );
330 /*********************************************************************
331 * _isspace_l (MSVCRT.@)
333 int CDECL MSVCRT__isspace_l(int c, MSVCRT__locale_t locale)
335 return MSVCRT__isctype_l( c, MSVCRT__SPACE, locale );
338 /*********************************************************************
339 * isspace (MSVCRT.@)
341 int CDECL MSVCRT_isspace(int c)
343 return MSVCRT__isctype( c, MSVCRT__SPACE );
346 /*********************************************************************
347 * _isupper_l (MSVCRT.@)
349 int CDECL MSVCRT__isupper_l(int c, MSVCRT__locale_t locale)
351 return MSVCRT__isctype_l( c, MSVCRT__UPPER, locale );
354 /*********************************************************************
355 * isupper (MSVCRT.@)
357 int CDECL MSVCRT_isupper(int c)
359 return MSVCRT__isctype( c, MSVCRT__UPPER );
362 /*********************************************************************
363 * _isxdigit_l (MSVCRT.@)
365 int CDECL MSVCRT__isxdigit_l(int c, MSVCRT__locale_t locale)
367 return MSVCRT__isctype_l( c, MSVCRT__HEX, locale );
370 /*********************************************************************
371 * isxdigit (MSVCRT.@)
373 int CDECL MSVCRT_isxdigit(int c)
375 return MSVCRT__isctype( c, MSVCRT__HEX );
378 /*********************************************************************
379 * _isblank_l (MSVCRT.@)
381 int CDECL MSVCRT__isblank_l(int c, MSVCRT__locale_t locale)
383 return c == '\t' || MSVCRT__isctype_l( c, MSVCRT__BLANK, locale );
386 /*********************************************************************
387 * isblank (MSVCRT.@)
389 int CDECL MSVCRT_isblank(int c)
391 return c == '\t' || MSVCRT__isctype( c, MSVCRT__BLANK );
394 /*********************************************************************
395 * __isascii (MSVCRT.@)
397 int CDECL MSVCRT___isascii(int c)
399 return ((unsigned)c < 0x80);
402 /*********************************************************************
403 * __toascii (MSVCRT.@)
405 int CDECL MSVCRT___toascii(int c)
407 return (unsigned)c & 0x7f;
410 /*********************************************************************
411 * iswascii (MSVCRT.@)
414 int CDECL MSVCRT_iswascii(MSVCRT_wchar_t c)
416 return ((unsigned)c < 0x80);
419 /*********************************************************************
420 * __iscsym (MSVCRT.@)
422 int CDECL MSVCRT___iscsym(int c)
424 return (c < 127 && (MSVCRT_isalnum(c) || c == '_'));
427 /*********************************************************************
428 * __iscsymf (MSVCRT.@)
430 int CDECL MSVCRT___iscsymf(int c)
432 return (c < 127 && (MSVCRT_isalpha(c) || c == '_'));
435 /*********************************************************************
436 * _toupper_l (MSVCRT.@)
438 int CDECL MSVCRT__toupper_l(int c, MSVCRT__locale_t locale)
440 MSVCRT_pthreadlocinfo locinfo;
441 unsigned char str[2], *p = str, ret[2];
443 if(!locale)
444 locinfo = get_locinfo();
445 else
446 locinfo = locale->locinfo;
448 if((unsigned)c < 256)
449 return locinfo->pcumap[c];
451 if(locinfo->pctype[(c>>8)&255] & MSVCRT__LEADBYTE)
452 *p++ = (c>>8) & 255;
453 else {
454 *MSVCRT__errno() = MSVCRT_EILSEQ;
455 str[1] = 0;
457 *p++ = c & 255;
459 switch(__crtLCMapStringA(locinfo->lc_handle[MSVCRT_LC_CTYPE], LCMAP_UPPERCASE,
460 (char*)str, p-str, (char*)ret, 2, locinfo->lc_codepage, 0))
462 case 0:
463 return c;
464 case 1:
465 return ret[0];
466 default:
467 return ret[0] + (ret[1]<<8);
471 /*********************************************************************
472 * toupper (MSVCRT.@)
474 int CDECL MSVCRT_toupper(int c)
476 if(initial_locale)
477 return c>='a' && c<='z' ? c-'a'+'A' : c;
478 return MSVCRT__toupper_l(c, NULL);
481 /*********************************************************************
482 * _toupper (MSVCRT.@)
484 int CDECL MSVCRT__toupper(int c)
486 return c - 0x20; /* sic */
489 /*********************************************************************
490 * _tolower_l (MSVCRT.@)
492 int CDECL MSVCRT__tolower_l(int c, MSVCRT__locale_t locale)
494 MSVCRT_pthreadlocinfo locinfo;
495 unsigned char str[2], *p = str, ret[2];
497 if(!locale)
498 locinfo = get_locinfo();
499 else
500 locinfo = locale->locinfo;
502 if((unsigned)c < 256)
503 return locinfo->pclmap[c];
505 if(locinfo->pctype[(c>>8)&255] & MSVCRT__LEADBYTE)
506 *p++ = (c>>8) & 255;
507 else {
508 *MSVCRT__errno() = MSVCRT_EILSEQ;
509 str[1] = 0;
511 *p++ = c & 255;
513 switch(__crtLCMapStringA(locinfo->lc_handle[MSVCRT_LC_CTYPE], LCMAP_LOWERCASE,
514 (char*)str, p-str, (char*)ret, 2, locinfo->lc_codepage, 0))
516 case 0:
517 return c;
518 case 1:
519 return ret[0];
520 default:
521 return ret[0] + (ret[1]<<8);
525 /*********************************************************************
526 * tolower (MSVCRT.@)
528 int CDECL MSVCRT_tolower(int c)
530 if(initial_locale)
531 return c>='A' && c<='Z' ? c-'A'+'a' : c;
532 return MSVCRT__tolower_l(c, NULL);
535 /*********************************************************************
536 * _tolower (MSVCRT.@)
538 int CDECL MSVCRT__tolower(int c)
540 return c + 0x20; /* sic */
543 #if _MSVCR_VER>=120
544 /*********************************************************************
545 * wctype (MSVCR120.@)
547 unsigned short __cdecl wctype(const char *property)
549 static const struct {
550 const char *name;
551 unsigned short mask;
552 } properties[] = {
553 { "alnum", MSVCRT__DIGIT|MSVCRT__ALPHA },
554 { "alpha", MSVCRT__ALPHA },
555 { "cntrl", MSVCRT__CONTROL },
556 { "digit", MSVCRT__DIGIT },
557 { "graph", MSVCRT__DIGIT|MSVCRT__PUNCT|MSVCRT__ALPHA },
558 { "lower", MSVCRT__LOWER },
559 { "print", MSVCRT__DIGIT|MSVCRT__PUNCT|MSVCRT__BLANK|MSVCRT__ALPHA },
560 { "punct", MSVCRT__PUNCT },
561 { "space", MSVCRT__SPACE },
562 { "upper", MSVCRT__UPPER },
563 { "xdigit", MSVCRT__HEX }
565 unsigned int i;
567 for(i=0; i<ARRAY_SIZE(properties); i++)
568 if(!strcmp(property, properties[i].name))
569 return properties[i].mask;
571 return 0;
573 #endif