source: trunk/src/kernel32/heapstring.cpp@ 3815

Last change on this file since 3815 was 3815, checked in by sandervl, 25 years ago

check if module contains resources before searching for a resource object

File size: 37.4 KB
Line 
1/* $Id: heapstring.cpp,v 1.30 2000-07-10 18:38:51 sandervl Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 *
6 * Win32 compatibility string functions for OS/2
7 *
8 * NOTE: lstrcpyn* always appends a terminating 0 (unlike strncpy)!
9 *
10 * Copyright 1999 Patrick Haller
11 */
12
13/*****************************************************************************
14 * Includes *
15 *****************************************************************************/
16
17#include <odin.h>
18#include <odinwrap.h>
19#include <os2sel.h>
20
21#include <os2win.h>
22#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25#include <winnls.h>
26#include <unicode.h>
27#include <ctype.h>
28#include <wcstr.h>
29#include "heap.h"
30#include <heapstring.h>
31#include "misc.h"
32#include "codepage.h"
33
34#define DBG_LOCALLOG DBG_heapstring
35#include "dbglocal.h"
36
37/*****************************************************************************
38 * Defines *
39 *****************************************************************************/
40
41ODINDEBUGCHANNEL(KERNEL32-HEAPSTRING)
42
43/*****************************************************************************
44 * Name :
45 * Purpose :
46 * Parameters:
47 * Variables :
48 * Result :
49 * Remark :
50 * Status :
51 *
52 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
53 *****************************************************************************/
54
55int WIN32API lstrlenA(LPCSTR arg1)
56{
57 dprintf2(("KERNEL32: lstrlenA(%s)\n",
58 arg1));
59
60 return O32_lstrlen(arg1);
61}
62
63
64/*****************************************************************************
65 * Name :
66 * Purpose :
67 * Parameters:
68 * Variables :
69 * Result :
70 * Remark :
71 * Status :
72 *
73 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
74 *****************************************************************************/
75
76int WIN32API lstrlenW(LPCWSTR arg1)
77{
78 int rc;
79
80 rc = UniStrlen( (UniChar*)arg1);
81 dprintf2(("KERNEL32: lstrlenW(%08xh) returns %d\n",
82 arg1,
83 rc));
84 return rc;
85}
86
87
88/*****************************************************************************
89 * Name :
90 * Purpose :
91 * Parameters:
92 * Variables :
93 * Result :
94 * Remark :
95 * Status :
96 *
97 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
98 *****************************************************************************/
99
100LPSTR WIN32API lstrcatA(LPSTR arg1, LPCSTR arg2)
101{
102 dprintf2(("KERNEL32: lstrcat(%s,%s)\n",
103 arg1,
104 arg2));
105
106 if(arg2 == NULL)
107 return arg1;
108 strcat(arg1, arg2);
109 return arg1;
110}
111
112
113/*****************************************************************************
114 * Name :
115 * Purpose :
116 * Parameters:
117 * Variables :
118 * Result :
119 * Remark :
120 * Status :
121 *
122 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
123 *****************************************************************************/
124
125LPWSTR WIN32API lstrcatW(LPWSTR arg1, LPCWSTR arg2)
126{
127 dprintf2(("KERNEL32: OS2lstrcatW(%08xh,%08xh)\n",
128 arg1,
129 arg2));
130
131 if(arg2 == NULL)
132 return arg1;
133
134 UniStrcat( (UniChar*) arg1, (UniChar*) arg2 );
135 return arg1;
136}
137
138
139/*****************************************************************************
140 * Name :
141 * Purpose :
142 * Parameters:
143 * Variables :
144 * Result :
145 * Remark :
146 * Status :
147 *
148 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
149 *****************************************************************************/
150
151int WIN32API lstrcmpA(LPCSTR arg1, LPCSTR arg2)
152{
153 dprintf2(("KERNEL32: OS2lstrcmpA(%s,%s)\n",
154 arg1,
155 arg2));
156
157 if(arg1 == NULL)
158 return -1;
159 if(arg2 == NULL)
160 return 1;
161
162 return O32_lstrcmp(arg1, arg2);
163}
164
165
166/*****************************************************************************
167 * Name :
168 * Purpose :
169 * Parameters:
170 * Variables :
171 * Result :
172 * Remark :
173 * Status :
174 *
175 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
176 *****************************************************************************/
177
178int WIN32API lstrncmpA(LPCSTR arg1, LPCSTR arg2, int l)
179{
180 dprintf2(("KERNEL32: OS2lstrncmpA(%s,%s,%d)\n",
181 arg1,
182 arg2,
183 l));
184
185 return strncmp(arg1, arg2, l);
186}
187
188/*****************************************************************************
189 * Name : lstrncmpiA
190 * Purpose :
191 * Parameters:
192 * Variables :
193 * Result :
194 * Remark :
195 * Status :
196 *
197 * Author : Przemyslaw Dobrowolski
198 *****************************************************************************/
199INT WINAPI lstrncmpiA( LPCSTR str1, LPCSTR str2, INT n )
200{
201 INT firstch,lastch;
202 INT result = 0;
203
204 if (n)
205 {
206 do
207 {
208 firstch = tolower(*str1);
209 lastch = tolower(*str2);
210 str1++;
211 str2++;
212 } while (--n && str1 && str2 && firstch == lastch);
213
214 result = firstch - lastch;
215 }
216
217 return(result);
218}
219//TODO: Don't know if this is completely correct
220int WIN32API lstrncmpiW(LPCWSTR str1, LPCWSTR str2, int n)
221{
222 INT firstch,lastch;
223 INT result = 0;
224
225 if (n)
226 {
227 do
228 {
229 firstch = tolower((char)*str1);
230 lastch = tolower((char)*str2);
231 str1++;
232 str2++;
233 } while (--n && str1 && str2 && firstch == lastch);
234
235 result = firstch - lastch;
236 }
237
238 return(result);
239}
240
241/*****************************************************************************
242 * Name :
243 * Purpose :
244 * Parameters:
245 * Variables :
246 * Result :
247 * Remark :
248 * Status :
249 *
250 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
251 *****************************************************************************/
252
253int WIN32API lstrcmpW(LPCWSTR arg1, LPCWSTR arg2)
254{
255 dprintf2(("KERNEL32: lstrcmpW (%08xh, %08xh)\n",
256 arg1,
257 arg2));
258
259 if(arg1 == NULL)
260 return -1;
261 if(arg2 == NULL)
262 return 1;
263
264 return wcscmp( (wchar_t*)arg1,
265 (wchar_t*)arg2 );
266}
267
268
269/*****************************************************************************
270 * Name :
271 * Purpose :
272 * Parameters:
273 * Variables :
274 * Result :
275 * Remark :
276 * Status :
277 *
278 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
279 *****************************************************************************/
280
281int WIN32API lstrncmpW(LPCWSTR arg1, LPCWSTR arg2, int l)
282{
283 dprintf2(("KERNEL32: OS2lstrncmpW(%08xh,%08xh,%d)\n",
284 arg1,
285 arg2,
286 l));
287
288 return wcsncmp((wchar_t*)arg1,
289 (wchar_t*)arg2,
290 l);
291}
292
293/*****************************************************************************
294 * Name :
295 * Purpose :
296 * Parameters:
297 * Variables :
298 * Result :
299 * Remark :
300 * Status :
301 *
302 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
303 *****************************************************************************/
304
305LPSTR WIN32API lstrcpyA(LPSTR dest, LPCSTR src)
306{
307 if ( (src == NULL) || (dest == NULL) ) // stupid parameter checking
308 return NULL;
309
310 return O32_lstrcpy(dest, src);
311}
312
313
314/*****************************************************************************
315 * Name :
316 * Purpose :
317 * Parameters:
318 * Variables :
319 * Result :
320 * Remark :
321 * Status :
322 *
323 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
324 *****************************************************************************/
325
326LPWSTR WIN32API lstrcpyW(LPWSTR dest, LPCWSTR src)
327{
328 if ( (src == NULL) || (dest == NULL) ) // stupid parameter checking
329 return NULL;
330
331 UniStrcpy( (UniChar*)dest,
332 (UniChar*)src );
333 return dest;
334}
335
336
337/*****************************************************************************
338 * Name :
339 * Purpose :
340 * Parameters:
341 * Variables :
342 * Result :
343 * Remark :
344 * Status :
345 *
346 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
347 *****************************************************************************/
348
349LPSTR WIN32API lstrcpynA(LPSTR arg1, LPCSTR arg2, int arg3)
350{
351 register LPSTR p1 = arg1;
352 register LPSTR p2 = (LPSTR)arg2;
353
354 dprintf2(("KERNEL32: OS2lstrcpyA(%08xh, %08xh, %08xh)\n",
355 arg1,
356 arg2,
357 arg3));
358
359 //PH: looks like either \0 or arg3 terminate the copy
360 //return strncpy(arg1, arg2, arg3);
361 arg3--; // pre-decrement to avoid exceeding buffer length
362 // results in better code than (arg1 > 1)
363
364 for (;*p2 && arg3; arg3--)
365 *p1++ = *p2++;
366
367 *p1 = 0; //CB: copy arg-1, set end 0
368
369 return arg1;
370}
371
372
373/*****************************************************************************
374 * Name :
375 * Purpose :
376 * Parameters:
377 * Variables :
378 * Result :
379 * Remark :
380 * Status :
381 *
382 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
383 *****************************************************************************/
384
385LPWSTR WIN32API lstrcpynW(LPWSTR dest, LPCWSTR src, int arg3)
386{
387 dprintf2(("KERNEL32: lstrcpynW(%08xh,%08xh,%08xh)",
388 dest,
389 src,
390 arg3));
391
392 if (arg3 == 0)
393 return NULL;
394
395 UniStrncpy( (UniChar*)dest,
396 (UniChar*)src,
397 arg3-1); //CB: copy arg3-1 characters
398 dest[arg3-1] = 0; //CB: set end
399 return dest;
400}
401
402
403/*****************************************************************************
404 * Name :
405 * Purpose :
406 * Parameters:
407 * Variables :
408 * Result :
409 * Remark :
410 * Status :
411 *
412 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
413 *****************************************************************************/
414
415int WIN32API lstrcmpiA(LPCSTR arg1, LPCSTR arg2)
416{
417 dprintf2(("KERNEL32: lstrcmpiA(%s,%s)\n",
418 arg1,
419 arg2));
420
421 if(arg1 == NULL)
422 return -1;
423
424 if(arg2 == NULL)
425 return 1;
426
427 return O32_lstrcmpi(arg1, arg2);
428}
429
430
431/*****************************************************************************
432 * Name :
433 * Purpose :
434 * Parameters:
435 * Variables :
436 * Result :
437 * Remark :
438 * Status :
439 *
440 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
441 *****************************************************************************/
442
443int WIN32API lstrcmpiW(LPCWSTR arg1, LPCWSTR arg2)
444{
445 char *astr1, *astr2;
446 int rc;
447
448 dprintf2(("KERNEL32: lstrcmpiW(%08xh,%08xh)\n",
449 arg1,
450 arg2));
451
452 if(arg1 == NULL)
453 return -1;
454
455 if(arg2 == NULL)
456 return 1;
457
458 // NOTE: This function has no equivalent in uunidef.h
459 astr1 = UnicodeToAsciiString((LPWSTR)arg1);
460 astr2 = UnicodeToAsciiString((LPWSTR)arg2);
461 rc = lstrcmpiA(astr1, astr2);
462 FreeAsciiString(astr2);
463 FreeAsciiString(astr1);
464 return(rc);
465}
466
467
468/*****************************************************************************
469 * Name :
470 * Purpose :
471 * Parameters:
472 * Variables :
473 * Result :
474 * Remark :
475 * Status :
476 *
477 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
478 *****************************************************************************/
479
480// unilen: length of astring buffer (including 0 terminator)
481// returns string length
482
483int WIN32API lstrcpynCtoA(LPSTR astring,
484 LPCWSTR ustring,
485 int unilen,
486 UconvObject uconv_object)
487{
488 int i;
489 int rc;
490 size_t uni_chars_left;
491 size_t out_bytes_left;
492 size_t num_subs;
493 UniChar* in_buf;
494 char* out_buf;
495
496 if (ustring == NULL)
497 {
498 if (astring != NULL && unilen > 0)
499 astring[0] = 0;
500 return 0;
501 }
502
503 if (astring == NULL || unilen <= 0)
504 return 0;
505
506 if (uconv_object)
507 {
508 if (unilen == 1)
509 {
510 astring[0] = 0;
511 return 0; //no data
512 }
513
514 //SvL: Determine length of unicode string
515 uni_chars_left = UniStrlen((UniChar*)ustring)+1;
516 uni_chars_left = min(uni_chars_left, unilen);
517 unilen = uni_chars_left;
518
519 out_bytes_left = uni_chars_left; //size in bytes == elements
520 in_buf = (UniChar*)ustring;
521 out_buf = astring;
522 rc = UniUconvFromUcs(uconv_object,
523 &in_buf, &uni_chars_left,
524 (void**)&out_buf, &out_bytes_left,
525 &num_subs);
526
527 unilen -= 1+out_bytes_left; //end + left bytes
528 astring[unilen] = 0; //terminate
529
530 return unilen; //length of string (excluding terminator)
531 }
532 else
533 {
534 /* idiots unicode conversion :) */
535 for (i = 0; i < unilen-1; i++)
536 {
537 astring[i] = (ustring[i] > 255) ? (char)20 : (char)ustring[i]; //CB: handle invalid characters as space
538 if (ustring[i] == 0) return i; //asta la vista, baby
539 }
540
541 astring[unilen-1] = 0; // @@@PH: 1999/06/09 fix - always terminate string
542
543 return(unilen-1);
544 }
545}
546
547int WIN32API lstrcpynWtoA(LPSTR astring,
548 LPCWSTR ustring,
549 int unilen)
550{
551 return lstrcpynCtoA(astring, ustring, unilen, GetWindowsUconvObject());
552}
553
554
555/*****************************************************************************
556 * Name :
557 * Purpose :
558 * Parameters:
559 * Variables :
560 * Result :
561 * Remark :
562 * Status :
563 *
564 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
565 *****************************************************************************/
566
567// asciilen: max length of unicode buffer (including end 0)
568// @@@PH 0 termination is NOT necessarily included !
569int lstrcpynAtoC(LPWSTR unicode,
570 LPCSTR ascii,
571 int asciilen,
572 UconvObject uconv_object)
573{
574 int rc;
575 int i;
576 size_t uni_chars_left;
577 size_t in_bytes_left;
578 size_t num_subs;
579 UniChar* out_buf;
580 char* in_buf;
581
582 dprintf2(("KERNEL32: HeapString: lstrcpynAtoW(%s,%08xh,%d)\n",
583 ascii,
584 unicode,
585 asciilen));
586
587 //CB: no input, set at least terminator
588 if (ascii == NULL)
589 {
590 if (unicode != NULL && asciilen > 0) unicode[0] = 0;
591 return 0;
592 }
593
594 if (unicode == NULL || asciilen <= 0)
595 return 0; //nothing to do
596
597 if (uconv_object)
598 {
599 //@@@PH what's this?
600 if ((asciilen == 1) && (*ascii == '\0') )
601 {
602 unicode[0] = 0;
603 return 0;
604 }
605
606 in_buf = (LPSTR)ascii;
607
608 //@@@PH what's this?
609 //in_bytes_left = asciilen-1; //buffer size in bytes
610
611 //SvL: Determine length of ascii string
612 in_bytes_left = strlen(in_buf)+1;
613 in_bytes_left = asciilen = min(in_bytes_left, asciilen); //buffer size in bytes
614
615 out_buf = (UniChar*)unicode;
616
617 uni_chars_left = in_bytes_left; //elements
618
619 rc = UniUconvToUcs( uconv_object,
620 (void**)&in_buf, &in_bytes_left,
621 &out_buf, &uni_chars_left,
622 &num_subs );
623
624 asciilen -= 1+uni_chars_left; //end + left bytes
625
626 unicode[asciilen] = 0; // always terminate string
627 return asciilen; //length of string (excluding terminator)
628 }
629 else
630 { //poor man's conversion
631
632// for(i = 0;i < asciilen-1;i++)
633 for(i = 0;i < asciilen;i++)
634 {
635 unicode[i] = ascii[i];
636 if (ascii[i] == 0)
637 //return i-1; //work done
638 return i; //work done
639 }
640
641// unicode[asciilen-1] = 0;
642// return asciilen-1;
643 return asciilen;
644 }
645}
646
647int WIN32API lstrcpynAtoW(LPWSTR unicode,
648 LPCSTR ascii,
649 int asciilen)
650{
651 return lstrcpynAtoC(unicode, ascii, asciilen, GetWindowsUconvObject());
652}
653
654/*****************************************************************************
655 * Name :
656 * Purpose : Converts unicode string to ascii string
657 * Parameters:
658 * Variables :
659 * Result : returns length of ascii string
660 * Remark :
661 * Status :
662 *
663 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
664 *****************************************************************************/
665
666LPSTR WIN32API lstrcpyWtoA(LPSTR ascii, LPCWSTR unicode)
667{
668 //@@@PH huh? wuz dat?
669 if (unicode == NULL)
670 {
671 if (unicode != NULL) ((LPWSTR)unicode)[0] = 0; //CB: set at least end
672 return NULL;
673 }
674
675 if (unicode == NULL)
676 return NULL; /* garbage in, garbage out ! */
677
678 /* forward to function with len parameter */
679 lstrcpynWtoA(ascii,
680 unicode,
681 UniStrlen((UniChar*)unicode)+1); //end included
682
683 return ascii;
684}
685
686
687/*****************************************************************************
688 * Name :
689 * Purpose : Copies the full string from ascii to unicode
690 * Parameters:
691 * Variables :
692 * Result :
693 * Remark :
694 * Status :
695 *
696 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
697 *****************************************************************************/
698
699LPWSTR WIN32API lstrcpyAtoW(LPWSTR unicode, LPCSTR ascii)
700{
701 /* achimha for security, strlen might trap if garbage in */
702 /* @@@PH 98/06/07 */
703 if (ascii == NULL)
704 {
705 if (unicode != NULL) unicode[0] = 0; //CB: set at least end
706 return NULL;
707 }
708
709 if (unicode == NULL)
710 return NULL; /* garbage in, garbage out ! */
711
712 /* forward to call with length parameter */
713 lstrcpynAtoW(unicode, ascii, strlen(ascii)+1); //end included
714 return (unicode);
715}
716
717
718
719
720/*****************************************************************************
721 * Name :
722 * Purpose :
723 * Parameters:
724 * Variables :
725 * Result :
726 * Remark :
727 * Status :
728 *
729 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
730 *****************************************************************************/
731
732LPVOID WIN32API HEAP_xalloc( HANDLE heap, DWORD flags, DWORD size )
733{
734 LPVOID p = HeapAlloc( heap, flags, size );
735 if (!p)
736 {
737 dprintf2(("KERNEL32: HEAP_xalloc(%08xh,%08xh,%08xh) out of memory.\n",
738 heap,
739 flags,
740 size));
741 }
742 return p;
743}
744
745
746/*****************************************************************************
747 * Name :
748 * Purpose :
749 * Parameters:
750 * Variables :
751 * Result :
752 * Remark :
753 * Status :
754 *
755 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
756 *****************************************************************************/
757
758LPVOID WIN32API HEAP_xrealloc( HANDLE heap, DWORD flags, LPVOID lpMem, DWORD size )
759{
760 LPVOID p = HeapReAlloc( heap, flags, lpMem, size );
761 if (!p)
762 {
763 dprintf2(("KERNEL32: HEAP_xrealloc(%08xh,%08xh,%08xh,%08xh) out of memory.\n",
764 heap,
765 flags,
766 lpMem,
767 size));
768 }
769 return p;
770}
771
772
773/*****************************************************************************
774 * Name :
775 * Purpose :
776 * Parameters:
777 * Variables :
778 * Result :
779 * Remark :
780 * Status :
781 *
782 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
783 *****************************************************************************/
784
785LPVOID WIN32API HEAP_malloc(DWORD size )
786{
787 LPVOID p = HeapAlloc( GetProcessHeap(), 0, size );
788 if (!p)
789 {
790 dprintf2(("KERNEL32: HEAP_malloc(%08xh) out of memory.\n",
791 size));
792 }
793 return p;
794}
795
796
797/*****************************************************************************
798 * Name :
799 * Purpose :
800 * Parameters:
801 * Variables :
802 * Result :
803 * Remark :
804 * Status :
805 *
806 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
807 *****************************************************************************/
808
809LPVOID WIN32API HEAP_realloc(LPVOID lpMem, DWORD size )
810{
811 LPVOID p = HeapReAlloc( GetProcessHeap(), 0, lpMem, size );
812 if (!p)
813 {
814 dprintf2(("KERNEL32: HEAP_realloc(%08xh,%08xh) out of memory.\n",
815 lpMem,
816 size));
817 }
818 return p;
819}
820
821
822/*****************************************************************************
823 * Name :
824 * Purpose :
825 * Parameters:
826 * Variables :
827 * Result :
828 * Remark :
829 * Status :
830 *
831 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
832 *****************************************************************************/
833
834VOID WIN32API HEAP_free(LPVOID lpMem)
835{
836 dprintf2(("KERNEL32: HEAP_free(%08xh)\n",
837 lpMem));
838
839 HeapFree( GetProcessHeap(), 0, lpMem);
840}
841
842
843/*****************************************************************************
844 * Name :
845 * Purpose :
846 * Parameters:
847 * Variables :
848 * Result :
849 * Remark :
850 * Status :
851 *
852 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
853 *****************************************************************************/
854
855LPSTR WIN32API HEAP_strdupA( HANDLE heap, DWORD flags, LPCSTR str )
856{
857 LPSTR p = (LPSTR)HEAP_xalloc( heap, flags, strlen(str) + 1 );
858 strcpy( p, str );
859 return p;
860}
861
862
863/*****************************************************************************
864 * Name :
865 * Purpose :
866 * Parameters:
867 * Variables :
868 * Result :
869 * Remark :
870 * Status :
871 *
872 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
873 *****************************************************************************/
874
875LPWSTR WIN32API HEAP_strdupW( HANDLE heap, DWORD flags, LPCWSTR str )
876{
877 INT len = lstrlenW(str) + 1;
878 LPWSTR p = (LPWSTR)HEAP_xalloc( heap, flags, len * sizeof(WCHAR) );
879 lstrcpyW( p, str );
880 return p;
881}
882
883
884/*****************************************************************************
885 * Name :
886 * Purpose :
887 * Parameters:
888 * Variables :
889 * Result :
890 * Remark :
891 * Status :
892 *
893 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
894 *****************************************************************************/
895
896LPWSTR WIN32API HEAP_strdupAtoW( HANDLE heap, DWORD flags, LPCSTR str )
897{
898 LPWSTR ret;
899
900 if (!str) return NULL;
901 ret = (LPWSTR)HEAP_xalloc( heap, flags, (strlen(str)+1) * sizeof(WCHAR) );
902 lstrcpyAtoW( ret, (LPSTR)str );
903 return ret;
904}
905
906
907/*****************************************************************************
908 * Name :
909 * Purpose :
910 * Parameters:
911 * Variables :
912 * Result :
913 * Remark :
914 * Status :
915 *
916 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
917 *****************************************************************************/
918
919LPSTR WIN32API HEAP_strdupWtoA( HANDLE heap, DWORD flags, LPCWSTR str )
920{
921 LPSTR ret;
922
923 if (!str) return NULL;
924 ret = (LPSTR)HEAP_xalloc( heap, flags, lstrlenW(str) + 1 );
925 lstrcpyWtoA( ret, (LPWSTR)str );
926 return ret;
927}
928
929
930/*****************************************************************************
931 * Name : WideCharToLocal
932 * Purpose : similar lstrcpyWtoA, should handle codepages properly
933 * Parameters:
934 * Variables :
935 * Result : strlen of the destination string
936 * Remark :
937 * Status :
938 *
939 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
940 *****************************************************************************/
941
942INT WIN32API WideCharToLocal(LPSTR pLocal, LPWSTR pWide, INT dwChars)
943{
944 dprintf2(("KERNEL32: WideCharToLocal(%08xh,%08xh,%08xh)\n",
945 pLocal,
946 pWide,
947 dwChars));
948
949 *pLocal = 0;
950 WideCharToMultiByte(CP_ACP,
951 0,
952 pWide,
953 -1,
954 pLocal,
955 dwChars,
956 NULL,
957 NULL);
958
959 return strlen(pLocal);
960}
961
962
963/*****************************************************************************
964 * Name : LocalToWideChar
965 * Purpose : similar lstrcpyAtoW, should handle codepages properly
966 * Parameters:
967 * Variables :
968 * Result : strlen of the destination string
969 * Remark :
970 * Status :
971 *
972 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
973 *****************************************************************************/
974
975INT WIN32API LocalToWideChar(LPWSTR pWide, LPSTR pLocal, INT dwChars)
976{
977 *pWide = 0;
978
979 dprintf2(("KERNEL32: LocalToWideChar(%08xh,%08xh,%08xh)\n",
980 pLocal,
981 pWide,
982 dwChars));
983
984 MultiByteToWideChar(CP_ACP,
985 0,
986 pLocal,
987 -1,
988 pWide,
989 dwChars);
990
991 return lstrlenW(pWide);
992}
993
994
995
996
997
998
999#if 0
1000
1001
1002/*****************************************************************************
1003 * Name :
1004 * Purpose :
1005 * Parameters:
1006 * Variables :
1007 * Result :
1008 * Remark :
1009 * Status :
1010 *
1011 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
1012 *****************************************************************************/
1013
1014// Converts unicode string to ascii string
1015// returns pointer to ascii string
1016char * WIN32API UnicodeToAsciiString(WCHAR *ustring)
1017{
1018 char *astring;
1019
1020 if(ustring == NULL) return(NULL);
1021
1022 astring = (char *)malloc( 1 + UniStrlen((UniChar*)ustring) );
1023 UnicodeToAscii( ustring, astring );
1024 return(astring);
1025}
1026
1027
1028/*****************************************************************************
1029 * Name :
1030 * Purpose :
1031 * Parameters:
1032 * Variables :
1033 * Result :
1034 * Remark :
1035 * Status :
1036 *
1037 * Author : Patrick Haller [Thu, 1999/08/05 20:46]
1038 *****************************************************************************/
1039
1040// Converts ascii string to unicode string
1041// returns pointer to unicode string
1042WCHAR * WIN32API AsciiToUnicodeString(char *astring)
1043{
1044 WCHAR *ustring;
1045
1046 if(astring == NULL)
1047 return(NULL);
1048
1049 ustring = (WCHAR *)malloc( 1 + strlen(astring) << 1 );
1050 AsciiToUnicode( astring, ustring );
1051 return(ustring);
1052}
1053
1054#endif
1055
1056
1057
1058/**************************************************************************
1059 * This function is used just locally !
1060 * Description: Inverts a string.
1061 */
1062static void OLE_InvertString(char* string)
1063{
1064 char sTmpArray[128];
1065 INT counter, i = 0;
1066
1067 for (counter = strlen(string); counter > 0; counter--)
1068 {
1069 memcpy(sTmpArray + i, string + counter-1, 1);
1070 i++;
1071 }
1072 memcpy(sTmpArray + i, "\0", 1);
1073 strcpy(string, sTmpArray);
1074}
1075
1076/***************************************************************************************
1077 * This function is used just locally !
1078 * Description: Test if the given string (psNumber) is valid or not.
1079 * The valid characters are the following:
1080 * - Characters '0' through '9'.
1081 * - One decimal point (dot) if the number is a floating-point value.
1082 * - A minus sign in the first character position if the number is
1083 * a negative value.
1084 * If the function succeeds, psBefore/psAfter will point to the string
1085 * on the right/left of the decimal symbol. pbNegative indicates if the
1086 * number is negative.
1087 */
1088static INT OLE_GetNumberComponents(char* pInput, char* psBefore, char* psAfter, BOOL* pbNegative)
1089{
1090char sNumberSet[] = "0123456789";
1091BOOL bInDecimal = FALSE;
1092
1093 /* Test if we do have a minus sign */
1094 if ( *pInput == '-' )
1095 {
1096 *pbNegative = TRUE;
1097 pInput++; /* Jump to the next character. */
1098 }
1099
1100 while(*pInput != '\0')
1101 {
1102 /* Do we have a valid numeric character */
1103 if ( strchr(sNumberSet, *pInput) != NULL )
1104 {
1105 if (bInDecimal == TRUE)
1106 *psAfter++ = *pInput;
1107 else
1108 *psBefore++ = *pInput;
1109 }
1110 else
1111 {
1112 /* Is this a decimal point (dot) */
1113 if ( *pInput == '.' )
1114 {
1115 /* Is it the first time we find it */
1116 if ((bInDecimal == FALSE))
1117 bInDecimal = TRUE;
1118 else
1119 return -1; /* ERROR: Invalid parameter */
1120 }
1121 else
1122 {
1123 /* It's neither a numeric character, nor a decimal point.
1124 * Thus, return an error.
1125 */
1126 return -1;
1127 }
1128 }
1129 pInput++;
1130 }
1131
1132 /* Add an End of Line character to the output buffers */
1133 *psBefore = '\0';
1134 *psAfter = '\0';
1135
1136 return 0;
1137}
1138
1139/**************************************************************************
1140 * This function is used just locally !
1141 * Description: A number could be formatted using different numbers
1142 * of "digits in group" (example: 4;3;2;0).
1143 * The first parameter of this function is an array
1144 * containing the rule to be used. It's format is the following:
1145 * |NDG|DG1|DG2|...|0|
1146 * where NDG is the number of used "digits in group" and DG1, DG2,
1147 * are the corresponding "digits in group".
1148 * Thus, this function returns the grouping value in the array
1149 * pointed by the second parameter.
1150 */
1151static INT OLE_GetGrouping(char* sRule, INT index)
1152{
1153 char sData[2], sRuleSize[2];
1154 INT nData, nRuleSize;
1155
1156 memcpy(sRuleSize, sRule, 1);
1157 memcpy(sRuleSize+1, "\0", 1);
1158 nRuleSize = atoi(sRuleSize);
1159
1160 if (index > 0 && index < nRuleSize)
1161 {
1162 memcpy(sData, sRule+index, 1);
1163 memcpy(sData+1, "\0", 1);
1164 nData = atoi(sData);
1165 }
1166
1167 else
1168 {
1169 memcpy(sData, sRule+nRuleSize-1, 1);
1170 memcpy(sData+1, "\0", 1);
1171 nData = atoi(sData);
1172 }
1173
1174 return nData;
1175}
1176
1177
1178/*****************************************************************************
1179 * Name : GetNumberFormat
1180 * Purpose : format a given number string according to local settings
1181 * Parameters:
1182 * Variables :
1183 * Result :
1184 * Remark : KERNEL32.355
1185 * Status :
1186 *
1187 * Author : Patrick Haller [Sun, 2000/06/12 12:46]
1188 *****************************************************************************/
1189
1190
1191ODINFUNCTION6(INT, GetNumberFormatA,
1192 LCID, locale,
1193 DWORD, dwflags,
1194 LPCSTR, lpvalue,
1195 CONST NUMBERFMTA *,lpFormat,
1196 LPSTR, lpNumberStr,
1197 int, cchNumber)
1198{
1199 dprintf(("not properly implemented.\n"));
1200
1201 char sNumberDigits[3], sDecimalSymbol[5], sDigitsInGroup[11], sDigitGroupSymbol[5], sILZero[2];
1202 INT nNumberDigits, nNumberDecimal, i, j, nCounter, nStep, nRuleIndex, nGrouping, nDigits, retVal, nLZ;
1203 char sNumber[128], sDestination[128], sDigitsAfterDecimal[10], sDigitsBeforeDecimal[128];
1204 char sRule[10], sSemiColumn[]=";", sBuffer[5], sNegNumber[2];
1205 char *pStr = NULL, *pTmpStr = NULL;
1206 LCID systemDefaultLCID;
1207 BOOL bNegative = FALSE;
1208 enum Operations
1209 {
1210 USE_PARAMETER,
1211 USE_LOCALEINFO,
1212 USE_SYSTEMDEFAULT,
1213 RETURN_ERROR
1214 } used_operation;
1215
1216 strncpy(sNumber, lpvalue, 128);
1217 sNumber[127] = '\0';
1218
1219 /* Make sure we have a valid input string, get the number
1220 * of digits before and after the decimal symbol, and check
1221 * if this is a negative number.
1222 */
1223 if ( OLE_GetNumberComponents(sNumber, sDigitsBeforeDecimal, sDigitsAfterDecimal, &bNegative) != -1)
1224 {
1225 nNumberDecimal = strlen(sDigitsBeforeDecimal);
1226 nDigits = strlen(sDigitsAfterDecimal);
1227 }
1228 else
1229 {
1230 SetLastError(ERROR_INVALID_PARAMETER);
1231 return 0;
1232 }
1233
1234 /* Which source will we use to format the string */
1235 used_operation = RETURN_ERROR;
1236 if (lpFormat != NULL)
1237 {
1238 if (dwflags == 0)
1239 used_operation = USE_PARAMETER;
1240 }
1241 else
1242 {
1243 if (dwflags & LOCALE_NOUSEROVERRIDE)
1244 used_operation = USE_LOCALEINFO;
1245 else
1246 used_operation = USE_SYSTEMDEFAULT;
1247 }
1248
1249 /* Load the fields we need */
1250 switch(used_operation)
1251 {
1252 case USE_LOCALEINFO:
1253 GetLocaleInfoA(locale, LOCALE_IDIGITS, sNumberDigits, sizeof(sNumberDigits));
1254 GetLocaleInfoA(locale, LOCALE_SDECIMAL, sDecimalSymbol, sizeof(sDecimalSymbol));
1255 GetLocaleInfoA(locale, LOCALE_SGROUPING, sDigitsInGroup, sizeof(sDigitsInGroup));
1256 GetLocaleInfoA(locale, LOCALE_STHOUSAND, sDigitGroupSymbol, sizeof(sDigitGroupSymbol));
1257 GetLocaleInfoA(locale, LOCALE_ILZERO, sILZero, sizeof(sILZero));
1258 GetLocaleInfoA(locale, LOCALE_INEGNUMBER, sNegNumber, sizeof(sNegNumber));
1259 break;
1260 case USE_PARAMETER:
1261 sprintf(sNumberDigits, "%d",lpFormat->NumDigits);
1262 strcpy(sDecimalSymbol, lpFormat->lpDecimalSep);
1263 sprintf(sDigitsInGroup, "%d;0",lpFormat->Grouping);
1264 strcpy(sDigitGroupSymbol, lpFormat->lpThousandSep);
1265 sprintf(sILZero, "%d",lpFormat->LeadingZero);
1266 sprintf(sNegNumber, "%d",lpFormat->NegativeOrder);
1267 break;
1268 case USE_SYSTEMDEFAULT:
1269 systemDefaultLCID = GetSystemDefaultLCID();
1270 GetLocaleInfoA(systemDefaultLCID, LOCALE_IDIGITS, sNumberDigits, sizeof(sNumberDigits));
1271 GetLocaleInfoA(systemDefaultLCID, LOCALE_SDECIMAL, sDecimalSymbol, sizeof(sDecimalSymbol));
1272 GetLocaleInfoA(systemDefaultLCID, LOCALE_SGROUPING, sDigitsInGroup, sizeof(sDigitsInGroup));
1273 GetLocaleInfoA(systemDefaultLCID, LOCALE_STHOUSAND, sDigitGroupSymbol, sizeof(sDigitGroupSymbol));
1274 GetLocaleInfoA(systemDefaultLCID, LOCALE_ILZERO, sILZero, sizeof(sILZero));
1275 GetLocaleInfoA(systemDefaultLCID, LOCALE_INEGNUMBER, sNegNumber, sizeof(sNegNumber));
1276 break;
1277 default:
1278 SetLastError(ERROR_INVALID_PARAMETER);
1279 return 0;
1280 }
1281
1282 nNumberDigits = atoi(sNumberDigits);
1283
1284 /* Remove the ";" */
1285 i=0;
1286 j = 1;
1287 for (nCounter=0; nCounter<strlen(sDigitsInGroup); nCounter++)
1288 {
1289 if ( memcmp(sDigitsInGroup + nCounter, sSemiColumn, 1) != 0 )
1290 {
1291 memcpy(sRule + j, sDigitsInGroup + nCounter, 1);
1292 i++;
1293 j++;
1294 }
1295 }
1296 sprintf(sBuffer, "%d", i);
1297 memcpy(sRule, sBuffer, 1); /* Number of digits in the groups ( used by OLE_GetGrouping() ) */
1298 memcpy(sRule + j, "\0", 1);
1299
1300 /* First, format the digits before the decimal. */
1301 if ((nNumberDecimal>0) && (atoi(sDigitsBeforeDecimal) != 0))
1302 {
1303 /* Working on an inverted string is easier ! */
1304 OLE_InvertString(sDigitsBeforeDecimal);
1305
1306 nStep = nCounter = i = j = 0;
1307 nRuleIndex = 1;
1308 nGrouping = OLE_GetGrouping(sRule, nRuleIndex);
1309
1310 /* Here, we will loop until we reach the end of the string.
1311 * An internal counter (j) is used in order to know when to
1312 * insert the "digit group symbol".
1313 */
1314 while (nNumberDecimal > 0)
1315 {
1316 i = nCounter + nStep;
1317 memcpy(sDestination + i, sDigitsBeforeDecimal + nCounter, 1);
1318 nCounter++;
1319 j++;
1320 if (j >= nGrouping)
1321 {
1322 j = 0;
1323 if (nRuleIndex < sRule[0])
1324 nRuleIndex++;
1325 nGrouping = OLE_GetGrouping(sRule, nRuleIndex);
1326 memcpy(sDestination + i+1, sDigitGroupSymbol, strlen(sDigitGroupSymbol));
1327 nStep+= strlen(sDigitGroupSymbol);
1328 }
1329
1330 nNumberDecimal--;
1331 }
1332
1333 memcpy(sDestination + i+1, "\0", 1);
1334 /* Get the string in the right order ! */
1335 OLE_InvertString(sDestination);
1336 }
1337 else
1338 {
1339 nLZ = atoi(sILZero);
1340 if (nLZ != 0)
1341 {
1342 /* Use 0.xxx instead of .xxx */
1343 memcpy(sDestination, "0", 1);
1344 memcpy(sDestination+1, "\0", 1);
1345 }
1346 else
1347 memcpy(sDestination, "\0", 1);
1348
1349 }
1350
1351 /* Second, format the digits after the decimal. */
1352 j = 0;
1353 nCounter = nNumberDigits;
1354 if ( (nDigits>0) && (pStr = strstr (sNumber, ".")) )
1355 {
1356 i = strlen(sNumber) - strlen(pStr) + 1;
1357 strncpy ( sDigitsAfterDecimal, sNumber + i, nNumberDigits);
1358 j = strlen(sDigitsAfterDecimal);
1359 if (j < nNumberDigits)
1360 nCounter = nNumberDigits-j;
1361 }
1362 for (i=0;i<nCounter;i++)
1363 memcpy(sDigitsAfterDecimal+i+j, "0", 1);
1364 memcpy(sDigitsAfterDecimal + nNumberDigits, "\0", 1);
1365
1366 i = strlen(sDestination);
1367 j = strlen(sDigitsAfterDecimal);
1368 /* Finally, construct the resulting formatted string. */
1369
1370 for (nCounter=0; nCounter<i; nCounter++)
1371 memcpy(sNumber + nCounter, sDestination + nCounter, 1);
1372
1373 memcpy(sNumber + nCounter, sDecimalSymbol, strlen(sDecimalSymbol));
1374
1375 for (i=0; i<j; i++)
1376 memcpy(sNumber + nCounter+i+strlen(sDecimalSymbol), sDigitsAfterDecimal + i, 1);
1377 memcpy(sNumber + nCounter+i+strlen(sDecimalSymbol), "\0", 1);
1378
1379 /* Is it a negative number */
1380 if (bNegative == TRUE)
1381 {
1382 i = atoi(sNegNumber);
1383 pStr = sDestination;
1384 pTmpStr = sNumber;
1385 switch (i)
1386 {
1387 case 0:
1388 *pStr++ = '(';
1389 while (*sNumber != '\0')
1390 *pStr++ = *pTmpStr++;
1391 *pStr++ = ')';
1392 break;
1393 case 1:
1394 *pStr++ = '-';
1395 while (*pTmpStr != '\0')
1396 *pStr++ = *pTmpStr++;
1397 break;
1398 case 2:
1399 *pStr++ = '-';
1400 *pStr++ = ' ';
1401 while (*pTmpStr != '\0')
1402 *pStr++ = *pTmpStr++;
1403 break;
1404 case 3:
1405 while (*pTmpStr != '\0')
1406 *pStr++ = *pTmpStr++;
1407 *pStr++ = '-';
1408 break;
1409 case 4:
1410 while (*pTmpStr != '\0')
1411 *pStr++ = *pTmpStr++;
1412 *pStr++ = ' ';
1413 *pStr++ = '-';
1414 break;
1415 default:
1416 while (*pTmpStr != '\0')
1417 *pStr++ = *pTmpStr++;
1418 break;
1419 }
1420 }
1421 else
1422 strcpy(sDestination, sNumber);
1423
1424 /* If cchNumber is zero, then returns the number of bytes or characters
1425 * required to hold the formatted number string
1426 */
1427 if (cchNumber==0)
1428 retVal = strlen(sDestination) + 1;
1429 else
1430 {
1431 strncpy (lpNumberStr, sDestination, cchNumber);
1432 lpNumberStr[cchNumber-1] = '\0'; /* ensure we got a NULL at the end */
1433 retVal = strlen(lpNumberStr);
1434 }
1435
1436 return retVal;
1437}
1438
1439
1440
1441
1442/*****************************************************************************
1443 * Name : GetNumberFormat
1444 * Purpose : format a given number string according to local settings
1445 * Parameters:
1446 * Variables :
1447 * Result :
1448 * Remark :
1449 * Status :
1450 *
1451 * Author : Patrick Haller [Sun, 2000/06/12 12:46]
1452 *****************************************************************************/
1453
1454int WIN32API GetNumberFormatW(LCID Locale,
1455 DWORD dwFlags,
1456 LPCWSTR lpValue,
1457 CONST NUMBERFMTW *lpFormat,
1458 LPWSTR lpNumberStr,
1459 int cchNumber)
1460{
1461 dprintf(("GetNumberFormatW(%08x,%08x,%s,%08x,%s,%08x) not properly implemented.\n",
1462 Locale,
1463 dwFlags,
1464 lpValue,
1465 lpFormat,
1466 lpNumberStr,
1467 cchNumber));
1468
1469 // @@@PH cheap ass emulation
1470 lstrcpynW(lpNumberStr,
1471 lpValue,
1472 cchNumber);
1473
1474 return lstrlenW(lpNumberStr);
1475}
1476
Note: See TracBrowser for help on using the repository browser.