forked from enlightenment/efl
Freedesktop.org desktop, icon, and menu support as per the discussion in
the mailing list. It's not ready yet. It needs documentation, EFL conformant naming, and a good whipping into shape by indent. The ecore integration needs a reveiw, see if I got that right. Consider this a preview, it's mostly there, just needs some tweking. SVN revision: 24560
This commit is contained in:
parent
f864ccd8e6
commit
ae95df23ab
|
@ -28,6 +28,7 @@ EXTRA_DIST = AUTHORS COPYING COPYING-PLAIN ecore.c.in gendoc ecore.supp ecore.m4
|
|||
debian/libecore0-con.install \
|
||||
debian/libecore0-config.install \
|
||||
debian/libecore0-dbus.install \
|
||||
debian/libecore0-desktop.install \
|
||||
debian/libecore0-dev.install \
|
||||
debian/libecore0-evas.install \
|
||||
debian/libecore0-fb.install \
|
||||
|
|
|
@ -921,7 +921,6 @@ fi
|
|||
AC_SUBST(ecore_ipc_cflags)
|
||||
AC_SUBST(ecore_ipc_libs)
|
||||
|
||||
|
||||
AC_MSG_CHECKING(whether ecore_dbus module is to be built)
|
||||
want_ecore_dbus="yes";
|
||||
have_ecore_dbus="no";
|
||||
|
@ -968,7 +967,6 @@ AC_SUBST(dbus_libs)
|
|||
AC_SUBST(ecore_dbus_cflags)
|
||||
AC_SUBST(ecore_dbus_libs)
|
||||
|
||||
|
||||
AC_MSG_CHECKING(whether ecore_config module is to be built)
|
||||
|
||||
want_ecore_config="yes";
|
||||
|
@ -1155,6 +1153,45 @@ fi
|
|||
AC_SUBST(fam_libs)
|
||||
AC_SUBST(ecore_file_libs)
|
||||
|
||||
|
||||
if test "x$have_ecore_file" = "xyes"; then
|
||||
AC_MSG_CHECKING(whether ecore_desktop module is to be built)
|
||||
want_ecore_desktop="yes";
|
||||
have_ecore_desktop="no";
|
||||
ecore_desktop_cflags="";
|
||||
ecore_desktop_libs="";
|
||||
|
||||
AC_ARG_ENABLE(ecore-desktop,
|
||||
[ --disable-ecore-desktop disable the ecore_desktop module],
|
||||
[
|
||||
if test x"$enableval" = x"yes" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
want_ecore_desktop="no"
|
||||
fi
|
||||
], [
|
||||
AC_MSG_RESULT(yes)
|
||||
]
|
||||
)
|
||||
|
||||
if test "x$want_ecore_desktop" = "xyes"; then
|
||||
AM_CONDITIONAL(BUILD_ECORE_DESKTOP, true)
|
||||
AC_DEFINE(BUILD_ECORE_DESKTOP, 1, [Build Ecore_Desktop Module])
|
||||
have_ecore_desktop="yes"
|
||||
ecore_desktop_libs="-lecore_desktop";
|
||||
else
|
||||
AM_CONDITIONAL(BUILD_ECORE_DESKTOP, false)
|
||||
fi
|
||||
|
||||
AC_SUBST(ecore_desktop_cflags)
|
||||
AC_SUBST(ecore_desktop_libs)
|
||||
else
|
||||
AC_MSG_RESULT(ecore_file not enabled so ecore_desktop will not be enabled)
|
||||
want_ecore_desktop="no"
|
||||
fi
|
||||
|
||||
|
||||
AC_ARG_ENABLE(pthreads,
|
||||
[ --disable-pthreads disable building with pthread support],
|
||||
[
|
||||
|
@ -1224,6 +1261,7 @@ src/lib/ecore_txt/Makefile
|
|||
src/lib/ecore_config/Makefile
|
||||
src/lib/ecore_file/Makefile
|
||||
src/lib/ecore_dbus/Makefile
|
||||
src/lib/ecore_desktop/Makefile
|
||||
src/lib/ecore_directfb/Makefile
|
||||
examples/Makefile
|
||||
ecore-config
|
||||
|
@ -1254,6 +1292,7 @@ echo " Ecore_Buffer.................: $have_ecore_evas_buffer"
|
|||
echo " Ecore_Ipc....................: $have_ecore_ipc (OpenSSL: $use_openssl)"
|
||||
echo " Ecore_Config.................: $have_ecore_config"
|
||||
echo " Ecore_DBUS...................: $have_ecore_dbus"
|
||||
echo " Ecore_Desktop................: $have_ecore_desktop"
|
||||
#echo " Ecore_File...................: $have_ecore_file (Inotify: $use_inotify) (FAM: $use_fam) (Poll: $use_poll)"
|
||||
echo " Ecore_File...................: $have_ecore_file (Inotify: $use_inotify) (Poll: $use_poll) (CURL: $use_curl)"
|
||||
echo
|
||||
|
|
|
@ -56,6 +56,19 @@ Description: Ecore DBus Library
|
|||
applications.
|
||||
This package contains the Ecore DBus Library.
|
||||
|
||||
Package: libecore0-desktop
|
||||
Architecture: any
|
||||
Section: libs
|
||||
Depends: ${shlibs:Depends}, libecore0 (= ${Source-Version}), libecore-file
|
||||
Provides: libecore-desktop
|
||||
Description: Ecore freedesktop.org .desktop, icon, menu parsing Library
|
||||
This is the core event abstraction layer and X abstraction layer that makes
|
||||
doing selections, Xdnd, general X stuff, and event loops, timeouts and idle
|
||||
handlers fast, optimized, and convenient. It's a separate library so anyone
|
||||
can make use of the work put into Ecore to make this job easy for
|
||||
applications.
|
||||
This package contains the Ecore freedesktop.org .desktop, icon, menu parsing Library.
|
||||
|
||||
Package: libecore0-evas
|
||||
Architecture: any
|
||||
Section: libs
|
||||
|
@ -152,7 +165,7 @@ Package: libecore0-all
|
|||
Architecture: any
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: libecore0 (= ${Source-Version}), libecore-config, libecore-con, libecore-dbus, libecore-evas, libecore-fb, libecore-file, libecore-ipc, libecore-job, libecore-txt, libecore-x
|
||||
Depends: libecore0 (= ${Source-Version}), libecore-config, libecore-con, libecore-dbus, libecore-desktop, libecore-evas, libecore-fb, libecore-file, libecore-ipc, libecore-job, libecore-txt, libecore-x
|
||||
Provides: libecore-all
|
||||
Description: Virtual package providing all available Ecore modules.
|
||||
This is the core event abstraction layer and X abstraction layer that makes
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
debian/tmp/usr/lib/libecore_desktop.so.*
|
|
@ -2,6 +2,7 @@ debian/tmp/usr/include/Ecore_Config.h
|
|||
debian/tmp/usr/include/Ecore_Con.h
|
||||
debian/tmp/usr/include/Ecore_Data.h
|
||||
debian/tmp/usr/include/Ecore_DBus.h
|
||||
debian/tmp/usr/include/Ecore_Desktop.h
|
||||
debian/tmp/usr/include/Ecore_Evas.h
|
||||
debian/tmp/usr/include/Ecore_Fb.h
|
||||
debian/tmp/usr/include/Ecore_File.h
|
||||
|
@ -24,6 +25,9 @@ debian/tmp/usr/lib/libecore_config.so
|
|||
debian/tmp/usr/lib/libecore_dbus.a
|
||||
debian/tmp/usr/lib/libecore_dbus.la
|
||||
debian/tmp/usr/lib/libecore_dbus.so
|
||||
debian/tmp/usr/lib/libecore_desktop.a
|
||||
debian/tmp/usr/lib/libecore_desktop.la
|
||||
debian/tmp/usr/lib/libecore_desktop.so
|
||||
debian/tmp/usr/lib/libecore_evas.a
|
||||
debian/tmp/usr/lib/libecore_evas.la
|
||||
debian/tmp/usr/lib/libecore_evas.so
|
||||
|
|
|
@ -6,8 +6,8 @@ exec_prefix_set=no
|
|||
|
||||
usage() {
|
||||
echo "Usage: ecore-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]" 1>&2
|
||||
echo " [--libs-con] [--libs-config] [--libs-dbus] [--libs-evas] [--libs-fb]" 1>&2
|
||||
echo " [--libs-file] [--libs-ipc] [--libs-job] [--libs-txt] [--libs-x]" 1>&2
|
||||
echo " [--libs-con] [--libs-config] [--libs-dbus] [--libs-desktop] [--libs-evas]" 1>&2
|
||||
echo " [--libs-fb] [--libs-file] [--libs-ipc] [--libs-job] [--libs-txt] [--libs-x]" 1>&2
|
||||
}
|
||||
|
||||
if test $# -eq 0; then
|
||||
|
@ -49,7 +49,7 @@ while test $# -gt 0; do
|
|||
;;
|
||||
--libs)
|
||||
libdirs=-L@libdir@
|
||||
echo $libdirs -lecore @ecore_job_libs@ @ecore_x_libs@ @ecore_evas_libs@ @ecore_con_libs@ @ecore_ipc_libs@ @ecore_txt_libs@ @ecore_fb_libs@ @ecore_config_libs@ @ecore_file_libs@ @ecore_dbus_libs@ @SSL_LIBS@ @winsock_libs@ @CURL_LIBS@ @EET_LIBS@ @EVAS_LIBS@ @x_libs@ @Xcursor_libs@ @Xrender_libs@ @Xprint_libs@ @Xinerama_libs@ @Xrandr_libs@ @Xfixes_libs@ @Xdamage_libs@ @Xss_libs@ @iconv_libs@ @tslib_libs@ @fam_libs@ -lm
|
||||
echo $libdirs -lecore @ecore_job_libs@ @ecore_x_libs@ @ecore_evas_libs@ @ecore_con_libs@ @ecore_ipc_libs@ @ecore_txt_libs@ @ecore_fb_libs@ @ecore_config_libs@ @ecore_file_libs@ @ecore_desktop_libs@ @ecore_dbus_libs@ @SSL_LIBS@ @winsock_libs@ @CURL_LIBS@ @EET_LIBS@ @EVAS_LIBS@ @x_libs@ @Xcursor_libs@ @Xrender_libs@ @Xprint_libs@ @Xinerama_libs@ @Xrandr_libs@ @Xfixes_libs@ @Xdamage_libs@ @Xss_libs@ @iconv_libs@ @tslib_libs@ @fam_libs@ -lm
|
||||
;;
|
||||
--libs-con)
|
||||
libdirs=-L@libdir@
|
||||
|
@ -63,6 +63,10 @@ while test $# -gt 0; do
|
|||
libdirs=-L@libdir@
|
||||
echo $libdirs -lecore @ecore_dbus_libs@ @SSL_LIBS@ -lm
|
||||
;;
|
||||
--libs-desktop)
|
||||
libdirs=-L@libdir@
|
||||
echo $libdirs -lecore @ecore_desktop_libs@ @ecore_file_libs@ -lm
|
||||
;;
|
||||
--libs-evas)
|
||||
libdirs=-L@libdir@
|
||||
echo $libdirs -lecore @ecore_evas_libs@ @EVAS_LIBS@ @ecore_x_libs@ @x_libs@ @Xcursor_libs@ @Xrender_libs@ @Xprint_libs@ @Xinerama_libs@ @Xrandr_libs@ @Xfixes_libs@ @Xdamage_libs@ @Xss_libs@ @ecore_txt_libs@ @iconv_libs@ @ecore_job_libs@ @ecore_fb_libs@ @tslib_libs@ -lm
|
||||
|
|
|
@ -27,7 +27,7 @@ Summary: Ecore headers and development libraries.
|
|||
Group: Development/Libraries
|
||||
Requires: %{name} = %{version}
|
||||
Requires: openssl-devel, evas-devel, eet-devel
|
||||
Requires: ecore-con, ecore-config, ecore-dbus, ecore-evas, ecore-fb, ecore-file, ecore-ipc, ecore-job, ecore-txt, ecore-x
|
||||
Requires: ecore-con, ecore-config, ecore-dbus, ecore-desktop, ecore-evas, ecore-fb, ecore-file, ecore-ipc, ecore-job, ecore-txt, ecore-x
|
||||
|
||||
%description devel
|
||||
Ecore development files
|
||||
|
@ -69,6 +69,11 @@ Summary: Ecore DBus Library
|
|||
Group: Development/Libraries
|
||||
Requires: %{name} = %{version}
|
||||
|
||||
%package desktop
|
||||
Summary: Ecore freedesktop.org .desktop, icon, menu parsing Library
|
||||
Group: Development/Libraries
|
||||
Requires: %{name} = %{version}
|
||||
|
||||
%description dbus
|
||||
Ecore DBus Library
|
||||
|
||||
|
@ -189,6 +194,10 @@ test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT
|
|||
%defattr(-, root, root)
|
||||
%{_libdir}/libecore_dbus.so.*
|
||||
|
||||
%files desktop
|
||||
%defattr(-, root, root)
|
||||
%{_libdir}/libecore_desktop.so.*
|
||||
|
||||
%files evas
|
||||
%defattr(-, root, root)
|
||||
%{_libdir}/libecore_evas.so.*
|
||||
|
|
|
@ -11,4 +11,5 @@ ecore_ipc \
|
|||
ecore_evas \
|
||||
ecore_config \
|
||||
ecore_file \
|
||||
ecore_desktop \
|
||||
ecore_dbus
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
.deps
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.lo
|
||||
*.la
|
|
@ -0,0 +1,122 @@
|
|||
#ifndef _ECORE_DESKTOP_H
|
||||
# define _ECORE_DESKTOP_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <Ecore_Data.h>
|
||||
|
||||
#define MAX_PATH 4096
|
||||
|
||||
#define E_FN_DEL(_fn, _h) if (_h) { _fn(_h); _h = NULL; }
|
||||
#define E_REALLOC(p, s, n) p = (s *)realloc(p, sizeof(s) * n)
|
||||
#define E_NEW(s, n) (s *)calloc(n, sizeof(s))
|
||||
#define E_NEW_BIG(s, n) (s *)malloc(n * sizeof(s))
|
||||
#define E_FREE(p) { if (p) {free(p); p = NULL;} }
|
||||
|
||||
Ecore_List *ecore_desktop_paths_config;
|
||||
Ecore_List *ecore_desktop_paths_menus;
|
||||
Ecore_List *ecore_desktop_paths_directories;
|
||||
Ecore_List *ecore_desktop_paths_desktops;
|
||||
Ecore_List *ecore_desktop_paths_icons;
|
||||
Ecore_List *ecore_desktop_paths_kde_legacy;
|
||||
|
||||
struct _Ecore_Desktop
|
||||
{
|
||||
Ecore_Hash *data, *group, *Categories, *OnlyShowIn, *NotShowIn;
|
||||
char *name;
|
||||
char *generic;
|
||||
char *comment;
|
||||
char *type;
|
||||
char *categories;
|
||||
char *exec;
|
||||
char *icon;
|
||||
char *icon_path;
|
||||
char *startup;
|
||||
char *window_class;
|
||||
int allocated; /* FIXME: NoDisplay, Hidden */
|
||||
};
|
||||
typedef struct _Ecore_Desktop Ecore_Desktop;
|
||||
|
||||
enum _Ecore_Desktop_Tree_Element_Type
|
||||
{
|
||||
ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL = 0,
|
||||
ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING = 1,
|
||||
ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE = 2,
|
||||
ECORE_DESKTOP_TREE_ELEMENT_TYPE_HASH = 3,
|
||||
};
|
||||
typedef enum _Ecore_Desktop_Tree_Element_Type Ecore_Desktop_Tree_Element_Type;
|
||||
|
||||
struct _Ecore_Desktop_Tree_Element
|
||||
{
|
||||
void *element; /* A pointer to the element. */
|
||||
Ecore_Desktop_Tree_Element_Type type; /* The type of the element. */
|
||||
};
|
||||
typedef struct _Ecore_Desktop_Tree_Element Ecore_Desktop_Tree_Element;
|
||||
|
||||
typedef struct _Ecore_Desktop_Tree Ecore_Desktop_Tree;
|
||||
struct _Ecore_Desktop_Tree
|
||||
{
|
||||
Ecore_Desktop_Tree_Element *elements; /* An array of elements. */
|
||||
int size; /* The size of the array. */
|
||||
char **buffers; /* An array of pointers to the bits of data. */
|
||||
int buffers_size; /* The size of the array. */
|
||||
Ecore_Desktop_Tree *parent; /* Parent if this is a child. */
|
||||
};
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
# endif
|
||||
|
||||
/* Function Prototypes */
|
||||
void ecore_desktop_paths_init(void);
|
||||
char *ecore_desktop_paths_search_for_file(Ecore_List *paths, char *file, int sub, int (*func) (const void *data, char *path), const void *data);
|
||||
char *ecore_desktop_paths_recursive_search(char *path, char *d, int (*dir_func) (const void *data, char *path), int (*func) (const void *data, char *path), const void *data);
|
||||
void ecore_desktop_paths_shutdown(void);
|
||||
|
||||
Ecore_Hash *ecore_desktop_hash_from_paths(char *paths);
|
||||
Ecore_List *ecore_desktop_list_from_paths(char *paths);
|
||||
|
||||
|
||||
void ecore_desktop_init(void);
|
||||
void ecore_desktop_shutdown(void);
|
||||
Ecore_Hash *ecore_desktop_parse_ini_file(char *file);
|
||||
Ecore_Desktop *ecore_desktop_parse_file(char *file);
|
||||
void ecore_desktop_destroy(Ecore_Desktop * desktop);
|
||||
|
||||
|
||||
char *ecore_desktop_find_icon(char *icon, char *icon_size, char *icon_theme);
|
||||
|
||||
|
||||
Ecore_Desktop_Tree *ecore_desktop_menus_get(char *file, Ecore_Desktop_Tree * merge_stack, int level);
|
||||
|
||||
|
||||
Ecore_Desktop_Tree *ecore_desktop_tree_new(char *buffer);
|
||||
Ecore_Desktop_Tree *ecore_desktop_tree_add(Ecore_Desktop_Tree * tree, char *element);
|
||||
void ecore_desktop_tree_track(Ecore_Desktop_Tree * tree, void *element);
|
||||
Ecore_Desktop_Tree *ecore_desktop_tree_extend(Ecore_Desktop_Tree * tree, char *element);
|
||||
Ecore_Desktop_Tree *ecore_desktop_tree_insert(Ecore_Desktop_Tree * tree, int before, void *element, Ecore_Desktop_Tree_Element_Type type);
|
||||
Ecore_Desktop_Tree *ecore_desktop_tree_merge(Ecore_Desktop_Tree * tree, int before, Ecore_Desktop_Tree * element);
|
||||
Ecore_Desktop_Tree *ecore_desktop_tree_add_child(Ecore_Desktop_Tree * tree, Ecore_Desktop_Tree * element);
|
||||
Ecore_Desktop_Tree *ecore_desktop_tree_add_hash(Ecore_Desktop_Tree * tree, Ecore_Hash * element);
|
||||
void ecore_desktop_tree_remove(Ecore_Desktop_Tree * tree, int element);
|
||||
int ecore_desktop_tree_exist(Ecore_Desktop_Tree * tree, char *element);
|
||||
int ecore_desktop_tree_foreach(Ecore_Desktop_Tree * tree, int level, int (*func) (const void *data, Ecore_Desktop_Tree * tree, int element, int level), const void *data);
|
||||
void ecore_esktop_tree_dump(Ecore_Desktop_Tree * tree, int level);
|
||||
void ecore_desktop_tree_del(Ecore_Desktop_Tree * tree);
|
||||
|
||||
|
||||
Ecore_Desktop_Tree *ecore_desktop_xmlame_new(char *buffer);
|
||||
Ecore_Desktop_Tree *ecore_desktop_xmlame_get(char *file);
|
||||
|
||||
char *ecore_desktop_get_home(void);
|
||||
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src/lib/ecore \
|
||||
-I$(top_builddir)/src/lib/ecore_file \
|
||||
-I$(top_builddir)/src/lib/ecore_desktop \
|
||||
-I$(top_builddir)/src/lib/ecore \
|
||||
-I$(top_srcdir)/src/lib/ecore_file \
|
||||
-I$(top_srcdir)/src/lib/ecore_desktop
|
||||
|
||||
libecore_desktop_la_LDFLAGS = -version-info 1:0:0 \
|
||||
-L$(top_builddir)/src/lib/ecore/.libs \
|
||||
-L$(top_builddir)/src/lib/ecore_file/.libs
|
||||
|
||||
if BUILD_ECORE_DESKTOP
|
||||
|
||||
lib_LTLIBRARIES = libecore_desktop.la
|
||||
include_HEADERS = \
|
||||
Ecore_Desktop.h
|
||||
|
||||
libecore_desktop_la_SOURCES = \
|
||||
ecore_desktop.c \
|
||||
ecore_desktop_tree.c \
|
||||
ecore_desktop_icon.c \
|
||||
ecore_desktop_menu.c \
|
||||
ecore_desktop_paths.c \
|
||||
ecore_desktop_xmlame.c \
|
||||
ecore_desktop_private.h
|
||||
|
||||
libecore_desktop_la_LIBADD = \
|
||||
$(top_builddir)/src/lib/ecore/libecore.la \
|
||||
$(top_builddir)/src/lib/ecore_file/libecore_file.la
|
||||
|
||||
libecore_desktop_la_DEPENDENCIES = \
|
||||
$(top_builddir)/src/lib/ecore/libecore.la \
|
||||
$(top_builddir)/src/lib/ecore_file/libecore_file.la
|
||||
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
Ecore_Desktop.h \
|
||||
ecore_desktop.c \
|
||||
ecore_desktop_tree.c \
|
||||
ecore_desktop_icon.c \
|
||||
ecore_desktop_menu.c \
|
||||
ecore_desktop_paths.c \
|
||||
ecore_desktop_xmlame.c \
|
||||
ecore_desktop_private.h
|
|
@ -0,0 +1,237 @@
|
|||
#include "Ecore_Desktop.h"
|
||||
#include "ecore_desktop_private.h"
|
||||
|
||||
extern int reject_count, not_over_count;
|
||||
|
||||
static Ecore_Hash *ini_file_cache;
|
||||
static Ecore_Hash *desktop_cache;
|
||||
|
||||
|
||||
Ecore_Hash *
|
||||
ecore_desktop_parse_ini_file(char *file)
|
||||
{
|
||||
Ecore_Hash *result;
|
||||
|
||||
/* FIXME: should probably look in ini_file_cache first. */
|
||||
result = ecore_hash_new(ecore_str_hash, ecore_str_compare);
|
||||
if (result)
|
||||
{
|
||||
FILE *f;
|
||||
char buffer[MAX_PATH];
|
||||
Ecore_Hash *current = NULL;
|
||||
|
||||
f = fopen(file, "r");
|
||||
if (!f)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Cannot Open File %s\n", file);
|
||||
ecore_hash_destroy(result);
|
||||
return NULL;
|
||||
}
|
||||
ecore_hash_set_free_key(result, free);
|
||||
ecore_hash_set_free_value(result, (Ecore_Free_Cb) ecore_hash_destroy);
|
||||
*buffer = '\0';
|
||||
#ifdef DEBUG
|
||||
fprintf(stdout, "PARSING INI %s\n", file);
|
||||
#endif
|
||||
while (fgets(buffer, sizeof(buffer), f) != NULL)
|
||||
{
|
||||
char *c;
|
||||
char *key;
|
||||
char *value;
|
||||
|
||||
c = buffer;
|
||||
/* Strip preceeding blanks. */
|
||||
while (((*c == ' ') || (*c == '\t')) && (*c != '\n') && (*c != '\0'))
|
||||
c++;
|
||||
/* Skip blank lines and comments */
|
||||
if ((*c == '\0') || (*c == '\n') || (*c == '#'))
|
||||
continue;
|
||||
if (*c == '[') /* New group. */
|
||||
{
|
||||
key = c + 1;
|
||||
while ((*c != ']') && (*c != '\n') && (*c != '\0'))
|
||||
c++;
|
||||
*c++ = '\0';
|
||||
current = ecore_hash_new(ecore_str_hash, ecore_str_compare);
|
||||
if (current)
|
||||
{
|
||||
ecore_hash_set_free_key(current, free);
|
||||
ecore_hash_set_free_value(current, free);
|
||||
ecore_hash_set(result, strdup(key), current);
|
||||
#ifdef DEBUG
|
||||
fprintf(stdout, " GROUP [%s]\n", key);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (current) /* key=value pair of current group. */
|
||||
{
|
||||
key = c;
|
||||
/* Find trailing blanks or =. */
|
||||
while ((*c != '=') && (*c != ' ') && (*c != '\t') && (*c != '\n') && (*c != '\0'))
|
||||
c++;
|
||||
if (*c != '=') /* Find equals. */
|
||||
{
|
||||
*c++ = '\0';
|
||||
while ((*c != '=') && (*c != '\n') && (*c != '\0'))
|
||||
c++;
|
||||
}
|
||||
if (*c == '=') /* Equals found. */
|
||||
{
|
||||
*c++ = '\0';
|
||||
/* Strip preceeding blanks. */
|
||||
while (((*c == ' ') || (*c == '\t')) && (*c != '\n') && (*c != '\0'))
|
||||
c++;
|
||||
value = c;
|
||||
/* Find end. */
|
||||
while ((*c != '\n') && (*c != '\0'))
|
||||
c++;
|
||||
*c++ = '\0';
|
||||
/* FIXME: should strip space at end, then unescape value. */
|
||||
ecore_hash_set(current, strdup(key), strdup(value));
|
||||
#ifdef DEBUG
|
||||
fprintf(stdout, " %s=%s\n", key, value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
buffer[0] = (char)0;
|
||||
|
||||
fclose(f);
|
||||
ecore_hash_set(ini_file_cache, strdup(file), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Ecore_Desktop *
|
||||
ecore_desktop_parse_file(char *file)
|
||||
{
|
||||
Ecore_Desktop *result;
|
||||
|
||||
result = (Ecore_Desktop *) ecore_hash_get(desktop_cache, file);
|
||||
if (!result)
|
||||
{
|
||||
result = calloc(1, sizeof(Ecore_Desktop));
|
||||
if (result)
|
||||
{
|
||||
result->data = ecore_desktop_parse_ini_file(file);
|
||||
if (result->data)
|
||||
{
|
||||
result->group = (Ecore_Hash *) ecore_hash_get(result->data, "Desktop Entry");
|
||||
if (!result->group)
|
||||
result->group = (Ecore_Hash *) ecore_hash_get(result->data, "KDE Desktop Entry");
|
||||
if (result->group)
|
||||
{
|
||||
char *value;
|
||||
|
||||
result->name = (char *)ecore_hash_get(result->group, "Name");
|
||||
result->generic = (char *)ecore_hash_get(result->group, "GenericName");
|
||||
result->comment = (char *)ecore_hash_get(result->group, "Comment");
|
||||
result->type = (char *)ecore_hash_get(result->group, "Type");
|
||||
result->exec = (char *)ecore_hash_get(result->group, "Exec");
|
||||
result->window_class = (char *)ecore_hash_get(result->group, "StartupWMClass");
|
||||
result->icon = (char *)ecore_hash_get(result->group, "Icon");
|
||||
result->categories = (char *)ecore_hash_get(result->group, "Categories");
|
||||
if (result->categories)
|
||||
result->Categories = ecore_desktop_hash_from_paths(result->categories);
|
||||
value = (char *)ecore_hash_get(result->group, "OnlyShowIn");
|
||||
if (value)
|
||||
result->OnlyShowIn = ecore_desktop_hash_from_paths(value);
|
||||
value = (char *)ecore_hash_get(result->group, "NotShowIn");
|
||||
if (value)
|
||||
result->NotShowIn = ecore_desktop_hash_from_paths(value);
|
||||
value = (char *)ecore_hash_get(result->group, "X-KDE-StartupNotify");
|
||||
if (value)
|
||||
result->startup = (!strcmp(value, "true")) ? "1" : "0";
|
||||
value = (char *)ecore_hash_get(result->group, "StartupNotify");
|
||||
if (value)
|
||||
result->startup = (!strcmp(value, "true")) ? "1" : "0";
|
||||
}
|
||||
|
||||
ecore_hash_set(desktop_cache, strdup(file), result);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ecore_desktop_init()
|
||||
{
|
||||
if (!ini_file_cache)
|
||||
{
|
||||
ini_file_cache = ecore_hash_new(ecore_str_hash, ecore_str_compare);
|
||||
if (ini_file_cache)
|
||||
{
|
||||
ecore_hash_set_free_key(ini_file_cache, free);
|
||||
ecore_hash_set_free_value(ini_file_cache, (Ecore_Free_Cb) ecore_hash_destroy);
|
||||
}
|
||||
}
|
||||
if (!desktop_cache)
|
||||
{
|
||||
desktop_cache = ecore_hash_new(ecore_str_hash, ecore_str_compare);
|
||||
if (desktop_cache)
|
||||
{
|
||||
ecore_hash_set_free_key(desktop_cache, free);
|
||||
ecore_hash_set_free_value(desktop_cache, (Ecore_Free_Cb) ecore_desktop_destroy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ecore_desktop_shutdown()
|
||||
{
|
||||
if (ini_file_cache)
|
||||
{
|
||||
ecore_hash_destroy(ini_file_cache);
|
||||
ini_file_cache = NULL;
|
||||
}
|
||||
if (desktop_cache)
|
||||
{
|
||||
ecore_hash_destroy(desktop_cache);
|
||||
desktop_cache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ecore_desktop_destroy(Ecore_Desktop * desktop)
|
||||
{
|
||||
if (desktop->NotShowIn)
|
||||
ecore_hash_destroy(desktop->NotShowIn);
|
||||
if (desktop->OnlyShowIn)
|
||||
ecore_hash_destroy(desktop->OnlyShowIn);
|
||||
if (desktop->Categories)
|
||||
ecore_hash_destroy(desktop->Categories);
|
||||
free(desktop);
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
ecore_desktop_get_home()
|
||||
{
|
||||
char *d;
|
||||
int length;
|
||||
char home[MAX_PATH];
|
||||
|
||||
/* Get Home Dir, check for trailing '/', strip it */
|
||||
snprintf(home, sizeof(home), "%s", getenv("HOME"));
|
||||
d = strrchr(home, '/');
|
||||
if (d)
|
||||
{
|
||||
if (strlen(d) == 1)
|
||||
{
|
||||
if (home[(length = strlen(home) - 1)] == '/')
|
||||
home[length] = '\0';
|
||||
}
|
||||
}
|
||||
return strdup(home);
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
#include <limits.h>
|
||||
|
||||
#include "Ecore_Desktop.h"
|
||||
#include "ecore_desktop_private.h"
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
static char * _ecore_desktop_find_icon0(char *icon, char *icon_size, char *icon_theme);
|
||||
|
||||
|
||||
/* FIXME: Ideally this should be -
|
||||
* {".png", ".svg", ".xpm", "", NULL}
|
||||
* Add them in when they are supported in .eaps.
|
||||
*/
|
||||
static const char *ext[] = { ".png", ".svg", ".xpm", "", NULL };
|
||||
|
||||
char *
|
||||
ecore_desktop_find_icon(char *icon, char *icon_size, char *icon_theme)
|
||||
{
|
||||
char icn[MAX_PATH], path[MAX_PATH];
|
||||
char *dir, *home;
|
||||
|
||||
if (icon == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Easy check first, was a full path supplied? */
|
||||
if ((icon[0] == '/') && (ecore_file_exists(icon)))
|
||||
return strdup(icon);
|
||||
|
||||
home = ecore_desktop_get_home();
|
||||
|
||||
snprintf(icn, sizeof(icn), "%s", icon);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\tTrying To Find Icon %s\n", icn);
|
||||
#endif
|
||||
|
||||
/* Check For Unsupported Extension */
|
||||
// if ((!strcmp(icon + strlen(icon) - 4, ".svg")) || (!strcmp(icon + strlen(icon) - 4, ".ico"))
|
||||
// || (!strcmp(icon + strlen(icon) - 4, ".xpm")))
|
||||
if (!strcmp(icon + strlen(icon) - 4, ".ico"))
|
||||
return NULL;
|
||||
|
||||
if (!icon_theme)
|
||||
{
|
||||
/* Check If Dir Supplied In Desktop File */
|
||||
dir = ecore_file_get_dir(icn);
|
||||
if (!strcmp(dir, icn) == 0)
|
||||
{
|
||||
snprintf(path, MAX_PATH, "%s", icn);
|
||||
/* Check Supplied Dir For Icon */
|
||||
if (ecore_file_exists(path))
|
||||
return strdup(icn);
|
||||
}
|
||||
}
|
||||
|
||||
dir = _ecore_desktop_find_icon0(icon, icon_size, icon_theme);
|
||||
if (dir)
|
||||
dir = strdup(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
/** Search for an icon the fdo way.
|
||||
*
|
||||
* This complies with the freedesktop.org Icon Theme Specification version 0.7
|
||||
*
|
||||
* @param icon The icon to search for.
|
||||
* @param icon_size The icon size to search for.
|
||||
* @param icon_theme The icon theme to search in.
|
||||
* @return The full path to the found icon.
|
||||
*/
|
||||
static char *
|
||||
_ecore_desktop_find_icon0(char *icon, char *icon_size, char *icon_theme)
|
||||
{
|
||||
/* NOTES ON OPTIMIZATIONS
|
||||
*
|
||||
* The spec has this to say -
|
||||
*
|
||||
* "The algorithm as described in this document works by always looking up
|
||||
* filenames in directories (a stat in unix terminology). A good
|
||||
* implementation is expected to read the directories once, and do all
|
||||
* lookups in memory using that information.
|
||||
*
|
||||
* "This caching can make it impossible for users to add icons without having
|
||||
* to restart applications. In order to handle this, any implementation that
|
||||
* does caching is required to look at the mtime of the toplevel icon
|
||||
* directories when doing a cache lookup, unless it already did so less than
|
||||
* 5 seconds ago. This means that any icon editor or theme installation
|
||||
* program need only to change the mtime of the the toplevel directory where
|
||||
* it changed the theme to make sure that the new icons will eventually get
|
||||
* used."
|
||||
*
|
||||
* On the other hand, OS caching (at least in linux) seems to do a reasonable
|
||||
* job here.
|
||||
*
|
||||
* We could also precalculate and cache all the information extracted from
|
||||
* the .theme files.
|
||||
*/
|
||||
|
||||
char icn[MAX_PATH], path[MAX_PATH];
|
||||
char *theme_path, *found;
|
||||
|
||||
if ((icon == NULL) || (icon[0] == '\0'))
|
||||
return NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\tTrying To Find Icon %s (%s) in theme %s\n", icon, icon_size, icon_theme);
|
||||
#endif
|
||||
|
||||
/* Get the theme description file. */
|
||||
snprintf(icn, MAX_PATH, "%s/index.theme", icon_theme);
|
||||
#ifdef DEBUG
|
||||
printf("SEARCHING FOR %s\n", icn);
|
||||
#endif
|
||||
theme_path = ecore_desktop_paths_search_for_file(ecore_desktop_paths_icons, icn, 1, NULL, NULL);
|
||||
if (theme_path)
|
||||
{
|
||||
Ecore_Hash *theme;
|
||||
|
||||
/* Parse the theme description file. */
|
||||
#ifdef DEBUG
|
||||
printf("Path to %s is %s\n", icn, theme_path);
|
||||
#endif
|
||||
theme = ecore_desktop_parse_ini_file(theme_path);
|
||||
if (theme)
|
||||
{
|
||||
Ecore_Hash *icon_group;
|
||||
|
||||
/* Grab the themes directory list, and what it inherits. */
|
||||
icon_group = (Ecore_Hash *) ecore_hash_get(theme, "Icon Theme");
|
||||
if (icon_group)
|
||||
{
|
||||
char *directories, *inherits;
|
||||
|
||||
directories = (char *)ecore_hash_get(icon_group, "Directories");
|
||||
inherits = (char *)ecore_hash_get(icon_group, "Inherits");
|
||||
if (directories)
|
||||
{
|
||||
Ecore_List *directory_paths;
|
||||
|
||||
/* Split the directory list. */
|
||||
#ifdef DEBUG
|
||||
printf("Inherits %s Directories %s\n", inherits, directories);
|
||||
#endif
|
||||
directory_paths = ecore_desktop_list_from_paths(directories);
|
||||
if (directory_paths)
|
||||
{
|
||||
int wanted_size;
|
||||
int minimal_size = INT_MAX;
|
||||
int i;
|
||||
char *closest = NULL;
|
||||
char *directory;
|
||||
|
||||
wanted_size = atoi(icon_size);
|
||||
/* Loop through the themes directories. */
|
||||
|
||||
ecore_list_goto_first(directory_paths);
|
||||
while ((directory = ecore_list_next(directory_paths)) != NULL)
|
||||
{
|
||||
Ecore_Hash *sub_group;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("FDO icon path = %s\n", directory_paths);
|
||||
#endif
|
||||
/* Get the details for this theme directory. */
|
||||
sub_group = (Ecore_Hash *) ecore_hash_get(theme, directory);
|
||||
if (sub_group)
|
||||
{
|
||||
char *size, *type, *minsize, *maxsize, *threshold;
|
||||
int j;
|
||||
|
||||
size = (char *)ecore_hash_get(sub_group, "Size");
|
||||
type = (char *)ecore_hash_get(sub_group, "Type");
|
||||
minsize = (char *)ecore_hash_get(sub_group, "MinSize");
|
||||
maxsize = (char *)ecore_hash_get(sub_group, "MaxSize");
|
||||
threshold = (char *)ecore_hash_get(sub_group, "Threshold");
|
||||
if (size)
|
||||
{
|
||||
int match = 0;
|
||||
int this_size, result_size = 0, min_size, max_size, thresh_size;
|
||||
|
||||
if (!minsize)
|
||||
minsize = size;
|
||||
if (!maxsize)
|
||||
maxsize = size;
|
||||
if (!threshold)
|
||||
threshold = "2";
|
||||
min_size = atoi(minsize);
|
||||
max_size = atoi(maxsize);
|
||||
thresh_size = atoi(threshold);
|
||||
|
||||
/* Does this theme directory match the required icon size? */
|
||||
this_size = atoi(size);
|
||||
if (!type)
|
||||
type = "Threshold";
|
||||
switch (type[0])
|
||||
{
|
||||
case 'F': /* Fixed. */
|
||||
{
|
||||
match = (wanted_size == this_size);
|
||||
result_size = abs(this_size - wanted_size);
|
||||
break;
|
||||
}
|
||||
case 'S': /* Scaled. */
|
||||
{
|
||||
match = ((min_size <= wanted_size) && (wanted_size <= max_size));
|
||||
if (wanted_size < min_size)
|
||||
result_size = min_size - wanted_size;
|
||||
if (wanted_size > max_size)
|
||||
result_size = wanted_size - max_size;
|
||||
break;
|
||||
}
|
||||
default: /* Threshold. */
|
||||
{
|
||||
match = (((this_size - thresh_size) <= wanted_size)
|
||||
&& (wanted_size <= (this_size + thresh_size)));
|
||||
if (wanted_size < (this_size - thresh_size))
|
||||
result_size = min_size - wanted_size;
|
||||
if (wanted_size > (this_size + thresh_size))
|
||||
result_size = wanted_size - max_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for icon with all extensions. */
|
||||
for (j = 0; ext[j] != NULL; j++)
|
||||
{
|
||||
snprintf(path, MAX_PATH, "%s/%s/%s%s", icon_theme, directory, icon, ext[j]);
|
||||
#ifdef DEBUG
|
||||
printf("FDO icon = %s\n", path);
|
||||
#endif
|
||||
found = ecore_desktop_paths_search_for_file(ecore_desktop_paths_icons, path, 0, NULL, NULL);
|
||||
if (found)
|
||||
{
|
||||
if (match) /* If there is a match in sizes, return the icon. */
|
||||
return found;
|
||||
if (result_size < minimal_size) /* While we are here, figure out our next fallback strategy. */
|
||||
{
|
||||
minimal_size = result_size;
|
||||
closest = found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} /* while ((directory = ecore_list_next(directory_paths)) != NULL) */
|
||||
|
||||
/* Fall back strategy #1, look for closest size in this theme. */
|
||||
if (closest)
|
||||
return closest;
|
||||
|
||||
/* Fall back strategy #2, Try again with the parent theme. */
|
||||
if ((inherits) && (inherits[0] != '\0') && (strcmp(icon_theme, "hicolor") != 0))
|
||||
{
|
||||
found = _ecore_desktop_find_icon0(icon, icon_size, inherits);
|
||||
if (found != NULL)
|
||||
return found;
|
||||
}
|
||||
|
||||
/* Fall back strategy #3, Try the default hicolor theme. */
|
||||
if ((!((inherits) && (inherits[0] != '\0'))) && (strcmp(icon_theme, "hicolor") != 0))
|
||||
{
|
||||
found = _ecore_desktop_find_icon0(icon, icon_size, "hicolor");
|
||||
if (found != NULL)
|
||||
return found;
|
||||
}
|
||||
|
||||
/* Fall back strategy #4, Just search in the base of the icon directories. */
|
||||
for (i = 0; ext[i] != NULL; i++)
|
||||
{
|
||||
snprintf(path, MAX_PATH, "%s%s", icon, ext[i]);
|
||||
#ifdef DEBUG
|
||||
printf("FDO icon = %s\n", path);
|
||||
#endif
|
||||
found = ecore_desktop_paths_search_for_file(ecore_desktop_paths_icons, path, 0, NULL, NULL);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(theme_path);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,657 @@
|
|||
/*
|
||||
* This conforms with the freedesktop.org XDG Base Directory Specification version 0.6
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
struct _config_exe_data
|
||||
{
|
||||
char *home;
|
||||
Ecore_List *paths, *types;
|
||||
int done;
|
||||
};
|
||||
|
||||
static Ecore_List *_ecore_desktop_paths_get(char *before, char *env_home, char *env, char *env_home_default, char *env_default, char *type,
|
||||
char *gnome_extra, char *kde);
|
||||
static void _ecore_desktop_paths_massage_path(char *path, char *home, char *first, char *second);
|
||||
static void _ecore_desktop_paths_check_and_add(Ecore_List * paths, char *path);
|
||||
static void _ecore_desktop_paths_exec_config(Ecore_List * paths, char *home, Ecore_List * extras, char *cmd);
|
||||
|
||||
static int _ecore_desktop_paths_cb_exe_exit(void *data, int type, void *event);
|
||||
|
||||
|
||||
Ecore_Event_Handler *exit_handler = NULL;
|
||||
Ecore_List *gnome_data = NULL;
|
||||
char *home;
|
||||
|
||||
|
||||
void
|
||||
ecore_desktop_paths_init()
|
||||
{
|
||||
/* FIXME: Keep track of any loose strdups in a list, so that we can free them at shutdown time. */
|
||||
|
||||
exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_desktop_paths_cb_exe_exit, NULL);
|
||||
gnome_data = ecore_list_new();
|
||||
home = ecore_desktop_get_home();
|
||||
if (home)
|
||||
{
|
||||
int last;
|
||||
|
||||
/* Strip trailing slash of home. */
|
||||
last = strlen(home) - 1;
|
||||
if ((last >= 0) && (home[last] == '/'))
|
||||
home[last] = '\0';
|
||||
}
|
||||
|
||||
if (exit_handler && gnome_data)
|
||||
{
|
||||
ecore_list_set_free_cb(gnome_data, free);
|
||||
_ecore_desktop_paths_exec_config(gnome_data, home, NULL, "gnome-config --datadir");
|
||||
}
|
||||
|
||||
if (!ecore_desktop_paths_desktops)
|
||||
{
|
||||
ecore_desktop_paths_desktops =
|
||||
_ecore_desktop_paths_get(NULL, "XDG_DATA_HOME", "XDG_DATA_DIRS",
|
||||
"~/.local/share", "/usr/local/share:/usr/share", "applications",
|
||||
"dist/desktop-files:dist/short-menu:gnome/apps", "xdgdata-apps:apps");
|
||||
_ecore_desktop_paths_check_and_add(ecore_desktop_paths_desktops, "/usr/local/share/update-desktop-files/templates");
|
||||
_ecore_desktop_paths_check_and_add(ecore_desktop_paths_desktops, "/usr/share/update-desktop-files/templates");
|
||||
}
|
||||
if (!ecore_desktop_paths_kde_legacy)
|
||||
{
|
||||
char temp[MAX_PATH], *path;
|
||||
Ecore_List *temp_list;
|
||||
|
||||
ecore_desktop_paths_kde_legacy = _ecore_desktop_paths_get(NULL, NULL, NULL, NULL, NULL, NULL, NULL, "apps");
|
||||
if (ecore_desktop_paths_kde_legacy)
|
||||
{
|
||||
/* Copy it, cause Ecore_List walks can not be nested. */
|
||||
temp_list = ecore_list_new();
|
||||
if (temp_list)
|
||||
{
|
||||
ecore_list_goto_first(ecore_desktop_paths_kde_legacy);
|
||||
while ((path = ecore_list_next(ecore_desktop_paths_kde_legacy)) != NULL)
|
||||
ecore_list_append(temp_list, path);
|
||||
|
||||
ecore_list_goto_first(temp_list);
|
||||
while ((path = ecore_list_next(temp_list)) != NULL)
|
||||
{
|
||||
char *t1, *t2;
|
||||
|
||||
t1 = rindex(path, '/');
|
||||
*t1 = '\0';
|
||||
t2 = rindex(path, '/');
|
||||
*t2 = '\0';
|
||||
sprintf(temp, "%s/apps/kappfinder/apps/", path);
|
||||
*t2 = '/';
|
||||
*t1 = '/';
|
||||
_ecore_desktop_paths_check_and_add(ecore_desktop_paths_kde_legacy, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ecore_desktop_paths_icons)
|
||||
{
|
||||
char *gnome;
|
||||
|
||||
ecore_desktop_paths_icons =
|
||||
_ecore_desktop_paths_get("~/.icons", "XDG_DATA_HOME", "XDG_DATA_DIRS", "~/.local/share", "/usr/local/share:/usr/share", "icons",
|
||||
"dist/icons", "icon:pixmap");
|
||||
_ecore_desktop_paths_check_and_add(ecore_desktop_paths_icons, "/usr/local/share/pixmaps/");
|
||||
_ecore_desktop_paths_check_and_add(ecore_desktop_paths_icons, "/usr/share/pixmaps/");
|
||||
gnome = getenv("GNOME_ICON_PATH");
|
||||
if (gnome)
|
||||
_ecore_desktop_paths_check_and_add(ecore_desktop_paths_icons, gnome);
|
||||
}
|
||||
if (!ecore_desktop_paths_menus)
|
||||
ecore_desktop_paths_menus =
|
||||
_ecore_desktop_paths_get(NULL, "XDG_CONFIG_HOME", "XDG_CONFIG_DIRS", "~/.config", "/etc/xdg", "menus", NULL, "xdgconf-menu");
|
||||
if (!ecore_desktop_paths_directories)
|
||||
ecore_desktop_paths_directories =
|
||||
_ecore_desktop_paths_get(NULL, "XDG_DATA_HOME", "XDG_DATA_DIRS",
|
||||
"~/.local/share", "/usr/local/share:/usr/share", "desktop-directories", "gnome/vfolders", "xdgdata-dirs");
|
||||
if (!ecore_desktop_paths_config)
|
||||
ecore_desktop_paths_config = _ecore_desktop_paths_get(NULL, "XDG_CONFIG_HOME", "XDG_CONFIG_DIRS", "~/.config", "/etc/xdg", "", NULL, NULL);
|
||||
|
||||
if (exit_handler) ecore_event_handler_del(exit_handler);
|
||||
}
|
||||
|
||||
void
|
||||
ecore_desktop_paths_shutdown()
|
||||
{
|
||||
E_FN_DEL(ecore_list_destroy, ecore_desktop_paths_menus);
|
||||
E_FN_DEL(ecore_list_destroy, ecore_desktop_paths_directories);
|
||||
E_FN_DEL(ecore_list_destroy, ecore_desktop_paths_desktops);
|
||||
E_FN_DEL(ecore_list_destroy, ecore_desktop_paths_icons);
|
||||
}
|
||||
|
||||
/** Search for a file in fdo compatible locations.
|
||||
*
|
||||
* This will search through all the diretories of a particular type, looking
|
||||
* for the file. It will recurse into subdirectories. If func is NULL, then
|
||||
* only the first file found will be returned. If func is defined, then each
|
||||
* file found will be passed to func, until func returns 1.
|
||||
*
|
||||
* @param type The type of directories to search.
|
||||
* @param file The file to search for.
|
||||
* @param sub Should we search sub directories.
|
||||
* @param func A function to call for each file found.
|
||||
* @param data A pointer to pass on to func.
|
||||
*/
|
||||
char *
|
||||
ecore_desktop_paths_search_for_file(Ecore_List *paths, char *file, int sub, int (*func) (const void *data, char *path), const void *data)
|
||||
{
|
||||
char *path = NULL, *this_path;
|
||||
char temp[MAX_PATH];
|
||||
struct stat path_stat;
|
||||
|
||||
if (paths)
|
||||
{
|
||||
ecore_list_goto_first(paths);
|
||||
while ((this_path = ecore_list_next(paths)) != NULL)
|
||||
{
|
||||
sprintf(temp, "%s%s", this_path, file);
|
||||
if (stat(temp, &path_stat) == 0)
|
||||
{
|
||||
path = strdup(temp);
|
||||
if (func)
|
||||
if (func(data, path))
|
||||
break;
|
||||
}
|
||||
else if (sub)
|
||||
path = ecore_desktop_paths_recursive_search(this_path, file, NULL, func, data);
|
||||
if (path && (!func))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/* We need -
|
||||
config file full of paths
|
||||
menus=pathlist
|
||||
desktops=pathlist
|
||||
directories=pathlist
|
||||
icons=pathlist
|
||||
*/
|
||||
|
||||
static Ecore_List *
|
||||
_ecore_desktop_paths_get(char *before, char *env_home, char *env, char *env_home_default, char *env_default, char *type, char *gnome_extra,
|
||||
char *kde)
|
||||
{
|
||||
Ecore_List *paths = NULL;
|
||||
Ecore_List *types = NULL;
|
||||
Ecore_List *gnome_extras = NULL;
|
||||
Ecore_List *kdes = NULL;
|
||||
|
||||
/* Don't sort them, as they are in preferred order from each source. */
|
||||
/* Merge the results, there are probably some duplicates. */
|
||||
|
||||
if (type) types = ecore_desktop_list_from_paths(strdup(type));
|
||||
if (gnome_extra) gnome_extras = ecore_desktop_list_from_paths(strdup(gnome_extra));
|
||||
if (kde) kdes = ecore_desktop_list_from_paths(strdup(kde));
|
||||
|
||||
paths = ecore_list_new();
|
||||
if (paths)
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
Ecore_List *env_list;
|
||||
|
||||
ecore_list_set_free_cb(paths, free);
|
||||
if (before)
|
||||
{
|
||||
Ecore_List *befores;
|
||||
|
||||
befores = ecore_desktop_list_from_paths(strdup(before));
|
||||
if (befores)
|
||||
{
|
||||
char *this_before;
|
||||
|
||||
ecore_list_goto_first(befores);
|
||||
while ((this_before = ecore_list_next(befores)) != NULL)
|
||||
{
|
||||
_ecore_desktop_paths_massage_path(path, home, this_before, NULL);
|
||||
_ecore_desktop_paths_check_and_add(paths, path);
|
||||
}
|
||||
E_FN_DEL(ecore_list_destroy, befores);
|
||||
}
|
||||
}
|
||||
|
||||
if (env_home)
|
||||
{
|
||||
char *value;
|
||||
|
||||
value = getenv(env_home);
|
||||
if ((value == NULL) || (value[0] == '\0'))
|
||||
value = env_home_default;
|
||||
env_list = ecore_desktop_list_from_paths(strdup(value));
|
||||
if (env_list && types)
|
||||
{
|
||||
char *this_env, *this_type;
|
||||
|
||||
ecore_list_goto_first(env_list);
|
||||
while ((this_env = ecore_list_next(env_list)) != NULL)
|
||||
{
|
||||
ecore_list_goto_first(types);
|
||||
while ((this_type = ecore_list_next(types)) != NULL)
|
||||
{
|
||||
_ecore_desktop_paths_massage_path(path, home, this_env, this_type);
|
||||
_ecore_desktop_paths_check_and_add(paths, path);
|
||||
}
|
||||
}
|
||||
E_FN_DEL(ecore_list_destroy, env_list);
|
||||
}
|
||||
}
|
||||
|
||||
if (env)
|
||||
{
|
||||
char *value;
|
||||
|
||||
value = getenv(env);
|
||||
if ((value == NULL) || (value[0] == '\0'))
|
||||
value = env_default;
|
||||
env_list = ecore_desktop_list_from_paths(value);
|
||||
if (env_list && types)
|
||||
{
|
||||
char *this_env, *this_type;
|
||||
|
||||
ecore_list_goto_first(env_list);
|
||||
while ((this_env = ecore_list_next(env_list)) != NULL)
|
||||
{
|
||||
ecore_list_goto_first(types);
|
||||
while ((this_type = ecore_list_next(types)) != NULL)
|
||||
{
|
||||
_ecore_desktop_paths_massage_path(path, home, this_env, this_type);
|
||||
_ecore_desktop_paths_check_and_add(paths, path);
|
||||
}
|
||||
}
|
||||
E_FN_DEL(ecore_list_destroy, env_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the pathlist from the config file - type=pathlist
|
||||
* for each path in config
|
||||
* if it is already in paths, skip it
|
||||
* if it exists, add it to end of paths
|
||||
*/
|
||||
|
||||
if (gnome_data && types)
|
||||
{
|
||||
char *this_gnome, *this_type;
|
||||
|
||||
ecore_list_goto_first(gnome_data);
|
||||
while ((this_gnome = ecore_list_next(gnome_data)) != NULL)
|
||||
{
|
||||
ecore_list_goto_first(types);
|
||||
while ((this_type = ecore_list_next(types)) != NULL)
|
||||
{
|
||||
_ecore_desktop_paths_massage_path(path, home, this_gnome, this_type);
|
||||
_ecore_desktop_paths_check_and_add(paths, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gnome_data && gnome_extras)
|
||||
{
|
||||
char *this_gnome, *this_type;
|
||||
|
||||
ecore_list_goto_first(gnome_data);
|
||||
while ((this_gnome = ecore_list_next(gnome_data)) != NULL)
|
||||
{
|
||||
ecore_list_goto_first(gnome_extras);
|
||||
while ((this_type = ecore_list_next(gnome_extras)) != NULL)
|
||||
{
|
||||
_ecore_desktop_paths_massage_path(path, home, this_gnome, this_type);
|
||||
_ecore_desktop_paths_check_and_add(paths, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((exit_handler != NULL) && (kdes != NULL))
|
||||
{
|
||||
char *this_kde;
|
||||
|
||||
ecore_list_goto_first(kdes);
|
||||
while ((this_kde = ecore_list_next(kdes)) != NULL)
|
||||
{
|
||||
char cmd[128];
|
||||
|
||||
sprintf(cmd, "kde-config --path %s", this_kde);
|
||||
_ecore_desktop_paths_exec_config(paths, home, NULL, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
E_FN_DEL(ecore_list_destroy, kdes);
|
||||
E_FN_DEL(ecore_list_destroy, gnome_extras);
|
||||
E_FN_DEL(ecore_list_destroy, types);
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_desktop_paths_massage_path(char *path, char *home, char *first, char *second)
|
||||
{
|
||||
int last;
|
||||
|
||||
/* Strip traling slash of first. */
|
||||
last = strlen(first) - 1;
|
||||
if ((last >= 0) && (first[last] == '/'))
|
||||
first[last] = '\0';
|
||||
|
||||
if (second)
|
||||
{
|
||||
/* Strip traling slash of second. */
|
||||
last = strlen(second) - 1;
|
||||
if ((last >= 0) && (second[last] == '/'))
|
||||
second[last] = '\0';
|
||||
}
|
||||
|
||||
if ((second) && (second[0] != '\0'))
|
||||
{
|
||||
if (first[0] == '~')
|
||||
sprintf(path, "%s%s/%s/", home, &first[1], &second[(second[0] == '/') ? 1 : 0]);
|
||||
else
|
||||
sprintf(path, "%s/%s/", first, &second[(second[0] == '/') ? 1 : 0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (first[0] == '~')
|
||||
sprintf(path, "%s%s/", home, &first[1]);
|
||||
else
|
||||
sprintf(path, "%s/", first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_ecore_desktop_paths_check_and_add(Ecore_List * paths, char *path)
|
||||
{
|
||||
struct stat path_stat;
|
||||
char *this_path;
|
||||
|
||||
if (paths == NULL)
|
||||
{
|
||||
paths = ecore_list_new();
|
||||
if (paths == NULL)
|
||||
return;
|
||||
ecore_list_set_free_cb(paths, free);
|
||||
}
|
||||
|
||||
/* Check if we have it already. */
|
||||
ecore_list_goto_first(paths);
|
||||
while ((this_path = ecore_list_next(paths)) != NULL)
|
||||
{
|
||||
if (strcmp(path, this_path) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if the path exists. */
|
||||
if ((stat(path, &path_stat) == 0) && (S_ISDIR(path_stat.st_mode)))
|
||||
ecore_list_append(paths, strdup(path));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_ecore_desktop_paths_exec_config(Ecore_List *paths, char *home, Ecore_List * extras, char *cmd)
|
||||
{
|
||||
Ecore_Exe *exe;
|
||||
struct _config_exe_data ced;
|
||||
|
||||
ced.home = home;
|
||||
ced.paths = paths;
|
||||
ced.types = extras;
|
||||
ced.done = 0;
|
||||
exe = ecore_exe_pipe_run(cmd, ECORE_EXE_PIPE_AUTO | ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_READ_LINE_BUFFERED, &ced);
|
||||
if (exe)
|
||||
{
|
||||
ecore_exe_tag_set(exe, "genmenu/fdo");
|
||||
while (ced.done == 0)
|
||||
{
|
||||
/* FIXME: raster is paranoid. If too much time passes, give up.
|
||||
* Or find a way to let the usual event loop shit do this without spinning our wheels.
|
||||
* On the other hand, these are quick commands, and we NEED this data before we can continue.
|
||||
*/
|
||||
ecore_main_loop_iterate();
|
||||
usleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
ecore_desktop_paths_recursive_search(char *path, char *file, int (*dir_func) (const void *data, char *path),
|
||||
int (*func) (const void *data, char *path), const void *data)
|
||||
{
|
||||
char *fpath = NULL;
|
||||
DIR *dir = NULL;
|
||||
|
||||
dir = opendir(path);
|
||||
|
||||
if (dir != NULL)
|
||||
{
|
||||
struct dirent *script;
|
||||
|
||||
while ((script = readdir(dir)) != NULL)
|
||||
{
|
||||
struct stat script_stat;
|
||||
char info_text[4096];
|
||||
|
||||
sprintf(info_text, "%s%s", path, script->d_name);
|
||||
if ((stat(info_text, &script_stat) == 0))
|
||||
{
|
||||
if (S_ISDIR(script_stat.st_mode))
|
||||
{
|
||||
if ((strcmp(basename(info_text), ".") != 0) && (strcmp(basename(info_text), "..") != 0))
|
||||
{
|
||||
sprintf(info_text, "%s%s/", path, script->d_name);
|
||||
if (dir_func)
|
||||
if (dir_func(data, info_text))
|
||||
break;
|
||||
fpath = ecore_desktop_paths_recursive_search(info_text, file, dir_func, func, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
if (strcmp(basename(info_text), file) == 0)
|
||||
{
|
||||
fpath = strdup(info_text);
|
||||
if (func)
|
||||
if (func(data, path))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (func)
|
||||
if (func(data, info_text))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fpath && (!func))
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
return fpath;
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_desktop_paths_cb_exe_exit(void *data, int type, void *event)
|
||||
{
|
||||
Ecore_Exe_Event_Del *ev;
|
||||
Ecore_List *paths;
|
||||
Ecore_List *config_list;
|
||||
Ecore_Exe_Event_Data *read;
|
||||
struct _config_exe_data *ced;
|
||||
char *value;
|
||||
char path[MAX_PATH];
|
||||
|
||||
ev = event;
|
||||
if (!ev->exe)
|
||||
return 1;
|
||||
value = ecore_exe_tag_get(ev->exe);
|
||||
if ((!value) || (strcmp(value, "genmenu/fdo")) != 0)
|
||||
return 1;
|
||||
ced = ecore_exe_data_get(ev->exe);
|
||||
if (!ced)
|
||||
return 1;
|
||||
paths = ced->paths;
|
||||
if (!paths)
|
||||
return 1;
|
||||
|
||||
read = ecore_exe_event_data_get(ev->exe, ECORE_EXE_PIPE_READ);
|
||||
if ((read) && (read->lines[0].line))
|
||||
{
|
||||
value = read->lines[0].line;
|
||||
if (value)
|
||||
{
|
||||
config_list = ecore_desktop_list_from_paths(value);
|
||||
if (config_list)
|
||||
{
|
||||
char *this_config, *this_type;
|
||||
|
||||
ecore_list_goto_first(config_list);
|
||||
while ((this_config = ecore_list_next(config_list)) != NULL)
|
||||
{
|
||||
if (ced->types)
|
||||
{
|
||||
ecore_list_goto_first(ced->types);
|
||||
while ((this_type = ecore_list_next(ced->types)) != NULL)
|
||||
{
|
||||
_ecore_desktop_paths_massage_path(path, ced->home, this_config, this_type);
|
||||
_ecore_desktop_paths_check_and_add(paths, path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_ecore_desktop_paths_massage_path(path, ced->home, this_config, NULL);
|
||||
_ecore_desktop_paths_check_and_add(paths, path);
|
||||
}
|
||||
}
|
||||
E_FN_DEL(ecore_list_destroy, config_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
ced->done = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Split a list of paths into an Ecore_Hash.
|
||||
*
|
||||
* The list of paths can use any one of ;:, to seperate the paths.
|
||||
* You can also escape the :;, with \.
|
||||
*
|
||||
* FIXME: The concept here is still buggy, but it should do for now.
|
||||
* Also, it writes to the input string, this may be bad.
|
||||
*
|
||||
* @param paths A list of paths.
|
||||
*/
|
||||
Ecore_Hash *
|
||||
ecore_desktop_hash_from_paths(char *paths)
|
||||
{
|
||||
Ecore_Hash *result;
|
||||
|
||||
result = ecore_hash_new(ecore_str_hash, ecore_str_compare);
|
||||
if (result)
|
||||
{
|
||||
ecore_hash_set_free_key(result, free);
|
||||
ecore_hash_set_free_value(result, free);
|
||||
|
||||
if (paths)
|
||||
{
|
||||
char *start, *end, temp;
|
||||
int finished = 0;
|
||||
|
||||
end = paths;
|
||||
while (!finished)
|
||||
{
|
||||
start = end;
|
||||
do /* FIXME: There is probably a better way to do this. */
|
||||
{
|
||||
while ((*end != ';') && (*end != ':') && (*end != ',') && (*end != '\0'))
|
||||
end++;
|
||||
}
|
||||
while ((end != paths) && (*(end - 1) == '\\') && (*end != '\0')); /* Ignore any escaped ;:, */
|
||||
/* FIXME: We still need to unescape it now. */
|
||||
temp = *end;
|
||||
if (*end == '\0')
|
||||
finished = 1;
|
||||
else
|
||||
*end = '\0';
|
||||
ecore_hash_set(result, strdup(start), strdup(start));
|
||||
if ((*end) != temp)
|
||||
*end = temp;
|
||||
end++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** Split a list of paths into an Ecore_Hash.
|
||||
*
|
||||
* The list of paths can use any one of ;:, to seperate the paths.
|
||||
* You can also escape the :;, with \.
|
||||
*
|
||||
* FIXME: The concept here is still buggy, but it should do for now.
|
||||
* Also, it writes to the input string, this may be bad.
|
||||
*
|
||||
* @param paths A list of paths.
|
||||
*/
|
||||
Ecore_List *
|
||||
ecore_desktop_list_from_paths(char *paths)
|
||||
{
|
||||
Ecore_List *result;
|
||||
|
||||
result = ecore_list_new();
|
||||
if (result)
|
||||
{
|
||||
ecore_list_set_free_cb(result, free);
|
||||
|
||||
if (paths)
|
||||
{
|
||||
char *start, *end, temp;
|
||||
int finished = 0;
|
||||
|
||||
end = paths;
|
||||
while (!finished)
|
||||
{
|
||||
start = end;
|
||||
do /* FIXME: There is probably a better way to do this. */
|
||||
{
|
||||
while ((*end != ';') && (*end != ':') && (*end != ',') && (*end != '\0'))
|
||||
end++;
|
||||
}
|
||||
while ((end != paths) && (*(end - 1) == '\\') && (*end != '\0')); /* Ignore any escaped ;:, */
|
||||
/* FIXME: We still need to unescape it now. */
|
||||
temp = *end;
|
||||
if (*end == '\0')
|
||||
finished = 1;
|
||||
else
|
||||
*end = '\0';
|
||||
ecore_list_append(result, strdup(start));
|
||||
if ((*end) != temp)
|
||||
*end = temp;
|
||||
end++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef _ECORE_DESKTOP_PRIVATE_H
|
||||
# define _ECORE_DESKTOP_PRIVATE_H
|
||||
|
||||
#include <Ecore_File.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,313 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
#include "Ecore_Desktop.h"
|
||||
#include "ecore_desktop_private.h"
|
||||
|
||||
static void ecore_desktop_tree_dump_each_hash_node(void *value, void *user_data);
|
||||
|
||||
/* Just a quick and dirty tree implemtation that will likely get replaced by
|
||||
* something much saner at a later date. I wrote most of this while falling
|
||||
* asleep. It will probably scare me when I wake up. B-)
|
||||
*
|
||||
* Devilhorns said to make it portable, so we can't rely on any external tree
|
||||
* implementation. So this tree is designed specifically for this task. Then
|
||||
* we finally found a place for the genmenu code, and Ecore was back on the
|
||||
* menu. However, speed could be an issue later, so it might be worth it to
|
||||
* stick with a custom tree implementation, so that we can optimize it for this
|
||||
* task.
|
||||
*
|
||||
* The trees will be tiny.
|
||||
* They only store strings.
|
||||
* There is no insertion or deletion, only append.
|
||||
* Append order must be maintained.
|
||||
* The trees will only ever be accessed sequentially, from begining to end.
|
||||
* The tree data will come in two ways, all in one big string, or a bunch of
|
||||
* seperate strings, one per element. Any particular tree might have both.
|
||||
*
|
||||
* No duplicates in the tree,
|
||||
* This is the nasty part of this tree implementation.
|
||||
* Insertions involve a linear search for dupes, most of the
|
||||
* time there won't be any dupes, so the tree is searched in
|
||||
* it's entirety. These trees will be really small, and only created at
|
||||
* the begining, so no big drama there.
|
||||
* The tree may allow duplicates.
|
||||
*/
|
||||
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_tree_new(char *buffer)
|
||||
{
|
||||
Ecore_Desktop_Tree *tree;
|
||||
|
||||
tree = E_NEW(Ecore_Desktop_Tree, 1);
|
||||
if ((tree) && (buffer))
|
||||
{
|
||||
tree->buffers = (char **)realloc(tree->buffers, (tree->buffers_size + 1) * sizeof(char *));
|
||||
tree->buffers[tree->buffers_size++] = strdup(buffer);
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_tree_add(Ecore_Desktop_Tree * tree, char *element)
|
||||
{
|
||||
tree->elements = (Ecore_Desktop_Tree_Element *) realloc(tree->elements, (tree->size + 1) * sizeof(Ecore_Desktop_Tree_Element));
|
||||
tree->elements[tree->size].element = element;
|
||||
tree->elements[tree->size++].type = ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING;
|
||||
return tree;
|
||||
}
|
||||
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_tree_extend(Ecore_Desktop_Tree * tree, char *element)
|
||||
{
|
||||
tree->buffers = (char **)realloc(tree->buffers, (tree->buffers_size + 1) * sizeof(char *));
|
||||
tree->buffers[tree->buffers_size++] = strdup(element);
|
||||
tree = ecore_desktop_tree_add(tree, tree->buffers[tree->buffers_size - 1]);
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
void
|
||||
ecore_desktop_tree_track(Ecore_Desktop_Tree * tree, void *element)
|
||||
{
|
||||
tree->buffers = (char **)realloc(tree->buffers, (tree->buffers_size + 1) * sizeof(char *));
|
||||
tree->buffers[tree->buffers_size++] = element;
|
||||
}
|
||||
|
||||
/* OK, so we need an insert after all, and it falls into the dumb category. */
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_tree_insert(Ecore_Desktop_Tree * tree, int before, void *element, Ecore_Desktop_Tree_Element_Type type)
|
||||
{
|
||||
int i;
|
||||
|
||||
tree->elements = (Ecore_Desktop_Tree_Element *) realloc(tree->elements, (tree->size + 1) * sizeof(Ecore_Desktop_Tree_Element));
|
||||
tree->size++;
|
||||
for (i = tree->size - 1; i > before; i--)
|
||||
{
|
||||
tree->elements[i].element = tree->elements[i - 1].element;
|
||||
tree->elements[i].type = tree->elements[i - 1].type;
|
||||
}
|
||||
tree->elements[before].element = element;
|
||||
tree->elements[before].type = type;
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* OK, so we need a tree merge after all, and it falls into the dumb category. */
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_tree_merge(Ecore_Desktop_Tree * tree, int before, Ecore_Desktop_Tree * element)
|
||||
{
|
||||
int i, size;
|
||||
|
||||
size = element->size;
|
||||
if (size)
|
||||
{
|
||||
tree->elements = (Ecore_Desktop_Tree_Element *) realloc(tree->elements, (tree->size + size) * sizeof(Ecore_Desktop_Tree_Element));
|
||||
tree->size += size;
|
||||
for (i = tree->size - 1; i > before; i--)
|
||||
{
|
||||
tree->elements[i].element = tree->elements[i - size].element;
|
||||
tree->elements[i].type = tree->elements[i - size].type;
|
||||
}
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
tree->elements[before + i].element = element->elements[i].element;
|
||||
tree->elements[before + i].type = element->elements[i].type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Careful, this might screw up the freeing order if that is important. */
|
||||
size = element->buffers_size;
|
||||
if (size)
|
||||
{
|
||||
/*
|
||||
tree->buffers = (char **) realloc(tree->buffers, (tree->buffers_size + size) * sizeof(char *));
|
||||
tree->buffers_size += size;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
tree->buffers[tree->buffers_size + i] = element->buffers[i];
|
||||
element->buffers[i] = NULL;
|
||||
}
|
||||
*/
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_tree_add_child(Ecore_Desktop_Tree * tree, Ecore_Desktop_Tree * element)
|
||||
{
|
||||
tree->elements = (Ecore_Desktop_Tree_Element *) realloc(tree->elements, (tree->size + 1) * sizeof(Ecore_Desktop_Tree_Element));
|
||||
tree->elements[tree->size].element = element;
|
||||
tree->elements[tree->size++].type = ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE;
|
||||
element->parent = tree;
|
||||
return tree;
|
||||
}
|
||||
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_tree_add_hash(Ecore_Desktop_Tree * tree, Ecore_Hash * element)
|
||||
{
|
||||
tree->elements = (Ecore_Desktop_Tree_Element *) realloc(tree->elements, (tree->size + 1) * sizeof(Ecore_Desktop_Tree_Element));
|
||||
tree->elements[tree->size].element = element;
|
||||
tree->elements[tree->size++].type = ECORE_DESKTOP_TREE_ELEMENT_TYPE_HASH;
|
||||
return tree;
|
||||
}
|
||||
|
||||
void
|
||||
ecore_desktop_tree_remove(Ecore_Desktop_Tree * tree, int element)
|
||||
{
|
||||
if (tree->size > element)
|
||||
{
|
||||
tree->elements[element].type = ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
||||
tree->elements[element].element = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ecore_desktop_tree_exist(Ecore_Desktop_Tree * tree, char *element)
|
||||
{
|
||||
int exist = 0;
|
||||
int i;
|
||||
|
||||
/* This is the dumb part of the tree, a linear search. */
|
||||
for (i = 0; i < tree->size; i++)
|
||||
{
|
||||
if ((tree->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING) && (strcmp((char *)tree->elements[i].element, element) == 0))
|
||||
{
|
||||
exist = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return exist;
|
||||
}
|
||||
|
||||
int
|
||||
ecore_desktop_tree_foreach(Ecore_Desktop_Tree * tree, int level, int (*func) (const void *data, Ecore_Desktop_Tree * tree, int element, int level),
|
||||
const void *data)
|
||||
{
|
||||
int result = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tree->size; i++)
|
||||
{
|
||||
if (tree->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
||||
{
|
||||
if (ecore_desktop_tree_foreach((Ecore_Desktop_Tree *) tree->elements[i].element, level + 1, func, data))
|
||||
result = 1;
|
||||
}
|
||||
else if (tree->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL)
|
||||
{
|
||||
/* This falls into the dumb category. */
|
||||
int j = i;
|
||||
int k = i;
|
||||
int moved = 0;
|
||||
|
||||
/* Find the next non NULL element. */
|
||||
while ((j < tree->size) && (tree->elements[j].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL))
|
||||
j++;
|
||||
/* Move the next batch of non NULL up. */
|
||||
while ((j < tree->size) && (tree->elements[j].type != ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL))
|
||||
{
|
||||
moved = 1;
|
||||
tree->elements[k].type = tree->elements[j].type;
|
||||
tree->elements[k].element = tree->elements[j].element;
|
||||
tree->elements[j].type = ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL;
|
||||
tree->elements[j].element = NULL;
|
||||
j++;
|
||||
k++;
|
||||
}
|
||||
if (moved)
|
||||
i--;
|
||||
else
|
||||
tree->size = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (func(data, tree, i, level))
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ecore_desktop_tree_dump(Ecore_Desktop_Tree * tree, int level)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tree->size; i++)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < level; j++)
|
||||
printf(".");
|
||||
switch (tree->elements[i].type)
|
||||
{
|
||||
case ECORE_DESKTOP_TREE_ELEMENT_TYPE_NULL:
|
||||
{
|
||||
printf("NULL\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case ECORE_DESKTOP_TREE_ELEMENT_TYPE_STRING:
|
||||
{
|
||||
printf("%s\n", (char *)tree->elements[i].element);
|
||||
}
|
||||
break;
|
||||
|
||||
case ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE:
|
||||
{
|
||||
printf("TREE ELEMENT TYPE\n");
|
||||
ecore_desktop_tree_dump((Ecore_Desktop_Tree *) tree->elements[i].element, level + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case ECORE_DESKTOP_TREE_ELEMENT_TYPE_HASH:
|
||||
{
|
||||
int lev;
|
||||
|
||||
lev = level + 1;
|
||||
printf("HASH ELEMENT TYPE\n");
|
||||
ecore_hash_for_each_node((Ecore_Hash *) tree->elements[i].element, ecore_desktop_tree_dump_each_hash_node, &lev);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
printf("UNKNOWN ELEMENT TYPE!\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ecore_desktop_tree_dump_each_hash_node(void *value, void *user_data)
|
||||
{
|
||||
Ecore_Hash_Node *node;
|
||||
int level;
|
||||
int j;
|
||||
|
||||
node = (Ecore_Hash_Node *) value;
|
||||
level = *((int *)user_data);
|
||||
for (j = 0; j < level; j++)
|
||||
printf(".");
|
||||
printf("%s = %s\n", (char *)node->key, (char *)node->value);
|
||||
}
|
||||
|
||||
void
|
||||
ecore_desktop_tree_del(Ecore_Desktop_Tree * tree)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = tree->size - 1; i >= 0; i--)
|
||||
{
|
||||
if (tree->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_TREE)
|
||||
ecore_desktop_tree_del((Ecore_Desktop_Tree *) tree->elements[i].element);
|
||||
else if (tree->elements[i].type == ECORE_DESKTOP_TREE_ELEMENT_TYPE_HASH)
|
||||
ecore_hash_destroy((Ecore_Hash *) tree->elements[i].element);
|
||||
}
|
||||
|
||||
E_FREE(tree->elements);
|
||||
|
||||
for (i = tree->buffers_size - 1; i >= 0; i--)
|
||||
E_FREE(tree->buffers[i]);
|
||||
E_FREE(tree);
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "Ecore_Desktop.h"
|
||||
#include "ecore_desktop_private.h"
|
||||
|
||||
/** xmlame.c Extensively Mocked Language Approximately Mangled for Enlightenment.
|
||||
*
|
||||
* This is NOT a real XML parser. There were a few ways we could go when it came
|
||||
* to parsing the freedesktop.org (fdo) XML menu files. Whatever way we went, we
|
||||
* needed some sort of XML parser if we wanted to fully support fdo menu files.
|
||||
* Nothing we can do about that, fdo set the standard and they choose XML to do it.
|
||||
*
|
||||
* After a discussion with raster, three things led to the decision to do it this
|
||||
* way. It is likely that this will get included as a core part of the E17 window
|
||||
* manager (E17) coz E17 needs this functionality. E17 is in a dependency freeze
|
||||
* and there is no XML parser in it's current dependencies. The fdo XML menu files
|
||||
* look to be simple enough to parse that this sort of fake, brain dead, XML parser
|
||||
* may get away with it. Much testing on lots of systems is highly recommended.
|
||||
*
|
||||
* The final '>' of a tag is replaced with a '\0', but it's existance can be implied.
|
||||
*/
|
||||
|
||||
static char *_ecore_desktop_xmlame_parse(Ecore_Desktop_Tree * tree, char *buffer);
|
||||
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_xmlame_new(char *buffer)
|
||||
{
|
||||
Ecore_Desktop_Tree *tree;
|
||||
|
||||
tree = ecore_desktop_tree_new(buffer);
|
||||
return tree;
|
||||
}
|
||||
|
||||
Ecore_Desktop_Tree *
|
||||
ecore_desktop_xmlame_get(char *file)
|
||||
{
|
||||
int size;
|
||||
char *buffer;
|
||||
Ecore_Desktop_Tree *tree = NULL;
|
||||
|
||||
size = ecore_file_size(file);
|
||||
buffer = (char *)malloc(size + 1);
|
||||
if (buffer)
|
||||
{
|
||||
int fd;
|
||||
|
||||
buffer[0] = '\0';
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd != -1)
|
||||
{
|
||||
if (read(fd, buffer, size) == size)
|
||||
buffer[size] = '\0';
|
||||
}
|
||||
tree = ecore_desktop_xmlame_new(buffer);
|
||||
if (tree)
|
||||
{
|
||||
/* Have the file name as the first item on the tree, for later reference. */
|
||||
ecore_desktop_tree_extend(tree, file);
|
||||
_ecore_desktop_xmlame_parse(tree, buffer);
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
static char *
|
||||
_ecore_desktop_xmlame_parse(Ecore_Desktop_Tree * tree, char *buffer)
|
||||
{
|
||||
do
|
||||
{
|
||||
char *text;
|
||||
|
||||
/* Skip any white space at the beginning. */
|
||||
while ((*buffer != '\0') && (isspace(*buffer)))
|
||||
buffer++;
|
||||
text = buffer;
|
||||
/* Find the beginning of a tag. */
|
||||
while ((*buffer != '<') && (*buffer != '\0'))
|
||||
buffer++;
|
||||
/* Check for data between tags. */
|
||||
if (buffer != text)
|
||||
{
|
||||
char t;
|
||||
|
||||
t = *buffer;
|
||||
*buffer = '\0';
|
||||
ecore_desktop_tree_extend(tree, strdup(text));
|
||||
*buffer = t;
|
||||
}
|
||||
if (*buffer != '\0')
|
||||
{
|
||||
char *begin;
|
||||
|
||||
begin = buffer++;
|
||||
/* Find the end of the tag. */
|
||||
while ((*buffer != '>') && (*buffer != '\0'))
|
||||
buffer++;
|
||||
/* We have our tag, do something with it. */
|
||||
if (*buffer != '\0')
|
||||
{
|
||||
*buffer++ = '\0';
|
||||
if (begin[1] == '/')
|
||||
{ /* The end of an element. */
|
||||
ecore_desktop_tree_add(tree, begin);
|
||||
break;
|
||||
}
|
||||
else if ((begin[1] == '!') || (begin[1] == '-') || (*(buffer - 2) == '/'))
|
||||
{ /* This is a script, a comment, or a stand alone tag. */
|
||||
ecore_desktop_tree_add(tree, begin);
|
||||
}
|
||||
else
|
||||
{ /* The beginning of an element. */
|
||||
Ecore_Desktop_Tree *new_tree;
|
||||
|
||||
new_tree = ecore_desktop_xmlame_new(NULL);
|
||||
if (new_tree)
|
||||
{
|
||||
ecore_desktop_tree_add_child(tree, new_tree);
|
||||
ecore_desktop_tree_add(new_tree, begin);
|
||||
buffer = _ecore_desktop_xmlame_parse(new_tree, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (*buffer != '\0');
|
||||
|
||||
return buffer;
|
||||
}
|
Loading…
Reference in New Issue