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

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

strncpy call changes + language api updates/fixes

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