Release 940405
[wine/gsoc-2012-control.git] / misc / profile.c
blob377924ade21c7beb741ca701bc761a4195ecfd79
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
14 static char Copyright [] = "Copyright (C) 1993 Miguel de Icaza";
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
20 #include "wine.h"
21 #include "windows.h"
22 #include "prototypes.h"
24 /* #define DEBUG */
26 #define STRSIZE 255
27 #define xmalloc(x) malloc(x)
28 #define overflow (next == &CharBuffer [STRSIZE-1])
30 enum { FirstBrace, OnSecHeader, IgnoreToEOL, KeyDef, KeyValue };
32 typedef struct TKeys {
33 char *KeyName;
34 char *Value;
35 struct TKeys *link;
36 } TKeys;
38 typedef struct TSecHeader {
39 char *AppName;
40 TKeys *Keys;
41 struct TSecHeader *link;
42 } TSecHeader;
44 typedef struct TProfile {
45 char *FileName;
46 TSecHeader *Section;
47 struct TProfile *link;
48 } TProfile;
50 TProfile *Current = 0;
51 TProfile *Base = 0;
53 static TSecHeader *is_loaded (char *FileName)
55 TProfile *p = Base;
57 while (p){
58 if (!strcasecmp (FileName, p->FileName)){
59 Current = p;
60 return p->Section;
62 p = p->link;
64 return 0;
67 static TSecHeader *load (char *file)
69 FILE *f;
70 int state;
71 TSecHeader *SecHeader = 0;
72 char CharBuffer [STRSIZE];
73 char *next;
74 char c;
76 #ifdef DEBUG
77 printf("Load %s\n", file);
78 #endif
79 if ((f = fopen (file, "r"))==NULL)
80 return NULL;
82 #ifdef DEBUG
83 printf("Loading %s\n", file);
84 #endif
85 state = FirstBrace;
86 while ((c = getc (f)) != EOF){
87 if (c == '\r') /* Ignore Carriage Return */
88 continue;
90 switch (state){
92 case OnSecHeader:
93 if (c == ']' || overflow){
94 *next = '\0';
95 next = CharBuffer;
96 SecHeader->AppName = strdup (CharBuffer);
97 state = IgnoreToEOL;
98 #ifdef DEBUG
99 printf("%s: section %s\n", file, CharBuffer);
100 #endif
101 } else
102 *next++ = c;
103 break;
105 case IgnoreToEOL:
106 if (c == '\n'){
107 state = KeyDef;
108 next = CharBuffer;
110 break;
112 case FirstBrace:
113 case KeyDef:
114 if (c == '['){
115 TSecHeader *temp;
117 temp = SecHeader;
118 SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader));
119 SecHeader->link = temp;
120 SecHeader->Keys = 0;
121 state = OnSecHeader;
122 next = CharBuffer;
123 break;
125 if (state == FirstBrace) /* On first pass, don't allow dangling keys */
126 break;
128 if (c == ' ' || c == '\t')
129 break;
131 if (c == '\n' || c == ';' || overflow) /* Abort Definition */
132 next = CharBuffer;
134 if (c == ';')
136 state = IgnoreToEOL;
137 break;
140 if (c == '=' || overflow){
141 TKeys *temp;
143 temp = SecHeader->Keys;
144 *next = '\0';
145 SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys));
146 SecHeader->Keys->link = temp;
147 SecHeader->Keys->KeyName = strdup (CharBuffer);
148 state = KeyValue;
149 next = CharBuffer;
150 #ifdef DEBUG
151 printf("%s: key %s\n", file, CharBuffer);
152 #endif
153 } else
154 *next++ = c;
155 break;
157 case KeyValue:
158 if (overflow || c == '\n'){
159 *next = '\0';
160 SecHeader->Keys->Value = strdup (CharBuffer);
161 state = c == '\n' ? KeyDef : IgnoreToEOL;
162 next = CharBuffer;
163 #ifdef DEBUG
164 printf ("[%s] (%s)=%s\n", SecHeader->AppName,
165 SecHeader->Keys->KeyName, SecHeader->Keys->Value);
166 #endif
167 } else
168 *next++ = c;
169 break;
171 } /* switch */
173 } /* while ((c = getc (f)) != EOF) */
174 return SecHeader;
177 static void new_key (TSecHeader *section, char *KeyName, char *Value)
179 TKeys *key;
181 key = (TKeys *) xmalloc (sizeof (TKeys));
182 key->KeyName = strdup (KeyName);
183 key->Value = strdup (Value);
184 key->link = section->Keys;
185 section->Keys = key;
188 static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
189 LPSTR Default, LPSTR ReturnedString, short Size,
190 LPSTR FileName)
193 TProfile *New;
194 TSecHeader *section;
195 TKeys *key;
197 if (!(section = is_loaded (FileName))){
198 New = (TProfile *) xmalloc (sizeof (TProfile));
199 New->link = Base;
200 New->FileName = strdup (FileName);
201 New->Section = load (FileName);
202 Base = New;
203 section = New->Section;
204 Current = New;
206 /* Start search */
207 for (; section; section = section->link){
208 if (strcasecmp (section->AppName, AppName))
209 continue;
211 /* If no key value given, then list all the keys */
212 if ((!AppName) && (!set)){
213 char *p = ReturnedString;
214 int left = Size - 1;
215 int slen;
217 for (key = section->Keys; key; key = key->link){
218 strncpy (p, key->KeyName, left);
219 slen = strlen (key->KeyName) + 1;
220 left -= slen+1;
221 p += slen;
223 return left;
225 for (key = section->Keys; key; key = key->link){
226 if (strcasecmp (key->KeyName, KeyName))
227 continue;
228 if (set){
229 free (key->Value);
230 key->Value = strdup (Default ? Default : "");
231 return 1;
233 ReturnedString [Size-1] = 0;
234 strncpy (ReturnedString, key->Value, Size-1);
235 return 1;
237 /* If Getting the information, then don't write the information
238 to the INI file, need to run a couple of tests with windog */
239 /* No key found */
240 if (set)
241 new_key (section, KeyName, Default);
242 else {
243 ReturnedString [Size-1] = 0;
244 strncpy (ReturnedString, Default, Size-1);
246 return 1;
248 /* Non existent section */
249 if (set){
250 section = (TSecHeader *) xmalloc (sizeof (TSecHeader));
251 section->AppName = strdup (AppName);
252 section->Keys = 0;
253 new_key (section, KeyName, Default);
254 section->link = Current->Section;
255 Current->Section = section;
256 } else {
257 ReturnedString [Size-1] = 0;
258 strncpy (ReturnedString, Default, Size-1);
260 return 1;
263 short GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
264 LPSTR Default, LPSTR ReturnedString,
265 short Size, LPSTR FileName)
267 int v;
269 v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
270 if (AppName)
271 return strlen (ReturnedString);
272 else
273 return Size - v;
276 int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default,
277 LPSTR ReturnedString, int Size)
279 return GetPrivateProfileString (AppName, KeyName, Default,
280 ReturnedString, Size, WIN_INI);
283 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
284 LPSTR File)
286 static char IntBuf [5];
287 static char buf [5];
289 sprintf (buf, "%d", Default);
291 /* Check the exact semantic with the SDK */
292 GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 5, File);
293 if (!strcasecmp (IntBuf, "true"))
294 return 1;
295 if (!strcasecmp (IntBuf, "yes"))
296 return 1;
297 return atoi (IntBuf);
300 WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
302 return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
305 BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
306 LPSTR FileName)
308 return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
311 BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String)
313 return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI));
316 static void dump_keys (FILE *profile, TKeys *p)
318 if (!p)
319 return;
320 dump_keys (profile, p->link);
321 fprintf (profile, "%s=%s\r\n", p->KeyName, p->Value);
324 static void dump_sections (FILE *profile, TSecHeader *p)
326 if (!p)
327 return;
328 dump_sections (profile, p->link);
329 fprintf (profile, "\r\n[%s]\r\n", p->AppName);
330 dump_keys (profile, p->Keys);
333 static void dump_profile (TProfile *p)
335 FILE *profile;
337 if (!p)
338 return;
339 dump_profile (p->link);
340 if ((profile = fopen (p->FileName, "w")) != NULL){
341 dump_sections (profile, p->Section);
342 fclose (profile);
346 void sync_profiles ()
348 dump_profile (Base);