2 * Initialization-File Functions.
4 * From the Wine project
6 Copyright (C) 1993, 1994 Miguel de Icaza.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <stdlib.h> /* For free() and atoi() */
29 #include <sys/types.h>
35 #define INIFILE "xxx.ini"
37 #define overflow (next == &CharBuffer [STRSIZE-1])
39 enum { FirstBrace
, OnSecHeader
, IgnoreToEOL
, KeyDef
, KeyDefOnKey
, KeyValue
};
41 typedef struct TKeys
{
47 typedef struct TSecHeader
{
50 struct TSecHeader
*link
;
53 typedef struct TProfile
{
56 struct TProfile
*link
;
59 TProfile
*Current
= 0;
62 static int is_loaded (char *FileName
, TSecHeader
**section
)
67 if (!strcasecmp (FileName
, p
->FileName
)){
69 *section
= p
->Section
;
77 #define TRANSLATION_CHAR '\200'
79 char *str_untranslate_newline_dup (char *s
)
85 l
+= (*p
== '\n' || *p
== TRANSLATION_CHAR
);
88 q
= p
= malloc (l
+ 1);
94 *p
++ = TRANSLATION_CHAR
;
97 case TRANSLATION_CHAR
:
98 if (s
[1] == 'n' || s
[1] == TRANSLATION_CHAR
)
99 *p
++ = TRANSLATION_CHAR
;
100 *p
++ = TRANSLATION_CHAR
;
111 return 0; /* not reached */
114 char *str_translate_newline_dup (char *s
)
117 q
= p
= malloc (strlen (s
) + 1);
121 if (*s
== TRANSLATION_CHAR
) {
126 case TRANSLATION_CHAR
:
127 *p
++ = TRANSLATION_CHAR
;
130 *p
++ = TRANSLATION_CHAR
;
134 *p
++ = TRANSLATION_CHAR
;
143 return q
; /* not reached */
146 static TSecHeader
*load (char *file
)
150 TSecHeader
*SecHeader
= 0;
151 char CharBuffer
[STRSIZE
];
152 char *next
= ""; /* Not needed */
155 if ((f
= fopen (file
, "r"))==NULL
)
159 while ((c
= getc (f
)) != EOF
){
160 if (c
== '\r') /* Ignore Carriage Return */
166 if (c
== ']' || overflow
){
169 SecHeader
->AppName
= strdup (CharBuffer
);
189 SecHeader
= (TSecHeader
*) xmalloc (sizeof (TSecHeader
),
191 SecHeader
->link
= temp
;
197 if (state
== FirstBrace
) /* On first pass, don't allow dangling keys */
200 if ((c
== ' ' && state
!= KeyDefOnKey
) || c
== '\t')
203 if (c
== '\n' || overflow
) /* Abort Definition */
206 if (c
== '=' || overflow
){
209 temp
= SecHeader
->Keys
;
211 SecHeader
->Keys
= (TKeys
*) xmalloc (sizeof (TKeys
), "KD2");
212 SecHeader
->Keys
->link
= temp
;
213 SecHeader
->Keys
->KeyName
= strdup (CharBuffer
);
223 if (overflow
|| c
== '\n'){
225 SecHeader
->Keys
->Value
= str_translate_newline_dup (CharBuffer
);
226 state
= c
== '\n' ? KeyDef
: IgnoreToEOL
;
229 printf ("[%s] (%s)=%s\n", SecHeader
->AppName
,
230 SecHeader
->Keys
->KeyName
, SecHeader
->Keys
->Value
);
238 } /* while ((c = getc (f)) != EOF) */
239 if (c
== EOF
&& state
== KeyValue
){
241 SecHeader
->Keys
->Value
= str_translate_newline_dup (CharBuffer
);
247 static void new_key (TSecHeader
*section
, char *KeyName
, char *Value
)
251 key
= (TKeys
*) xmalloc (sizeof (TKeys
), "new_key");
252 key
->KeyName
= strdup (KeyName
);
253 key
->Value
= strdup (Value
);
254 key
->link
= section
->Keys
;
258 char *GetSetProfileChar (int set
, char *AppName
, char *KeyName
,
259 char *Default
, char *FileName
)
266 if (!is_loaded (FileName
, §ion
)){
267 New
= (TProfile
*) xmalloc (sizeof (TProfile
), "GetSetProfile");
269 New
->FileName
= strdup (FileName
);
270 New
->Section
= load (FileName
);
272 section
= New
->Section
;
277 for (; section
; section
= section
->link
){
278 if (section
->AppName
== 0 || strcasecmp (section
->AppName
, AppName
))
280 for (key
= section
->Keys
; key
; key
= key
->link
){
281 if (strcasecmp (key
->KeyName
, KeyName
))
285 key
->Value
= strdup (Default
);
289 /* If getting the information, then don't write the information
290 to the INI file, need to run a couple of tests with windog */
293 new_key (section
, KeyName
, Default
);
298 /* Non existent section */
300 section
= (TSecHeader
*) xmalloc (sizeof (TSecHeader
), "GSP3");
301 section
->AppName
= strdup (AppName
);
303 new_key (section
, KeyName
, Default
);
304 section
->link
= Current
->Section
;
305 Current
->Section
= section
;
310 short GetSetProfile (int set
, char * AppName
, char * KeyName
, char * Default
,
311 char * ReturnedString
, short Size
, char * FileName
)
316 s
= GetSetProfileChar (set
, AppName
, KeyName
, Default
, FileName
);
318 ReturnedString
[Size
-1] = 0;
319 strncpy (ReturnedString
, s
, Size
-1);
324 short GetPrivateProfileString (char * AppName
, char * KeyName
,
325 char * Default
, char * ReturnedString
,
326 short Size
, char * FileName
)
328 return (GetSetProfile (0, AppName
, KeyName
, Default
, ReturnedString
, Size
, FileName
));
331 char *get_profile_string (char *AppName
, char *KeyName
, char *Default
,
334 return GetSetProfileChar (0, AppName
, KeyName
, Default
, FileName
);
338 int GetProfileString (char * AppName
, char * KeyName
, char * Default
,
339 char * ReturnedString
, int Size
)
341 return GetPrivateProfileString (AppName
, KeyName
, Default
,
342 ReturnedString
, Size
, INIFILE
);
346 int GetPrivateProfileInt (char * AppName
, char * KeyName
, int Default
,
349 static char IntBuf
[15];
350 static char buf
[15];
352 sprintf (buf
, "%d", Default
);
354 /* Check the exact semantic with the SDK */
355 GetPrivateProfileString (AppName
, KeyName
, buf
, IntBuf
, 15, File
);
356 if (!strcasecmp (IntBuf
, "true"))
358 if (!strcasecmp (IntBuf
, "yes"))
360 return atoi (IntBuf
);
364 int GetProfileInt (char * AppName
, char * KeyName
, int Default
)
366 return GetPrivateProfileInt (AppName
, KeyName
, Default
, INIFILE
);
370 int WritePrivateProfileString (char * AppName
, char * KeyName
, char * String
,
373 return GetSetProfile (1, AppName
, KeyName
, String
, "", 0, FileName
);
377 int WriteProfileString (char * AppName
, char * KeyName
, char * String
)
379 return (WritePrivateProfileString (AppName
, KeyName
, String
, INIFILE
));
383 static void dump_keys (FILE * profile
, TKeys
* p
)
388 dump_keys (profile
, p
->link
);
389 t
= str_untranslate_newline_dup (p
->Value
);
390 fprintf (profile
, "%s=%s\n", p
->KeyName
, t
);
394 static void dump_sections (FILE *profile
, TSecHeader
*p
)
398 dump_sections (profile
, p
->link
);
400 fprintf (profile
, "\n[%s]\n", p
->AppName
);
401 dump_keys (profile
, p
->Keys
);
405 static void dump_profile (TProfile
*p
)
411 dump_profile (p
->link
);
412 /* .ado: p->FileName can be empty, it's better to jump over */
413 if (p
->FileName
[0] != (char) 0)
414 if ((profile
= fopen (p
->FileName
, "w")) != NULL
){
415 dump_sections (profile
, p
->Section
);
421 * Must be called at the end of wine run
424 void sync_profiles (void)
429 static void free_keys (TKeys
*p
)
439 static void free_sections (TSecHeader
*p
)
443 free_sections (p
->link
);
451 static void free_profile (TProfile
*p
)
455 free_profile (p
->link
);
456 free_sections (p
->Section
);
461 void free_profile_name (char *s
)
468 for (p
= Base
; p
; p
= p
->link
){
469 if (strcmp (s
, p
->FileName
) == 0){
470 free_sections (p
->Section
);
478 void free_profiles (void)
483 void *profile_init_iterator (char *appname
, char *file
)
488 if (!is_loaded (file
, §ion
)){
489 New
= (TProfile
*) xmalloc (sizeof (TProfile
), "GetSetProfile");
491 New
->FileName
= strdup (file
);
492 New
->Section
= load (file
);
494 section
= New
->Section
;
497 for (; section
; section
= section
->link
){
498 if (strcasecmp (section
->AppName
, appname
))
500 return section
->Keys
;
505 void *profile_iterator_next (void *s
, char **key
, char **value
)
507 TKeys
*keys
= (TKeys
*) s
;
510 *key
= keys
->KeyName
;
511 *value
= keys
->Value
;
517 void profile_clean_section (char *appname
, char *file
)
521 /* We assume the user has called one of the other initialization funcs */
522 if (!is_loaded (file
, §ion
)){
523 fprintf (stderr
,"Warning: profile_clean_section called before init\n");
526 /* We only disable the section, so it will still be freed, but it */
527 /* won't be find by further walks of the structure */
529 for (; section
; section
= section
->link
){
530 if (strcasecmp (section
->AppName
, appname
))
532 section
->AppName
[0] = 0;
536 int profile_has_section (char *section_name
, char *profile
)
540 /* We assume the user has called one of the other initialization funcs */
541 if (!is_loaded (profile
, §ion
)){
544 for (; section
; section
= section
->link
){
545 if (strcasecmp (section
->AppName
, section_name
))
552 void profile_forget_profile (char *file
)
556 for (p
= Base
; p
; p
= p
->link
){
557 if (strcasecmp (file
, p
->FileName
))