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

Last change on this file since 113 was 113, checked in by umoeller, 24 years ago

Misc updates.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 15.2 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-2001 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_WINSHELLDATA
42#include <os2.h>
43
44#include <stdlib.h>
45#include <stdio.h>
46#include <string.h>
47#include <math.h>
48
49#include "setup.h" // code generation and debugging options
50
51#include "helpers\prfh.h"
52#include "helpers\nls.h"
53
54#pragma hdrstop
55
56/*
57 *@@category: Helpers\C helpers\National Language Support
58 * See stringh.c and xstring.c.
59 */
60
61/*
62 *@@ nlsQueryCountrySettings:
63 * this returns the most frequently used country settings
64 * all at once into a COUNTRYSETTINGS structure (prfh.h).
65 * This data corresponds to the user settings in the
66 * WPS "Country" object (which writes the data in "PM_National"
67 * in OS2.INI).
68 *
69 * In case a key cannot be found, the following (English)
70 * default values are set:
71 * -- ulDateFormat = 0 (English date format, mm.dd.yyyy);
72 * -- ulTimeFormat = 0 (12-hour clock);
73 * -- cDateSep = '/' (date separator);
74 * -- cTimeSep = ':' (time separator);
75 * -- cDecimal = '.' (decimal separator).
76 * -- cThousands = ',' (thousands separator).
77 *
78 *@@added V0.9.0 [umoeller]
79 *@@changed V0.9.7 (2000-12-02) [umoeller]: added cDecimal
80 */
81
82VOID nlsQueryCountrySettings(PCOUNTRYSETTINGS pcs)
83{
84 if (pcs)
85 {
86 pcs->ulDateFormat = PrfQueryProfileInt(HINI_USER,
87 (PSZ)PMINIAPP_NATIONAL,
88 "iDate",
89 0);
90 pcs->ulTimeFormat = PrfQueryProfileInt(HINI_USER,
91 (PSZ)PMINIAPP_NATIONAL,
92 "iTime",
93 0);
94 pcs->cDateSep = prfhQueryProfileChar(HINI_USER,
95 (PSZ)PMINIAPP_NATIONAL,
96 "sDate",
97 '/');
98 pcs->cTimeSep = prfhQueryProfileChar(HINI_USER,
99 (PSZ)PMINIAPP_NATIONAL,
100 "sTime",
101 ':');
102 pcs->cDecimal = prfhQueryProfileChar(HINI_USER,
103 (PSZ)PMINIAPP_NATIONAL,
104 "sDecimal",
105 '.');
106 pcs->cThousands = prfhQueryProfileChar(HINI_USER,
107 (PSZ)PMINIAPP_NATIONAL,
108 "sThousand",
109 ',');
110 }
111}
112
113/*
114 *@@ nlsThousandsULong:
115 * converts a ULONG into a decimal string, while
116 * inserting thousands separators into it. Specify
117 * the separator character in cThousands.
118 *
119 * Returns pszTarget so you can use it directly
120 * with sprintf and the "%s" flag.
121 *
122 * For cThousands, you should use the data in
123 * OS2.INI ("PM_National" application), which is
124 * always set according to the "Country" object.
125 * You can use nlsQueryCountrySettings to
126 * retrieve this setting.
127 *
128 * Use nlsThousandsDouble for "double" values.
129 */
130
131PSZ nlsThousandsULong(PSZ pszTarget, // out: decimal as string
132 ULONG ul, // in: decimal to convert
133 CHAR cThousands) // in: separator char (e.g. '.')
134{
135 USHORT ust, uss, usc;
136 CHAR szTemp[40];
137 sprintf(szTemp, "%lu", ul);
138
139 ust = 0;
140 usc = strlen(szTemp);
141 for (uss = 0; uss < usc; uss++)
142 {
143 if (uss)
144 if (((usc - uss) % 3) == 0)
145 {
146 pszTarget[ust] = cThousands;
147 ust++;
148 }
149 pszTarget[ust] = szTemp[uss];
150 ust++;
151 }
152 pszTarget[ust] = '\0';
153
154 return (pszTarget);
155}
156
157/*
158 * strhThousandsULong:
159 * wrapper around nlsThousandsULong for those
160 * who used the XFLDR.DLL export.
161 *
162 *added V0.9.16 (2001-10-11) [umoeller]
163 */
164
165PSZ APIENTRY strhThousandsULong(PSZ pszTarget, // out: decimal as string
166 ULONG ul, // in: decimal to convert
167 CHAR cThousands) // in: separator char (e.g. '.')
168{
169 return (nlsThousandsULong(pszTarget, ul, cThousands));
170}
171
172/*
173 *@@ nlsThousandsDouble:
174 * like nlsThousandsULong, but for a "double"
175 * value. Note that after-comma values are truncated.
176 */
177
178PSZ nlsThousandsDouble(PSZ pszTarget,
179 double dbl,
180 CHAR cThousands)
181{
182 USHORT ust, uss, usc;
183 CHAR szTemp[40];
184 sprintf(szTemp, "%.0f", floor(dbl));
185
186 ust = 0;
187 usc = strlen(szTemp);
188 for (uss = 0; uss < usc; uss++)
189 {
190 if (uss)
191 if (((usc - uss) % 3) == 0)
192 {
193 pszTarget[ust] = cThousands;
194 ust++;
195 }
196 pszTarget[ust] = szTemp[uss];
197 ust++;
198 }
199 pszTarget[ust] = '\0';
200
201 return (pszTarget);
202}
203
204/*
205 *@@ nlsVariableDouble:
206 * like nlsThousandsULong, but for a "double" value, and
207 * with a variable number of decimal places depending on the
208 * size of the quantity.
209 *
210 *@@added V0.9.6 (2000-11-12) [pr]
211 */
212
213PSZ nlsVariableDouble(PSZ pszTarget,
214 double dbl,
215 PSZ pszUnits,
216 CHAR cThousands)
217{
218 if (dbl < 100.0)
219 sprintf(pszTarget, "%.2f%s", dbl, pszUnits);
220 else
221 if (dbl < 1000.0)
222 sprintf(pszTarget, "%.1f%s", dbl, pszUnits);
223 else
224 strcat(nlsThousandsDouble(pszTarget, dbl, cThousands),
225 pszUnits);
226
227 return(pszTarget);
228}
229
230/*
231 *@@ nlsFileDate:
232 * converts file date data to a string (to pszBuf).
233 * You can pass any FDATE structure to this function,
234 * which are returned in those FILEFINDBUF* or
235 * FILESTATUS* structs by the Dos* functions.
236 *
237 * ulDateFormat is the PM setting for the date format,
238 * as set in the "Country" object, and can be queried using
239 + PrfQueryProfileInt(HINI_USER, "PM_National", "iDate", 0);
240 *
241 * meaning:
242 * -- 0 mm.dd.yyyy (English)
243 * -- 1 dd.mm.yyyy (e.g. German)
244 * -- 2 yyyy.mm.dd (Japanese, ISO)
245 * -- 3 yyyy.dd.mm
246 *
247 * cDateSep is used as a date separator (e.g. '.').
248 * This can be queried using:
249 + prfhQueryProfileChar(HINI_USER, "PM_National", "sDate", '/');
250 *
251 * Alternatively, you can query all the country settings
252 * at once using nlsQueryCountrySettings (prfh.c).
253 *
254 *@@changed V0.9.0 (99-11-07) [umoeller]: now calling nlsDateTime
255 */
256
257VOID nlsFileDate(PSZ pszBuf, // out: string returned
258 FDATE *pfDate, // in: date information
259 ULONG ulDateFormat, // in: date format (0-3)
260 CHAR cDateSep) // in: date separator (e.g. '.')
261{
262 DATETIME dt;
263 dt.day = pfDate->day;
264 dt.month = pfDate->month;
265 dt.year = pfDate->year + 1980;
266
267 nlsDateTime(pszBuf,
268 NULL, // no time
269 &dt,
270 ulDateFormat,
271 cDateSep,
272 0, 0); // no time
273}
274
275/*
276 *@@ nlsFileTime:
277 * converts file time data to a string (to pszBuf).
278 * You can pass any FTIME structure to this function,
279 * which are returned in those FILEFINDBUF* or
280 * FILESTATUS* structs by the Dos* functions.
281 *
282 * ulTimeFormat is the PM setting for the time format,
283 * as set in the "Country" object, and can be queried using
284 + PrfQueryProfileInt(HINI_USER, "PM_National", "iTime", 0);
285 * meaning:
286 * -- 0 12-hour clock
287 * -- >0 24-hour clock
288 *
289 * cDateSep is used as a time separator (e.g. ':').
290 * This can be queried using:
291 + prfhQueryProfileChar(HINI_USER, "PM_National", "sTime", ':');
292 *
293 * Alternatively, you can query all the country settings
294 * at once using nlsQueryCountrySettings (prfh.c).
295 *
296 *@@changed V0.8.5 (99-03-15) [umoeller]: fixed 12-hour crash
297 *@@changed V0.9.0 (99-11-07) [umoeller]: now calling nlsDateTime
298 */
299
300VOID nlsFileTime(PSZ pszBuf, // out: string returned
301 FTIME *pfTime, // in: time information
302 ULONG ulTimeFormat, // in: 24-hour time format (0 or 1)
303 CHAR cTimeSep) // in: time separator (e.g. ':')
304{
305 DATETIME dt;
306 dt.hours = pfTime->hours;
307 dt.minutes = pfTime->minutes;
308 dt.seconds = pfTime->twosecs * 2;
309
310 nlsDateTime(NULL, // no date
311 pszBuf,
312 &dt,
313 0, 0, // no date
314 ulTimeFormat,
315 cTimeSep);
316}
317
318/*
319 *@@ nlsDateTime:
320 * converts Control Program DATETIME info
321 * into two strings. See nlsFileDate and nlsFileTime
322 * for more detailed parameter descriptions.
323 *
324 *@@added V0.9.0 (99-11-07) [umoeller]
325 */
326
327VOID nlsDateTime(PSZ pszDate, // out: date string returned (can be NULL)
328 PSZ pszTime, // out: time string returned (can be NULL)
329 DATETIME *pDateTime, // in: date/time information
330 ULONG ulDateFormat, // in: date format (0-3); see nlsFileDate
331 CHAR cDateSep, // in: date separator (e.g. '.')
332 ULONG ulTimeFormat, // in: 24-hour time format (0 or 1); see nlsFileTime
333 CHAR cTimeSep) // in: time separator (e.g. ':')
334{
335 if (pszDate)
336 {
337 switch (ulDateFormat)
338 {
339 case 0: // mm.dd.yyyy (English)
340 sprintf(pszDate, "%02d%c%02d%c%04d",
341 pDateTime->month,
342 cDateSep,
343 pDateTime->day,
344 cDateSep,
345 pDateTime->year);
346 break;
347
348 case 1: // dd.mm.yyyy (e.g. German)
349 sprintf(pszDate, "%02d%c%02d%c%04d",
350 pDateTime->day,
351 cDateSep,
352 pDateTime->month,
353 cDateSep,
354 pDateTime->year);
355 break;
356
357 case 2: // yyyy.mm.dd (Japanese)
358 sprintf(pszDate, "%04d%c%02d%c%02d",
359 pDateTime->year,
360 cDateSep,
361 pDateTime->month,
362 cDateSep,
363 pDateTime->day);
364 break;
365
366 default: // yyyy.dd.mm
367 sprintf(pszDate, "%04d%c%02d%c%02d",
368 pDateTime->year,
369 cDateSep,
370 pDateTime->day,
371 cDateSep,
372 pDateTime->month);
373 break;
374 }
375 }
376
377 if (pszTime)
378 {
379 if (ulTimeFormat == 0)
380 {
381 // for 12-hour clock, we need additional INI data
382 CHAR szAMPM[10] = "err";
383
384 if (pDateTime->hours > 12)
385 {
386 // > 12h: PM.
387
388 // Note: 12:xx noon is 12 AM, not PM (even though
389 // AM stands for "ante meridiam", but English is just
390 // not logical), so that's handled below.
391
392 PrfQueryProfileString(HINI_USER,
393 "PM_National",
394 "s2359", // key
395 "PM", // default
396 szAMPM, sizeof(szAMPM)-1);
397 sprintf(pszTime, "%02d%c%02d%c%02d %s",
398 // leave 12 == 12 (not 0)
399 pDateTime->hours % 12,
400 cTimeSep,
401 pDateTime->minutes,
402 cTimeSep,
403 pDateTime->seconds,
404 szAMPM);
405 }
406 else
407 {
408 // <= 12h: AM
409 PrfQueryProfileString(HINI_USER,
410 "PM_National",
411 "s1159", // key
412 "AM", // default
413 szAMPM, sizeof(szAMPM)-1);
414 sprintf(pszTime, "%02d%c%02d%c%02d %s",
415 pDateTime->hours,
416 cTimeSep,
417 pDateTime->minutes,
418 cTimeSep,
419 pDateTime->seconds,
420 szAMPM);
421 }
422 }
423 else
424 // 24-hour clock
425 sprintf(pszTime, "%02d%c%02d%c%02d",
426 pDateTime->hours,
427 cTimeSep,
428 pDateTime->minutes,
429 cTimeSep,
430 pDateTime->seconds);
431 }
432}
433
434/*
435 * strhDateTime:
436 * wrapper around nlsDateTime for those who used
437 * the XFLDR.DLL export.
438 */
439
440VOID APIENTRY strhDateTime(PSZ pszDate, // out: date string returned (can be NULL)
441 PSZ pszTime, // out: time string returned (can be NULL)
442 DATETIME *pDateTime, // in: date/time information
443 ULONG ulDateFormat, // in: date format (0-3); see nlsFileDate
444 CHAR cDateSep, // in: date separator (e.g. '.')
445 ULONG ulTimeFormat, // in: 24-hour time format (0 or 1); see nlsFileTime
446 CHAR cTimeSep) // in: time separator (e.g. ':')
447{
448 nlsDateTime(pszDate,
449 pszTime,
450 pDateTime,
451 ulDateFormat,
452 cDateSep,
453 ulTimeFormat,
454 cTimeSep);
455}
456
Note: See TracBrowser for help on using the repository browser.