00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032 #include <sys/types.h>
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #define xmalloc(x, y) malloc (x)
00044 #include "profile.h"
00045
00046 #define INIFILE "win.ini"
00047 #define STRSIZE 255
00048 #define overflow (next == &CharBuffer [STRSIZE-1])
00049
00050 enum {
00051 FirstBrace, OnSecHeader, IgnoreToEOL, KeyDef, KeyValue, FirstChar
00052 };
00053
00054 typedef struct TKeys {
00055 char *KeyName;
00056 char *Value;
00057 struct TKeys *link;
00058 } TKeys;
00059
00060 typedef struct TSecHeader {
00061 char *AppName;
00062 TKeys *Keys;
00063 struct TSecHeader *link;
00064 } TSecHeader;
00065
00066 typedef struct TProfile {
00067 char *FileName;
00068 TSecHeader *Section;
00069 struct TProfile *link;
00070 } TProfile;
00071
00072 TProfile *Current = 0;
00073 TProfile *Base = 0;
00074
00075 static int
00076 is_loaded (char *FileName, TSecHeader ** section)
00077 {
00078 TProfile *p = Base;
00079
00080 while (p) {
00081 if (!strcasecmp (FileName, p->FileName)) {
00082 Current = p;
00083 *section = p->Section;
00084 return 1;
00085 }
00086 p = p->link;
00087 }
00088 return 0;
00089 }
00090
00091
00092
00093 static TSecHeader *
00094 load (char *file)
00095 {
00096 FILE *f;
00097 int state;
00098 TSecHeader *SecHeader = 0;
00099 char CharBuffer[STRSIZE];
00100 char *next = "";
00101 int c;
00102
00103 if ((f = fopen (file, "r")) == NULL)
00104 return NULL;
00105
00106 state = FirstBrace;
00107 while ((c = getc (f)) != EOF) {
00108 if (c == '\r')
00109 continue;
00110
00111 switch (state) {
00112
00113 case OnSecHeader:
00114 if (c == ']' || overflow) {
00115 *next = '\0';
00116 next = CharBuffer;
00117 SecHeader->AppName = strdup (CharBuffer);
00118 state = IgnoreToEOL;
00119 } else
00120 *next++ = c;
00121 break;
00122
00123 case IgnoreToEOL:
00124 if (c == '\n') {
00125 state = FirstChar;
00126 next = CharBuffer;
00127 }
00128 break;
00129
00130 case FirstBrace:
00131 case FirstChar:
00132 if (c == '#' || c == ';') {
00133 state = IgnoreToEOL;
00134 break;
00135 }
00136 case KeyDef:
00137 if (c == '[') {
00138 TSecHeader *temp;
00139
00140 temp = SecHeader;
00141 SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader),
00142 "KeyDef");
00143 SecHeader->link = temp;
00144 SecHeader->Keys = 0;
00145 state = OnSecHeader;
00146 next = CharBuffer;
00147 break;
00148 }
00149 if (state == FirstBrace)
00150 break;
00151
00152 if (state == FirstChar)
00153 state = KeyDef;
00154
00155 if (c == ' ' || c == '\t')
00156 break;
00157
00158 if (c == '\n' || overflow) {
00159 #ifdef DEBUG
00160 printf ("Abort %s (%s)\n", next, CharBuffer);
00161 #endif
00162 next = CharBuffer;
00163 break;
00164 }
00165 if (c == '=' || overflow) {
00166 TKeys *temp;
00167
00168 temp = SecHeader->Keys;
00169 *next = '\0';
00170 SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys), "KD2");
00171 SecHeader->Keys->link = temp;
00172 SecHeader->Keys->KeyName = strdup (CharBuffer);
00173 state = KeyValue;
00174 next = CharBuffer;
00175 } else
00176 *next++ = c;
00177 break;
00178
00179 case KeyValue:
00180 if (overflow || c == '\n') {
00181 *next = '\0';
00182 SecHeader->Keys->Value = strdup (CharBuffer);
00183 state = c == '\n' ? FirstChar : IgnoreToEOL;
00184 next = CharBuffer;
00185 #ifdef DEBUG
00186 printf ("[%s] (%s)=%s\n", SecHeader->AppName,
00187 SecHeader->Keys->KeyName, SecHeader->Keys->Value);
00188 #endif
00189 } else
00190 *next++ = c;
00191 break;
00192
00193 }
00194 #ifdef DEBUG
00195 printf ("%i Step %c [%s] (%s)\n", state, c, next, CharBuffer);
00196 #endif
00197 }
00198 return SecHeader;
00199 }
00200
00201 static void
00202 new_key (TSecHeader * section, char *KeyName, char *Value)
00203 {
00204 TKeys *key;
00205
00206 key = (TKeys *) xmalloc (sizeof (TKeys), "new_key");
00207 key->KeyName = strdup (KeyName);
00208 key->Value = strdup (Value);
00209 key->link = section->Keys;
00210 section->Keys = key;
00211 }
00212
00213 char *
00214 GetSetProfileChar (int set, char *AppName, char *KeyName,
00215 char *Default, char *FileName)
00216 {
00217
00218 TProfile *New;
00219 TSecHeader *section;
00220 TKeys *key;
00221
00222 if (!is_loaded (FileName, §ion)) {
00223 New = (TProfile *) xmalloc (sizeof (TProfile), "GetSetProfile");
00224 New->link = Base;
00225 New->FileName = strdup (FileName);
00226 New->Section = load (FileName);
00227 Base = New;
00228 section = New->Section;
00229 Current = New;
00230 }
00231
00232 for (; section; section = section->link) {
00233 if (strcasecmp (section->AppName, AppName))
00234 continue;
00235 for (key = section->Keys; key; key = key->link) {
00236 if (strcasecmp (key->KeyName, KeyName))
00237 continue;
00238 if (set) {
00239 free (key->Value);
00240 key->Value = strdup (Default);
00241 }
00242 return key->Value;
00243 }
00244
00245
00246
00247 if (set) {
00248 new_key (section, KeyName, Default);
00249 return 0;
00250 }
00251 }
00252
00253
00254 if (set) {
00255 section = (TSecHeader *) xmalloc (sizeof (TSecHeader), "GSP3");
00256 section->AppName = strdup (AppName);
00257 section->Keys = 0;
00258 new_key (section, KeyName, Default);
00259 section->link = Current->Section;
00260 Current->Section = section;
00261 }
00262 return Default;
00263 }
00264
00265 short
00266 GetSetProfile (int set, char *AppName, char *KeyName, char *Default,
00267 char *ReturnedString, short Size, char *FileName)
00268 {
00269 char *s;
00270
00271 s = GetSetProfileChar (set, AppName, KeyName, Default, FileName);
00272 if (!set) {
00273 ReturnedString[Size - 1] = 0;
00274 strncpy (ReturnedString, s, Size - 1);
00275 }
00276 return 1;
00277 }
00278
00279 short
00280 GetPrivateProfileString (char *AppName, char *KeyName,
00281 char *Default, char *ReturnedString,
00282 short Size, char *FileName)
00283 {
00284 return (GetSetProfile (0, AppName, KeyName, Default, ReturnedString, Size, FileName));
00285 }
00286
00287 char *
00288 get_profile_string (char *AppName, char *KeyName, char *Default,
00289 char *FileName)
00290 {
00291 return GetSetProfileChar (0, AppName, KeyName, Default, FileName);
00292 }
00293
00294 int
00295 GetProfileString (char *AppName, char *KeyName, char *Default,
00296 char *ReturnedString, int Size)
00297 {
00298 return GetPrivateProfileString (AppName, KeyName, Default,
00299 ReturnedString, Size, INIFILE);
00300 }
00301
00302 int
00303 GetPrivateProfileInt (char *AppName, char *KeyName, short Default,
00304 char *File)
00305 {
00306 static char IntBuf[10];
00307 static char buf[10];
00308
00309 sprintf (buf, "%d", Default);
00310
00311
00312 GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 5, File);
00313 if (!strcasecmp (IntBuf, "true"))
00314 return 1;
00315 if (!strcasecmp (IntBuf, "yes"))
00316 return 1;
00317 return atoi (IntBuf);
00318 }
00319
00320 int
00321 GetProfileInt (char *AppName, char *KeyName, int Default)
00322 {
00323 return GetPrivateProfileInt (AppName, KeyName, Default, INIFILE);
00324 }
00325
00326 int
00327 WritePrivateProfileString (char *AppName, char *KeyName, char *String,
00328 char *FileName)
00329 {
00330 return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
00331 }
00332
00333 int
00334 WriteProfileString (char *AppName, char *KeyName, char *String)
00335 {
00336 return (WritePrivateProfileString (AppName, KeyName, String, INIFILE));
00337 }
00338
00339 static void
00340 dump_keys (FILE * profile, TKeys * p)
00341 {
00342 if (!p)
00343 return;
00344 dump_keys (profile, p->link);
00345 fprintf (profile, "%s=%s\n", p->KeyName, p->Value);
00346 }
00347
00348 static void
00349 dump_sections (FILE * profile, TSecHeader * p)
00350 {
00351 if (!p)
00352 return;
00353 dump_sections (profile, p->link);
00354 if (p->AppName[0]) {
00355 fprintf (profile, "\n[%s]\n", p->AppName);
00356 dump_keys (profile, p->Keys);
00357 }
00358 }
00359
00360 static void
00361 dump_profile (TProfile * p)
00362 {
00363 FILE *profile;
00364
00365 if (!p)
00366 return;
00367 dump_profile (p->link);
00368 if ((profile = fopen (p->FileName, "w")) != NULL) {
00369 dump_sections (profile, p->Section);
00370 fclose (profile);
00371 }
00372 }
00373
00374
00375
00376
00377
00378 void
00379 sync_profiles (void)
00380 {
00381 dump_profile (Base);
00382 }
00383
00384 static void
00385 free_keys (TKeys * p)
00386 {
00387 if (!p)
00388 return;
00389 free_keys (p->link);
00390 free (p->KeyName);
00391 free (p->Value);
00392 free (p);
00393 }
00394
00395 static void
00396 free_sections (TSecHeader * p)
00397 {
00398 if (!p)
00399 return;
00400 free_sections (p->link);
00401 free_keys (p->Keys);
00402 free (p->AppName);
00403 p->link = 0;
00404 p->Keys = 0;
00405 free (p);
00406 }
00407
00408 static void
00409 free_profile (TProfile * p)
00410 {
00411 if (!p)
00412 return;
00413 free_profile (p->link);
00414 free_sections (p->Section);
00415 free (p->FileName);
00416 free (p);
00417 }
00418
00419 void
00420 free_profiles (void)
00421 {
00422 free_profile (Base);
00423 }
00424
00425 void *
00426 profile_init_iterator (char *appname, char *file)
00427 {
00428 TProfile *New;
00429 TSecHeader *section;
00430
00431 if (!is_loaded (file, §ion)) {
00432 New = (TProfile *) xmalloc (sizeof (TProfile), "GetSetProfile");
00433 New->link = Base;
00434 New->FileName = strdup (file);
00435 New->Section = load (file);
00436 Base = New;
00437 section = New->Section;
00438 Current = New;
00439 }
00440 for (; section; section = section->link) {
00441 if (strcasecmp (section->AppName, appname))
00442 continue;
00443 return section->Keys;
00444 }
00445 return 0;
00446 }
00447
00448 void *
00449 profile_iterator_next (void *s, char **key, char **value)
00450 {
00451 TKeys *keys = (TKeys *) s;
00452
00453 if (keys) {
00454 *key = keys->KeyName;
00455 *value = keys->Value;
00456 keys = keys->link;
00457 }
00458 return keys;
00459 }
00460
00461 void
00462 profile_clean_section (char *appname, char *file)
00463 {
00464 TSecHeader *section;
00465
00466
00467 if (!is_loaded (file, §ion)) {
00468 fprintf (stderr, "Warning: profile_clean_section called before init\n");
00469 return;
00470 }
00471
00472
00473
00474 for (; section; section = section->link) {
00475 if (strcasecmp (section->AppName, appname))
00476 continue;
00477 section->AppName[0] = 0;
00478 }
00479 }