2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2009 Kim Woelders
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 /* Update Mode.theme.paths (theme path list) */
32 ThemePathsUpdate(void)
36 Esnprintf(paths, sizeof(paths), "%s/themes:%s/themes:%s", EDirUser(),
37 EDirRoot(), (Conf.theme.extra_path) ? Conf.theme.extra_path : "");
38 _EFDUP(Mode.theme.paths, paths);
41 /* Check if this is a theme dir */
43 ThemeCheckPath(const char *path)
45 static const char *const theme_files[] = {
48 "epplets/epplets.cfg",
56 for (i = 0; (tf = theme_files[i]) != NULL; i++)
58 Esnprintf(s, sizeof(s), "%s/%s", path, tf);
67 ThemePathName(const char *path)
74 p = strrchr(path, '/');
76 return Estrdup(path); /* Name only */
77 if (strcmp(p + 1, "e16"))
78 return Estrdup(p + 1); /* Regular path */
80 /* <path>/<themename>/e16 */
85 return Estrdup(path); /* Should not happen */
87 memmove(s, p, strlen(p) + 1);
92 append_merge_dir(char *dir, char ***list, int *count)
94 char ss[FILEPATH_LEN_MAX], s1[FILEPATH_LEN_MAX];
95 char **str = NULL, *s;
98 str = E_ls(dir, &num);
102 for (i = 0; i < num; i++)
104 if (!strcmp(str[i], "DEFAULT"))
107 Esnprintf(ss, sizeof(ss), "%s/%s", dir, str[i]);
111 if (ThemeCheckPath(ss))
113 Esnprintf(ss, sizeof(ss), "%s/%s/e16", dir, str[i]);
114 if (ThemeCheckPath(ss))
120 s = strstr(str[i], ".etheme");
123 Esnprintf(s1, sizeof(s1), "%s/themes/%s", EDirUser(), str[i]);
124 s = strstr(s1, ".etheme");
138 *list = EREALLOC(char *, *list, *count);
140 (*list)[(*count) - 1] = Estrdup(ss);
142 StrlistFree(str, num);
146 ThemesList(int *number)
152 lst = StrlistFromString(Mode.theme.paths, ':', &num);
156 for (i = 0; i < num; i++)
157 append_merge_dir(lst[i], &list, &count);
159 StrlistFree(lst, num);
166 ThemeGetPath(const char *path, char *buf, unsigned int len)
169 char s1[FILEPATH_LEN_MAX];
172 /* We only attempt to dereference a DEFAULT link */
173 s = strstr(path, "/DEFAULT");
177 l = readlink(path, s1, sizeof(s1) - 1);
184 Esnprintf(buf, len, "%s", s1);
188 Esnprintf(buf, len, "%s", path); /* Copy path */
190 Esnprintf(buf + l, len - l, "%s", s1); /* Substitute link */
196 ThemeExtract(const char *path)
198 char s[FILEPATH_LEN_MAX];
199 char th[FILEPATH_LEN_MAX];
201 unsigned char buf[320];
204 /* its a directory - just use it "as is" */
207 path = ThemeGetPath(path, s, sizeof(s));
214 /* its a file - check its type */
215 f = fopen(path, "r");
218 fread(buf, 1, 320, f);
222 Esnprintf(th, sizeof(th), "%s/themes/%s", EDirUser(), name);
225 /* check magic numbers */
226 if ((buf[0] == 31) && (buf[1] == 139))
228 /* gzipped tarball */
229 Esnprintf(s, sizeof(s),
230 "gzip -d -c < %s | (cd %s ; tar -xf -)", path, th);
232 else if ((buf[257] == 'u') && (buf[258] == 's') &&
233 (buf[259] == 't') && (buf[260] == 'a') && (buf[261] == 'r'))
235 /* vanilla tarball */
236 Esnprintf(s, sizeof(s), "(cd %s ; tar -xf %s)", th, path);
244 /* exec the untar if tarred */
248 if (ThemeCheckPath(path))
249 return Estrdup(path);
256 ThemeFind(const char *theme)
258 static const char *const default_themes[] = {
259 "DEFAULT", "winter", "BrushedMetal-Tigert", "ShinyMetal", NULL
261 char tdir[4096], *path;
269 if (!theme || !theme[0])
273 else if (!strcmp(theme, "-")) /* Use fallbacks */
277 else if (isabspath(theme))
279 path = ThemeExtract(theme);
285 lst = StrlistFromString(Mode.theme.paths, ':', &num);
292 for (j = 0; j < num; j++)
294 Esnprintf(tdir, sizeof(tdir), "%s/%s", lst[j], theme);
295 path = ThemeExtract(tdir);
299 Esnprintf(tdir, sizeof(tdir), "%s/%s/e16", lst[j], theme);
300 path = ThemeExtract(tdir);
305 theme = default_themes[i++];
310 StrlistFree(lst, num);
315 /* No theme found yet, just find any theme */
316 lst = ThemesList(&num);
319 path = Estrdup(lst[0]);
320 StrlistFree(lst, num);
331 * Conf.theme.name is read from the configuration.
332 * Mode.theme.path may be assigned on the command line.
334 name = (Mode.theme.path) ? Mode.theme.path : Conf.theme.name;
335 path = ThemeFind(name);
337 if (!path && (!name || strcmp(name, "-")))
339 Alert(_("No themes were found in the default directories:\n"
341 "Proceeding from here is mostly pointless.\n"),
345 Efree(Conf.theme.name);
346 Conf.theme.name = ThemePathName(path);
348 Efree(Mode.theme.path);
349 Mode.theme.path = (path) ? path : Estrdup("-");
355 * Configuration dialog
357 static char tmp_use_theme_font;
358 static char tmp_use_alt_font;
361 _DlgThemeConfigure(Dialog * d __UNUSED__, int val, void *data __UNUSED__)
365 if (Conf.theme.use_theme_font_cfg == tmp_use_theme_font &&
366 Conf.theme.use_alt_font_cfg == tmp_use_alt_font)
369 DialogOK(_("Message"), _("Changes will take effect after restart"));
371 Conf.theme.use_theme_font_cfg = tmp_use_theme_font;
372 Conf.theme.use_alt_font_cfg = tmp_use_alt_font;
377 _DlgThemeFill(Dialog * d __UNUSED__, DItem * table, void *data __UNUSED__)
382 tmp_use_theme_font = Conf.theme.use_theme_font_cfg;
383 tmp_use_alt_font = Conf.theme.use_alt_font_cfg;
385 DialogItemTableSetOptions(table, 2, 0, 0, 0);
387 di = DialogAddItem(table, DITEM_CHECKBUTTON);
388 DialogItemSetColSpan(di, 2);
389 DialogItemSetText(di, _("Use theme font configuration"));
390 DialogItemCheckButtonSetPtr(di, &tmp_use_theme_font);
392 di = DialogAddItem(table, DITEM_CHECKBUTTON);
393 DialogItemSetColSpan(di, 2);
394 Esnprintf(buf, sizeof(buf), _("Use alternate font configuration (%s)"),
395 Conf.theme.font_cfg ? Conf.theme.font_cfg : _("Not set"));
396 DialogItemSetText(di, buf);
397 DialogItemCheckButtonSetPtr(di, &tmp_use_alt_font);
400 const DialogDef DlgTheme = {
403 N_("Theme Settings"),
404 SOUND_SETTINGS_MISCELLANEOUS,
405 "pix/miscellaneous.png",
406 N_("Enlightenment Theme\n" "Settings Dialog\n"),
408 DLG_OAC, _DlgThemeConfigure,
410 #endif /* ENABLE_DIALOGS */
417 ThemesIpc(const char *params)
420 char cmd[128], prm[128];
423 cmd[0] = prm[0] = '\0';
428 sscanf(p, "%100s %100s %n", cmd, prm, &len);
432 if (!p || cmd[0] == '?')
436 IpcPrintf("Name: %s\n", (Conf.theme.name) ? Conf.theme.name : "-");
437 IpcPrintf("Full: %s\n", Mode.theme.path);
438 path = ThemeFind(NULL);
439 IpcPrintf("Default: %s\n", path);
441 IpcPrintf("Path: %s\n", Mode.theme.paths);
443 else if (!strncmp(cmd, "list", 2))
448 lst = ThemesList(&num);
451 for (i = 0; i < num; i++)
452 IpcPrintf("%s\n", lst[i]);
453 StrlistFree(lst, num);
455 else if (!strcmp(cmd, "use"))
457 /* FIXME - ThemeCheckIfValid(s) */
458 SessionExit(EEXIT_THEME, prm);
462 static const IpcItem ThemeIpcArray[] = {
467 " theme Show current theme\n"
468 " theme list Show all themes\n"
469 " theme use <name> Switch to theme <name>\n"}
472 #define N_IPC_FUNCS (sizeof(ThemeIpcArray)/sizeof(IpcItem))
474 static const CfgItem ThemeCfgItems[] = {
475 CFG_ITEM_STR(Conf.theme, name),
476 CFG_ITEM_STR(Conf.theme, extra_path),
477 CFG_ITEM_BOOL(Conf.theme, use_theme_font_cfg, 0),
478 CFG_ITEM_BOOL(Conf.theme, use_alt_font_cfg, 0),
479 CFG_ITEM_STR(Conf.theme, font_cfg),
481 #define N_CFG_ITEMS (sizeof(ThemeCfgItems)/sizeof(CfgItem))
486 extern const EModule ModTheme;
487 const EModule ModTheme = {
490 {N_IPC_FUNCS, ThemeIpcArray},
491 {N_CFG_ITEMS, ThemeCfgItems}