2006-08-11 06:45:39 -07:00
|
|
|
/*
|
|
|
|
* This conforms with the freedesktop.org Desktop Menu Specification version 0.92
|
|
|
|
*
|
|
|
|
* This is gonna be repetative and slow. The idea is to first get it to correctly
|
|
|
|
* follow the spec in a way that is easy to check. Only then can we start to
|
|
|
|
* optomize into "ugly but fast".
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <libgen.h>
|
|
|
|
|
|
|
|
#include <Ecore.h>
|
|
|
|
|
|
|
|
#include "Ecore_Desktop.h"
|
|
|
|
#include "ecore_desktop_private.h"
|
|
|
|
|
|
|
|
//#define DEBUG 1
|
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_expand_apps_data
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char *path;
|
|
|
|
Ecore_Hash *pool;
|
|
|
|
int length;
|
2006-08-11 06:45:39 -07:00
|
|
|
};
|
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_unxml_data
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char *file;
|
|
|
|
char *base;
|
|
|
|
char *path;
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *stack, *merge_stack;
|
2006-08-13 21:41:44 -07:00
|
|
|
int unallocated, level;
|
2006-08-11 06:45:39 -07:00
|
|
|
};
|
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_generate_data
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char *name, *path;
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *rules;
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Hash *pool, *apps;
|
|
|
|
int unallocated;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
Ecore_Desktop_Tree *rule;
|
2006-08-13 21:41:44 -07:00
|
|
|
int include;
|
2006-08-11 06:45:39 -07:00
|
|
|
};
|
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_legacy_data
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *merge;
|
|
|
|
Ecore_Desktop_Tree *current;
|
2006-08-13 21:41:44 -07:00
|
|
|
char *menu;
|
|
|
|
char *prefix;
|
|
|
|
char *path;
|
|
|
|
int length, menu_length, level;
|
2006-08-11 06:45:39 -07:00
|
|
|
};
|
|
|
|
|
2006-08-13 23:49:49 -07:00
|
|
|
static Ecore_Desktop_Tree *_ecore_desktop_menu_get0(char *file, Ecore_Desktop_Tree * merge_stack, int level);
|
2006-08-13 22:44:04 -07:00
|
|
|
static Ecore_Desktop_Tree *_ecore_desktop_menu_create_menu();
|
|
|
|
static int _ecore_desktop_menu_unxml(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree * tree,
|
|
|
|
int element, int level);
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_check_directory(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
char *path);
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_check_menu(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
char *path);
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_legacy_menu_dir(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
char *path);
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_legacy_menu(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
char *path);
|
2006-08-13 22:44:04 -07:00
|
|
|
static void _ecore_desktop_menu_unxml_rules(Ecore_Desktop_Tree * rules,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree * tree,
|
|
|
|
char type, char sub_type);
|
2006-08-13 22:44:04 -07:00
|
|
|
static void _ecore_desktop_menu_unxml_moves(Ecore_Desktop_Tree * menu,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree * tree);
|
2006-08-13 22:44:04 -07:00
|
|
|
static void _ecore_desktop_menu_add_dirs(Ecore_Desktop_Tree * tree,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_List * paths, char *pre,
|
|
|
|
char *post, char *extra,
|
|
|
|
int element);
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_expand_apps(struct
|
|
|
|
_ecore_desktop_menu_unxml_data
|
2006-08-13 21:41:44 -07:00
|
|
|
*unxml_data, char *app_dir,
|
|
|
|
Ecore_Hash * pool);
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_check_app(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
char *path);
|
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_merge(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree * tree,
|
|
|
|
int element, int level);
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_expand_default_dirs(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree
|
|
|
|
* tree,
|
|
|
|
int element,
|
|
|
|
int level);
|
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_generate(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree * tree,
|
|
|
|
int element, int level);
|
2006-08-13 22:44:04 -07:00
|
|
|
static void _ecore_desktop_menu_inherit_apps(void *value,
|
2006-08-13 21:41:44 -07:00
|
|
|
void *user_data);
|
2006-08-13 22:44:04 -07:00
|
|
|
static void _ecore_desktop_menu_select_app(void *value,
|
2006-08-13 21:41:44 -07:00
|
|
|
void *user_data);
|
2006-08-13 22:44:04 -07:00
|
|
|
static int _ecore_desktop_menu_apply_rules(struct
|
|
|
|
_ecore_desktop_menu_generate_data
|
2006-08-13 21:41:44 -07:00
|
|
|
*generate_data,
|
|
|
|
Ecore_Desktop_Tree * rule,
|
|
|
|
char *key,
|
|
|
|
Ecore_Desktop * desktop);
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 23:49:49 -07:00
|
|
|
/**
|
|
|
|
* @defgroup Ecore_Desktop_Menu_Group menu Functions
|
|
|
|
*
|
|
|
|
* Functions that deal with freedesktop.org menus.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decode a freedesktop.org menu XML jungle.
|
|
|
|
*
|
|
|
|
* Using the algorithm specified by freedesktop.org, fully decode
|
|
|
|
* a menu based on an initial menu file.
|
|
|
|
*
|
|
|
|
* @param file The base file for the menu.
|
|
|
|
* @return The resulting menu tree.
|
|
|
|
* @ingroup Ecore_Desktop_Menu_Group
|
|
|
|
*/
|
|
|
|
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *
|
2006-08-13 23:49:49 -07:00
|
|
|
ecore_desktop_menu_get(char *file)
|
|
|
|
{
|
|
|
|
return _ecore_desktop_menu_get0(file, NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Ecore_Desktop_Tree *
|
|
|
|
_ecore_desktop_menu_get0(char *file, Ecore_Desktop_Tree * merge_stack, int level)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *menu_xml;
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_unxml_data data;
|
2006-08-13 21:41:44 -07:00
|
|
|
int oops = 0;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
/* Preperation. */
|
|
|
|
data.stack = ecore_desktop_tree_new(NULL);
|
|
|
|
data.base = ecore_file_strip_ext(ecore_file_get_file(file));
|
|
|
|
data.path = ecore_file_get_dir(file);
|
|
|
|
if ((level == 0) && (merge_stack == NULL))
|
|
|
|
merge_stack = ecore_desktop_tree_new(NULL);
|
|
|
|
menu_xml = ecore_desktop_xmlame_get(file);
|
2006-08-13 21:41:44 -07:00
|
|
|
if ((data.stack) && (data.base) && (data.path) && (merge_stack)
|
|
|
|
&& (menu_xml))
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
int i;
|
|
|
|
|
|
|
|
data.file = file;
|
|
|
|
data.level = level;
|
|
|
|
data.merge_stack = merge_stack;
|
|
|
|
|
|
|
|
/* Setup the merge stack. */
|
|
|
|
if (merge_stack->size <= level)
|
|
|
|
{
|
|
|
|
while (merge_stack->size < level)
|
|
|
|
ecore_desktop_tree_add(merge_stack, "");
|
|
|
|
ecore_desktop_tree_add(merge_stack, file);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
merge_stack->elements[level].element = file;
|
|
|
|
|
|
|
|
/* Find out if we are looping. */
|
|
|
|
for (i = 0; i < level; i++)
|
|
|
|
{
|
|
|
|
char *text;
|
|
|
|
|
|
|
|
/* I can safely assume that they are all strings. */
|
|
|
|
text = (char *)merge_stack->elements[i].element;
|
|
|
|
if (strcmp(text, file) == 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"\n### Oops, infinite menu merging loop detected at %s\n",
|
|
|
|
file);
|
|
|
|
oops++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oops == 0)
|
|
|
|
{
|
|
|
|
/* Get on with it. */
|
2006-08-13 22:44:04 -07:00
|
|
|
ecore_desktop_tree_foreach(menu_xml, 0, _ecore_desktop_menu_unxml,
|
2006-08-13 21:41:44 -07:00
|
|
|
&data);
|
2006-08-13 22:44:04 -07:00
|
|
|
ecore_desktop_tree_foreach(menu_xml, 0, _ecore_desktop_menu_merge,
|
2006-08-13 21:41:44 -07:00
|
|
|
&data);
|
|
|
|
|
|
|
|
/* The rest of this is only done after ALL the menus have been merged. */
|
|
|
|
if (level == 0)
|
|
|
|
{
|
|
|
|
ecore_desktop_tree_foreach(menu_xml, 0,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_expand_default_dirs,
|
2006-08-13 21:41:44 -07:00
|
|
|
&data);
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_desktop_tree_dump(menu_xml, 0);
|
|
|
|
printf("\n\n");
|
2006-08-11 06:45:39 -07:00
|
|
|
#endif
|
|
|
|
|
2006-08-13 21:41:44 -07:00
|
|
|
data.unallocated = FALSE;
|
|
|
|
ecore_desktop_tree_foreach(menu_xml, 0,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_generate,
|
2006-08-13 21:41:44 -07:00
|
|
|
&data);
|
|
|
|
data.unallocated = TRUE;
|
|
|
|
ecore_desktop_tree_foreach(menu_xml, 0,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_generate,
|
2006-08-13 21:41:44 -07:00
|
|
|
&data);
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_desktop_tree_dump(menu_xml, 0);
|
|
|
|
printf("\n\n");
|
2006-08-11 06:45:39 -07:00
|
|
|
#endif
|
2006-08-13 21:41:44 -07:00
|
|
|
}
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
oops++;
|
|
|
|
|
|
|
|
if (oops)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
E_FN_DEL(ecore_desktop_tree_del, (menu_xml));
|
|
|
|
if (level == 0)
|
|
|
|
{
|
|
|
|
E_FN_DEL(ecore_desktop_tree_del, (merge_stack));
|
|
|
|
}
|
|
|
|
E_FREE(data.path);
|
|
|
|
E_FREE(data.base);
|
|
|
|
E_FN_DEL(ecore_desktop_tree_del, (data.stack));
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return menu_xml;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml(const void *data, Ecore_Desktop_Tree * tree,
|
2006-08-13 21:41:44 -07:00
|
|
|
int element, int level)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_unxml_data *unxml_data;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
unxml_data = (struct _ecore_desktop_menu_unxml_data *)data;
|
2006-08-11 06:45:39 -07:00
|
|
|
if (tree->elements[element].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (strncmp((char *)tree->elements[element].element, "<!", 2) == 0)
|
|
|
|
{
|
|
|
|
tree->elements[element].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
|
|
|
tree->elements[element].element = NULL;
|
|
|
|
}
|
|
|
|
else if (strcmp((char *)tree->elements[element].element, "<Menu") == 0)
|
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *menu;
|
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
menu = _ecore_desktop_menu_create_menu();
|
2006-08-13 21:41:44 -07:00
|
|
|
if (menu)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *flags = " ", *name = "", *directory =
|
|
|
|
"", *menu_path = "";
|
2006-08-17 10:09:23 -07:00
|
|
|
char temp[PATH_MAX];
|
2006-08-13 21:41:44 -07:00
|
|
|
|
|
|
|
flags = (char *)menu->elements[0].element;
|
|
|
|
flags += 7;
|
|
|
|
tree->elements[element].element = menu;
|
|
|
|
tree->elements[element].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE;
|
|
|
|
for (i = element + 1; i < tree->size; i++)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
if (tree->elements[i].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
|
|
|
if (strncmp
|
|
|
|
((char *)tree->elements[i].element, "<!",
|
|
|
|
2) == 0)
|
|
|
|
{
|
|
|
|
tree->elements[i].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
|
|
|
tree->elements[i].element = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (strcmp
|
|
|
|
((char *)tree->elements[i].element,
|
|
|
|
"<Deleted/") == 0)
|
|
|
|
{
|
|
|
|
flags[1] = 'D';
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (strcmp
|
|
|
|
((char *)tree->elements[i].element,
|
|
|
|
"<NotDeleted/") == 0)
|
|
|
|
{
|
|
|
|
flags[1] = ' ';
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (strcmp
|
|
|
|
((char *)tree->elements[i].element,
|
|
|
|
"<OnlyUnallocated/") == 0)
|
|
|
|
{
|
|
|
|
flags[2] = 'O';
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (strcmp
|
|
|
|
((char *)tree->elements[i].element,
|
|
|
|
"<NotOnlyUnallocated/") == 0)
|
|
|
|
{
|
|
|
|
flags[2] = ' ';
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (strcmp
|
|
|
|
((char *)tree->elements[i].element,
|
|
|
|
"</Menu") == 0)
|
|
|
|
{
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ecore_desktop_tree_extend(menu,
|
|
|
|
(char *)tree->
|
|
|
|
elements[i].element);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tree->elements[i].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *sub;
|
|
|
|
|
|
|
|
sub =
|
|
|
|
(Ecore_Desktop_Tree *) tree->elements[i].element;
|
|
|
|
if ((sub) && (sub->size))
|
|
|
|
{
|
|
|
|
if (sub->elements[0].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
|
|
|
if (strcmp
|
|
|
|
((char *)sub->elements[0].element,
|
|
|
|
"<Name") == 0)
|
|
|
|
{
|
|
|
|
int i, length = 0;
|
|
|
|
|
|
|
|
name =
|
|
|
|
strdup((char *)sub->elements[1].
|
|
|
|
element);
|
|
|
|
sprintf(temp,
|
|
|
|
"<MENU <%.4s> <%s> <%s>",
|
|
|
|
flags, name, directory);
|
|
|
|
menu->elements[0].element =
|
|
|
|
strdup(temp);
|
|
|
|
ecore_desktop_tree_track(menu, name);
|
|
|
|
ecore_desktop_tree_track(menu,
|
|
|
|
menu->
|
|
|
|
elements[0].
|
|
|
|
element);
|
|
|
|
flags =
|
|
|
|
(char *)menu->elements[0].element;
|
|
|
|
flags += 7;
|
|
|
|
/* The rest of this is probably not needed, except to ease debugging. */
|
|
|
|
if (unxml_data->stack->size <= level)
|
|
|
|
{
|
|
|
|
while (unxml_data->stack->size <
|
|
|
|
level)
|
|
|
|
ecore_desktop_tree_add
|
|
|
|
(unxml_data->stack, "");
|
|
|
|
ecore_desktop_tree_add
|
|
|
|
(unxml_data->stack, name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
unxml_data->stack->
|
|
|
|
elements[level].element = name;
|
|
|
|
temp[0] = '\0';
|
|
|
|
for (i = 0; i <= level; i++)
|
|
|
|
{
|
|
|
|
char *text;
|
|
|
|
|
|
|
|
/* I can safely assume that they are all strings. */
|
|
|
|
text =
|
|
|
|
(char *)unxml_data->stack->
|
|
|
|
elements[i].element;
|
|
|
|
if (text[0] != '\0')
|
|
|
|
{
|
|
|
|
sprintf(&temp[length],
|
|
|
|
"%s%s",
|
|
|
|
((length) ? "/" :
|
|
|
|
""), text);
|
|
|
|
length +=
|
|
|
|
strlen(text) +
|
|
|
|
((length) ? 1 : 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
menu_path = strdup(temp);
|
|
|
|
sprintf(temp, "<MENU_PATH %s",
|
|
|
|
menu_path);
|
|
|
|
menu->elements[1].element =
|
|
|
|
strdup(temp);
|
|
|
|
ecore_desktop_tree_track(menu,
|
|
|
|
menu_path);
|
|
|
|
ecore_desktop_tree_track(menu,
|
|
|
|
menu->
|
|
|
|
elements[1].
|
|
|
|
element);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
/* FIXME: Move this to later in the sequence. */
|
|
|
|
else
|
|
|
|
if (strcmp
|
|
|
|
((char *)sub->elements[0].element,
|
|
|
|
"<Directory") == 0)
|
|
|
|
{
|
|
|
|
directory =
|
|
|
|
strdup((char *)sub->elements[1].
|
|
|
|
element);
|
|
|
|
sprintf(temp,
|
|
|
|
"<MENU <%.4s> <%s> <%s>",
|
|
|
|
flags, name, directory);
|
|
|
|
menu->elements[0].element =
|
|
|
|
strdup(temp);
|
|
|
|
ecore_desktop_tree_track(menu,
|
|
|
|
directory);
|
|
|
|
ecore_desktop_tree_track(menu,
|
|
|
|
menu->
|
|
|
|
elements[0].
|
|
|
|
element);
|
|
|
|
flags =
|
|
|
|
(char *)menu->elements[0].element;
|
|
|
|
flags += 7;
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (strcmp
|
|
|
|
((char *)sub->elements[0].element,
|
|
|
|
"<Menu") == 0)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml(data, sub,
|
2006-08-13 21:41:44 -07:00
|
|
|
0,
|
|
|
|
level +
|
|
|
|
1);
|
|
|
|
ecore_desktop_tree_add_child(menu,
|
|
|
|
(Ecore_Desktop_Tree
|
|
|
|
*)
|
|
|
|
sub->
|
|
|
|
elements
|
|
|
|
[0].
|
|
|
|
element);
|
|
|
|
/* FIXME: Dunno if this causes a memory leak, but for now we play it safe. */
|
|
|
|
tree->elements[i].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
|
|
|
tree->elements[i].element = NULL;
|
2006-08-11 06:45:39 -07:00
|
|
|
// result = 1;
|
2006-08-13 21:41:44 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
if (strcmp
|
|
|
|
((char *)sub->elements[0].element,
|
|
|
|
"<Move") == 0)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml_moves
|
2006-08-13 21:41:44 -07:00
|
|
|
(menu, sub);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((sub->size == 3)
|
|
|
|
&& (sub->elements[1].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
&&
|
|
|
|
(((char *)sub->elements[1].
|
|
|
|
element)[0] != '<'))
|
|
|
|
{
|
|
|
|
char
|
2006-08-17 10:09:23 -07:00
|
|
|
temp[PATH_MAX];
|
2006-08-13 21:41:44 -07:00
|
|
|
|
|
|
|
sprintf(temp, "%s %s",
|
|
|
|
(char *)sub->
|
|
|
|
elements[0].element,
|
|
|
|
(char *)sub->
|
|
|
|
elements[1].element);
|
|
|
|
ecore_desktop_tree_extend(menu,
|
|
|
|
temp);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ecore_desktop_tree_add_child
|
|
|
|
(menu, sub);
|
|
|
|
tree->elements[i].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
|
|
|
tree->elements[i].element =
|
|
|
|
NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
if (tree->elements[i].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
ecore_desktop_tree_del((Ecore_Desktop_Tree *)
|
|
|
|
tree->elements[i].
|
|
|
|
element);
|
|
|
|
tree->elements[i].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
|
|
|
tree->elements[i].element = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add it if it has not been deleted. */
|
|
|
|
if (flags[1] != 'D')
|
|
|
|
{
|
|
|
|
tree->elements[element].element = menu;
|
|
|
|
tree->elements[element].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Ecore_Desktop_Tree *
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_create_menu()
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *menu, *rules;
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Hash *pool, *apps;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
menu = ecore_desktop_tree_new(NULL);
|
|
|
|
rules = ecore_desktop_tree_new(NULL);
|
|
|
|
pool = ecore_hash_new(ecore_str_hash, ecore_str_compare);
|
|
|
|
apps = ecore_hash_new(ecore_str_hash, ecore_str_compare);
|
|
|
|
if ((menu) && (rules) && (pool) && (apps))
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_hash_set_free_key(pool, free);
|
|
|
|
ecore_hash_set_free_value(pool, free);
|
|
|
|
ecore_hash_set_free_key(apps, free);
|
|
|
|
ecore_hash_set_free_value(apps, free);
|
|
|
|
ecore_desktop_tree_extend(menu, "<MENU < > <> <>");
|
|
|
|
ecore_desktop_tree_extend(menu, "<MENU_PATH ");
|
|
|
|
ecore_desktop_tree_add_hash(menu, pool);
|
|
|
|
ecore_desktop_tree_add_child(menu, rules);
|
|
|
|
ecore_desktop_tree_add_hash(menu, apps);
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (apps)
|
|
|
|
ecore_hash_destroy(apps);
|
|
|
|
if (pool)
|
|
|
|
ecore_hash_destroy(pool);
|
|
|
|
if (rules)
|
|
|
|
ecore_desktop_tree_del(rules);
|
|
|
|
if (menu)
|
|
|
|
ecore_desktop_tree_del(menu);
|
2006-08-11 06:45:39 -07:00
|
|
|
menu = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_check_directory(const void *data, char *path)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char *p;
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *merge;
|
|
|
|
|
|
|
|
merge = (Ecore_Desktop_Tree *) data;
|
|
|
|
p = strrchr(path, '.');
|
|
|
|
if (p)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (strcmp(p, ".directory") == 0)
|
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char merge_file[PATH_MAX];
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 21:41:44 -07:00
|
|
|
sprintf(merge_file, "<Directory %s", path);
|
|
|
|
ecore_desktop_tree_extend(merge, merge_file);
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_check_menu(const void *data, char *path)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char *p;
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *merge;
|
|
|
|
|
|
|
|
merge = (Ecore_Desktop_Tree *) data;
|
|
|
|
p = strrchr(path, '.');
|
|
|
|
if (p)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (strcmp(p, ".menu") == 0)
|
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char merge_file[PATH_MAX];
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 21:41:44 -07:00
|
|
|
sprintf(merge_file, "<MergeFile type=\"path\" %s", path);
|
|
|
|
ecore_desktop_tree_extend(merge, merge_file);
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_legacy_menu_dir(const void *data, char *path)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_legacy_data *legacy_data;
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *menu;
|
2006-08-13 21:41:44 -07:00
|
|
|
int start;
|
|
|
|
int i, count = 0;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
legacy_data = (struct _ecore_desktop_menu_legacy_data *)data;
|
2006-08-11 06:45:39 -07:00
|
|
|
for (i = legacy_data->length; path[i] != '\0'; i++)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (path[i] == '/')
|
|
|
|
count++;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
if (count == 1)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
legacy_data->current = legacy_data->merge;
|
|
|
|
legacy_data->level = 0;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
else if (count <= legacy_data->level)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if ((legacy_data->current) && (legacy_data->current->parent))
|
|
|
|
{
|
2006-08-11 06:45:39 -07:00
|
|
|
legacy_data->current = legacy_data->current->parent;
|
2006-08-13 21:41:44 -07:00
|
|
|
legacy_data->level--;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
start = legacy_data->length;
|
|
|
|
count = 0;
|
|
|
|
for (i = legacy_data->length; path[i] != '\0'; i++)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (path[i] == '/')
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
|
|
|
if (count >= legacy_data->level)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
path[i] = '\0';
|
2006-08-13 22:44:04 -07:00
|
|
|
menu = _ecore_desktop_menu_create_menu();
|
2006-08-13 21:41:44 -07:00
|
|
|
if (menu)
|
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char temp[PATH_MAX];
|
2006-08-13 21:41:44 -07:00
|
|
|
|
|
|
|
sprintf(temp, "<MENU < L> <%s> <>", &path[start]);
|
|
|
|
menu->elements[0].element = strdup(temp);
|
|
|
|
ecore_desktop_tree_track(menu,
|
|
|
|
menu->elements[0].element);
|
|
|
|
sprintf(temp, "<MENU_PATH %s/%s", legacy_data->menu,
|
|
|
|
&path[legacy_data->length]);
|
|
|
|
menu->elements[1].element = strdup(temp);
|
|
|
|
ecore_desktop_tree_track(menu,
|
|
|
|
menu->elements[1].element);
|
|
|
|
|
|
|
|
ecore_desktop_tree_add_child(legacy_data->current, menu);
|
|
|
|
/* This is not needed, but if it was, this is where it would go.
|
|
|
|
* sprintf(temp, "<AppDir %s/", path);
|
|
|
|
* ecore_desktop_tree_extend(menu, temp);
|
|
|
|
*/
|
|
|
|
sprintf(temp, "<DirectoryDir %s/", path);
|
|
|
|
ecore_desktop_tree_extend(menu, temp);
|
|
|
|
|
|
|
|
legacy_data->current = menu;
|
|
|
|
legacy_data->level++;
|
|
|
|
}
|
|
|
|
path[i] = '/';
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
start = i + 1;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
legacy_data->level = count;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_legacy_menu(const void *data, char *path)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_legacy_data *legacy_data;
|
2006-08-13 21:41:44 -07:00
|
|
|
char *menu_path, *file;
|
2006-08-17 10:09:23 -07:00
|
|
|
char temp[PATH_MAX];
|
2006-08-13 21:41:44 -07:00
|
|
|
int i, count = 0, menu_count = 0;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
legacy_data = (struct _ecore_desktop_menu_legacy_data *)data;
|
2006-08-11 06:45:39 -07:00
|
|
|
if ((legacy_data->current) && (legacy_data->current->size > 0) &&
|
2006-08-13 21:41:44 -07:00
|
|
|
(legacy_data->current->elements[1].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING))
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
menu_path = (char *)legacy_data->current->elements[1].element;
|
|
|
|
menu_path += 12 + legacy_data->menu_length;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
menu_path = "";
|
|
|
|
printf(" PROBLEM IN LEGACYDIR FILE - %s - %s %s\n",
|
|
|
|
legacy_data->prefix, legacy_data->path,
|
|
|
|
&path[legacy_data->length]);
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = legacy_data->length; path[i] != '\0'; i++)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (path[i] == '/')
|
|
|
|
count++;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
for (i = 0; menu_path[i] != '\0'; i++)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (menu_path[i] == '/')
|
|
|
|
menu_count++;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
while (menu_count >= count)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
legacy_data->current = legacy_data->current->parent;
|
|
|
|
menu_count--;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
if ((legacy_data->current) && (legacy_data->current->size > 0) &&
|
2006-08-13 21:41:44 -07:00
|
|
|
(legacy_data->current->elements[1].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING))
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
menu_path = (char *)legacy_data->current->elements[1].element;
|
|
|
|
menu_path += 12 + legacy_data->menu_length;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
/* FIXME: Bugger, a corner case.
|
2006-08-11 06:45:39 -07:00
|
|
|
* If this is .directory, then maybe ignore it?
|
|
|
|
* If this is a desktop, we need to put it into the pool of the menu that legacy_data->merge will get merged into.
|
2006-08-13 21:41:44 -07:00
|
|
|
*/
|
|
|
|
menu_path = "";
|
|
|
|
printf(" LEGACYDIR FILE - %s - %s %s\n", legacy_data->prefix,
|
|
|
|
legacy_data->path, &path[legacy_data->length]);
|
2006-08-11 06:45:39 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2006-08-13 21:41:44 -07:00
|
|
|
|
2006-08-11 06:45:39 -07:00
|
|
|
menu_count = strlen(menu_path);
|
|
|
|
if (menu_count)
|
|
|
|
menu_count++;
|
|
|
|
file = &path[legacy_data->length + menu_count];
|
|
|
|
count = strlen(file);
|
2006-08-13 21:41:44 -07:00
|
|
|
|
2006-08-11 06:45:39 -07:00
|
|
|
if (strcmp(".directory", file) == 0)
|
|
|
|
{
|
|
|
|
menu_path = (char *)legacy_data->current->elements[0].element;
|
|
|
|
menu_count = strlen(menu_path);
|
|
|
|
menu_path[menu_count - 3] = '\0';
|
2006-08-13 21:41:44 -07:00
|
|
|
sprintf(temp, "%s <.directory>", menu_path);
|
|
|
|
legacy_data->current->elements[0].element = strdup(temp);
|
|
|
|
ecore_desktop_tree_track(legacy_data->current,
|
|
|
|
legacy_data->current->elements[0].element);
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
else if (strcmp(".desktop", &file[count - 8]) == 0)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Hash *pool;
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *rules;
|
|
|
|
|
2006-08-13 21:41:44 -07:00
|
|
|
pool = (Ecore_Hash *) legacy_data->current->elements[2].element;
|
|
|
|
rules =
|
|
|
|
(Ecore_Desktop_Tree *) legacy_data->current->elements[3].element;
|
2006-08-11 06:45:39 -07:00
|
|
|
if (rules->size == 0)
|
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *new_rules;
|
|
|
|
|
2006-08-13 21:41:44 -07:00
|
|
|
new_rules = ecore_desktop_tree_new(NULL);
|
2006-08-11 06:45:39 -07:00
|
|
|
if (new_rules)
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_desktop_tree_add_child(rules, new_rules);
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
sprintf(temp, "%s%s", legacy_data->prefix, file);
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_hash_set(pool, strdup(temp), strdup(path));
|
2006-08-11 06:45:39 -07:00
|
|
|
if (rules->size > 0)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
rules = (Ecore_Desktop_Tree *) rules->elements[0].element;
|
2006-08-11 06:45:39 -07:00
|
|
|
sprintf(temp, "IOF %s%s", legacy_data->prefix, file);
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_desktop_tree_extend(rules, temp);
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml_rules(Ecore_Desktop_Tree * rules,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree * tree, char type,
|
|
|
|
char sub_type)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
int i;
|
2006-08-17 10:09:23 -07:00
|
|
|
char temp[PATH_MAX];
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
for (i = 0; i < tree->size; i++)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (tree->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
|
|
|
if (strcmp((char *)tree->elements[i].element, "<All/") == 0)
|
|
|
|
{
|
|
|
|
sprintf(temp, "%c%cA", type, sub_type);
|
|
|
|
ecore_desktop_tree_extend(rules, temp);
|
|
|
|
}
|
|
|
|
else if (strcmp((char *)tree->elements[i].element, "<Filename") ==
|
|
|
|
0)
|
|
|
|
{
|
|
|
|
sprintf(temp, "%c%cF %s", type, sub_type,
|
|
|
|
(char *)tree->elements[i + 1].element);
|
|
|
|
ecore_desktop_tree_extend(rules, temp);
|
|
|
|
}
|
|
|
|
else if (strcmp((char *)tree->elements[i].element, "<Category") ==
|
|
|
|
0)
|
|
|
|
{
|
|
|
|
sprintf(temp, "%c%cC %s", type, sub_type,
|
|
|
|
(char *)tree->elements[i + 1].element);
|
|
|
|
ecore_desktop_tree_extend(rules, temp);
|
|
|
|
}
|
|
|
|
else if (strcmp((char *)tree->elements[i].element, "<Or") == 0)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml_rules(rules,
|
2006-08-13 21:41:44 -07:00
|
|
|
(Ecore_Desktop_Tree *) tree->
|
|
|
|
elements[i + 1].element,
|
|
|
|
type, sub_type);
|
|
|
|
}
|
|
|
|
else if ((strcmp((char *)tree->elements[i].element, "<And") == 0)
|
|
|
|
|| (strcmp((char *)tree->elements[i].element, "<Not") ==
|
|
|
|
0))
|
|
|
|
{
|
|
|
|
char this_type;
|
|
|
|
Ecore_Desktop_Tree *sub;
|
|
|
|
|
|
|
|
this_type = ((char *)tree->elements[i].element)[1];
|
|
|
|
sub = ecore_desktop_tree_new(NULL);
|
|
|
|
if (sub)
|
|
|
|
{
|
|
|
|
ecore_desktop_tree_add_child(rules, sub);
|
|
|
|
for (i++; i < tree->size; i++)
|
|
|
|
{
|
|
|
|
if (tree->elements[i].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml_rules(sub,
|
2006-08-13 21:41:44 -07:00
|
|
|
(Ecore_Desktop_Tree
|
|
|
|
*) tree->
|
|
|
|
elements[i].
|
|
|
|
element, type,
|
|
|
|
this_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tree->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml_rules(rules,
|
2006-08-13 21:41:44 -07:00
|
|
|
(Ecore_Desktop_Tree *) tree->
|
|
|
|
elements[i].element, type,
|
|
|
|
sub_type);
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml_moves(Ecore_Desktop_Tree * menu,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree * tree)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
int i;
|
|
|
|
char *old = NULL;
|
|
|
|
char *new = NULL;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
for (i = 0; i < tree->size; i++)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (tree->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *sub;
|
|
|
|
|
|
|
|
sub = (Ecore_Desktop_Tree *) tree->elements[i].element;
|
|
|
|
if ((sub) && (sub->size))
|
|
|
|
{
|
|
|
|
if (sub->elements[0].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
|
|
|
if (strcmp((char *)sub->elements[0].element, "<Old") ==
|
|
|
|
0)
|
|
|
|
old = strdup((char *)sub->elements[1].element);
|
|
|
|
if (strcmp((char *)sub->elements[0].element, "<New") ==
|
|
|
|
0)
|
|
|
|
new = strdup((char *)sub->elements[1].element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((old) && (new))
|
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char temp[PATH_MAX * 2];
|
2006-08-13 21:41:44 -07:00
|
|
|
|
|
|
|
sprintf(temp, "<MOVE <%s> <%s>", old, new);
|
|
|
|
ecore_desktop_tree_extend(menu, temp);
|
|
|
|
free(old);
|
|
|
|
old = NULL;
|
|
|
|
free(new);
|
|
|
|
new = NULL;
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_add_dirs(Ecore_Desktop_Tree * tree, Ecore_List * paths,
|
2006-08-13 21:41:44 -07:00
|
|
|
char *pre, char *post, char *extra, int element)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char t[PATH_MAX], *this_path;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
/* reverse the order of the dirs. */
|
|
|
|
ecore_list_goto_first(paths);
|
|
|
|
while ((this_path = ecore_list_next(paths)) != NULL)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (extra)
|
|
|
|
sprintf(t, "%s %s%s-merged/", pre, this_path, extra);
|
|
|
|
else
|
|
|
|
sprintf(t, "%s %s", pre, this_path);
|
|
|
|
if (tree)
|
|
|
|
ecore_desktop_tree_extend(tree, t);
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_expand_apps(struct _ecore_desktop_menu_unxml_data
|
2006-08-13 21:41:44 -07:00
|
|
|
*unxml_data, char *app_dir, Ecore_Hash * pool)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
|
|
|
if (pool)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_expand_apps_data our_data;
|
2006-08-17 10:09:23 -07:00
|
|
|
char dir[PATH_MAX];
|
2006-08-13 21:41:44 -07:00
|
|
|
|
|
|
|
our_data.pool = pool;
|
|
|
|
sprintf(dir, "%s", app_dir);
|
|
|
|
if (dir[0] != '/')
|
|
|
|
sprintf(dir, "%s/%s", unxml_data->path, app_dir);
|
|
|
|
our_data.path = dir;
|
|
|
|
our_data.length = strlen(dir);
|
|
|
|
ecore_desktop_paths_recursive_search(dir, NULL, NULL,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_check_app,
|
2006-08-13 21:41:44 -07:00
|
|
|
&our_data);
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_check_app(const void *data, char *path)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char *p;
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_expand_apps_data *our_data;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
our_data = (struct _ecore_desktop_menu_expand_apps_data *)data;
|
2006-08-11 06:45:39 -07:00
|
|
|
p = strrchr(path, '.');
|
|
|
|
if (p)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (strcmp(p, ".desktop") == 0)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *file;
|
|
|
|
|
|
|
|
file = strdup(path + our_data->length);
|
|
|
|
if ((file) && (path))
|
|
|
|
{
|
|
|
|
for (i = 0; file[i] != '\0'; i++)
|
|
|
|
if (file[i] == '/')
|
|
|
|
file[i] = '-';
|
|
|
|
ecore_hash_set(our_data->pool, file, strdup(path));
|
|
|
|
}
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_merge(const void *data, Ecore_Desktop_Tree * tree,
|
2006-08-13 21:41:44 -07:00
|
|
|
int element, int level)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_unxml_data *unxml_data;
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *merge;
|
2006-08-13 21:41:44 -07:00
|
|
|
int result = 0;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
unxml_data = (struct _ecore_desktop_menu_unxml_data *)data;
|
2006-08-11 06:45:39 -07:00
|
|
|
merge = ecore_desktop_tree_new(NULL);
|
|
|
|
if (tree->elements[element].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char *string;
|
|
|
|
|
|
|
|
string = (char *)tree->elements[element].element;
|
|
|
|
if (strcmp(string, "<DefaultMergeDirs/") == 0)
|
|
|
|
{
|
|
|
|
if (unxml_data->base)
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_add_dirs(merge, ecore_desktop_paths_menus,
|
2006-08-13 21:41:44 -07:00
|
|
|
"<MergeDir", "</MergeDir",
|
|
|
|
unxml_data->base, element);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else if (strcmp(string, "<KDELegacyDirs/") == 0)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_add_dirs(merge,
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_desktop_paths_kde_legacy,
|
|
|
|
"<LegacyDir prefix=\"kde-\"",
|
|
|
|
"</LegacyDir", NULL, element);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else if (strncmp(string, "<MergeDir ", 10) == 0)
|
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char merge_path[PATH_MAX];
|
2006-08-13 21:41:44 -07:00
|
|
|
|
|
|
|
if (string[10] == '/')
|
|
|
|
sprintf(merge_path, "%s", &string[10]);
|
|
|
|
else
|
|
|
|
sprintf(merge_path, "%s%s", unxml_data->path, &string[10]);
|
|
|
|
ecore_desktop_paths_recursive_search(merge_path, NULL, NULL,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_check_menu,
|
2006-08-13 21:41:44 -07:00
|
|
|
merge);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else if (strncmp(string, "<LegacyDir ", 11) == 0)
|
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char merge_path[PATH_MAX];
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_legacy_data legacy_data;
|
2006-08-13 21:41:44 -07:00
|
|
|
|
|
|
|
string += 11;
|
|
|
|
legacy_data.prefix = NULL;
|
|
|
|
legacy_data.merge = merge;
|
|
|
|
legacy_data.current = merge;
|
2006-08-11 06:45:39 -07:00
|
|
|
legacy_data.level = 0;
|
|
|
|
legacy_data.menu = (char *)tree->elements[0].element;
|
|
|
|
legacy_data.menu += 14;
|
2006-08-13 21:41:44 -07:00
|
|
|
legacy_data.menu_length =
|
|
|
|
index(legacy_data.menu, '>') - legacy_data.menu;
|
2006-08-11 06:45:39 -07:00
|
|
|
legacy_data.menu[legacy_data.menu_length] = '\0';
|
2006-08-13 21:41:44 -07:00
|
|
|
if (strncmp(string, "prefix=\"", 8) == 0)
|
|
|
|
{
|
|
|
|
string += 8;
|
|
|
|
legacy_data.prefix = string;
|
|
|
|
while ((*string != '"') && (*string != '\0'))
|
|
|
|
string++;
|
|
|
|
if (*string != '\0')
|
|
|
|
*string++ = '\0';
|
|
|
|
while ((*string == ' ') && (*string != '\0'))
|
|
|
|
string++;
|
|
|
|
}
|
|
|
|
if (string[0] == '/')
|
|
|
|
sprintf(merge_path, "%s", string);
|
|
|
|
else
|
|
|
|
sprintf(merge_path, "%s%s", unxml_data->path, string);
|
|
|
|
legacy_data.path = merge_path;
|
|
|
|
legacy_data.length = strlen(merge_path);
|
2006-08-11 06:45:39 -07:00
|
|
|
#ifdef DEBUG
|
2006-08-13 21:41:44 -07:00
|
|
|
printf("<LEGACYDIR> - %s - %s\n", legacy_data.prefix, merge_path);
|
2006-08-11 06:45:39 -07:00
|
|
|
#endif
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_desktop_paths_recursive_search(merge_path, NULL,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_legacy_menu_dir,
|
|
|
|
_ecore_desktop_menu_legacy_menu,
|
2006-08-13 21:41:44 -07:00
|
|
|
&legacy_data);
|
2006-08-11 06:45:39 -07:00
|
|
|
legacy_data.menu[legacy_data.menu_length] = '>';
|
2006-08-13 21:41:44 -07:00
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else if (strncmp(string, "<MergeFile ", 11) == 0)
|
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char merge_path[PATH_MAX];
|
2006-08-13 21:41:44 -07:00
|
|
|
int path_type = 1;
|
|
|
|
|
|
|
|
/* FIXME: need to weed out duplicate <MergeFile's, use the last one. */
|
|
|
|
string += 11;
|
|
|
|
if (strncmp(string, "type=\"", 6) == 0)
|
|
|
|
{
|
|
|
|
string += 6;
|
|
|
|
if (strncmp(string, "parent\"", 7) == 0)
|
|
|
|
path_type = 0;
|
|
|
|
while ((*string != '"') && (*string != '\0'))
|
|
|
|
string++;
|
|
|
|
if (*string != '\0')
|
|
|
|
string++;
|
|
|
|
while ((*string == ' ') && (*string != '\0'))
|
|
|
|
string++;
|
|
|
|
}
|
|
|
|
if (path_type)
|
|
|
|
{
|
|
|
|
if (string[0] == '/')
|
|
|
|
sprintf(merge_path, "%s", string);
|
|
|
|
else
|
|
|
|
sprintf(merge_path, "%s/%s", unxml_data->path, string);
|
|
|
|
}
|
|
|
|
else /* This is a parent type MergeFile. */
|
|
|
|
{
|
|
|
|
/* The spec is a little unclear, and the examples may look like they
|
|
|
|
* contradict the description, but it all makes sense if you cross
|
|
|
|
* reference it with the XDG Base Directory Specification (version 0.6).
|
|
|
|
* To make things harder, parent type MergeFiles never appear on my box.
|
|
|
|
*
|
|
|
|
* What you do is this.
|
|
|
|
*
|
|
|
|
* Take the XDG_CONFIG_DIRS stuff as a whole ($XDG_CONFIG_HOME, then
|
|
|
|
* $XDG_CONFIG_DIRS), in this code that will be ecore_desktop_paths_config.
|
|
|
|
*
|
|
|
|
* If this menu file is from one of the directories in ecore_desktop_paths_config,
|
|
|
|
* scan the rest of ecore_desktop_paths_config looking for the new menu. In other
|
|
|
|
* words start searching in the next ecore_desktop_paths_config entry after the one
|
|
|
|
* that this menu is in.
|
|
|
|
*
|
|
|
|
* The file to look for is the path to this menu with the portion from
|
|
|
|
* ecore_desktop_paths_config stripped off the beginning. For instance, the top level
|
|
|
|
* menu file is typically /etc/xdg/menus/applications.menu, and /etc/xdg is
|
|
|
|
* typically in ecore_desktop_paths_config, so search for menus/applications.menu.
|
|
|
|
*
|
|
|
|
* If this menu file is NOT from one of the directories in ecore_desktop_paths_menus,
|
|
|
|
* insert nothing.
|
|
|
|
*
|
|
|
|
* The first one found wins, if none are found, don't merge anything.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* FIXME: Actually implement this when I have some menus that will exercise it. */
|
|
|
|
merge_path[0] = '\0';
|
|
|
|
printf("\n### Didn't expect a MergeFile parent type\n");
|
|
|
|
}
|
|
|
|
if (merge_path[0] != '\0')
|
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *new_menu;
|
|
|
|
|
|
|
|
new_menu =
|
2006-08-13 23:49:49 -07:00
|
|
|
_ecore_desktop_menu_get0(merge_path,
|
2006-08-13 21:41:44 -07:00
|
|
|
unxml_data->merge_stack,
|
|
|
|
level + 1);
|
|
|
|
if (new_menu)
|
|
|
|
{
|
|
|
|
if (new_menu->size > 1)
|
|
|
|
{
|
|
|
|
if (new_menu->elements[1].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
{
|
|
|
|
new_menu =
|
|
|
|
(Ecore_Desktop_Tree *) new_menu->
|
|
|
|
elements[1].element;
|
|
|
|
if (new_menu->size > 0)
|
|
|
|
{
|
|
|
|
if (new_menu->elements[0].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
{
|
|
|
|
merge =
|
|
|
|
(Ecore_Desktop_Tree *) new_menu->
|
|
|
|
elements[0].element;
|
|
|
|
ecore_desktop_tree_remove(merge, 0);
|
|
|
|
ecore_desktop_tree_remove(merge, 1);
|
|
|
|
ecore_desktop_tree_remove(merge, 2);
|
|
|
|
ecore_desktop_tree_remove(merge, 3);
|
|
|
|
ecore_desktop_tree_remove(merge, 4);
|
|
|
|
/* FIXME: The MENU_PATHs need to be prefixed. */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf
|
2006-08-13 22:44:04 -07:00
|
|
|
("FUCK an error in _ecore_desktop_menu_merge(%s)\n",
|
2006-08-13 21:41:44 -07:00
|
|
|
merge_path);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf
|
2006-08-13 22:44:04 -07:00
|
|
|
("FUCK another error in _ecore_desktop_menu_merge(%s)\n",
|
2006-08-13 21:41:44 -07:00
|
|
|
merge_path);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf
|
2006-08-13 22:44:04 -07:00
|
|
|
("FUCK ME! An error in _ecore_desktop_menu_merge(%s)\n",
|
2006-08-13 21:41:44 -07:00
|
|
|
merge_path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result = 1;
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if ((merge) && (merge->size))
|
|
|
|
ecore_desktop_tree_merge(tree, element + 1, merge);
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 21:41:44 -07:00
|
|
|
tree->elements[element].type = ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
|
|
|
tree->elements[element].element = NULL;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_expand_default_dirs(const void *data,
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree * tree, int element,
|
|
|
|
int level)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_unxml_data *unxml_data;
|
2006-08-11 06:45:39 -07:00
|
|
|
Ecore_Desktop_Tree *merge;
|
2006-08-13 21:41:44 -07:00
|
|
|
int result = 0;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
unxml_data = (struct _ecore_desktop_menu_unxml_data *)data;
|
2006-08-11 06:45:39 -07:00
|
|
|
merge = ecore_desktop_tree_new(NULL);
|
|
|
|
if (tree->elements[element].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char *string;
|
|
|
|
|
|
|
|
string = (char *)tree->elements[element].element;
|
|
|
|
if (strcmp(string, "<DefaultAppDirs/") == 0)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_add_dirs(merge, ecore_desktop_paths_desktops,
|
2006-08-13 21:41:44 -07:00
|
|
|
"<AppDir", "</AppDir", NULL,
|
|
|
|
element);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else if (strcmp(string, "<DefaultDirectoryDirs/") == 0)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_add_dirs(merge,
|
2006-08-13 21:41:44 -07:00
|
|
|
ecore_desktop_paths_directories,
|
|
|
|
"<DirectoryDir", "</DirectoryDir",
|
|
|
|
NULL, element);
|
|
|
|
result = 1;
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
if (result)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if ((merge) && (merge->size))
|
|
|
|
ecore_desktop_tree_merge(tree, element + 1, merge);
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 21:41:44 -07:00
|
|
|
tree->elements[element].type = ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
|
|
|
tree->elements[element].element = NULL;
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_generate(const void *data, Ecore_Desktop_Tree * tree,
|
2006-08-13 21:41:44 -07:00
|
|
|
int element, int level)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_unxml_data *unxml_data;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
unxml_data = (struct _ecore_desktop_menu_unxml_data *)data;
|
2006-08-11 06:45:39 -07:00
|
|
|
if (tree->elements[element].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (strncmp((char *)tree->elements[element].element, "<MENU ", 6) == 0)
|
|
|
|
{
|
|
|
|
int i;
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_generate_data generate_data;
|
2006-08-13 21:41:44 -07:00
|
|
|
|
|
|
|
generate_data.unallocated = unxml_data->unallocated;
|
|
|
|
generate_data.name = (char *)tree->elements[element].element;
|
|
|
|
generate_data.path = (char *)tree->elements[element + 1].element;
|
|
|
|
generate_data.pool =
|
|
|
|
(Ecore_Hash *) tree->elements[element + 2].element;
|
|
|
|
generate_data.rules =
|
|
|
|
(Ecore_Desktop_Tree *) tree->elements[element + 3].element;
|
|
|
|
generate_data.apps =
|
|
|
|
(Ecore_Hash *) tree->elements[element + 4].element;
|
|
|
|
|
|
|
|
/* generate and inherit the pools on the first pass, and preparse the include/exclude logic. */
|
|
|
|
if (!generate_data.unallocated)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = element + 5; i < tree->size; i++)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
char *string;
|
|
|
|
|
|
|
|
if (tree->elements[i].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
|
|
|
string = (char *)tree->elements[i].element;
|
|
|
|
if (strncmp(string, "<AppDir ", 8) == 0)
|
|
|
|
{
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_expand_apps(unxml_data,
|
2006-08-13 21:41:44 -07:00
|
|
|
&string[8],
|
|
|
|
generate_data.
|
|
|
|
pool);
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
else if (strncmp(string, "<DirectoryDir ", 14) == 0)
|
|
|
|
{
|
2006-08-17 10:09:23 -07:00
|
|
|
char merge_path[PATH_MAX];
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Desktop_Tree *merge;
|
|
|
|
|
|
|
|
if (string[14] == '/')
|
|
|
|
sprintf(merge_path, "%s", &string[14]);
|
|
|
|
else
|
|
|
|
sprintf(merge_path, "%s%s",
|
|
|
|
unxml_data->path, &string[14]);
|
|
|
|
merge = ecore_desktop_tree_new(NULL);
|
|
|
|
if (merge)
|
|
|
|
{
|
|
|
|
ecore_desktop_paths_recursive_search
|
|
|
|
(merge_path, NULL, NULL,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_check_directory,
|
2006-08-13 21:41:44 -07:00
|
|
|
merge);
|
|
|
|
ecore_desktop_tree_merge(tree, i + 1,
|
|
|
|
merge);
|
|
|
|
}
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tree->elements[i].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *sub;
|
|
|
|
|
|
|
|
sub =
|
|
|
|
(Ecore_Desktop_Tree *) tree->elements[i].element;
|
|
|
|
if ((sub) && (sub->size))
|
|
|
|
{
|
|
|
|
if (sub->elements[0].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING)
|
|
|
|
{
|
|
|
|
string = (char *)sub->elements[0].element;
|
|
|
|
if ((strcmp(string, "<Include") == 0)
|
|
|
|
|| (strcmp(string, "<Exclude") == 0))
|
|
|
|
{
|
|
|
|
Ecore_Desktop_Tree *new_sub;
|
|
|
|
|
|
|
|
new_sub =
|
|
|
|
ecore_desktop_tree_new(NULL);
|
|
|
|
if (new_sub)
|
|
|
|
{
|
|
|
|
ecore_desktop_tree_add_child
|
|
|
|
(generate_data.rules,
|
|
|
|
new_sub);
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_unxml_rules
|
2006-08-13 21:41:44 -07:00
|
|
|
(new_sub, sub, string[1],
|
|
|
|
'O');
|
|
|
|
}
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
tree->elements[i].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
|
|
|
tree->elements[i].element = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unxml_data->stack->size <= level)
|
|
|
|
{
|
|
|
|
while (unxml_data->stack->size < level)
|
|
|
|
ecore_desktop_tree_add_hash(unxml_data->stack,
|
|
|
|
generate_data.pool);
|
|
|
|
ecore_desktop_tree_add_hash(unxml_data->stack,
|
|
|
|
generate_data.pool);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unxml_data->stack->elements[level].type =
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_HASH;
|
|
|
|
unxml_data->stack->elements[level].element =
|
|
|
|
generate_data.pool;
|
|
|
|
}
|
|
|
|
for (i = level - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (unxml_data->stack->elements[i].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_HASH)
|
|
|
|
{
|
|
|
|
Ecore_Hash *ancestor;
|
|
|
|
|
|
|
|
ancestor =
|
|
|
|
(Ecore_Hash *) unxml_data->stack->elements[i].
|
|
|
|
element;
|
|
|
|
ecore_hash_for_each_node(ancestor,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_inherit_apps,
|
2006-08-13 21:41:44 -07:00
|
|
|
generate_data.pool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process the rules. */
|
|
|
|
if (generate_data.name[9] ==
|
|
|
|
(generate_data.unallocated ? 'O' : ' '))
|
|
|
|
{
|
2006-08-11 06:45:39 -07:00
|
|
|
#ifdef DEBUG
|
2006-08-13 21:41:44 -07:00
|
|
|
printf("MAKING MENU - %s \t\t%s\n", generate_data.path,
|
|
|
|
generate_data.name);
|
2006-08-11 06:45:39 -07:00
|
|
|
#endif
|
2006-08-13 21:41:44 -07:00
|
|
|
for (i = 0; i < generate_data.rules->size; i++)
|
|
|
|
{
|
|
|
|
if (generate_data.rules->elements[i].type ==
|
|
|
|
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
{
|
|
|
|
generate_data.rule =
|
|
|
|
(Ecore_Desktop_Tree *) generate_data.rules->
|
|
|
|
elements[i].element;
|
|
|
|
if (generate_data.rule->size > 0)
|
|
|
|
{
|
|
|
|
if (((char *)generate_data.rule->elements[0].
|
|
|
|
element)[0] == 'I')
|
|
|
|
{
|
|
|
|
generate_data.include = TRUE;
|
|
|
|
ecore_hash_for_each_node(generate_data.
|
|
|
|
pool,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_select_app,
|
2006-08-13 21:41:44 -07:00
|
|
|
&generate_data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
generate_data.include = FALSE;
|
|
|
|
ecore_hash_for_each_node(generate_data.
|
|
|
|
apps,
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_select_app,
|
2006-08-13 21:41:44 -07:00
|
|
|
&generate_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf("Fuck, a bug in _ecore_desktop_menus.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_inherit_apps(void *value, void *user_data)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Hash_Node *node;
|
|
|
|
Ecore_Hash *pool;
|
|
|
|
char *key, *app;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
pool = (Ecore_Hash *) user_data;
|
|
|
|
node = (Ecore_Hash_Node *) value;
|
|
|
|
key = (char *)node->key;
|
|
|
|
app = (char *)node->value;
|
|
|
|
if (!ecore_hash_get(pool, key))
|
|
|
|
ecore_hash_set(pool, strdup(key), strdup(app));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_select_app(void *value, void *user_data)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
Ecore_Hash_Node *node;
|
|
|
|
Ecore_Desktop *desktop;
|
2006-08-13 22:44:04 -07:00
|
|
|
struct _ecore_desktop_menu_generate_data *generate_data;
|
2006-08-13 21:41:44 -07:00
|
|
|
char *key, *app;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
node = (Ecore_Hash_Node *) value;
|
2006-08-13 22:44:04 -07:00
|
|
|
generate_data = (struct _ecore_desktop_menu_generate_data *)user_data;
|
2006-08-11 06:45:39 -07:00
|
|
|
key = (char *)node->key;
|
|
|
|
app = (char *)node->value;
|
|
|
|
|
2006-08-14 14:42:53 -07:00
|
|
|
/* FIXME: pass an actualy language parameter. */
|
|
|
|
desktop = ecore_desktop_get(app, NULL);
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
if ((generate_data->unallocated) && (desktop->allocated))
|
|
|
|
return;
|
|
|
|
|
2006-08-13 22:44:04 -07:00
|
|
|
if (_ecore_desktop_menu_apply_rules
|
2006-08-13 21:41:44 -07:00
|
|
|
(generate_data, generate_data->rule, key, desktop))
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
desktop->allocated = TRUE;
|
|
|
|
if (generate_data->include)
|
|
|
|
{
|
|
|
|
ecore_hash_set(generate_data->apps, key, strdup(app));
|
2006-08-11 06:45:39 -07:00
|
|
|
#ifdef DEBUG
|
2006-08-13 21:41:44 -07:00
|
|
|
printf("INCLUDING %s%s\n",
|
|
|
|
((generate_data->unallocated) ? "UNALLOCATED " : ""), key);
|
2006-08-11 06:45:39 -07:00
|
|
|
#endif
|
2006-08-13 21:41:44 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ecore_hash_remove(generate_data->apps, key);
|
2006-08-11 06:45:39 -07:00
|
|
|
#ifdef DEBUG
|
2006-08-13 21:41:44 -07:00
|
|
|
printf("EXCLUDING %s%s\n",
|
|
|
|
((generate_data->unallocated) ? "UNALLOCATED " : ""), key);
|
2006-08-11 06:45:39 -07:00
|
|
|
#endif
|
2006-08-13 21:41:44 -07:00
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_apply_rules(struct _ecore_desktop_menu_generate_data
|
2006-08-13 21:41:44 -07:00
|
|
|
*generate_data, Ecore_Desktop_Tree * rule,
|
|
|
|
char *key, Ecore_Desktop * desktop)
|
2006-08-11 06:45:39 -07:00
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
char type = 'O';
|
|
|
|
int result = FALSE;
|
|
|
|
int i;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
for (i = 0; i < rule->size; i++)
|
|
|
|
{
|
2006-08-13 21:41:44 -07:00
|
|
|
if (rule->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
|
|
|
{
|
|
|
|
result =
|
2006-08-13 22:44:04 -07:00
|
|
|
_ecore_desktop_menu_apply_rules(generate_data,
|
2006-08-13 21:41:44 -07:00
|
|
|
(Ecore_Desktop_Tree *) rule->
|
|
|
|
elements[i].element, key,
|
|
|
|
desktop);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *rul;
|
|
|
|
char match;
|
|
|
|
int sub_result = FALSE;
|
|
|
|
|
|
|
|
rul = (char *)rule->elements[i].element;
|
|
|
|
type = rul[1];
|
|
|
|
match = rul[2];
|
|
|
|
switch (match)
|
|
|
|
{
|
|
|
|
case 'A':
|
|
|
|
{
|
|
|
|
sub_result = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'F':
|
|
|
|
{
|
|
|
|
if (strcmp(key, &rul[4]) == 0)
|
|
|
|
sub_result = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'C':
|
|
|
|
{
|
|
|
|
/* Try to match a category. */
|
|
|
|
if (desktop->Categories)
|
|
|
|
{
|
2006-08-11 06:45:39 -07:00
|
|
|
// int j;
|
|
|
|
|
2006-08-13 21:41:44 -07:00
|
|
|
if (ecore_hash_get(desktop->Categories, &rul[4]) !=
|
|
|
|
NULL)
|
|
|
|
sub_result = TRUE;
|
2006-08-11 06:45:39 -07:00
|
|
|
|
|
|
|
// for (j = 0; j < desktop->Categories->size; j++)
|
|
|
|
// {
|
|
|
|
// if (strcmp((char *)(desktop->Categories->elements[j].element), &rul[4]) == 0)
|
|
|
|
// {
|
|
|
|
// sub_result = TRUE;
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// }
|
2006-08-13 21:41:44 -07:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 'A':
|
|
|
|
{
|
|
|
|
result = TRUE;
|
|
|
|
if (!sub_result)
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'N':
|
|
|
|
{
|
|
|
|
result = TRUE;
|
|
|
|
if (sub_result)
|
|
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
if (sub_result)
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-08-11 06:45:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
OR (implied)
|
|
|
|
loop through the rules
|
|
|
|
as soon as one matches, return true
|
|
|
|
otherwise return false.
|
|
|
|
|
|
|
|
SUB RULES
|
|
|
|
process the sub rules, return the result
|
|
|
|
|
|
|
|
AND
|
|
|
|
loop through the rules
|
|
|
|
as soon as one doesn't match, return false
|
|
|
|
otherwise return true.
|
|
|
|
|
|
|
|
NOT (implied OR)
|
|
|
|
loop through the rules
|
|
|
|
as soon as one matches, return false
|
|
|
|
otherwise return true.
|
|
|
|
|
|
|
|
ALL
|
|
|
|
return true
|
|
|
|
|
|
|
|
FILENAME
|
|
|
|
if the rule string matches the desktop id return true
|
|
|
|
otherwise return false
|
|
|
|
|
|
|
|
CATEGORY
|
|
|
|
loop through the apps categories
|
|
|
|
as soon as one matches the rule string, return true
|
|
|
|
otherwise return false.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
merge menus
|
|
|
|
* expand <KDELegacyDir>'s to <LegacyDir>.
|
|
|
|
* expand <LegacyDir>'s
|
|
|
|
* for each dir (recursive)
|
|
|
|
* create recursively nested <MENU < L> <dirname> <> element
|
|
|
|
* // <AppDir>dirpath</AppDir>
|
|
|
|
* <DirectoryDir>dirpath</DirectoryDir>
|
|
|
|
* if exist .directory
|
|
|
|
* add <.directory> to name
|
|
|
|
* <Include>
|
|
|
|
* for each *.desktop
|
|
|
|
if no categories in bar.desktop
|
|
|
|
* <Filename>prefix-bar.desktop</Filename>
|
|
|
|
add "Legacy" to categories
|
|
|
|
* add any prefix to the desktop ID.
|
|
|
|
* add it to the pool
|
|
|
|
* </Include>
|
|
|
|
* for each <MergeFile>, and <MergeDir> element
|
|
|
|
* get the root <Menu> elements from that elements file/s.
|
|
|
|
* remove the <Name> element from those root <Menu> elements.
|
|
|
|
* replace that element with the child elements of those root <Menu> elements.
|
|
|
|
* expand the <DefaultMergeDirs> with the name/s of that elements file/s
|
|
|
|
* loop until all <MergeFile>, <MergeDir>, and <LegacyDir> elements are done,
|
|
|
|
* careful to avoid infinite loops in files that reference each other.
|
|
|
|
* for each <Menu> recursively
|
|
|
|
consolidate duplicate child <Menu>s.
|
|
|
|
* expand <DefaultAppDir>s and <DefaultDirectoryDir>s to <AppDir>s and <DirectoryDir>s.
|
|
|
|
consolidate duplicate child <AppDir>s, <DirectoryDir>s, and <Directory>s.
|
|
|
|
resolve duplicate <Move>s.
|
|
|
|
for each <Menu> recursively
|
|
|
|
for each <Move>
|
|
|
|
do the move.
|
|
|
|
mark any <Menu> that has been affected.
|
|
|
|
for each marked <Menu> recursively
|
|
|
|
consolidate duplicate child <Menu>s.
|
|
|
|
* for each <Menu> recursively
|
|
|
|
* if there are <Deleted> elements that are not ovreridden by a <NotDelete> element
|
|
|
|
* remove this <Menu> element and all it's children.
|
|
|
|
|
|
|
|
*generate menus
|
|
|
|
* for each <Menu> that is <NotOnlyUnallocated> (which is the default)
|
|
|
|
* for each <AppDir>
|
|
|
|
* for each .desktop
|
|
|
|
* if it exists in the pool, replace it.
|
|
|
|
* else add it to the pool.
|
|
|
|
* for each parent <Menu>
|
|
|
|
* for each .desktop in the pool
|
|
|
|
* if it doesn't exist in the child <Menu> pool
|
|
|
|
* add it to the pool.
|
|
|
|
* for each <Include> and <Exclude>
|
|
|
|
* if rule is an <Include>
|
|
|
|
* for each .desktop in pool
|
|
|
|
* for each rule
|
|
|
|
* if rule matches .desktop in pool
|
|
|
|
* add .desktop to menu.
|
|
|
|
* mark it as allocated
|
|
|
|
* if rule is an <Exclude>
|
|
|
|
* for each .desktop in menu
|
|
|
|
* for each rule
|
|
|
|
* if rule matches .desktop in menu
|
|
|
|
* remove .desktop from menu.
|
|
|
|
* leave it as allocated.
|
|
|
|
|
|
|
|
<Menu (tree)
|
|
|
|
name
|
|
|
|
flags = " " or "MDO" the first letter of - Marked, Deleted, OnlyUnallocated
|
|
|
|
pool (hash)
|
|
|
|
id = path
|
|
|
|
id = path
|
|
|
|
rules (tree)
|
|
|
|
rule
|
|
|
|
rule
|
|
|
|
menu (hash)
|
|
|
|
id = path
|
|
|
|
id = path
|
|
|
|
<Menu (tree)
|
|
|
|
<Menu (tree)
|
|
|
|
|
|
|
|
rules (tree)
|
|
|
|
include/exclude or all/file/category x
|
|
|
|
and/not (tree)
|
|
|
|
include/exclude and/not all/file/category x
|
|
|
|
|
|
|
|
*generate unallocated menus
|
|
|
|
* Same as for menus, but only the <OnlyUnallocated> ones.
|
|
|
|
* Only the unallocated .desktop entries can be used.
|
|
|
|
|
|
|
|
generate menu layout
|
|
|
|
*/
|