Winspool DocumentProperties and DeviceCapabilities should now work on
[wine.git] / memory / string.c
bloba90621a15ec4e6ca412f7276015cd416c8f1e52d
1 /*
2 * String functions
4 * Copyright 1993 Yngvi Sigurjonsson
5 * Copyright 1996 Alexandre Julliard
6 */
8 #include <ctype.h>
9 #include <string.h>
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "winbase.h"
14 #include "winuser.h"
15 #include "wine/keyboard16.h"
16 #include "wine/exception.h"
17 #include "winerror.h"
18 #include "crtdll.h"
19 #include "ldt.h"
20 #include "debugtools.h"
21 #include "winnls.h"
23 DEFAULT_DEBUG_CHANNEL(string)
25 static const BYTE STRING_Oem2Ansi[256] =
26 "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\244"
27 "\020\021\022\023\266\247\026\027\030\031\032\033\034\035\036\037"
28 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
29 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
30 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
31 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
32 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
33 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
34 "\307\374\351\342\344\340\345\347\352\353\350\357\356\354\304\305"
35 "\311\346\306\364\366\362\373\371\377\326\334\242\243\245\120\203"
36 "\341\355\363\372\361\321\252\272\277\137\254\275\274\241\253\273"
37 "\137\137\137\246\246\246\246\053\053\246\246\053\053\053\053\053"
38 "\053\055\055\053\055\053\246\246\053\053\055\055\246\055\053\055"
39 "\055\055\055\053\053\053\053\053\053\053\053\137\137\246\137\137"
40 "\137\337\137\266\137\137\265\137\137\137\137\137\137\137\137\137"
41 "\137\261\137\137\137\137\367\137\260\225\267\137\156\262\137\137";
43 static const BYTE STRING_Ansi2Oem[256] =
44 "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
45 "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
46 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
47 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
48 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
49 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
50 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
51 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
52 "\200\201\054\237\054\137\375\374\210\045\123\074\117\215\216\217"
53 "\220\140\047\042\042\371\055\137\230\231\163\076\157\235\236\131"
54 "\040\255\233\234\017\235\335\025\042\143\246\256\252\055\162\137"
55 "\370\361\375\063\047\346\024\372\054\061\247\257\254\253\137\250"
56 "\101\101\101\101\216\217\222\200\105\220\105\105\111\111\111\111"
57 "\104\245\117\117\117\117\231\170\117\125\125\125\232\131\137\341"
58 "\205\240\203\141\204\206\221\207\212\202\210\211\215\241\214\213"
59 "\144\244\225\242\223\157\224\366\157\227\243\226\201\171\137\230";
61 #define OEM_TO_ANSI(ch) (STRING_Oem2Ansi[(unsigned char)(ch)])
62 #define ANSI_TO_OEM(ch) (STRING_Ansi2Oem[(unsigned char)(ch)])
64 /* Internaly used by strchr family functions */
65 static BOOL ChrCmpA( WORD word1, WORD word2);
68 /* filter for page-fault exceptions */
69 static WINE_EXCEPTION_FILTER(page_fault)
71 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
72 return EXCEPTION_EXECUTE_HANDLER;
73 return EXCEPTION_CONTINUE_SEARCH;
77 /***********************************************************************
78 * hmemcpy (KERNEL.348)
80 void WINAPI hmemcpy16( LPVOID dst, LPCVOID src, LONG count )
82 memcpy( dst, src, count );
86 /***********************************************************************
87 * lstrcat16 (KERNEL.89)
89 SEGPTR WINAPI lstrcat16( SEGPTR dst, LPCSTR src )
91 /* Windows does not check for NULL pointers here, so we don't either */
92 strcat( (LPSTR)PTR_SEG_TO_LIN(dst), src );
93 return dst;
97 /***********************************************************************
98 * lstrcatA (KERNEL32.599)
100 LPSTR WINAPI lstrcatA( LPSTR dst, LPCSTR src )
102 __TRY
104 strcat( dst, src );
106 __EXCEPT(page_fault)
108 SetLastError( ERROR_INVALID_PARAMETER );
109 return NULL;
111 __ENDTRY
112 return dst;
116 /***********************************************************************
117 * lstrcatW (KERNEL32.600)
119 LPWSTR WINAPI lstrcatW( LPWSTR dst, LPCWSTR src )
121 __TRY
123 CRTDLL_wcscat( dst, src );
125 __EXCEPT(page_fault)
127 SetLastError( ERROR_INVALID_PARAMETER );
128 return NULL;
130 __ENDTRY
131 return dst;
135 /***********************************************************************
136 * lstrcatn16 (KERNEL.352)
138 SEGPTR WINAPI lstrcatn16( SEGPTR dst, LPCSTR src, INT16 n )
140 LPSTR p = (LPSTR)PTR_SEG_TO_LIN(dst);
142 while (*p) p++;
143 if ((n -= (p - (LPSTR)PTR_SEG_TO_LIN(dst))) <= 0) return dst;
144 lstrcpynA( p, src, n );
145 return dst;
149 /***********************************************************************
150 * lstrcmp16 (USER.430)
152 INT16 WINAPI lstrcmp16( LPCSTR str1, LPCSTR str2 )
154 return (INT16)strcmp( str1, str2 );
158 /***********************************************************************
159 * lstrcmp32A (KERNEL.602)
161 INT WINAPI lstrcmpA( LPCSTR str1, LPCSTR str2 )
163 return CompareStringA(LOCALE_SYSTEM_DEFAULT,0,str1,-1,str2,-1) - 2 ;
167 /***********************************************************************
168 * lstrcmp32W (KERNEL.603)
169 * FIXME : should call CompareString32W, when it is implemented.
170 * This implementation is not "word sort", as it should.
172 INT WINAPI lstrcmpW( LPCWSTR str1, LPCWSTR str2 )
174 TRACE("L%s and L%s\n",
175 debugstr_w (str1), debugstr_w (str2));
176 if (!str1 || !str2) {
177 SetLastError(ERROR_INVALID_PARAMETER);
178 return 0;
180 while (*str1 && (*str1 == *str2)) { str1++; str2++; }
181 return (INT)(*str1 - *str2);
185 /***********************************************************************
186 * lstrcmpi16 (USER.471)
188 INT16 WINAPI lstrcmpi16( LPCSTR str1, LPCSTR str2 )
190 return (INT16)lstrcmpiA( str1, str2 );
194 /***********************************************************************
195 * lstrcmpi32A (KERNEL32.605)
197 INT WINAPI lstrcmpiA( LPCSTR str1, LPCSTR str2 )
198 { TRACE("strcmpi %s and %s\n",
199 debugstr_a (str1), debugstr_a (str2));
200 return CompareStringA(LOCALE_SYSTEM_DEFAULT,NORM_IGNORECASE,str1,-1,str2,-1)-2;
204 /***********************************************************************
205 * lstrcmpi32W (KERNEL32.606)
207 INT WINAPI lstrcmpiW( LPCWSTR str1, LPCWSTR str2 )
209 INT res;
211 #if 0
212 /* Too much! (From registry loading.) */
213 TRACE("strcmpi L%s and L%s\n",
214 debugstr_w (str1), debugstr_w (str2));
215 #endif
216 if (!str1 || !str2) {
217 SetLastError(ERROR_INVALID_PARAMETER);
218 return 0;
220 while (*str1)
222 if ((*str1<0x100 ) && (*str2<0x100)) {
223 if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
224 } else {
225 if ((res = towupper(*str1) - towupper(*str2)) != 0) return res;
227 str1++;
228 str2++;
230 return towupper(*str1) - towupper(*str2);
234 /***********************************************************************
235 * lstrcpy16 (KERNEL.88)
237 SEGPTR WINAPI lstrcpy16( SEGPTR dst, LPCSTR src )
239 /* this is how Windows does it */
240 memmove( (LPSTR)PTR_SEG_TO_LIN(dst), src, strlen(src)+1 );
241 return dst;
245 /***********************************************************************
246 * lstrcpyA (KERNEL32.608)
248 LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src )
250 __TRY
252 /* this is how Windows does it */
253 memmove( dst, src, strlen(src)+1 );
255 __EXCEPT(page_fault)
257 SetLastError( ERROR_INVALID_PARAMETER );
258 return NULL;
260 __ENDTRY
261 return dst;
265 /***********************************************************************
266 * lstrcpyW (KERNEL32.609)
268 LPWSTR WINAPI lstrcpyW( LPWSTR dst, LPCWSTR src )
270 __TRY
272 CRTDLL_wcscpy( dst, src );
274 __EXCEPT(page_fault)
276 SetLastError( ERROR_INVALID_PARAMETER );
277 return NULL;
279 __ENDTRY
280 return dst;
284 /***********************************************************************
285 * lstrcpyn16 (KERNEL.353)
287 SEGPTR WINAPI lstrcpyn16( SEGPTR dst, LPCSTR src, INT16 n )
289 lstrcpynA( (LPSTR)PTR_SEG_TO_LIN(dst), src, n );
290 return dst;
294 /***********************************************************************
295 * lstrcpyn32A (KERNEL32.611)
296 * Note: this function differs from the UNIX strncpy, it _always_ writes
297 * a terminating \0
299 LPSTR WINAPI lstrcpynA( LPSTR dst, LPCSTR src, INT n )
301 LPSTR p = dst;
302 TRACE("strcpyn %s for %d chars\n",
303 debugstr_an (src,n), n);
304 /* In real windows the whole function is protected by an exception handler
305 * that returns ERROR_INVALID_PARAMETER on faulty parameters
306 * We currently just check for NULL.
308 if (!dst || !src) {
309 SetLastError(ERROR_INVALID_PARAMETER);
310 return 0;
312 while ((n-- > 1) && *src) *p++ = *src++;
313 if (n >= 0) *p = 0;
314 return dst;
318 /***********************************************************************
319 * lstrcpyn32W (KERNEL32.612)
320 * Note: this function differs from the UNIX strncpy, it _always_ writes
321 * a terminating \0
323 LPWSTR WINAPI lstrcpynW( LPWSTR dst, LPCWSTR src, INT n )
325 LPWSTR p = dst;
326 TRACE("strcpyn L%s for %d chars\n",
327 debugstr_wn (src,n), n);
328 /* In real windows the whole function is protected by an exception handler
329 * that returns ERROR_INVALID_PARAMETER on faulty parameters
330 * We currently just check for NULL.
332 if (!dst || !src) {
333 SetLastError(ERROR_INVALID_PARAMETER);
334 return 0;
336 while ((n-- > 1) && *src) *p++ = *src++;
337 if (n >= 0) *p = 0;
338 return dst;
342 /***********************************************************************
343 * lstrlen16 (KERNEL.90)
345 INT16 WINAPI lstrlen16( LPCSTR str )
347 return (INT16)lstrlenA( str );
351 /***********************************************************************
352 * lstrlenA (KERNEL32.614)
354 INT WINAPI lstrlenA( LPCSTR str )
356 INT ret;
357 __TRY
359 ret = strlen(str);
361 __EXCEPT(page_fault)
363 SetLastError( ERROR_INVALID_PARAMETER );
364 return 0;
366 __ENDTRY
367 return ret;
371 /***********************************************************************
372 * lstrlenW (KERNEL32.615)
374 INT WINAPI lstrlenW( LPCWSTR str )
376 INT ret;
377 __TRY
379 ret = CRTDLL_wcslen(str);
381 __EXCEPT(page_fault)
383 SetLastError( ERROR_INVALID_PARAMETER );
384 return 0;
386 __ENDTRY
387 return ret;
391 /***********************************************************************
392 * lstrcpyAtoW (Not a Windows API)
394 LPWSTR WINAPI lstrcpyAtoW( LPWSTR dst, LPCSTR src )
396 register LPWSTR p = dst;
398 TRACE("%s\n",src);
400 while ((*p++ = (WCHAR)(unsigned char)*src++));
401 return dst;
405 /***********************************************************************
406 * lstrcpyWtoA (Not a Windows API)
408 LPSTR WINAPI lstrcpyWtoA( LPSTR dst, LPCWSTR src )
410 register LPSTR p = dst;
412 TRACE("L%s\n",debugstr_w(src));
414 while ((*p++ = (CHAR)*src++));
415 return dst;
419 /***********************************************************************
420 * lstrcpynAtoW (Not a Windows API)
421 * Note: this function differs from the UNIX strncpy, it _always_ writes
422 * a terminating \0
424 LPWSTR WINAPI lstrcpynAtoW( LPWSTR dst, LPCSTR src, INT n )
426 LPWSTR p = dst;
428 TRACE("%s %i\n",src, n);
430 while ((n-- > 1) && *src) *p++ = (WCHAR)(unsigned char)*src++;
431 if (n >= 0) *p = 0;
432 return dst;
436 /***********************************************************************
437 * lstrcpynWtoA (Not a Windows API)
438 * Note: this function differs from the UNIX strncpy, it _always_ writes
439 * a terminating \0
441 LPSTR WINAPI lstrcpynWtoA( LPSTR dst, LPCWSTR src, INT n )
443 if (--n >= 0)
445 CRTDLL_wcstombs( dst, src, n );
446 dst[n] = 0;
448 return dst;
451 /***********************************************************************
452 * UnicodeToAnsi (KERNEL.434)
454 INT16 WINAPI UnicodeToAnsi16( LPCWSTR src, LPSTR dst, INT16 codepage )
456 if ( codepage != -1 )
457 FIXME("codepage %d not supported\n", codepage );
459 lstrcpyWtoA( dst, src );
461 return (INT16)lstrlenA( dst );
465 /***********************************************************************
466 * Copy (GDI.250)
468 void WINAPI Copy16( LPVOID src, LPVOID dst, WORD size )
470 memcpy( dst, src, size );
474 /***********************************************************************
475 * RtlFillMemory (KERNEL32.441)
477 VOID WINAPI RtlFillMemory( LPVOID ptr, UINT len, UINT fill )
479 memset( ptr, fill, len );
483 /***********************************************************************
484 * RtlMoveMemory (KERNEL32.442)
486 VOID WINAPI RtlMoveMemory( LPVOID dst, LPCVOID src, UINT len )
488 memmove( dst, src, len );
492 /***********************************************************************
493 * RtlZeroMemory (KERNEL32.444)
495 VOID WINAPI RtlZeroMemory( LPVOID ptr, UINT len )
497 memset( ptr, 0, len );
501 /***********************************************************************
502 * AnsiToOem16 (KEYBOARD.5)
504 INT16 WINAPI AnsiToOem16( LPCSTR s, LPSTR d )
506 CharToOemA( s, d );
507 return -1;
511 /***********************************************************************
512 * OemToAnsi16 (KEYBOARD.6)
514 INT16 WINAPI OemToAnsi16( LPCSTR s, LPSTR d )
516 OemToCharA( s, d );
517 return -1;
521 /***********************************************************************
522 * AnsiToOemBuff16 (KEYBOARD.134)
524 void WINAPI AnsiToOemBuff16( LPCSTR s, LPSTR d, UINT16 len )
526 if (len != 0) CharToOemBuffA( s, d, len );
530 /***********************************************************************
531 * OemToAnsiBuff16 (KEYBOARD.135)
533 void WINAPI OemToAnsiBuff16( LPCSTR s, LPSTR d, UINT16 len )
535 if (len != 0) OemToCharBuffA( s, d, len );
539 /***********************************************************************
540 * CharToOem32A (USER32.37)
542 BOOL WINAPI CharToOemA( LPCSTR s, LPSTR d )
544 LPSTR oldd = d;
545 if (!s || !d) return TRUE;
546 TRACE("CharToOem %s\n", debugstr_a (s));
547 while ((*d++ = ANSI_TO_OEM(*s++)));
548 TRACE(" to %s\n", debugstr_a (oldd));
549 return TRUE;
553 /***********************************************************************
554 * CharToOemBuff32A (USER32.38)
556 BOOL WINAPI CharToOemBuffA( LPCSTR s, LPSTR d, DWORD len )
558 while (len--) *d++ = ANSI_TO_OEM(*s++);
559 return TRUE;
563 /***********************************************************************
564 * CharToOemBuff32W (USER32.39)
566 BOOL WINAPI CharToOemBuffW( LPCWSTR s, LPSTR d, DWORD len )
568 while (len--) *d++ = ANSI_TO_OEM(*s++);
569 return TRUE;
573 /***********************************************************************
574 * CharToOem32W (USER32.40)
576 BOOL WINAPI CharToOemW( LPCWSTR s, LPSTR d )
578 LPSTR oldd = d;
579 if (!s || !d) return TRUE;
580 TRACE("CharToOem L%s\n", debugstr_w (s));
581 while ((*d++ = ANSI_TO_OEM(*s++)));
582 TRACE(" to %s\n", debugstr_a (oldd));
583 return TRUE;
587 /***********************************************************************
588 * OemToChar32A (USER32.402)
590 BOOL WINAPI OemToCharA( LPCSTR s, LPSTR d )
592 LPSTR oldd = d;
593 TRACE("OemToChar %s\n", debugstr_a (s));
594 while ((*d++ = OEM_TO_ANSI(*s++)));
595 TRACE(" to %s\n", debugstr_a (oldd));
596 return TRUE;
600 /***********************************************************************
601 * OemToCharBuff32A (USER32.403)
603 BOOL WINAPI OemToCharBuffA( LPCSTR s, LPSTR d, DWORD len )
605 TRACE("OemToCharBuff %s\n", debugstr_an (s, len));
606 while (len--) *d++ = OEM_TO_ANSI(*s++);
607 return TRUE;
611 /***********************************************************************
612 * OemToCharBuff32W (USER32.404)
614 BOOL WINAPI OemToCharBuffW( LPCSTR s, LPWSTR d, DWORD len )
616 TRACE("OemToCharBuff %s\n", debugstr_an (s, len));
617 while (len--) *d++ = (WCHAR)OEM_TO_ANSI(*s++);
618 return TRUE;
622 /***********************************************************************
623 * OemToChar32W (USER32.405)
625 BOOL WINAPI OemToCharW( LPCSTR s, LPWSTR d )
627 while ((*d++ = (WCHAR)OEM_TO_ANSI(*s++)));
628 return TRUE;
631 /***********************************************************************
632 * WideCharToLocal (Not a Windows API)
633 * similar lstrcpyWtoA, should handle codepages properly
635 * RETURNS
636 * strlen of the destination string
639 INT WINAPI WideCharToLocal(
640 LPSTR pLocal,
641 LPWSTR pWide,
642 INT dwChars)
643 { *pLocal = 0;
644 TRACE("(%p, %s, %i)\n", pLocal, debugstr_w(pWide),dwChars);
645 WideCharToMultiByte(CP_ACP,0,pWide,-1,pLocal,dwChars,NULL,NULL);
646 return strlen(pLocal);
648 /***********************************************************************
649 * LocalToWideChar (Not a Windows API)
650 * similar lstrcpyAtoW, should handle codepages properly
652 * RETURNS
653 * strlen of the destination string
655 INT WINAPI LocalToWideChar(
656 LPWSTR pWide,
657 LPSTR pLocal,
658 INT dwChars)
659 { *pWide = 0;
660 TRACE("(%p, %s, %i)\n",pWide, pLocal, dwChars);
661 MultiByteToWideChar(CP_ACP,0,pLocal,-1,pWide,dwChars);
662 return lstrlenW(pWide);
666 /***********************************************************************
667 * lstrrchr (Not a Windows API)
669 * This is the implementation meant to be invoked form within
670 * COMCTL32_StrRChrA and shell32(TODO)...
672 * Return a pointer to the last occurence of wMatch in lpStart
673 * not looking further than lpEnd...
675 LPSTR WINAPI lstrrchr( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
677 LPCSTR lpGotIt = NULL;
679 TRACE("(%s, %s)\n", lpStart, lpEnd);
681 if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
683 for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
684 if (!ChrCmpA( GET_WORD(lpStart), wMatch))
685 lpGotIt = lpStart;
687 return ((LPSTR)lpGotIt);
690 /***********************************************************************
691 * ChrCmpW
692 * This fuction returns FALSE if both words match, TRUE otherwise...
694 static BOOL ChrCmpW( WORD word1, WORD word2) {
695 return (word1 != word2);
698 /***********************************************************************
699 * lstrrchrw (Not a Windows API)
701 * This is the implementation meant to be invoked form within
702 * COMCTL32_StrRChrW and shell32(TODO)...
704 * Return a pointer to the last occurence of wMatch in lpStart
705 * not looking further than lpEnd...
707 LPWSTR WINAPI lstrrchrw( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch )
709 LPCWSTR lpGotIt = NULL;
711 TRACE("(%p, %p, %c)\n", lpStart, lpEnd, wMatch);
712 if (!lpEnd) lpEnd = lpStart + lstrlenW(lpStart);
714 for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
715 if (!ChrCmpW( GET_WORD(lpStart), wMatch))
716 lpGotIt = lpStart;
718 return (LPWSTR)lpGotIt;
721 /***********************************************************************
722 * ChrCmpA
723 * This fuction returns FALSE if both words match, TRUE otherwise...
725 static BOOL ChrCmpA( WORD word1, WORD word2) {
726 if (LOBYTE(word1) == LOBYTE(word2)) {
727 if (IsDBCSLeadByte(LOBYTE(word1))) {
728 return (word1 != word2);
730 return FALSE;
732 return TRUE;