Release 950109
[wine/multimedia.git] / misc / profile.c
blob7fd305da78746fafdaf136eaa6aab22a9276c344
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>
24 #include "wine.h"
25 #include "windows.h"
26 #include "dos_fs.h"
27 #include "stddebug.h"
28 /* #define DEBUG_PROFILE */
29 #include "debug.h"
31 #define STRSIZE 255
32 #define xmalloc(x) malloc(x)
33 #define overflow (next == &CharBuffer [STRSIZE-1])
35 enum { FirstBrace, OnSecHeader, IgnoreToEOL, KeyDef, KeyValue };
37 typedef struct TKeys {
38 char *KeyName;
39 char *Value;
40 struct TKeys *link;
41 } TKeys;
43 typedef struct TSecHeader {
44 char *AppName;
45 TKeys *Keys;
46 struct TSecHeader *link;
47 } TSecHeader;
49 typedef struct TProfile {
50 char *FileName;
51 TSecHeader *Section;
52 struct TProfile *link;
53 int changed;
54 } TProfile;
56 TProfile *Current = 0;
57 TProfile *Base = 0;
59 static TSecHeader *is_loaded (char *FileName)
61 TProfile *p = Base;
63 while (p){
64 if (!strcasecmp (FileName, p->FileName)){
65 Current = p;
66 return p->Section;
68 p = p->link;
70 return 0;
73 static char *GetIniFileName(char *name)
75 char temp[256];
77 if (strchr(name, '/'))
78 return name;
80 if (strchr(name, '\\'))
81 return DOS_GetUnixFileName(name);
83 GetWindowsDirectory(temp, sizeof(temp) );
84 strcat(temp, "\\");
85 strcat(temp, name);
87 return DOS_GetUnixFileName(temp);
90 static TSecHeader *load (char *filename)
92 FILE *f;
93 int state;
94 TSecHeader *SecHeader = 0;
95 char CharBuffer [STRSIZE];
96 char *next, *file;
97 char c;
99 file = GetIniFileName(filename);
101 dprintf_profile(stddeb,"Load %s\n", file);
102 if ((f = fopen (file, "r"))==NULL)
103 return NULL;
105 dprintf_profile(stddeb,"Loading %s\n", file);
108 state = FirstBrace;
109 while ((c = getc (f)) != EOF){
110 if (c == '\r') /* Ignore Carriage Return */
111 continue;
113 switch (state){
115 case OnSecHeader:
116 if (c == ']' || overflow){
117 *next = '\0';
118 next = CharBuffer;
119 SecHeader->AppName = strdup (CharBuffer);
120 state = IgnoreToEOL;
121 dprintf_profile(stddeb,"%s: section %s\n", file, CharBuffer);
122 } else
123 *next++ = c;
124 break;
126 case IgnoreToEOL:
127 if (c == '\n'){
128 state = KeyDef;
129 next = CharBuffer;
131 break;
133 case FirstBrace:
134 case KeyDef:
135 if (c == '['){
136 TSecHeader *temp;
138 temp = SecHeader;
139 SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader));
140 SecHeader->link = temp;
141 SecHeader->Keys = 0;
142 state = OnSecHeader;
143 next = CharBuffer;
144 break;
146 if (state == FirstBrace) /* On first pass, don't allow dangling keys */
147 break;
149 if (c == '\t')
150 break;
152 if (c == '\n' || c == ';' || overflow) /* Abort Definition */
153 next = CharBuffer;
155 if (c == ';')
157 state = IgnoreToEOL;
158 break;
161 if (c == '=' || overflow){
162 TKeys *temp;
164 temp = SecHeader->Keys;
165 while(next[-1]==' ')next--;
166 *next = '\0';
167 SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys));
168 SecHeader->Keys->link = temp;
169 SecHeader->Keys->KeyName = strdup (CharBuffer);
170 state = KeyValue;
171 next = CharBuffer;
172 dprintf_profile(stddeb,"%s: key %s\n", file, CharBuffer);
173 } else
174 *next++ = c;
175 break;
177 case KeyValue:
178 if (overflow || c == '\n'){
179 *next = '\0';
180 SecHeader->Keys->Value = strdup (CharBuffer);
181 state = c == '\n' ? KeyDef : IgnoreToEOL;
182 next = CharBuffer;
183 dprintf_profile (stddeb, "[%s] (%s)=%s\n", SecHeader->AppName,
184 SecHeader->Keys->KeyName, SecHeader->Keys->Value);
185 } else
186 *next++ = c;
187 break;
189 } /* switch */
191 } /* while ((c = getc (f)) != EOF) */
192 return SecHeader;
195 static void new_key (TSecHeader *section, char *KeyName, char *Value)
197 TKeys *key;
199 key = (TKeys *) xmalloc (sizeof (TKeys));
200 key->KeyName = strdup (KeyName);
201 key->Value = strdup (Value);
202 key->link = section->Keys;
203 section->Keys = key;
206 static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
207 LPSTR Default, LPSTR ReturnedString, short Size,
208 LPSTR FileName)
211 TProfile *New;
212 TSecHeader *section;
213 TKeys *key;
215 /* Supposedly Default should NEVER be NULL. But sometimes it is. */
216 if (Default == NULL)
217 Default = "";
219 if (!(section = is_loaded (FileName))){
220 New = (TProfile *) xmalloc (sizeof (TProfile));
221 New->link = Base;
222 New->FileName = strdup (FileName);
223 New->Section = load (FileName);
224 New->changed = FALSE;
225 Base = New;
226 section = New->Section;
227 Current = New;
229 /* Start search */
230 for (; section; section = section->link){
231 if (strcasecmp (section->AppName, AppName))
232 continue;
234 /* If no key value given, then list all the keys */
235 if ((!KeyName) && (!set)){
236 char *p = ReturnedString;
237 int left = Size - 2;
238 int slen;
240 dprintf_profile(stddeb,"GetSetProfile // KeyName == NULL, Enumeration !\n");
241 for (key = section->Keys; key; key = key->link){
242 if (left < 1) {
243 dprintf_profile(stddeb,"GetSetProfile // No more storage for enum !\n");
244 return (Size - 2);
246 slen = min(strlen(key->KeyName) + 1, left);
247 dprintf_profile(stddeb,"GetSetProfile // strncpy(%p, %p, %d);\n",
248 ReturnedString, key->Value, slen);
249 strncpy (p, key->KeyName, slen);
250 dprintf_profile(stddeb,"GetSetProfile // enum '%s' !\n", p);
251 left -= slen;
252 p += slen;
254 *p = '\0';
255 dprintf_profile(stddeb,"GetSetProfile // normal end of enum !\n");
256 return (Size - 2 - left);
258 for (key = section->Keys; key; key = key->link){
259 if (strcasecmp (key->KeyName, KeyName))
260 continue;
261 if (set){
262 free (key->Value);
263 key->Value = strdup (Default ? Default : "");
264 Current->changed=TRUE;
265 return 1;
267 ReturnedString [Size-1] = 0;
268 strncpy (ReturnedString, key->Value, Size-1);
269 return 1;
271 /* If Getting the information, then don't write the information
272 to the INI file, need to run a couple of tests with windog */
273 /* No key found */
274 if (set)
275 new_key (section, KeyName, Default);
276 else {
277 ReturnedString [Size-1] = 0;
278 strncpy (ReturnedString, Default, Size-1);
280 return 1;
282 /* Non existent section */
283 if (set){
284 section = (TSecHeader *) xmalloc (sizeof (TSecHeader));
285 section->AppName = strdup (AppName);
286 section->Keys = 0;
287 new_key (section, KeyName, Default);
288 section->link = Current->Section;
289 Current->Section = section;
290 Current->changed = TRUE;
291 } else {
292 ReturnedString [Size-1] = 0;
293 strncpy (ReturnedString, Default, Size-1);
295 return 1;
298 short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
299 LPSTR Default, LPSTR ReturnedString,
300 short Size, LPSTR FileName)
302 int v;
304 dprintf_profile(stddeb,"GetPrivateProfileString ('%s', '%s', '%s', %p, %d, %s\n",
305 AppName, KeyName, Default, ReturnedString, Size, FileName);
306 v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
307 if (AppName)
308 return strlen (ReturnedString);
309 else
310 return Size - v;
313 int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default,
314 LPSTR ReturnedString, int Size)
316 return GetPrivateProfileString (AppName, KeyName, Default,
317 ReturnedString, Size, WIN_INI);
320 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
321 LPSTR File)
323 static char IntBuf [6];
324 static char buf [6];
326 sprintf (buf, "%d", Default);
328 /* Check the exact semantic with the SDK */
329 GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 6, File);
330 if (!strcasecmp (IntBuf, "true"))
331 return 1;
332 if (!strcasecmp (IntBuf, "yes"))
333 return 1;
334 return atoi (IntBuf);
337 WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
339 return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
342 BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
343 LPSTR FileName)
345 return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
348 BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String)
350 return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI));
353 static void dump_keys (FILE *profile, TKeys *p)
355 if (!p)
356 return;
357 dump_keys (profile, p->link);
358 fprintf (profile, "%s=%s\r\n", p->KeyName, p->Value);
361 static void dump_sections (FILE *profile, TSecHeader *p)
363 if (!p)
364 return;
365 dump_sections (profile, p->link);
366 fprintf (profile, "\r\n[%s]\r\n", p->AppName);
367 dump_keys (profile, p->Keys);
370 static void dump_profile (TProfile *p)
372 FILE *profile;
374 if (!p)
375 return;
376 dump_profile (p->link);
377 if(!p->changed)
378 return;
379 if ((profile = fopen (GetIniFileName(p->FileName), "w")) != NULL){
380 dump_sections (profile, p->Section);
381 fclose (profile);
385 void sync_profiles (void)
387 dump_profile (Base);