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