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

Last change on this file since 164 was 164, checked in by umoeller, 23 years ago

Massive pager rework.

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