source: trunk/src/helpers/prfh.c@ 98

Last change on this file since 98 was 71, 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: 19.4 KB
Line 
1
2/*
3 *@@sourcefile prfh.c:
4 * contains those Presentation Manager helper functions
5 * which deal with Profile (Prf*) functions.
6 * This file is new with V0.82.
7 *
8 * Usage: All OS/2 programs.
9 *
10 * Function prefixes:
11 * -- prfh* Prf (profile, INI) helper functions
12 *
13 * Note: Version numbering in this file relates to XWorkplace version
14 * numbering.
15 *
16 *@@header "helpers\prfh.h"
17 */
18
19/*
20 * Copyright (C) 1997-2000 Ulrich M”ller.
21 * This file is part of the "XWorkplace helpers" source package.
22 * This is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published
24 * by the Free Software Foundation, in version 2 as it comes in the
25 * "COPYING" file of the XWorkplace main distribution.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 */
31
32#define OS2EMX_PLAIN_CHAR
33 // this is needed for "os2emx.h"; if this is defined,
34 // emx will define PSZ as _signed_ char, otherwise
35 // as unsigned char
36
37#define INCL_DOSERRORS
38#define INCL_WINSHELLDATA
39#include <os2.h>
40
41#include <stdlib.h>
42#include <stdio.h>
43#include <string.h>
44
45#include "setup.h" // code generation and debugging options
46
47#include "helpers\prfh.h"
48
49#pragma hdrstop
50
51/*
52 *@@category: Helpers\Profile (INI) helpers
53 */
54
55/*
56 *@@ prfhQueryKeysForApp:
57 * returns the keys list for an INI application. This
58 * list is copied into a newly allocated buffer, of which
59 * the address is returned.
60 *
61 * Returns NULL upon errors.
62 *
63 * If the return value is != NULL, the PSZ points to a new
64 * buffer which contains all the keys within the pszApp
65 * application. Each key name in the list is terminated with
66 * a null character. The last string in the list is terminated
67 * with two null characters.
68 *
69 * The returned buffer should be freed later using free().
70 *
71 * <B>Example</B> for iterating over a keys list:
72 *
73 + PSZ pszKeysList = prfhQueryKeysForApp(...);
74 + if (pszKeysList)
75 + {
76 + PSZ pKey2 = pszKeysList;
77 +
78 + while (*pKey2 != 0)
79 + {
80 + ... // pKey2 has the current key now
81 + pKey2 += strlen(pKey2)+1; // next key
82 + }
83 + free(pszKeysList);
84 + }
85 *
86 * You can also use this function to query the applications
87 * list for hIni, if you specifiy pszApp as NULL.
88 *
89 *@@changed V0.9.12 (2001-05-12) [umoeller]: changed prototypes to return APIRET now
90 */
91
92APIRET prfhQueryKeysForApp(HINI hIni, // in: INI handle (can be HINI_USER or HINI_SYSTEM)
93 const char *pcszApp, // in: application to query list for (or NULL for applications list)
94 PSZ *ppszKeys) // out: keys list (newly allocated)
95{
96 APIRET arc = NO_ERROR;
97 PSZ pKeys = NULL;
98 ULONG ulSizeOfKeysList = 0;
99
100 // get size of keys list for pszApp
101 if ( (!PrfQueryProfileSize(hIni, (PSZ)pcszApp, NULL, &ulSizeOfKeysList))
102 || (ulSizeOfKeysList == 0)
103 )
104 arc = PRFERR_KEYSLIST;
105 else
106 {
107 pKeys = (PSZ)malloc(ulSizeOfKeysList);
108 if (!pKeys)
109 arc = ERROR_NOT_ENOUGH_MEMORY;
110 else
111 if (!PrfQueryProfileData(hIni, (PSZ)pcszApp, NULL, pKeys, &ulSizeOfKeysList))
112 arc = PRFERR_KEYSLIST;
113 }
114
115 if (!arc) // V0.9.12 (2001-05-12) [umoeller]
116 *ppszKeys = pKeys;
117 else
118 if (pKeys)
119 free(pKeys);
120
121 return (arc);
122}
123
124#ifdef __DEBUG_MALLOC_ENABLED__ // setup.h, helpers\memdebug.c
125
126/*
127 *@@ prfhQueryProfileDataDebug:
128 * debug version of prfhQueryProfileData, which is
129 * automatically mapped to if __XWPMEMDEBUG__ is defined.
130 *
131 *@@added V0.9.1 (99-12-20) [umoeller]
132 *@@changed V0.9.3 (2000-04-20) [umoeller]: this called malloc(0) if the key existed, but was empty. Fixed.
133 */
134
135PSZ prfhQueryProfileDataDebug(HINI hIni, // in: INI handle (can be HINI_USER or HINI_SYSTEM)
136 const char *pcszApp, // in: application to query
137 const char *pcszKey, // in: key to query
138 PULONG pcbBuf, // out: size of the returned buffer
139 const char *file,
140 unsigned long line,
141 const char *function)
142{
143 PSZ pData = NULL;
144 ULONG ulSizeOfData = 0;
145
146 // get size of data for pszApp/pszKey
147 if (PrfQueryProfileSize(hIni, (PSZ)pcszApp, (PSZ)pcszKey, &ulSizeOfData))
148 {
149 if (ulSizeOfData)
150 {
151 pData = (PSZ)memdMalloc(ulSizeOfData, file, line, function);
152 if (!PrfQueryProfileData(hIni, (PSZ)pcszApp, (PSZ)pcszKey, pData, &ulSizeOfData))
153 {
154 free(pData);
155 pData = NULL;
156 }
157 }
158 }
159
160 if (pcbBuf)
161 *pcbBuf = ulSizeOfData;
162
163 return (pData);
164}
165
166#else
167
168/*
169 *@@ prfhQueryProfileData:
170 * similar to PrfQueryProfileData, but this one copies
171 * the data into a newly allocated buffer, of which the
172 * address is returned.
173 *
174 * Returns NULL upon errors, for example if the specified
175 * key doesn't exist or doesn't contain any data.
176 *
177 * If pcbBuf != NULL, this func will write the size of
178 * the allocated buffer into *pcbBuf.
179 *
180 * The returned buffer should be freed later using free().
181 *
182 *@@added V0.9.0 [umoeller]
183 *@@changed V0.9.3 (2000-04-20) [umoeller]: this called malloc(0) if the key existed, but was empty. Fixed.
184 */
185
186PSZ prfhQueryProfileData(HINI hIni, // in: INI handle (can be HINI_USER or HINI_SYSTEM)
187 const char *pcszApp, // in: application to query
188 const char *pcszKey, // in: key to query
189 PULONG pcbBuf) // out: size of the returned buffer; ptr can be NULL
190{
191 PSZ pData = NULL;
192 ULONG ulSizeOfData = 0;
193
194 // get size of data for pszApp/pszKey
195 if (PrfQueryProfileSize(hIni, (PSZ)pcszApp, (PSZ)pcszKey, &ulSizeOfData))
196 {
197 if (ulSizeOfData)
198 {
199 pData = (PSZ)malloc(ulSizeOfData);
200 if (!PrfQueryProfileData(hIni, (PSZ)pcszApp, (PSZ)pcszKey, pData, &ulSizeOfData))
201 {
202 free(pData);
203 pData = NULL;
204 }
205 }
206 }
207
208 if (pcbBuf)
209 *pcbBuf = ulSizeOfData;
210
211 return (pData);
212}
213
214#endif
215
216/*
217 *@@ prfhQueryProfileChar:
218 * this query the first character of profile data.
219 * This is mostly useful with the PM country settings
220 * in OS2.INI:
221 * -- date separator: "PM_National", "sDate"
222 * -- time separator: "PM_National", "sTime"
223 */
224
225CHAR prfhQueryProfileChar(HINI hini, // in: INI handle (can be HINI_USER or HINI_SYSTEM)
226 const char *pcszApp, // in: application to query
227 const char *pcszKey, // in: key to query
228 CHAR cDefault) // in: default to return if not found
229{
230 // CHAR crc = 0;
231 CHAR szTemp[5],
232 szDefault[5];
233 szDefault[0] = cDefault;
234 szDefault[1] = 0;
235 PrfQueryProfileString(HINI_USER, (PSZ)pcszApp, (PSZ)pcszKey,
236 szDefault,
237 szTemp, sizeof(szTemp)-1);
238 return (szTemp[0]);
239}
240
241/*
242 *@@ prfhQueryCountrySettings:
243 * this returns the most frequently used country settings
244 * all at once into a COUNTRYSETTINGS structure (prfh.h).
245 * This data corresponds to the user settings in the
246 * WPS "Country" object (which writes the data in "PM_National"
247 * in OS2.INI).
248 *
249 * In case a key cannot be found, the following (English)
250 * default values are set:
251 * -- ulDateFormat = 0 (English date format, mm.dd.yyyy);
252 * -- ulTimeFormat = 0 (12-hour clock);
253 * -- cDateSep = '/' (date separator);
254 * -- cTimeSep = ':' (time separator);
255 * -- cDecimal = '.' (decimal separator).
256 * -- cThousands = ',' (thousands separator).
257 *
258 *@@added V0.9.0 [umoeller]
259 *@@changed V0.9.7 (2000-12-02) [umoeller]: added cDecimal
260 */
261
262VOID prfhQueryCountrySettings(PCOUNTRYSETTINGS pcs)
263{
264 if (pcs)
265 {
266 const char *pcszApp = "PM_National";
267 pcs->ulDateFormat = PrfQueryProfileInt(HINI_USER, (PSZ)pcszApp, "iDate", 0);
268 pcs->ulTimeFormat = PrfQueryProfileInt(HINI_USER, (PSZ)pcszApp, "iTime", 0);
269 pcs->cDateSep = prfhQueryProfileChar(HINI_USER, (PSZ)pcszApp, "sDate", '/');
270 pcs->cTimeSep = prfhQueryProfileChar(HINI_USER, (PSZ)pcszApp, "sTime", ':');
271 pcs->cDecimal = prfhQueryProfileChar(HINI_USER, (PSZ)pcszApp, "sDecimal", '.');
272 pcs->cThousands = prfhQueryProfileChar(HINI_USER, (PSZ)pcszApp, "sThousand", ',');
273 }
274}
275
276/*
277 *@@ prfhQueryColor:
278 * returns a system color in OS2.INI's PM_Colors as a LONG.
279 */
280
281LONG prfhQueryColor(const char *pcszKeyName,
282 const char *pcszDefault)
283{
284 CHAR szColor[30];
285 ULONG r, g, b;
286 PrfQueryProfileString(
287 HINI_USER,
288 "PM_Colors",
289 (PSZ)pcszKeyName,
290 (PSZ)pcszDefault,
291 szColor,
292 sizeof(szColor)-1);
293 sscanf(szColor, "%lu %lu %lu ", &r, &g, &b);
294 return (LONG)(r*0x10000 + g*0x100 + b);
295}
296
297/*
298 *@@ prfhCopyKey:
299 * this copies one key from the given profile and application
300 * to another one.
301 *
302 * pszTargetApp may be in the same profile (and must be
303 * different from pszSourceApp then) or in a different
304 * profile (and can be the same then).
305 *
306 * You must specify all parameters. You cannot specify pszKey
307 * as NULL to have a whole application copied. Use prfhCopyApp
308 * for that.
309 * No check is made for this.
310 *
311 * Returns:
312 * -- 0: no error
313 *
314 * -- PRFERR_DATASIZE: couldn't query data size for key
315 *
316 * -- PRFERR_MEMORY: couldn't allocate memory
317 *
318 * -- PRFERR_READ: couldn't read data from source (PrfQueryProfileData error)
319 *
320 * -- PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
321 *
322 *@@added V0.9.0 [umoeller]
323 */
324
325APIRET prfhCopyKey(HINI hiniSource, // in: source profile (can be HINI_USER or HINI_SYSTEM)
326 const char *pcszSourceApp, // in: source application
327 const char *pcszKey, // in: source/target key
328 HINI hiniTarget, // in: target profile (can be HINI_USER or HINI_SYSTEM)
329 const char *pcszTargetApp) // in: target app
330{
331 ULONG ulSizeOfData = 0,
332 ulrc = 0; // return: no error
333
334 if (PrfQueryProfileSize(hiniSource, (PSZ)pcszSourceApp, (PSZ)pcszKey, &ulSizeOfData))
335 {
336 PSZ pData = 0;
337
338 // copy data
339 if (ulSizeOfData == 0)
340 {
341 // data size == 0: this shouldn't really happen,
342 // but if it does, we'll just create a NULL string.
343 // Users have reported that some INI files seem to
344 // contain those "empty" keys. I don't see how these
345 // can exist, but they seem to...
346 pData = (PSZ)malloc(1);
347 *pData = 0;
348 }
349 else
350 pData = (PSZ)malloc(ulSizeOfData);
351
352 if (pData)
353 {
354 if (PrfQueryProfileData(hiniSource,
355 (PSZ)pcszSourceApp,
356 (PSZ)pcszKey,
357 pData,
358 &ulSizeOfData))
359 {
360 if (!PrfWriteProfileData(hiniTarget,
361 (PSZ)pcszTargetApp,
362 (PSZ)pcszKey,
363 pData,
364 ulSizeOfData))
365 ulrc = PRFERR_WRITE;
366 }
367 else
368 ulrc = PRFERR_READ;
369
370 free(pData);
371 }
372 else
373 ulrc = ERROR_NOT_ENOUGH_MEMORY;
374 }
375 else
376 ulrc = PRFERR_DATASIZE;
377
378 return (ulrc);
379}
380
381/*
382 *@@ prfhCopyApp:
383 * this copies one key from the given profile and application
384 * to another one.
385 *
386 * You can use this function in several contexts:
387 *
388 * -- copy one application within the same profile
389 * (i.e. hiniSource == hiniTarget);
390 * in this case, pszSourceApp must be != pszTargetApp;
391 *
392 * -- copy an application from one profile to another
393 * (i.e. hiniSource != hiniTarget);
394 * in this case, pszSourceApp can be == pszTargetApp
395 * (but can be different also).
396 *
397 * WARNING: This does _not_ check for whether the target
398 * application exists already. This has two consequences:
399 *
400 * -- existing data will be overwritten without warning;
401 *
402 * -- if the existing target application has keys that are
403 * not in the source application, they are not deleted.
404 * As a result, you might end up with more keys than
405 * in the source application.
406 *
407 * So you should delete the target application before
408 * calling this function, like this:
409 *
410 + PrfWriteProfileString(hiniTarget, pszTargetApp, NULL, NULL);
411 *
412 * You must specify all parameters. You cannot specify pszApp
413 * as NULL to have a whole profile copied. Use prfhCopyProfile
414 * for that.
415 * No check is made for this.
416 *
417 * Returns:
418 *
419 * -- 0: no error
420 *
421 * -- PRFERR_KEYSLIST: couldn't query keys for pszSourceApp
422 *
423 * -- PRFERR_DATASIZE: couldn't query data size for key
424 *
425 * -- PRFERR_MEMORY: couldn't allocate memory
426 *
427 * -- PRFERR_READ: couldn't read data from source (PrfQueryProfileData error)
428 *
429 * -- PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
430 *
431 *@@added V0.9.0 [umoeller]
432 */
433
434APIRET prfhCopyApp(HINI hiniSource, // in: source profile (can be HINI_USER or HINI_SYSTEM)
435 const char *pcszSourceApp, // in: source application
436 HINI hiniTarget, // in: target profile (can be HINI_USER or HINI_SYSTEM)
437 const char *pcszTargetApp, // in: name of pszSourceApp in hiniTarget
438 PSZ pszErrorKey) // out: failing key in case of error; ptr can be NULL
439{
440 APIRET arc = NO_ERROR;
441 PSZ pszKeysList = NULL;
442
443 if (pszErrorKey)
444 *pszErrorKey = 0;
445
446 if (!(arc = prfhQueryKeysForApp(hiniSource,
447 (PSZ)pcszSourceApp,
448 &pszKeysList)))
449 {
450 PSZ pKey2 = pszKeysList;
451
452 while (*pKey2 != 0)
453 {
454 // copy this key
455 arc = prfhCopyKey(hiniSource,
456 pcszSourceApp,
457 pKey2,
458 hiniTarget,
459 pcszTargetApp);
460 if (arc)
461 {
462 // error: copy failing key to buffer
463 if (pszErrorKey)
464 strcpy(pszErrorKey, pKey2);
465 break;
466 }
467 pKey2 += strlen(pKey2)+1;
468 } // end while (*pKey2 != 0)
469
470 free (pszKeysList);
471 }
472
473 return (arc);
474}
475
476/*
477 *@@ prfhRenameKey:
478 * renames a key in an INI file.
479 *
480 * Since there's no such thing as a PrfRename,
481 * what we do here is load the old data, write
482 * it under a new key, and delete the old data.
483 *
484 * Returns:
485 *
486 * -- 0: no error
487 *
488 * -- PRFERR_INVALID_KEY: pcszApp or pcszOldKey do not exist.
489 *
490 * -- PRFERR_KEY_EXISTS: pcszNewApp/pcszNewKey is already occupied.
491 *
492 * -- PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
493 *
494 *@@added V0.9.9 (2001-02-06) [umoeller]
495 */
496
497ULONG prfhRenameKey(HINI hini,
498 const char *pcszOldApp,
499 const char *pcszOldKey, // in: key to rename
500 const char *pcszNewApp, // in: new app (if NULL, pcszOldApp is used)
501 const char *pcszNewKey) // in: new name for pcszOldKey
502{
503 ULONG ulrc = 0;
504
505 ULONG cbData = 0;
506 PSZ pszData = prfhQueryProfileData(hini,
507 pcszOldApp,
508 pcszOldKey,
509 &cbData);
510 if (!pszData)
511 // not found:
512 ulrc = PRFERR_INVALID_KEY;
513 else
514 {
515 ULONG cb;
516
517 if (!pcszNewApp)
518 // is NULL:
519 pcszNewApp = pcszOldApp;
520
521 // make sure target doesn't exist
522 if ( (PrfQueryProfileSize(hini,
523 (PSZ)pcszNewApp,
524 (PSZ)pcszNewKey,
525 &cb))
526 && (cb)
527 )
528 ulrc = PRFERR_KEY_EXISTS;
529 else
530 {
531 if (!PrfWriteProfileData(hini,
532 (PSZ)pcszNewApp,
533 (PSZ)pcszNewKey,
534 pszData,
535 cbData))
536 ulrc = PRFERR_WRITE;
537 else
538 {
539 // success writing:
540 // delete old
541 PrfWriteProfileData(hini,
542 (PSZ)pcszOldApp,
543 (PSZ)pcszOldKey,
544 NULL,
545 0);
546 }
547 }
548
549 free(pszData);
550 }
551
552 return (ulrc);
553}
554
555/*
556 *@@ prfhSetUserProfile:
557 * calls PrfReset to change the current user
558 * profile (normally OS2.INI) to the specified
559 * INI file.
560 *
561 *@@added V0.9.4 (2000-07-19) [umoeller]
562 */
563
564BOOL prfhSetUserProfile(HAB hab,
565 const char *pcszUserProfile) // in: new user profile (.INI)
566{
567 BOOL brc = FALSE;
568 // find out current profile names
569 PRFPROFILE Profiles;
570 Profiles.cchUserName = Profiles.cchSysName = 0;
571 // first query their file name lengths
572 if (PrfQueryProfile(hab, &Profiles))
573 {
574 // allocate memory for filenames
575 Profiles.pszUserName = (PSZ)malloc(Profiles.cchUserName);
576 Profiles.pszSysName = (PSZ)malloc(Profiles.cchSysName);
577
578 if ((Profiles.pszSysName) && (Profiles.pszUserName))
579 {
580 // get filenames
581 if (PrfQueryProfile(hab, &Profiles))
582 {
583 // _Pmpf(("Old user profile: %s", Profiles.pszUserName));
584
585 // change INIs
586 free(Profiles.pszUserName);
587 Profiles.pszUserName = (PSZ)pcszUserProfile;
588 Profiles.cchUserName = strlen(pcszUserProfile) + 1;
589 brc = PrfReset(hab, &Profiles);
590 free(Profiles.pszSysName);
591 }
592 }
593 }
594
595 return (brc);
596}
597
598
Note: See TracBrowser for help on using the repository browser.