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

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

Rewrote winlist widget to use daemon.

  • 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 szTemp[5],
236 szDefault[5];
237 szDefault[0] = cDefault;
238 szDefault[1] = 0;
239 PrfQueryProfileString(HINI_USER, (PSZ)pcszApp, (PSZ)pcszKey,
240 szDefault,
241 szTemp, sizeof(szTemp)-1);
242 return (szTemp[0]);
243}
244
245/*
246 *@@ prfhQueryColor:
247 * returns a system color in OS2.INI's PM_Colors as a LONG.
248 */
249
250LONG prfhQueryColor(const char *pcszKeyName,
251 const char *pcszDefault)
252{
253 CHAR szColor[30];
254 ULONG r, g, b;
255 PrfQueryProfileString(
256 HINI_USER,
257 "PM_Colors",
258 (PSZ)pcszKeyName,
259 (PSZ)pcszDefault,
260 szColor,
261 sizeof(szColor)-1);
262 sscanf(szColor, "%lu %lu %lu ", &r, &g, &b);
263 return (LONG)(r*0x10000 + g*0x100 + b);
264}
265
266/*
267 *@@ prfhCopyKey:
268 * this copies one key from the given profile and application
269 * to another one.
270 *
271 * pszTargetApp may be in the same profile (and must be
272 * different from pszSourceApp then) or in a different
273 * profile (and can be the same then).
274 *
275 * You must specify all parameters. You cannot specify pszKey
276 * as NULL to have a whole application copied. Use prfhCopyApp
277 * for that.
278 * No check is made for this.
279 *
280 * Returns:
281 * -- 0: no error
282 *
283 * -- PRFERR_DATASIZE: couldn't query data size for key
284 *
285 * -- PRFERR_MEMORY: couldn't allocate memory
286 *
287 * -- PRFERR_READ: couldn't read data from source (PrfQueryProfileData error)
288 *
289 * -- PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
290 *
291 *@@added V0.9.0 [umoeller]
292 */
293
294APIRET prfhCopyKey(HINI hiniSource, // in: source profile (can be HINI_USER or HINI_SYSTEM)
295 const char *pcszSourceApp, // in: source application
296 const char *pcszKey, // in: source/target key
297 HINI hiniTarget, // in: target profile (can be HINI_USER or HINI_SYSTEM)
298 const char *pcszTargetApp) // in: target app
299{
300 ULONG ulSizeOfData = 0,
301 ulrc = 0; // return: no error
302
303 if (PrfQueryProfileSize(hiniSource, (PSZ)pcszSourceApp, (PSZ)pcszKey, &ulSizeOfData))
304 {
305 PSZ pData = 0;
306
307 // copy data
308 if (ulSizeOfData == 0)
309 {
310 // data size == 0: this shouldn't really happen,
311 // but if it does, we'll just create a NULL string.
312 // Users have reported that some INI files seem to
313 // contain those "empty" keys. I don't see how these
314 // can exist, but they seem to...
315 pData = (PSZ)malloc(1);
316 *pData = 0;
317 }
318 else
319 pData = (PSZ)malloc(ulSizeOfData);
320
321 if (pData)
322 {
323 if (PrfQueryProfileData(hiniSource,
324 (PSZ)pcszSourceApp,
325 (PSZ)pcszKey,
326 pData,
327 &ulSizeOfData))
328 {
329 if (!PrfWriteProfileData(hiniTarget,
330 (PSZ)pcszTargetApp,
331 (PSZ)pcszKey,
332 pData,
333 ulSizeOfData))
334 ulrc = PRFERR_WRITE;
335 }
336 else
337 ulrc = PRFERR_READ;
338
339 free(pData);
340 }
341 else
342 ulrc = ERROR_NOT_ENOUGH_MEMORY;
343 }
344 else
345 ulrc = PRFERR_DATASIZE;
346
347 return (ulrc);
348}
349
350/*
351 *@@ prfhCopyApp:
352 * this copies one key from the given profile and application
353 * to another one.
354 *
355 * You can use this function in several contexts:
356 *
357 * -- copy one application within the same profile
358 * (i.e. hiniSource == hiniTarget);
359 * in this case, pszSourceApp must be != pszTargetApp;
360 *
361 * -- copy an application from one profile to another
362 * (i.e. hiniSource != hiniTarget);
363 * in this case, pszSourceApp can be == pszTargetApp
364 * (but can be different also).
365 *
366 * WARNING: This does _not_ check for whether the target
367 * application exists already. This has two consequences:
368 *
369 * -- existing data will be overwritten without warning;
370 *
371 * -- if the existing target application has keys that are
372 * not in the source application, they are not deleted.
373 * As a result, you might end up with more keys than
374 * in the source application.
375 *
376 * So you should delete the target application before
377 * calling this function, like this:
378 *
379 + PrfWriteProfileString(hiniTarget, pszTargetApp, NULL, NULL);
380 *
381 * You must specify all parameters. You cannot specify pszApp
382 * as NULL to have a whole profile copied. Use prfhCopyProfile
383 * for that.
384 * No check is made for this.
385 *
386 * Returns:
387 *
388 * -- 0: no error
389 *
390 * -- PRFERR_KEYSLIST: couldn't query keys for pszSourceApp
391 *
392 * -- PRFERR_DATASIZE: couldn't query data size for key
393 *
394 * -- PRFERR_MEMORY: couldn't allocate memory
395 *
396 * -- PRFERR_READ: couldn't read data from source (PrfQueryProfileData error)
397 *
398 * -- PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
399 *
400 *@@added V0.9.0 [umoeller]
401 */
402
403APIRET prfhCopyApp(HINI hiniSource, // in: source profile (can be HINI_USER or HINI_SYSTEM)
404 const char *pcszSourceApp, // in: source application
405 HINI hiniTarget, // in: target profile (can be HINI_USER or HINI_SYSTEM)
406 const char *pcszTargetApp, // in: name of pszSourceApp in hiniTarget
407 PSZ pszErrorKey) // out: failing key in case of error; ptr can be NULL
408{
409 APIRET arc = NO_ERROR;
410 PSZ pszKeysList = NULL;
411
412 if (pszErrorKey)
413 *pszErrorKey = 0;
414
415 if (!(arc = prfhQueryKeysForApp(hiniSource,
416 (PSZ)pcszSourceApp,
417 &pszKeysList)))
418 {
419 PSZ pKey2 = pszKeysList;
420
421 while (*pKey2 != 0)
422 {
423 // copy this key
424 arc = prfhCopyKey(hiniSource,
425 pcszSourceApp,
426 pKey2,
427 hiniTarget,
428 pcszTargetApp);
429 if (arc)
430 {
431 // error: copy failing key to buffer
432 if (pszErrorKey)
433 strcpy(pszErrorKey, pKey2);
434 break;
435 }
436 pKey2 += strlen(pKey2)+1;
437 } // end while (*pKey2 != 0)
438
439 free (pszKeysList);
440 }
441
442 return arc;
443}
444
445/*
446 *@@ prfhRenameKey:
447 * renames a key in an INI file.
448 *
449 * Since there's no such thing as a PrfRename,
450 * what we do here is load the old data, write
451 * it under a new key, and delete the old data.
452 *
453 * Returns:
454 *
455 * -- 0: no error
456 *
457 * -- PRFERR_INVALID_KEY: pcszApp or pcszOldKey do not exist.
458 *
459 * -- PRFERR_KEY_EXISTS: pcszNewApp/pcszNewKey is already occupied.
460 *
461 * -- PRFERR_WRITE: couldn't write data to target (PrfWriteProfileData error)
462 *
463 *@@added V0.9.9 (2001-02-06) [umoeller]
464 */
465
466ULONG prfhRenameKey(HINI hini,
467 const char *pcszOldApp,
468 const char *pcszOldKey, // in: key to rename
469 const char *pcszNewApp, // in: new app (if NULL, pcszOldApp is used)
470 const char *pcszNewKey) // in: new name for pcszOldKey
471{
472 ULONG ulrc = 0;
473
474 ULONG cbData = 0;
475 PSZ pszData = prfhQueryProfileData(hini,
476 pcszOldApp,
477 pcszOldKey,
478 &cbData);
479 if (!pszData)
480 // not found:
481 ulrc = PRFERR_INVALID_KEY;
482 else
483 {
484 ULONG cb;
485
486 if (!pcszNewApp)
487 // is NULL:
488 pcszNewApp = pcszOldApp;
489
490 // make sure target doesn't exist
491 if ( (PrfQueryProfileSize(hini,
492 (PSZ)pcszNewApp,
493 (PSZ)pcszNewKey,
494 &cb))
495 && (cb)
496 )
497 ulrc = PRFERR_KEY_EXISTS;
498 else
499 {
500 if (!PrfWriteProfileData(hini,
501 (PSZ)pcszNewApp,
502 (PSZ)pcszNewKey,
503 pszData,
504 cbData))
505 ulrc = PRFERR_WRITE;
506 else
507 {
508 // success writing:
509 // delete old
510 PrfWriteProfileData(hini,
511 (PSZ)pcszOldApp,
512 (PSZ)pcszOldKey,
513 NULL,
514 0);
515 }
516 }
517
518 free(pszData);
519 }
520
521 return (ulrc);
522}
523
524/*
525 *@@ prfhSetUserProfile:
526 * calls PrfReset to change the current user
527 * profile (normally OS2.INI) to the specified
528 * INI file.
529 *
530 *@@added V0.9.4 (2000-07-19) [umoeller]
531 *@@changed V0.9.19 (2002-04-02) [umoeller]: now returning APIRET
532 */
533
534APIRET prfhSetUserProfile(HAB hab,
535 const char *pcszUserProfile) // in: new user profile (.INI)
536{
537 APIRET arc = NO_ERROR;
538
539 // find out current profile names
540 PRFPROFILE Profiles;
541 Profiles.cchUserName = Profiles.cchSysName = 0;
542 // first query their file name lengths
543 if (PrfQueryProfile(hab, &Profiles))
544 {
545 // allocate memory for filenames
546 Profiles.pszUserName = (PSZ)malloc(Profiles.cchUserName);
547 Profiles.pszSysName = (PSZ)malloc(Profiles.cchSysName);
548
549 if ((Profiles.pszSysName) && (Profiles.pszUserName))
550 {
551 // get filenames
552 if (PrfQueryProfile(hab, &Profiles))
553 {
554 // _Pmpf(("Old user profile: %s", Profiles.pszUserName));
555
556 // change INIs
557 free(Profiles.pszUserName);
558 Profiles.pszUserName = (PSZ)pcszUserProfile;
559 Profiles.cchUserName = strlen(pcszUserProfile) + 1;
560 if (!PrfReset(hab, &Profiles))
561 arc = PRFERR_RESET;
562 free(Profiles.pszSysName);
563 }
564 else
565 arc = PRFERR_QUERY;
566 }
567 else
568 arc = PRFERR_QUERY;
569 }
570 else
571 arc = PRFERR_QUERY;
572
573 return arc;
574}
575
576
Note: See TracBrowser for help on using the repository browser.