source: trunk/src/helpers/nls.c@ 265

Last change on this file since 265 was 257, checked in by umoeller, 22 years ago

Fixes that have piled up in the last three months.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 26.3 KB
Line 
1
2/*
3 *@@sourcefile nls.c:
4 * contains a few helpers for National Language Support (NLS),
5 * such as printing strings with the format specified by
6 * the "Country" object.
7 *
8 * Usage: All OS/2 programs.
9 *
10 * Function prefixes (new with V0.81):
11 * -- nls* NLS helpers
12 *
13 * This file is new with 0.9.16, but contains functions
14 * formerly in stringh.c.
15 *
16 * Note: Version numbering in this file relates to XWorkplace version
17 * numbering.
18 *
19 *@@header "helpers\nls.h"
20 *@@added V0.9.16 (2001-10-11) [umoeller]
21 */
22
23/*
24 * Copyright (C) 1997-2002 Ulrich M”ller.
25 * This file is part of the "XWorkplace helpers" source package.
26 * This is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published
28 * by the Free Software Foundation, in version 2 as it comes in the
29 * "COPYING" file of the XWorkplace main distribution.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 */
35
36#define OS2EMX_PLAIN_CHAR
37 // this is needed for "os2emx.h"; if this is defined,
38 // emx will define PSZ as _signed_ char, otherwise
39 // as unsigned char
40
41#define INCL_DOSNLS
42#define INCL_DOSDATETIME
43#define INCL_DOSERRORS
44#define INCL_WINSHELLDATA
45#include <os2.h>
46
47#include <stdlib.h>
48#include <stdio.h>
49#include <string.h>
50#include <math.h>
51
52// XWP's setup.h replaces strchr and the like, and
53// we want the originals in here
54#define DONT_REPLACE_FOR_DBCS
55#include "setup.h" // code generation and debugging options
56
57#include "helpers\nls.h"
58#include "helpers\prfh.h"
59#include "helpers\standards.h"
60
61#pragma hdrstop
62
63/*
64 *@@category: Helpers\National Language Support
65 * See nls.c.
66 */
67
68/* ******************************************************************
69 *
70 * DBCS support
71 *
72 ********************************************************************/
73
74#define MAX_LEADBYTE 256
75
76#pragma pack(1)
77
78typedef struct _DBCSVECTOR
79{
80 BYTE bLow;
81 BYTE bHigh;
82} DBCSVECTOR;
83
84#pragma pack()
85
86BOOL G_afLeadByte[MAX_LEADBYTE] = {0};
87ULONG G_fDBCS = 2; // not queried yet
88COUNTRYCODE G_cc = { 0, 0 };
89DBCSVECTOR G_aDBCSVector[8];
90
91/*
92 *@@ nlsQueryCodepage:
93 * returns the current process codepage as a ULONG.
94 *
95 *@@added V1.0.2 (2003-02-07) [umoeller]
96 */
97
98ULONG nlsQueryCodepage(VOID)
99{
100 ULONG acp[8];
101 ULONG cb = 0;
102 if (DosQueryCp(sizeof(acp),
103 acp,
104 &cb))
105 return 437; // I think this is still the system default
106
107 return acp[0];
108}
109
110/*
111 *@@ nlsDBCS:
112 * returns TRUE if the system is currently using DBCS.
113 *
114 *@@added V0.9.19 (2002-06-13) [umoeller]
115 *@@changed V0.9.20 (2002-07-03) [umoeller]: fixed, this never worked
116 */
117
118BOOL nlsDBCS(VOID)
119{
120 APIRET arc;
121
122 if (G_fDBCS != 2)
123 // already queried:
124 return G_fDBCS;
125
126 // V0.9.20 (2002-07-03) [umoeller]
127 // assume a non-DBCS system UNLESS the below
128 // loop gives us something meaningful; even
129 // on non-DBCS systems like mine, DosQueryDBCSEnv
130 // does not return an error
131 G_fDBCS = FALSE;
132
133 if (!(arc = DosQueryDBCSEnv(8 * sizeof(DBCSVECTOR),
134 &G_cc,
135 (PCHAR)G_aDBCSVector)))
136 {
137 int i;
138 for (i = 0;
139 i < 8;
140 ++i)
141 {
142 if ( (G_aDBCSVector[i].bLow)
143 && (G_aDBCSVector[i].bHigh)
144 )
145 {
146 int n;
147 for (n = G_aDBCSVector[i].bLow;
148 n <= G_aDBCSVector[i].bHigh;
149 ++n)
150 G_afLeadByte[n] = TRUE;
151
152 G_fDBCS = TRUE;
153 }
154 else
155 break;
156 }
157 }
158
159 return G_fDBCS;
160}
161
162/*
163 *@@ nlsQueryDBCSChar:
164 * returns the type of the DBCS character with
165 * the given index. Note that the index is the
166 * DBCS character index, not just the array
167 * index into the CHAR array.
168 *
169 * Returns:
170 *
171 * -- TYPE_SBCS: ulOfs is single byte.
172 *
173 * -- TYPE_DBCS_1ST: ulOfs is a double-byte lead char.
174 *
175 * -- TYPE_DBCS_2ND: ulOfs is a double-byte trail char.
176 *
177 * Preconditions:
178 *
179 * -- nlsDBCS must have been called to initialize our
180 * globals, and must have returned TRUE.
181 *
182 *@@added V0.9.19 (2002-06-13) [umoeller]
183 */
184
185ULONG nlsQueryDBCSChar(PCSZ pcszString,
186 ULONG ulOfs)
187
188{
189 ULONG ulDBCSType = TYPE_SBCS;
190 ULONG i;
191
192 for (i = 0;
193 i <= ulOfs;
194 ++i)
195 {
196 switch (ulDBCSType)
197 {
198 case TYPE_SBCS:
199 case TYPE_DBCS_2ND:
200 ulDBCSType = G_afLeadByte[pcszString[i]];
201 break;
202
203 case TYPE_DBCS_1ST :
204 ulDBCSType = TYPE_DBCS_2ND;
205 break;
206 }
207 }
208
209 return ulDBCSType;
210}
211
212/*
213 *@@ nlschr:
214 * replacement for strchr with DBCS support.
215 *
216 * If the system is not running with DBCS,
217 * this calls plain strchr automatically.
218 *
219 *@@added V0.9.19 (2002-06-13) [umoeller]
220 *@@changed V0.9.20 (2002-07-22) [umoeller]: optimized
221 *@@changed V0.9.20 (2002-07-22) [lafaix]: optimized
222 */
223
224PSZ nlschr(PCSZ p, char c)
225{
226 PCSZ p2;
227 ULONG ulDBCSType = TYPE_SBCS;
228
229 if (!nlsDBCS())
230 // not DBCS:
231 return strchr(p, c);
232
233 // we're on DBCS:
234
235 // we can't find c if it is a leading byte
236 if (G_afLeadByte[c] != TYPE_SBCS)
237 return NULL;
238
239 for (p2 = p;
240 *p2;
241 ++p2)
242 {
243 // check _previous_ DBCS type and refresh
244 // DBCS type accordingly
245 switch (ulDBCSType)
246 {
247 case TYPE_SBCS:
248 case TYPE_DBCS_2ND:
249 ulDBCSType = G_afLeadByte[*p2];
250 // we can safely do the test here (and skip rechecking
251 // the type) because c can't possibly be a leading byte
252 // V0.9.20 (2002-07-22) [lafaix]
253 if (*p2 == c)
254 return (PSZ)p2;
255 break;
256
257 case TYPE_DBCS_1ST :
258 ulDBCSType = TYPE_DBCS_2ND;
259 break;
260 }
261 }
262
263 /* old code V0.9.20 (2002-07-22) [umoeller]
264 // we're on DBCS:
265 for (p2 = p;
266 *p2;
267 ++p2)
268 {
269 if (*p2 == c)
270 {
271 // match: return this only if it's SBCS;
272 // if it's a DBCS lead char, skip it
273 switch (ulDBCS = nlsQueryDBCSChar(p, p2 - p))
274 {
275 case TYPE_SBCS:
276 return (PSZ)p2;
277
278 case TYPE_DBCS_1ST:
279 ++p2;
280 }
281 }
282 }
283 */
284
285 return NULL;
286}
287
288/*
289 *@@ nlsrchr:
290 * replacement for strrchr with DBCS support.
291 *
292 * If the system is not running with DBCS,
293 * this calls plain strrchr automatically.
294 *
295 *@@added V0.9.19 (2002-06-13) [umoeller]
296 *@@changed V0.9.20 (2002-07-22) [lafaix]: optimized
297 */
298
299PSZ nlsrchr(PCSZ p, char c)
300{
301 PCSZ p2,
302 pLast = NULL;
303 ULONG ulDBCSType = TYPE_SBCS;
304
305 if (!nlsDBCS())
306 // not DBCS:
307 return strrchr(p, c);
308
309 // we're on DBCS:
310
311 // we can't find c if it is a leading byte
312 if (G_afLeadByte[c] != TYPE_SBCS)
313 return NULL;
314
315 for (p2 = p;
316 *p2;
317 ++p2)
318 {
319 // check _previous_ DBCS type and refresh
320 // DBCS type accordingly
321 switch (ulDBCSType)
322 {
323 case TYPE_SBCS:
324 case TYPE_DBCS_2ND:
325 ulDBCSType = G_afLeadByte[*p2];
326 if (*p2 == c)
327 pLast = p2;
328 break;
329
330 case TYPE_DBCS_1ST :
331 ulDBCSType = TYPE_DBCS_2ND;
332 break;
333 }
334 }
335
336 return (PSZ)pLast;
337
338 // old code V0.9.20 (2002-07-22) [lafaix]
339 /*
340 ulLength = strlen(p);
341 for (p2 = p + ulLength - 1;
342 p2 >= p;
343 --p2)
344 {
345 if (*p2 == c)
346 {
347 // match: return this only if it's SBCS;
348 // if it's a DBCS trail char, skip it
349 switch (ulDBCS = nlsQueryDBCSChar(p, p2 - p))
350 {
351 case TYPE_SBCS:
352 return (PSZ)p2;
353
354 case TYPE_DBCS_2ND:
355 --p2;
356 }
357 }
358 }
359
360 return NULL;
361 */
362}
363
364/* ******************************************************************
365 *
366 * Country-dependent formatting
367 *
368 ********************************************************************/
369
370/*
371 *@@ nlsGetAMPM:
372 *
373 *@@added V1.0.1 (2003-01-17) [umoeller]
374 */
375
376VOID nlsGetAMPM(PCOUNTRYAMPM pampm)
377{
378 PrfQueryProfileString(HINI_USER,
379 "PM_National",
380 "s2359", // key
381 "PM", // default
382 pampm->sz2359,
383 sizeof(pampm->sz2359));
384
385 PrfQueryProfileString(HINI_USER,
386 "PM_National",
387 "s1159", // key
388 "AM", // default
389 pampm->sz1159,
390 sizeof(pampm->sz1159));
391}
392
393/*
394 *@@ nlsQueryCountrySettings:
395 * this returns the most frequently used country settings
396 * all at once into a COUNTRYSETTINGS structure (prfh.h).
397 * This data corresponds to the user settings in the
398 * WPS "Country" object (which writes the data in "PM_National"
399 * in OS2.INI).
400 *
401 * In case a key cannot be found, the following (English)
402 * default values are set:
403 * -- ulDateFormat = 0 (English date format, mm.dd.yyyy);
404 * -- ulTimeFormat = 0 (12-hour clock);
405 * -- cDateSep = '/' (date separator);
406 * -- cTimeSep = ':' (time separator);
407 * -- cDecimal = '.' (decimal separator).
408 * -- cThousands = ',' (thousands separator).
409 *
410 *@@added V0.9.0 [umoeller]
411 *@@changed V0.9.7 (2000-12-02) [umoeller]: added cDecimal
412 */
413
414VOID nlsQueryCountrySettings(PCOUNTRYSETTINGS2 pcs2)
415{
416 if (pcs2)
417 {
418 PCOUNTRYSETTINGS pcs = &pcs2->cs;
419 pcs->ulDateFormat = PrfQueryProfileInt(HINI_USER,
420 (PSZ)PMINIAPP_NATIONAL,
421 "iDate",
422 0);
423 pcs->ulTimeFormat = PrfQueryProfileInt(HINI_USER,
424 (PSZ)PMINIAPP_NATIONAL,
425 "iTime",
426 0);
427 pcs->cDateSep = prfhQueryProfileChar(HINI_USER,
428 (PSZ)PMINIAPP_NATIONAL,
429 "sDate",
430 '/');
431 pcs->cTimeSep = prfhQueryProfileChar(HINI_USER,
432 (PSZ)PMINIAPP_NATIONAL,
433 "sTime",
434 ':');
435 pcs->cDecimal = prfhQueryProfileChar(HINI_USER,
436 (PSZ)PMINIAPP_NATIONAL,
437 "sDecimal",
438 '.');
439 pcs->cThousands = prfhQueryProfileChar(HINI_USER,
440 (PSZ)PMINIAPP_NATIONAL,
441 "sThousand",
442 ',');
443
444 nlsGetAMPM(&pcs2->ampm);
445 }
446}
447
448/*
449 *@@ nlsThousandsULong:
450 * converts a ULONG into a decimal string, while
451 * inserting thousands separators into it. Specify
452 * the separator character in cThousands.
453 *
454 * Returns pszTarget so you can use it directly
455 * with sprintf and the "%s" flag.
456 *
457 * For cThousands, you should use the data in
458 * OS2.INI ("PM_National" application), which is
459 * always set according to the "Country" object.
460 * You can use nlsQueryCountrySettings to
461 * retrieve this setting.
462 *
463 * Use nlsThousandsDouble for "double" values.
464 *
465 *@@changed V0.9.20 (2002-07-03) [umoeller]: optimized
466 */
467
468PSZ nlsThousandsULong(PSZ pszTarget, // out: decimal as string
469 ULONG ul, // in: decimal to convert
470 CHAR cThousands) // in: separator char (e.g. '.')
471{
472 CHAR szTemp[30];
473 USHORT ust = 0,
474 uss,
475 usLen = sprintf(szTemp, "%lu", ul); // V0.9.20 (2002-07-03) [umoeller]
476
477 for (uss = 0;
478 uss < usLen;
479 ++uss)
480 {
481 if (uss)
482 if (0 == ((usLen - uss) % 3))
483 {
484 pszTarget[ust] = cThousands;
485 ust++;
486 }
487
488 pszTarget[ust++] = szTemp[uss];
489 }
490
491 pszTarget[ust] = '\0';
492
493 return pszTarget;
494}
495
496/*
497 * strhThousandsULong:
498 * wrapper around nlsThousandsULong for those
499 * who used the XFLDR.DLL export.
500 *
501 *added V0.9.16 (2001-10-11) [umoeller]
502 */
503
504PSZ APIENTRY strhThousandsULong(PSZ pszTarget, // out: decimal as string
505 ULONG ul, // in: decimal to convert
506 CHAR cThousands) // in: separator char (e.g. '.')
507{
508 return nlsThousandsULong(pszTarget, ul, cThousands);
509}
510
511/*
512 *@@ nlsThousandsDouble:
513 * like nlsThousandsULong, but for a "double"
514 * value. Note that after-comma values are truncated.
515 *
516 *@@changed V0.9.20 (2002-07-03) [umoeller]: optimized
517 */
518
519PSZ nlsThousandsDouble(PSZ pszTarget,
520 double dbl,
521 CHAR cThousands)
522{
523 USHORT ust, uss, usLen;
524 CHAR szTemp[40];
525 usLen = sprintf(szTemp, "%.0f", floor(dbl)); // V0.9.20 (2002-07-03) [umoeller]
526
527 ust = 0;
528 for (uss = 0; uss < usLen; uss++)
529 {
530 if (uss)
531 if (((usLen - uss) % 3) == 0)
532 {
533 pszTarget[ust] = cThousands;
534 ust++;
535 }
536 pszTarget[ust] = szTemp[uss];
537 ust++;
538 }
539 pszTarget[ust] = '\0';
540
541 return pszTarget;
542}
543
544/*
545 *@@ nlsVariableDouble:
546 * like nlsThousandsULong, but for a "double" value, and
547 * with a variable number of decimal places depending on the
548 * size of the quantity.
549 *
550 *@@added V0.9.6 (2000-11-12) [pr]
551 *@@changed V0.9.20 (2002-07-03) [umoeller]: now using PCSZ pcszUnits
552 */
553
554PSZ nlsVariableDouble(PSZ pszTarget,
555 double dbl,
556 PCSZ pcszUnits,
557 CHAR cThousands)
558{
559 if (dbl < 100.0)
560 sprintf(pszTarget, "%.2f%s", dbl, pcszUnits);
561 else
562 if (dbl < 1000.0)
563 sprintf(pszTarget, "%.1f%s", dbl, pcszUnits);
564 else
565 strcat(nlsThousandsDouble(pszTarget, dbl, cThousands),
566 pcszUnits);
567
568 return pszTarget;
569}
570
571/*
572 *@@ nlsFileDate:
573 * converts file date data to a string (to pszBuf).
574 * You can pass any FDATE structure to this function,
575 * which are returned in those FILEFINDBUF* or
576 * FILESTATUS* structs by the Dos* functions.
577 *
578 * ulDateFormat is the PM setting for the date format,
579 * as set in the "Country" object, and can be queried using
580 + PrfQueryProfileInt(HINI_USER, "PM_National", "iDate", 0);
581 *
582 * meaning:
583 * -- 0 mm.dd.yyyy (English)
584 * -- 1 dd.mm.yyyy (e.g. German)
585 * -- 2 yyyy.mm.dd (Japanese, ISO)
586 * -- 3 yyyy.dd.mm
587 *
588 * cDateSep is used as a date separator (e.g. '.').
589 * This can be queried using:
590 + prfhQueryProfileChar(HINI_USER, "PM_National", "sDate", '/');
591 *
592 * Alternatively, you can query all the country settings
593 * at once using nlsQueryCountrySettings (prfh.c).
594 *
595 *@@changed V0.9.0 (99-11-07) [umoeller]: now calling nlsDateTime
596 *@@changed V1.0.1 (2003-01-17) [umoeller]: prototype changed for optimization, this was not exported
597 */
598
599VOID nlsFileDate(PSZ pszBuf, // out: string returned
600 const FDATE *pfDate, // in: date information
601 const COUNTRYSETTINGS2 *pcs)
602{
603 nlsDate(pcs,
604 pszBuf,
605 pfDate->year + 1980,
606 pfDate->month,
607 pfDate->day);
608}
609
610/*
611 *@@ nlsFileTime:
612 * converts file time data to a string (to pszBuf).
613 * You can pass any FTIME structure to this function,
614 * which are returned in those FILEFINDBUF* or
615 * FILESTATUS* structs by the Dos* functions.
616 *
617 * ulTimeFormat is the PM setting for the time format,
618 * as set in the "Country" object, and can be queried using
619 + PrfQueryProfileInt(HINI_USER, "PM_National", "iTime", 0);
620 * meaning:
621 * -- 0 12-hour clock
622 * -- >0 24-hour clock
623 *
624 * cDateSep is used as a time separator (e.g. ':').
625 * This can be queried using:
626 + prfhQueryProfileChar(HINI_USER, "PM_National", "sTime", ':');
627 *
628 * Alternatively, you can query all the country settings
629 * at once using nlsQueryCountrySettings (prfh.c).
630 *
631 *@@changed V0.8.5 (99-03-15) [umoeller]: fixed 12-hour crash
632 *@@changed V0.9.0 (99-11-07) [umoeller]: now calling nlsDateTime
633 *@@changed V1.0.1 (2003-01-17) [umoeller]: prototype changed for optimization, this was not exported
634 */
635
636VOID nlsFileTime(PSZ pszBuf, // out: string returned
637 const FTIME *pfTime, // in: time information
638 const COUNTRYSETTINGS2 *pcs)
639{
640 nlsTime(pcs,
641 pszBuf,
642 pfTime->hours,
643 pfTime->minutes,
644 pfTime->twosecs * 2);
645}
646
647/*
648 *@@ nlsDate:
649 *
650 *@@added V1.0.1 (2003-01-17) [umoeller]
651 */
652
653VOID nlsDate(const COUNTRYSETTINGS2 *pcs2,
654 PSZ pszDate, // out: date string returned
655 USHORT year,
656 BYTE month,
657 BYTE day)
658{
659 switch (pcs2->cs.ulDateFormat)
660 {
661 case 0: // mm.dd.yyyy (English)
662 sprintf(pszDate, "%02d%c%02d%c%04d",
663 month,
664 pcs2->cs.cDateSep,
665 day,
666 pcs2->cs.cDateSep,
667 year);
668 break;
669
670 case 1: // dd.mm.yyyy (e.g. German)
671 sprintf(pszDate, "%02d%c%02d%c%04d",
672 day,
673 pcs2->cs.cDateSep,
674 month,
675 pcs2->cs.cDateSep,
676 year);
677 break;
678
679 case 2: // yyyy.mm.dd (ISO and Japanese)
680 sprintf(pszDate, "%04d%c%02d%c%02d",
681 year,
682 pcs2->cs.cDateSep,
683 month,
684 pcs2->cs.cDateSep,
685 day);
686 break;
687
688 default: // yyyy.dd.mm
689 sprintf(pszDate, "%04d%c%02d%c%02d",
690 year,
691 pcs2->cs.cDateSep,
692 day,
693 pcs2->cs.cDateSep,
694 month);
695 break;
696 }
697}
698
699/*
700 *@@ nlsTime:
701 *
702 *@@added V1.0.1 (2003-01-17) [umoeller]
703 */
704
705VOID nlsTime(const COUNTRYSETTINGS2 *pcs2,
706 PSZ pszTime, // out: time string returned
707 BYTE hours,
708 BYTE minutes,
709 BYTE seconds)
710{
711 if (!pcs2->cs.ulTimeFormat)
712 {
713 // for 12-hour clock, we need additional INI data
714 if (hours >= 12) // V0.9.16 (2001-12-05) [pr] if (hours > 12)
715 {
716 // yeah cool Paul, now we get 00:20 PM if it's 20 past noon
717 // V0.9.18 (2002-02-13) [umoeller]
718 ULONG ulHours;
719 if (!(ulHours = hours % 12))
720 ulHours = 12;
721
722 // >= 12h: PM.
723 sprintf(pszTime, "%02d%c%02d%c%02d %s",
724 // leave 12 == 12 (not 0)
725 ulHours,
726 pcs2->cs.cTimeSep,
727 minutes,
728 pcs2->cs.cTimeSep,
729 seconds,
730 pcs2->ampm.sz2359);
731 }
732 else
733 {
734 // < 12h: AM
735 sprintf(pszTime, "%02d%c%02d%c%02d %s",
736 hours,
737 pcs2->cs.cTimeSep,
738 minutes,
739 pcs2->cs.cTimeSep,
740 seconds,
741 pcs2->ampm.sz1159);
742 }
743 }
744 else
745 // 24-hour clock
746 sprintf(pszTime, "%02d%c%02d%c%02d",
747 hours,
748 pcs2->cs.cTimeSep,
749 minutes,
750 pcs2->cs.cTimeSep,
751 seconds);
752}
753
754/*
755 *@@ nlsDateTime:
756 * converts Control Program DATETIME info
757 * into two strings. See nlsFileDate and nlsFileTime
758 * for more detailed parameter descriptions.
759 *
760 * Use of this function is deprecated. Use the
761 * speedier nlsDateTime2 instead.
762 *
763 *@@added V0.9.0 (99-11-07) [umoeller]
764 *@@changed V0.9.16 (2001-12-05) [pr]: fixed AM/PM hour bug
765 *@@changed V0.9.18 (2002-02-13) [umoeller]: fixed AM/PM hour bug fix
766 *@@changed V1.0.1 (2003-01-17) [umoeller]: extracted nlsDate, nlsTime
767 */
768
769VOID nlsDateTime(PSZ pszDate, // out: date string returned (can be NULL)
770 PSZ pszTime, // out: time string returned (can be NULL)
771 const DATETIME *pDateTime, // in: date/time information
772 ULONG ulDateFormat, // in: date format (0-3); see nlsFileDate
773 CHAR cDateSep, // in: date separator (e.g. '.')
774 ULONG ulTimeFormat, // in: 24-hour time format (0 or 1); see nlsFileTime
775 CHAR cTimeSep) // in: time separator (e.g. ':')
776{
777 COUNTRYSETTINGS2 cs2;
778 if (pszDate)
779 {
780 cs2.cs.ulDateFormat = ulDateFormat;
781 cs2.cs.cDateSep = cDateSep;
782 nlsDate(&cs2,
783 pszDate, // out: date string returned
784 pDateTime->year,
785 pDateTime->month,
786 pDateTime->day);
787 }
788
789 if (pszTime)
790 {
791 cs2.cs.ulTimeFormat = ulTimeFormat;
792 cs2.cs.cTimeSep = cTimeSep;
793 nlsGetAMPM(&cs2.ampm);
794 nlsTime(&cs2,
795 pszTime,
796 pDateTime->hours,
797 pDateTime->minutes,
798 pDateTime->seconds);
799 }
800}
801
802/*
803 * strhDateTime:
804 * wrapper around nlsDateTime for those who used
805 * the XFLDR.DLL export.
806 */
807
808VOID APIENTRY strhDateTime(PSZ pszDate, // out: date string returned (can be NULL)
809 PSZ pszTime, // out: time string returned (can be NULL)
810 DATETIME *pDateTime, // in: date/time information
811 ULONG ulDateFormat, // in: date format (0-3); see nlsFileDate
812 CHAR cDateSep, // in: date separator (e.g. '.')
813 ULONG ulTimeFormat, // in: 24-hour time format (0 or 1); see nlsFileTime
814 CHAR cTimeSep) // in: time separator (e.g. ':')
815{
816 nlsDateTime(pszDate,
817 pszTime,
818 pDateTime,
819 ulDateFormat,
820 cDateSep,
821 ulTimeFormat,
822 cTimeSep);
823}
824
825/*
826 *@@ nlsDateTime2:
827 * speedier version of nlsDateTime that caches
828 * all information and needs _no_ Prf* call
829 * any more.
830 *
831 *@@added V1.0.1 (2003-01-17) [umoeller]
832 */
833
834VOID nlsDateTime2(PSZ pszDate,
835 PSZ pszTime,
836 const DATETIME *pDateTime,
837 const COUNTRYSETTINGS2 *pcs2)
838{
839 if (pszDate)
840 nlsDate(pcs2,
841 pszDate,
842 pDateTime->year,
843 pDateTime->month,
844 pDateTime->day);
845
846 if (pszTime)
847 nlsTime(pcs2,
848 pszTime,
849 pDateTime->hours,
850 pDateTime->minutes,
851 pDateTime->seconds);
852}
853
854CHAR G_szUpperMap[257];
855BOOL G_fUpperMapInited = FALSE;
856
857/*
858 *@@ InitUpperMap:
859 * initializes the case map for nlsUpper.
860 *
861 *@@added V0.9.20 (2002-07-25) [umoeller]
862 */
863
864STATIC VOID InitUpperMap(VOID)
865{
866 ULONG ul;
867 COUNTRYCODE cc;
868 BOOL fDBCS = nlsDBCS();
869
870 for (ul = 0;
871 ul < 256;
872 ++ul)
873 {
874 G_szUpperMap[ul] = (CHAR)ul;
875
876 if ( (fDBCS)
877 && (G_afLeadByte[ul] != TYPE_SBCS)
878 )
879 G_szUpperMap[ul] = ' ';
880 }
881
882 G_szUpperMap[256] = '\0';
883
884 cc.country = 0; // use system country code
885 cc.codepage = 0; // use process default codepage
886 DosMapCase(255,
887 &cc,
888 G_szUpperMap + 1);
889
890 G_fUpperMapInited = TRUE;
891}
892
893/*
894 *@@ nlsUpper:
895 * quick hack for upper-casing a string.
896 *
897 * This now returns the length of the given string always
898 * (V0.9.20).
899 *
900 * Remarks:
901 *
902 * -- On the first call, we build a case map table by
903 * calling DosMapCase with the default system country
904 * code and the process's codepage. Since DosMapCase
905 * is terribly slow with all the 16-bit thunking
906 * involved, we can then use our table without having
907 * to use the API ever again.
908 *
909 * -- As a result, if the process codepage changes for
910 * any reason, this function will not pick up the
911 * change.
912 *
913 * -- This has provisions for DBCS, which hopefully
914 * work.
915 *
916 *@@added V0.9.16 (2001-10-25) [umoeller]
917 *@@changed V0.9.20 (2002-07-25) [umoeller]: speedup, changed prototype
918 */
919
920ULONG nlsUpper(PSZ psz) // in/out: string
921{
922 ULONG ul = 0;
923 PSZ p;
924
925 if (!G_fUpperMapInited)
926 InitUpperMap();
927
928 if (p = psz)
929 {
930 while (*p++ = G_szUpperMap[*p])
931 ++ul;
932 }
933
934 return ul;
935}
936
937
Note: See TracBrowser for help on using the repository browser.