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
);