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 */
26 #include "winnt.h" /* HEAP_ macros */
30 #include "stackframe.h"
34 extern const WORD OLE2NLS_CT_CType3_LUT[]; /* FIXME: does not belong here */
37 /* Funny to divide them between user and kernel. */
39 /* be careful: always use functions from wctype.h if character > 255 */
42 * Unicode case conversion routines ... these should be used where
43 * toupper/tolower are used for ASCII.
46 /* FIXME: should probably get rid of wctype.h altogether */
49 WCHAR towupper(WCHAR code)
51 const WCHAR * ptr = uprtable[HIBYTE(code)];
52 return ptr ? ptr[LOBYTE(code)] : code;
55 WCHAR towlower(WCHAR code)
57 const WCHAR * ptr = lwrtable[HIBYTE(code)];
58 return ptr ? ptr[LOBYTE(code)] : code;
60 #endif /* HAVE_WCTYPE_H */
62 /***********************************************************************
63 * IsCharAlpha (USER.433)
65 BOOL16 WINAPI IsCharAlpha16(CHAR ch)
67 return isalpha(ch); /* This is probably not right for NLS */
70 /***********************************************************************
71 * IsCharAlphanumeric (USER.434)
73 BOOL16 WINAPI IsCharAlphaNumeric16(CHAR ch)
78 /***********************************************************************
79 * IsCharUpper (USER.435)
81 BOOL16 WINAPI IsCharUpper16(CHAR ch)
86 /***********************************************************************
87 * IsCharLower (USER.436)
89 BOOL16 WINAPI IsCharLower16(CHAR ch)
94 /***********************************************************************
95 * AnsiUpper16 (USER.431)
97 SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar )
99 /* I am not sure if the locale stuff works with toupper, but then again
100 I am not sure if the Linux libc locale stuffs works at all */
102 /* uppercase only one char if strOrChar < 0x10000 */
103 if (HIWORD(strOrChar))
106 for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
109 else return toupper((char)strOrChar);
113 /***********************************************************************
114 * AnsiUpperBuff16 (USER.437)
116 UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len )
118 UINT32 count = len ? len : 65536;
119 for (; count; count--, str++) *str = toupper(*str);
123 /***********************************************************************
124 * AnsiLower16 (USER.432)
126 SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar )
128 /* I am not sure if the locale stuff works with toupper, but then again
129 I am not sure if the Linux libc locale stuffs works at all */
131 /* lowercase only one char if strOrChar < 0x10000 */
132 if (HIWORD(strOrChar))
135 for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
138 else return tolower((char)strOrChar);
142 /***********************************************************************
143 * AnsiLowerBuff16 (USER.438)
145 UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len )
147 UINT32 count = len ? len : 65536;
148 for (; count; count--, str++) *str = tolower(*str);
153 /***********************************************************************
154 * AnsiNext16 (USER.472)
156 SEGPTR WINAPI AnsiNext16(SEGPTR current)
158 return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
162 /***********************************************************************
163 * AnsiPrev16 (USER.473)
165 SEGPTR WINAPI AnsiPrev16( SEGPTR start, SEGPTR current )
167 return (current == start) ? start : current - 1;
171 /***********************************************************************
172 * OutputDebugString16 (KERNEL.115)
174 void WINAPI OutputDebugString16( LPCSTR str )
177 if (!GetModuleName( GetCurrentTask(), module, sizeof(module) ))
178 strcpy( module, "???" );
180 DUMP( "%s says %s\n", module, debugstr_a(str) );
184 /***********************************************************************
185 * OutputDebugString32A (KERNEL32
187 void WINAPI OutputDebugString32A( LPCSTR str )
189 OutputDebugString16( str );
194 /***********************************************************************
195 * OutputDebugString32W (KERNEL32
197 void WINAPI OutputDebugString32W( LPCWSTR str )
199 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
200 OutputDebugString32A( p );
201 HeapFree( GetProcessHeap(), 0, p );
206 /***********************************************************************
207 * CharNext32A (USER32.29)
209 LPSTR WINAPI CharNext32A( LPCSTR ptr )
211 if (!*ptr) return (LPSTR)ptr;
212 if (IsDBCSLeadByte32( *ptr )) return (LPSTR)(ptr + 2);
213 return (LPSTR)(ptr + 1);
217 /***********************************************************************
218 * CharNextEx32A (USER32.30)
220 LPSTR WINAPI CharNextEx32A( WORD codepage, LPCSTR ptr, DWORD flags )
222 if (!*ptr) return (LPSTR)ptr;
223 if (IsDBCSLeadByteEx( codepage, *ptr )) return (LPSTR)(ptr + 2);
224 return (LPSTR)(ptr + 1);
228 /***********************************************************************
229 * CharNextExW (USER32.31)
231 LPWSTR WINAPI CharNextEx32W(WORD codepage,LPCWSTR x,DWORD flags)
233 /* FIXME: add DBCS / codepage stuff */
234 if (*x) return (LPWSTR)(x+1);
235 else return (LPWSTR)x;
238 /***********************************************************************
239 * CharNextW (USER32.32)
241 LPWSTR WINAPI CharNext32W(LPCWSTR x)
243 if (*x) return (LPWSTR)(x+1);
244 else return (LPWSTR)x;
247 /***********************************************************************
248 * CharPrev32A (USER32.33)
250 LPSTR WINAPI CharPrev32A( LPCSTR start, LPCSTR ptr )
252 while (*start && (start < ptr))
254 LPCSTR next = CharNext32A( start );
255 if (next >= ptr) break;
262 /***********************************************************************
263 * CharPrevEx32A (USER32.34)
265 LPSTR WINAPI CharPrevEx32A( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
267 while (*start && (start < ptr))
269 LPCSTR next = CharNextEx32A( codepage, start, flags );
270 if (next > ptr) break;
277 /***********************************************************************
278 * CharPrevExW (USER32.35)
280 LPWSTR WINAPI CharPrevEx32W(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
282 /* FIXME: add DBCS / codepage stuff */
283 if (x>start) return (LPWSTR)(x-1);
284 else return (LPWSTR)x;
287 /***********************************************************************
288 * CharPrevW (USER32.36)
290 LPWSTR WINAPI CharPrev32W(LPCWSTR start,LPCWSTR x)
292 if (x>start) return (LPWSTR)(x-1);
293 else return (LPWSTR)x;
296 /***********************************************************************
297 * CharLowerA (USER32.25)
298 * FIXME: handle current locale
300 LPSTR WINAPI CharLower32A(LPSTR x)
314 else return (LPSTR)tolower((char)(int)x);
317 /***********************************************************************
318 * CharLowerBuffA (USER32.26)
319 * FIXME: handle current locale
321 DWORD WINAPI CharLowerBuff32A(LPSTR x,DWORD buflen)
325 if (!x) return 0; /* YES */
326 while (*x && (buflen--))
335 /***********************************************************************
336 * CharLowerBuffW (USER32.27)
337 * FIXME: handle current locale
339 DWORD WINAPI CharLowerBuff32W(LPWSTR x,DWORD buflen)
343 if (!x) return 0; /* YES */
344 while (*x && (buflen--))
353 /***********************************************************************
354 * CharLowerW (USER32.28)
355 * FIXME: handle current locale
357 LPWSTR WINAPI CharLower32W(LPWSTR x)
369 else return (LPWSTR)((UINT32)towlower(LOWORD(x)));
372 /***********************************************************************
373 * CharUpper32A (USER32.41)
374 * FIXME: handle current locale
376 LPSTR WINAPI CharUpper32A(LPSTR x)
388 return (LPSTR)toupper((char)(int)x);
391 /***********************************************************************
392 * CharUpperBuffA (USER32.42)
393 * FIXME: handle current locale
395 DWORD WINAPI CharUpperBuff32A(LPSTR x,DWORD buflen)
399 if (!x) return 0; /* YES */
400 while (*x && (buflen--))
409 /***********************************************************************
410 * CharUpperBuffW (USER32.43)
411 * FIXME: handle current locale
413 DWORD WINAPI CharUpperBuff32W(LPWSTR x,DWORD buflen)
417 if (!x) return 0; /* YES */
418 while (*x && (buflen--))
427 /***********************************************************************
428 * CharUpperW (USER32.44)
429 * FIXME: handle current locale
431 LPWSTR WINAPI CharUpper32W(LPWSTR x)
443 else return (LPWSTR)((UINT32)towupper(LOWORD(x)));
446 /***********************************************************************
447 * IsCharAlphaA (USER32.331)
448 * FIXME: handle current locale
450 BOOL32 WINAPI IsCharAlpha32A(CHAR x)
452 return (OLE2NLS_CT_CType3_LUT[(unsigned char)x] & C3_ALPHA);
455 /***********************************************************************
456 * IsCharAlphaNumericA (USER32.332)
457 * FIXME: handle current locale
459 BOOL32 WINAPI IsCharAlphaNumeric32A(CHAR x)
461 return IsCharAlpha32A(x) || isdigit(x) ;
464 /***********************************************************************
465 * IsCharAlphaNumericW (USER32.333)
466 * FIXME: handle current locale
468 BOOL32 WINAPI IsCharAlphaNumeric32W(WCHAR x)
473 /***********************************************************************
474 * IsCharAlphaW (USER32.334)
475 * FIXME: handle current locale
477 BOOL32 WINAPI IsCharAlpha32W(WCHAR x)
482 /***********************************************************************
483 * IsCharLower32A (USER32.335)
484 * FIXME: handle current locale
486 BOOL32 WINAPI IsCharLower32A(CHAR x)
491 /***********************************************************************
492 * IsCharLower32W (USER32.336)
493 * FIXME: handle current locale
495 BOOL32 WINAPI IsCharLower32W(WCHAR x)
500 /***********************************************************************
501 * IsCharUpper32A (USER32.337)
502 * FIXME: handle current locale
504 BOOL32 WINAPI IsCharUpper32A(CHAR x)
509 /***********************************************************************
510 * IsCharUpper32W (USER32.338)
511 * FIXME: handle current locale
513 BOOL32 WINAPI IsCharUpper32W(WCHAR x)
518 /***********************************************************************
519 * FormatMessage16 (USER.606)
521 DWORD WINAPI FormatMessage16(
528 LPDWORD args /* va_list *args */
530 return FormatMessage32A(dwFlags, lpSource, (DWORD)dwMessageId, (DWORD)dwLanguageId, lpBuffer, (DWORD)nSize, args);
533 /***********************************************************************
534 * FormatMessage32A (KERNEL32.138)
535 * FIXME: missing wrap,FROM_SYSTEM message-loading,
537 DWORD WINAPI FormatMessage32A(
544 LPDWORD args /* va_list *args */
547 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
551 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
552 DWORD nolinefeed = 0;
554 TRACE(resource, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
555 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
557 FIXME(resource,"line wrapping not supported.\n");
559 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
560 from = HEAP_strdupA( GetProcessHeap(), 0, (LPSTR)lpSource);
561 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
562 from = HeapAlloc( GetProcessHeap(),0,200 );
563 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
565 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
568 dwMessageId &= 0xFFFF;
569 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
571 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
572 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
575 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
579 #define ADD_TO_T(c) \
581 if (t-target == talloced) {\
582 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
583 t = target+talloced;\
589 while (*f && !nolinefeed) {
592 char *fmtstr,*sprintfbuf,*x,*lastf;
603 case '1':case '2':case '3':case '4':case '5':
604 case '6':case '7':case '8':case '9':
607 case '0':case '1':case '2':case '3':
608 case '4':case '5':case '6':case '7':
611 insertnr=insertnr*10+*f-'0';
620 if (NULL!=(x=strchr(f,'!'))) {
622 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
623 sprintf(fmtstr,"%%%s",f);
626 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
627 sprintf(fmtstr,"%%%s",f);
628 f+=strlen(f); /*at \0*/
634 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
636 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
637 argliststart=args+insertnr-1;
639 argliststart=(*(DWORD**)args)+insertnr-1;
641 if (fmtstr[strlen(fmtstr)-1]=='s')
642 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
644 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
646 /* CMF - This makes a BIG assumption about va_list */
647 wvsprintf32A(sprintfbuf, fmtstr, (va_list) argliststart);
652 HeapFree(GetProcessHeap(),0,sprintfbuf);
654 /* NULL args - copy formatstr
657 while ((lastf<f)&&(*lastf)) {
661 HeapFree(GetProcessHeap(),0,fmtstr);
664 /* FIXME: perhaps add \r too? */
672 default:ADD_TO_T(*f++)
684 if(t==target || t[-1]!='\n')
685 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
687 talloced = strlen(target)+1;
688 if (nSize && talloced<nSize) {
689 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
691 TRACE(resource,"-- %s\n",debugstr_a(target));
692 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
693 /* nSize is the MINIMUM size */
694 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced);
695 memcpy(*(LPSTR*)lpBuffer,target,talloced);
697 strncpy(lpBuffer,target,nSize);
698 HeapFree(GetProcessHeap(),0,target);
699 if (from) HeapFree(GetProcessHeap(),0,from);
700 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
701 strlen(*(LPSTR*)lpBuffer):
705 #endif /* __i386__ */
710 /***********************************************************************
711 * FormatMessage32W (KERNEL32.138)
713 DWORD WINAPI FormatMessage32W(
720 LPDWORD args /* va_list *args */
723 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
727 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
728 DWORD nolinefeed = 0;
730 TRACE(resource, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
731 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
733 FIXME(resource,"line wrapping not supported.\n");
735 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
736 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
737 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
738 /* gather information from system message tables ... */
739 from = HeapAlloc( GetProcessHeap(),0,200 );
740 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
742 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
745 dwMessageId &= 0xFFFF;
746 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
749 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
750 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
753 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
757 #define ADD_TO_T(c) \
759 if (t-target == talloced) {\
760 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
761 t = target+talloced;\
767 while (*f && !nolinefeed) {
770 char *fmtstr,*sprintfbuf,*x;
780 case '1':case '2':case '3':case '4':case '5':
781 case '6':case '7':case '8':case '9':
784 case '0':case '1':case '2':case '3':
785 case '4':case '5':case '6':case '7':
788 insertnr=insertnr*10+*f-'0';
797 if (NULL!=(x=strchr(f,'!')))
800 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
801 sprintf(fmtstr,"%%%s",f);
804 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
805 sprintf(fmtstr,"%%%s",f);
806 f+=strlen(f); /*at \0*/
812 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
813 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
814 argliststart=args+insertnr-1;
816 argliststart=(*(DWORD**)args)+insertnr-1;
818 if (fmtstr[strlen(fmtstr)-1]=='s') {
821 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
822 /* possible invalid pointers */
823 xarr[1]=*(argliststart+1);
824 xarr[2]=*(argliststart+2);
825 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR)argliststart[0])*2+1);
827 /* CMF - This makes a BIG assumption about va_list */
828 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
830 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
832 /* CMF - This makes a BIG assumption about va_list */
833 wvsprintf32A(sprintfbuf, fmtstr, (va_list) argliststart);
839 HeapFree(GetProcessHeap(),0,sprintfbuf);
840 HeapFree(GetProcessHeap(),0,fmtstr);
843 /* FIXME: perhaps add \r too? */
851 default:ADD_TO_T(*f++)
863 if(t==target || t[-1]!='\n')
864 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
866 talloced = strlen(target)+1;
867 if (nSize && talloced<nSize)
868 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
869 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
870 /* nSize is the MINIMUM size */
871 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced*2+2);
872 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
874 lstrcpynAtoW(lpBuffer,target,nSize);
875 HeapFree(GetProcessHeap(),0,target);
876 if (from) HeapFree(GetProcessHeap(),0,from);
877 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
878 lstrlen32W(*(LPWSTR*)lpBuffer):
879 lstrlen32W(lpBuffer);
882 #endif /* __i386__ */