e16/src/config.c

614 lines
15 KiB
C
Raw Normal View History

/*
2004-01-19 14:30:35 -08:00
* Copyright (C) 2000-2004 Carsten Haitzler, Geoff Harrison and various contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "E.h"
#include "conf.h"
#include <ctype.h>
#define SKIP_If_EXISTS(name, type) \
2004-12-28 15:46:49 -08:00
if (ConfigSkipIfExists(ConfigFile, name, type)) return
static void
SkipTillEnd(FILE * ConfigFile)
{
char s[FILEPATH_LEN_MAX];
int i1, i2, fields;
while (GetLine(s, sizeof(s), ConfigFile))
{
i1 = i2 = 0;
fields = sscanf(s, "%i %i", &i1, &i2);
if (i1 == CONFIG_CLOSE)
return;
if (i2 == CONFIG_OPEN)
SkipTillEnd(ConfigFile);
}
}
2004-12-28 15:46:49 -08:00
int
ConfigSkipIfExists(FILE * ConfigFile, const char *name, int type)
{
2004-12-28 15:46:49 -08:00
if (FindItem(name, 0, LIST_FINDBY_NAME, type))
{
2004-12-28 15:46:49 -08:00
SkipTillEnd(ConfigFile);
return 1;
}
2004-12-28 15:46:49 -08:00
return 0;
}
2004-12-28 15:46:49 -08:00
static int
IsWhitespace(const char *s)
{
2004-12-28 15:46:49 -08:00
int i = 0;
2004-12-28 15:46:49 -08:00
while (s[i])
{
if ((s[i] != ' ') && (s[i] != '\n') && (s[i] != '\t'))
return 0;
i++;
}
return 1;
}
2004-12-28 15:46:49 -08:00
#define LINE_BUFFER_SIZE 1024
/*
* This function will get a single line from the file
* The string will be null terminated.
* Size must be >= 2.
*/
char *
GetLine(char *s, int size, FILE * f)
{
char *si, *so, ch, quote, escape;
static char *buffer = NULL;
static char *bufptr = NULL;
2004-12-28 15:46:49 -08:00
si = bufptr;
so = s;
quote = '\0';
escape = '\0';
for (;;)
{
2004-12-28 15:46:49 -08:00
if (buffer == NULL)
{
2004-12-28 15:46:49 -08:00
buffer = Emalloc(LINE_BUFFER_SIZE);
if (buffer == NULL)
return NULL;
}
2004-12-28 15:46:49 -08:00
/* Get a line from the input file */
if (si == NULL)
{
2004-12-28 15:46:49 -08:00
si = fgets(buffer, LINE_BUFFER_SIZE - 1, f);
buffer[LINE_BUFFER_SIZE - 1] = '\0';
if (si == NULL)
{
2004-12-28 15:46:49 -08:00
/* EOF */
Efree(buffer);
buffer = bufptr = NULL;
return NULL;
}
}
2004-12-28 15:46:49 -08:00
/* Split on ';' or '\n', handle quoting */
for (; si;)
{
ch = *si++;
switch (ch)
{
case '\0':
si = NULL;
if (so == s) /* Skip empty lines */
break;
goto case_eol;
case ';': /* Line separator */
if (escape || quote)
goto case_char;
case '\n':
if (so == s) /* Skip empty lines */
break;
case_eol:
*so++ = '\0'; /* Terminate and return */
goto done;
case '\r': /* Ignore */
break;
case '\\': /* Escape */
if (escape)
goto case_char;
escape = ch;
break;
case '"': /* Quoting */
/* case '\'': */
if (escape)
goto case_char;
if (quote == '\0')
quote = ch;
else if (quote == ch)
quote = '\0';
else
goto case_char;
break;
case ' ': /* Whitespace */
case '\t':
if (so == s) /* Skip leading whitespace */
break;
case_char: /* Normal character */
default:
*so++ = ch;
escape = '\0';
if (--size > 1)
break;
*so = '\0';
goto done;
}
}
}
2004-12-28 15:46:49 -08:00
done:
bufptr = si;
if (EventDebug(EDBUG_TYPE_CONFIG))
Eprintf("GetLine %s\n", s);
return s;
}
2004-12-28 15:46:49 -08:00
void
ConfigAlertLoad(const char *txt)
{
RecoverUserConfig();
Alert(_("Warning: Configuration error in %s block.\n"
"Outcome is likely not good.\n"), txt);
}
2004-12-28 15:46:49 -08:00
static int
ConfigFilePreparse(const char *path, const char *dest)
{
2004-12-28 15:46:49 -08:00
static char have_epp = 0;
char execline[FILEPATH_LEN_MAX];
const char *epp_path = ENLIGHTENMENT_BIN "/epp";
2004-12-28 15:46:49 -08:00
char *def_home, *def_user, *def_shell;
if (EventDebug(EDBUG_TYPE_CONFIG))
Eprintf("ConfigFilePreparse %s->%s\n", path, dest);
if ((!have_epp) && (!(isfile(epp_path)) && (canexec(epp_path))))
{
Alert(_("Help! Cannot find epp!\n"
"Enlightenment is looking for epp here:\n" "%s\n"
"This is a FATAL ERROR.\n"
"This is probably due to either the program not existing or\n"
"it not being able to be executed by you.\n"), epp_path);
SessionExit(EEXIT_ERROR, NULL);
2004-12-28 15:46:49 -08:00
}
have_epp = 1;
def_home = homedir(getuid());
def_user = username(getuid());
def_shell = usershell(getuid());
Esnprintf(execline, sizeof(execline), "%s " "-P " "-nostdinc " "-undef "
"-include %s/config/definitions " "-I%s " "-I%s/config "
"-D ENLIGHTENMENT_VERSION=%s " "-D ENLIGHTENMENT_ROOT=%s "
"-D ENLIGHTENMENT_BIN=%s "
"-D ENLIGHTENMENT_THEME=%s " "-D ECONFDIR=%s "
"-D ECACHEDIR=%s " "-D SCREEN_RESOLUTION_%ix%i=1 "
"-D SCREEN_WIDTH_%i=1 " "-D SCREEN_HEIGHT_%i=1 "
"-D SCREEN_DEPTH_%i=1 " "-D USER_NAME=%s " "-D HOME_DIR=%s "
"-D USER_SHELL=%s " "-D ENLIGHTENMENT_VERSION_015=1 "
"%s %s",
epp_path, EDirRoot(), Mode.theme.path, EDirRoot(),
ENLIGHTENMENT_VERSION, EDirRoot(), EDirBin(),
Mode.theme.path, EDirUser(), EDirUserCache(), VRoot.w,
VRoot.h, VRoot.w, VRoot.h, VRoot.depth, def_user, def_home,
def_shell, path, dest);
system(execline);
if (def_user)
Efree(def_user);
if (def_shell)
Efree(def_shell);
if (def_home)
Efree(def_home);
return exists(dest) ? 0 : 1;
}
/* Split the process of finding the file from the process of loading it */
static int
2004-12-28 15:46:49 -08:00
ConfigFileRead(FILE * fs)
{
2004-12-28 15:46:49 -08:00
int err;
int i1, i2, fields;
char s[FILEPATH_LEN_MAX];
int e_cfg_ver = 0;
int min_e_cfg_ver = 0;
2004-12-28 15:46:49 -08:00
while (GetLine(s, sizeof(s), fs))
{
if (IsWhitespace(s))
continue;
2004-12-28 15:46:49 -08:00
i1 = i2 = CONFIG_INVALID;
fields = sscanf(s, "%i %i", &i1, &i2);
if (fields < 1)
i1 = CONFIG_INVALID;
else if (i1 == CONFIG_VERSION)
{
if (fields == 2)
e_cfg_ver = i2;
}
else if (i1 == CONFIG_CLOSE)
{
if (fields != 1)
{
RecoverUserConfig();
Alert(_("CONFIG: ignoring extra data in \"%s\"\n"), s);
}
}
else if (i1 != CONFIG_INVALID)
{
if (fields != 2)
{
RecoverUserConfig();
Alert(_("CONFIG: missing required data in \"%s\"\n"), s);
}
}
if (i2 == CONFIG_OPEN)
{
if (e_cfg_ver != min_e_cfg_ver)
{
2004-12-28 15:46:49 -08:00
AlertX(_("Theme versioning ERROR"),
_("Restart with Defaults"), " ",
_("Abort and Exit"),
_("ERROR:\n" "\n"
"The configuration for the theme you are "
"running is\n"
"incompatible. It's config revision is %i. "
"It needs to\n"
"be marked as being revision %i\n" "\n"
"Please contact the theme author or "
"maintainer and\n"
"inform them that in order for their theme "
"to function\n"
"with this version of Enlightenment, they "
"have to\n"
"update it to the current settings, and "
"then match\n" "the revision number.\n" "\n"
"If the theme revision is higher than "
"Enlightenment's\n"
"it may be that you haven't upgraded "
"Enlightenment for\n"
"a while and this theme takes advantages of new\n"
"features in Enlightenment in new versions.\n"),
e_cfg_ver, min_e_cfg_ver);
SessionExit(EEXIT_THEME, "DEFAULT");
}
else
{
switch (i1)
{
case CONFIG_CLOSE:
2004-12-28 15:46:49 -08:00
goto done;
case CONFIG_IMAGECLASS:
2004-12-28 15:46:49 -08:00
err = ImageclassConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Image class"));
break;
case CONFIG_TOOLTIP:
2004-12-28 15:46:49 -08:00
err = TooltipConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Tooltip"));
break;
2004-12-28 15:46:49 -08:00
case CONFIG_FONTS:
err = FontConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Font"));
break;
2004-12-28 15:46:49 -08:00
case CONFIG_TEXT:
err = TextclassConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Text class"));
break;
case MENU_STYLE:
2004-12-28 15:46:49 -08:00
err = MenuStyleConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Menu style"));
break;
case CONFIG_BORDER:
2004-12-28 15:46:49 -08:00
err = BorderConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Border"));
break;
case CONFIG_BUTTON:
2004-12-28 15:46:49 -08:00
err = ButtonsConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Button"));
break;
case CONFIG_DESKTOP:
2004-12-28 15:46:49 -08:00
err = BackgroundsConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Background"));
break;
case CONFIG_WINDOWMATCH:
err = WindowMatchConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Window match"));
break;
case CONFIG_COLORMOD:
2004-12-28 15:46:49 -08:00
#if 0 /* FIXME - ? */
Config_ColorModifier(fs);
#endif
break;
case CONFIG_ACTIONCLASS:
2004-12-28 15:46:49 -08:00
err = AclassConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Action class"));
break;
case CONFIG_SLIDEOUT:
2004-12-28 15:46:49 -08:00
err = SlideoutsConfigLoad(fs);
if (err)
ConfigAlertLoad(_("Slideout"));
break;
default:
break;
}
}
}
}
2004-12-28 15:46:49 -08:00
done:
return 0;
}
char *
2004-12-28 15:46:49 -08:00
FindFile(const char *file, const char *themepath)
{
char s[FILEPATH_LEN_MAX];
/* if absolute path - and file exists - return it */
2004-02-18 14:18:41 -08:00
if (isabspath(file))
{
strcpy(s, file);
if (findLocalizedFile(s) || isfile(s))
return Estrdup(s);
}
2004-12-28 15:46:49 -08:00
/* look in ~/.e16 first */
Esnprintf(s, sizeof(s), "%s/%s", EDirUser(), file);
if (findLocalizedFile(s) || isfile(s))
return Estrdup(s);
2004-12-28 15:46:49 -08:00
if (themepath)
{
/* look in theme dir */
Esnprintf(s, sizeof(s), "%s/%s", themepath, file);
if (findLocalizedFile(s) || isfile(s))
return Estrdup(s);
2004-12-28 15:46:49 -08:00
}
/* look in system config dir */
Esnprintf(s, sizeof(s), "%s/config/%s", EDirRoot(), file);
if (findLocalizedFile(s) || isfile(s))
return Estrdup(s);
/* not found.... NULL */
return NULL;
}
2004-12-28 15:46:49 -08:00
char *
ThemeFileFind(const char *file)
{
return FindFile(file, Mode.theme.path);
}
char *
ConfigFileFind(const char *name, const char *themepath, int pp)
{
char s[FILEPATH_LEN_MAX];
2004-12-28 15:46:49 -08:00
char *fullname, *file, *ppfile;
int i, err;
2004-12-28 15:46:49 -08:00
fullname = FindFile(name, themepath);
if (!fullname)
return NULL;
2004-12-28 15:46:49 -08:00
/* Quit if not preparsing */
if (!pp)
return fullname;
2004-12-28 15:46:49 -08:00
/* The file exists. Now check the preparsed one. */
file = Estrdup(fullname);
for (i = 0; file[i]; i++)
if (file[i] == '/')
file[i] = '.';
2004-12-28 15:46:49 -08:00
Esnprintf(s, sizeof(s), "%s/cached/cfg/%s.preparsed", EDirUserCache(), file);
ppfile = Estrdup(s);
if (exists(s) && moddate(s) > moddate(fullname))
goto done;
/* No preparesd file or source is newer. Do preparsing. */
err = ConfigFilePreparse(fullname, ppfile);
if (err)
{
Efree(ppfile);
ppfile = NULL;
}
done:
Efree(fullname);
Efree(file);
return ppfile;
}
int
2004-12-28 15:46:49 -08:00
ConfigFileLoad(const char *name, const char *themepath,
int (*parse) (FILE * fs), int preparse)
{
2004-12-28 15:46:49 -08:00
int err = -1;
char *file;
FILE *fs;
2004-12-28 15:46:49 -08:00
if (EventDebug(EDBUG_TYPE_CONFIG))
Eprintf("ConfigFileLoad %s\n", name);
file = ConfigFileFind(name, themepath, preparse);
if (!file)
2004-12-28 15:46:49 -08:00
goto done;
fs = fopen(file, "r");
Efree(file);
if (!fs)
goto done;
2004-12-28 15:46:49 -08:00
err = parse(fs);
2004-12-28 15:46:49 -08:00
fclose(fs);
2004-12-28 15:46:49 -08:00
done:
return err;
}
int
2004-12-28 15:46:49 -08:00
ThemeConfigLoad(void)
{
2004-12-28 15:46:49 -08:00
static const char *const config_files[] = {
"fonts.cfg",
"init.cfg",
"textclasses.cfg",
"backup-textclasses.cfg",
"colormodifiers.cfg",
"backup-colormodifiers.cfg",
"imageclasses.cfg",
"backup-imageclasses.cfg",
"desktops.cfg",
"actionclasses.cfg",
"backup-cursors.cfg",
"buttons.cfg",
"slideouts.cfg",
"borders.cfg",
"backup-borders.cfg",
"windowmatches.cfg",
2004-12-28 15:46:49 -08:00
"tooltips.cfg",
"backup-tooltips.cfg",
"menustyles.cfg",
};
char s[FILEPATH_LEN_MAX];
Progressbar *p = NULL;
int i;
2004-12-28 15:46:49 -08:00
Esnprintf(s, sizeof(s), "%s/", Mode.theme.path);
2004-12-28 15:46:49 -08:00
for (i = 0; i < (int)(sizeof(config_files) / sizeof(char *)); i++)
{
2004-12-28 15:46:49 -08:00
if (!Mode.wm.restart)
{
if (i == 2)
StartupWindowsCreate(1);
2004-02-18 14:18:41 -08:00
2004-12-28 15:46:49 -08:00
if ((i > 1) && (!p))
{
p = ProgressbarCreate(_("Enlightenment Starting..."), 400,
16);
if (p)
ProgressbarShow(p);
}
}
ConfigFileLoad(config_files[i], Mode.theme.path, ConfigFileRead, 1);
2004-12-28 15:46:49 -08:00
if (p)
ProgressbarSet(p, (i * 100) /
(int)(sizeof(config_files) / sizeof(char *)));
}
2004-12-28 15:46:49 -08:00
if (p)
ProgressbarDestroy(p);
2004-12-28 15:46:49 -08:00
/* No longer needed */
FontConfigUnload();
2004-12-28 15:46:49 -08:00
/* Loose ends... */
Esnprintf(s, sizeof(s), "%s.misc", EGetSavePrefix());
ConfigFileLoad(s, NULL, ConfigFileRead, 0);
2004-12-28 15:46:49 -08:00
BordersSetupFallback();
return 0;
}
void
SaveUserControlConfig(void)
{
char s[4096], s2[4096];
2004-12-28 15:46:49 -08:00
FILE *fs;
/* Save the configuration parameters */
2004-12-28 15:46:49 -08:00
ConfigurationSave();
/* Save odd bits */
Etmp(s2);
fs = fopen(s2, "w");
2004-12-28 15:46:49 -08:00
if (!fs)
return;
2004-12-28 15:46:49 -08:00
fprintf(fs, "1001 0\n");
2004-12-28 15:46:49 -08:00
BackgroundsConfigSave(fs);
ButtonsConfigSave(fs);
2004-12-28 15:46:49 -08:00
fclose(fs);
Esnprintf(s, sizeof(s), "%s.misc", EGetSavePrefix());
E_mv(s2, s);
if (!isfile(s))
Alert(_("There was an error saving your autosave data - filing\n"
"system problems.\n"));
}
2004-12-28 15:46:49 -08:00
void
RecoverUserConfig(void)
{
int save;
2004-12-28 15:46:49 -08:00
/* Don't save settings if we restart or quit */
save = Conf.autosave;
Conf.autosave = 0;
AlertX(_("Recover system config?"), _("Yes, Attempt recovery"),
_("Restart and try again"), _("Quit and give up"),
_
("Enlightenment has encountered parsing errors in your autosaved\n"
"configuration.\n" "\n"
"This may be due to filing system errors, Minor bugs or "
"unforeseen\n" "system shutdowns.\n" "\n"
"Do you wish Enlightenment to recover its original system\n"
"configuration and try again?\n"));
/* Allow settings to be saved if we continue */
Conf.autosave = save;
}