Release 960728
[wine/multimedia.git] / misc / lstr.c
blobfc0de1851ee202cdd133ba4cbd17507ef3fd050b
1 /*
2 * String functions
4 * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5 * Copyright 1996 Marcus Meissner
6 */
8 #include <stdio.h>
9 #include <stdarg.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
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"
23 #define ToUpper(c) toupper(c)
24 #define ToLower(c) tolower(c)
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";
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";
63 /* Funny to divide them between user and kernel. */
65 /* IsCharAlpha USER 433 */
66 BOOL16 IsCharAlpha16(CHAR ch)
68 return isalpha(ch); /* This is probably not right for NLS */
71 /* IsCharAlphanumeric USER 434 */
72 BOOL16 IsCharAlphanumeric16(CHAR ch)
74 return isalnum(ch);
77 /* IsCharUpper USER 435 */
78 BOOL16 IsCharUpper16(CHAR ch)
80 return isupper(ch);
83 /* IsCharLower USER 436 */
84 BOOL16 IsCharLower16(CHAR ch)
86 return islower(ch);
89 /***********************************************************************
90 * AnsiUpper (USER.431)
93 /* 16-bit version */
94 SEGPTR WIN16_AnsiUpper( SEGPTR strOrChar )
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 */
99 /* uppercase only one char if strOrChar < 0x10000 */
100 if (HIWORD(strOrChar))
102 char *s = PTR_SEG_TO_LIN(strOrChar);
103 while (*s) {
104 *s = ToUpper( *s );
105 s++;
107 return strOrChar;
109 else return (SEGPTR)ToUpper( (int)strOrChar );
112 /* 32-bit version */
113 LPSTR AnsiUpper(LPSTR strOrChar)
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 */
119 while (*s) {
120 *s = ToUpper( *s );
121 s++;
123 return strOrChar;
127 /***********************************************************************
128 * AnsiUpperBuff (USER.437)
130 UINT AnsiUpperBuff(LPSTR str,UINT len)
132 int i;
133 len=(len==0)?65536:len;
135 for(i=0;i<len;i++)
136 str[i]=toupper(str[i]);
137 return i;
140 /***********************************************************************
141 * AnsiLower (USER.432)
144 /* 16-bit version */
145 SEGPTR WIN16_AnsiLower(SEGPTR strOrChar)
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 */
150 /* lowercase only one char if strOrChar < 0x10000 */
151 if (HIWORD(strOrChar))
153 char *s = PTR_SEG_TO_LIN( strOrChar );
154 while (*s) {
155 *s = ToLower( *s );
156 s++;
158 return strOrChar;
160 else return (SEGPTR)ToLower( (int)strOrChar );
163 /* 32-bit version */
164 LPSTR AnsiLower(LPSTR strOrChar)
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 */
170 while (*s) {
171 *s = ToLower( *s );
172 s++;
174 return strOrChar;
178 /***********************************************************************
179 * AnsiLowerBuff (USER.438)
181 UINT AnsiLowerBuff(LPSTR str,UINT len)
183 int i;
184 len=(len==0)?65536:len;
185 i=0;
187 for(i=0;i<len;i++)
188 str[i]=tolower(str[i]);
190 return i;
194 /* AnsiNext USER.472 */
195 SEGPTR AnsiNext(SEGPTR current)
197 return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
200 /* AnsiPrev USER.473 */
201 SEGPTR AnsiPrev( SEGPTR start, SEGPTR current)
203 return (current==start)?start:current-1;
207 /* AnsiToOem Keyboard.5 */
208 INT AnsiToOem(LPCSTR lpAnsiStr, LPSTR lpOemStr)
210 dprintf_keyboard(stddeb, "AnsiToOem: %s\n", lpAnsiStr);
211 while(*lpAnsiStr){
212 *lpOemStr++=Ansi2Oem[(unsigned char)(*lpAnsiStr++)];
214 *lpOemStr = 0;
215 return -1;
218 /* OemToAnsi Keyboard.6 */
219 BOOL OemToAnsi(LPCSTR lpOemStr, LPSTR lpAnsiStr)
221 dprintf_keyboard(stddeb, "OemToAnsi: %s\n", lpOemStr);
222 while(*lpOemStr){
223 *lpAnsiStr++=Oem2Ansi[(unsigned char)(*lpOemStr++)];
225 *lpAnsiStr = 0;
226 return -1;
229 /* AnsiToOemBuff Keyboard.134 */
230 void AnsiToOemBuff(LPCSTR lpAnsiStr, LPSTR lpOemStr, UINT nLength)
232 int i;
233 for(i=0;i<nLength;i++)
234 lpOemStr[i]=Ansi2Oem[(unsigned char)(lpAnsiStr[i])];
237 /* OemToAnsi Keyboard.135 */
238 void OemToAnsiBuff(LPCSTR lpOemStr, LPSTR lpAnsiStr, INT nLength)
240 int i;
241 for(i=0;i<nLength;i++)
242 lpAnsiStr[i]=Oem2Ansi[(unsigned char)(lpOemStr[i])];
246 /***********************************************************************
247 * OutputDebugString (KERNEL.115)
249 void OutputDebugString( LPCSTR str )
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 );
263 /***********************************************************************
264 * CharNextA (USER32.28)
266 LPSTR CharNext32A(LPCSTR x)
268 if (*x) return (LPSTR)(x+1);
269 else return (LPSTR)x;
272 /***********************************************************************
273 * CharNextExA (USER32.29)
275 LPSTR CharNextEx32A(WORD codepage,LPCSTR x,DWORD flags)
277 /* FIXME: add DBCS / codepage stuff */
278 if (*x) return (LPSTR)(x+1);
279 else return (LPSTR)x;
282 /***********************************************************************
283 * CharNextExW (USER32.30)
285 LPWSTR CharNextEx32W(WORD codepage,LPCWSTR x,DWORD flags)
287 /* FIXME: add DBCS / codepage stuff */
288 if (*x) return (LPWSTR)(x+1);
289 else return (LPWSTR)x;
292 /***********************************************************************
293 * CharNextW (USER32.31)
295 LPWSTR CharNext32W(LPCWSTR x)
297 if (*x) return (LPWSTR)(x+1);
298 else return (LPWSTR)x;
301 /***********************************************************************
302 * CharPrevA (USER32.32)
304 LPSTR CharPrev32A(LPCSTR start,LPCSTR x)
306 if (x>start) return (LPSTR)(x-1);
307 else return (LPSTR)x;
310 /***********************************************************************
311 * CharPrevExA (USER32.33)
313 LPSTR CharPrevEx32A(WORD codepage,LPCSTR start,LPCSTR x,DWORD flags)
315 /* FIXME: add DBCS / codepage stuff */
316 if (x>start) return (LPSTR)(x-1);
317 else return (LPSTR)x;
320 /***********************************************************************
321 * CharPrevExW (USER32.34)
323 LPWSTR CharPrevEx32W(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
325 /* FIXME: add DBCS / codepage stuff */
326 if (x>start) return (LPWSTR)(x-1);
327 else return (LPWSTR)x;
330 /***********************************************************************
331 * CharPrevW (USER32.35)
333 LPWSTR CharPrev32W(LPCWSTR start,LPCWSTR x)
335 if (x>start) return (LPWSTR)(x-1);
336 else return (LPWSTR)x;
339 /***********************************************************************
340 * CharLowerA (USER32.24)
341 * FIXME: handle current locale
343 LPSTR CharLower32A(LPSTR x)
345 LPSTR s;
347 if (HIWORD(x))
349 s=x;
350 while (*s)
352 *s=tolower(*s);
353 s++;
355 return x;
357 else return (LPSTR)tolower(LOWORD(x));
360 /***********************************************************************
361 * CharLowerBuffA (USER32.25)
362 * FIXME: handle current locale
364 DWORD CharLowerBuff32A(LPSTR x,DWORD buflen)
366 DWORD done=0;
368 while (*x && (buflen--))
370 *x=tolower(*x);
371 x++;
372 done++;
374 return done;
377 /***********************************************************************
378 * CharLowerBuffW (USER32.26)
379 * FIXME: handle current locale
381 DWORD CharLowerBuff32W(LPWSTR x,DWORD buflen)
383 DWORD done=0;
385 while (*x && (buflen--))
387 *x=tolower(*x);
388 x++;
389 done++;
391 return done;
394 /***********************************************************************
395 * CharLowerW (USER32.27)
396 * FIXME: handle current locale
398 LPWSTR CharLower32W(LPWSTR x)
400 if (HIWORD(x))
402 LPWSTR s = x;
403 while (*s)
405 *s=tolower(*s);
406 s++;
408 return x;
410 else return (LPWSTR)tolower(LOWORD(x));
413 /***********************************************************************
414 * CharUpperA (USER32.40)
415 * FIXME: handle current locale
417 LPSTR CharUpper32A(LPSTR x)
419 if (HIWORD(x))
421 LPSTR s = x;
422 while (*s)
424 *s=toupper(*s);
425 s++;
427 return x;
429 else return (LPSTR)toupper(LOWORD(x));
432 /***********************************************************************
433 * CharUpperBuffA (USER32.41)
434 * FIXME: handle current locale
436 DWORD CharUpperBuff32A(LPSTR x,DWORD buflen)
438 DWORD done=0;
440 while (*x && (buflen--))
442 *x=toupper(*x);
443 x++;
444 done++;
446 return done;
449 /***********************************************************************
450 * CharUpperBuffW (USER32.42)
451 * FIXME: handle current locale
453 DWORD CharUpperBuff32W(LPWSTR x,DWORD buflen)
455 DWORD done=0;
457 while (*x && (buflen--))
459 *x=toupper(*x);
460 x++;
461 done++;
463 return done;
466 /***********************************************************************
467 * CharUpperW (USER32.43)
468 * FIXME: handle current locale
470 LPWSTR CharUpper32W(LPWSTR x)
472 if (HIWORD(x))
474 LPWSTR s = x;
475 while (*s)
477 *s=toupper(*s);
478 s++;
480 return x;
482 else return (LPWSTR)toupper(LOWORD(x));
485 /***********************************************************************
486 * IsCharAlphaA (USER32.330)
487 * FIXME: handle current locale
489 BOOL32 IsCharAlpha32A(CHAR x)
491 return isalpha(x);
494 /***********************************************************************
495 * IsCharAlphaNumericA (USER32.331)
496 * FIXME: handle current locale
498 BOOL32 IsCharAlphaNumeric32A(CHAR x)
500 return isalnum(x);
503 /***********************************************************************
504 * IsCharAlphaNumericW (USER32.332)
505 * FIXME: handle current locale
507 BOOL32 IsCharAlphaNumeric32W(WCHAR x)
509 return isalnum(x);
512 /***********************************************************************
513 * IsCharAlphaW (USER32.333)
514 * FIXME: handle current locale
516 BOOL32 IsCharAlpha32W(WCHAR x)
518 return isalpha(x);
521 /***********************************************************************
522 * IsCharAlphaW (USER32.334)
523 * FIXME: handle current locale
525 BOOL32 IsCharLower32A(CHAR x)
527 return islower(x);
530 /***********************************************************************
531 * IsCharAlphaW (USER32.335)
532 * FIXME: handle current locale
534 BOOL32 IsCharLower32W(WCHAR x)
536 return islower(x);
539 /***********************************************************************
540 * IsCharAlphaW (USER32.336)
541 * FIXME: handle current locale
543 BOOL32 IsCharUpper32A(CHAR x)
545 return isupper(x);
548 /***********************************************************************
549 * IsCharAlphaW (USER32.337)
550 * FIXME: handle current locale
552 BOOL32 IsCharUpper32W(WCHAR x)
554 return isupper(x);
557 /***********************************************************************
558 * CharToOemA (USER32.36)
560 BOOL32 CharToOem32A(LPSTR s,LPSTR d)
562 AnsiToOem(s,d);
563 return TRUE;
566 /***********************************************************************
567 * CharToOemBuffA (USER32.37)
569 BOOL32 CharToOemBuff32A(LPSTR s,LPSTR d,DWORD len)
571 AnsiToOemBuff(s,d,len);
572 return TRUE;
575 /***********************************************************************
576 * CharToOemBuffW (USER32.38)
578 BOOL32 CharToOemBuff32W(LPCWSTR s,LPSTR d,DWORD len)
580 LPSTR x=STRING32_DupUniToAnsi(s);
581 AnsiToOemBuff(x,d,len);
582 return TRUE;
585 /***********************************************************************
586 * CharToOemW (USER32.39)
588 BOOL32 CharToOem32W(LPCWSTR s,LPSTR d)
590 LPSTR x=STRING32_DupUniToAnsi(s);
591 AnsiToOem(x,d);
592 return TRUE;
595 /***********************************************************************
596 * OemToCharA (USER32.401)
598 BOOL32 OemToChar32A(LPSTR s,LPSTR d)
600 OemToAnsi(s,d);
601 return TRUE;
604 /***********************************************************************
605 * OemToCharBuffA (USER32.402)
607 BOOL32 OemToCharBuff32A(LPSTR s,LPSTR d,DWORD len)
609 OemToAnsiBuff(s,d,len);
610 return TRUE;
613 /***********************************************************************
614 * OemToCharBuffW (USER32.403)
616 BOOL32 OemToCharBuff32W(LPCSTR s,LPWSTR d,DWORD len)
618 LPSTR x=(char*)xmalloc(strlen(s));
619 OemToAnsiBuff((LPSTR)s,x,len);
620 STRING32_AnsiToUni(d,x);
621 return TRUE;
624 /***********************************************************************
625 * OemToCharW (USER32.404)
627 BOOL32 OemToChar32W(LPCSTR s,LPWSTR d)
629 LPSTR x=(char*)xmalloc(strlen(s));
630 OemToAnsi((LPSTR)s,x);
631 STRING32_AnsiToUni(d,x);
632 return TRUE;
635 /***********************************************************************
636 * FormatMessageA (KERNEL32.138)
637 * FIXME: missing wrap, function has no clue about varargs handling
639 DWORD
640 FormatMessage32A(
641 DWORD dwFlags,
642 LPCVOID lpSource,
643 DWORD dwMessageId,
644 DWORD dwLanguageId,
645 LPSTR lpBuffer,
646 DWORD nSize,
647 LPDWORD *Arguments /* va_list *Arguments */
649 LPSTR target,t;
650 DWORD talloced;
651 LPSTR from,f;
652 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
654 fprintf(stddeb,"FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
655 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,
656 nSize,Arguments
658 if (width)
659 fprintf(stdnimp," - line wrapping not supported.\n");
660 from = NULL;
661 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
662 from = (LPSTR)lpSource;
663 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
664 /* gather information from system message tables ... */
665 fprintf(stdnimp," - FORMAT_MESSAGE_FROM_SYSTEM not implemented.\n");
667 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
668 /* gather information from module's message tables ... */
669 fprintf(stdnimp," - FORMAT_MESSAGE_FROM_HMODULE not implemented.\n");
671 target = (char*)xmalloc(100);
672 t = target;
673 talloced= 100;
674 *t = 0;
676 #define ADD_TO_T(c) \
677 *t++=c;\
678 if (t-target == talloced) {\
679 target = (char*)xrealloc(target,talloced*2);\
680 t = target+talloced;\
681 talloced*=2;\
684 if (from) {
685 f=from;
686 fprintf(stddeb," from is %s\n",from);
687 while (*f) {
688 if (*f=='%') {
689 int insertnr;
690 char *fmtstr,*sprintfbuf,*x;
691 DWORD arg1,arg2,arg3;
693 f++;
694 if (!*f) {
695 ADD_TO_T('%');
696 continue;
698 switch (*f) {
699 case '1':case '2':case '3':case '4':case '5':
700 case '6':case '7':case '8':case '9':
701 insertnr=*f-'0';
702 switch (f[1]) {
703 case '0':case '1':case '2':case '3':
704 case '4':case '5':case '6':case '7':
705 case '8':case '9':
706 f++;
707 insertnr=insertnr*10+*f-'0';
708 break;
709 default:break;
711 if (f[1]=='!') {
712 f+=2;
713 if (NULL!=(x=strchr(f,'!'))) {
714 *x='\0';
715 fmtstr=strdup(f);
716 f=x+1;
718 } else {
719 fmtstr=strdup("%s");
722 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) {
723 DWORD *args = (DWORD*)Arguments;
724 arg1 = args[insertnr-1];
725 arg2 = args[insertnr+0];
726 arg3 = args[insertnr+1];
727 } else {
729 int i;
730 va_list vl;
732 vl=va_start(Arguments,7);
733 for (i=insertnr;i--;)
734 va_arg(vl,DWORD);
735 arg1 = va_arg(vl,DWORD);
736 arg2 = va_arg(vl,DWORD);
737 arg3 = va_arg(vl,DWORD);
738 va_end(vl);
740 fprintf(stdnimp," - varargs not supported yet.\n");
743 if (fmtstr[strlen(fmtstr)]=='s') {
744 sprintfbuf=(char*)xmalloc(strlen((LPSTR)arg1)+1);
745 } else {
746 sprintfbuf=(char*)xmalloc(100);
748 sprintf(sprintfbuf,fmtstr,arg1,arg2,arg3);
749 x=sprintfbuf;
750 while (*x) {
751 ADD_TO_T(*x++);
753 free(sprintfbuf);
754 free(fmtstr);
755 break;
756 default:ADD_TO_T(*f++)
757 break;
760 } else {
761 ADD_TO_T(*f++)
764 *t='\0';
766 talloced = strlen(target)+1;
767 if (nSize && talloced<nSize) {
768 target = (char*)xrealloc(target,nSize);
770 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
771 /* nSize is the MINIMUM size */
772 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced);
773 memcpy(*(LPSTR*)lpBuffer,target,talloced);
774 } else
775 strncpy(lpBuffer,target,nSize);
776 free(target);
777 return strlen(lpBuffer);