Release 960712
[wine] / misc / lstr.c
1 /*
2  * String functions
3  *
4  * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5  * Copyright 1996 Marcus Meissner
6  */
7
8 #include <stdio.h>
9 #include <stdarg.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13
14 #include "windows.h"
15 #include "ldt.h"
16 #include "module.h"
17 #include "stackframe.h"
18 #include "stddebug.h"
19 #include "debug.h"
20 #include "xmalloc.h"
21 #include "string32.h"
22
23 #define ToUpper(c)      toupper(c)
24 #define ToLower(c)      tolower(c)
25
26
27 static const BYTE Oem2Ansi[256] =
28 "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\244"
29 "\020\021\022\023\266\247\026\027\030\031\032\033\034\035\036\037"
30 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
31 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
32 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
33 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
34 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
35 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
36 "\307\374\351\342\344\340\345\347\352\353\350\357\356\354\304\305"
37 "\311\346\306\364\366\362\373\371\377\326\334\242\243\245\120\203"
38 "\341\355\363\372\361\321\252\272\277\137\254\275\274\241\253\273"
39 "\137\137\137\246\246\246\246\053\053\246\246\053\053\053\053\053"
40 "\053\055\055\053\055\053\246\246\053\053\055\055\246\055\053\055"
41 "\055\055\055\053\053\053\053\053\053\053\053\137\137\246\137\137"
42 "\137\337\137\266\137\137\265\137\137\137\137\137\137\137\137\137"
43 "\137\261\137\137\137\137\367\137\260\225\267\137\156\262\137\137";
44
45 static const BYTE Ansi2Oem[256] =
46 "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
47 "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
48 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
49 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
50 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
51 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
52 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
53 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
54 "\200\201\054\237\054\137\375\374\210\045\123\074\117\215\216\217"
55 "\220\140\047\042\042\371\055\137\230\231\163\076\157\235\236\131"
56 "\040\255\233\234\017\235\335\025\042\143\246\256\252\055\162\137"
57 "\370\361\375\063\047\346\024\372\054\061\247\257\254\253\137\250"
58 "\101\101\101\101\216\217\222\200\105\220\105\105\111\111\111\111"
59 "\104\245\117\117\117\117\231\170\117\125\125\125\232\131\137\341"
60 "\205\240\203\141\204\206\221\207\212\202\210\211\215\241\214\213"
61 "\144\244\225\242\223\157\224\366\157\227\243\226\201\171\137\230";
62
63 /* Funny to divide them between user and kernel. */
64
65 /* IsCharAlpha USER 433 */
66 BOOL16 IsCharAlpha16(CHAR ch)
67 {
68   return isalpha(ch);   /* This is probably not right for NLS */
69 }
70
71 /* IsCharAlphanumeric USER 434 */
72 BOOL16 IsCharAlphanumeric16(CHAR ch)
73 {
74     return isalnum(ch);
75 }
76
77 /* IsCharUpper USER 435 */
78 BOOL16 IsCharUpper16(CHAR ch)
79 {
80   return isupper(ch);
81 }
82
83 /* IsCharLower USER 436 */
84 BOOL16 IsCharLower16(CHAR ch)
85 {
86   return islower(ch);
87 }
88
89 /***********************************************************************
90  *           AnsiUpper   (USER.431)
91  */
92
93 /* 16-bit version */
94 SEGPTR WIN16_AnsiUpper( SEGPTR strOrChar )
95 {
96   /* I am not sure if the locale stuff works with toupper, but then again 
97      I am not sure if the Linux libc locale stuffs works at all */
98
99     /* uppercase only one char if strOrChar < 0x10000 */
100     if (HIWORD(strOrChar))
101     {
102         char *s = PTR_SEG_TO_LIN(strOrChar);
103         while (*s) {
104             *s = ToUpper( *s );
105             s++;
106         }
107         return strOrChar;
108     }
109     else return (SEGPTR)ToUpper( (int)strOrChar );
110 }
111
112 /* 32-bit version */
113 LPSTR AnsiUpper(LPSTR strOrChar)
114 {
115     char *s = strOrChar;
116   /* I am not sure if the locale stuff works with toupper, but then again 
117      I am not sure if the Linux libc locale stuffs works at all */
118
119     while (*s) {
120         *s = ToUpper( *s );
121         s++;
122     }
123     return strOrChar;
124 }
125
126
127 /***********************************************************************
128  *           AnsiUpperBuff   (USER.437)
129  */
130 UINT AnsiUpperBuff(LPSTR str,UINT len)
131 {
132   int i;
133   len=(len==0)?65536:len;
134
135   for(i=0;i<len;i++)
136     str[i]=toupper(str[i]);
137   return i;     
138 }
139
140 /***********************************************************************
141  *           AnsiLower   (USER.432)
142  */
143
144 /* 16-bit version */
145 SEGPTR WIN16_AnsiLower(SEGPTR strOrChar)
146 {
147   /* I am not sure if the locale stuff works with toupper, but then again 
148      I am not sure if the Linux libc locale stuffs works at all */
149
150     /* lowercase only one char if strOrChar < 0x10000 */
151     if (HIWORD(strOrChar))
152     {
153         char *s = PTR_SEG_TO_LIN( strOrChar );
154         while (*s) {        
155             *s = ToLower( *s );
156             s++;
157         }
158         return strOrChar;
159     }
160     else return (SEGPTR)ToLower( (int)strOrChar );
161 }
162
163 /* 32-bit version */
164 LPSTR AnsiLower(LPSTR strOrChar)
165 {
166     char *s = strOrChar;
167   /* I am not sure if the locale stuff works with toupper, but then again 
168      I am not sure if the Linux libc locale stuffs works at all */
169
170     while (*s) {
171         *s = ToLower( *s );
172         s++;
173     }
174     return strOrChar;
175 }
176
177
178 /***********************************************************************
179  *           AnsiLowerBuff   (USER.438)
180  */
181 UINT AnsiLowerBuff(LPSTR str,UINT len)
182 {
183   int i;
184   len=(len==0)?65536:len;
185   i=0;
186
187   for(i=0;i<len;i++)
188     str[i]=tolower(str[i]);
189  
190   return i;     
191 }
192
193
194 /* AnsiNext USER.472 */
195 SEGPTR AnsiNext(SEGPTR current)
196 {
197     return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
198 }
199
200 /* AnsiPrev USER.473 */
201 SEGPTR AnsiPrev( SEGPTR start, SEGPTR current)
202 {
203     return (current==start)?start:current-1;
204 }
205
206
207 /* AnsiToOem Keyboard.5 */
208 INT AnsiToOem(LPCSTR lpAnsiStr, LPSTR lpOemStr)
209 {
210     dprintf_keyboard(stddeb, "AnsiToOem: %s\n", lpAnsiStr);
211     while(*lpAnsiStr){
212         *lpOemStr++=Ansi2Oem[(unsigned char)(*lpAnsiStr++)];
213     }
214     *lpOemStr = 0;
215     return -1;
216 }
217
218 /* OemToAnsi Keyboard.6 */
219 BOOL OemToAnsi(LPCSTR lpOemStr, LPSTR lpAnsiStr)
220 {
221     dprintf_keyboard(stddeb, "OemToAnsi: %s\n", lpOemStr);
222     while(*lpOemStr){
223         *lpAnsiStr++=Oem2Ansi[(unsigned char)(*lpOemStr++)];
224     }
225     *lpAnsiStr = 0;
226     return -1;
227 }
228
229 /* AnsiToOemBuff Keyboard.134 */
230 void AnsiToOemBuff(LPCSTR lpAnsiStr, LPSTR lpOemStr, UINT nLength)
231 {
232   int i;
233   for(i=0;i<nLength;i++)
234     lpOemStr[i]=Ansi2Oem[(unsigned char)(lpAnsiStr[i])];
235 }
236
237 /* OemToAnsi Keyboard.135 */
238 void OemToAnsiBuff(LPCSTR lpOemStr, LPSTR lpAnsiStr, INT nLength)
239 {
240   int i;
241   for(i=0;i<nLength;i++)
242     lpAnsiStr[i]=Oem2Ansi[(unsigned char)(lpOemStr[i])];
243 }
244
245
246 /***********************************************************************
247  *           OutputDebugString   (KERNEL.115)
248  */
249 void OutputDebugString( LPCSTR str )
250 {
251     char *module;
252     char *p, *buffer = xmalloc( strlen(str)+1 );
253     /* Remove CRs */
254     for (p = buffer; *str; str++) if (*str != '\r') *p++ = *str;
255     *p = '\0';
256     if ((p > buffer) && (p[-1] == '\n')) p[1] = '\0'; /* Remove trailing \n */
257     module = MODULE_GetModuleName( GetExePtr(GetCurrentTask()) );
258     fprintf( stderr, "OutputDebugString: %s says '%s'\n",
259              module ? module : "???", buffer );
260     free( buffer );
261 }
262
263 /***********************************************************************
264  *           CharNextA   (USER32.28)
265  */
266 LPSTR CharNext32A(LPCSTR x)
267 {
268     if (*x) return (LPSTR)(x+1);
269     else return (LPSTR)x;
270 }
271
272 /***********************************************************************
273  *           CharNextExA   (USER32.29)
274  */
275 LPSTR CharNextEx32A(WORD codepage,LPCSTR x,DWORD flags)
276 {
277     /* FIXME: add DBCS / codepage stuff */
278     if (*x) return (LPSTR)(x+1);
279     else return (LPSTR)x;
280 }
281
282 /***********************************************************************
283  *           CharNextExW   (USER32.30)
284  */
285 LPWSTR CharNextEx32W(WORD codepage,LPCWSTR x,DWORD flags)
286 {
287     /* FIXME: add DBCS / codepage stuff */
288     if (*x) return (LPWSTR)(x+1);
289     else return (LPWSTR)x;
290 }
291
292 /***********************************************************************
293  *           CharNextW   (USER32.31)
294  */
295 LPWSTR CharNext32W(LPCWSTR x)
296 {
297     if (*x) return (LPWSTR)(x+1);
298     else return (LPWSTR)x;
299 }
300
301 /***********************************************************************
302  *           CharPrevA   (USER32.32)
303  */
304 LPSTR CharPrev32A(LPCSTR start,LPCSTR x)
305 {
306     if (x>start) return (LPSTR)(x-1);
307     else return (LPSTR)x;
308 }
309
310 /***********************************************************************
311  *           CharPrevExA   (USER32.33)
312  */
313 LPSTR CharPrevEx32A(WORD codepage,LPCSTR start,LPCSTR x,DWORD flags)
314 {
315     /* FIXME: add DBCS / codepage stuff */
316     if (x>start) return (LPSTR)(x-1);
317     else return (LPSTR)x;
318 }
319
320 /***********************************************************************
321  *           CharPrevExW   (USER32.34)
322  */
323 LPWSTR CharPrevEx32W(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
324 {
325     /* FIXME: add DBCS / codepage stuff */
326     if (x>start) return (LPWSTR)(x-1);
327     else return (LPWSTR)x;
328 }
329
330 /***********************************************************************
331  *           CharPrevW   (USER32.35)
332  */
333 LPWSTR CharPrev32W(LPCWSTR start,LPCWSTR x)
334 {
335     if (x>start) return (LPWSTR)(x-1);
336     else return (LPWSTR)x;
337 }
338
339 /***********************************************************************
340  *           CharLowerA   (USER32.24)
341  * FIXME: handle current locale
342  */
343 LPSTR CharLower32A(LPSTR x)
344 {
345     LPSTR       s;
346
347     if (HIWORD(x))
348     {
349         s=x;
350         while (*s)
351         {
352             *s=tolower(*s);
353             s++;
354         }
355         return x;
356     }
357     else return (LPSTR)tolower(LOWORD(x));
358 }
359
360 /***********************************************************************
361  *           CharLowerBuffA   (USER32.25)
362  * FIXME: handle current locale
363  */
364 DWORD CharLowerBuff32A(LPSTR x,DWORD buflen)
365 {
366     DWORD done=0;
367
368     while (*x && (buflen--))
369     {
370         *x=tolower(*x);
371         x++;
372         done++;
373     }
374     return done;
375 }
376
377 /***********************************************************************
378  *           CharLowerBuffW   (USER32.26)
379  * FIXME: handle current locale
380  */
381 DWORD CharLowerBuff32W(LPWSTR x,DWORD buflen)
382 {
383     DWORD done=0;
384
385     while (*x && (buflen--))
386     {
387         *x=tolower(*x);
388         x++;
389         done++;
390     }
391     return done;
392 }
393
394 /***********************************************************************
395  *           CharLowerW   (USER32.27)
396  * FIXME: handle current locale
397  */
398 LPWSTR CharLower32W(LPWSTR x)
399 {
400     if (HIWORD(x))
401     {
402         LPWSTR s = x;
403         while (*s)
404         {
405             *s=tolower(*s);
406             s++;
407         }
408         return x;
409     }
410     else return (LPWSTR)tolower(LOWORD(x));
411 }
412
413 /***********************************************************************
414  *           CharUpperA   (USER32.40)
415  * FIXME: handle current locale
416  */
417 LPSTR CharUpper32A(LPSTR x)
418 {
419     if (HIWORD(x))
420     {
421         LPSTR s = x;
422         while (*s)
423         {
424             *s=toupper(*s);
425             s++;
426         }
427         return x;
428     }
429     else return (LPSTR)toupper(LOWORD(x));
430 }
431
432 /***********************************************************************
433  *           CharUpperBuffA   (USER32.41)
434  * FIXME: handle current locale
435  */
436 DWORD CharUpperBuff32A(LPSTR x,DWORD buflen)
437 {
438     DWORD done=0;
439
440     while (*x && (buflen--))
441     {
442         *x=toupper(*x);
443         x++;
444         done++;
445     }
446     return done;
447 }
448
449 /***********************************************************************
450  *           CharUpperBuffW   (USER32.42)
451  * FIXME: handle current locale
452  */
453 DWORD CharUpperBuff32W(LPWSTR x,DWORD buflen)
454 {
455     DWORD done=0;
456
457     while (*x && (buflen--))
458     {
459         *x=toupper(*x);
460         x++;
461         done++;
462     }
463     return done;
464 }
465
466 /***********************************************************************
467  *           CharUpperW   (USER32.43)
468  * FIXME: handle current locale
469  */
470 LPWSTR CharUpper32W(LPWSTR x)
471 {
472     if (HIWORD(x))
473     {
474         LPWSTR s = x;
475         while (*s)
476         {
477             *s=toupper(*s);
478             s++;
479         }
480         return x;
481     }
482     else return (LPWSTR)toupper(LOWORD(x));
483 }
484
485 /***********************************************************************
486  *           IsCharAlphaA   (USER32.330)
487  * FIXME: handle current locale
488  */
489 BOOL32 IsCharAlpha32A(CHAR x)
490 {
491     return isalpha(x);
492 }
493
494 /***********************************************************************
495  *           IsCharAlphaNumericA   (USER32.331)
496  * FIXME: handle current locale
497  */
498 BOOL32 IsCharAlphaNumeric32A(CHAR x)
499 {
500     return isalnum(x);
501 }
502
503 /***********************************************************************
504  *           IsCharAlphaNumericW   (USER32.332)
505  * FIXME: handle current locale
506  */
507 BOOL32 IsCharAlphaNumeric32W(WCHAR x)
508 {
509     return isalnum(x);
510 }
511
512 /***********************************************************************
513  *           IsCharAlphaW   (USER32.333)
514  * FIXME: handle current locale
515  */
516 BOOL32 IsCharAlpha32W(WCHAR x)
517 {
518     return isalpha(x);
519 }
520
521 /***********************************************************************
522  *           IsCharAlphaW   (USER32.334)
523  * FIXME: handle current locale
524  */
525 BOOL32 IsCharLower32A(CHAR x)
526 {
527     return islower(x);
528 }
529
530 /***********************************************************************
531  *           IsCharAlphaW   (USER32.335)
532  * FIXME: handle current locale
533  */
534 BOOL32 IsCharLower32W(WCHAR x)
535 {
536     return islower(x);
537 }
538
539 /***********************************************************************
540  *           IsCharAlphaW   (USER32.336)
541  * FIXME: handle current locale
542  */
543 BOOL32 IsCharUpper32A(CHAR x)
544 {
545     return isupper(x);
546 }
547
548 /***********************************************************************
549  *           IsCharAlphaW   (USER32.337)
550  * FIXME: handle current locale
551  */
552 BOOL32 IsCharUpper32W(WCHAR x)
553 {
554     return isupper(x);
555 }
556
557 /***********************************************************************
558  *           CharToOemA   (USER32.36)
559  */
560 BOOL32 CharToOem32A(LPSTR s,LPSTR d)
561 {
562     AnsiToOem(s,d);
563     return TRUE;
564 }
565
566 /***********************************************************************
567  *           CharToOemBuffA   (USER32.37)
568  */
569 BOOL32 CharToOemBuff32A(LPSTR s,LPSTR d,DWORD len)
570 {
571     AnsiToOemBuff(s,d,len);
572     return TRUE;
573 }
574
575 /***********************************************************************
576  *           CharToOemBuffW   (USER32.38)
577  */
578 BOOL32 CharToOemBuff32W(LPCWSTR s,LPSTR d,DWORD len)
579 {
580     LPSTR       x=STRING32_DupUniToAnsi(s);
581     AnsiToOemBuff(x,d,len);
582     return TRUE;
583 }
584
585 /***********************************************************************
586  *           CharToOemW   (USER32.39)
587  */
588 BOOL32 CharToOem32W(LPCWSTR s,LPSTR d)
589 {
590     LPSTR       x=STRING32_DupUniToAnsi(s);
591     AnsiToOem(x,d);
592     return TRUE;
593 }
594
595 /***********************************************************************
596  *           OemToCharA   (USER32.401)
597  */
598 BOOL32 OemToChar32A(LPSTR s,LPSTR d)
599 {
600     OemToAnsi(s,d);
601     return TRUE;
602 }
603
604 /***********************************************************************
605  *           OemToCharBuffA   (USER32.402)
606  */
607 BOOL32 OemToCharBuff32A(LPSTR s,LPSTR d,DWORD len)
608 {
609     OemToAnsiBuff(s,d,len);
610     return TRUE;
611 }
612
613 /***********************************************************************
614  *           OemToCharBuffW   (USER32.403)
615  */
616 BOOL32 OemToCharBuff32W(LPCSTR s,LPWSTR d,DWORD len)
617 {
618     LPSTR x=(char*)xmalloc(strlen(s));
619     OemToAnsiBuff((LPSTR)s,x,len);
620     STRING32_AnsiToUni(d,x);
621     return TRUE;
622 }
623
624 /***********************************************************************
625  *           OemToCharW   (USER32.404)
626  */
627 BOOL32 OemToChar32W(LPCSTR s,LPWSTR d)
628 {
629     LPSTR x=(char*)xmalloc(strlen(s));
630     OemToAnsi((LPSTR)s,x);
631     STRING32_AnsiToUni(d,x);
632     return TRUE;
633 }