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

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

Lots of updates from the last week for conditional compiles and other stuff.

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