Moved a bunch of functions out of libwine/kernel/gdi into USER.
[wine/gsoc_dplay.git] / dlls / user / lstr.c
blob347b3e23828b239841cc7a727b4f9bcb280433c8
1 /*
2 * String functions
4 * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5 * Copyright 1996 Marcus Meissner
6 */
8 #include <stdarg.h>
9 #include <stdlib.h>
10 #include <stdio.h>
12 #include "windef.h"
13 #include "winbase.h"
14 #include "wine/winbase16.h"
15 #include "wine/winuser16.h"
17 #include "heap.h"
18 #include "ldt.h"
19 #include "debugtools.h"
21 DEFAULT_DEBUG_CHANNEL(resource);
23 /***********************************************************************
24 * FormatMessage16 (USER.606)
26 DWORD WINAPI FormatMessage16(
27 DWORD dwFlags,
28 SEGPTR lpSource, /*not always a valid pointer*/
29 WORD dwMessageId,
30 WORD dwLanguageId,
31 LPSTR lpBuffer, /* *((HLOCAL16*)) for FORMAT_MESSAGE_ALLOCATE_BUFFER*/
32 WORD nSize,
33 LPDWORD args /* va_list *args */
34 ) {
35 #ifdef __i386__
36 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
37 LPSTR target,t;
38 DWORD talloced;
39 LPSTR from,f;
40 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
41 BOOL eos = FALSE;
42 LPSTR allocstring = NULL;
44 TRACE("(0x%lx,%lx,%d,0x%x,%p,%d,%p)\n",
45 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
46 if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
47 && (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)) return 0;
48 if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
49 &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
50 || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
52 if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK)
53 FIXME("line wrapping (%lu) not supported.\n", width);
54 from = NULL;
55 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
56 from = HEAP_strdupA( GetProcessHeap(), 0, PTR_SEG_TO_LIN(lpSource));
57 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
58 from = HeapAlloc( GetProcessHeap(),0,200 );
59 sprintf(from,"Systemmessage, messageid = 0x%08x\n",dwMessageId);
61 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
62 INT16 bufsize;
63 HINSTANCE16 hinst16 = ((HMODULE)lpSource & 0xffff);
65 dwMessageId &= 0xFFFF;
66 bufsize=LoadString16(hinst16,dwMessageId,NULL,0);
67 if (bufsize) {
68 from = HeapAlloc( GetProcessHeap(), 0, bufsize +1);
69 LoadString16(hinst16,dwMessageId,from,bufsize+1);
72 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
73 t = target;
74 talloced= 100;
76 #define ADD_TO_T(c) \
77 *t++=c;\
78 if (t-target == talloced) {\
79 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
80 t = target+talloced;\
81 talloced*=2;\
84 if (from) {
85 f=from;
86 while (*f && !eos) {
87 if (*f=='%') {
88 int insertnr;
89 char *fmtstr,*x,*lastf;
90 DWORD *argliststart;
92 fmtstr = NULL;
93 lastf = f;
94 f++;
95 if (!*f) {
96 ADD_TO_T('%');
97 continue;
99 switch (*f) {
100 case '1':case '2':case '3':case '4':case '5':
101 case '6':case '7':case '8':case '9':
102 insertnr=*f-'0';
103 switch (f[1]) {
104 case '0':case '1':case '2':case '3':
105 case '4':case '5':case '6':case '7':
106 case '8':case '9':
107 f++;
108 insertnr=insertnr*10+*f-'0';
109 f++;
110 break;
111 default:
112 f++;
113 break;
115 if (*f=='!') {
116 f++;
117 if (NULL!=(x=strchr(f,'!'))) {
118 *x='\0';
119 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
120 sprintf(fmtstr,"%%%s",f);
121 f=x+1;
122 } else {
123 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
124 sprintf(fmtstr,"%%%s",f);
125 f+=strlen(f); /*at \0*/
127 } else
128 if(!args)
129 break;
130 else
131 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
132 if (args) {
133 int sz;
134 LPSTR b = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz = 100);
136 argliststart=args+insertnr-1;
138 /* CMF - This makes a BIG assumption about va_list */
139 while (vsnprintf(b, sz, fmtstr, (va_list) argliststart) < 0) {
140 b = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, b, sz += 100);
142 for (x=b; *x; x++) ADD_TO_T(*x);
143 } else {
144 /* NULL args - copy formatstr
145 * (probably wrong)
147 while ((lastf<f)&&(*lastf)) {
148 ADD_TO_T(*lastf++);
151 HeapFree(GetProcessHeap(),0,fmtstr);
152 break;
153 case '0': /* Just stop processing format string */
154 eos = TRUE;
155 f++;
156 break;
157 case 'n': /* 16 bit version just outputs 'n' */
158 default:
159 ADD_TO_T(*f++);
160 break;
162 } else { /* '\n' or '\r' gets mapped to "\r\n" */
163 if(*f == '\n' || *f == '\r') {
164 if (width == 0) {
165 ADD_TO_T('\r');
166 ADD_TO_T('\n');
167 if(*f++ == '\r' && *f == '\n')
168 f++;
170 } else {
171 ADD_TO_T(*f++);
175 *t='\0';
177 talloced = strlen(target)+1;
178 if (nSize && talloced<nSize) {
179 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
181 TRACE("-- %s\n",debugstr_a(target));
182 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
183 /* nSize is the MINIMUM size */
184 HLOCAL16 h = LocalAlloc16(LPTR,talloced);
185 SEGPTR ptr = LocalLock16(h);
186 allocstring = PTR_SEG_TO_LIN( ptr );
187 memcpy( allocstring,target,talloced);
188 LocalUnlock16( h );
189 *((HLOCAL16*)lpBuffer) = h;
190 } else
191 lstrcpynA(lpBuffer,target,nSize);
192 HeapFree(GetProcessHeap(),0,target);
193 if (from) HeapFree(GetProcessHeap(),0,from);
194 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
195 strlen(allocstring):
196 strlen(lpBuffer);
197 #else
198 return 0;
199 #endif /* __i386__ */
201 #undef ADD_TO_T