4 * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5 * Copyright 1996 Marcus Meissner
19 # define towlower(c) tolower(c)
20 # define towupper(c) toupper(c)
21 # define iswalnum(c) isalnum(c)
22 # define iswalpha(c) isalpha(c)
23 # define iswupper(c) isupper(c)
24 # define iswlower(c) islower(c)
25 #endif /* HAVE_WCTYPE_H */
29 #include "winnt.h" /* HEAP_ macros */
33 #include "stackframe.h"
37 /* Funny to divide them between user and kernel. */
39 /* be careful: always use functions from wctype.h if character > 255 */
41 /***********************************************************************
42 * IsCharAlpha (USER.433)
44 BOOL16 WINAPI IsCharAlpha16(CHAR ch)
46 return isalpha(ch); /* This is probably not right for NLS */
49 /***********************************************************************
50 * IsCharAlphanumeric (USER.434)
52 BOOL16 WINAPI IsCharAlphaNumeric16(CHAR ch)
57 /***********************************************************************
58 * IsCharUpper (USER.435)
60 BOOL16 WINAPI IsCharUpper16(CHAR ch)
65 /***********************************************************************
66 * IsCharLower (USER.436)
68 BOOL16 WINAPI IsCharLower16(CHAR ch)
73 /***********************************************************************
74 * AnsiUpper16 (USER.431)
76 SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar )
78 /* I am not sure if the locale stuff works with toupper, but then again
79 I am not sure if the Linux libc locale stuffs works at all */
81 /* uppercase only one char if strOrChar < 0x10000 */
82 if (HIWORD(strOrChar))
85 for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
88 else return toupper((char)strOrChar);
92 /***********************************************************************
93 * AnsiUpperBuff16 (USER.437)
95 UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len )
97 UINT32 count = len ? len : 65536;
98 for (; count; count--, str++) *str = toupper(*str);
102 /***********************************************************************
103 * AnsiLower16 (USER.432)
105 SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar )
107 /* I am not sure if the locale stuff works with toupper, but then again
108 I am not sure if the Linux libc locale stuffs works at all */
110 /* lowercase only one char if strOrChar < 0x10000 */
111 if (HIWORD(strOrChar))
114 for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
117 else return tolower((char)strOrChar);
121 /***********************************************************************
122 * AnsiLowerBuff16 (USER.438)
124 UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len )
126 UINT32 count = len ? len : 65536;
127 for (; count; count--, str++) *str = tolower(*str);
132 /***********************************************************************
133 * AnsiNext16 (USER.472)
135 SEGPTR WINAPI AnsiNext16(SEGPTR current)
137 return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
141 /***********************************************************************
142 * AnsiPrev16 (USER.473)
144 SEGPTR WINAPI AnsiPrev16( SEGPTR start, SEGPTR current )
146 return (current == start) ? start : current - 1;
150 /***********************************************************************
151 * OutputDebugString16 (KERNEL.115)
153 void WINAPI OutputDebugString16( LPCSTR str )
156 char *p, *buffer = HeapAlloc( GetProcessHeap(), 0, strlen(str)+2 );
158 for (p = buffer; *str; str++) if (*str != '\r') *p++ = *str;
160 if ((p > buffer) && (p[-1] == '\n')) p[1] = '\0'; /* Remove trailing \n */
161 module = MODULE_GetModuleName( GetCurrentTask() );
162 TRACE(resource, "%s says '%s'\n",
163 module ? module : "???", buffer );
164 HeapFree( GetProcessHeap(), 0, buffer );
168 /***********************************************************************
169 * OutputDebugString32A (KERNEL32
171 void WINAPI OutputDebugString32A( LPCSTR str )
173 OutputDebugString16( str );
178 /***********************************************************************
179 * OutputDebugString32W (KERNEL32
181 void WINAPI OutputDebugString32W( LPCWSTR str )
183 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
184 OutputDebugString32A( p );
185 HeapFree( GetProcessHeap(), 0, p );
190 /***********************************************************************
191 * CharNext32A (USER32.29)
193 LPSTR WINAPI CharNext32A( LPCSTR ptr )
195 if (!*ptr) return (LPSTR)ptr;
196 if (IsDBCSLeadByte32( *ptr )) return (LPSTR)(ptr + 2);
197 return (LPSTR)(ptr + 1);
201 /***********************************************************************
202 * CharNextEx32A (USER32.30)
204 LPSTR WINAPI CharNextEx32A( WORD codepage, LPCSTR ptr, DWORD flags )
206 if (!*ptr) return (LPSTR)ptr;
207 if (IsDBCSLeadByteEx( codepage, *ptr )) return (LPSTR)(ptr + 2);
208 return (LPSTR)(ptr + 1);
212 /***********************************************************************
213 * CharNextExW (USER32.31)
215 LPWSTR WINAPI CharNextEx32W(WORD codepage,LPCWSTR x,DWORD flags)
217 /* FIXME: add DBCS / codepage stuff */
218 if (*x) return (LPWSTR)(x+1);
219 else return (LPWSTR)x;
222 /***********************************************************************
223 * CharNextW (USER32.32)
225 LPWSTR WINAPI CharNext32W(LPCWSTR x)
227 if (*x) return (LPWSTR)(x+1);
228 else return (LPWSTR)x;
231 /***********************************************************************
232 * CharPrev32A (USER32.33)
234 LPSTR WINAPI CharPrev32A( LPCSTR start, LPCSTR ptr )
236 while (*start && (start < ptr))
238 LPCSTR next = CharNext32A( start );
239 if (next >= ptr) break;
246 /***********************************************************************
247 * CharPrevEx32A (USER32.34)
249 LPSTR WINAPI CharPrevEx32A( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
251 while (*start && (start < ptr))
253 LPCSTR next = CharNextEx32A( codepage, start, flags );
254 if (next > ptr) break;
261 /***********************************************************************
262 * CharPrevExW (USER32.35)
264 LPWSTR WINAPI CharPrevEx32W(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
266 /* FIXME: add DBCS / codepage stuff */
267 if (x>start) return (LPWSTR)(x-1);
268 else return (LPWSTR)x;
271 /***********************************************************************
272 * CharPrevW (USER32.36)
274 LPWSTR WINAPI CharPrev32W(LPCWSTR start,LPCWSTR x)
276 if (x>start) return (LPWSTR)(x-1);
277 else return (LPWSTR)x;
280 /***********************************************************************
281 * CharLowerA (USER32.25)
282 * FIXME: handle current locale
284 LPSTR WINAPI CharLower32A(LPSTR x)
298 else return (LPSTR)tolower((char)(int)x);
301 /***********************************************************************
302 * CharLowerBuffA (USER32.26)
303 * FIXME: handle current locale
305 DWORD WINAPI CharLowerBuff32A(LPSTR x,DWORD buflen)
309 if (!x) return 0; /* YES */
310 while (*x && (buflen--))
319 /***********************************************************************
320 * CharLowerBuffW (USER32.27)
321 * FIXME: handle current locale
323 DWORD WINAPI CharLowerBuff32W(LPWSTR x,DWORD buflen)
327 if (!x) return 0; /* YES */
328 while (*x && (buflen--))
337 /***********************************************************************
338 * CharLowerW (USER32.28)
339 * FIXME: handle current locale
341 LPWSTR WINAPI CharLower32W(LPWSTR x)
353 else return (LPWSTR)towlower(LOWORD(x));
356 /***********************************************************************
357 * CharUpper32A (USER32.41)
358 * FIXME: handle current locale
360 LPSTR WINAPI CharUpper32A(LPSTR x)
372 return (LPSTR)toupper((char)(int)x);
375 /***********************************************************************
376 * CharUpperBuffA (USER32.42)
377 * FIXME: handle current locale
379 DWORD WINAPI CharUpperBuff32A(LPSTR x,DWORD buflen)
383 if (!x) return 0; /* YES */
384 while (*x && (buflen--))
393 /***********************************************************************
394 * CharUpperBuffW (USER32.43)
395 * FIXME: handle current locale
397 DWORD WINAPI CharUpperBuff32W(LPWSTR x,DWORD buflen)
401 if (!x) return 0; /* YES */
402 while (*x && (buflen--))
411 /***********************************************************************
412 * CharUpperW (USER32.44)
413 * FIXME: handle current locale
415 LPWSTR WINAPI CharUpper32W(LPWSTR x)
427 else return (LPWSTR)towupper(LOWORD(x));
430 /***********************************************************************
431 * IsCharAlphaA (USER32.331)
432 * FIXME: handle current locale
434 BOOL32 WINAPI IsCharAlpha32A(CHAR x)
439 /***********************************************************************
440 * IsCharAlphaNumericA (USER32.332)
441 * FIXME: handle current locale
443 BOOL32 WINAPI IsCharAlphaNumeric32A(CHAR x)
448 /***********************************************************************
449 * IsCharAlphaNumericW (USER32.333)
450 * FIXME: handle current locale
452 BOOL32 WINAPI IsCharAlphaNumeric32W(WCHAR x)
457 /***********************************************************************
458 * IsCharAlphaW (USER32.334)
459 * FIXME: handle current locale
461 BOOL32 WINAPI IsCharAlpha32W(WCHAR x)
466 /***********************************************************************
467 * IsCharLower32A (USER32.335)
468 * FIXME: handle current locale
470 BOOL32 WINAPI IsCharLower32A(CHAR x)
475 /***********************************************************************
476 * IsCharLower32W (USER32.336)
477 * FIXME: handle current locale
479 BOOL32 WINAPI IsCharLower32W(WCHAR x)
484 /***********************************************************************
485 * IsCharUpper32A (USER32.337)
486 * FIXME: handle current locale
488 BOOL32 WINAPI IsCharUpper32A(CHAR x)
493 /***********************************************************************
494 * IsCharUpper32W (USER32.338)
495 * FIXME: handle current locale
497 BOOL32 WINAPI IsCharUpper32W(WCHAR x)
502 /***********************************************************************
503 * FormatMessage32A (KERNEL32.138)
504 * FIXME: missing wrap,FROM_SYSTEM message-loading,
506 DWORD WINAPI FormatMessage32A(
513 LPDWORD args /* va_list *args */
518 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
519 DWORD nolinefeed = 0;
521 TRACE(resource, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
522 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
524 FIXME(resource,"line wrapping not supported.\n");
526 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
527 from = HEAP_strdupA( GetProcessHeap(), 0, (LPSTR)lpSource);
528 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
529 from = HeapAlloc( GetProcessHeap(),0,200 );
530 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
532 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
535 dwMessageId &= 0xFFFF;
536 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
538 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
539 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
542 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
546 #define ADD_TO_T(c) \
548 if (t-target == talloced) {\
549 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
550 t = target+talloced;\
559 char *fmtstr,*sprintfbuf,*x,*lastf;
570 case '1':case '2':case '3':case '4':case '5':
571 case '6':case '7':case '8':case '9':
574 case '0':case '1':case '2':case '3':
575 case '4':case '5':case '6':case '7':
578 insertnr=insertnr*10+*f-'0';
587 if (NULL!=(x=strchr(f,'!'))) {
589 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
590 sprintf(fmtstr,"%%%s",f);
593 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
594 sprintf(fmtstr,"%%%s",f);
595 f+=strlen(f); /*at \0*/
601 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
603 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
604 argliststart=args+insertnr-1;
606 argliststart=(*(DWORD**)args)+insertnr-1;
608 if (fmtstr[strlen(fmtstr)-1]=='s')
609 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
611 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
613 /* CMF - This makes a BIG assumption about va_list */
614 wvsprintf32A(sprintfbuf, fmtstr, (va_list) argliststart);
619 HeapFree(GetProcessHeap(),0,sprintfbuf);
621 /* NULL args - copy formatstr
624 while ((lastf<f)&&(*lastf)) {
628 HeapFree(GetProcessHeap(),0,fmtstr);
631 /* FIXME: perhaps add \r too? */
639 default:ADD_TO_T(*f++)
650 /* remove linefeed */
651 if(t>target && t[-1]=='\n') {
653 if(t>target && t[-1]=='\r')
658 if(t==target || t[-1]!='\n')
659 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
661 talloced = strlen(target)+1;
662 if (nSize && talloced<nSize) {
663 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
665 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
666 /* nSize is the MINIMUM size */
667 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced);
668 memcpy(*(LPSTR*)lpBuffer,target,talloced);
670 strncpy(lpBuffer,target,nSize);
671 HeapFree(GetProcessHeap(),0,target);
672 if (from) HeapFree(GetProcessHeap(),0,from);
673 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
674 strlen(*(LPSTR*)lpBuffer):
680 /***********************************************************************
681 * FormatMessage32W (KERNEL32.138)
683 DWORD WINAPI FormatMessage32W(
690 LPDWORD args /* va_list *args */
695 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
696 DWORD nolinefeed = 0;
698 TRACE(resource, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
699 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
701 FIXME(resource,"line wrapping not supported.\n");
703 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
704 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
705 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
706 /* gather information from system message tables ... */
707 from = HeapAlloc( GetProcessHeap(),0,200 );
708 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
710 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
713 dwMessageId &= 0xFFFF;
714 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
717 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
718 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
721 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
725 #define ADD_TO_T(c) \
727 if (t-target == talloced) {\
728 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
729 t = target+talloced;\
738 char *fmtstr,*sprintfbuf,*x;
748 case '1':case '2':case '3':case '4':case '5':
749 case '6':case '7':case '8':case '9':
752 case '0':case '1':case '2':case '3':
753 case '4':case '5':case '6':case '7':
756 insertnr=insertnr*10+*f-'0';
765 if (NULL!=(x=strchr(f,'!')))
768 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
769 sprintf(fmtstr,"%%%s",f);
772 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
773 sprintf(fmtstr,"%%%s",f);
774 f+=strlen(f); /*at \0*/
780 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
781 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
782 argliststart=args+insertnr-1;
784 argliststart=(*(DWORD**)args)+insertnr-1;
786 if (fmtstr[strlen(fmtstr)-1]=='s') {
789 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
790 /* possible invalid pointers */
791 xarr[1]=*(argliststart+1);
792 xarr[2]=*(argliststart+2);
793 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR)argliststart[0])*2+1);
795 /* CMF - This makes a BIG assumption about va_list */
796 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
798 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
800 /* CMF - This makes a BIG assumption about va_list */
801 wvsprintf32A(sprintfbuf, fmtstr, (va_list) argliststart);
807 HeapFree(GetProcessHeap(),0,sprintfbuf);
808 HeapFree(GetProcessHeap(),0,fmtstr);
811 /* FIXME: perhaps add \r too? */
819 default:ADD_TO_T(*f++)
830 /* remove linefeed */
831 if(t>target && t[-1]=='\n') {
833 if(t>target && t[-1]=='\r')
838 if(t==target || t[-1]!='\n')
839 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
841 talloced = strlen(target)+1;
842 if (nSize && talloced<nSize)
843 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
844 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
845 /* nSize is the MINIMUM size */
846 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced*2+2);
847 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
849 lstrcpynAtoW(lpBuffer,target,nSize);
850 HeapFree(GetProcessHeap(),0,target);
851 if (from) HeapFree(GetProcessHeap(),0,from);
852 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
853 lstrlen32W(*(LPWSTR*)lpBuffer):
854 lstrlen32W(lpBuffer);