Release 960928
[wine/multimedia.git] / files / profile.c
blob4570b5e510fcfa12c1e8e488fa12a5ed1e244f78
1 /*
2 * Profile functions
4 * Copyright 1993 Miguel de Icaza
5 * Copyright 1996 Alexandre Julliard
6 */
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #include "dos_fs.h"
14 #include "windows.h"
15 #include "xmalloc.h"
16 #include "stddebug.h"
17 #include "debug.h"
19 typedef struct tagPROFILEKEY
21 char *name;
22 char *value;
23 struct tagPROFILEKEY *next;
24 } PROFILEKEY;
26 typedef struct tagPROFILESECTION
28 char *name;
29 struct tagPROFILEKEY *key;
30 struct tagPROFILESECTION *next;
31 } PROFILESECTION;
34 typedef struct
36 int changed;
37 PROFILESECTION *section;
38 char *dos_name;
39 } PROFILE;
42 /* Cached profile file */
43 static PROFILE CurProfile = { FALSE, NULL, NULL };
45 /* wine.ini profile content */
46 static PROFILESECTION *WineProfile;
48 #define PROFILE_MAX_LINE_LEN 1024
50 /* Wine profile name in $HOME directory; must begin with slash */
51 static const char PROFILE_WineIniName[] = "/.winerc";
53 /* Check for comments in profile */
54 #define IS_ENTRY_COMMENT(str) ((str)[0] == ';')
56 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
58 /***********************************************************************
59 * PROFILE_CopyEntry
61 * Copy the content of an entry into a buffer, removing quotes, and possibly
62 * translating environment variables.
64 static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
65 int handle_env )
67 char quote = '\0';
68 const char *p;
70 if ((*value == '\'') || (*value == '\"'))
72 if (value[1] && (value[strlen(value)-1] == *value)) quote = *value++;
75 if (!handle_env)
77 lstrcpyn32A( buffer, value, len );
78 if (quote && (len >= strlen(value))) buffer[strlen(buffer)-1] = '\0';
79 return;
82 for (p = value; (*p && (len > 1)); *buffer++ = *p++, len-- )
84 if ((*p == '$') && (p[1] == '{'))
86 char env_val[1024];
87 const char *env_p;
88 const char *p2 = strchr( p, '}' );
89 if (!p2) continue; /* ignore it */
90 lstrcpyn32A(env_val, p + 2, MIN( sizeof(env_val), (int)(p2-p)-1 ));
91 if ((env_p = getenv( env_val )) != NULL)
93 lstrcpyn32A( buffer, env_p, len );
94 buffer += strlen( buffer );
95 len -= strlen( buffer );
97 p = p2 + 1;
100 *buffer = '\0';
104 /***********************************************************************
105 * PROFILE_Save
107 * Save a profile tree to a file.
109 static void PROFILE_Save( FILE *file, PROFILESECTION *section )
111 PROFILEKEY *key;
113 for ( ; section; section = section->next)
115 if (section->name) fprintf( file, "[%s]\r\n", section->name );
116 for (key = section->key; key; key = key->next)
118 fprintf( file, "%s", key->name );
119 if (key->value) fprintf( file, "=%s", key->value );
120 fprintf( file, "\r\n" );
126 /***********************************************************************
127 * PROFILE_Free
129 * Free a profile tree.
131 static void PROFILE_Free( PROFILESECTION *section )
133 PROFILESECTION *next_section;
134 PROFILEKEY *key, *next_key;
136 for ( ; section; section = next_section)
138 if (section->name) free( section->name );
139 for (key = section->key; key; key = next_key)
141 next_key = key->next;
142 if (key->name) free( key->name );
143 if (key->value) free( key->value );
144 free( key );
146 next_section = section->next;
147 free( section );
152 /***********************************************************************
153 * PROFILE_Load
155 * Load a profile tree from a file.
157 static PROFILESECTION *PROFILE_Load( FILE *file )
159 char buffer[PROFILE_MAX_LINE_LEN];
160 char *p, *p2;
161 int line = 0;
162 PROFILESECTION *section, *first_section;
163 PROFILESECTION **prev_section;
164 PROFILEKEY *key, **prev_key;
166 first_section = (PROFILESECTION *)xmalloc( sizeof(*section) );
167 first_section->name = NULL;
168 first_section->key = NULL;
169 first_section->next = NULL;
170 prev_section = &first_section->next;
171 prev_key = &first_section->key;
173 while (fgets( buffer, PROFILE_MAX_LINE_LEN, file ))
175 line++;
176 p = buffer + strlen(buffer) - 1;
177 while ((p > buffer) && ((*p == '\n') || isspace(*p))) *p-- = '\0';
178 p = buffer;
179 while (*p && isspace(*p)) p++;
180 if (*p == '[') /* section start */
182 if (!(p2 = strrchr( p, ']' )))
184 fprintf( stderr, "PROFILE_Load: Invalid section header at line %d: '%s'\n",
185 line, p );
187 else
189 *p2 = '\0';
190 p++;
191 section = (PROFILESECTION *)xmalloc( sizeof(*section));
192 section->name = xstrdup( p );
193 section->key = NULL;
194 section->next = NULL;
195 *prev_section = section;
196 prev_section = &section->next;
197 prev_key = &section->key;
198 continue;
201 if ((p2 = strchr( p, '=' )) != NULL)
203 char *p3 = p2 - 1;
204 while ((p3 > p) && isspace(*p3)) *p3-- = '\0';
205 *p2++ = '\0';
206 while (*p2 && isspace(*p2)) p2++;
208 key = (PROFILEKEY *)xmalloc( sizeof(*key) );
209 key->name = xstrdup( p );
210 key->value = p2 ? xstrdup( p2 ) : NULL;
211 key->next = NULL;
212 *prev_key = key;
213 prev_key = &key->next;
215 if (debugging_profile)
217 fprintf( stddeb, "PROFILE_Load:\n" );
218 PROFILE_Save( stddeb, first_section );
219 fprintf( stddeb, "PROFILE_Load finished.\n" );
221 return first_section;
225 /***********************************************************************
226 * PROFILE_DeleteSection
228 * Delete a section from a profile tree.
230 static BOOL PROFILE_DeleteSection( PROFILESECTION **section, const char *name )
232 while (*section)
234 if ((*section)->name && !lstrcmpi32A( (*section)->name, name ))
236 PROFILESECTION *to_del = *section;
237 *section = to_del->next;
238 to_del->next = NULL;
239 PROFILE_Free( to_del );
240 return TRUE;
242 section = &(*section)->next;
244 return FALSE;
248 /***********************************************************************
249 * PROFILE_DeleteKey
251 * Delete a key from a profile tree.
253 static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
254 const char *section_name, const char *key_name )
256 while (*section)
258 if ((*section)->name && !lstrcmpi32A( (*section)->name, section_name ))
260 PROFILEKEY **key = &(*section)->key;
261 while (*key)
263 if (!lstrcmpi32A( (*key)->name, key_name ))
265 PROFILEKEY *to_del = *key;
266 *key = to_del->next;
267 if (to_del->name) free( to_del->name );
268 if (to_del->value) free( to_del->value );
269 free( to_del );
270 return TRUE;
272 key = &(*key)->next;
275 section = &(*section)->next;
277 return FALSE;
281 /***********************************************************************
282 * PROFILE_Find
284 * Find a key in a profile tree, optionally creating it.
286 static PROFILEKEY *PROFILE_Find( PROFILESECTION **section,
287 const char *section_name,
288 const char *key_name, int create )
290 while (*section)
292 if ((*section)->name && !lstrcmpi32A( (*section)->name, section_name ))
294 PROFILEKEY **key = &(*section)->key;
295 while (*key)
297 if (!lstrcmpi32A( (*key)->name, key_name )) return *key;
298 key = &(*key)->next;
300 if (!create) return NULL;
301 *key = (PROFILEKEY *)xmalloc( sizeof(PROFILEKEY) );
302 (*key)->name = xstrdup( key_name );
303 (*key)->value = NULL;
304 (*key)->next = NULL;
305 return *key;
307 section = &(*section)->next;
309 if (!create) return NULL;
310 *section = (PROFILESECTION *)xmalloc( sizeof(PROFILESECTION) );
311 (*section)->name = xstrdup(section_name);
312 (*section)->next = NULL;
313 (*section)->key = (PROFILEKEY *)xmalloc( sizeof(PROFILEKEY) );
314 (*section)->key->name = xstrdup( key_name );
315 (*section)->key->value = NULL;
316 (*section)->key->next = NULL;
317 return (*section)->key;
321 /***********************************************************************
322 * PROFILE_FlushFile
324 * Flush the current profile to disk if changed.
326 static BOOL PROFILE_FlushFile(void)
328 char *p, buffer[MAX_PATHNAME_LEN];
329 const char *unix_name;
330 FILE *file = NULL;
332 if (!CurProfile.changed || !CurProfile.dos_name) return TRUE;
333 if (!(unix_name = DOSFS_GetUnixFileName( CurProfile.dos_name, FALSE )) ||
334 !(file = fopen( unix_name, "w" )))
336 /* Try to create it in $HOME/.wine */
337 /* FIXME: this will need a more general solution */
338 if ((p = getenv( "HOME" )) != NULL)
340 strcpy( buffer, p );
341 strcat( buffer, "/.wine/" );
342 p = buffer + strlen(buffer);
343 strcpy( p, strrchr( CurProfile.dos_name, '\\' ) + 1 );
344 AnsiLower( p );
345 file = fopen( buffer, "w" );
346 unix_name = buffer;
350 if (!file)
352 fprintf( stderr, "Warning: could not save profile file %s\n",
353 CurProfile.dos_name );
354 return FALSE;
357 dprintf_profile( stddeb, "Saving '%s' into '%s'\n",
358 CurProfile.dos_name, unix_name );
359 PROFILE_Save( file, CurProfile.section );
360 fclose( file );
361 CurProfile.changed = FALSE;
362 return TRUE;
366 /***********************************************************************
367 * PROFILE_Open
369 * Open a profile file, checking the cached file first.
371 static BOOL PROFILE_Open( const char *filename )
373 char buffer[MAX_PATHNAME_LEN];
374 const char *dos_name, *unix_name;
375 char *newdos_name, *p;
376 FILE *file = NULL;
378 if (strchr( filename, '/' ) || strchr( filename, '\\' ) ||
379 strchr( filename, ':' ))
381 if (!(dos_name = DOSFS_GetDosTrueName( filename, FALSE))) return FALSE;
383 else
385 GetWindowsDirectory32A( buffer, sizeof(buffer) );
386 strcat( buffer, "\\" );
387 strcat( buffer, filename );
388 if (!(dos_name = DOSFS_GetDosTrueName( buffer, FALSE ))) return FALSE;
390 if (CurProfile.dos_name && !strcmp( dos_name, CurProfile.dos_name ))
392 dprintf_profile( stddeb, "PROFILE_Open(%s): already opened\n",
393 filename );
394 return TRUE;
397 /* Flush the previous profile */
399 newdos_name = xstrdup( dos_name );
400 PROFILE_FlushFile();
401 PROFILE_Free( CurProfile.section );
402 if (CurProfile.dos_name) free( CurProfile.dos_name );
403 CurProfile.section = NULL;
404 CurProfile.dos_name = newdos_name;
406 /* Try to open the profile file, first in $HOME/.wine */
408 /* FIXME: this will need a more general solution */
409 if ((p = getenv( "HOME" )) != NULL)
411 strcpy( buffer, p );
412 strcat( buffer, "/.wine/" );
413 p = buffer + strlen(buffer);
414 strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
415 AnsiLower( p );
416 if ((file = fopen( buffer, "r" )))
417 dprintf_profile( stddeb, "Found it in %s\n", buffer );
420 if (!file && ((unix_name = DOSFS_GetUnixFileName( dos_name, TRUE ))))
422 if ((file = fopen( unix_name, "r" )))
423 dprintf_profile( stddeb, "Found it in %s\n", unix_name );
426 if (file)
428 CurProfile.section = PROFILE_Load( file );
429 fclose( file );
431 else
433 /* Does not exist yet, we will create it in PROFILE_FlushFile */
434 fprintf( stderr, "Warning: profile file %s not found\n", newdos_name );
436 dprintf_profile( stddeb, "PROFILE_Open(%s): successful\n", filename );
437 return TRUE;
441 /***********************************************************************
442 * PROFILE_GetSection
444 * Enumerate all the keys of a section.
446 static INT PROFILE_GetSection( PROFILESECTION *section,
447 const char *section_name,
448 char *buffer, INT len, int handle_env )
450 PROFILEKEY *key;
451 while (section)
453 if (section->name && !lstrcmpi32A( section->name, section_name ))
455 INT oldlen = len;
456 for (key = section->key; key; key = key->next)
458 if (len <= 2) break;
459 if (IS_ENTRY_COMMENT(key->name)) continue; /* Skip comments */
460 PROFILE_CopyEntry( buffer, key->name, len - 1, handle_env );
461 len -= strlen(buffer) + 1;
462 buffer += strlen(buffer) + 1;
464 *buffer = '\0';
465 return oldlen - len + 1;
467 section = section->next;
469 buffer[0] = buffer[1] = '\0';
470 return 2;
474 /***********************************************************************
475 * PROFILE_GetString
477 * Get a profile string.
479 static INT PROFILE_GetString( const char *section, const char *key_name,
480 const char *def_val, char *buffer, INT len )
482 PROFILEKEY *key = NULL;
484 if (!def_val) def_val = "";
485 if (key_name)
487 key = PROFILE_Find( &CurProfile.section, section, key_name, FALSE );
488 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val,
489 len, FALSE );
490 dprintf_profile( stddeb, "PROFILE_GetString('%s','%s','%s'): returning '%s'\n",
491 section, key_name, def_val, buffer );
492 return strlen( buffer );
494 return PROFILE_GetSection(CurProfile.section, section, buffer, len, FALSE);
498 /***********************************************************************
499 * PROFILE_SetString
501 * Set a profile string.
503 static BOOL PROFILE_SetString( const char *section_name, const char *key_name,
504 const char *value )
506 BOOL ret;
508 if (!key_name) /* Delete a whole section */
510 dprintf_profile(stddeb, "PROFILE_DeleteSection('%s')\n", section_name);
511 ret = PROFILE_DeleteSection( &CurProfile.section, section_name );
512 CurProfile.changed |= ret;
513 return ret;
515 else if (!value) /* Delete a key */
517 dprintf_profile( stddeb, "PROFILE_DeleteKey('%s','%s')\n",
518 section_name, key_name );
519 ret = PROFILE_DeleteKey( &CurProfile.section, section_name, key_name );
520 CurProfile.changed |= ret;
521 return ret;
523 else /* Set the key value */
525 PROFILEKEY *key = PROFILE_Find( &CurProfile.section, section_name,
526 key_name, TRUE );
527 dprintf_profile( stddeb, "PROFILE_SetString('%s','%s','%s'): ",
528 section_name, key_name, value );
529 if (key->value)
531 if (!strcmp( key->value, value ))
533 dprintf_profile( stddeb, "no change needed\n" );
534 return TRUE; /* No change needed */
536 dprintf_profile( stddeb, "replacing '%s'\n", key->value );
537 free( key->value );
539 else dprintf_profile( stddeb, "creating key\n" );
540 key->value = xstrdup( value );
541 CurProfile.changed = TRUE;
542 return TRUE;
547 /***********************************************************************
548 * PROFILE_GetWineIniString
550 * Get a config string from the wine.ini file.
552 int PROFILE_GetWineIniString( const char *section, const char *key_name,
553 const char *def, char *buffer, int len )
555 if (key_name)
557 PROFILEKEY *key = PROFILE_Find(&WineProfile, section, key_name, FALSE);
558 PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def,
559 len, TRUE );
560 dprintf_profile( stddeb, "PROFILE_GetWineIniString('%s','%s','%s'): returning '%s'\n",
561 section, key_name, def, buffer );
562 return strlen( buffer );
564 return PROFILE_GetSection( WineProfile, section, buffer, len, TRUE );
568 /***********************************************************************
569 * PROFILE_GetWineIniInt
571 * Get a config integer from the wine.ini file.
573 int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def )
575 char buffer[20];
576 char *p;
577 long result;
579 PROFILEKEY *key = PROFILE_Find( &WineProfile, section, key_name, FALSE );
580 if (!key || !key->value) return def;
581 PROFILE_CopyEntry( buffer, key->value, sizeof(buffer), TRUE );
582 result = strtol( buffer, &p, 0 );
583 if (p == buffer) return 0; /* No digits at all */
584 return (int)result;
588 /***********************************************************************
589 * PROFILE_LoadWineIni
591 * Load the wine.ini file.
593 int PROFILE_LoadWineIni(void)
595 char buffer[MAX_PATHNAME_LEN];
596 const char *p;
597 FILE *f;
599 if ((p = getenv( "HOME" )) != NULL)
601 lstrcpyn32A(buffer, p, MAX_PATHNAME_LEN - sizeof(PROFILE_WineIniName));
602 strcat( buffer, PROFILE_WineIniName );
603 if ((f = fopen( buffer, "r" )) != NULL)
605 WineProfile = PROFILE_Load( f );
606 fclose( f );
607 return 1;
610 else fprintf( stderr, "Warning: could not get $HOME value for config file.\n" );
612 /* Try global file */
614 if ((f = fopen( WINE_INI_GLOBAL, "r" )) != NULL)
616 WineProfile = PROFILE_Load( f );
617 fclose( f );
618 return 1;
620 fprintf( stderr, "Can't open configuration file %s or $HOME%s\n",
621 WINE_INI_GLOBAL, PROFILE_WineIniName );
622 return 0;
626 /***********************************************************************
627 * GetProfileInt (KERNEL.57)
629 UINT GetProfileInt( LPCSTR section, LPCSTR entry, INT def_val )
631 return GetPrivateProfileInt( section, entry, def_val, "win.ini" );
635 /***********************************************************************
636 * GetProfileString (KERNEL.58)
638 INT GetProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val,
639 LPSTR buffer, INT len )
641 return GetPrivateProfileString( section, entry, def_val,
642 buffer, len, "win.ini" );
646 /***********************************************************************
647 * WriteProfileString (KERNEL.59)
649 BOOL WriteProfileString( LPCSTR section, LPCSTR entry, LPCSTR string )
651 return WritePrivateProfileString( section, entry, string, "win.ini" );
655 /***********************************************************************
656 * GetPrivateProfileInt (KERNEL.127)
658 UINT GetPrivateProfileInt( LPCSTR section, LPCSTR entry, INT def_val,
659 LPCSTR filename )
661 char buffer[20];
662 char *p;
663 long result;
665 GetPrivateProfileString( section, entry, "",
666 buffer, sizeof(buffer), filename );
667 if (!buffer[0]) return (UINT)def_val;
668 result = strtol( buffer, &p, 0 );
669 if (p == buffer) return 0; /* No digits at all */
670 #ifdef WINELIB32
671 return (UINT)result;
672 #else
673 if (result > 65535) return 65535;
674 if (result >= 0) return (UINT)result;
675 if (result < -32768) return -32768;
676 return (UINT)(INT)result;
677 #endif
681 /***********************************************************************
682 * GetPrivateProfileString (KERNEL.128)
684 INT GetPrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val,
685 LPSTR buffer, INT len, LPCSTR filename )
687 if (PROFILE_Open( filename ))
688 return PROFILE_GetString( section, entry, def_val, buffer, len );
689 lstrcpyn32A( buffer, def_val, len );
690 return strlen( buffer );
694 /***********************************************************************
695 * WritePrivateProfileString (KERNEL.129)
697 BOOL WritePrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR string,
698 LPCSTR filename )
700 if (!PROFILE_Open( filename )) return FALSE;
701 if (!section) return PROFILE_FlushFile();
702 return PROFILE_SetString( section, entry, string );
706 /***********************************************************************
707 * WriteOutProfiles (KERNEL.315)
709 void WriteOutProfiles(void)
711 PROFILE_FlushFile();