Lay down the infrastructure for gdi font rendering.
[wine] / memory / string.c
1 /*
2  * String functions
3  *
4  * Copyright 1993 Yngvi Sigurjonsson
5  * Copyright 1996 Alexandre Julliard
6  */
7
8 #include <ctype.h>
9 #include <string.h>
10
11 #include "windef.h"
12 #include "winbase.h"
13 #include "wine/winbase16.h"
14 #include "wine/exception.h"
15 #include "wine/unicode.h"
16 #include "winerror.h"
17 #include "winnls.h"
18 #include "debugtools.h"
19
20 DEFAULT_DEBUG_CHANNEL(string);
21
22 /* filter for page-fault exceptions */
23 static WINE_EXCEPTION_FILTER(page_fault)
24 {
25     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
26         return EXCEPTION_EXECUTE_HANDLER;
27     return EXCEPTION_CONTINUE_SEARCH;
28 }
29
30
31 /***********************************************************************
32  *           hmemcpy   (KERNEL.348)
33  */
34 void WINAPI hmemcpy16( LPVOID dst, LPCVOID src, LONG count )
35 {
36     memcpy( dst, src, count );
37 }
38
39
40 /***********************************************************************
41  *           lstrcat   (KERNEL.89)
42  */
43 SEGPTR WINAPI lstrcat16( SEGPTR dst, LPCSTR src )
44 {
45     /* Windows does not check for NULL pointers here, so we don't either */
46     strcat( MapSL(dst), src );
47     return dst;
48 }
49
50
51 /***********************************************************************
52  *           lstrcat    (KERNEL32.@)
53  *           lstrcatA   (KERNEL32.@)
54  */
55 LPSTR WINAPI lstrcatA( LPSTR dst, LPCSTR src )
56 {
57     __TRY
58     {
59         strcat( dst, src );
60     }
61     __EXCEPT(page_fault)
62     {
63         SetLastError( ERROR_INVALID_PARAMETER );
64         return NULL;
65     }
66     __ENDTRY
67     return dst;
68 }
69
70
71 /***********************************************************************
72  *           lstrcatW   (KERNEL32.@)
73  */
74 LPWSTR WINAPI lstrcatW( LPWSTR dst, LPCWSTR src )
75 {
76     __TRY
77     {
78         strcatW( dst, src );
79     }
80     __EXCEPT(page_fault)
81     {
82         SetLastError( ERROR_INVALID_PARAMETER );
83         return NULL;
84     }
85     __ENDTRY
86     return dst;
87 }
88
89
90 /***********************************************************************
91  *           lstrcatn   (KERNEL.352)
92  */
93 SEGPTR WINAPI lstrcatn16( SEGPTR dst, LPCSTR src, INT16 n )
94 {
95     LPSTR p = MapSL(dst);
96     LPSTR start = p;
97
98     while (*p) p++;
99     if ((n -= (p - start)) <= 0) return dst;
100     lstrcpynA( p, src, n );
101     return dst;
102 }
103
104
105 /***********************************************************************
106  *           lstrcmp    (KERNEL32.@)
107  *           lstrcmpA   (KERNEL32.@)
108  */
109 INT WINAPI lstrcmpA( LPCSTR str1, LPCSTR str2 )
110 {
111     return CompareStringA(LOCALE_SYSTEM_DEFAULT,0,str1,-1,str2,-1) - 2 ;
112 }
113
114
115 /***********************************************************************
116  *           lstrcmpW   (KERNEL32.@)
117  * FIXME : should call CompareStringW, when it is implemented.
118  *    This implementation is not "word sort", as it should.
119  */
120 INT WINAPI lstrcmpW( LPCWSTR str1, LPCWSTR str2 )
121 {
122     TRACE("%s and %s\n",
123                    debugstr_w (str1), debugstr_w (str2));
124     if (!str1 || !str2) {
125         SetLastError(ERROR_INVALID_PARAMETER);
126         return 0;
127     }
128     while (*str1 && (*str1 == *str2)) { str1++; str2++; }
129     return (INT)(*str1 - *str2);
130 }
131
132
133 /***********************************************************************
134  *           lstrcmpi    (KERNEL32.@)
135  *           lstrcmpiA   (KERNEL32.@)
136  */
137 INT WINAPI lstrcmpiA( LPCSTR str1, LPCSTR str2 )
138 {    TRACE("strcmpi %s and %s\n",
139                    debugstr_a (str1), debugstr_a (str2));
140     return CompareStringA(LOCALE_SYSTEM_DEFAULT,NORM_IGNORECASE,str1,-1,str2,-1)-2;
141 }
142
143
144 /***********************************************************************
145  *           lstrcmpiW   (KERNEL32.@)
146  */
147 INT WINAPI lstrcmpiW( LPCWSTR str1, LPCWSTR str2 )
148 {
149     if (!str1 || !str2) {
150         SetLastError(ERROR_INVALID_PARAMETER);
151         return 0;
152     }
153     return strcmpiW( str1, str2 );
154 }
155
156
157 /***********************************************************************
158  *           lstrcpy   (KERNEL.88)
159  */
160 SEGPTR WINAPI lstrcpy16( SEGPTR dst, LPCSTR src )
161 {
162     if (!lstrcpyA( MapSL(dst), src )) dst = 0;
163     return dst;
164 }
165
166
167 /***********************************************************************
168  *           lstrcpy    (KERNEL32.@)
169  *           lstrcpyA   (KERNEL32.@)
170  */
171 LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src )
172 {
173     __TRY
174     {
175         /* this is how Windows does it */
176         memmove( dst, src, strlen(src)+1 );
177     }
178     __EXCEPT(page_fault)
179     {
180         ERR("(%p, %p): page fault occurred ! Caused by bug ?\n", dst, src);
181         SetLastError( ERROR_INVALID_PARAMETER );
182         return NULL;
183     }
184     __ENDTRY
185     return dst;
186 }
187
188
189 /***********************************************************************
190  *           lstrcpyW   (KERNEL32.@)
191  */
192 LPWSTR WINAPI lstrcpyW( LPWSTR dst, LPCWSTR src )
193 {
194     __TRY
195     {
196         strcpyW( dst, src );
197     }
198     __EXCEPT(page_fault)
199     {
200         SetLastError( ERROR_INVALID_PARAMETER );
201         return NULL;
202     }
203     __ENDTRY
204     return dst;
205 }
206
207
208 /***********************************************************************
209  *           lstrcpyn   (KERNEL.353)
210  */
211 SEGPTR WINAPI lstrcpyn16( SEGPTR dst, LPCSTR src, INT16 n )
212 {
213     lstrcpynA( MapSL(dst), src, n );
214     return dst;
215 }
216
217
218 /***********************************************************************
219  *           lstrcpyn    (KERNEL32.@)
220  *           lstrcpynA   (KERNEL32.@)
221  *
222  * Note: this function differs from the UNIX strncpy, it _always_ writes
223  * a terminating \0
224  */
225 LPSTR WINAPI lstrcpynA( LPSTR dst, LPCSTR src, INT n )
226 {
227     LPSTR p = dst;
228     TRACE("(%p, %s, %i)\n", dst, debugstr_an(src,n), n);
229     /* In real windows the whole function is protected by an exception handler
230      * that returns ERROR_INVALID_PARAMETER on faulty parameters
231      * We currently just check for NULL.
232      */
233     if (!dst || !src) {
234         SetLastError(ERROR_INVALID_PARAMETER);
235         return 0;
236     }
237     while ((n-- > 1) && *src) *p++ = *src++;
238     if (n >= 0) *p = 0;
239     return dst;
240 }
241
242
243 /***********************************************************************
244  *           lstrcpynW   (KERNEL32.@)
245  * Note: this function differs from the UNIX strncpy, it _always_ writes
246  * a terminating \0
247  */
248 LPWSTR WINAPI lstrcpynW( LPWSTR dst, LPCWSTR src, INT n )
249 {
250     LPWSTR p = dst;
251     TRACE("(%p, %s, %i)\n", dst,  debugstr_wn(src,n), n);
252     /* In real windows the whole function is protected by an exception handler
253      * that returns ERROR_INVALID_PARAMETER on faulty parameters
254      * We currently just check for NULL.
255      */
256     if (!dst || !src) {
257         SetLastError(ERROR_INVALID_PARAMETER);
258         return 0;
259     }
260     while ((n-- > 1) && *src) *p++ = *src++;
261     if (n >= 0) *p = 0;
262     return dst;
263 }
264
265
266 /***********************************************************************
267  *           lstrlen   (KERNEL.90)
268  */
269 INT16 WINAPI lstrlen16( LPCSTR str )
270 {
271     return (INT16)lstrlenA( str );
272 }
273
274
275 /***********************************************************************
276  *           lstrlen    (KERNEL32.@)
277  *           lstrlenA   (KERNEL32.@)
278  */
279 INT WINAPI lstrlenA( LPCSTR str )
280 {
281     INT ret;
282     __TRY
283     {
284         ret = strlen(str);
285     }
286     __EXCEPT(page_fault)
287     {
288         SetLastError( ERROR_INVALID_PARAMETER );
289         return 0;
290     }
291     __ENDTRY
292     return ret;
293 }
294
295
296 /***********************************************************************
297  *           lstrlenW   (KERNEL32.@)
298  */
299 INT WINAPI lstrlenW( LPCWSTR str )
300 {
301     INT ret;
302     __TRY
303     {
304         ret = strlenW(str);
305     }
306     __EXCEPT(page_fault)
307     {
308         SetLastError( ERROR_INVALID_PARAMETER );
309         return 0;
310     }
311     __ENDTRY
312     return ret;
313 }
314
315
316 /***********************************************************************
317  *           UnicodeToAnsi   (KERNEL.434)
318  */
319 INT16 WINAPI UnicodeToAnsi16( LPCWSTR src, LPSTR dst, INT16 codepage )
320 {
321     if ( codepage == -1 )
322         codepage = CP_ACP;
323
324     return WideCharToMultiByte( codepage, 0, src, -1, dst, 0x7fffffff, NULL, NULL );
325 }