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 */
27 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
33 #include "stackframe.h"
37 extern const WORD OLE2NLS_CT_CType3_LUT[]; /* FIXME: does not belong here */
40 /* Funny to divide them between user and kernel. */
42 /* be careful: always use functions from wctype.h if character > 255 */
45 * Unicode case conversion routines ... these should be used where
46 * toupper/tolower are used for ASCII.
49 /* FIXME: should probably get rid of wctype.h altogether */
52 WCHAR towupper(WCHAR code)
54 const WCHAR * ptr = uprtable[HIBYTE(code)];
55 return ptr ? ptr[LOBYTE(code)] : code;
58 WCHAR towlower(WCHAR code)
60 const WCHAR * ptr = lwrtable[HIBYTE(code)];
61 return ptr ? ptr[LOBYTE(code)] : code;
63 #endif /* HAVE_WCTYPE_H */
65 /***********************************************************************
66 * IsCharAlpha (USER.433)
68 BOOL16 WINAPI IsCharAlpha16(CHAR ch)
70 return isalpha(ch); /* This is probably not right for NLS */
73 /***********************************************************************
74 * IsCharAlphanumeric (USER.434)
76 BOOL16 WINAPI IsCharAlphaNumeric16(CHAR ch)
81 /***********************************************************************
82 * IsCharUpper (USER.435)
84 BOOL16 WINAPI IsCharUpper16(CHAR ch)
89 /***********************************************************************
90 * IsCharLower (USER.436)
92 BOOL16 WINAPI IsCharLower16(CHAR ch)
97 /***********************************************************************
98 * AnsiUpper16 (USER.431)
100 SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar )
102 /* I am not sure if the locale stuff works with toupper, but then again
103 I am not sure if the Linux libc locale stuffs works at all */
105 /* uppercase only one char if strOrChar < 0x10000 */
106 if (HIWORD(strOrChar))
109 for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
112 else return toupper((char)strOrChar);
116 /***********************************************************************
117 * AnsiUpperBuff16 (USER.437)
119 UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len )
121 UINT count = len ? len : 65536;
122 for (; count; count--, str++) *str = toupper(*str);
126 /***********************************************************************
127 * AnsiLower16 (USER.432)
129 SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar )
131 /* I am not sure if the locale stuff works with toupper, but then again
132 I am not sure if the Linux libc locale stuffs works at all */
134 /* lowercase only one char if strOrChar < 0x10000 */
135 if (HIWORD(strOrChar))
138 for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
141 else return tolower((char)strOrChar);
145 /***********************************************************************
146 * AnsiLowerBuff16 (USER.438)
148 UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len )
150 UINT count = len ? len : 65536;
151 for (; count; count--, str++) *str = tolower(*str);
156 /***********************************************************************
157 * AnsiNext16 (USER.472)
159 SEGPTR WINAPI AnsiNext16(SEGPTR current)
161 return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
165 /***********************************************************************
166 * AnsiPrev16 (USER.473)
168 SEGPTR WINAPI AnsiPrev16( SEGPTR start, SEGPTR current )
170 return (current == start) ? start : current - 1;
174 /***********************************************************************
175 * OutputDebugString16 (KERNEL.115)
177 void WINAPI OutputDebugString16( LPCSTR str )
180 if (!GetModuleName16( GetCurrentTask(), module, sizeof(module) ))
181 strcpy( module, "???" );
183 DUMP( "%s says %s\n", module, debugstr_a(str) );
187 /***********************************************************************
188 * OutputDebugString32A (KERNEL32
190 void WINAPI OutputDebugStringA( LPCSTR str )
192 OutputDebugString16( str );
197 /***********************************************************************
198 * OutputDebugString32W (KERNEL32
200 void WINAPI OutputDebugStringW( LPCWSTR str )
202 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
203 OutputDebugStringA( p );
204 HeapFree( GetProcessHeap(), 0, p );
209 /***********************************************************************
210 * CharNext32A (USER32.29)
212 LPSTR WINAPI CharNextA( LPCSTR ptr )
214 if (!*ptr) return (LPSTR)ptr;
215 if (IsDBCSLeadByte( *ptr )) return (LPSTR)(ptr + 2);
216 return (LPSTR)(ptr + 1);
220 /***********************************************************************
221 * CharNextEx32A (USER32.30)
223 LPSTR WINAPI CharNextExA( WORD codepage, LPCSTR ptr, DWORD flags )
225 if (!*ptr) return (LPSTR)ptr;
226 if (IsDBCSLeadByteEx( codepage, *ptr )) return (LPSTR)(ptr + 2);
227 return (LPSTR)(ptr + 1);
231 /***********************************************************************
232 * CharNextExW (USER32.31)
234 LPWSTR WINAPI CharNextExW(WORD codepage,LPCWSTR x,DWORD flags)
236 /* FIXME: add DBCS / codepage stuff */
237 if (*x) return (LPWSTR)(x+1);
238 else return (LPWSTR)x;
241 /***********************************************************************
242 * CharNextW (USER32.32)
244 LPWSTR WINAPI CharNextW(LPCWSTR x)
246 if (*x) return (LPWSTR)(x+1);
247 else return (LPWSTR)x;
250 /***********************************************************************
251 * CharPrev32A (USER32.33)
253 LPSTR WINAPI CharPrevA( LPCSTR start, LPCSTR ptr )
255 while (*start && (start < ptr))
257 LPCSTR next = CharNextA( start );
258 if (next >= ptr) break;
265 /***********************************************************************
266 * CharPrevEx32A (USER32.34)
268 LPSTR WINAPI CharPrevExA( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
270 while (*start && (start < ptr))
272 LPCSTR next = CharNextExA( codepage, start, flags );
273 if (next > ptr) break;
280 /***********************************************************************
281 * CharPrevExW (USER32.35)
283 LPWSTR WINAPI CharPrevExW(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
285 /* FIXME: add DBCS / codepage stuff */
286 if (x>start) return (LPWSTR)(x-1);
287 else return (LPWSTR)x;
290 /***********************************************************************
291 * CharPrevW (USER32.36)
293 LPWSTR WINAPI CharPrevW(LPCWSTR start,LPCWSTR x)
295 if (x>start) return (LPWSTR)(x-1);
296 else return (LPWSTR)x;
299 /***********************************************************************
300 * CharLowerA (USER32.25)
301 * FIXME: handle current locale
303 LPSTR WINAPI CharLowerA(LPSTR x)
317 else return (LPSTR)tolower((char)(int)x);
320 /***********************************************************************
321 * CharLowerBuffA (USER32.26)
322 * FIXME: handle current locale
324 DWORD WINAPI CharLowerBuffA(LPSTR x,DWORD buflen)
328 if (!x) return 0; /* YES */
329 while (*x && (buflen--))
338 /***********************************************************************
339 * CharLowerBuffW (USER32.27)
340 * FIXME: handle current locale
342 DWORD WINAPI CharLowerBuffW(LPWSTR x,DWORD buflen)
346 if (!x) return 0; /* YES */
347 while (*x && (buflen--))
356 /***********************************************************************
357 * CharLowerW (USER32.28)
358 * FIXME: handle current locale
360 LPWSTR WINAPI CharLowerW(LPWSTR x)
372 else return (LPWSTR)((UINT)towlower(LOWORD(x)));
375 /***********************************************************************
376 * CharUpper32A (USER32.41)
377 * FIXME: handle current locale
379 LPSTR WINAPI CharUpperA(LPSTR x)
391 return (LPSTR)toupper((char)(int)x);
394 /***********************************************************************
395 * CharUpperBuffA (USER32.42)
396 * FIXME: handle current locale
398 DWORD WINAPI CharUpperBuffA(LPSTR x,DWORD buflen)
402 if (!x) return 0; /* YES */
403 while (*x && (buflen--))
412 /***********************************************************************
413 * CharUpperBuffW (USER32.43)
414 * FIXME: handle current locale
416 DWORD WINAPI CharUpperBuffW(LPWSTR x,DWORD buflen)
420 if (!x) return 0; /* YES */
421 while (*x && (buflen--))
430 /***********************************************************************
431 * CharUpperW (USER32.44)
432 * FIXME: handle current locale
434 LPWSTR WINAPI CharUpperW(LPWSTR x)
446 else return (LPWSTR)((UINT)towupper(LOWORD(x)));
449 /***********************************************************************
450 * IsCharAlphaA (USER32.331)
451 * FIXME: handle current locale
453 BOOL WINAPI IsCharAlphaA(CHAR x)
455 return (OLE2NLS_CT_CType3_LUT[(unsigned char)x] & C3_ALPHA);
458 /***********************************************************************
459 * IsCharAlphaNumericA (USER32.332)
460 * FIXME: handle current locale
462 BOOL WINAPI IsCharAlphaNumericA(CHAR x)
464 return IsCharAlphaA(x) || isdigit(x) ;
467 /***********************************************************************
468 * IsCharAlphaNumericW (USER32.333)
469 * FIXME: handle current locale
471 BOOL WINAPI IsCharAlphaNumericW(WCHAR x)
476 /***********************************************************************
477 * IsCharAlphaW (USER32.334)
478 * FIXME: handle current locale
480 BOOL WINAPI IsCharAlphaW(WCHAR x)
485 /***********************************************************************
486 * IsCharLower32A (USER32.335)
487 * FIXME: handle current locale
489 BOOL WINAPI IsCharLowerA(CHAR x)
494 /***********************************************************************
495 * IsCharLower32W (USER32.336)
496 * FIXME: handle current locale
498 BOOL WINAPI IsCharLowerW(WCHAR x)
503 /***********************************************************************
504 * IsCharUpper32A (USER32.337)
505 * FIXME: handle current locale
507 BOOL WINAPI IsCharUpperA(CHAR x)
512 /***********************************************************************
513 * IsCharUpper32W (USER32.338)
514 * FIXME: handle current locale
516 BOOL WINAPI IsCharUpperW(WCHAR x)
521 /***********************************************************************
522 * FormatMessage16 (USER.606)
524 DWORD WINAPI FormatMessage16(
531 LPDWORD args /* va_list *args */
533 return FormatMessageA(dwFlags, lpSource, (DWORD)dwMessageId, (DWORD)dwLanguageId, lpBuffer, (DWORD)nSize, args);
536 /***********************************************************************
537 * FormatMessage32A (KERNEL32.138)
538 * FIXME: missing wrap,FROM_SYSTEM message-loading,
540 DWORD WINAPI FormatMessageA(
547 LPDWORD args /* va_list *args */
550 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
554 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
555 DWORD nolinefeed = 0;
557 TRACE(resource, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
558 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
560 FIXME(resource,"line wrapping not supported.\n");
562 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
563 from = HEAP_strdupA( GetProcessHeap(), 0, (LPSTR)lpSource);
564 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
565 from = HeapAlloc( GetProcessHeap(),0,200 );
566 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
568 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
571 dwMessageId &= 0xFFFF;
572 bufsize=LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,NULL,100);
574 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
575 LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
578 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
582 #define ADD_TO_T(c) \
584 if (t-target == talloced) {\
585 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
586 t = target+talloced;\
592 while (*f && !nolinefeed) {
595 char *fmtstr,*sprintfbuf,*x,*lastf;
606 case '1':case '2':case '3':case '4':case '5':
607 case '6':case '7':case '8':case '9':
610 case '0':case '1':case '2':case '3':
611 case '4':case '5':case '6':case '7':
614 insertnr=insertnr*10+*f-'0';
623 if (NULL!=(x=strchr(f,'!'))) {
625 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
626 sprintf(fmtstr,"%%%s",f);
629 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
630 sprintf(fmtstr,"%%%s",f);
631 f+=strlen(f); /*at \0*/
637 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
639 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
640 argliststart=args+insertnr-1;
642 argliststart=(*(DWORD**)args)+insertnr-1;
644 if (fmtstr[strlen(fmtstr)-1]=='s')
645 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
647 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
649 /* CMF - This makes a BIG assumption about va_list */
650 wvsprintfA(sprintfbuf, fmtstr, (va_list) argliststart);
655 HeapFree(GetProcessHeap(),0,sprintfbuf);
657 /* NULL args - copy formatstr
660 while ((lastf<f)&&(*lastf)) {
664 HeapFree(GetProcessHeap(),0,fmtstr);
667 /* FIXME: perhaps add \r too? */
675 default:ADD_TO_T(*f++)
687 if(t==target || t[-1]!='\n')
688 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
690 talloced = strlen(target)+1;
691 if (nSize && talloced<nSize) {
692 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
694 TRACE(resource,"-- %s\n",debugstr_a(target));
695 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
696 /* nSize is the MINIMUM size */
697 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,talloced);
698 memcpy(*(LPSTR*)lpBuffer,target,talloced);
700 strncpy(lpBuffer,target,nSize);
701 HeapFree(GetProcessHeap(),0,target);
702 if (from) HeapFree(GetProcessHeap(),0,from);
703 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
704 strlen(*(LPSTR*)lpBuffer):
708 #endif /* __i386__ */
713 /***********************************************************************
714 * FormatMessage32W (KERNEL32.138)
716 DWORD WINAPI FormatMessageW(
723 LPDWORD args /* va_list *args */
726 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
730 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
731 DWORD nolinefeed = 0;
733 TRACE(resource, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
734 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
736 FIXME(resource,"line wrapping not supported.\n");
738 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
739 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
740 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
741 /* gather information from system message tables ... */
742 from = HeapAlloc( GetProcessHeap(),0,200 );
743 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
745 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
748 dwMessageId &= 0xFFFF;
749 bufsize=LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,NULL,100);
752 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
753 LoadMessageA((HMODULE)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
756 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
760 #define ADD_TO_T(c) \
762 if (t-target == talloced) {\
763 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
764 t = target+talloced;\
770 while (*f && !nolinefeed) {
773 char *fmtstr,*sprintfbuf,*x;
783 case '1':case '2':case '3':case '4':case '5':
784 case '6':case '7':case '8':case '9':
787 case '0':case '1':case '2':case '3':
788 case '4':case '5':case '6':case '7':
791 insertnr=insertnr*10+*f-'0';
800 if (NULL!=(x=strchr(f,'!')))
803 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
804 sprintf(fmtstr,"%%%s",f);
807 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
808 sprintf(fmtstr,"%%%s",f);
809 f+=strlen(f); /*at \0*/
815 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
816 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
817 argliststart=args+insertnr-1;
819 argliststart=(*(DWORD**)args)+insertnr-1;
821 if (fmtstr[strlen(fmtstr)-1]=='s') {
824 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
825 /* possible invalid pointers */
826 xarr[1]=*(argliststart+1);
827 xarr[2]=*(argliststart+2);
828 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlenW((LPWSTR)argliststart[0])*2+1);
830 /* CMF - This makes a BIG assumption about va_list */
831 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
833 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
835 /* CMF - This makes a BIG assumption about va_list */
836 wvsprintfA(sprintfbuf, fmtstr, (va_list) argliststart);
842 HeapFree(GetProcessHeap(),0,sprintfbuf);
843 HeapFree(GetProcessHeap(),0,fmtstr);
846 /* FIXME: perhaps add \r too? */
854 default:ADD_TO_T(*f++)
866 if(t==target || t[-1]!='\n')
867 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
869 talloced = strlen(target)+1;
870 if (nSize && talloced<nSize)
871 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
872 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
873 /* nSize is the MINIMUM size */
874 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,talloced*2+2);
875 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
877 lstrcpynAtoW(lpBuffer,target,nSize);
878 HeapFree(GetProcessHeap(),0,target);
879 if (from) HeapFree(GetProcessHeap(),0,from);
880 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
881 lstrlenW(*(LPWSTR*)lpBuffer):
885 #endif /* __i386__ */