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 */
549 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
550 DWORD nolinefeed
= 0;
552 TRACE(resource
, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
553 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
);
555 FIXME(resource
,"line wrapping not supported.\n");
557 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
558 from
= HEAP_strdupA( GetProcessHeap(), 0, (LPSTR
)lpSource
);
559 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
560 from
= HeapAlloc( GetProcessHeap(),0,200 );
561 sprintf(from
,"Systemmessage, messageid = 0x%08lx\n",dwMessageId
);
563 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
566 dwMessageId
&= 0xFFFF;
567 bufsize
=LoadMessage32A((HMODULE32
)lpSource
,dwMessageId
,dwLanguageId
,NULL
,100);
569 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
570 LoadMessage32A((HMODULE32
)lpSource
,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
573 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100);
577 #define ADD_TO_T(c) \
579 if (t-target == talloced) {\
580 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
581 t = target+talloced;\
587 while (*f
&& !nolinefeed
) {
590 char *fmtstr
,*sprintfbuf
,*x
,*lastf
;
601 case '1':case '2':case '3':case '4':case '5':
602 case '6':case '7':case '8':case '9':
605 case '0':case '1':case '2':case '3':
606 case '4':case '5':case '6':case '7':
609 insertnr
=insertnr
*10+*f
-'0';
618 if (NULL
!=(x
=strchr(f
,'!'))) {
620 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
)+2);
621 sprintf(fmtstr
,"%%%s",f
);
624 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
));
625 sprintf(fmtstr
,"%%%s",f
);
626 f
+=strlen(f
); /*at \0*/
632 fmtstr
=HEAP_strdupA(GetProcessHeap(),0,"%s");
634 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
635 argliststart
=args
+insertnr
-1;
637 argliststart
=(*(DWORD
**)args
)+insertnr
-1;
639 if (fmtstr
[strlen(fmtstr
)-1]=='s')
640 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR
)argliststart
[0])+1);
642 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
644 /* CMF - This makes a BIG assumption about va_list */
645 wvsprintf32A(sprintfbuf
, fmtstr
, (va_list) argliststart
);
650 HeapFree(GetProcessHeap(),0,sprintfbuf
);
652 /* NULL args - copy formatstr
655 while ((lastf
<f
)&&(*lastf
)) {
659 HeapFree(GetProcessHeap(),0,fmtstr
);
662 /* FIXME: perhaps add \r too? */
670 default:ADD_TO_T(*f
++)
682 if(t
==target
|| t
[-1]!='\n')
683 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
685 talloced
= strlen(target
)+1;
686 if (nSize
&& talloced
<nSize
) {
687 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
689 TRACE(resource
,"-- %s\n",debugstr_a(target
));
690 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
691 /* nSize is the MINIMUM size */
692 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc32(GMEM_ZEROINIT
,talloced
);
693 memcpy(*(LPSTR
*)lpBuffer
,target
,talloced
);
695 strncpy(lpBuffer
,target
,nSize
);
696 HeapFree(GetProcessHeap(),0,target
);
697 if (from
) HeapFree(GetProcessHeap(),0,from
);
698 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
699 strlen(*(LPSTR
*)lpBuffer
):
705 /***********************************************************************
706 * FormatMessage32W (KERNEL32.138)
708 DWORD WINAPI
FormatMessage32W(
715 LPDWORD args
/* va_list *args */
720 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
721 DWORD nolinefeed
= 0;
723 TRACE(resource
, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
724 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
);
726 FIXME(resource
,"line wrapping not supported.\n");
728 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
729 from
= HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)lpSource
);
730 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
731 /* gather information from system message tables ... */
732 from
= HeapAlloc( GetProcessHeap(),0,200 );
733 sprintf(from
,"Systemmessage, messageid = 0x%08lx\n",dwMessageId
);
735 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
738 dwMessageId
&= 0xFFFF;
739 bufsize
=LoadMessage32A((HMODULE32
)lpSource
,dwMessageId
,dwLanguageId
,NULL
,100);
742 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
743 LoadMessage32A((HMODULE32
)lpSource
,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
746 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100 );
750 #define ADD_TO_T(c) \
752 if (t-target == talloced) {\
753 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
754 t = target+talloced;\
760 while (*f
&& !nolinefeed
) {
763 char *fmtstr
,*sprintfbuf
,*x
;
773 case '1':case '2':case '3':case '4':case '5':
774 case '6':case '7':case '8':case '9':
777 case '0':case '1':case '2':case '3':
778 case '4':case '5':case '6':case '7':
781 insertnr
=insertnr
*10+*f
-'0';
790 if (NULL
!=(x
=strchr(f
,'!')))
793 fmtstr
=HeapAlloc( GetProcessHeap(), 0, strlen(f
)+2);
794 sprintf(fmtstr
,"%%%s",f
);
797 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
));
798 sprintf(fmtstr
,"%%%s",f
);
799 f
+=strlen(f
); /*at \0*/
805 fmtstr
=HEAP_strdupA( GetProcessHeap(),0,"%s");
806 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
807 argliststart
=args
+insertnr
-1;
809 argliststart
=(*(DWORD
**)args
)+insertnr
-1;
811 if (fmtstr
[strlen(fmtstr
)-1]=='s') {
814 xarr
[0]=(DWORD
)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)(*(argliststart
+0)));
815 /* possible invalid pointers */
816 xarr
[1]=*(argliststart
+1);
817 xarr
[2]=*(argliststart
+2);
818 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR
)argliststart
[0])*2+1);
820 /* CMF - This makes a BIG assumption about va_list */
821 vsprintf(sprintfbuf
, fmtstr
, (va_list) xarr
);
823 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
825 /* CMF - This makes a BIG assumption about va_list */
826 wvsprintf32A(sprintfbuf
, fmtstr
, (va_list) argliststart
);
832 HeapFree(GetProcessHeap(),0,sprintfbuf
);
833 HeapFree(GetProcessHeap(),0,fmtstr
);
836 /* FIXME: perhaps add \r too? */
844 default:ADD_TO_T(*f
++)
856 if(t
==target
|| t
[-1]!='\n')
857 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
859 talloced
= strlen(target
)+1;
860 if (nSize
&& talloced
<nSize
)
861 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
862 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
863 /* nSize is the MINIMUM size */
864 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc32(GMEM_ZEROINIT
,talloced
*2+2);
865 lstrcpynAtoW(*(LPWSTR
*)lpBuffer
,target
,talloced
);
867 lstrcpynAtoW(lpBuffer
,target
,nSize
);
868 HeapFree(GetProcessHeap(),0,target
);
869 if (from
) HeapFree(GetProcessHeap(),0,from
);
870 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
871 lstrlen32W(*(LPWSTR
*)lpBuffer
):
872 lstrlen32W(lpBuffer
);