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 */
27 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
33 #include "stackframe.h"
37 extern const WORD OLE2NLS_CT_CType3_LUT
[]; /* FIXME: does not belong here */
40 /* Funny to divide them between user and kernel. */
42 /* be careful: always use functions from wctype.h if character > 255 */
45 * Unicode case conversion routines ... these should be used where
46 * toupper/tolower are used for ASCII.
49 /* FIXME: should probably get rid of wctype.h altogether */
52 WCHAR
towupper(WCHAR code
)
54 const WCHAR
* ptr
= uprtable
[HIBYTE(code
)];
55 return ptr
? ptr
[LOBYTE(code
)] : code
;
58 WCHAR
towlower(WCHAR code
)
60 const WCHAR
* ptr
= lwrtable
[HIBYTE(code
)];
61 return ptr
? ptr
[LOBYTE(code
)] : code
;
63 #endif /* HAVE_WCTYPE_H */
65 /***********************************************************************
66 * IsCharAlpha (USER.433)
68 BOOL16 WINAPI
IsCharAlpha16(CHAR ch
)
70 return isalpha(ch
); /* This is probably not right for NLS */
73 /***********************************************************************
74 * IsCharAlphanumeric (USER.434)
76 BOOL16 WINAPI
IsCharAlphaNumeric16(CHAR ch
)
81 /***********************************************************************
82 * IsCharUpper (USER.435)
84 BOOL16 WINAPI
IsCharUpper16(CHAR ch
)
89 /***********************************************************************
90 * IsCharLower (USER.436)
92 BOOL16 WINAPI
IsCharLower16(CHAR ch
)
97 /***********************************************************************
98 * AnsiUpper16 (USER.431)
100 SEGPTR WINAPI
AnsiUpper16( SEGPTR strOrChar
)
102 /* I am not sure if the locale stuff works with toupper, but then again
103 I am not sure if the Linux libc locale stuffs works at all */
105 /* uppercase only one char if strOrChar < 0x10000 */
106 if (HIWORD(strOrChar
))
109 for (s
= PTR_SEG_TO_LIN(strOrChar
); *s
; s
++) *s
= toupper(*s
);
112 else return toupper((char)strOrChar
);
116 /***********************************************************************
117 * AnsiUpperBuff16 (USER.437)
119 UINT16 WINAPI
AnsiUpperBuff16( LPSTR str
, UINT16 len
)
121 UINT count
= len
? len
: 65536;
122 for (; count
; count
--, str
++) *str
= toupper(*str
);
126 /***********************************************************************
127 * AnsiLower16 (USER.432)
129 SEGPTR WINAPI
AnsiLower16( SEGPTR strOrChar
)
131 /* I am not sure if the locale stuff works with toupper, but then again
132 I am not sure if the Linux libc locale stuffs works at all */
134 /* lowercase only one char if strOrChar < 0x10000 */
135 if (HIWORD(strOrChar
))
138 for (s
= PTR_SEG_TO_LIN( strOrChar
); *s
; s
++) *s
= tolower( *s
);
141 else return tolower((char)strOrChar
);
145 /***********************************************************************
146 * AnsiLowerBuff16 (USER.438)
148 UINT16 WINAPI
AnsiLowerBuff16( LPSTR str
, UINT16 len
)
150 UINT count
= len
? len
: 65536;
151 for (; count
; count
--, str
++) *str
= tolower(*str
);
156 /***********************************************************************
157 * AnsiNext16 (USER.472)
159 SEGPTR WINAPI
AnsiNext16(SEGPTR current
)
161 return (*(char *)PTR_SEG_TO_LIN(current
)) ? current
+ 1 : current
;
165 /***********************************************************************
166 * AnsiPrev16 (USER.473)
168 SEGPTR WINAPI
AnsiPrev16( SEGPTR start
, SEGPTR current
)
170 return (current
== start
) ? start
: current
- 1;
174 /***********************************************************************
175 * OutputDebugString16 (KERNEL.115)
177 void WINAPI
OutputDebugString16( LPCSTR str
)
180 if (!GetModuleName16( GetCurrentTask(), module
, sizeof(module
) ))
181 strcpy( module
, "???" );
183 DUMP( "%s says %s\n", module
, debugstr_a(str
) );
187 /***********************************************************************
188 * OutputDebugString32A (KERNEL32
190 void WINAPI
OutputDebugStringA( LPCSTR str
)
192 OutputDebugString16( str
);
197 /***********************************************************************
198 * OutputDebugString32W (KERNEL32
200 void WINAPI
OutputDebugStringW( LPCWSTR str
)
202 LPSTR p
= HEAP_strdupWtoA( GetProcessHeap(), 0, str
);
203 OutputDebugStringA( p
);
204 HeapFree( GetProcessHeap(), 0, p
);
209 /***********************************************************************
210 * CharNext32A (USER32.29)
212 LPSTR WINAPI
CharNextA( LPCSTR ptr
)
214 if (!*ptr
) return (LPSTR
)ptr
;
215 if (IsDBCSLeadByte( *ptr
)) return (LPSTR
)(ptr
+ 2);
216 return (LPSTR
)(ptr
+ 1);
220 /***********************************************************************
221 * CharNextEx32A (USER32.30)
223 LPSTR WINAPI
CharNextExA( WORD codepage
, LPCSTR ptr
, DWORD flags
)
225 if (!*ptr
) return (LPSTR
)ptr
;
226 if (IsDBCSLeadByteEx( codepage
, *ptr
)) return (LPSTR
)(ptr
+ 2);
227 return (LPSTR
)(ptr
+ 1);
231 /***********************************************************************
232 * CharNextExW (USER32.31)
234 LPWSTR WINAPI
CharNextExW(WORD codepage
,LPCWSTR x
,DWORD flags
)
236 /* FIXME: add DBCS / codepage stuff */
237 if (*x
) return (LPWSTR
)(x
+1);
238 else return (LPWSTR
)x
;
241 /***********************************************************************
242 * CharNextW (USER32.32)
244 LPWSTR WINAPI
CharNextW(LPCWSTR x
)
246 if (*x
) return (LPWSTR
)(x
+1);
247 else return (LPWSTR
)x
;
250 /***********************************************************************
251 * CharPrev32A (USER32.33)
253 LPSTR WINAPI
CharPrevA( LPCSTR start
, LPCSTR ptr
)
255 while (*start
&& (start
< ptr
))
257 LPCSTR next
= CharNextA( start
);
258 if (next
>= ptr
) break;
265 /***********************************************************************
266 * CharPrevEx32A (USER32.34)
268 LPSTR WINAPI
CharPrevExA( WORD codepage
, LPCSTR start
, LPCSTR ptr
, DWORD flags
)
270 while (*start
&& (start
< ptr
))
272 LPCSTR next
= CharNextExA( codepage
, start
, flags
);
273 if (next
> ptr
) break;
280 /***********************************************************************
281 * CharPrevExW (USER32.35)
283 LPWSTR WINAPI
CharPrevExW(WORD codepage
,LPCWSTR start
,LPCWSTR x
,DWORD flags
)
285 /* FIXME: add DBCS / codepage stuff */
286 if (x
>start
) return (LPWSTR
)(x
-1);
287 else return (LPWSTR
)x
;
290 /***********************************************************************
291 * CharPrevW (USER32.36)
293 LPWSTR WINAPI
CharPrevW(LPCWSTR start
,LPCWSTR x
)
295 if (x
>start
) return (LPWSTR
)(x
-1);
296 else return (LPWSTR
)x
;
299 /***********************************************************************
300 * CharLowerA (USER32.25)
301 * FIXME: handle current locale
303 LPSTR WINAPI
CharLowerA(LPSTR x
)
317 else return (LPSTR
)tolower((char)(int)x
);
320 /***********************************************************************
321 * CharLowerBuffA (USER32.26)
322 * FIXME: handle current locale
324 DWORD WINAPI
CharLowerBuffA(LPSTR x
,DWORD buflen
)
328 if (!x
) return 0; /* YES */
329 while (*x
&& (buflen
--))
338 /***********************************************************************
339 * CharLowerBuffW (USER32.27)
340 * FIXME: handle current locale
342 DWORD WINAPI
CharLowerBuffW(LPWSTR x
,DWORD buflen
)
346 if (!x
) return 0; /* YES */
347 while (*x
&& (buflen
--))
356 /***********************************************************************
357 * CharLowerW (USER32.28)
358 * FIXME: handle current locale
360 LPWSTR WINAPI
CharLowerW(LPWSTR x
)
372 else return (LPWSTR
)((UINT
)towlower(LOWORD(x
)));
375 /***********************************************************************
376 * CharUpper32A (USER32.41)
377 * FIXME: handle current locale
379 LPSTR WINAPI
CharUpperA(LPSTR x
)
391 return (LPSTR
)toupper((char)(int)x
);
394 /***********************************************************************
395 * CharUpperBuffA (USER32.42)
396 * FIXME: handle current locale
398 DWORD WINAPI
CharUpperBuffA(LPSTR x
,DWORD buflen
)
402 if (!x
) return 0; /* YES */
403 while (*x
&& (buflen
--))
412 /***********************************************************************
413 * CharUpperBuffW (USER32.43)
414 * FIXME: handle current locale
416 DWORD WINAPI
CharUpperBuffW(LPWSTR x
,DWORD buflen
)
420 if (!x
) return 0; /* YES */
421 while (*x
&& (buflen
--))
430 /***********************************************************************
431 * CharUpperW (USER32.44)
432 * FIXME: handle current locale
434 LPWSTR WINAPI
CharUpperW(LPWSTR x
)
446 else return (LPWSTR
)((UINT
)towupper(LOWORD(x
)));
449 /***********************************************************************
450 * IsCharAlphaA (USER32.331)
451 * FIXME: handle current locale
453 BOOL WINAPI
IsCharAlphaA(CHAR x
)
455 return (OLE2NLS_CT_CType3_LUT
[(unsigned char)x
] & C3_ALPHA
);
458 /***********************************************************************
459 * IsCharAlphaNumericA (USER32.332)
460 * FIXME: handle current locale
462 BOOL WINAPI
IsCharAlphaNumericA(CHAR x
)
464 return IsCharAlphaA(x
) || isdigit(x
) ;
467 /***********************************************************************
468 * IsCharAlphaNumericW (USER32.333)
469 * FIXME: handle current locale
471 BOOL WINAPI
IsCharAlphaNumericW(WCHAR x
)
476 /***********************************************************************
477 * IsCharAlphaW (USER32.334)
478 * FIXME: handle current locale
480 BOOL WINAPI
IsCharAlphaW(WCHAR x
)
485 /***********************************************************************
486 * IsCharLower32A (USER32.335)
487 * FIXME: handle current locale
489 BOOL WINAPI
IsCharLowerA(CHAR x
)
494 /***********************************************************************
495 * IsCharLower32W (USER32.336)
496 * FIXME: handle current locale
498 BOOL WINAPI
IsCharLowerW(WCHAR x
)
503 /***********************************************************************
504 * IsCharUpper32A (USER32.337)
505 * FIXME: handle current locale
507 BOOL WINAPI
IsCharUpperA(CHAR x
)
512 /***********************************************************************
513 * IsCharUpper32W (USER32.338)
514 * FIXME: handle current locale
516 BOOL WINAPI
IsCharUpperW(WCHAR x
)
521 /***********************************************************************
522 * FormatMessage16 (USER.606)
524 DWORD WINAPI
FormatMessage16(
531 LPDWORD args
/* va_list *args */
533 return FormatMessageA(dwFlags
, lpSource
, (DWORD
)dwMessageId
, (DWORD
)dwLanguageId
, lpBuffer
, (DWORD
)nSize
, args
);
536 /***********************************************************************
537 * FormatMessage32A (KERNEL32.138)
538 * FIXME: missing wrap,FROM_SYSTEM message-loading,
540 DWORD WINAPI
FormatMessageA(
547 LPDWORD args
/* va_list *args */
550 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
554 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
555 DWORD nolinefeed
= 0;
557 TRACE(resource
, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
558 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
);
560 FIXME(resource
,"line wrapping not supported.\n");
562 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
563 from
= HEAP_strdupA( GetProcessHeap(), 0, (LPSTR
)lpSource
);
564 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
565 from
= HeapAlloc( GetProcessHeap(),0,200 );
566 sprintf(from
,"Systemmessage, messageid = 0x%08lx\n",dwMessageId
);
568 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
571 dwMessageId
&= 0xFFFF;
572 bufsize
=LoadMessageA((HMODULE
)lpSource
,dwMessageId
,dwLanguageId
,NULL
,100);
574 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
575 LoadMessageA((HMODULE
)lpSource
,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
578 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100);
582 #define ADD_TO_T(c) \
584 if (t-target == talloced) {\
585 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
586 t = target+talloced;\
592 while (*f
&& !nolinefeed
) {
595 char *fmtstr
,*sprintfbuf
,*x
,*lastf
;
606 case '1':case '2':case '3':case '4':case '5':
607 case '6':case '7':case '8':case '9':
610 case '0':case '1':case '2':case '3':
611 case '4':case '5':case '6':case '7':
614 insertnr
=insertnr
*10+*f
-'0';
623 if (NULL
!=(x
=strchr(f
,'!'))) {
625 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
)+2);
626 sprintf(fmtstr
,"%%%s",f
);
629 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
));
630 sprintf(fmtstr
,"%%%s",f
);
631 f
+=strlen(f
); /*at \0*/
637 fmtstr
=HEAP_strdupA(GetProcessHeap(),0,"%s");
639 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
640 argliststart
=args
+insertnr
-1;
642 argliststart
=(*(DWORD
**)args
)+insertnr
-1;
644 if (fmtstr
[strlen(fmtstr
)-1]=='s')
645 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR
)argliststart
[0])+1);
647 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
649 /* CMF - This makes a BIG assumption about va_list */
650 wvsprintfA(sprintfbuf
, fmtstr
, (va_list) argliststart
);
655 HeapFree(GetProcessHeap(),0,sprintfbuf
);
657 /* NULL args - copy formatstr
660 while ((lastf
<f
)&&(*lastf
)) {
664 HeapFree(GetProcessHeap(),0,fmtstr
);
667 /* FIXME: perhaps add \r too? */
675 default:ADD_TO_T(*f
++)
687 if(t
==target
|| t
[-1]!='\n')
688 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
690 talloced
= strlen(target
)+1;
691 if (nSize
&& talloced
<nSize
) {
692 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
694 TRACE(resource
,"-- %s\n",debugstr_a(target
));
695 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
696 /* nSize is the MINIMUM size */
697 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc(GMEM_ZEROINIT
,talloced
);
698 memcpy(*(LPSTR
*)lpBuffer
,target
,talloced
);
700 strncpy(lpBuffer
,target
,nSize
);
701 HeapFree(GetProcessHeap(),0,target
);
702 if (from
) HeapFree(GetProcessHeap(),0,from
);
703 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
704 strlen(*(LPSTR
*)lpBuffer
):
708 #endif /* __i386__ */
713 /***********************************************************************
714 * FormatMessage32W (KERNEL32.138)
716 DWORD WINAPI
FormatMessageW(
723 LPDWORD args
/* va_list *args */
726 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
730 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
731 DWORD nolinefeed
= 0;
733 TRACE(resource
, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
734 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
);
736 FIXME(resource
,"line wrapping not supported.\n");
738 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
739 from
= HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)lpSource
);
740 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
741 /* gather information from system message tables ... */
742 from
= HeapAlloc( GetProcessHeap(),0,200 );
743 sprintf(from
,"Systemmessage, messageid = 0x%08lx\n",dwMessageId
);
745 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
748 dwMessageId
&= 0xFFFF;
749 bufsize
=LoadMessageA((HMODULE
)lpSource
,dwMessageId
,dwLanguageId
,NULL
,100);
752 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
753 LoadMessageA((HMODULE
)lpSource
,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
756 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100 );
760 #define ADD_TO_T(c) \
762 if (t-target == talloced) {\
763 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
764 t = target+talloced;\
770 while (*f
&& !nolinefeed
) {
773 char *fmtstr
,*sprintfbuf
,*x
;
783 case '1':case '2':case '3':case '4':case '5':
784 case '6':case '7':case '8':case '9':
787 case '0':case '1':case '2':case '3':
788 case '4':case '5':case '6':case '7':
791 insertnr
=insertnr
*10+*f
-'0';
800 if (NULL
!=(x
=strchr(f
,'!')))
803 fmtstr
=HeapAlloc( GetProcessHeap(), 0, strlen(f
)+2);
804 sprintf(fmtstr
,"%%%s",f
);
807 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
));
808 sprintf(fmtstr
,"%%%s",f
);
809 f
+=strlen(f
); /*at \0*/
815 fmtstr
=HEAP_strdupA( GetProcessHeap(),0,"%s");
816 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
817 argliststart
=args
+insertnr
-1;
819 argliststart
=(*(DWORD
**)args
)+insertnr
-1;
821 if (fmtstr
[strlen(fmtstr
)-1]=='s') {
824 xarr
[0]=(DWORD
)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)(*(argliststart
+0)));
825 /* possible invalid pointers */
826 xarr
[1]=*(argliststart
+1);
827 xarr
[2]=*(argliststart
+2);
828 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,lstrlenW((LPWSTR
)argliststart
[0])*2+1);
830 /* CMF - This makes a BIG assumption about va_list */
831 vsprintf(sprintfbuf
, fmtstr
, (va_list) xarr
);
833 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
835 /* CMF - This makes a BIG assumption about va_list */
836 wvsprintfA(sprintfbuf
, fmtstr
, (va_list) argliststart
);
842 HeapFree(GetProcessHeap(),0,sprintfbuf
);
843 HeapFree(GetProcessHeap(),0,fmtstr
);
846 /* FIXME: perhaps add \r too? */
854 default:ADD_TO_T(*f
++)
866 if(t
==target
|| t
[-1]!='\n')
867 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
869 talloced
= strlen(target
)+1;
870 if (nSize
&& talloced
<nSize
)
871 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
872 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
873 /* nSize is the MINIMUM size */
874 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc(GMEM_ZEROINIT
,talloced
*2+2);
875 lstrcpynAtoW(*(LPWSTR
*)lpBuffer
,target
,talloced
);
877 lstrcpynAtoW(lpBuffer
,target
,nSize
);
878 HeapFree(GetProcessHeap(),0,target
);
879 if (from
) HeapFree(GetProcessHeap(),0,from
);
880 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
881 lstrlenW(*(LPWSTR
*)lpBuffer
):
885 #endif /* __i386__ */