Release 941122
[wine/multimedia.git] / misc / profile.c
blobd4f5af10c851e2172972d0496906b394589654d5
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.
19 static char Copyright [] = "Copyright (C) 1993 Miguel de Icaza";
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "wine.h"
26 #include "windows.h"
27 #include "prototypes.h"
28 #include "stddebug.h"
29 /* #define DEBUG_PROFILE */
30 /* #undef DEBUG_PROFILE */
31 #include "debug.h"
34 #define STRSIZE 255
35 #define xmalloc(x) malloc(x)
36 #define overflow (next == &CharBuffer [STRSIZE-1])
38 enum { FirstBrace, OnSecHeader, IgnoreToEOL, KeyDef, KeyValue };
40 typedef struct TKeys {
41 char *KeyName;
42 char *Value;
43 struct TKeys *link;
44 } TKeys;
46 typedef struct TSecHeader {
47 char *AppName;
48 TKeys *Keys;
49 struct TSecHeader *link;
50 } TSecHeader;
52 typedef struct TProfile {
53 char *FileName;
54 TSecHeader *Section;
55 struct TProfile *link;
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)
77 char temp[256];
79 if (strchr(name, '/'))
80 return name;
82 if (strchr(name, '\\'))
83 return GetUnixFileName(name);
85 GetWindowsDirectory(temp, sizeof(temp) );
86 strcat(temp, "\\");
87 strcat(temp, name);
89 return GetUnixFileName(temp);
92 static TSecHeader *load (char *filename)
94 FILE *f;
95 int state;
96 TSecHeader *SecHeader = 0;
97 char CharBuffer [STRSIZE];
98 char *next, *file;
99 char c;
101 file = GetIniFileName(filename);
103 dprintf_profile(stddeb,"Load %s\n", file);
104 if ((f = fopen (file, "r"))==NULL)
105 return NULL;
107 dprintf_profile(stddeb,"Loading %s\n", file);
110 state = FirstBrace;
111 while ((c = getc (f)) != EOF){
112 if (c == '\r') /* Ignore Carriage Return */
113 continue;
115 switch (state){
117 case OnSecHeader:
118 if (c == ']' || overflow){
119 *next = '\0';
120 next = CharBuffer;
121 SecHeader->AppName = strdup (CharBuffer);
122 state = IgnoreToEOL;
123 dprintf_profile(stddeb,"%s: section %s\n", file, CharBuffer);
124 } else
125 *next++ = c;
126 break;
128 case IgnoreToEOL:
129 if (c == '\n'){
130 state = KeyDef;
131 next = CharBuffer;
133 break;
135 case FirstBrace:
136 case KeyDef:
137 if (c == '['){
138 TSecHeader *temp;
140 temp = SecHeader;
141 SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader));
142 SecHeader->link = temp;
143 SecHeader->Keys = 0;
144 state = OnSecHeader;
145 next = CharBuffer;
146 break;
148 if (state == FirstBrace) /* On first pass, don't allow dangling keys */
149 break;
151 if (c == '\t')
152 break;
154 if (c == '\n' || c == ';' || overflow) /* Abort Definition */
155 next = CharBuffer;
157 if (c == ';')
159 state = IgnoreToEOL;
160 break;
163 if (c == '=' || overflow){
164 TKeys *temp;
166 temp = SecHeader->Keys;
167 while(next[-1]==' ')next--;
168 *next = '\0';
169 SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys));
170 SecHeader->Keys->link = temp;
171 SecHeader->Keys->KeyName = strdup (CharBuffer);
172 state = KeyValue;
173 next = CharBuffer;
174 dprintf_profile(stddeb,"%s: key %s\n", file, CharBuffer);
175 } else
176 *next++ = c;
177 break;
179 case KeyValue:
180 if (overflow || c == '\n'){
181 *next = '\0';
182 SecHeader->Keys->Value = strdup (CharBuffer);
183 state = c == '\n' ? KeyDef : IgnoreToEOL;
184 next = CharBuffer;
185 dprintf_profile (stddeb, "[%s] (%s)=%s\n", SecHeader->AppName,
186 SecHeader->Keys->KeyName, SecHeader->Keys->Value);
187 } else
188 *next++ = c;
189 break;
191 } /* switch */
193 } /* while ((c = getc (f)) != EOF) */
194 return SecHeader;
197 static void new_key (TSecHeader *section, char *KeyName, char *Value)
199 TKeys *key;
201 key = (TKeys *) xmalloc (sizeof (TKeys));
202 key->KeyName = strdup (KeyName);
203 key->Value = strdup (Value);
204 key->link = section->Keys;
205 section->Keys = key;
208 static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
209 LPSTR Default, LPSTR ReturnedString, short Size,
210 LPSTR FileName)
213 TProfile *New;
214 TSecHeader *section;
215 TKeys *key;
217 /* Supposedly Default should NEVER be NULL. But sometimes it is. */
218 if (Default == NULL)
219 Default = "";
221 if (!(section = is_loaded (FileName))){
222 New = (TProfile *) xmalloc (sizeof (TProfile));
223 New->link = Base;
224 New->FileName = strdup (FileName);
225 New->Section = load (FileName);
226 Base = New;
227 section = New->Section;
228 Current = New;
230 /* Start search */
231 for (; section; section = section->link){
232 if (strcasecmp (section->AppName, AppName))
233 continue;
235 /* If no key value given, then list all the keys */
236 if ((!KeyName) && (!set)){
237 char *p = ReturnedString;
238 int left = Size - 2;
239 int slen;
241 dprintf_profile(stddeb,"GetSetProfile // KeyName == NULL, Enumeration !\n");
242 for (key = section->Keys; key; key = key->link){
243 if (left < 1) {
244 dprintf_profile(stddeb,"GetSetProfile // No more storage for enum !\n");
245 return (Size - 2);
247 slen = min(strlen(key->KeyName) + 1, left);
248 dprintf_profile(stddeb,"GetSetProfile // strncpy(%p, %p, %d);\n",
249 ReturnedString, key->Value, slen);
250 strncpy (p, key->KeyName, slen);
251 dprintf_profile(stddeb,"GetSetProfile // enum '%s' !\n", p);
252 left -= slen;
253 p += slen;
255 *p = '\0';
256 #ifdef DEBUG_PROFILE
257 printf("GetSetProfile // normal end of enum !\n");
258 #endif
259 return (Size - 2 - left);
261 for (key = section->Keys; key; key = key->link){
262 if (strcasecmp (key->KeyName, KeyName))
263 continue;
264 if (set){
265 free (key->Value);
266 key->Value = strdup (Default ? Default : "");
267 return 1;
269 ReturnedString [Size-1] = 0;
270 strncpy (ReturnedString, key->Value, Size-1);
271 return 1;
273 /* If Getting the information, then don't write the information
274 to the INI file, need to run a couple of tests with windog */
275 /* No key found */
276 if (set)
277 new_key (section, KeyName, Default);
278 else {
279 ReturnedString [Size-1] = 0;
280 strncpy (ReturnedString, Default, Size-1);
282 return 1;
284 /* Non existent section */
285 if (set){
286 section = (TSecHeader *) xmalloc (sizeof (TSecHeader));
287 section->AppName = strdup (AppName);
288 section->Keys = 0;
289 new_key (section, KeyName, Default);
290 section->link = Current->Section;
291 Current->Section = section;
292 } else {
293 ReturnedString [Size-1] = 0;
294 strncpy (ReturnedString, Default, Size-1);
296 return 1;
299 short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
300 LPSTR Default, LPSTR ReturnedString,
301 short Size, LPSTR FileName)
303 int v;
305 dprintf_profile(stddeb,"GetPrivateProfileString ('%s', '%s', '%s', %p, %d, %s\n",
306 AppName, KeyName, Default, ReturnedString, Size, FileName);
307 v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
308 if (AppName)
309 return strlen (ReturnedString);
310 else
311 return Size - v;
314 int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default,
315 LPSTR ReturnedString, int Size)
317 return GetPrivateProfileString (AppName, KeyName, Default,
318 ReturnedString, Size, WIN_INI);
321 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
322 LPSTR File)
324 static char IntBuf [6];
325 static char buf [6];
327 sprintf (buf, "%d", Default);
329 /* Check the exact semantic with the SDK */
330 GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 6, File);
331 if (!strcasecmp (IntBuf, "true"))
332 return 1;
333 if (!strcasecmp (IntBuf, "yes"))
334 return 1;
335 return atoi (IntBuf);
338 WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
340 return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
343 BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
344 LPSTR FileName)
346 return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
349 BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String)
351 return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI));
354 static void dump_keys (FILE *profile, TKeys *p)
356 if (!p)
357 return;
358 dump_keys (profile, p->link);
359 fprintf (profile, "%s=%s\r\n", p->KeyName, p->Value);
362 static void dump_sections (FILE *profile, TSecHeader *p)
364 if (!p)
365 return;
366 dump_sections (profile, p->link);
367 fprintf (profile, "\r\n[%s]\r\n", p->AppName);
368 dump_keys (profile, p->Keys);
371 static void dump_profile (TProfile *p)
373 FILE *profile;
375 if (!p)
376 return;
377 dump_profile (p->link);
378 if ((profile = fopen (GetIniFileName(p->FileName), "w")) != NULL){
379 dump_sections (profile, p->Section);
380 fclose (profile);
384 void sync_profiles (void)
386 dump_profile (Base);