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"
32 #include "stackframe.h"
36 DEFAULT_DEBUG_CHANNEL(resource
)
38 extern const WORD OLE2NLS_CT_CType3_LUT
[]; /* FIXME: does not belong here */
41 /* Funny to divide them between user and kernel. */
43 /* be careful: always use functions from wctype.h if character > 255 */
46 * Unicode case conversion routines ... these should be used where
47 * toupper/tolower are used for ASCII.
50 /* FIXME: should probably get rid of wctype.h altogether */
53 WCHAR
towupper(WCHAR code
)
55 const WCHAR
* ptr
= uprtable
[HIBYTE(code
)];
56 return ptr
? ptr
[LOBYTE(code
)] : code
;
59 WCHAR
towlower(WCHAR code
)
61 const WCHAR
* ptr
= lwrtable
[HIBYTE(code
)];
62 return ptr
? ptr
[LOBYTE(code
)] : code
;
64 #endif /* HAVE_WCTYPE_H */
66 /***********************************************************************
67 * IsCharAlpha (USER.433)
69 BOOL16 WINAPI
IsCharAlpha16(CHAR ch
)
71 return isalpha(ch
); /* This is probably not right for NLS */
74 /***********************************************************************
75 * IsCharAlphanumeric (USER.434)
77 BOOL16 WINAPI
IsCharAlphaNumeric16(CHAR ch
)
82 /***********************************************************************
83 * IsCharUpper (USER.435)
85 BOOL16 WINAPI
IsCharUpper16(CHAR ch
)
90 /***********************************************************************
91 * IsCharLower (USER.436)
93 BOOL16 WINAPI
IsCharLower16(CHAR ch
)
98 /***********************************************************************
99 * AnsiUpper16 (USER.431)
101 SEGPTR WINAPI
AnsiUpper16( SEGPTR strOrChar
)
103 /* I am not sure if the locale stuff works with toupper, but then again
104 I am not sure if the Linux libc locale stuffs works at all */
106 /* uppercase only one char if strOrChar < 0x10000 */
107 if (HIWORD(strOrChar
))
110 for (s
= PTR_SEG_TO_LIN(strOrChar
); *s
; s
++) *s
= toupper(*s
);
113 else return toupper((char)strOrChar
);
117 /***********************************************************************
118 * AnsiUpperBuff16 (USER.437)
120 UINT16 WINAPI
AnsiUpperBuff16( LPSTR str
, UINT16 len
)
122 UINT count
= len
? len
: 65536;
123 for (; count
; count
--, str
++) *str
= toupper(*str
);
127 /***********************************************************************
128 * AnsiLower16 (USER.432)
130 SEGPTR WINAPI
AnsiLower16( SEGPTR strOrChar
)
132 /* I am not sure if the locale stuff works with toupper, but then again
133 I am not sure if the Linux libc locale stuffs works at all */
135 /* lowercase only one char if strOrChar < 0x10000 */
136 if (HIWORD(strOrChar
))
139 for (s
= PTR_SEG_TO_LIN( strOrChar
); *s
; s
++) *s
= tolower( *s
);
142 else return tolower((char)strOrChar
);
146 /***********************************************************************
147 * AnsiLowerBuff16 (USER.438)
149 UINT16 WINAPI
AnsiLowerBuff16( LPSTR str
, UINT16 len
)
151 UINT count
= len
? len
: 65536;
152 for (; count
; count
--, str
++) *str
= tolower(*str
);
157 /***********************************************************************
158 * AnsiNext16 (USER.472)
160 SEGPTR WINAPI
AnsiNext16(SEGPTR current
)
162 return (*(char *)PTR_SEG_TO_LIN(current
)) ? current
+ 1 : current
;
166 /***********************************************************************
167 * AnsiPrev16 (USER.473)
169 SEGPTR WINAPI
AnsiPrev16( SEGPTR start
, SEGPTR current
)
171 return (current
== start
) ? start
: current
- 1;
175 /***********************************************************************
176 * OutputDebugString16 (KERNEL.115)
178 void WINAPI
OutputDebugString16( LPCSTR str
)
181 if (!GetModuleName16( GetCurrentTask(), module
, sizeof(module
) ))
182 strcpy( module
, "???" );
184 DUMP( "%s says %s\n", module
, debugstr_a(str
) );
188 /***********************************************************************
189 * OutputDebugString32A (KERNEL32
191 void WINAPI
OutputDebugStringA( LPCSTR str
)
193 OutputDebugString16( str
);
198 /***********************************************************************
199 * OutputDebugString32W (KERNEL32
201 void WINAPI
OutputDebugStringW( LPCWSTR str
)
203 LPSTR p
= HEAP_strdupWtoA( GetProcessHeap(), 0, str
);
204 OutputDebugStringA( p
);
205 HeapFree( GetProcessHeap(), 0, p
);
210 /***********************************************************************
211 * CharNext32A (USER32.29)
213 LPSTR WINAPI
CharNextA( LPCSTR ptr
)
215 if (!*ptr
) return (LPSTR
)ptr
;
216 if (IsDBCSLeadByte( *ptr
)) return (LPSTR
)(ptr
+ 2);
217 return (LPSTR
)(ptr
+ 1);
221 /***********************************************************************
222 * CharNextEx32A (USER32.30)
224 LPSTR WINAPI
CharNextExA( WORD codepage
, LPCSTR ptr
, DWORD flags
)
226 if (!*ptr
) return (LPSTR
)ptr
;
227 if (IsDBCSLeadByteEx( codepage
, *ptr
)) return (LPSTR
)(ptr
+ 2);
228 return (LPSTR
)(ptr
+ 1);
232 /***********************************************************************
233 * CharNextExW (USER32.31)
235 LPWSTR WINAPI
CharNextExW(WORD codepage
,LPCWSTR x
,DWORD flags
)
237 /* FIXME: add DBCS / codepage stuff */
238 if (*x
) return (LPWSTR
)(x
+1);
239 else return (LPWSTR
)x
;
242 /***********************************************************************
243 * CharNextW (USER32.32)
245 LPWSTR WINAPI
CharNextW(LPCWSTR x
)
247 if (*x
) return (LPWSTR
)(x
+1);
248 else return (LPWSTR
)x
;
251 /***********************************************************************
252 * CharPrev32A (USER32.33)
254 LPSTR WINAPI
CharPrevA( LPCSTR start
, LPCSTR ptr
)
256 while (*start
&& (start
< ptr
))
258 LPCSTR next
= CharNextA( start
);
259 if (next
>= ptr
) break;
266 /***********************************************************************
267 * CharPrevEx32A (USER32.34)
269 LPSTR WINAPI
CharPrevExA( WORD codepage
, LPCSTR start
, LPCSTR ptr
, DWORD flags
)
271 while (*start
&& (start
< ptr
))
273 LPCSTR next
= CharNextExA( codepage
, start
, flags
);
274 if (next
> ptr
) break;
281 /***********************************************************************
282 * CharPrevExW (USER32.35)
284 LPWSTR WINAPI
CharPrevExW(WORD codepage
,LPCWSTR start
,LPCWSTR x
,DWORD flags
)
286 /* FIXME: add DBCS / codepage stuff */
287 if (x
>start
) return (LPWSTR
)(x
-1);
288 else return (LPWSTR
)x
;
291 /***********************************************************************
292 * CharPrevW (USER32.36)
294 LPWSTR WINAPI
CharPrevW(LPCWSTR start
,LPCWSTR x
)
296 if (x
>start
) return (LPWSTR
)(x
-1);
297 else return (LPWSTR
)x
;
300 /***********************************************************************
301 * CharLowerA (USER32.25)
302 * FIXME: handle current locale
304 LPSTR WINAPI
CharLowerA(LPSTR x
)
318 else return (LPSTR
)tolower((char)(int)x
);
321 /***********************************************************************
322 * CharLowerBuffA (USER32.26)
323 * FIXME: handle current locale
325 DWORD WINAPI
CharLowerBuffA(LPSTR x
,DWORD buflen
)
329 if (!x
) return 0; /* YES */
330 while (*x
&& (buflen
--))
339 /***********************************************************************
340 * CharLowerBuffW (USER32.27)
341 * FIXME: handle current locale
343 DWORD WINAPI
CharLowerBuffW(LPWSTR x
,DWORD buflen
)
347 if (!x
) return 0; /* YES */
348 while (*x
&& (buflen
--))
357 /***********************************************************************
358 * CharLowerW (USER32.28)
359 * FIXME: handle current locale
361 LPWSTR WINAPI
CharLowerW(LPWSTR x
)
373 else return (LPWSTR
)((UINT
)towlower(LOWORD(x
)));
376 /***********************************************************************
377 * CharUpper32A (USER32.41)
378 * FIXME: handle current locale
380 LPSTR WINAPI
CharUpperA(LPSTR x
)
392 return (LPSTR
)toupper((char)(int)x
);
395 /***********************************************************************
396 * CharUpperBuffA (USER32.42)
397 * FIXME: handle current locale
399 DWORD WINAPI
CharUpperBuffA(LPSTR x
,DWORD buflen
)
403 if (!x
) return 0; /* YES */
404 while (*x
&& (buflen
--))
413 /***********************************************************************
414 * CharUpperBuffW (USER32.43)
415 * FIXME: handle current locale
417 DWORD WINAPI
CharUpperBuffW(LPWSTR x
,DWORD buflen
)
421 if (!x
) return 0; /* YES */
422 while (*x
&& (buflen
--))
431 /***********************************************************************
432 * CharUpperW (USER32.44)
433 * FIXME: handle current locale
435 LPWSTR WINAPI
CharUpperW(LPWSTR x
)
447 else return (LPWSTR
)((UINT
)towupper(LOWORD(x
)));
450 /***********************************************************************
451 * IsCharAlphaA (USER32.331)
452 * FIXME: handle current locale
454 BOOL WINAPI
IsCharAlphaA(CHAR x
)
456 return (OLE2NLS_CT_CType3_LUT
[(unsigned char)x
] & C3_ALPHA
);
459 /***********************************************************************
460 * IsCharAlphaNumericA (USER32.332)
461 * FIXME: handle current locale
463 BOOL WINAPI
IsCharAlphaNumericA(CHAR x
)
465 return IsCharAlphaA(x
) || isdigit(x
) ;
468 /***********************************************************************
469 * IsCharAlphaNumericW (USER32.333)
470 * FIXME: handle current locale
472 BOOL WINAPI
IsCharAlphaNumericW(WCHAR x
)
477 /***********************************************************************
478 * IsCharAlphaW (USER32.334)
479 * FIXME: handle current locale
481 BOOL WINAPI
IsCharAlphaW(WCHAR x
)
486 /***********************************************************************
487 * IsCharLower32A (USER32.335)
488 * FIXME: handle current locale
490 BOOL WINAPI
IsCharLowerA(CHAR x
)
495 /***********************************************************************
496 * IsCharLower32W (USER32.336)
497 * FIXME: handle current locale
499 BOOL WINAPI
IsCharLowerW(WCHAR x
)
504 /***********************************************************************
505 * IsCharUpper32A (USER32.337)
506 * FIXME: handle current locale
508 BOOL WINAPI
IsCharUpperA(CHAR x
)
513 /***********************************************************************
514 * IsCharUpper32W (USER32.338)
515 * FIXME: handle current locale
517 BOOL WINAPI
IsCharUpperW(WCHAR x
)
522 /***********************************************************************
523 * FormatMessage16 (USER.606)
525 DWORD WINAPI
FormatMessage16(
532 LPDWORD args
/* va_list *args */
534 return FormatMessageA(dwFlags
, lpSource
, (DWORD
)dwMessageId
, (DWORD
)dwLanguageId
, lpBuffer
, (DWORD
)nSize
, args
);
537 /***********************************************************************
538 * FormatMessage32A (KERNEL32.138)
539 * FIXME: missing wrap,FROM_SYSTEM message-loading,
541 DWORD WINAPI
FormatMessageA(
548 LPDWORD args
/* va_list *args */
551 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
555 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
556 DWORD nolinefeed
= 0;
558 TRACE(resource
, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
559 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
);
561 FIXME(resource
,"line wrapping not supported.\n");
563 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
564 from
= HEAP_strdupA( GetProcessHeap(), 0, (LPSTR
)lpSource
);
565 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
566 from
= HeapAlloc( GetProcessHeap(),0,200 );
567 sprintf(from
,"Systemmessage, messageid = 0x%08lx\n",dwMessageId
);
569 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
572 dwMessageId
&= 0xFFFF;
573 bufsize
=LoadMessageA((HMODULE
)lpSource
,dwMessageId
,dwLanguageId
,NULL
,100);
575 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
576 LoadMessageA((HMODULE
)lpSource
,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
579 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100);
583 #define ADD_TO_T(c) \
585 if (t-target == talloced) {\
586 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
587 t = target+talloced;\
593 while (*f
&& !nolinefeed
) {
596 char *fmtstr
,*sprintfbuf
,*x
,*lastf
;
607 case '1':case '2':case '3':case '4':case '5':
608 case '6':case '7':case '8':case '9':
611 case '0':case '1':case '2':case '3':
612 case '4':case '5':case '6':case '7':
615 insertnr
=insertnr
*10+*f
-'0';
624 if (NULL
!=(x
=strchr(f
,'!'))) {
626 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
)+2);
627 sprintf(fmtstr
,"%%%s",f
);
630 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
));
631 sprintf(fmtstr
,"%%%s",f
);
632 f
+=strlen(f
); /*at \0*/
638 fmtstr
=HEAP_strdupA(GetProcessHeap(),0,"%s");
640 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
641 argliststart
=args
+insertnr
-1;
643 argliststart
=(*(DWORD
**)args
)+insertnr
-1;
645 if (fmtstr
[strlen(fmtstr
)-1]=='s')
646 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR
)argliststart
[0])+1);
648 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
650 /* CMF - This makes a BIG assumption about va_list */
651 wvsprintfA(sprintfbuf
, fmtstr
, (va_list) argliststart
);
656 HeapFree(GetProcessHeap(),0,sprintfbuf
);
658 /* NULL args - copy formatstr
661 while ((lastf
<f
)&&(*lastf
)) {
665 HeapFree(GetProcessHeap(),0,fmtstr
);
668 /* FIXME: perhaps add \r too? */
676 default:ADD_TO_T(*f
++)
688 if(t
==target
|| t
[-1]!='\n')
689 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
691 talloced
= strlen(target
)+1;
692 if (nSize
&& talloced
<nSize
) {
693 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
695 TRACE(resource
,"-- %s\n",debugstr_a(target
));
696 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
697 /* nSize is the MINIMUM size */
698 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc(GMEM_ZEROINIT
,talloced
);
699 memcpy(*(LPSTR
*)lpBuffer
,target
,talloced
);
701 strncpy(lpBuffer
,target
,nSize
);
702 HeapFree(GetProcessHeap(),0,target
);
703 if (from
) HeapFree(GetProcessHeap(),0,from
);
704 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
705 strlen(*(LPSTR
*)lpBuffer
):
709 #endif /* __i386__ */
714 /***********************************************************************
715 * FormatMessage32W (KERNEL32.138)
717 DWORD WINAPI
FormatMessageW(
724 LPDWORD args
/* va_list *args */
727 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
731 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
732 DWORD nolinefeed
= 0;
734 TRACE(resource
, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
735 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
);
737 FIXME(resource
,"line wrapping not supported.\n");
739 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
740 from
= HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)lpSource
);
741 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
742 /* gather information from system message tables ... */
743 from
= HeapAlloc( GetProcessHeap(),0,200 );
744 sprintf(from
,"Systemmessage, messageid = 0x%08lx\n",dwMessageId
);
746 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
749 dwMessageId
&= 0xFFFF;
750 bufsize
=LoadMessageA((HMODULE
)lpSource
,dwMessageId
,dwLanguageId
,NULL
,100);
753 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
754 LoadMessageA((HMODULE
)lpSource
,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
757 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100 );
761 #define ADD_TO_T(c) \
763 if (t-target == talloced) {\
764 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
765 t = target+talloced;\
771 while (*f
&& !nolinefeed
) {
774 char *fmtstr
,*sprintfbuf
,*x
;
784 case '1':case '2':case '3':case '4':case '5':
785 case '6':case '7':case '8':case '9':
788 case '0':case '1':case '2':case '3':
789 case '4':case '5':case '6':case '7':
792 insertnr
=insertnr
*10+*f
-'0';
801 if (NULL
!=(x
=strchr(f
,'!')))
804 fmtstr
=HeapAlloc( GetProcessHeap(), 0, strlen(f
)+2);
805 sprintf(fmtstr
,"%%%s",f
);
808 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
));
809 sprintf(fmtstr
,"%%%s",f
);
810 f
+=strlen(f
); /*at \0*/
816 fmtstr
=HEAP_strdupA( GetProcessHeap(),0,"%s");
817 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
818 argliststart
=args
+insertnr
-1;
820 argliststart
=(*(DWORD
**)args
)+insertnr
-1;
822 if (fmtstr
[strlen(fmtstr
)-1]=='s') {
825 xarr
[0]=(DWORD
)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)(*(argliststart
+0)));
826 /* possible invalid pointers */
827 xarr
[1]=*(argliststart
+1);
828 xarr
[2]=*(argliststart
+2);
829 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,lstrlenW((LPWSTR
)argliststart
[0])*2+1);
831 /* CMF - This makes a BIG assumption about va_list */
832 vsprintf(sprintfbuf
, fmtstr
, (va_list) xarr
);
834 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
836 /* CMF - This makes a BIG assumption about va_list */
837 wvsprintfA(sprintfbuf
, fmtstr
, (va_list) argliststart
);
843 HeapFree(GetProcessHeap(),0,sprintfbuf
);
844 HeapFree(GetProcessHeap(),0,fmtstr
);
847 /* FIXME: perhaps add \r too? */
855 default:ADD_TO_T(*f
++)
867 if(t
==target
|| t
[-1]!='\n')
868 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
870 talloced
= strlen(target
)+1;
871 if (nSize
&& talloced
<nSize
)
872 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
873 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
874 /* nSize is the MINIMUM size */
875 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc(GMEM_ZEROINIT
,talloced
*2+2);
876 lstrcpynAtoW(*(LPWSTR
*)lpBuffer
,target
,talloced
);
878 lstrcpynAtoW(lpBuffer
,target
,nSize
);
879 HeapFree(GetProcessHeap(),0,target
);
880 if (from
) HeapFree(GetProcessHeap(),0,from
);
881 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
882 lstrlenW(*(LPWSTR
*)lpBuffer
):
886 #endif /* __i386__ */