Release 940804
[wine/gsoc-2012-control.git] / misc / profile.c
blob7bd94881d6c52d610808a0636de05c7faa535e50
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"
29 /* #define DEBUG */
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 } TProfile;
55 TProfile *Current = 0;
56 TProfile *Base = 0;
58 static TSecHeader *is_loaded (char *FileName)
60 TProfile *p = Base;
62 while (p){
63 if (!strcasecmp (FileName, p->FileName)){
64 Current = p;
65 return p->Section;
67 p = p->link;
69 return 0;
72 static char *GetIniFileName(char *name)
74 char temp[256];
76 if (strchr(name, '/'))
77 return name;
79 if (strchr(name, '\\'))
80 return GetUnixFileName(name);
82 GetWindowsDirectory(temp, sizeof(temp) );
83 strcat(temp, "\\");
84 strcat(temp, name);
86 return GetUnixFileName(temp);
89 static TSecHeader *load (char *filename)
91 FILE *f;
92 int state;
93 TSecHeader *SecHeader = 0;
94 char CharBuffer [STRSIZE];
95 char *next, *file;
96 char c;
98 file = GetIniFileName(filename);
100 #ifdef DEBUG
101 printf("Load %s\n", file);
102 #endif
103 if ((f = fopen (file, "r"))==NULL)
104 return NULL;
106 #ifdef DEBUG
107 printf("Loading %s\n", file);
108 #endif
111 state = FirstBrace;
112 while ((c = getc (f)) != EOF){
113 if (c == '\r') /* Ignore Carriage Return */
114 continue;
116 switch (state){
118 case OnSecHeader:
119 if (c == ']' || overflow){
120 *next = '\0';
121 next = CharBuffer;
122 SecHeader->AppName = strdup (CharBuffer);
123 state = IgnoreToEOL;
124 #ifdef DEBUG
125 printf("%s: section %s\n", file, CharBuffer);
126 #endif
127 } else
128 *next++ = c;
129 break;
131 case IgnoreToEOL:
132 if (c == '\n'){
133 state = KeyDef;
134 next = CharBuffer;
136 break;
138 case FirstBrace:
139 case KeyDef:
140 if (c == '['){
141 TSecHeader *temp;
143 temp = SecHeader;
144 SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader));
145 SecHeader->link = temp;
146 SecHeader->Keys = 0;
147 state = OnSecHeader;
148 next = CharBuffer;
149 break;
151 if (state == FirstBrace) /* On first pass, don't allow dangling keys */
152 break;
154 if (c == ' ' || c == '\t')
155 break;
157 if (c == '\n' || c == ';' || overflow) /* Abort Definition */
158 next = CharBuffer;
160 if (c == ';')
162 state = IgnoreToEOL;
163 break;
166 if (c == '=' || overflow){
167 TKeys *temp;
169 temp = SecHeader->Keys;
170 *next = '\0';
171 SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys));
172 SecHeader->Keys->link = temp;
173 SecHeader->Keys->KeyName = strdup (CharBuffer);
174 state = KeyValue;
175 next = CharBuffer;
176 #ifdef DEBUG
177 printf("%s: key %s\n", file, CharBuffer);
178 #endif
179 } else
180 *next++ = c;
181 break;
183 case KeyValue:
184 if (overflow || c == '\n'){
185 *next = '\0';
186 SecHeader->Keys->Value = strdup (CharBuffer);
187 state = c == '\n' ? KeyDef : IgnoreToEOL;
188 next = CharBuffer;
189 #ifdef DEBUG
190 printf ("[%s] (%s)=%s\n", SecHeader->AppName,
191 SecHeader->Keys->KeyName, SecHeader->Keys->Value);
192 #endif
193 } else
194 *next++ = c;
195 break;
197 } /* switch */
199 } /* while ((c = getc (f)) != EOF) */
200 return SecHeader;
203 static void new_key (TSecHeader *section, char *KeyName, char *Value)
205 TKeys *key;
207 key = (TKeys *) xmalloc (sizeof (TKeys));
208 key->KeyName = strdup (KeyName);
209 key->Value = strdup (Value);
210 key->link = section->Keys;
211 section->Keys = key;
214 static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
215 LPSTR Default, LPSTR ReturnedString, short Size,
216 LPSTR FileName)
219 TProfile *New;
220 TSecHeader *section;
221 TKeys *key;
223 /* Supposedly Default should NEVER be NULL. But sometimes it is. */
224 if (Default == NULL)
225 Default = "";
227 if (!(section = is_loaded (FileName))){
228 New = (TProfile *) xmalloc (sizeof (TProfile));
229 New->link = Base;
230 New->FileName = strdup (FileName);
231 New->Section = load (FileName);
232 Base = New;
233 section = New->Section;
234 Current = New;
236 /* Start search */
237 for (; section; section = section->link){
238 if (strcasecmp (section->AppName, AppName))
239 continue;
241 /* If no key value given, then list all the keys */
242 if ((!KeyName) && (!set)){
243 char *p = ReturnedString;
244 int left = Size - 2;
245 int slen;
246 #ifdef DEBUG_PROFILE
247 printf("GetSetProfile // KeyName == NULL, Enumeration !\n");
248 #endif
249 for (key = section->Keys; key; key = key->link){
250 if (left < 1) {
251 printf("GetSetProfile // No more storage for enum !\n");
252 return (Size - 2);
254 slen = min(strlen(key->KeyName) + 1, left);
255 #ifdef DEBUG_PROFILE
256 printf("GetSetProfile // strncpy(%08X, %08X, %d);\n",
257 ReturnedString, key->Value, slen);
258 #endif
259 strncpy (p, key->KeyName, slen);
260 #ifdef DEBUG_PROFILE
261 printf("GetSetProfile // enum '%s' !\n", p);
262 #endif
263 left -= slen;
264 p += slen;
266 *p = '\0';
267 printf("GetSetProfile // normal end of enum !\n");
268 return (Size - 2 - left);
270 for (key = section->Keys; key; key = key->link){
271 if (strcasecmp (key->KeyName, KeyName))
272 continue;
273 if (set){
274 free (key->Value);
275 key->Value = strdup (Default ? Default : "");
276 return 1;
278 ReturnedString [Size-1] = 0;
279 strncpy (ReturnedString, key->Value, Size-1);
280 return 1;
282 /* If Getting the information, then don't write the information
283 to the INI file, need to run a couple of tests with windog */
284 /* No key found */
285 if (set)
286 new_key (section, KeyName, Default);
287 else {
288 ReturnedString [Size-1] = 0;
289 strncpy (ReturnedString, Default, Size-1);
291 return 1;
293 /* Non existent section */
294 if (set){
295 section = (TSecHeader *) xmalloc (sizeof (TSecHeader));
296 section->AppName = strdup (AppName);
297 section->Keys = 0;
298 new_key (section, KeyName, Default);
299 section->link = Current->Section;
300 Current->Section = section;
301 } else {
302 ReturnedString [Size-1] = 0;
303 strncpy (ReturnedString, Default, Size-1);
305 return 1;
308 short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
309 LPSTR Default, LPSTR ReturnedString,
310 short Size, LPSTR FileName)
312 int v;
314 #ifdef DEBUG_PROFILE
315 printf("GetPrivateProfileString ('%s', '%s', '%s', %08X, %d, %s\n",
316 AppName, KeyName, Default, ReturnedString, Size, FileName);
317 #endif
318 v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
319 if (AppName)
320 return strlen (ReturnedString);
321 else
322 return Size - v;
325 int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default,
326 LPSTR ReturnedString, int Size)
328 return GetPrivateProfileString (AppName, KeyName, Default,
329 ReturnedString, Size, WIN_INI);
332 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
333 LPSTR File)
335 static char IntBuf [6];
336 static char buf [6];
338 sprintf (buf, "%d", Default);
340 /* Check the exact semantic with the SDK */
341 GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 6, File);
342 if (!strcasecmp (IntBuf, "true"))
343 return 1;
344 if (!strcasecmp (IntBuf, "yes"))
345 return 1;
346 return atoi (IntBuf);
349 WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
351 return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
354 BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
355 LPSTR FileName)
357 return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
360 BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String)
362 return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI));
365 static void dump_keys (FILE *profile, TKeys *p)
367 if (!p)
368 return;
369 dump_keys (profile, p->link);
370 fprintf (profile, "%s=%s\r\n", p->KeyName, p->Value);
373 static void dump_sections (FILE *profile, TSecHeader *p)
375 if (!p)
376 return;
377 dump_sections (profile, p->link);
378 fprintf (profile, "\r\n[%s]\r\n", p->AppName);
379 dump_keys (profile, p->Keys);
382 static void dump_profile (TProfile *p)
384 FILE *profile;
386 if (!p)
387 return;
388 dump_profile (p->link);
389 if ((profile = fopen (GetIniFileName(p->FileName), "w")) != NULL){
390 dump_sections (profile, p->Section);
391 fclose (profile);
395 void sync_profiles (void)
397 dump_profile (Base);