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.
25 #include "backgrounds.h"
38 static char menu_scan_recursive = 0;
40 static Menu *MenuCreateFromDirectory(const char *name, Menu * parent,
41 MenuStyle * ms, const char *dir);
42 static int _ext_is_imagetype(const char *ext);
45 MenuItemCreateFromBackground(const char *bgid, const char *file)
50 char thumb[1024], buf[1024];
52 bg = BrackgroundCreateFromImage(bgid, file, thumb, sizeof(thumb));
56 ic = ImageclassCreateSimple("`", thumb);
58 Esnprintf(buf, sizeof(buf), "bg use %s", bgid);
60 mi = MenuItemCreate(NULL, ic, buf, NULL);
66 _dircache_filename(char *buf, unsigned int len, struct stat *st)
68 static const char chmap[] =
69 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
73 bb = filedev_map((int)st->st_dev);
74 cc = (st->st_mtime > st->st_ctime) ? st->st_mtime : st->st_ctime;
75 Esnprintf(buf, len, ".%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
76 chmap[(aa >> 0) & 0x3f], chmap[(aa >> 6) & 0x3f],
77 chmap[(aa >> 12) & 0x3f], chmap[(aa >> 18) & 0x3f],
78 chmap[(aa >> 24) & 0x3f], chmap[(aa >> 28) & 0x3f],
79 chmap[(bb >> 0) & 0x3f], chmap[(bb >> 6) & 0x3f],
80 chmap[(bb >> 12) & 0x3f], chmap[(bb >> 18) & 0x3f],
81 chmap[(bb >> 24) & 0x3f], chmap[(bb >> 28) & 0x3f],
82 chmap[(cc >> 0) & 0x3f], chmap[(cc >> 6) & 0x3f],
83 chmap[(cc >> 12) & 0x3f], chmap[(cc >> 18) & 0x3f],
84 chmap[(cc >> 24) & 0x3f], chmap[(cc >> 28) & 0x3f]);
90 MenuLoadFromDirectory(Menu * m)
92 Progressbar *p = NULL;
96 char **list, s[4096], ss[4096], cs[4096];
103 dir = MenuGetData(m);
104 lastmod = moddate(dir);
105 if (!menu_scan_recursive && lastmod <= MenuGetTimestamp(m))
107 MenuSetTimestamp(m, lastmod);
111 if (stat(dir, &st) < 0)
114 if (Mode.backgrounds.force_scan)
117 Esnprintf(cs, sizeof(cs), "%s/cached/img/%s",
118 EDirUserCache(), _dircache_filename(ss, sizeof(ss), &st));
121 /* cached dir listing - use it */
126 while (fgets(s, sizeof(s), f))
130 s[strlen(s) - 1] = 0;
132 sscanf(s, "%1000s %1000s %n", ss, s2, &len);
133 if (!strcmp(ss, "BG"))
135 Esnprintf(ss, sizeof(ss), "%s/%s", dir, s2);
136 mi = MenuItemCreateFromBackground(s + len, ss);
139 else if (!strcmp(ss, "EXE"))
141 Esnprintf(ss, sizeof(ss), "exec %s/%s", dir, s2);
142 mi = MenuItemCreate(NULL, NULL, ss, NULL);
145 else if (!strcmp(ss, "DIR"))
147 Esnprintf(ss, sizeof(ss), "%s/%s", dir, s2);
148 mm = MenuCreateFromDirectory(ss, m, NULL, ss);
149 mi = MenuItemCreate(s2, NULL, NULL, mm);
158 Esnprintf(s, sizeof(s), "Scanning %s", dir);
160 p = ProgressbarCreate(s, 600, 16);
166 list = E_ls(dir, &num);
167 for (i = 0; i < num; i++)
170 ProgressbarSet(p, (i * 100) / num);
171 Esnprintf(ss, sizeof(ss), "%s/%s", dir, list[i]);
172 /* skip "dot" files and dirs - senisble */
173 if ((*(list[i]) == '.') || (stat(ss, &st) < 0))
177 if (S_ISDIR(st.st_mode))
180 mm = MenuCreateFromDirectory(ss, m, NULL, ss);
181 mi = MenuItemCreate(list[i], NULL, NULL, mm);
184 fprintf(f, "DIR %s\n", list[i]);
187 else if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
190 /* that's it - people are stupid and have executable images and just */
191 /* don't get it - so I'm disablign this to save people from their own */
193 mi = MenuItemCreate(list[i], NULL, ss, NULL);
196 fprintf(f, "EXE %s\n", list[i]);
199 else if (_ext_is_imagetype(ext))
204 _dircache_filename(s3, sizeof(s3), &st);
206 mi = MenuItemCreateFromBackground(s3, ss);
212 fprintf(f, "BG %s %s\n", list[i], s3);
219 ProgressbarDestroy(p);
221 StrlistFree(list, num);
227 MenuCreateFromDirectory(const char *name, Menu * parent, MenuStyle * ms,
230 static int calls = 0;
237 m = MenuCreate(name, NULL, parent, ms);
238 MenuSetData(m, Estrdup(dir));
239 MenuSetLoader(m, MenuLoadFromDirectory);
241 if (menu_scan_recursive)
242 MenuLoadFromDirectory(m);
250 ScanBackgroundMenu(void)
252 menu_scan_recursive = 1;
253 MenuLoad(MenuFind("BACKGROUNDS_MENU", NULL));
254 Mode.backgrounds.force_scan = 0;
255 menu_scan_recursive = 0;
259 FillFlatFileMenu(Menu * m, const char *file)
266 f = fopen(file, "r");
269 Eprintf("Unable to open menu file %s -- %s\n", file, strerror(errno));
273 MenuSetIconSize(m, 0); /* Scale to default */
275 while (fgets(s, 4096, f))
280 while (len && (s[len - 1] == '\n' || s[len - 1] == '\r'))
288 char *title, *style, *alias;
292 title = style = alias = NULL;
293 parse(s, "%S%S%S", &title, &style, &alias);
296 MenuSetTitle(m, title);
298 style = (char *)"ROOT";
299 MenuSetStyle(m, MenuStyleFind(style));
301 MenuSetAlias(m, alias);
305 char *txt, *icon, *act, *params;
308 ImageClass *icc = NULL;
311 txt = icon = act = params = NULL;
312 parse(s, "%S%T%S%S", &txt, &icon, &act, ¶ms);
314 if (icon && exists(icon))
316 Esnprintf(wd, sizeof(wd), "__FM.%s", icon);
317 icc = ImageclassFind(wd, 0);
319 icc = ImageclassCreateSimple(wd, icon);
321 if ((act) && (!strcmp(act, "exec")) && (params))
323 sscanf(params, "%4000s", wd);
324 if (path_canexec(wd))
326 Esnprintf(wd, sizeof(wd), "exec %s", params);
327 mi = MenuItemCreate(txt, icc, wd, NULL);
331 else if ((act) && (!strcmp(act, "menu")) && (params))
333 mm = MenuFind(params, NULL);
336 mi = MenuItemCreate(txt, icc, NULL, mm);
342 mi = MenuItemCreate(txt, icc, act, NULL);
351 MenuLoadFromFlatFile(Menu * m)
357 lastmod = moddate(ff);
358 if (lastmod <= MenuGetTimestamp(m))
360 MenuSetTimestamp(m, lastmod);
363 FillFlatFileMenu(m, ff);
369 MenuCreateFromFlatFile(const char *name, Menu * parent, MenuStyle * ms,
374 static int calls = 0;
385 ff = FindFile(file, NULL);
389 /* Check menus subdir first */
390 Esnprintf(buf, sizeof(buf), "menus/%s", file);
391 ff = FindFile(buf, NULL);
393 ff = FindFile(file, NULL);
398 m = MenuCreate(file, NULL, parent, ms);
400 MenuSetAlias(m, name);
402 MenuSetLoader(m, MenuLoadFromFlatFile);
411 MenuLoadFromThemes(Menu * m)
418 if (MenuGetTimestamp(m))
420 MenuSetTimestamp(m, 1);
422 lst = ThemesList(&num);
423 for (i = 0; i < num; i++)
425 s = ThemePathName(lst[i]);
426 Esnprintf(ss, sizeof(ss), "theme use %s", s);
427 mi = MenuItemCreate(s, NULL, ss, NULL);
438 MenuCreateFromThemes(const char *name, MenuStyle * ms)
442 m = MenuCreate(name, NULL, NULL, ms);
443 MenuSetTitle(m, _("Themes"));
445 MenuSetLoader(m, MenuLoadFromThemes);
451 BorderNameCompare(void *b1, void *b2)
454 return strcmp(BorderGetName((Border *) b1), BorderGetName((Border *) b2));
460 MenuCreateFromBorders(const char *name, MenuStyle * ms)
468 m = MenuCreate(name, NULL, NULL, ms);
469 MenuSetTitle(m, _("Border"));
471 lst = BordersGetList(&num);
473 Quicksort((void **)lst, 0, num - 1, BorderNameCompare);
474 for (i = 0; i < num; i++)
476 /* if its not internal (ie doesnt start with _ ) */
477 if (lst[i]->name[0] != '_')
479 Esnprintf(s, sizeof(s), "wop * bo %s", lst[i]->name);
480 mi = MenuItemCreate(lst[i]->name, NULL, s, NULL);
490 MenuCheckShowEwinDesk(EWin * ewin, void *prm)
492 if (!EwinGetTitle(ewin) || ewin->props.skip_winlist)
494 return prm == NULL || EwinGetDesk(ewin) == prm;
498 MenuLoadFromEwins(Menu * m, int (*f) (EWin * ewin, void *prm), void *prm)
505 lst = EwinListGetAll(&num);
506 for (i = 0; i < num; i++)
511 Esnprintf(s, sizeof(s), "wop %#lx focus", EwinGetClientXwin(lst[i]));
512 mi = MenuItemCreate(EwinGetTitle(lst[i]), NULL, s, NULL);
518 MenuLoadFromAllEwins(Menu * m)
521 MenuLoadFromEwins(m, MenuCheckShowEwinDesk, NULL);
526 MenuCreateFromAllEWins(const char *name, MenuStyle * ms)
530 m = MenuCreate(name, NULL, NULL, ms);
531 MenuSetTitle(m, _("Window List"));
534 MenuSetLoader(m, MenuLoadFromAllEwins);
540 MenuLoadFromDesktops(Menu * m)
549 for (i = 0; i < DesksGetNumber(); i++)
551 mm = MenuCreate("__SUBMENUDESK_E", NULL, m, NULL);
552 Esnprintf(s, sizeof(s), "desk goto %i", i);
553 mi = MenuItemCreate(_("Go to this Desktop"), NULL, s, NULL);
555 MenuLoadFromEwins(mm, MenuCheckShowEwinDesk, DeskGet(i));
557 Esnprintf(s, sizeof(s), _("Desktop %i"), i);
558 mi = MenuItemCreate(s, NULL, NULL, mm);
566 MenuCreateFromDesktops(const char *name, MenuStyle * ms)
570 m = MenuCreate(name, NULL, NULL, ms);
571 MenuSetTitle(m, _("Desks"));
574 MenuSetLoader(m, MenuLoadFromDesktops);
580 MenuLoadFromGroups(Menu * m)
590 lst = GroupsGetList(&num);
594 for (i = 0; i < num; i++)
596 mm = MenuCreate("__SUBMENUGROUP_E", NULL, m, NULL);
598 Esnprintf(s, sizeof(s), "gop %li showhide",
599 EwinGetClientXwin(lst[i]->members[0]));
600 mi = MenuItemCreate(_("Show/Hide this group"), NULL, s, NULL);
602 Esnprintf(s, sizeof(s), "wop %#lx ic",
603 EwinGetClientXwin(lst[i]->members[0]));
605 mi = MenuItemCreate(_("Iconify this group"), NULL, s, NULL);
608 for (j = 0; j < lst[i]->num_members; j++)
610 Esnprintf(s, sizeof(s), "wop %#lx focus",
611 EwinGetClientXwin(lst[i]->members[j]));
612 mi = MenuItemCreate(EwinGetTitle(lst[i]->members[j]), NULL,
616 Esnprintf(s, sizeof(s), _("Group %i"), i);
617 mi = MenuItemCreate(s, NULL, NULL, mm);
626 MenuCreateFromGroups(const char *name, MenuStyle * ms)
630 m = MenuCreate(name, NULL, NULL, ms);
631 MenuSetTitle(m, _("Groups"));
634 MenuSetLoader(m, MenuLoadFromGroups);
639 #if 0 /* Not finished */
641 MenuCreateMoveToDesktop(char *name, Menu * parent, MenuStyle * ms)
645 char s1[256], s2[256];
649 m = MenuCreate(name, NULL, parent, ms);
651 for (i = 0; i < Mode.numdesktops; i++)
653 Esnprintf(s1, sizeof(s1), _("Desktop %i"), i);
654 Esnprintf(s2, sizeof(s2), "%i", i);
655 mi = MenuItemCreate(s1, NULL, s2, NULL);
664 MenusCreateInternal(const char *type, const char *name, const char *style,
673 ms = MenuStyleFind(style);
677 if (!strstr(name, ".menu"))
681 if (!type || !strcmp(type, "file"))
683 m = MenuCreateFromFlatFile(name, NULL, ms, prm);
685 else if (!strcmp(type, "dirscan"))
687 SoundPlay(SOUND_SCANNING);
688 m = MenuCreateFromDirectory(name, NULL, ms, prm);
690 else if (!strcmp(type, "borders"))
692 m = MenuCreateFromBorders(name, ms);
694 else if (!strcmp(type, "themes"))
696 m = MenuCreateFromThemes(name, ms);
698 else if (!strcmp(type, "windowlist"))
700 m = MenuCreateFromAllEWins(name, ms);
702 else if (!strcmp(type, "deskmenu"))
704 m = MenuCreateFromDesktops(name, ms);
706 else if (!strcmp(type, "groupmenu"))
708 m = MenuCreateFromGroups(name, ms);
715 _ext_is_imagetype(const char *ext)
717 static const char *const exts[] = {
718 "jpg", "jpeg", "gif", "png", "tif", "tiff",
719 "xpm", "ppm", "pgm", "pnm", "bmp", NULL
723 for (i = 0; exts[i]; i++)
724 if (!Estrcasecmp(exts[i], ext))