Reimplemented Unicode case mapping in a slightly more efficient way.
[wine] / dlls / shell32 / shellstring.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <stdlib.h> 
5
6 #include "winnls.h"
7 #include "winerror.h"
8 #include "debugtools.h"
9 #include "winversion.h"
10 #include "crtdll.h"
11 #include "heap.h"
12
13 #include "shellapi.h"
14 #include "wine/undocshell.h"
15
16 DEFAULT_DEBUG_CHANNEL(shell);
17
18 /************************* STRRET functions ****************************/
19
20 /*************************************************************************
21  * StrRetToStrN                                 [SHELL32.96]
22  * 
23  * converts a STRRET to a normal string
24  *
25  * NOTES
26  *  the pidl is for STRRET OFFSET
27  */
28 HRESULT WINAPI StrRetToStrNA (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST pidl)
29 {
30         TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
31
32         switch (src->uType)
33         {
34           case STRRET_WSTR:
35             WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
36             SHFree(src->u.pOleStr);
37             break;
38
39           case STRRET_CSTRA:
40             lstrcpynA((LPSTR)dest, src->u.cStr, len);
41             break;
42
43           case STRRET_OFFSETA:
44             lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
45             break;
46
47           default:
48             FIXME("unknown type!\n");
49             if (len)
50             {
51               *(LPSTR)dest = '\0';
52             }
53             return(FALSE);
54         }
55         return S_OK;
56 }
57
58 HRESULT WINAPI StrRetToStrNW (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST pidl)
59 {
60         TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
61
62         switch (src->uType)
63         {
64           case STRRET_WSTR:
65             lstrcpynW((LPWSTR)dest, src->u.pOleStr, len);
66             SHFree(src->u.pOleStr);
67             break;
68
69           case STRRET_CSTRA:
70             lstrcpynAtoW((LPWSTR)dest, src->u.cStr, len);
71             break;
72
73           case STRRET_OFFSETA:
74             if (pidl)
75             {
76               lstrcpynAtoW((LPWSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
77             }
78             break;
79
80           default:
81             FIXME("unknown type!\n");
82             if (len)
83             { *(LPSTR)dest = '\0';
84             }
85             return(FALSE);
86         }
87         return S_OK;
88 }
89 HRESULT WINAPI StrRetToStrNAW (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST pidl)
90 {
91         if(VERSION_OsIsUnicode())
92           return StrRetToStrNW (dest, len, src, pidl);
93         return StrRetToStrNA (dest, len, src, pidl);
94 }
95
96 /*************************************************************************
97  * StrRetToBufA                                 [SHLWAPI.@]
98  * 
99  * converts a STRRET to a normal string
100  *
101  * NOTES
102  *  the pidl is for STRRET OFFSET
103  */
104 HRESULT WINAPI StrRetToBufA (LPSTRRET src, LPITEMIDLIST pidl, LPSTR dest, DWORD len)
105 {
106         return StrRetToStrNA(dest, len, src, pidl);
107 }
108
109 /*************************************************************************
110  * StrRetToBufW                                 [SHLWAPI.@]
111  * 
112  * converts a STRRET to a normal string
113  *
114  * NOTES
115  *  the pidl is for STRRET OFFSET
116  */
117 HRESULT WINAPI StrRetToBufW (LPSTRRET src, LPITEMIDLIST pidl, LPWSTR dest, DWORD len)
118 {
119         return StrRetToStrNW(dest, len, src, pidl);
120 }
121
122 /************************* string functions ****************************/
123
124 /*************************************************************************
125  * StrChrA                                      [SHLWAPI]
126  */
127 LPSTR WINAPI StrChrA (LPCSTR str, INT c)
128 {
129         TRACE("%s %i stub\n", str,c);
130         return strchr(str, c);
131 }
132
133 /*************************************************************************
134  * StrChrW                                      [NT 4.0:SHELL32.651]
135  *
136  */
137 LPWSTR WINAPI StrChrW (LPWSTR str, WCHAR x )
138 {
139         TRACE("%s 0x%04x\n",debugstr_w(str),x);
140         return CRTDLL_wcschr(str, x);
141 }
142
143 /*************************************************************************
144  * StrCmpNA                                     [NT 4.0:SHELL32.*]
145  */
146 INT WINAPI StrCmpNA ( LPCSTR str1, LPCSTR str2, INT len)
147 {
148         TRACE("%s %s %i stub\n", str1,str2,len);
149         return strncmp(str1, str2, len);
150 }
151
152 /*************************************************************************
153  * StrCmpNW                                     [NT 4.0:SHELL32.*]
154  */
155 INT WINAPI StrCmpNW ( LPCWSTR wstr1, LPCWSTR wstr2, INT len)
156 {
157         TRACE("%s %s %i stub\n", debugstr_w(wstr1),debugstr_w(wstr2),len);
158         return CRTDLL_wcsncmp(wstr1, wstr2, len);
159 }
160
161 /*************************************************************************
162  * StrCmpNIA                                    [NT 4.0:SHELL32.*]
163  */
164 int WINAPI StrCmpNIA ( LPCSTR str1, LPCSTR str2, int len)
165 {
166         TRACE("%s %s %i stub\n", str1,str2,len);
167         return strncasecmp(str1, str2, len);
168 }
169
170 /*************************************************************************
171  * StrCmpNIW                                    [NT 4.0:SHELL32.*]
172  */
173 int WINAPI StrCmpNIW ( LPCWSTR wstr1, LPCWSTR wstr2, int len)
174 {
175         TRACE("%s %s %i stub\n", debugstr_w(wstr1),debugstr_w(wstr2),len);
176         return CRTDLL__wcsnicmp(wstr1, wstr2, len);
177 }
178
179 /*************************************************************************
180  * StrStrA                                      [SHLWAPI]
181  */
182 LPSTR WINAPI StrStrA(LPCSTR lpFirst, LPCSTR lpSrch)
183 {
184     while (*lpFirst)
185     {
186         LPCSTR p1 = lpFirst, p2 = lpSrch;
187         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
188         if (!*p2) return (LPSTR)lpFirst;
189         lpFirst++;
190     }
191     return NULL;
192 }
193
194 /*************************************************************************
195  * StrStrW                                      [SHLWAPI]
196  */
197 LPWSTR WINAPI StrStrW(LPCWSTR lpFirst, LPCWSTR lpSrch)
198 {
199     while (*lpFirst)
200     {
201         LPCWSTR p1 = lpFirst, p2 = lpSrch;
202         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
203         if (!*p2) return (LPWSTR)lpFirst;
204         lpFirst++;
205     }
206     return NULL;
207 }
208
209 /*************************************************************************
210  * StrStrIA                                     [SHLWAPI]
211  */
212 LPSTR WINAPI StrStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
213 {
214     while (*lpFirst)
215     {
216         LPCSTR p1 = lpFirst, p2 = lpSrch;
217         while (*p1 && *p2 && toupper(*p1) == toupper(*p2)) { p1++; p2++; }
218         if (!*p2) return (LPSTR)lpFirst;
219         lpFirst++;
220     }
221     return NULL;
222 }
223
224 /*************************************************************************
225  * StrStrIW                                     [SHLWAPI]
226  */
227 LPWSTR WINAPI StrStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch)
228 {
229     while (*lpFirst)
230     {
231         LPCWSTR p1 = lpFirst, p2 = lpSrch;
232         while (*p1 && *p2 && CRTDLL_towupper(*p1) == CRTDLL_towupper(*p2)) { p1++; p2++; }
233         if (!*p2) return (LPWSTR)lpFirst;
234         lpFirst++;
235     }
236     return NULL;
237 }
238
239 /*************************************************************************
240  *      StrToIntA                       [SHLWAPI]
241  */
242 int WINAPI StrToIntA(LPCSTR lpSrc)
243 {
244         TRACE("%s\n", lpSrc);
245         return atol(lpSrc);
246 }
247
248 /*************************************************************************
249  *      StrToIntW                       [SHLWAPI]
250  */
251 int WINAPI StrToIntW(LPCWSTR lpSrc)
252 {
253         int ret;
254         LPSTR lpStr =  HEAP_strdupWtoA(GetProcessHeap(),0,lpSrc);
255
256         TRACE("%s\n", debugstr_w(lpSrc));
257
258         ret = atol(lpStr);
259         HeapFree(GetProcessHeap(),0,lpStr);
260         return ret;
261 }
262
263 /*************************************************************************
264  *      StrDupA                 [SHLWAPI]
265  */
266 LPSTR WINAPI StrDupA (LPCSTR lpSrc)
267 {
268         int len = strlen(lpSrc);
269         LPSTR lpDest = (LPSTR) LocalAlloc(LMEM_FIXED, len+1);
270         
271         TRACE("%s\n", lpSrc);
272
273         if (lpDest) strcpy(lpDest, lpSrc);
274         return lpDest;
275 }
276
277 /*************************************************************************
278  *      StrDupW                 [SHLWAPI]
279  */
280 LPWSTR WINAPI StrDupW (LPCWSTR lpSrc)
281 {
282         int len = lstrlenW(lpSrc);
283         LPWSTR lpDest = (LPWSTR) LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * (len+1));
284         
285         TRACE("%s\n", debugstr_w(lpSrc));
286
287         if (lpDest) lstrcpyW(lpDest, lpSrc);
288         return lpDest;
289 }
290
291 /*************************************************************************
292  *      StrCSpnA                [SHLWAPI]
293  */
294 int WINAPI StrCSpnA (LPCSTR lpStr, LPCSTR lpSet)
295 {
296         int i,j, pos = strlen(lpStr);
297
298         TRACE("(%p %s  %p %s)\n",
299            lpStr, debugstr_a(lpStr), lpSet, debugstr_a(lpSet));
300
301         for (i=0; i < strlen(lpSet) ; i++ )
302         {
303           for (j = 0; j < pos;j++)
304           {
305             if (lpStr[j] == lpSet[i])
306             {
307               pos = j;
308             }
309           }
310         }      
311         TRACE("-- %u\n", pos);
312         return pos;     
313 }
314
315 /*************************************************************************
316  *      StrCSpnW                [SHLWAPI]
317  */
318 int WINAPI StrCSpnW (LPCWSTR lpStr, LPCWSTR lpSet)
319 {
320         int i,j, pos = lstrlenW(lpStr);
321
322         TRACE("(%p %s %p %s)\n",
323            lpStr, debugstr_w(lpStr), lpSet, debugstr_w(lpSet));
324
325         for (i=0; i < lstrlenW(lpSet) ; i++ )
326         {
327           for (j = 0; j < pos;j++)
328           {
329             if (lpStr[j] == lpSet[i])
330             {
331               pos = j;
332             }
333           }
334         }      
335         TRACE("-- %u\n", pos);
336         return pos;     
337 }
338
339 /************************* OLESTR functions ****************************/
340
341 /************************************************************************
342  *      StrToOleStr                     [SHELL32.163]
343  *
344  */
345 int WINAPI StrToOleStrA (LPWSTR lpWideCharStr, LPCSTR lpMultiByteString)
346 {
347         TRACE("(%p, %p %s)\n",
348         lpWideCharStr, lpMultiByteString, debugstr_a(lpMultiByteString));
349
350         return MultiByteToWideChar(0, 0, lpMultiByteString, -1, lpWideCharStr, MAX_PATH);
351
352 }
353 int WINAPI StrToOleStrW (LPWSTR lpWideCharStr, LPCWSTR lpWString)
354 {
355         TRACE("(%p, %p %s)\n",
356         lpWideCharStr, lpWString, debugstr_w(lpWString));
357
358         if (lstrcpyW (lpWideCharStr, lpWString ))
359         { return lstrlenW (lpWideCharStr);
360         }
361         return 0;
362 }
363
364 BOOL WINAPI StrToOleStrAW (LPWSTR lpWideCharStr, LPCVOID lpString)
365 {
366         if (VERSION_OsIsUnicode())
367           return StrToOleStrW (lpWideCharStr, lpString);
368         return StrToOleStrA (lpWideCharStr, lpString);
369 }
370
371 /*************************************************************************
372  * StrToOleStrN                                 [SHELL32.79]
373  *  lpMulti, nMulti, nWide [IN]
374  *  lpWide [OUT]
375  */
376 BOOL WINAPI StrToOleStrNA (LPWSTR lpWide, INT nWide, LPCSTR lpStrA, INT nStr) 
377 {
378         TRACE("(%p, %x, %s, %x)\n", lpWide, nWide, debugstr_an(lpStrA,nStr), nStr);
379         return MultiByteToWideChar (0, 0, lpStrA, nStr, lpWide, nWide);
380 }
381 BOOL WINAPI StrToOleStrNW (LPWSTR lpWide, INT nWide, LPCWSTR lpStrW, INT nStr) 
382 {
383         TRACE("(%p, %x, %s, %x)\n", lpWide, nWide, debugstr_wn(lpStrW, nStr), nStr);
384
385         if (lstrcpynW (lpWide, lpStrW, nWide))
386         { return lstrlenW (lpWide);
387         }
388         return 0;
389 }
390
391 BOOL WINAPI StrToOleStrNAW (LPWSTR lpWide, INT nWide, LPCVOID lpStr, INT nStr) 
392 {
393         if (VERSION_OsIsUnicode())
394           return StrToOleStrNW (lpWide, nWide, lpStr, nStr);
395         return StrToOleStrNA (lpWide, nWide, lpStr, nStr);
396 }
397
398 /*************************************************************************
399  * OleStrToStrN                                 [SHELL32.78]
400  */
401 BOOL WINAPI OleStrToStrNA (LPSTR lpStr, INT nStr, LPCWSTR lpOle, INT nOle) 
402 {
403         TRACE("(%p, %x, %s, %x)\n", lpStr, nStr, debugstr_wn(lpOle,nOle), nOle);
404         return WideCharToMultiByte (0, 0, lpOle, nOle, lpStr, nStr, NULL, NULL);
405 }
406
407 BOOL WINAPI OleStrToStrNW (LPWSTR lpwStr, INT nwStr, LPCWSTR lpOle, INT nOle) 
408 {
409         TRACE("(%p, %x, %s, %x)\n", lpwStr, nwStr, debugstr_wn(lpOle,nOle), nOle);
410
411         if (lstrcpynW ( lpwStr, lpOle, nwStr))
412         { return lstrlenW (lpwStr);
413         }
414         return 0;
415 }
416
417 BOOL WINAPI OleStrToStrNAW (LPVOID lpOut, INT nOut, LPCVOID lpIn, INT nIn) 
418 {
419         if (VERSION_OsIsUnicode())
420           return OleStrToStrNW (lpOut, nOut, lpIn, nIn);
421         return OleStrToStrNA (lpOut, nOut, lpIn, nIn);
422 }
423
424 /*************************************************************************
425  * StrFormatByteSizeA                           [SHLWAPI]
426  */
427 LPSTR WINAPI StrFormatByteSizeA ( DWORD dw, LPSTR pszBuf, UINT cchBuf )
428 {       char buf[64];
429         TRACE("%lx %p %i\n", dw, pszBuf, cchBuf);
430         if ( dw<1024L )
431         { sprintf (buf,"%3.1f bytes", (FLOAT)dw);
432         }
433         else if ( dw<1048576L)
434         { sprintf (buf,"%3.1f KB", (FLOAT)dw/1024);
435         }
436         else if ( dw < 1073741824L)
437         { sprintf (buf,"%3.1f MB", (FLOAT)dw/1048576L);
438         }
439         else
440         { sprintf (buf,"%3.1f GB", (FLOAT)dw/1073741824L);
441         }
442         lstrcpynA (pszBuf, buf, cchBuf);
443         return pszBuf;  
444 }
445
446 /*************************************************************************
447  * StrFormatByteSizeW                           [SHLWAPI]
448  */
449 LPWSTR WINAPI StrFormatByteSizeW ( DWORD dw, LPWSTR pszBuf, UINT cchBuf )
450 {       char buf[64];
451         TRACE("%lx %p %i\n", dw, pszBuf, cchBuf);
452         if ( dw<1024L )
453         { sprintf (buf,"%3.1f bytes", (FLOAT)dw);
454         }
455         else if ( dw<1048576L)
456         { sprintf (buf,"%3.1f KB", (FLOAT)dw/1024);
457         }
458         else if ( dw < 1073741824L)
459         { sprintf (buf,"%3.1f MB", (FLOAT)dw/1048576L);
460         }
461         else
462         { sprintf (buf,"%3.1f GB", (FLOAT)dw/1073741824L);
463         }
464         lstrcpynAtoW (pszBuf, buf, cchBuf);
465         return pszBuf;  
466 }
467