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__ */