- Indicate that StrRetToStrN{A|W} and StrRetToBuf{A|W} are identical
[wine] / dlls / shlwapi / string.c
1 #include <ctype.h>
2 #include <stdlib.h> 
3 #include <stdio.h>
4 #include <string.h>
5 #include <wctype.h>
6
7 #include "winerror.h"
8 #include "windef.h"
9 #include "winbase.h"
10 #include "wingdi.h"
11 #include "winuser.h"
12 #include "shlwapi.h"
13 #include "shlobj.h"
14 #include "wine/unicode.h"
15 #include "debugtools.h"
16
17 DEFAULT_DEBUG_CHANNEL(shell);
18
19 /*************************************************************************
20  * StrChrA                                      [SHLWAPI.@]
21  */
22 LPSTR WINAPI StrChrA (LPCSTR str, WORD c)
23 {
24         TRACE("%s %i\n", str,c);
25         return strchr(str, c);
26 }
27
28 /*************************************************************************
29  * StrChrW                                      [SHLWAPI.@]
30  *
31  */
32 LPWSTR WINAPI StrChrW (LPCWSTR str, WCHAR x )
33 {
34         TRACE("%s 0x%04x\n",debugstr_w(str),x);
35         return strchrW(str, x);
36 }
37
38 /*************************************************************************
39  * StrCmpIW                                     [SHLWAPI.@]
40  */
41 int WINAPI StrCmpIW ( LPCWSTR wstr1, LPCWSTR wstr2 )
42 {
43     TRACE("%s %s\n", debugstr_w(wstr1),debugstr_w(wstr2));
44     return strcmpiW( wstr1, wstr2 );
45 }
46
47 /*************************************************************************
48  * StrCmpNA                                     [SHLWAPI.@]
49  */
50 INT WINAPI StrCmpNA ( LPCSTR str1, LPCSTR str2, INT len)
51 {
52         TRACE("%s %s %i stub\n", str1,str2,len);
53         return strncmp(str1, str2, len);
54 }
55
56 /*************************************************************************
57  * StrCmpNW                                     [SHLWAPI.@]
58  */
59 INT WINAPI StrCmpNW ( LPCWSTR wstr1, LPCWSTR wstr2, INT len)
60 {
61         TRACE("%s %s %i stub\n", debugstr_w(wstr1),debugstr_w(wstr2),len);
62         return strncmpW(wstr1, wstr2, len);
63 }
64
65 /*************************************************************************
66  * StrCmpNIA                                    [SHLWAPI.@]
67  */
68 int WINAPI StrCmpNIA ( LPCSTR str1, LPCSTR str2, int len)
69 {
70         TRACE("%s %s %i stub\n", str1,str2,len);
71         return strncasecmp(str1, str2, len);
72 }
73
74 /*************************************************************************
75  * StrCmpNIW                                    [SHLWAPI.@]
76  */
77 int WINAPI StrCmpNIW ( LPCWSTR wstr1, LPCWSTR wstr2, int len)
78 {
79         TRACE("%s %s %i stub\n", debugstr_w(wstr1),debugstr_w(wstr2),len);
80         return strncmpiW(wstr1, wstr2, len);
81 }
82
83 /*************************************************************************
84  * StrCmpW                                      [SHLWAPI.@]
85  */
86 int WINAPI StrCmpW ( LPCWSTR wstr1, LPCWSTR wstr2 )
87 {
88     TRACE("%s %s\n", debugstr_w(wstr1),debugstr_w(wstr2));
89     return strcmpW( wstr1, wstr2 );
90 }
91
92 /*************************************************************************
93  * StrCatW                                      [SHLWAPI.@]
94  */
95 LPWSTR WINAPI StrCatW( LPWSTR wstr1, LPCWSTR wstr2 )
96 {
97     return strcatW( wstr1, wstr2 );
98 }
99
100
101 /*************************************************************************
102  * StrCpyW                                      [SHLWAPI.@]
103  */
104 LPWSTR WINAPI StrCpyW( LPWSTR wstr1, LPCWSTR wstr2 )
105 {
106     return strcpyW( wstr1, wstr2 );
107 }
108
109
110 /*************************************************************************
111  * StrCpyNW                                     [SHLWAPI.@]
112  */
113 LPWSTR WINAPI StrCpyNW( LPWSTR wstr1, LPCWSTR wstr2, int n )
114 {
115     return lstrcpynW( wstr1, wstr2, n );
116 }
117
118
119 /*************************************************************************
120  * StrStrA                                      [SHLWAPI.@]
121  */
122 LPSTR WINAPI StrStrA(LPCSTR lpFirst, LPCSTR lpSrch)
123 {
124     while (*lpFirst)
125     {
126         LPCSTR p1 = lpFirst, p2 = lpSrch;
127         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
128         if (!*p2) return (LPSTR)lpFirst;
129         lpFirst++;
130     }
131     return NULL;
132 }
133
134 /*************************************************************************
135  * StrStrW                                      [SHLWAPI.@]
136  */
137 LPWSTR WINAPI StrStrW(LPCWSTR lpFirst, LPCWSTR lpSrch)
138 {
139     while (*lpFirst)
140     {
141         LPCWSTR p1 = lpFirst, p2 = lpSrch;
142         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
143         if (!*p2) return (LPWSTR)lpFirst;
144         lpFirst++;
145     }
146     return NULL;
147 }
148
149 /*************************************************************************
150  * StrStrIA                                     [SHLWAPI.@]
151  */
152 LPSTR WINAPI StrStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
153 {
154     while (*lpFirst)
155     {
156         LPCSTR p1 = lpFirst, p2 = lpSrch;
157         while (*p1 && *p2 && toupper(*p1) == toupper(*p2)) { p1++; p2++; }
158         if (!*p2) return (LPSTR)lpFirst;
159         lpFirst++;
160     }
161     return NULL;
162 }
163
164 /*************************************************************************
165  * StrStrIW                                     [SHLWAPI.@]
166  */
167 LPWSTR WINAPI StrStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch)
168 {
169     while (*lpFirst)
170     {
171         LPCWSTR p1 = lpFirst, p2 = lpSrch;
172         while (*p1 && *p2 && toupperW(*p1) == toupperW(*p2)) { p1++; p2++; }
173         if (!*p2) return (LPWSTR)lpFirst;
174         lpFirst++;
175     }
176     return NULL;
177 }
178
179 /*************************************************************************
180  *      StrToIntA                       [SHLWAPI.@]
181  */
182 int WINAPI StrToIntA(LPCSTR lpSrc)
183 {
184         TRACE("%s\n", lpSrc);
185         return atol(lpSrc);
186 }
187
188 /*************************************************************************
189  *      StrToIntW                       [SHLWAPI.@]
190  */
191 int WINAPI StrToIntW(LPCWSTR lpSrc)
192 {
193     char buffer[32];
194
195     TRACE("%s\n", debugstr_w(lpSrc));
196     WideCharToMultiByte( CP_ACP, 0, lpSrc, -1, buffer, sizeof(buffer), NULL, NULL );
197     buffer[sizeof(buffer)-1] = 0;
198     return atol(buffer);
199 }
200
201 /*************************************************************************
202  *      StrToIntExA                     [SHLWAPI.@]
203  */
204 BOOL WINAPI StrToIntExA( LPCSTR pszString, DWORD dwFlags, LPINT piRet)
205 {
206         TRACE("%s %ld stub !\n", debugstr_a(pszString), dwFlags);
207         piRet = (LPINT) StrToIntA(pszString);
208         return TRUE;
209 }
210
211 /*************************************************************************
212  *      StrToIntExW                     [SHLWAPI.@]
213  */
214 BOOL WINAPI StrToIntExW( LPCWSTR pszString, DWORD dwFlags, LPINT piRet)
215 {
216         TRACE("%s %ld stub !\n", debugstr_w(pszString), dwFlags);
217         piRet = (LPINT) StrToIntW(pszString);
218         return TRUE;
219 }
220
221 /*************************************************************************
222  *      StrDupA                 [SHLWAPI.@]
223  */
224 LPSTR WINAPI StrDupA (LPCSTR lpSrc)
225 {
226         int len = strlen(lpSrc);
227         LPSTR lpDest = (LPSTR) LocalAlloc(LMEM_FIXED, len+1);
228         
229         TRACE("%s\n", lpSrc);
230
231         if (lpDest) strcpy(lpDest, lpSrc);
232         return lpDest;
233 }
234
235 /*************************************************************************
236  *      StrDupW                 [SHLWAPI.@]
237  */
238 LPWSTR WINAPI StrDupW (LPCWSTR lpSrc)
239 {
240         int len = strlenW(lpSrc);
241         LPWSTR lpDest = (LPWSTR) LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * (len+1));
242         
243         TRACE("%s\n", debugstr_w(lpSrc));
244
245         if (lpDest) strcpyW(lpDest, lpSrc);
246         return lpDest;
247 }
248
249 /*************************************************************************
250  *      StrCSpnA                [SHLWAPI.@]
251  */
252 int WINAPI StrCSpnA (LPCSTR lpStr, LPCSTR lpSet)
253 {
254         int i,j, pos = strlen(lpStr);
255
256         TRACE("(%p %s  %p %s)\n",
257            lpStr, debugstr_a(lpStr), lpSet, debugstr_a(lpSet));
258
259         for (i=0; i < strlen(lpSet) ; i++ )
260         {
261           for (j = 0; j < pos;j++)
262           {
263             if (lpStr[j] == lpSet[i])
264             {
265               pos = j;
266             }
267           }
268         }      
269         TRACE("-- %u\n", pos);
270         return pos;     
271 }
272
273 /*************************************************************************
274  *      StrCSpnW                [SHLWAPI.@]
275  */
276 int WINAPI StrCSpnW (LPCWSTR lpStr, LPCWSTR lpSet)
277 {
278         int i,j, pos = strlenW(lpStr);
279
280         TRACE("(%p %s %p %s)\n",
281            lpStr, debugstr_w(lpStr), lpSet, debugstr_w(lpSet));
282
283         for (i=0; i < strlenW(lpSet) ; i++ )
284         {
285           for (j = 0; j < pos;j++)
286           {
287             if (lpStr[j] == lpSet[i])
288             {
289               pos = j;
290             }
291           }
292         }      
293         TRACE("-- %u\n", pos);
294         return pos;     
295 }
296
297 /**************************************************************************
298  * StrRChrA [SHLWAPI.@]
299  *
300  */
301 LPSTR WINAPI StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
302 {
303     LPCSTR lpGotIt = NULL;
304     BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
305
306     TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
307
308     if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
309
310     for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
311     {
312         if (*lpStart != LOBYTE(wMatch)) continue;
313         if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue;
314         lpGotIt = lpStart;
315     }    
316     return (LPSTR)lpGotIt;
317 }
318
319
320 /**************************************************************************
321  * StrRChrW [SHLWAPI.@]
322  *
323  */
324 LPWSTR WINAPI StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
325 {
326     LPCWSTR lpGotIt = NULL;
327
328     TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
329     if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
330
331     for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
332         if (*lpStart == wMatch) lpGotIt = lpStart;
333
334     return (LPWSTR)lpGotIt;
335 }
336
337
338 /**************************************************************************
339  * StrRChrIA [SHLWAPI.@]
340  *
341  */
342 LPSTR WINAPI StrRChrIA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
343 {
344     LPCSTR lpGotIt = NULL;
345     BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
346
347     TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
348
349     if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
350
351     for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
352     {
353         if (dbcs) {
354             /*
355             if (_mbctoupper(*lpStart) == _mbctoupper(wMatch))
356                 lpGotIt = lpStart;
357             */
358             if (toupper(*lpStart) == toupper(wMatch)) lpGotIt = lpStart;
359         } else {
360             if (toupper(*lpStart) == toupper(wMatch)) lpGotIt = lpStart;
361         }
362     }    
363     return (LPSTR)lpGotIt;
364 }
365
366
367 /**************************************************************************
368  * StrRChrIW [SHLWAPI.@]
369  *
370  */
371 LPWSTR WINAPI StrRChrIW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
372 {
373     LPCWSTR lpGotIt = NULL;
374
375     TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
376     if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
377
378     for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
379         if (towupper(*lpStart) == towupper(wMatch)) lpGotIt = lpStart;
380
381     return (LPWSTR)lpGotIt;
382 }
383
384
385 /*************************************************************************
386  *      StrCatBuffA             [SHLWAPI.@]
387  *
388  * Appends back onto front, stopping when front is size-1 characters long.
389  * Returns front.
390  *
391  */
392 LPSTR WINAPI StrCatBuffA(LPSTR front, LPCSTR back, INT size)
393 {
394     LPSTR dst = front + strlen(front);
395     LPCSTR src = back, end = front + size - 1;
396
397     while(dst < end && *src)
398         *dst++ = *src++;
399     *dst = '\0';
400     return front;
401 }
402
403 /*************************************************************************
404  *      StrCatBuffW             [SHLWAPI.@]
405  *
406  * Appends back onto front, stopping when front is size-1 characters long.
407  * Returns front.
408  *
409  */
410 LPWSTR WINAPI StrCatBuffW(LPWSTR front, LPCWSTR back, INT size)
411 {
412     LPWSTR dst = front + strlenW(front);
413     LPCWSTR src = back, end = front + size - 1;
414
415     while(dst < end && *src)
416         *dst++ = *src++;
417     *dst = '\0';
418     return front;
419 }
420
421 /*************************************************************************
422  * StrRetToBufA                                 [SHLWAPI.@]
423  * 
424  * converts a STRRET to a normal string
425  *
426  * NOTES
427  *  the pidl is for STRRET OFFSET
428  *
429  * ***** NOTE *****
430  *  This routine is identical to StrRetToStrNA in dlls/shell32/shellstring.c.
431  *  It was duplicated there because not every version of Shlwapi.dll exports
432  *  StrRetToBufA. If you change one routine, change them both. YOU HAVE BEEN
433  *  WARNED.
434  * ***** NOTE *****
435  */
436 HRESULT WINAPI StrRetToBufA (LPSTRRET src, const ITEMIDLIST *pidl, LPSTR dest, DWORD len)
437 {
438         TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
439
440         switch (src->uType)
441         {
442           case STRRET_WSTR:
443             WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, (LPSTR)dest, len, NULL, NULL);
444 /*          SHFree(src->u.pOleStr);  FIXME: is this right? */
445             break;
446
447           case STRRET_CSTRA:
448             lstrcpynA((LPSTR)dest, src->u.cStr, len);
449             break;
450
451           case STRRET_OFFSETA:
452             lstrcpynA((LPSTR)dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len);
453             break;
454
455           default:
456             FIXME("unknown type!\n");
457             if (len)
458             {
459               *(LPSTR)dest = '\0';
460             }
461             return(FALSE);
462         }
463         return S_OK;
464 }
465
466 /*************************************************************************
467  * StrRetToBufW                                 [SHLWAPI.@]
468  * 
469  * converts a STRRET to a normal string
470  *
471  * NOTES
472  *  the pidl is for STRRET OFFSET
473  *
474  * ***** NOTE *****
475  *  This routine is identical to StrRetToStrNW in dlls/shell32/shellstring.c.
476  *  It was duplicated there because not every version of Shlwapi.dll exports
477  *  StrRetToBufW. If you change one routine, change them both. YOU HAVE BEEN
478  *  WARNED.
479  * ***** NOTE *****
480  */
481 HRESULT WINAPI StrRetToBufW (LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, DWORD len)
482 {
483         TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
484
485         switch (src->uType)
486         {
487           case STRRET_WSTR:
488             lstrcpynW((LPWSTR)dest, src->u.pOleStr, len);
489 /*          SHFree(src->u.pOleStr);  FIXME: is this right? */
490             break;
491
492           case STRRET_CSTRA:
493               if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ) && len)
494                   dest[len-1] = 0;
495             break;
496
497           case STRRET_OFFSETA:
498             if (pidl)
499             {
500               if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
501                                         dest, len ) && len)
502                   dest[len-1] = 0;
503             }
504             break;
505
506           default:
507             FIXME("unknown type!\n");
508             if (len)
509             { *(LPSTR)dest = '\0';
510             }
511             return(FALSE);
512         }
513         return S_OK;
514 }
515
516 /*************************************************************************
517  * StrFormatByteSizeA                           [SHLWAPI.@]
518  */
519 LPSTR WINAPI StrFormatByteSizeA ( DWORD dw, LPSTR pszBuf, UINT cchBuf )
520 {       char buf[64];
521         TRACE("%lx %p %i\n", dw, pszBuf, cchBuf);
522         if ( dw<1024L )
523         { sprintf (buf,"%ld bytes", dw);
524         }
525         else if ( dw<1048576L)
526         { sprintf (buf,"%3.1f KB", (FLOAT)dw/1024);
527         }
528         else if ( dw < 1073741824L)
529         { sprintf (buf,"%3.1f MB", (FLOAT)dw/1048576L);
530         }
531         else
532         { sprintf (buf,"%3.1f GB", (FLOAT)dw/1073741824L);
533         }
534         lstrcpynA (pszBuf, buf, cchBuf);
535         return pszBuf;  
536 }
537
538 /*************************************************************************
539  * StrFormatByteSizeW                           [SHLWAPI.@]
540  */
541 LPWSTR WINAPI StrFormatByteSizeW ( DWORD dw, LPWSTR pszBuf, UINT cchBuf )
542 {
543         char buf[64];
544         StrFormatByteSizeA( dw, buf, sizeof(buf) );
545         if (!MultiByteToWideChar( CP_ACP, 0, buf, -1, pszBuf, cchBuf ) && cchBuf)
546             pszBuf[cchBuf-1] = 0;
547         return pszBuf;
548 }
549
550 /*************************************************************************
551  *      StrNCatA        [SHLWAPI.@]
552  */
553 LPSTR WINAPI StrNCatA(LPSTR front, LPCSTR back, INT cchMax)
554 {
555         TRACE("%s %s %i stub\n", debugstr_a(front),debugstr_a(back),cchMax);
556         return (front);
557 }
558
559 /*************************************************************************
560  *      StrNCatW        [SHLWAPI.@]
561  */
562 LPWSTR WINAPI StrNCatW(LPWSTR front, LPCWSTR back, INT cchMax)
563 {
564         TRACE("%s %s %i stub\n", debugstr_w(front),debugstr_w(back),cchMax);
565         return (front);
566 }
567
568 /*************************************************************************
569  *      StrTrimA        [SHLWAPI.@]
570  */
571 BOOL WINAPI StrTrimA(LPSTR pszSource, LPCSTR pszTrimChars)
572 {
573     BOOL trimmed = FALSE;
574     LPSTR pSrc;
575     LPCSTR pTrim;
576
577     TRACE("('%s', '%s');\n", pszSource, pszTrimChars);
578     for (pTrim = pszTrimChars; *pTrim; pTrim++)
579     {
580          for (pSrc = pszSource; *pSrc; pSrc++)
581              if (*pSrc == *pTrim)
582              {
583                  /* match -> remove this char.
584                   * strlen(pSrc) equiv. to the correct strlen(pSrc+1)+1 */
585                  memmove(pSrc, pSrc+1, strlen(pSrc));
586                  trimmed = TRUE;
587              }
588     }
589     TRACE("<- '%s'\n", pszSource);
590     return trimmed;
591 }
592
593 /*************************************************************************
594  *      wnsprintfA      [SHLWAPI.@]
595  */
596 int WINAPIV wnsprintfA(LPSTR lpOut, int cchLimitIn, LPCSTR lpFmt, ...)
597 {
598     va_list valist;
599     INT res;
600
601     va_start( valist, lpFmt );
602     res = wvsnprintfA( lpOut, cchLimitIn, lpFmt, valist );
603     va_end( valist );
604     return res;
605 }
606
607 /*************************************************************************
608  *      wnsprintfW      [SHLWAPI.@]
609  */
610 int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...)
611 {
612     va_list valist;
613     INT res;
614
615     va_start( valist, lpFmt );
616     res = wvsnprintfW( lpOut, cchLimitIn, lpFmt, valist );
617     va_end( valist );
618     return res;
619 }