kernelbase: Reimplement LOCALE_*CTRYNAME in GetLocaleInfoW/Ex using the locale.nls...
[wine.git] / dlls / msvcrt / ctype.c
blob5a7d3450edab9c6b5c6da3a7861925493b42a04f
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 <locale.h>
22 #include "msvcrt.h"
23 #include "winnls.h"
25 /* Some abbreviations to make the following table readable */
26 #define _C_ _CONTROL
27 #define _S_ _SPACE
28 #define _P_ _PUNCT
29 #define _D_ _DIGIT
30 #define _H_ _HEX
31 #define _U_ _UPPER
32 #define _L_ _LOWER
34 WORD MSVCRT__ctype [257] = {
35 0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_,
36 _S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_,
37 _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_BLANK,
38 _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_,
39 _P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_,
40 _D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_,
41 _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_,
42 _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_,
43 _U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_,
44 _L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_,
45 _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_,
46 _C_, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
54 #if _MSVCR_VER <= 110
55 # define B110 _BLANK
56 #else
57 # define B110 0
58 #endif
60 #if _MSVCR_VER == 120
61 # define D120 0
62 #else
63 # define D120 4
64 #endif
66 #if _MSVCR_VER >= 140
67 # define S140 _SPACE
68 # define L140 _LOWER | 0x100
69 # define C140 _CONTROL
70 #else
71 # define S140 0
72 # define L140 0
73 # define C140 0
74 #endif
75 WORD MSVCRT__wctype[257] =
78 /* 00 */
79 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
80 0x0020, 0x0028 | B110, 0x0028, 0x0028, 0x0028, 0x0028, 0x0020, 0x0020,
81 /* 10 */
82 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
83 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
84 /* 20 */
85 0x0048, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
86 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
87 /* 30 */
88 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
89 0x0084, 0x0084, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
90 /* 40 */
91 0x0010, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0101,
92 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
93 /* 50 */
94 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
95 0x0101, 0x0101, 0x0101, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
96 /* 60 */
97 0x0010, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0102,
98 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
99 /* 70 */
100 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
101 0x0102, 0x0102, 0x0102, 0x0010, 0x0010, 0x0010, 0x0010, 0x0020,
102 /* 80 */
103 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 | S140, 0x0020, 0x0020,
104 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
105 /* 90 */
106 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
107 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
108 /* a0 */
109 0x0008 | B110, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
110 0x0010, 0x0010, 0x0010 | L140, 0x0010, 0x0010, 0x0010 | C140, 0x0010, 0x0010,
111 /* b0 */
112 0x0010, 0x0010, 0x0010 | D120, 0x0010 | D120, 0x0010, 0x0010 | L140, 0x0010, 0x0010,
113 0x0010, 0x0010 | D120, 0x0010 | L140, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
114 /* c0 */
115 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
116 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
117 /* d0 */
118 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0010,
119 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0102,
120 /* e0 */
121 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
122 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
123 /* f0 */
124 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0010,
125 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102
128 WORD *MSVCRT__pwctype = MSVCRT__wctype + 1;
130 /*********************************************************************
131 * __p__pctype (MSVCRT.@)
133 unsigned short** CDECL __p__pctype(void)
135 return &get_locinfo()->pctype;
138 /*********************************************************************
139 * __pctype_func (MSVCRT.@)
141 const unsigned short* CDECL __pctype_func(void)
143 return get_locinfo()->pctype;
146 /*********************************************************************
147 * __p__pwctype (MSVCRT.@)
149 unsigned short** CDECL __p__pwctype(void)
151 return &MSVCRT__pwctype;
154 /*********************************************************************
155 * __pwctype_func (MSVCRT.@)
157 const unsigned short* CDECL __pwctype_func(void)
159 return MSVCRT__pwctype;
162 /*********************************************************************
163 * _isctype_l (MSVCRT.@)
165 int CDECL _isctype_l(int c, int type, _locale_t locale)
167 pthreadlocinfo locinfo;
169 if(!locale)
170 locinfo = get_locinfo();
171 else
172 locinfo = locale->locinfo;
174 if (c >= -1 && c <= 255)
175 return locinfo->pctype[c] & type;
177 if (locinfo->mb_cur_max != 1 && c > 0)
179 /* FIXME: Is there a faster way to do this? */
180 WORD typeInfo;
181 char convert[3], *pconv = convert;
183 if (locinfo->pctype[(UINT)c >> 8] & _LEADBYTE)
184 *pconv++ = (UINT)c >> 8;
185 *pconv++ = c & 0xff;
186 *pconv = 0;
188 if (GetStringTypeExA(locinfo->lc_handle[LC_CTYPE],
189 CT_CTYPE1, convert, convert[1] ? 2 : 1, &typeInfo))
190 return typeInfo & type;
192 return 0;
195 /*********************************************************************
196 * _isctype (MSVCRT.@)
198 int CDECL _isctype(int c, int type)
200 return _isctype_l(c, type, NULL);
203 /*********************************************************************
204 * _isalnum_l (MSVCRT.@)
206 int CDECL _isalnum_l(int c, _locale_t locale)
208 return _isctype_l( c, _ALPHA | _DIGIT, locale );
211 /*********************************************************************
212 * isalnum (MSVCRT.@)
214 int CDECL isalnum(int c)
216 return _isctype( c, _ALPHA | _DIGIT );
219 /*********************************************************************
220 * _isalpha_l (MSVCRT.@)
222 int CDECL _isalpha_l(int c, _locale_t locale)
224 return _isctype_l( c, _ALPHA, locale );
227 /*********************************************************************
228 * isalpha (MSVCRT.@)
230 int CDECL isalpha(int c)
232 return _isctype( c, _ALPHA );
235 /*********************************************************************
236 * _iscntrl_l (MSVCRT.@)
238 int CDECL _iscntrl_l(int c, _locale_t locale)
240 return _isctype_l( c, _CONTROL, locale );
243 /*********************************************************************
244 * iscntrl (MSVCRT.@)
246 int CDECL iscntrl(int c)
248 return _isctype( c, _CONTROL );
251 /*********************************************************************
252 * _isdigit_l (MSVCRT.@)
254 int CDECL _isdigit_l(int c, _locale_t locale)
256 return _isctype_l( c, _DIGIT, locale );
259 /*********************************************************************
260 * isdigit (MSVCRT.@)
262 int CDECL isdigit(int c)
264 return _isctype( c, _DIGIT );
267 /*********************************************************************
268 * _isgraph_l (MSVCRT.@)
270 int CDECL _isgraph_l(int c, _locale_t locale)
272 return _isctype_l( c, _ALPHA | _DIGIT | _PUNCT, locale );
275 /*********************************************************************
276 * isgraph (MSVCRT.@)
278 int CDECL isgraph(int c)
280 return _isctype( c, _ALPHA | _DIGIT | _PUNCT );
283 /*********************************************************************
284 * _isleadbyte_l (MSVCRT.@)
286 int CDECL _isleadbyte_l(int c, _locale_t locale)
288 return _isctype_l( c, _LEADBYTE, locale );
291 /*********************************************************************
292 * isleadbyte (MSVCRT.@)
294 int CDECL isleadbyte(int c)
296 return _isctype( c, _LEADBYTE );
299 /*********************************************************************
300 * _islower_l (MSVCRT.@)
302 int CDECL _islower_l(int c, _locale_t locale)
304 return _isctype_l( c, _LOWER, locale );
307 /*********************************************************************
308 * islower (MSVCRT.@)
310 int CDECL islower(int c)
312 return _isctype( c, _LOWER );
315 /*********************************************************************
316 * _isprint_l (MSVCRT.@)
318 int CDECL _isprint_l(int c, _locale_t locale)
320 return _isctype_l( c, _ALPHA | _DIGIT | _BLANK | _PUNCT, locale );
323 /*********************************************************************
324 * isprint (MSVCRT.@)
326 int CDECL isprint(int c)
328 return _isctype( c, _ALPHA | _DIGIT | _BLANK | _PUNCT );
331 /*********************************************************************
332 * ispunct (MSVCRT.@)
334 int CDECL ispunct(int c)
336 return _isctype( c, _PUNCT );
339 /*********************************************************************
340 * _ispunct_l (MSVCR80.@)
342 int CDECL _ispunct_l(int c, _locale_t locale)
344 return _isctype_l( c, _PUNCT, locale );
347 /*********************************************************************
348 * _isspace_l (MSVCRT.@)
350 int CDECL _isspace_l(int c, _locale_t locale)
352 return _isctype_l( c, _SPACE, locale );
355 /*********************************************************************
356 * isspace (MSVCRT.@)
358 int CDECL isspace(int c)
360 return _isctype( c, _SPACE );
363 /*********************************************************************
364 * _isupper_l (MSVCRT.@)
366 int CDECL _isupper_l(int c, _locale_t locale)
368 return _isctype_l( c, _UPPER, locale );
371 /*********************************************************************
372 * isupper (MSVCRT.@)
374 int CDECL isupper(int c)
376 return _isctype( c, _UPPER );
379 /*********************************************************************
380 * _isxdigit_l (MSVCRT.@)
382 int CDECL _isxdigit_l(int c, _locale_t locale)
384 return _isctype_l( c, _HEX, locale );
387 /*********************************************************************
388 * isxdigit (MSVCRT.@)
390 int CDECL isxdigit(int c)
392 return _isctype( c, _HEX );
395 /*********************************************************************
396 * _isblank_l (MSVCRT.@)
398 int CDECL _isblank_l(int c, _locale_t locale)
400 #if _MSVCR_VER < 140
401 if (c == '\t') return _BLANK;
402 #endif
403 return _isctype_l( c, _BLANK, locale );
406 /*********************************************************************
407 * isblank (MSVCRT.@)
409 int CDECL isblank(int c)
411 return c == '\t' || _isctype( c, _BLANK );
414 /*********************************************************************
415 * __isascii (MSVCRT.@)
417 int CDECL __isascii(int c)
419 return ((unsigned)c < 0x80);
422 /*********************************************************************
423 * __toascii (MSVCRT.@)
425 int CDECL __toascii(int c)
427 return (unsigned)c & 0x7f;
430 /*********************************************************************
431 * iswascii (MSVCRT.@)
434 int CDECL iswascii(wchar_t c)
436 return ((unsigned)c < 0x80);
439 /*********************************************************************
440 * __iscsym (MSVCRT.@)
442 int CDECL __iscsym(int c)
444 return (c < 127 && (isalnum(c) || c == '_'));
447 /*********************************************************************
448 * __iscsymf (MSVCRT.@)
450 int CDECL __iscsymf(int c)
452 return (c < 127 && (isalpha(c) || c == '_'));
455 /*********************************************************************
456 * _toupper_l (MSVCRT.@)
458 int CDECL _toupper_l(int c, _locale_t locale)
460 pthreadlocinfo locinfo;
461 unsigned char str[2], *p = str, ret[2];
463 if(!locale)
464 locinfo = get_locinfo();
465 else
466 locinfo = locale->locinfo;
468 if((unsigned)c < 256)
469 return locinfo->pcumap[c];
471 if(locinfo->pctype[(c>>8)&255] & _LEADBYTE)
472 *p++ = (c>>8) & 255;
473 else {
474 *_errno() = EILSEQ;
475 str[1] = 0;
477 *p++ = c & 255;
479 switch(__crtLCMapStringA(locinfo->lc_handle[LC_CTYPE], LCMAP_UPPERCASE,
480 (char*)str, p-str, (char*)ret, 2, locinfo->lc_codepage, 0))
482 case 0:
483 return c;
484 case 1:
485 return ret[0];
486 default:
487 return ret[0] + (ret[1]<<8);
491 /*********************************************************************
492 * toupper (MSVCRT.@)
494 int CDECL toupper(int c)
496 if(initial_locale)
497 return c>='a' && c<='z' ? c-'a'+'A' : c;
498 return _toupper_l(c, NULL);
501 /*********************************************************************
502 * _toupper (MSVCRT.@)
504 int CDECL _toupper(int c)
506 return c - 0x20; /* sic */
509 /*********************************************************************
510 * _tolower_l (MSVCRT.@)
512 int CDECL _tolower_l(int c, _locale_t locale)
514 pthreadlocinfo locinfo;
515 unsigned char str[2], *p = str, ret[2];
517 if(!locale)
518 locinfo = get_locinfo();
519 else
520 locinfo = locale->locinfo;
522 if((unsigned)c < 256)
523 return locinfo->pclmap[c];
525 if(locinfo->pctype[(c>>8)&255] & _LEADBYTE)
526 *p++ = (c>>8) & 255;
527 else {
528 *_errno() = EILSEQ;
529 str[1] = 0;
531 *p++ = c & 255;
533 switch(__crtLCMapStringA(locinfo->lc_handle[LC_CTYPE], LCMAP_LOWERCASE,
534 (char*)str, p-str, (char*)ret, 2, locinfo->lc_codepage, 0))
536 case 0:
537 return c;
538 case 1:
539 return ret[0];
540 default:
541 return ret[0] + (ret[1]<<8);
545 /*********************************************************************
546 * tolower (MSVCRT.@)
548 int CDECL tolower(int c)
550 if(initial_locale)
551 return c>='A' && c<='Z' ? c-'A'+'a' : c;
552 return _tolower_l(c, NULL);
555 /*********************************************************************
556 * _tolower (MSVCRT.@)
558 int CDECL _tolower(int c)
560 return c + 0x20; /* sic */
563 #if _MSVCR_VER>=120
564 /*********************************************************************
565 * wctype (MSVCR120.@)
567 unsigned short __cdecl wctype(const char *property)
569 static const struct {
570 const char *name;
571 unsigned short mask;
572 } properties[] = {
573 { "alnum", _DIGIT|_ALPHA },
574 { "alpha", _ALPHA },
575 { "cntrl", _CONTROL },
576 { "digit", _DIGIT },
577 { "graph", _DIGIT|_PUNCT|_ALPHA },
578 { "lower", _LOWER },
579 { "print", _DIGIT|_PUNCT|_BLANK|_ALPHA },
580 { "punct", _PUNCT },
581 { "space", _SPACE },
582 { "upper", _UPPER },
583 { "xdigit", _HEX }
585 unsigned int i;
587 for(i=0; i<ARRAY_SIZE(properties); i++)
588 if(!strcmp(property, properties[i].name))
589 return properties[i].mask;
591 return 0;
593 #endif