4 * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5 * Copyright 1996 Marcus Meissner
18 # define iswalnum(c) isalnum(c)
19 # define iswalpha(c) isalpha(c)
20 # define iswupper(c) isupper(c)
21 # define iswlower(c) islower(c)
22 #endif /* HAVE_WCTYPE_H */
24 #include "wine/winbase16.h"
25 #include "wine/winuser16.h"
32 #include "stackframe.h"
34 #include "debugtools.h"
36 DEFAULT_DEBUG_CHANNEL(resource)
38 extern const WORD OLE2NLS_CT_CType3_LUT[]; /* FIXME: does not belong here */
41 /* Funny to divide them between user and kernel. */
43 /* be careful: always use functions from wctype.h if character > 255 */
46 * Unicode case conversion routines ... these should be used where
47 * toupper/tolower are used for ASCII.
50 /* FIXME: should probably get rid of wctype.h altogether */
53 WCHAR towupper(WCHAR code)
55 const WCHAR * ptr = uprtable[HIBYTE(code)];
56 return ptr ? ptr[LOBYTE(code)] : code;
59 WCHAR towlower(WCHAR code)
61 const WCHAR * ptr = lwrtable[HIBYTE(code)];
62 return ptr ? ptr[LOBYTE(code)] : code;
64 #endif /* HAVE_WCTYPE_H */
66 /***********************************************************************
67 * IsCharAlpha (USER.433)
69 BOOL16 WINAPI IsCharAlpha16(CHAR ch)
71 return isalpha(ch); /* This is probably not right for NLS */
74 /***********************************************************************
75 * IsCharAlphanumeric (USER.434)
77 BOOL16 WINAPI IsCharAlphaNumeric16(CHAR ch)
82 /***********************************************************************
83 * IsCharUpper (USER.435)
85 BOOL16 WINAPI IsCharUpper16(CHAR ch)
90 /***********************************************************************
91 * IsCharLower (USER.436)
93 BOOL16 WINAPI IsCharLower16(CHAR ch)
98 /***********************************************************************
99 * AnsiUpper16 (USER.431)
101 SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar )
103 /* I am not sure if the locale stuff works with toupper, but then again
104 I am not sure if the Linux libc locale stuffs works at all */
106 /* uppercase only one char if strOrChar < 0x10000 */
107 if (HIWORD(strOrChar))
110 for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
113 else return toupper((char)strOrChar);
117 /***********************************************************************
118 * AnsiUpperBuff16 (USER.437)
120 UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len )
122 UINT count = len ? len : 65536;
123 for (; count; count--, str++) *str = toupper(*str);
127 /***********************************************************************
128 * AnsiLower16 (USER.432)
130 SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar )
132 /* I am not sure if the locale stuff works with toupper, but then again
133 I am not sure if the Linux libc locale stuffs works at all */
135 /* lowercase only one char if strOrChar < 0x10000 */
136 if (HIWORD(strOrChar))
139 for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
142 else return tolower((char)strOrChar);
146 /***********************************************************************
147 * AnsiLowerBuff16 (USER.438)
149 UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len )
151 UINT count = len ? len : 65536;
152 for (; count; count--, str++) *str = tolower(*str);
157 /***********************************************************************
158 * AnsiNext16 (USER.472)
160 SEGPTR WINAPI AnsiNext16(SEGPTR current)
162 return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
166 /***********************************************************************
167 * AnsiPrev16 (USER.473)
169 SEGPTR WINAPI AnsiPrev16( SEGPTR start, SEGPTR current )
171 return (current == start) ? start : current - 1;
175 /***********************************************************************
176 * CharNext32A (USER32.29)
178 LPSTR WINAPI CharNextA( LPCSTR ptr )
180 if (!*ptr) return (LPSTR)ptr;
181 if (IsDBCSLeadByte( *ptr )) return (LPSTR)(ptr + 2);
182 return (LPSTR)(ptr + 1);
186 /***********************************************************************
187 * CharNextEx32A (USER32.30)
189 LPSTR WINAPI CharNextExA( WORD codepage, LPCSTR ptr, DWORD flags )
191 if (!*ptr) return (LPSTR)ptr;
192 if (IsDBCSLeadByteEx( codepage, *ptr )) return (LPSTR)(ptr + 2);
193 return (LPSTR)(ptr + 1);
197 /***********************************************************************
198 * CharNextExW (USER32.31)
200 LPWSTR WINAPI CharNextExW(WORD codepage,LPCWSTR x,DWORD flags)
202 /* FIXME: add DBCS / codepage stuff */
203 if (*x) return (LPWSTR)(x+1);
204 else return (LPWSTR)x;
207 /***********************************************************************
208 * CharNextW (USER32.32)
210 LPWSTR WINAPI CharNextW(LPCWSTR x)
212 if (*x) return (LPWSTR)(x+1);
213 else return (LPWSTR)x;
216 /***********************************************************************
217 * CharPrev32A (USER32.33)
219 LPSTR WINAPI CharPrevA( LPCSTR start, LPCSTR ptr )
221 while (*start && (start < ptr))
223 LPCSTR next = CharNextA( start );
224 if (next >= ptr) break;
231 /***********************************************************************
232 * CharPrevEx32A (USER32.34)
234 LPSTR WINAPI CharPrevExA( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
236 while (*start && (start < ptr))
238 LPCSTR next = CharNextExA( codepage, start, flags );
239 if (next > ptr) break;
246 /***********************************************************************
247 * CharPrevExW (USER32.35)
249 LPWSTR WINAPI CharPrevExW(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
251 /* FIXME: add DBCS / codepage stuff */
252 if (x>start) return (LPWSTR)(x-1);
253 else return (LPWSTR)x;
256 /***********************************************************************
257 * CharPrevW (USER32.36)
259 LPWSTR WINAPI CharPrevW(LPCWSTR start,LPCWSTR x)
261 if (x>start) return (LPWSTR)(x-1);
262 else return (LPWSTR)x;
265 /***********************************************************************
266 * CharLowerA (USER32.25)
267 * FIXME: handle current locale
269 LPSTR WINAPI CharLowerA(LPSTR x)
283 else return (LPSTR)tolower((char)(int)x);
286 /***********************************************************************
287 * CharLowerBuffA (USER32.26)
288 * FIXME: handle current locale
290 DWORD WINAPI CharLowerBuffA(LPSTR x,DWORD buflen)
294 if (!x) return 0; /* YES */
295 while (*x && (buflen--))
304 /***********************************************************************
305 * CharLowerBuffW (USER32.27)
306 * FIXME: handle current locale
308 DWORD WINAPI CharLowerBuffW(LPWSTR x,DWORD buflen)
312 if (!x) return 0; /* YES */
313 while (*x && (buflen--))
322 /***********************************************************************
323 * CharLowerW (USER32.28)
324 * FIXME: handle current locale
326 LPWSTR WINAPI CharLowerW(LPWSTR x)
338 else return (LPWSTR)((UINT)towlower(LOWORD(x)));
341 /***********************************************************************
342 * CharUpper32A (USER32.41)
343 * FIXME: handle current locale
345 LPSTR WINAPI CharUpperA(LPSTR x)
357 return (LPSTR)toupper((char)(int)x);
360 /***********************************************************************
361 * CharUpperBuffA (USER32.42)
362 * FIXME: handle current locale
364 DWORD WINAPI CharUpperBuffA(LPSTR x,DWORD buflen)
368 if (!x) return 0; /* YES */
369 while (*x && (buflen--))
378 /***********************************************************************
379 * CharUpperBuffW (USER32.43)
380 * FIXME: handle current locale
382 DWORD WINAPI CharUpperBuffW(LPWSTR x,DWORD buflen)
386 if (!x) return 0; /* YES */
387 while (*x && (buflen--))
396 /***********************************************************************
397 * CharUpperW (USER32.44)
398 * FIXME: handle current locale
400 LPWSTR WINAPI CharUpperW(LPWSTR x)
412 else return (LPWSTR)((UINT)towupper(LOWORD(x)));
415 /***********************************************************************
416 * IsCharAlphaA (USER32.331)
417 * FIXME: handle current locale
419 BOOL WINAPI IsCharAlphaA(CHAR x)
421 return (OLE2NLS_CT_CType3_LUT[(unsigned char)x] & C3_ALPHA);
424 /***********************************************************************
425 * IsCharAlphaNumericA (USER32.332)
426 * FIXME: handle current locale
428 BOOL WINAPI IsCharAlphaNumericA(CHAR x)
430 return IsCharAlphaA(x) || isdigit(x) ;
433 /***********************************************************************
434 * IsCharAlphaNumericW (USER32.333)
435 * FIXME: handle current locale
437 BOOL WINAPI IsCharAlphaNumericW(WCHAR x)
442 /***********************************************************************
443 * IsCharAlphaW (USER32.334)
444 * FIXME: handle current locale
446 BOOL WINAPI IsCharAlphaW(WCHAR x)
451 /***********************************************************************
452 * IsCharLower32A (USER32.335)
453 * FIXME: handle current locale
455 BOOL WINAPI IsCharLowerA(CHAR x)
460 /***********************************************************************
461 * IsCharLower32W (USER32.336)
462 * FIXME: handle current locale
464 BOOL WINAPI IsCharLowerW(WCHAR x)
469 /***********************************************************************
470 * IsCharUpper32A (USER32.337)
471 * FIXME: handle current locale
473 BOOL WINAPI IsCharUpperA(CHAR x)
478 /***********************************************************************
479 * IsCharUpper32W (USER32.338)
480 * FIXME: handle current locale
482 BOOL WINAPI IsCharUpperW(WCHAR x)
487 /***********************************************************************
488 * FormatMessage16 (USER.606)
490 DWORD WINAPI FormatMessage16(
497 LPDWORD args /* va_list *args */
499 return FormatMessageA(dwFlags, lpSource, (DWORD)dwMessageId, (DWORD)dwLanguageId, lpBuffer, (DWORD)nSize, args);
502 /***********************************************************************
503 * FormatMessage32A (KERNEL32.138)
504 * FIXME: missing wrap,FROM_SYSTEM message-loading,
506 DWORD WINAPI FormatMessageA(
513 LPDWORD args /* va_list *args */
516 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
520 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
521 DWORD nolinefeed = 0;
523 TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
524 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
526 FIXME("line wrapping not supported.\n");
528 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
529 from = HEAP_strdupA( GetProcessHeap(), 0, (LPSTR)lpSource);
530 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
531 from = HeapAlloc( GetProcessHeap(),0,200 );
532 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
534 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
537 dwMessageId &= 0xFFFF;
538 bufsize=LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,NULL,100);
540 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
541 LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
544 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
548 #define ADD_TO_T(c) \
550 if (t-target == talloced) {\
551 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
552 t = target+talloced;\
558 while (*f && !nolinefeed) {
561 char *fmtstr,*sprintfbuf,*x,*lastf;
572 case '1':case '2':case '3':case '4':case '5':
573 case '6':case '7':case '8':case '9':
576 case '0':case '1':case '2':case '3':
577 case '4':case '5':case '6':case '7':
580 insertnr=insertnr*10+*f-'0';
589 if (NULL!=(x=strchr(f,'!'))) {
591 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
592 sprintf(fmtstr,"%%%s",f);
595 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
596 sprintf(fmtstr,"%%%s",f);
597 f+=strlen(f); /*at \0*/
603 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
605 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
606 argliststart=args+insertnr-1;
608 argliststart=(*(DWORD**)args)+insertnr-1;
610 if (fmtstr[strlen(fmtstr)-1]=='s')
611 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
613 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
615 /* CMF - This makes a BIG assumption about va_list */
616 wvsprintfA(sprintfbuf, fmtstr, (va_list) argliststart);
621 HeapFree(GetProcessHeap(),0,sprintfbuf);
623 /* NULL args - copy formatstr
626 while ((lastf<f)&&(*lastf)) {
630 HeapFree(GetProcessHeap(),0,fmtstr);
633 /* FIXME: perhaps add \r too? */
641 default:ADD_TO_T(*f++)
653 if(t==target || t[-1]!='\n')
654 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
656 talloced = strlen(target)+1;
657 if (nSize && talloced<nSize) {
658 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
660 TRACE("-- %s\n",debugstr_a(target));
661 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
662 /* nSize is the MINIMUM size */
663 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,talloced);
664 memcpy(*(LPSTR*)lpBuffer,target,talloced);
666 strncpy(lpBuffer,target,nSize);
667 HeapFree(GetProcessHeap(),0,target);
668 if (from) HeapFree(GetProcessHeap(),0,from);
669 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
670 strlen(*(LPSTR*)lpBuffer):
674 #endif /* __i386__ */
679 /***********************************************************************
680 * FormatMessage32W (KERNEL32.138)
682 DWORD WINAPI FormatMessageW(
689 LPDWORD args /* va_list *args */
692 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
696 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
697 DWORD nolinefeed = 0;
699 TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
700 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
702 FIXME("line wrapping not supported.\n");
704 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
705 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
706 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
707 /* gather information from system message tables ... */
708 from = HeapAlloc( GetProcessHeap(),0,200 );
709 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
711 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
714 dwMessageId &= 0xFFFF;
715 bufsize=LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,NULL,100);
718 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
719 LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
722 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
726 #define ADD_TO_T(c) \
728 if (t-target == talloced) {\
729 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
730 t = target+talloced;\
736 while (*f && !nolinefeed) {
739 char *fmtstr,*sprintfbuf,*x;
749 case '1':case '2':case '3':case '4':case '5':
750 case '6':case '7':case '8':case '9':
753 case '0':case '1':case '2':case '3':
754 case '4':case '5':case '6':case '7':
757 insertnr=insertnr*10+*f-'0';
766 if (NULL!=(x=strchr(f,'!')))
769 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
770 sprintf(fmtstr,"%%%s",f);
773 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
774 sprintf(fmtstr,"%%%s",f);
775 f+=strlen(f); /*at \0*/
781 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
782 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
783 argliststart=args+insertnr-1;
785 argliststart=(*(DWORD**)args)+insertnr-1;
787 if (fmtstr[strlen(fmtstr)-1]=='s') {
790 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
791 /* possible invalid pointers */
792 xarr[1]=*(argliststart+1);
793 xarr[2]=*(argliststart+2);
794 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlenW((LPWSTR)argliststart[0])*2+1);
796 /* CMF - This makes a BIG assumption about va_list */
797 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
799 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
801 /* CMF - This makes a BIG assumption about va_list */
802 wvsprintfA(sprintfbuf, fmtstr, (va_list) argliststart);
808 HeapFree(GetProcessHeap(),0,sprintfbuf);
809 HeapFree(GetProcessHeap(),0,fmtstr);
812 /* FIXME: perhaps add \r too? */
820 default:ADD_TO_T(*f++)
832 if(t==target || t[-1]!='\n')
833 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
835 talloced = strlen(target)+1;
836 if (nSize && talloced<nSize)
837 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
838 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
839 /* nSize is the MINIMUM size */
840 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,talloced*2+2);
841 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
843 lstrcpynAtoW(lpBuffer,target,nSize);
844 HeapFree(GetProcessHeap(),0,target);
845 if (from) HeapFree(GetProcessHeap(),0,from);
846 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
847 lstrlenW(*(LPWSTR*)lpBuffer):
851 #endif /* __i386__ */