user32: Add call frame annotations in x86 assembly code.
[wine] / dlls / user32 / lstr.c
1 /*
2  * USER string functions
3  *
4  * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5  * Copyright 1996 Alexandre Julliard
6  * Copyright 1996 Marcus Meissner
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <ctype.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winuser.h"
35 #include "winerror.h"
36
37 #include "wine/exception.h"
38 #include "wine/unicode.h"
39
40
41 /***********************************************************************
42  *           CharNextA   (USER32.@)
43  */
44 LPSTR WINAPI CharNextA( LPCSTR ptr )
45 {
46     if (!*ptr) return (LPSTR)ptr;
47     if (IsDBCSLeadByte( ptr[0] ) && ptr[1]) return (LPSTR)(ptr + 2);
48     return (LPSTR)(ptr + 1);
49 }
50
51
52 /***********************************************************************
53  *           CharNextExA   (USER32.@)
54  */
55 LPSTR WINAPI CharNextExA( WORD codepage, LPCSTR ptr, DWORD flags )
56 {
57     if (!*ptr) return (LPSTR)ptr;
58     if (IsDBCSLeadByteEx( codepage, ptr[0] ) && ptr[1]) return (LPSTR)(ptr + 2);
59     return (LPSTR)(ptr + 1);
60 }
61
62
63 /***********************************************************************
64  *           CharNextExW   (USER32.@)
65  */
66 LPWSTR WINAPI CharNextExW( WORD codepage, LPCWSTR ptr, DWORD flags )
67 {
68     /* doesn't make sense, there are no codepages for Unicode */
69     return NULL;
70 }
71
72
73 /***********************************************************************
74  *           CharNextW   (USER32.@)
75  */
76 LPWSTR WINAPI CharNextW(LPCWSTR x)
77 {
78     if (*x) x++;
79
80     return (LPWSTR)x;
81 }
82
83
84 /***********************************************************************
85  *           CharPrevA   (USER32.@)
86  */
87 LPSTR WINAPI CharPrevA( LPCSTR start, LPCSTR ptr )
88 {
89     while (*start && (start < ptr))
90     {
91         LPCSTR next = CharNextA( start );
92         if (next >= ptr) break;
93         start = next;
94     }
95     return (LPSTR)start;
96 }
97
98
99 /***********************************************************************
100  *           CharPrevExA   (USER32.@)
101  */
102 LPSTR WINAPI CharPrevExA( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
103 {
104     while (*start && (start < ptr))
105     {
106         LPCSTR next = CharNextExA( codepage, start, flags );
107         if (next >= ptr) break;
108         start = next;
109     }
110     return (LPSTR)start;
111 }
112
113
114 /***********************************************************************
115  *           CharPrevExW   (USER32.@)
116  */
117 LPSTR WINAPI CharPrevExW( WORD codepage, LPCWSTR start, LPCWSTR ptr, DWORD flags )
118 {
119     /* doesn't make sense, there are no codepages for Unicode */
120     return NULL;
121 }
122
123
124 /***********************************************************************
125  *           CharPrevW   (USER32.@)
126  */
127 LPWSTR WINAPI CharPrevW(LPCWSTR start,LPCWSTR x)
128 {
129     if (x>start) return (LPWSTR)(x-1);
130     else return (LPWSTR)x;
131 }
132
133
134 /***********************************************************************
135  *           CharToOemA   (USER32.@)
136  */
137 BOOL WINAPI CharToOemA( LPCSTR s, LPSTR d )
138 {
139     if ( !s || !d ) return TRUE;
140     return CharToOemBuffA( s, d, strlen( s ) + 1 );
141 }
142
143
144 /***********************************************************************
145  *           CharToOemBuffA   (USER32.@)
146  */
147 BOOL WINAPI CharToOemBuffA( LPCSTR s, LPSTR d, DWORD len )
148 {
149     WCHAR *bufW;
150
151     bufW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
152     if( bufW )
153     {
154         MultiByteToWideChar( CP_ACP, 0, s, len, bufW, len );
155         WideCharToMultiByte( CP_OEMCP, 0, bufW, len, d, len, NULL, NULL );
156         HeapFree( GetProcessHeap(), 0, bufW );
157     }
158     return TRUE;
159 }
160
161
162 /***********************************************************************
163  *           CharToOemBuffW   (USER32.@)
164  */
165 BOOL WINAPI CharToOemBuffW( LPCWSTR s, LPSTR d, DWORD len )
166 {
167    if ( !s || !d ) return TRUE;
168     WideCharToMultiByte( CP_OEMCP, 0, s, len, d, len, NULL, NULL );
169     return TRUE;
170 }
171
172
173 /***********************************************************************
174  *           CharToOemW   (USER32.@)
175  */
176 BOOL WINAPI CharToOemW( LPCWSTR s, LPSTR d )
177 {
178     return CharToOemBuffW( s, d, strlenW( s ) + 1 );
179 }
180
181
182 /***********************************************************************
183  *           OemToCharA   (USER32.@)
184  */
185 BOOL WINAPI OemToCharA( LPCSTR s, LPSTR d )
186 {
187     return OemToCharBuffA( s, d, strlen( s ) + 1 );
188 }
189
190
191 /***********************************************************************
192  *           OemToCharBuffA   (USER32.@)
193  */
194 BOOL WINAPI OemToCharBuffA( LPCSTR s, LPSTR d, DWORD len )
195 {
196     WCHAR *bufW;
197
198     bufW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
199     if( bufW )
200     {
201         MultiByteToWideChar( CP_OEMCP, 0, s, len, bufW, len );
202         WideCharToMultiByte( CP_ACP, 0, bufW, len, d, len, NULL, NULL );
203         HeapFree( GetProcessHeap(), 0, bufW );
204     }
205     return TRUE;
206 }
207
208
209 /***********************************************************************
210  *           OemToCharBuffW   (USER32.@)
211  */
212 BOOL WINAPI OemToCharBuffW( LPCSTR s, LPWSTR d, DWORD len )
213 {
214     MultiByteToWideChar( CP_OEMCP, 0, s, len, d, len );
215     return TRUE;
216 }
217
218
219 /***********************************************************************
220  *           OemToCharW   (USER32.@)
221  */
222 BOOL WINAPI OemToCharW( LPCSTR s, LPWSTR d )
223 {
224     return OemToCharBuffW( s, d, strlen( s ) + 1 );
225 }
226
227
228 /***********************************************************************
229  *           CharLowerA   (USER32.@)
230  */
231 LPSTR WINAPI CharLowerA(LPSTR str)
232 {
233     if (!HIWORD(str))
234     {
235         char ch = LOWORD(str);
236         CharLowerBuffA( &ch, 1 );
237         return (LPSTR)(UINT_PTR)(BYTE)ch;
238     }
239
240     __TRY
241     {
242         CharLowerBuffA( str, strlen(str) );
243     }
244     __EXCEPT_PAGE_FAULT
245     {
246         SetLastError( ERROR_INVALID_PARAMETER );
247         return NULL;
248     }
249     __ENDTRY
250     return str;
251 }
252
253
254 /***********************************************************************
255  *           CharUpperA   (USER32.@)
256  */
257 LPSTR WINAPI CharUpperA(LPSTR str)
258 {
259     if (!HIWORD(str))
260     {
261         char ch = LOWORD(str);
262         CharUpperBuffA( &ch, 1 );
263         return (LPSTR)(UINT_PTR)(BYTE)ch;
264     }
265
266     __TRY
267     {
268         CharUpperBuffA( str, strlen(str) );
269     }
270     __EXCEPT_PAGE_FAULT
271     {
272         SetLastError( ERROR_INVALID_PARAMETER );
273         return NULL;
274     }
275     __ENDTRY
276     return str;
277 }
278
279
280 /***********************************************************************
281  *           CharLowerW   (USER32.@)
282  */
283 LPWSTR WINAPI CharLowerW(LPWSTR x)
284 {
285     if (HIWORD(x)) return strlwrW(x);
286     else return (LPWSTR)((UINT_PTR)tolowerW(LOWORD(x)));
287 }
288
289
290 /***********************************************************************
291  *           CharUpperW   (USER32.@)
292  */
293 LPWSTR WINAPI CharUpperW(LPWSTR x)
294 {
295     if (HIWORD(x)) return struprW(x);
296     else return (LPWSTR)((UINT_PTR)toupperW(LOWORD(x)));
297 }
298
299
300 /***********************************************************************
301  *           CharLowerBuffA   (USER32.@)
302  */
303 DWORD WINAPI CharLowerBuffA( LPSTR str, DWORD len )
304 {
305     DWORD lenW;
306     WCHAR buffer[32];
307     WCHAR *strW = buffer;
308
309     if (!str) return 0; /* YES */
310
311     lenW = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0);
312     if (lenW > sizeof(buffer)/sizeof(WCHAR))
313     {
314         strW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
315         if (!strW) return 0;
316     }
317     MultiByteToWideChar(CP_ACP, 0, str, len, strW, lenW);
318     CharLowerBuffW(strW, lenW);
319     len = WideCharToMultiByte(CP_ACP, 0, strW, lenW, str, len, NULL, NULL);
320     if (strW != buffer) HeapFree(GetProcessHeap(), 0, strW);
321     return len;
322 }
323
324
325 /***********************************************************************
326  *           CharLowerBuffW   (USER32.@)
327  */
328 DWORD WINAPI CharLowerBuffW( LPWSTR str, DWORD len )
329 {
330     DWORD ret = len;
331     if (!str) return 0; /* YES */
332     for (; len; len--, str++) *str = tolowerW(*str);
333     return ret;
334 }
335
336
337 /***********************************************************************
338  *           CharUpperBuffA   (USER32.@)
339  */
340 DWORD WINAPI CharUpperBuffA( LPSTR str, DWORD len )
341 {
342     DWORD lenW;
343     WCHAR buffer[32];
344     WCHAR *strW = buffer;
345
346     if (!str) return 0; /* YES */
347
348     lenW = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0);
349     if (lenW > sizeof(buffer)/sizeof(WCHAR))
350     {
351         strW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
352         if (!strW) return 0;
353     }
354     MultiByteToWideChar(CP_ACP, 0, str, len, strW, lenW);
355     CharUpperBuffW(strW, lenW);
356     len = WideCharToMultiByte(CP_ACP, 0, strW, lenW, str, len, NULL, NULL);
357     if (strW != buffer) HeapFree(GetProcessHeap(), 0, strW);
358     return len;
359 }
360
361
362 /***********************************************************************
363  *           CharUpperBuffW   (USER32.@)
364  */
365 DWORD WINAPI CharUpperBuffW( LPWSTR str, DWORD len )
366 {
367     DWORD ret = len;
368     if (!str) return 0; /* YES */
369     for (; len; len--, str++) *str = toupperW(*str);
370     return ret;
371 }
372
373
374 /***********************************************************************
375  *           IsCharLower    (USER.436)
376  *           IsCharLowerA   (USER32.@)
377  */
378 BOOL WINAPI IsCharLowerA(CHAR x)
379 {
380     WCHAR wch;
381     MultiByteToWideChar(CP_ACP, 0, &x, 1, &wch, 1);
382     return IsCharLowerW(wch);
383 }
384
385
386 /***********************************************************************
387  *           IsCharLowerW   (USER32.@)
388  */
389 BOOL WINAPI IsCharLowerW(WCHAR x)
390 {
391     return (get_char_typeW(x) & C1_LOWER) != 0;
392 }
393
394
395 /***********************************************************************
396  *           IsCharUpper    (USER.435)
397  *           IsCharUpperA   (USER32.@)
398  */
399 BOOL WINAPI IsCharUpperA(CHAR x)
400 {
401     WCHAR wch;
402     MultiByteToWideChar(CP_ACP, 0, &x, 1, &wch, 1);
403     return IsCharUpperW(wch);
404 }
405
406
407 /***********************************************************************
408  *           IsCharUpperW   (USER32.@)
409  */
410 BOOL WINAPI IsCharUpperW(WCHAR x)
411 {
412     return (get_char_typeW(x) & C1_UPPER) != 0;
413 }
414
415
416 /***********************************************************************
417  *           IsCharAlphaNumeric    (USER.434)
418  *           IsCharAlphaNumericA   (USER32.@)
419  */
420 BOOL WINAPI IsCharAlphaNumericA(CHAR x)
421 {
422     WCHAR wch;
423     MultiByteToWideChar(CP_ACP, 0, &x, 1, &wch, 1);
424     return IsCharAlphaNumericW(wch);
425 }
426
427
428 /***********************************************************************
429  *           IsCharAlphaNumericW   (USER32.@)
430  */
431 BOOL WINAPI IsCharAlphaNumericW(WCHAR x)
432 {
433     return (get_char_typeW(x) & (C1_ALPHA|C1_DIGIT)) != 0;
434 }
435
436
437 /***********************************************************************
438  *           IsCharAlpha    (USER.433)
439  *           IsCharAlphaA   (USER32.@)
440  */
441 BOOL WINAPI IsCharAlphaA(CHAR x)
442 {
443     WCHAR wch;
444     MultiByteToWideChar(CP_ACP, 0, &x, 1, &wch, 1);
445     return IsCharAlphaW(wch);
446 }
447
448
449 /***********************************************************************
450  *           IsCharAlphaW   (USER32.@)
451  */
452 BOOL WINAPI IsCharAlphaW(WCHAR x)
453 {
454     return (get_char_typeW(x) & C1_ALPHA) != 0;
455 }