1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-21 21:38:00 +01:00

wmmenugen: Finish the XDG parser

Recognize the freedesktop.org-mandated Main Categories in .desktop files
and put menu entries in the appropriate categories.

Signed-off-by: Tamas TEVESZ <ice@extreme.hu>
This commit is contained in:
Tamas TEVESZ
2010-10-10 18:55:06 +02:00
committed by Carlos R. Mafra
parent a23b72c32a
commit 4f853ce3b6
2 changed files with 105 additions and 40 deletions

View File

@@ -232,12 +232,12 @@ static Bool wmc_to_wm(WMConfigMenuEntry **wmc, WMMenuEntry **wm)
size_t slen;
/* only Exec is mandatory, and it's better exist in a known place */
if (!*wmc ||
!(*wmc)->Exec || !*(*wmc)->Exec ||
!fileInPath((*wmc)->Exec))
if (!((*wmc)->Exec &&
*(*wmc)->Exec &&
fileInPath((*wmc)->Exec)))
return False;
/* normalize Exec: wmconfig tends to stuck an ampersand
/* normalize Exec: wmconfig tends to stick an ampersand
* at the end of everything, which we don't need */
slen = strlen((*wmc)->Exec) - 1;
p = (*wmc)->Exec;

View File

@@ -22,14 +22,16 @@
/*
* http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.1.html
* http://standards.freedesktop.org/menu-spec/menu-spec-1.1.html
*
* We will only deal with Type == "Application" entries in [Desktop Entry]
* groups. Since there is no passing of file name arguments or anything of
* the sort to applications from the menu, execname is determined as follows:
* - If `TryExec' is present, use that;
* - else use `Exec' with any switches stripped
* XXX: Only the first item of `Categories' is taken into consideration,
* which will be used as the sole category to put the entry into.
*
* Only the (first, though there should not be more than one) `Main Category'
* is used to place the entry in a submenu.
*
* Basic validation of the .desktop file is done.
*/
@@ -77,6 +79,7 @@ static void getKey(char **target, const char *line);
static void getStringValue(char **target, const char *line);
static void getLocalizedStringValue(char **target, const char *line, int *match_level);
static int getBooleanValue(const char *line);
static void getMenuHierarchyFor(char **xdgmenuspec);
static int compare_matchlevel(int *current_level, const char *found_locale);
static Bool xdg_to_wm(XDGMenuEntry **xdg, WMMenuEntry **wmentry);
static void init_xdg_storage(XDGMenuEntry **xdg);
@@ -173,15 +176,8 @@ void parse_xdg(const char *file, void (*addWMMenuEntryCallback)(WMMenuEntry *aEn
if (getBooleanValue(p))
xdg->Flags |= F_TERMINAL;
} else if (strcmp(key, "Categories") == 0) {
/* use only the first item */
getStringValue(&tmp, p);
if (tmp != NULL) {
tmp[strcspn(tmp, ";")] = '\0';
tmp[strcspn(tmp, "\t ")] = '\0';
xdg->Category = wstrdup(tmp);
wfree(tmp);
tmp = NULL;
}
getStringValue(&xdg->Category, p);
getMenuHierarchyFor(&xdg->Category);
}
wfree(key);
@@ -201,30 +197,36 @@ void parse_xdg(const char *file, void (*addWMMenuEntryCallback)(WMMenuEntry *aEn
*/
static Bool xdg_to_wm(XDGMenuEntry **xdg, WMMenuEntry **wm)
{
if (!*xdg)
char *p;
/* Exec or TryExec is mandatory */
if (!((*xdg)->Exec || (*xdg)->TryExec))
return False;
if ((*xdg)->Exec || (*xdg)->TryExec) {
(*wm)->Flags = (*xdg)->Flags;
/* if there's no Name, use the first word of Exec or TryExec
*/
if ((*xdg)->Name) {
(*wm)->Name = (*xdg)->Name;
}
if ((*xdg)->Exec) {
if (!(*wm)->Name)
(*wm)->Name = (*xdg)->Exec;
(*wm)->CmdLine = (*xdg)->Exec;
}
if ((*xdg)->TryExec) {
if (!(*wm)->Name)
(*wm)->Name = (*xdg)->TryExec;
if (!(*wm)->CmdLine)
(*wm)->CmdLine = (*xdg)->TryExec;
}
}
if ((*wm)->Name && (*wm)->CmdLine)
return True;
} else {
if ((*xdg)->Exec)
(*wm)->Name = wstrdup((*xdg)->Exec);
else /* (*xdg)->TryExec */
(*wm)->Name = wstrdup((*xdg)->TryExec);
return False;
p = strchr((*wm)->Name, ' ');
if (p)
*p = '\0';
}
if ((*xdg)->Exec)
(*wm)->CmdLine = (*xdg)->Exec;
else /* (*xdg)->TryExec */
(*wm)->CmdLine = (*xdg)->TryExec;
(*wm)->SubMenu = (*xdg)->Category;
(*wm)->Flags = (*xdg)->Flags;
return True;
}
/* (re-)initialize a XDGMenuEntry storage
@@ -282,7 +284,7 @@ static void getKey(char **target, const char *line)
/* skip up until first whitespace or '[' (localestring) or '=' */
kend = kstart + 1;
while (!isspace(*(p + kend)) && *(p + kend) != '=' && *(p + kend) != '[')
while (*(p + kend) && !isspace(*(p + kend)) && *(p + kend) != '=' && *(p + kend) != '[')
kend++;
*target = wstrndup(p + kstart, kend - kstart);
@@ -298,12 +300,12 @@ static void getStringValue(char **target, const char *line)
kstart = 0;
/* skip until after '=' */
while (*(p + kstart) != '=')
while (*(p + kstart) && *(p + kstart) != '=')
kstart++;
kstart++;
/* skip whitespace */
while (isspace(*(p + kstart)))
while (*(p + kstart) && isspace(*(p + kstart)))
kstart++;
*target = wstrdup(p + kstart);
@@ -327,7 +329,7 @@ static void getLocalizedStringValue(char **target, const char *line, int *match_
locale = NULL;
/* skip until after '=', mark if '[' and ']' is found */
while (*(p + kstart) != '=') {
while (*(p + kstart) && *(p + kstart) != '=') {
switch (*(p + kstart)) {
case '[': sqbstart = kstart + 1;break;
case ']': sqbend = kstart; break;
@@ -477,3 +479,66 @@ static Bool compare_matchlevel(int *current_level, const char *found_locale)
return False;
}
/* get the (first) xdg main category from a list of categories
*/
static void getMenuHierarchyFor(char **xdgmenuspec)
{
char *category, *p;
char buf[1024];
if (!*xdgmenuspec || !**xdgmenuspec)
return;
category = wstrdup(*xdgmenuspec);
wfree(*xdgmenuspec);
memset(buf, 0, sizeof(buf));
p = strtok(category, ";");
while (p) { /* get a known category */
if (strcmp(p, "AudioVideo") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Audio & Video"));
break;
} else if (strcmp(p, "Audio") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Audio"));
break;
} else if (strcmp(p, "Video") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Video"));
break;
} else if (strcmp(p, "Development") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Development"));
break;
} else if (strcmp(p, "Education") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Education"));
break;
} else if (strcmp(p, "Game") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Game"));
break;
} else if (strcmp(p, "Graphics") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Graphics"));
break;
} else if (strcmp(p, "Network") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Network"));
break;
} else if (strcmp(p, "Office") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Office"));
break;
} else if (strcmp(p, "Settings") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Settings"));
break;
} else if (strcmp(p, "System") == 0) {
snprintf(buf, sizeof(buf), "%s", _("System"));
break;
} else if (strcmp(p, "Utility") == 0) {
snprintf(buf, sizeof(buf), "%s", _("Utility"));
break;
}
p = strtok(NULL, ";");
}
if (!*buf) /* come up with something if nothing found */
snprintf(buf, sizeof(buf), "%s", _("Applications"));
*xdgmenuspec = wstrdup(buf);
}