riched20: Pass the run to the text drawing routine.
[wine] / dlls / ntdll / string.c
1 /*
2  * NTDLL string functions
3  *
4  * Copyright 2000 Alexandre Julliard
5  * Copyright 2000 Jon Griffiths
6  * Copyright 2003 Thomas Mertes
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <ctype.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "windef.h"
33 #include "winternl.h"
34
35
36 /*********************************************************************
37  *                  memchr   (NTDLL.@)
38  */
39 void * __cdecl NTDLL_memchr( const void *ptr, int c, size_t n )
40 {
41     return memchr( ptr, c, n );
42 }
43
44
45 /*********************************************************************
46  *                  memcmp   (NTDLL.@)
47  */
48 int __cdecl NTDLL_memcmp( const void *ptr1, const void *ptr2, size_t n )
49 {
50     return memcmp( ptr1, ptr2, n );
51 }
52
53
54 /*********************************************************************
55  *                  memcpy   (NTDLL.@)
56  *
57  * NOTES
58  *  Behaves like memmove.
59  */
60 void * __cdecl NTDLL_memcpy( void *dst, const void *src, size_t n )
61 {
62     return memmove( dst, src, n );
63 }
64
65
66 /*********************************************************************
67  *                  memmove   (NTDLL.@)
68  */
69 void * __cdecl NTDLL_memmove( void *dst, const void *src, size_t n )
70 {
71     return memmove( dst, src, n );
72 }
73
74
75 /*********************************************************************
76  *                  memset   (NTDLL.@)
77  */
78 void * __cdecl NTDLL_memset( void *dst, int c, size_t n )
79 {
80     return memset( dst, c, n );
81 }
82
83
84 /*********************************************************************
85  *                  strcat   (NTDLL.@)
86  */
87 char * __cdecl NTDLL_strcat( char *dst, const char *src )
88 {
89     return strcat( dst, src );
90 }
91
92
93 /*********************************************************************
94  *                  strchr   (NTDLL.@)
95  */
96 char * __cdecl NTDLL_strchr( const char *str, int c )
97 {
98     return strchr( str, c );
99 }
100
101
102 /*********************************************************************
103  *                  strcmp   (NTDLL.@)
104  */
105 int __cdecl NTDLL_strcmp( const char *str1, const char *str2 )
106 {
107     return strcmp( str1, str2 );
108 }
109
110
111 /*********************************************************************
112  *                  strcpy   (NTDLL.@)
113  */
114 char * __cdecl NTDLL_strcpy( char *dst, const char *src )
115 {
116     return strcpy( dst, src );
117 }
118
119
120 /*********************************************************************
121  *                  strcspn   (NTDLL.@)
122  */
123 size_t __cdecl NTDLL_strcspn( const char *str, const char *reject )
124 {
125     return strcspn( str, reject );
126 }
127
128
129 /*********************************************************************
130  *                  strlen   (NTDLL.@)
131  */
132 size_t __cdecl NTDLL_strlen( const char *str )
133 {
134     return strlen( str );
135 }
136
137
138 /*********************************************************************
139  *                  strncat   (NTDLL.@)
140  */
141 char * __cdecl NTDLL_strncat( char *dst, const char *src, size_t len )
142 {
143     return strncat( dst, src, len );
144 }
145
146
147 /*********************************************************************
148  *                  strncmp   (NTDLL.@)
149  */
150 int __cdecl NTDLL_strncmp( const char *str1, const char *str2, size_t len )
151 {
152     return strncmp( str1, str2, len );
153 }
154
155
156 /*********************************************************************
157  *                  strncpy   (NTDLL.@)
158  */
159 char * __cdecl NTDLL_strncpy( char *dst, const char *src, size_t len )
160 {
161     return strncpy( dst, src, len );
162 }
163
164
165 /*********************************************************************
166  *                  strpbrk   (NTDLL.@)
167  */
168 char * __cdecl NTDLL_strpbrk( const char *str, const char *accept )
169 {
170     return strpbrk( str, accept );
171 }
172
173
174 /*********************************************************************
175  *                  strrchr   (NTDLL.@)
176  */
177 char * __cdecl NTDLL_strrchr( const char *str, int c )
178 {
179     return strrchr( str, c );
180 }
181
182
183 /*********************************************************************
184  *                  strspn   (NTDLL.@)
185  */
186 size_t __cdecl NTDLL_strspn( const char *str, const char *accept )
187 {
188     return strspn( str, accept );
189 }
190
191
192 /*********************************************************************
193  *                  strstr   (NTDLL.@)
194  */
195 char * __cdecl NTDLL_strstr( const char *haystack, const char *needle )
196 {
197     return strstr( haystack, needle );
198 }
199
200
201 /*********************************************************************
202  *                  _memccpy   (NTDLL.@)
203  */
204 void * __cdecl _memccpy( void *dst, const void *src, int c, size_t n )
205 {
206     return memccpy( dst, src, c, n );
207 }
208
209
210 /*********************************************************************
211  *                  _memicmp   (NTDLL.@)
212  *
213  * Compare two blocks of memory as strings, ignoring case.
214  *
215  * PARAMS
216  *  s1  [I] First string to compare to s2
217  *  s2  [I] Second string to compare to s1
218  *  len [I] Number of bytes to compare
219  *
220  * RETURNS
221  *  An integer less than, equal to, or greater than zero indicating that
222  *  s1 is less than, equal to or greater than s2 respectively.
223  *
224  * NOTES
225  *  Any Nul characters in s1 or s2 are ignored. This function always
226  *  compares up to len bytes or the first place where s1 and s2 differ.
227  */
228 INT __cdecl _memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
229 {
230     int ret = 0;
231     while (len--)
232     {
233         if ((ret = tolower(*s1) - tolower(*s2))) break;
234         s1++;
235         s2++;
236     }
237     return ret;
238 }
239
240
241 /*********************************************************************
242  *                  _stricmp   (NTDLL.@)
243  *                  _strcmpi   (NTDLL.@)
244  */
245 int __cdecl _stricmp( LPCSTR str1, LPCSTR str2 )
246 {
247     return strcasecmp( str1, str2 );
248 }
249
250
251 /*********************************************************************
252  *                  _strnicmp   (NTDLL.@)
253  */
254 int __cdecl _strnicmp( LPCSTR str1, LPCSTR str2, size_t n )
255 {
256     return strncasecmp( str1, str2, n );
257 }
258
259
260 /*********************************************************************
261  *                  _strupr   (NTDLL.@)
262  *
263  * Convert a string to upper case.
264  *
265  * PARAMS
266  *  str [I/O] String to convert
267  *
268  * RETURNS
269  *  str. There is no error return, if str is NULL or invalid, this
270  *  function will crash.
271  */
272 LPSTR __cdecl _strupr( LPSTR str )
273 {
274     LPSTR ret = str;
275     for ( ; *str; str++) *str = toupper(*str);
276     return ret;
277 }
278
279
280 /*********************************************************************
281  *                  _strlwr   (NTDLL.@)
282  *
283  * Convert a string to lowercase
284  *
285  * PARAMS
286  *  str [I/O] String to convert
287  *
288  * RETURNS
289  *  str. There is no error return, if str is NULL or invalid, this
290  *  function will crash.
291  */
292 LPSTR __cdecl _strlwr( LPSTR str )
293 {
294     LPSTR ret = str;
295     for ( ; *str; str++) *str = tolower(*str);
296     return ret;
297 }
298
299
300 /*********************************************************************
301  *                  tolower   (NTDLL.@)
302  */
303 int __cdecl NTDLL_tolower( int c )
304 {
305     return tolower( c );
306 }
307
308
309 /*********************************************************************
310  *                  toupper   (NTDLL.@)
311  */
312 int __cdecl NTDLL_toupper( int c )
313 {
314     return toupper( c );
315 }
316
317
318 /*********************************************************************
319  *                  isalnum   (NTDLL.@)
320  */
321 int __cdecl NTDLL_isalnum( int c )
322 {
323     return isalnum( c );
324 }
325
326
327 /*********************************************************************
328  *                  isalpha   (NTDLL.@)
329  */
330 int __cdecl NTDLL_isalpha( int c )
331 {
332     return isalpha( c );
333 }
334
335
336 /*********************************************************************
337  *                  iscntrl   (NTDLL.@)
338  */
339 int __cdecl NTDLL_iscntrl( int c )
340 {
341     return iscntrl( c );
342 }
343
344
345 /*********************************************************************
346  *                  isdigit   (NTDLL.@)
347  */
348 int __cdecl NTDLL_isdigit( int c )
349 {
350     return isdigit( c );
351 }
352
353
354 /*********************************************************************
355  *                  isgraph   (NTDLL.@)
356  */
357 int __cdecl NTDLL_isgraph( int c )
358 {
359     return isgraph( c );
360 }
361
362
363 /*********************************************************************
364  *                  islower   (NTDLL.@)
365  */
366 int __cdecl NTDLL_islower( int c )
367 {
368     return islower( c );
369 }
370
371
372 /*********************************************************************
373  *                  isprint   (NTDLL.@)
374  */
375 int __cdecl NTDLL_isprint( int c )
376 {
377     return isprint( c );
378 }
379
380
381 /*********************************************************************
382  *                  ispunct   (NTDLL.@)
383  */
384 int __cdecl NTDLL_ispunct( int c )
385 {
386     return ispunct( c );
387 }
388
389
390 /*********************************************************************
391  *                  isspace   (NTDLL.@)
392  */
393 int __cdecl NTDLL_isspace( int c )
394 {
395     return isspace( c );
396 }
397
398
399 /*********************************************************************
400  *                  isupper   (NTDLL.@)
401  */
402 int __cdecl NTDLL_isupper( int c )
403 {
404     return isupper( c );
405 }
406
407
408 /*********************************************************************
409  *                  isxdigit   (NTDLL.@)
410  */
411 int __cdecl NTDLL_isxdigit( int c )
412 {
413     return isxdigit( c );
414 }
415
416
417 /*********************************************************************
418  *                  strtol   (NTDLL.@)
419  */
420 LONG __cdecl NTDLL_strtol( const char *nptr, char **endptr, int base )
421 {
422     return strtol( nptr, endptr, base );
423 }
424
425
426 /*********************************************************************
427  *                  strtoul   (NTDLL.@)
428  */
429 ULONG __cdecl NTDLL_strtoul( const char *nptr, char **endptr, int base )
430 {
431     return strtoul( nptr, endptr, base );
432 }
433
434
435 /*********************************************************************
436  *      _ultoa   (NTDLL.@)
437  *
438  * Convert an unsigned long integer to a string.
439  *
440  * RETURNS
441  *  str.
442  *
443  * NOTES
444  *  - Converts value to a Nul terminated string which is copied to str.
445  *  - The maximum length of the copied str is 33 bytes.
446  *  - Does not check if radix is in the range of 2 to 36.
447  *  - If str is NULL it crashes, as the native function does.
448  */
449 char * __cdecl _ultoa(
450     ULONG value,         /* [I] Value to be converted */
451     char *str,           /* [O] Destination for the converted value */
452     int radix)           /* [I] Number base for conversion */
453 {
454     char buffer[33];
455     char *pos;
456     int digit;
457
458     pos = &buffer[32];
459     *pos = '\0';
460
461     do {
462         digit = value % radix;
463         value = value / radix;
464         if (digit < 10) {
465             *--pos = '0' + digit;
466         } else {
467             *--pos = 'a' + digit - 10;
468         } /* if */
469     } while (value != 0L);
470
471     memcpy(str, pos, &buffer[32] - pos + 1);
472     return str;
473 }
474
475
476 /*********************************************************************
477  *      _ltoa   (NTDLL.@)
478  *
479  * Convert a long integer to a string.
480  *
481  * RETURNS
482  *  str.
483  *
484  * NOTES
485  *  - Converts value to a Nul terminated string which is copied to str.
486  *  - The maximum length of the copied str is 33 bytes. If radix
487  *  is 10 and value is negative, the value is converted with sign.
488  *  - Does not check if radix is in the range of 2 to 36.
489  *  - If str is NULL it crashes, as the native function does.
490  */
491 char * __cdecl _ltoa(
492     LONG value, /* [I] Value to be converted */
493     char *str,  /* [O] Destination for the converted value */
494     int radix)  /* [I] Number base for conversion */
495 {
496     ULONG val;
497     int negative;
498     char buffer[33];
499     char *pos;
500     int digit;
501
502     if (value < 0 && radix == 10) {
503         negative = 1;
504         val = -value;
505     } else {
506         negative = 0;
507         val = value;
508     } /* if */
509
510     pos = &buffer[32];
511     *pos = '\0';
512
513     do {
514         digit = val % radix;
515         val = val / radix;
516         if (digit < 10) {
517             *--pos = '0' + digit;
518         } else {
519             *--pos = 'a' + digit - 10;
520         } /* if */
521     } while (val != 0L);
522
523     if (negative) {
524         *--pos = '-';
525     } /* if */
526
527     memcpy(str, pos, &buffer[32] - pos + 1);
528     return str;
529 }
530
531
532 /*********************************************************************
533  *      _itoa    (NTDLL.@)
534  *
535  * Converts an integer to a string.
536  *
537  * RETURNS
538  *  str.
539  *
540  * NOTES
541  *  - Converts value to a '\0' terminated string which is copied to str.
542  *  - The maximum length of the copied str is 33 bytes. If radix
543  *  is 10 and value is negative, the value is converted with sign.
544  *  - Does not check if radix is in the range of 2 to 36.
545  *  - If str is NULL it crashes, as the native function does.
546  */
547 char * __cdecl _itoa(
548     int value, /* [I] Value to be converted */
549     char *str, /* [O] Destination for the converted value */
550     int radix) /* [I] Number base for conversion */
551 {
552     return _ltoa(value, str, radix);
553 }
554
555
556 /*********************************************************************
557  *      _ui64toa   (NTDLL.@)
558  *
559  * Converts a large unsigned integer to a string.
560  *
561  * RETURNS
562  *  str.
563  *
564  * NOTES
565  *  - Converts value to a '\0' terminated string which is copied to str.
566  *  - The maximum length of the copied str is 65 bytes.
567  *  - Does not check if radix is in the range of 2 to 36.
568  *  - If str is NULL it crashes, as the native function does.
569  */
570 char * __cdecl _ui64toa(
571     ULONGLONG value, /* [I] Value to be converted */
572     char *str,       /* [O] Destination for the converted value */
573     int radix)       /* [I] Number base for conversion */
574 {
575     char buffer[65];
576     char *pos;
577     int digit;
578
579     pos = &buffer[64];
580     *pos = '\0';
581
582     do {
583         digit = value % radix;
584         value = value / radix;
585         if (digit < 10) {
586             *--pos = '0' + digit;
587         } else {
588             *--pos = 'a' + digit - 10;
589         } /* if */
590     } while (value != 0L);
591
592     memcpy(str, pos, &buffer[64] - pos + 1);
593     return str;
594 }
595
596
597 /*********************************************************************
598  *      _i64toa   (NTDLL.@)
599  *
600  * Converts a large integer to a string.
601  *
602  * RETURNS
603  *  str.
604  *
605  * NOTES
606  *  - Converts value to a Nul terminated string which is copied to str.
607  *  - The maximum length of the copied str is 65 bytes. If radix
608  *  is 10 and value is negative, the value is converted with sign.
609  *  - Does not check if radix is in the range of 2 to 36.
610  *  - If str is NULL it crashes, as the native function does.
611  *
612  * DIFFERENCES
613  * - The native DLL converts negative values (for base 10) wrong:
614  *|                     -1 is converted to -18446744073709551615
615  *|                     -2 is converted to -18446744073709551614
616  *|   -9223372036854775807 is converted to  -9223372036854775809
617  *|   -9223372036854775808 is converted to  -9223372036854775808
618  *   The native msvcrt _i64toa function and our ntdll _i64toa function
619  *   do not have this bug.
620  */
621 char * __cdecl _i64toa(
622     LONGLONG value, /* [I] Value to be converted */
623     char *str,      /* [O] Destination for the converted value */
624     int radix)      /* [I] Number base for conversion */
625 {
626     ULONGLONG val;
627     int negative;
628     char buffer[65];
629     char *pos;
630     int digit;
631
632     if (value < 0 && radix == 10) {
633         negative = 1;
634         val = -value;
635     } else {
636         negative = 0;
637         val = value;
638     } /* if */
639
640     pos = &buffer[64];
641     *pos = '\0';
642
643     do {
644         digit = val % radix;
645         val = val / radix;
646         if (digit < 10) {
647             *--pos = '0' + digit;
648         } else {
649             *--pos = 'a' + digit - 10;
650         } /* if */
651     } while (val != 0L);
652
653     if (negative) {
654         *--pos = '-';
655     } /* if */
656
657     memcpy(str, pos, &buffer[64] - pos + 1);
658     return str;
659 }
660
661
662 /*********************************************************************
663  *      _atoi64   (NTDLL.@)
664  *
665  * Convert a string to a large integer.
666  *
667  * PARAMS
668  *  str [I] String to be converted
669  *
670  * RETURNS
671  *  Success: The integer value represented by str.
672  *  Failure: 0. Note that this cannot be distinguished from a successful
673  *           return, if the string contains "0".
674  *
675  * NOTES
676  *  - Accepts: {whitespace} [+|-] {digits}
677  *  - No check is made for value overflow, only the lower 64 bits are assigned.
678  *  - If str is NULL it crashes, as the native function does.
679  */
680 LONGLONG __cdecl _atoi64( const char *str )
681 {
682     ULONGLONG RunningTotal = 0;
683     char bMinus = 0;
684
685     while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
686         str++;
687     } /* while */
688
689     if (*str == '+') {
690         str++;
691     } else if (*str == '-') {
692         bMinus = 1;
693         str++;
694     } /* if */
695
696     while (*str >= '0' && *str <= '9') {
697         RunningTotal = RunningTotal * 10 + *str - '0';
698         str++;
699     } /* while */
700
701     return bMinus ? -RunningTotal : RunningTotal;
702 }
703
704
705 /*********************************************************************
706  *                  atoi   (NTDLL.@)
707  */
708 int __cdecl NTDLL_atoi( const char *nptr )
709 {
710     return _atoi64( nptr );
711 }
712
713
714 /*********************************************************************
715  *                  atol   (NTDLL.@)
716  */
717 LONG __cdecl NTDLL_atol( const char *nptr )
718 {
719     return _atoi64( nptr );
720 }
721
722
723 /*********************************************************************
724  *                  sscanf   (NTDLL.@)
725  */
726 int __cdecl NTDLL_sscanf( const char *str, const char *format, ... )
727 {
728     int ret;
729     va_list valist;
730     va_start( valist, format );
731     ret = vsscanf( str, format, valist );
732     va_end( valist );
733     return ret;
734 }
735
736
737 /*********************************************************************
738  *              _splitpath (NTDLL.@)
739  *
740  * Split a path into its component pieces.
741  *
742  * PARAMS
743  *  inpath [I] Path to split
744  *  drv    [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
745  *  dir    [O] Destination for directory component. Should be at least MAX_PATH characters.
746  *  fname  [O] Destination for File name component. Should be at least MAX_PATH characters.
747  *  ext    [O] Destination for file extension component. Should be at least MAX_PATH characters.
748  *
749  * RETURNS
750  *  Nothing.
751  */
752 void __cdecl _splitpath(const char* inpath, char * drv, char * dir,
753                         char* fname, char * ext )
754 {
755     const char *p, *end;
756
757     if (inpath[0] && inpath[1] == ':')
758     {
759         if (drv)
760         {
761             drv[0] = inpath[0];
762             drv[1] = inpath[1];
763             drv[2] = 0;
764         }
765         inpath += 2;
766     }
767     else if (drv) drv[0] = 0;
768
769     /* look for end of directory part */
770     end = NULL;
771     for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
772
773     if (end)  /* got a directory */
774     {
775         if (dir)
776         {
777             memcpy( dir, inpath, end - inpath );
778             dir[end - inpath] = 0;
779         }
780         inpath = end;
781     }
782     else if (dir) dir[0] = 0;
783
784     /* look for extension: what's after the last dot */
785     end = NULL;
786     for (p = inpath; *p; p++) if (*p == '.') end = p;
787
788     if (!end) end = p; /* there's no extension */
789
790     if (fname)
791     {
792         memcpy( fname, inpath, end - inpath );
793         fname[end - inpath] = 0;
794     }
795     if (ext) strcpy( ext, end );
796 }