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 /* Funny to divide them between user and kernel. */
36 /* be careful: always use functions from wctype.h if character > 255 */
39 * Unicode case conversion routines ... these should be used where
40 * toupper/tolower are used for ASCII.
43 /* FIXME: should probably get rid of wctype.h altogether */
46 WCHAR
towupper(WCHAR code
)
48 const WCHAR
* ptr
= uprtable
[HIBYTE(code
)];
49 return ptr
? ptr
[LOBYTE(code
)] : code
;
52 WCHAR
towlower(WCHAR code
)
54 const WCHAR
* ptr
= lwrtable
[HIBYTE(code
)];
55 return ptr
? ptr
[LOBYTE(code
)] : code
;
57 #endif /* HAVE_WCTYPE_H */
59 /***********************************************************************
60 * IsCharAlpha (USER.433)
62 BOOL16 WINAPI
IsCharAlpha16(CHAR ch
)
64 return isalpha(ch
); /* This is probably not right for NLS */
67 /***********************************************************************
68 * IsCharAlphanumeric (USER.434)
70 BOOL16 WINAPI
IsCharAlphaNumeric16(CHAR ch
)
75 /***********************************************************************
76 * IsCharUpper (USER.435)
78 BOOL16 WINAPI
IsCharUpper16(CHAR ch
)
83 /***********************************************************************
84 * IsCharLower (USER.436)
86 BOOL16 WINAPI
IsCharLower16(CHAR ch
)
91 /***********************************************************************
92 * AnsiUpper16 (USER.431)
94 SEGPTR WINAPI
AnsiUpper16( 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
))
103 for (s
= PTR_SEG_TO_LIN(strOrChar
); *s
; s
++) *s
= toupper(*s
);
106 else return toupper((char)strOrChar
);
110 /***********************************************************************
111 * AnsiUpperBuff16 (USER.437)
113 UINT16 WINAPI
AnsiUpperBuff16( LPSTR str
, UINT16 len
)
115 UINT32 count
= len
? len
: 65536;
116 for (; count
; count
--, str
++) *str
= toupper(*str
);
120 /***********************************************************************
121 * AnsiLower16 (USER.432)
123 SEGPTR WINAPI
AnsiLower16( SEGPTR strOrChar
)
125 /* I am not sure if the locale stuff works with toupper, but then again
126 I am not sure if the Linux libc locale stuffs works at all */
128 /* lowercase only one char if strOrChar < 0x10000 */
129 if (HIWORD(strOrChar
))
132 for (s
= PTR_SEG_TO_LIN( strOrChar
); *s
; s
++) *s
= tolower( *s
);
135 else return tolower((char)strOrChar
);
139 /***********************************************************************
140 * AnsiLowerBuff16 (USER.438)
142 UINT16 WINAPI
AnsiLowerBuff16( LPSTR str
, UINT16 len
)
144 UINT32 count
= len
? len
: 65536;
145 for (; count
; count
--, str
++) *str
= tolower(*str
);
150 /***********************************************************************
151 * AnsiNext16 (USER.472)
153 SEGPTR WINAPI
AnsiNext16(SEGPTR current
)
155 return (*(char *)PTR_SEG_TO_LIN(current
)) ? current
+ 1 : current
;
159 /***********************************************************************
160 * AnsiPrev16 (USER.473)
162 SEGPTR WINAPI
AnsiPrev16( SEGPTR start
, SEGPTR current
)
164 return (current
== start
) ? start
: current
- 1;
168 /***********************************************************************
169 * OutputDebugString16 (KERNEL.115)
171 void WINAPI
OutputDebugString16( LPCSTR str
)
174 if (!GetModuleName( GetCurrentTask(), module
, sizeof(module
) ))
175 strcpy( module
, "???" );
177 DUMP( "%s says %s\n", module
, debugstr_a(str
) );
181 /***********************************************************************
182 * OutputDebugString32A (KERNEL32
184 void WINAPI
OutputDebugString32A( LPCSTR str
)
186 OutputDebugString16( str
);
191 /***********************************************************************
192 * OutputDebugString32W (KERNEL32
194 void WINAPI
OutputDebugString32W( LPCWSTR str
)
196 LPSTR p
= HEAP_strdupWtoA( GetProcessHeap(), 0, str
);
197 OutputDebugString32A( p
);
198 HeapFree( GetProcessHeap(), 0, p
);
203 /***********************************************************************
204 * CharNext32A (USER32.29)
206 LPSTR WINAPI
CharNext32A( LPCSTR ptr
)
208 if (!*ptr
) return (LPSTR
)ptr
;
209 if (IsDBCSLeadByte32( *ptr
)) return (LPSTR
)(ptr
+ 2);
210 return (LPSTR
)(ptr
+ 1);
214 /***********************************************************************
215 * CharNextEx32A (USER32.30)
217 LPSTR WINAPI
CharNextEx32A( WORD codepage
, LPCSTR ptr
, DWORD flags
)
219 if (!*ptr
) return (LPSTR
)ptr
;
220 if (IsDBCSLeadByteEx( codepage
, *ptr
)) return (LPSTR
)(ptr
+ 2);
221 return (LPSTR
)(ptr
+ 1);
225 /***********************************************************************
226 * CharNextExW (USER32.31)
228 LPWSTR WINAPI
CharNextEx32W(WORD codepage
,LPCWSTR x
,DWORD flags
)
230 /* FIXME: add DBCS / codepage stuff */
231 if (*x
) return (LPWSTR
)(x
+1);
232 else return (LPWSTR
)x
;
235 /***********************************************************************
236 * CharNextW (USER32.32)
238 LPWSTR WINAPI
CharNext32W(LPCWSTR x
)
240 if (*x
) return (LPWSTR
)(x
+1);
241 else return (LPWSTR
)x
;
244 /***********************************************************************
245 * CharPrev32A (USER32.33)
247 LPSTR WINAPI
CharPrev32A( LPCSTR start
, LPCSTR ptr
)
249 while (*start
&& (start
< ptr
))
251 LPCSTR next
= CharNext32A( start
);
252 if (next
>= ptr
) break;
259 /***********************************************************************
260 * CharPrevEx32A (USER32.34)
262 LPSTR WINAPI
CharPrevEx32A( WORD codepage
, LPCSTR start
, LPCSTR ptr
, DWORD flags
)
264 while (*start
&& (start
< ptr
))
266 LPCSTR next
= CharNextEx32A( codepage
, start
, flags
);
267 if (next
> ptr
) break;
274 /***********************************************************************
275 * CharPrevExW (USER32.35)
277 LPWSTR WINAPI
CharPrevEx32W(WORD codepage
,LPCWSTR start
,LPCWSTR x
,DWORD flags
)
279 /* FIXME: add DBCS / codepage stuff */
280 if (x
>start
) return (LPWSTR
)(x
-1);
281 else return (LPWSTR
)x
;
284 /***********************************************************************
285 * CharPrevW (USER32.36)
287 LPWSTR WINAPI
CharPrev32W(LPCWSTR start
,LPCWSTR x
)
289 if (x
>start
) return (LPWSTR
)(x
-1);
290 else return (LPWSTR
)x
;
293 /***********************************************************************
294 * CharLowerA (USER32.25)
295 * FIXME: handle current locale
297 LPSTR WINAPI
CharLower32A(LPSTR x
)
311 else return (LPSTR
)tolower((char)(int)x
);
314 /***********************************************************************
315 * CharLowerBuffA (USER32.26)
316 * FIXME: handle current locale
318 DWORD WINAPI
CharLowerBuff32A(LPSTR x
,DWORD buflen
)
322 if (!x
) return 0; /* YES */
323 while (*x
&& (buflen
--))
332 /***********************************************************************
333 * CharLowerBuffW (USER32.27)
334 * FIXME: handle current locale
336 DWORD WINAPI
CharLowerBuff32W(LPWSTR x
,DWORD buflen
)
340 if (!x
) return 0; /* YES */
341 while (*x
&& (buflen
--))
350 /***********************************************************************
351 * CharLowerW (USER32.28)
352 * FIXME: handle current locale
354 LPWSTR WINAPI
CharLower32W(LPWSTR x
)
366 else return (LPWSTR
)((UINT32
)towlower(LOWORD(x
)));
369 /***********************************************************************
370 * CharUpper32A (USER32.41)
371 * FIXME: handle current locale
373 LPSTR WINAPI
CharUpper32A(LPSTR x
)
385 return (LPSTR
)toupper((char)(int)x
);
388 /***********************************************************************
389 * CharUpperBuffA (USER32.42)
390 * FIXME: handle current locale
392 DWORD WINAPI
CharUpperBuff32A(LPSTR x
,DWORD buflen
)
396 if (!x
) return 0; /* YES */
397 while (*x
&& (buflen
--))
406 /***********************************************************************
407 * CharUpperBuffW (USER32.43)
408 * FIXME: handle current locale
410 DWORD WINAPI
CharUpperBuff32W(LPWSTR x
,DWORD buflen
)
414 if (!x
) return 0; /* YES */
415 while (*x
&& (buflen
--))
424 /***********************************************************************
425 * CharUpperW (USER32.44)
426 * FIXME: handle current locale
428 LPWSTR WINAPI
CharUpper32W(LPWSTR x
)
440 else return (LPWSTR
)((UINT32
)towupper(LOWORD(x
)));
443 /***********************************************************************
444 * IsCharAlphaA (USER32.331)
445 * FIXME: handle current locale
447 BOOL32 WINAPI
IsCharAlpha32A(CHAR x
)
452 /***********************************************************************
453 * IsCharAlphaNumericA (USER32.332)
454 * FIXME: handle current locale
456 BOOL32 WINAPI
IsCharAlphaNumeric32A(CHAR x
)
461 /***********************************************************************
462 * IsCharAlphaNumericW (USER32.333)
463 * FIXME: handle current locale
465 BOOL32 WINAPI
IsCharAlphaNumeric32W(WCHAR x
)
470 /***********************************************************************
471 * IsCharAlphaW (USER32.334)
472 * FIXME: handle current locale
474 BOOL32 WINAPI
IsCharAlpha32W(WCHAR x
)
479 /***********************************************************************
480 * IsCharLower32A (USER32.335)
481 * FIXME: handle current locale
483 BOOL32 WINAPI
IsCharLower32A(CHAR x
)
488 /***********************************************************************
489 * IsCharLower32W (USER32.336)
490 * FIXME: handle current locale
492 BOOL32 WINAPI
IsCharLower32W(WCHAR x
)
497 /***********************************************************************
498 * IsCharUpper32A (USER32.337)
499 * FIXME: handle current locale
501 BOOL32 WINAPI
IsCharUpper32A(CHAR x
)
506 /***********************************************************************
507 * IsCharUpper32W (USER32.338)
508 * FIXME: handle current locale
510 BOOL32 WINAPI
IsCharUpper32W(WCHAR x
)
515 /***********************************************************************
516 * FormatMessage16 (USER.606)
518 DWORD WINAPI
FormatMessage16(
525 LPDWORD args
/* va_list *args */
527 return FormatMessage32A(dwFlags
, lpSource
, (DWORD
)dwMessageId
, (DWORD
)dwLanguageId
, lpBuffer
, (DWORD
)nSize
, args
);
530 /***********************************************************************
531 * FormatMessage32A (KERNEL32.138)
532 * FIXME: missing wrap,FROM_SYSTEM message-loading,
534 DWORD WINAPI
FormatMessage32A(
541 LPDWORD args
/* va_list *args */
546 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
547 DWORD nolinefeed
= 0;
549 TRACE(resource
, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
550 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
);
552 FIXME(resource
,"line wrapping not supported.\n");
554 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
555 from
= HEAP_strdupA( GetProcessHeap(), 0, (LPSTR
)lpSource
);
556 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
557 from
= HeapAlloc( GetProcessHeap(),0,200 );
558 sprintf(from
,"Systemmessage, messageid = 0x%08lx\n",dwMessageId
);
560 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
563 dwMessageId
&= 0xFFFF;
564 bufsize
=LoadMessage32A((HMODULE32
)lpSource
,dwMessageId
,dwLanguageId
,NULL
,100);
566 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
567 LoadMessage32A((HMODULE32
)lpSource
,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
570 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100);
574 #define ADD_TO_T(c) \
576 if (t-target == talloced) {\
577 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
578 t = target+talloced;\
584 while (*f
&& !nolinefeed
) {
587 char *fmtstr
,*sprintfbuf
,*x
,*lastf
;
598 case '1':case '2':case '3':case '4':case '5':
599 case '6':case '7':case '8':case '9':
602 case '0':case '1':case '2':case '3':
603 case '4':case '5':case '6':case '7':
606 insertnr
=insertnr
*10+*f
-'0';
615 if (NULL
!=(x
=strchr(f
,'!'))) {
617 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
)+2);
618 sprintf(fmtstr
,"%%%s",f
);
621 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
));
622 sprintf(fmtstr
,"%%%s",f
);
623 f
+=strlen(f
); /*at \0*/
629 fmtstr
=HEAP_strdupA(GetProcessHeap(),0,"%s");
631 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
632 argliststart
=args
+insertnr
-1;
634 argliststart
=(*(DWORD
**)args
)+insertnr
-1;
636 if (fmtstr
[strlen(fmtstr
)-1]=='s')
637 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR
)argliststart
[0])+1);
639 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
641 /* CMF - This makes a BIG assumption about va_list */
642 wvsprintf32A(sprintfbuf
, fmtstr
, (va_list) argliststart
);
647 HeapFree(GetProcessHeap(),0,sprintfbuf
);
649 /* NULL args - copy formatstr
652 while ((lastf
<f
)&&(*lastf
)) {
656 HeapFree(GetProcessHeap(),0,fmtstr
);
659 /* FIXME: perhaps add \r too? */
667 default:ADD_TO_T(*f
++)
679 if(t
==target
|| t
[-1]!='\n')
680 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
682 talloced
= strlen(target
)+1;
683 if (nSize
&& talloced
<nSize
) {
684 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
686 TRACE(resource
,"-- %s\n",debugstr_a(target
));
687 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
688 /* nSize is the MINIMUM size */
689 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc32(GMEM_ZEROINIT
,talloced
);
690 memcpy(*(LPSTR
*)lpBuffer
,target
,talloced
);
692 strncpy(lpBuffer
,target
,nSize
);
693 HeapFree(GetProcessHeap(),0,target
);
694 if (from
) HeapFree(GetProcessHeap(),0,from
);
695 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
696 strlen(*(LPSTR
*)lpBuffer
):
702 /***********************************************************************
703 * FormatMessage32W (KERNEL32.138)
705 DWORD WINAPI
FormatMessage32W(
712 LPDWORD args
/* va_list *args */
717 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
718 DWORD nolinefeed
= 0;
720 TRACE(resource
, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
721 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
);
723 FIXME(resource
,"line wrapping not supported.\n");
725 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
726 from
= HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)lpSource
);
727 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
728 /* gather information from system message tables ... */
729 from
= HeapAlloc( GetProcessHeap(),0,200 );
730 sprintf(from
,"Systemmessage, messageid = 0x%08lx\n",dwMessageId
);
732 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
735 dwMessageId
&= 0xFFFF;
736 bufsize
=LoadMessage32A((HMODULE32
)lpSource
,dwMessageId
,dwLanguageId
,NULL
,100);
739 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
740 LoadMessage32A((HMODULE32
)lpSource
,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
743 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100 );
747 #define ADD_TO_T(c) \
749 if (t-target == talloced) {\
750 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
751 t = target+talloced;\
757 while (*f
&& !nolinefeed
) {
760 char *fmtstr
,*sprintfbuf
,*x
;
770 case '1':case '2':case '3':case '4':case '5':
771 case '6':case '7':case '8':case '9':
774 case '0':case '1':case '2':case '3':
775 case '4':case '5':case '6':case '7':
778 insertnr
=insertnr
*10+*f
-'0';
787 if (NULL
!=(x
=strchr(f
,'!')))
790 fmtstr
=HeapAlloc( GetProcessHeap(), 0, strlen(f
)+2);
791 sprintf(fmtstr
,"%%%s",f
);
794 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
));
795 sprintf(fmtstr
,"%%%s",f
);
796 f
+=strlen(f
); /*at \0*/
802 fmtstr
=HEAP_strdupA( GetProcessHeap(),0,"%s");
803 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
804 argliststart
=args
+insertnr
-1;
806 argliststart
=(*(DWORD
**)args
)+insertnr
-1;
808 if (fmtstr
[strlen(fmtstr
)-1]=='s') {
811 xarr
[0]=(DWORD
)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)(*(argliststart
+0)));
812 /* possible invalid pointers */
813 xarr
[1]=*(argliststart
+1);
814 xarr
[2]=*(argliststart
+2);
815 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR
)argliststart
[0])*2+1);
817 /* CMF - This makes a BIG assumption about va_list */
818 vsprintf(sprintfbuf
, fmtstr
, (va_list) xarr
);
820 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
822 /* CMF - This makes a BIG assumption about va_list */
823 wvsprintf32A(sprintfbuf
, fmtstr
, (va_list) argliststart
);
829 HeapFree(GetProcessHeap(),0,sprintfbuf
);
830 HeapFree(GetProcessHeap(),0,fmtstr
);
833 /* FIXME: perhaps add \r too? */
841 default:ADD_TO_T(*f
++)
853 if(t
==target
|| t
[-1]!='\n')
854 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
856 talloced
= strlen(target
)+1;
857 if (nSize
&& talloced
<nSize
)
858 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
859 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
860 /* nSize is the MINIMUM size */
861 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc32(GMEM_ZEROINIT
,talloced
*2+2);
862 lstrcpynAtoW(*(LPWSTR
*)lpBuffer
,target
,talloced
);
864 lstrcpynAtoW(lpBuffer
,target
,nSize
);
865 HeapFree(GetProcessHeap(),0,target
);
866 if (from
) HeapFree(GetProcessHeap(),0,from
);
867 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
868 lstrlen32W(*(LPWSTR
*)lpBuffer
):
869 lstrlen32W(lpBuffer
);