Release 951124
[wine/multimedia.git] / misc / profile.c
blob080c3dcd43a06f4a8b84bbb578b9b869b54c1a44
1 /*
2 * Initialization-File Functions.
4 * Copyright (c) 1993 Miguel de Icaza
6 * 1/Dec o Corrected return values for Get*ProfileString
8 * o Now, if AppName == NULL in Get*ProfileString it returns a list
9 * of the KeyNames (as documented in the MS-SDK).
11 * o if KeyValue == NULL now clears the value in Get*ProfileString
13 * 20/Apr SL - I'm not sure where these definitions came from, but my SDK
14 * has a NULL KeyValue returning a list of KeyNames, and a NULL
15 * AppName undefined. I changed GetSetProfile to match. This makes
16 * PROGMAN.EXE do the right thing.
18 static char Copyright [] = "Copyright (C) 1993 Miguel de Icaza";
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
25 #include "wine.h"
26 #include "windows.h"
27 #include "dos_fs.h"
28 #include "module.h"
29 #include "toolhelp.h"
30 #include "stddebug.h"
31 /* #define DEBUG_PROFILE */
32 #include "debug.h"
33 #include "xmalloc.h"
35 #define STRSIZE 255
36 #define overflow (next == &CharBuffer [STRSIZE-1])
38 typedef struct TKeys {
39 char *KeyName;
40 char *Value;
41 struct TKeys *link;
42 } TKeys;
44 typedef struct TSecHeader {
45 char *AppName;
46 TKeys *Keys;
47 struct TSecHeader *link;
48 } TSecHeader;
50 typedef struct TProfile {
51 char *FileName;
52 char *FullName;
53 TSecHeader *Section;
54 struct TProfile *link;
55 int changed;
56 } TProfile;
58 TProfile *Current = 0;
59 TProfile *Base = 0;
61 static TSecHeader *is_loaded (char *FileName)
63 TProfile *p = Base;
65 while (p){
66 if (!strcasecmp (FileName, p->FileName)){
67 Current = p;
68 return p->Section;
70 p = p->link;
72 return 0;
75 static char *GetIniFileName(char *name, char *dir)
77 char temp[256];
79 if (strchr(name, '/'))
80 return name;
82 if (strchr(name, '\\'))
83 return DOS_GetUnixFileName(name);
85 strcpy(temp, dir);
86 strcat(temp, "\\");
87 strcat(temp, name);
89 return DOS_GetUnixFileName(temp);
92 static TSecHeader *load (char *filename, char **pfullname)
94 FILE *f;
95 TSecHeader *SecHeader = 0;
96 char CharBuffer [STRSIZE];
97 char *bufptr;
98 char *lastnonspc;
99 int bufsize;
100 char *file;
101 int c;
102 char path[MAX_PATH+1];
103 BOOL firstbrace;
105 *pfullname = NULL;
107 /* Try the Windows directory */
109 GetWindowsDirectory(path, sizeof(path));
110 file = GetIniFileName(filename, path);
112 dprintf_profile(stddeb,"Load %s\n", file);
113 f = fopen(file, "r");
115 if (f == NULL) {
116 /* Try the path of the current executable */
118 if (GetCurrentTask())
120 char *p;
121 GetModuleFileName( GetCurrentTask(), path, MAX_PATH );
122 if ((p = strrchr( path, '\\' )))
124 p[1] = '\0';
125 file = GetIniFileName(filename, path);
126 f = fopen(file, "r");
130 if (f == NULL) {
131 fprintf(stderr, "profile.c: load() can't find file %s\n", filename);
132 /* FIXME: we ought to create it now (in which directory?) */
133 return NULL;
136 *pfullname = strdup(file);
137 dprintf_profile(stddeb,"Loading %s\n", file);
139 firstbrace = TRUE;
140 for(;;) {
141 c = fgetc(f);
142 if (c == EOF) goto finished;
144 if (isspace(c))
145 continue;
147 if (c == '[') {
148 TSecHeader *temp = SecHeader;
150 SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader));
151 SecHeader->link = temp;
152 SecHeader->Keys = NULL;
153 do {
154 c = fgetc(f);
155 if (c == EOF) goto bad_file;
156 } while (isspace(c));
157 bufptr = lastnonspc = CharBuffer;
158 bufsize = 0;
159 do {
160 if (c != ']') {
161 bufsize++;
162 *bufptr++ = c;
163 if (!isspace(c))
164 lastnonspc = bufptr;
165 } else
166 break;
167 c = fgetc(f);
168 if (c == EOF) goto bad_file;
169 } while(bufsize < STRSIZE-1);
170 *lastnonspc = 0;
171 if (!strlen(CharBuffer))
172 fprintf(stderr, "warning: empty section name in ini file\n");
173 SecHeader->AppName = strdup (CharBuffer);
174 dprintf_profile(stddeb,"%s: section %s\n", file, CharBuffer);
175 firstbrace = FALSE;
176 } else if (SecHeader) {
177 TKeys *temp = SecHeader->Keys;
178 BOOL skipspc;
180 if (firstbrace)
181 goto bad_file;
182 bufptr = lastnonspc = CharBuffer;
183 bufsize = 0;
184 do {
185 if (c != '=') {
186 bufsize++;
187 *bufptr++ = c;
188 if (!isspace(c))
189 lastnonspc = bufptr;
190 } else
191 break;
192 c = fgetc(f);
193 if (c == EOF) goto bad_file;
194 } while(bufsize < STRSIZE-1);
195 *lastnonspc = 0;
196 if (!strlen(CharBuffer))
197 fprintf(stderr, "warning: empty key name in ini file\n");
198 SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys));
199 SecHeader->Keys->link = temp;
200 SecHeader->Keys->KeyName = strdup (CharBuffer);
202 dprintf_profile(stddeb,"%s: key %s\n", file, CharBuffer);
204 bufptr = lastnonspc = CharBuffer;
205 bufsize = 0;
206 skipspc = TRUE;
207 do {
208 c = fgetc(f);
209 if (c == EOF) break;
210 if (c != '\n') {
211 if (!isspace(c) || !skipspc) {
212 skipspc = FALSE;
213 bufsize++;
214 *bufptr++ = c;
215 if (!isspace(c))
216 lastnonspc = bufptr;
218 } else
219 break;
220 } while(bufsize < STRSIZE-1);
221 *lastnonspc = 0;
222 SecHeader->Keys->Value = strdup (CharBuffer);
223 dprintf_profile (stddeb, "[%s] (%s)=%s\n", SecHeader->AppName,
224 SecHeader->Keys->KeyName, SecHeader->Keys->Value);
229 bad_file:
230 fprintf(stderr, "warning: bad ini file\n");
231 finished:
232 return SecHeader;
235 static void new_key (TSecHeader *section, char *KeyName, char *Value)
237 TKeys *key;
239 key = (TKeys *) xmalloc (sizeof (TKeys));
240 key->KeyName = strdup (KeyName);
241 key->Value = strdup (Value);
242 key->link = section->Keys;
243 section->Keys = key;
246 static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
247 LPSTR Default, LPSTR ReturnedString, short Size,
248 LPSTR FileName)
251 TProfile *New;
252 TSecHeader *section;
253 TKeys *key;
255 /* Supposedly Default should NEVER be NULL. But sometimes it is. */
256 if (Default == NULL)
257 Default = "";
259 if (!(section = is_loaded (FileName))){
260 New = (TProfile *) xmalloc (sizeof (TProfile));
261 New->link = Base;
262 New->FileName = strdup (FileName);
263 New->Section = load (FileName, &New->FullName);
264 New->changed = FALSE;
265 Base = New;
266 section = New->Section;
267 Current = New;
269 /* Start search */
270 for (; section; section = section->link){
271 if (strcasecmp (section->AppName, AppName))
272 continue;
274 /* If no key value given, then list all the keys */
275 if ((!KeyName) && (!set)){
276 char *p = ReturnedString;
277 int left = Size - 2;
278 int slen;
280 dprintf_profile(stddeb,"GetSetProfile // KeyName == NULL, Enumeration !\n");
281 for (key = section->Keys; key; key = key->link){
282 if (left < 1) {
283 dprintf_profile(stddeb,"GetSetProfile // No more storage for enum !\n");
284 return (Size - 2);
286 slen = MIN(strlen(key->KeyName) + 1, left);
287 dprintf_profile(stddeb,"GetSetProfile // strncpy(%p, %p, %d);\n",
288 ReturnedString, key->Value, slen);
289 strncpy (p, key->KeyName, slen);
290 dprintf_profile(stddeb,"GetSetProfile // enum '%s' !\n", p);
291 left -= slen;
292 p += slen;
294 *p = '\0';
295 dprintf_profile(stddeb,"GetSetProfile // normal end of enum !\n");
296 return (Size - 2 - left);
298 for (key = section->Keys; key; key = key->link){
299 int slen;
300 if (strcasecmp (key->KeyName, KeyName))
301 continue;
302 if (set){
303 free (key->Value);
304 key->Value = strdup (Default ? Default : "");
305 Current->changed=TRUE;
306 return 1;
308 slen = MIN(strlen(key->Value), Size - 1);
309 ReturnedString[slen] = 0;
310 strncpy (ReturnedString, key->Value, slen);
311 dprintf_profile(stddeb,"GetSetProfile // Return ``%s''\n", ReturnedString);
312 return 1;
314 /* If Getting the information, then don't write the information
315 to the INI file, need to run a couple of tests with windog */
316 /* No key found */
317 if (set) {
318 new_key (section, KeyName, Default);
319 } else {
320 int slen = MIN(strlen(Default), Size - 1);
321 ReturnedString[slen] = 0;
322 strncpy(ReturnedString, Default, slen);
323 dprintf_profile(stddeb,"GetSetProfile // Key not found\n");
325 return 1;
327 /* Non existent section */
328 if (set){
329 section = (TSecHeader *) xmalloc (sizeof (TSecHeader));
330 section->AppName = strdup (AppName);
331 section->Keys = 0;
332 new_key (section, KeyName, Default);
333 section->link = Current->Section;
334 Current->Section = section;
335 Current->changed = TRUE;
336 } else {
337 int slen = MIN(strlen(Default), Size - 1);
338 ReturnedString[slen] = 0;
339 strncpy(ReturnedString, Default, slen);
340 dprintf_profile(stddeb,"GetSetProfile // Section not found\n");
342 return 1;
345 short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
346 LPSTR Default, LPSTR ReturnedString,
347 short Size, LPSTR FileName)
349 int v;
351 dprintf_profile(stddeb,"GetPrivateProfileString ('%s', '%s', '%s', %p, %d, %s\n",
352 AppName, KeyName, Default, ReturnedString, Size, FileName);
353 v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
354 if (AppName)
355 return strlen (ReturnedString);
356 else
357 return Size - v;
360 int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default,
361 LPSTR ReturnedString, int Size)
363 return GetPrivateProfileString (AppName, KeyName, Default,
364 ReturnedString, Size, WIN_INI);
367 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
368 LPSTR File)
370 static char IntBuf[10];
371 static char buf[10];
373 sprintf (buf, "%d", Default);
375 /* Check the exact semantic with the SDK */
376 GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 10, File);
377 if (!strcasecmp (IntBuf, "true"))
378 return 1;
379 if (!strcasecmp (IntBuf, "yes"))
380 return 1;
381 return strtoul( IntBuf, NULL, 0 );
384 WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
386 return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
389 BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
390 LPSTR FileName)
392 if (!AppName || !KeyName || !String) /* Flush file to disk */
393 return TRUE;
394 return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
397 BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String)
399 return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI));
402 static void dump_keys (FILE *profile, TKeys *p)
404 if (!p)
405 return;
406 dump_keys (profile, p->link);
407 fprintf (profile, "%s=%s\r\n", p->KeyName, p->Value);
410 static void dump_sections (FILE *profile, TSecHeader *p)
412 if (!p)
413 return;
414 dump_sections (profile, p->link);
415 fprintf (profile, "\r\n[%s]\r\n", p->AppName);
416 dump_keys (profile, p->Keys);
419 static void dump_profile (TProfile *p)
421 FILE *profile;
423 if (!p)
424 return;
425 dump_profile (p->link);
426 if(!p->changed)
427 return;
428 if (p->FullName && (profile = fopen (p->FullName, "w")) != NULL){
429 dump_sections (profile, p->Section);
430 fclose (profile);
434 void sync_profiles (void)
436 dump_profile (Base);