From 50fb6af19b666261c1254d65596ac7adbafdfbaa Mon Sep 17 00:00:00 2001 From: Sean Davis <smd.seandavis@gmail.com> Date: Thu, 11 Oct 2018 22:47:14 -0400 Subject: [PATCH] Drop all leftovers from the garcon port --- src/Makefile.am | 48 - src/canonicalize.c | 330 ------ src/canonicalize.h | 38 - src/desktop-entries.c | 786 ------------- src/desktop-entries.h | 85 -- src/entry-directories.c | 1105 ------------------ src/entry-directories.h | 67 -- src/menu-layout.c | 2359 --------------------------------------- src/menu-layout.h | 161 --- src/menu-monitor.c | 431 ------- src/menu-monitor.h | 70 -- src/menu-util.c | 436 -------- src/menu-util.h | 59 - 13 files changed, 5975 deletions(-) delete mode 100644 src/canonicalize.c delete mode 100644 src/canonicalize.h delete mode 100644 src/desktop-entries.c delete mode 100644 src/desktop-entries.h delete mode 100644 src/entry-directories.c delete mode 100644 src/entry-directories.h delete mode 100644 src/menu-layout.c delete mode 100644 src/menu-layout.h delete mode 100644 src/menu-monitor.c delete mode 100644 src/menu-monitor.h delete mode 100644 src/menu-util.c delete mode 100644 src/menu-util.h diff --git a/src/Makefile.am b/src/Makefile.am index 1061a58a..dfdc7c23 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -156,18 +156,6 @@ xfce4_screensaver_dialog_SOURCES = \ xfcekbd-keyboard-config.h \ xfce-bg.c \ xfce-bg.h \ - desktop-entries.c \ - desktop-entries.h \ - menu-layout.c \ - menu-layout.h \ - menu-util.c \ - menu-util.h \ - menu-monitor.c \ - menu-monitor.h \ - canonicalize.c \ - canonicalize.h \ - entry-directories.c \ - entry-directories.h \ $(AUTH_SOURCES) \ $(NULL) @@ -187,18 +175,6 @@ EXTRA_xfce4_screensaver_dialog_SOURCES = \ xfcekbd-desktop-config.h \ xfcekbd-keyboard-config.c \ xfcekbd-keyboard-config.h \ - desktop-entries.c \ - desktop-entries.h \ - menu-layout.c \ - menu-layout.h \ - menu-util.c \ - menu-util.h \ - menu-monitor.c \ - menu-monitor.h \ - canonicalize.c \ - canonicalize.h \ - entry-directories.c \ - entry-directories.h \ $(NULL) xfce4_screensaver_dialog_LDADD = \ @@ -264,18 +240,6 @@ xfce4_screensaver_SOURCES = \ xfcekbd-desktop-config.h \ xfcekbd-keyboard-config.c \ xfcekbd-keyboard-config.h \ - desktop-entries.c \ - desktop-entries.h \ - menu-layout.c \ - menu-layout.h \ - menu-util.c \ - menu-util.h \ - menu-monitor.c \ - menu-monitor.h \ - canonicalize.c \ - canonicalize.h \ - entry-directories.c \ - entry-directories.h \ $(BUILT_SOURCES) \ $(NULL) @@ -321,18 +285,6 @@ xfce4_screensaver_preferences_SOURCES = \ xfcekbd-desktop-config.h \ xfcekbd-keyboard-config.c \ xfcekbd-keyboard-config.h \ - canonicalize.c \ - canonicalize.h \ - entry-directories.c \ - entry-directories.h \ - menu-util.c \ - menu-util.h \ - menu-layout.c \ - menu-layout.h \ - menu-monitor.c \ - menu-monitor.h \ - desktop-entries.c \ - desktop-entries.h \ $(NULL) xfce4_screensaver_preferences_LDADD = \ diff --git a/src/canonicalize.c b/src/canonicalize.c deleted file mode 100644 index 1a29ae97..00000000 --- a/src/canonicalize.c +++ /dev/null @@ -1,330 +0,0 @@ -/* Return the canonical absolute name of a given file. - * Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. - * This file is part of the GNU C Library. - * - * Copyright (C) 2002 Red Hat, Inc. (trivial port to GLib) - * - * The GNU C Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * The GNU C Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the GNU C Library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -#include <config.h> - -#include "canonicalize.h" - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <limits.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <errno.h> -#include <stddef.h> - -#ifndef MAXSYMLINKS -#define MAXSYMLINKS sysconf(_SC_SYMLOOP_MAX) -#endif - -/* Return the canonical absolute name of file NAME. A canonical name - does not contain any `.', `..' components nor any repeated path - separators ('/') or symlinks. All path components must exist. If - RESOLVED is null, the result is malloc'd; otherwise, if the - canonical name is PATH_MAX chars or more, returns null with `errno' - set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, - returns the name in RESOLVED. If the name cannot be resolved and - RESOLVED is non-NULL, it contains the path of the first component - that cannot be resolved. If the path can be resolved, RESOLVED - holds the same value as the value returned. */ - -static char* menu_realpath(const char* name, char* resolved) -{ - char* rpath = NULL; - char* dest = NULL; - char* extra_buf = NULL; - const char* start; - const char* end; - const char* rpath_limit; - long int path_max; - int num_links = 0; - - if (name == NULL) - { - /* As per Single Unix Specification V2 we must return an error if - * either parameter is a null pointer. We extend this to allow - * the RESOLVED parameter to be NULL in case the we are expected to - * allocate the room for the return value. */ - errno = EINVAL; - return NULL; - } - - if (name[0] == '\0') - { - /* As per Single Unix Specification V2 we must return an error if - * the name argument points to an empty string. */ - errno = ENOENT; - return NULL; - } - - #ifdef PATH_MAX - path_max = PATH_MAX; - #else - path_max = pathconf(name, _PC_PATH_MAX); - - if (path_max <= 0) - { - path_max = 1024; - } - #endif - - rpath = resolved ? g_alloca(path_max) : g_malloc(path_max); - rpath_limit = rpath + path_max; - - if (name[0] != G_DIR_SEPARATOR) - { - if (!getcwd(rpath, path_max)) - { - rpath[0] = '\0'; - goto error; - } - - dest = strchr(rpath, '\0'); - } - else - { - rpath[0] = G_DIR_SEPARATOR; - dest = rpath + 1; - } - - for (start = end = name; *start; start = end) - { - struct stat st; - int n; - - /* Skip sequence of multiple path-separators. */ - while (*start == G_DIR_SEPARATOR) - { - ++start; - } - - /* Find end of path component. */ - for (end = start; *end && *end != G_DIR_SEPARATOR; ++end) - { - /* Nothing. */; - } - - if (end - start == 0) - { - break; - } - else if (end - start == 1 && start[0] == '.') - { - /* nothing */; - } - else if (end - start == 2 && start[0] == '.' && start[1] == '.') - { - /* Back up to previous component, ignore if at root already. */ - if (dest > rpath + 1) - { - while ((--dest)[-1] != G_DIR_SEPARATOR) - { - /* Nothing. */; - } - } - } - else - { - size_t new_size; - - if (dest[-1] != G_DIR_SEPARATOR) - { - *dest++ = G_DIR_SEPARATOR; - } - - if (dest + (end - start) >= rpath_limit) - { - char* new_rpath; - ptrdiff_t dest_offset = dest - rpath; - - if (resolved) - { - #ifdef ENAMETOOLONG - errno = ENAMETOOLONG; - #else - /* Uh... just pick something */ - errno = EINVAL; - #endif - - if (dest > rpath + 1) - { - dest--; - } - - *dest = '\0'; - goto error; - } - - new_size = rpath_limit - rpath; - - if (end - start + 1 > path_max) - { - new_size += end - start + 1; - } - else - { - new_size += path_max; - } - - new_rpath = (char*) realloc(rpath, new_size); - - if (new_rpath == NULL) - { - goto error; - } - - rpath = new_rpath; - rpath_limit = rpath + new_size; - - dest = rpath + dest_offset; - } - - memcpy(dest, start, end - start); - dest = dest + (end - start); - *dest = '\0'; - - if (stat(rpath, &st) < 0) - { - goto error; - } - - if (S_ISLNK(st.st_mode)) - { - char* buf = alloca(path_max); - size_t len; - - if (++num_links > MAXSYMLINKS) - { - errno = ELOOP; - goto error; - } - - n = readlink(rpath, buf, path_max); - - if (n < 0) - { - goto error; - } - - buf[n] = '\0'; - - - - if (!extra_buf) - { - extra_buf = g_alloca(path_max); - } - - len = strlen(end); - - if ((long int) (n + len) >= path_max) - { - #ifdef ENAMETOOLONG - errno = ENAMETOOLONG; - #else - /* Uh... just pick something */ - errno = EINVAL; - #endif - - goto error; - } - - /* Careful here, end may be a pointer into extra_buf... */ - g_memmove(&extra_buf[n], end, len + 1); - name = end = memcpy(extra_buf, buf, n); - - if (buf[0] == G_DIR_SEPARATOR) - { - dest = rpath + 1; /* It's an absolute symlink */ - } - else - { - /* Back up to previous component, ignore if at root already: */ - if (dest > rpath + 1) - { - while ((--dest)[-1] != G_DIR_SEPARATOR) - { - /* Nothing. */; - } - } - } - } - } - } - - if (dest > rpath + 1 && dest[-1] == G_DIR_SEPARATOR) - { - --dest; - } - - *dest = '\0'; - - return resolved ? memcpy(resolved, rpath, dest - rpath + 1) : rpath; - - error: - - if (resolved) - { - strcpy(resolved, rpath); - } - else - { - g_free(rpath); - } - - return NULL; -} - -char* menu_canonicalize_file_name(const char* name, gboolean allow_missing_basename) -{ - char* retval; - - retval = menu_realpath(name, NULL); - - /* We could avoid some system calls by using the second - * argument to realpath() instead of doing realpath - * all over again, but who cares really. we'll see if - * it's ever in a profile. - */ - if (allow_missing_basename && retval == NULL) - { - char* dirname; - char* canonical_dirname; - - dirname = g_path_get_dirname(name); - canonical_dirname = menu_realpath(dirname, NULL); - g_free(dirname); - - if (canonical_dirname) - { - char* basename; - - basename = g_path_get_basename(name); - retval = g_build_filename(canonical_dirname, basename, NULL); - g_free(basename); - g_free(canonical_dirname); - } - } - - return retval; -} diff --git a/src/canonicalize.h b/src/canonicalize.h deleted file mode 100644 index dcc6f6ef..00000000 --- a/src/canonicalize.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Return the canonical absolute name of a given file. - * Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. - * This file is part of the GNU C Library. - * - * Copyright (C) 2002 Red Hat, Inc. (trivial port to GLib) - * - * The GNU C Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * The GNU C Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the GNU C Library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -#ifndef G_CANONICALIZE_H -#define G_CANONICALIZE_H - -#include <glib.h> - -#ifdef __cplusplus -extern "C" { -#endif - -char* menu_canonicalize_file_name(const char* name, gboolean allow_missing_basename); - -#ifdef __cplusplus -} -#endif - -#endif /* G_CANONICALIZE_H */ diff --git a/src/desktop-entries.c b/src/desktop-entries.c deleted file mode 100644 index b46f4e7a..00000000 --- a/src/desktop-entries.c +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Copyright (C) 2002 - 2004 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <config.h> - -#include "desktop-entries.h" - -#include <string.h> - -#include "menu-util.h" - -#define DESKTOP_ENTRY_GROUP "Desktop Entry" -#define KDE_DESKTOP_ENTRY_GROUP "KDE Desktop Entry" - -enum { - DESKTOP_ENTRY_NO_DISPLAY = 1 << 0, - DESKTOP_ENTRY_HIDDEN = 1 << 1, - DESKTOP_ENTRY_SHOW_IN_XFCE = 1 << 2, - DESKTOP_ENTRY_TRYEXEC_FAILED = 1 << 3 -}; - -struct DesktopEntry { - char* path; - char* basename; - - GQuark* categories; - - char* name; - char* generic_name; - char* full_name; - char* comment; - char* icon; - char* exec; - gboolean terminal; - - guint type: 2; - guint flags: 4; - guint refcount: 24; -}; - -struct DesktopEntrySet { - int refcount; - GHashTable* hash; -}; - -/* - * Desktop entries - */ - -static guint get_flags_from_key_file(DesktopEntry* entry, GKeyFile* key_file, const char* desktop_entry_group) -{ - GError *error; - char **strv; - gboolean no_display; - gboolean hidden; - gboolean show_in_xfce; - gboolean tryexec_failed; - char *tryexec; - guint flags; - int i; - - error = NULL; - no_display = g_key_file_get_boolean (key_file, - desktop_entry_group, - "NoDisplay", - &error); - if (error) - { - no_display = FALSE; - g_error_free (error); - } - - error = NULL; - hidden = g_key_file_get_boolean (key_file, - desktop_entry_group, - "Hidden", - &error); - if (error) - { - hidden = FALSE; - g_error_free (error); - } - - show_in_xfce = TRUE; - strv = g_key_file_get_string_list (key_file, - desktop_entry_group, - "OnlyShowIn", - NULL, - NULL); - if (strv) - { - show_in_xfce = FALSE; - for (i = 0; strv[i]; i++) - { - /* Since we use the same codebase as MATE and GNOME, don't let them have all the fun. */ - if (!strcmp (strv[i], "XFCE") || !strcmp (strv[i], "MATE") || !strcmp (strv[i], "GNOME")) - { - show_in_xfce = TRUE; - break; - } - } - } - else - { - strv = g_key_file_get_string_list (key_file, - desktop_entry_group, - "NotShowIn", - NULL, - NULL); - if (strv) - { - show_in_xfce = TRUE; - for (i = 0; strv[i]; i++) - { - if (!strcmp (strv[i], "XFCE")) - { - show_in_xfce = FALSE; - } - } - } - } - g_strfreev (strv); - - tryexec_failed = FALSE; - tryexec = g_key_file_get_string (key_file, - desktop_entry_group, - "TryExec", - NULL); - if (tryexec) - { - char *path; - - path = g_find_program_in_path (g_strstrip (tryexec)); - - tryexec_failed = (path == NULL); - - g_free (path); - g_free (tryexec); - } - - flags = 0; - if (no_display) - flags |= DESKTOP_ENTRY_NO_DISPLAY; - if (hidden) - flags |= DESKTOP_ENTRY_HIDDEN; - if (show_in_xfce) - flags |= DESKTOP_ENTRY_SHOW_IN_XFCE; - if (tryexec_failed) - flags |= DESKTOP_ENTRY_TRYEXEC_FAILED; - - return flags; -} - -static GQuark* get_categories_from_key_file (DesktopEntry* entry, GKeyFile* key_file, const char* desktop_entry_group) -{ - GQuark *retval; - char **strv; - gsize len; - int i; - - strv = g_key_file_get_string_list (key_file, - desktop_entry_group, - "Categories", - &len, - NULL); - if (!strv) - return NULL; - - retval = g_new0 (GQuark, len + 1); - - for (i = 0; strv[i]; i++) - retval[i] = g_quark_from_string (strv[i]); - - g_strfreev (strv); - - return retval; -} - -static DesktopEntry* desktop_entry_load(DesktopEntry* entry) -{ - DesktopEntry *retval = NULL; - GKeyFile *key_file; - GError *error; - const char *desktop_entry_group; - char *name_str; - char *type_str; - - key_file = g_key_file_new (); - - error = NULL; - if (!g_key_file_load_from_file (key_file, entry->path, 0, &error)) - { - menu_verbose ("Failed to load \"%s\": %s\n", - entry->path, error->message); - g_error_free (error); - goto out; - } - - if (g_key_file_has_group (key_file, DESKTOP_ENTRY_GROUP)) - { - desktop_entry_group = DESKTOP_ENTRY_GROUP; - } - else - { - menu_verbose ("\"%s\" contains no \"" DESKTOP_ENTRY_GROUP "\" group\n", - entry->path); - - if (g_key_file_has_group (key_file, KDE_DESKTOP_ENTRY_GROUP)) - { - desktop_entry_group = KDE_DESKTOP_ENTRY_GROUP; - menu_verbose ("\"%s\" contains deprecated \"" KDE_DESKTOP_ENTRY_GROUP "\" group\n", - entry->path); - } - else - { - goto out; - } - } - - if (!g_key_file_has_key (key_file, desktop_entry_group, "Name", NULL)) - { - menu_verbose ("\"%s\" contains no \"Name\" key\n", entry->path); - goto out; - } - - name_str = g_key_file_get_locale_string (key_file, desktop_entry_group, "Name", NULL, NULL); - if (!name_str) - { - menu_verbose ("\"%s\" contains an invalid \"Name\" key\n", entry->path); - goto out; - } - - g_free (name_str); - - type_str = g_key_file_get_string (key_file, desktop_entry_group, "Type", NULL); - if (!type_str) - { - menu_verbose ("\"%s\" contains no \"Type\" key\n", entry->path); - goto out; - } - - if ((entry->type == DESKTOP_ENTRY_DESKTOP && strcmp (type_str, "Application") != 0) || - (entry->type == DESKTOP_ENTRY_DIRECTORY && strcmp (type_str, "Directory") != 0)) - { - menu_verbose ("\"%s\" does not contain the correct \"Type\" value\n", entry->path); - g_free (type_str); - goto out; - } - - g_free (type_str); - - if (entry->type == DESKTOP_ENTRY_DESKTOP && - !g_key_file_has_key (key_file, desktop_entry_group, "Exec", NULL)) - { - menu_verbose ("\"%s\" does not contain an \"Exec\" key\n", entry->path); - goto out; - } - - retval = entry; - -#define GET_LOCALE_STRING(n) g_key_file_get_locale_string (key_file, desktop_entry_group, (n), NULL, NULL) - - retval->name = GET_LOCALE_STRING ("Name"); - retval->generic_name = GET_LOCALE_STRING ("GenericName"); - retval->full_name = GET_LOCALE_STRING ("X-XFCE-FullName"); - retval->comment = GET_LOCALE_STRING ("Comment"); - retval->icon = GET_LOCALE_STRING ("Icon"); - retval->flags = get_flags_from_key_file (retval, key_file, desktop_entry_group); - retval->categories = get_categories_from_key_file (retval, key_file, desktop_entry_group); - - if (entry->type == DESKTOP_ENTRY_DESKTOP) - { - retval->exec = g_key_file_get_string (key_file, desktop_entry_group, "Exec", NULL); - retval->terminal = g_key_file_get_boolean (key_file, desktop_entry_group, "Terminal", NULL); - } - -#undef GET_LOCALE_STRING - - menu_verbose ("Desktop entry \"%s\" (%s, %s, %s, %s, %s) flags: NoDisplay=%s, Hidden=%s, ShowInXFCE=%s, TryExecFailed=%s\n", - retval->basename, - retval->name, - retval->generic_name ? retval->generic_name : "(null)", - retval->full_name ? retval->full_name : "(null)", - retval->comment ? retval->comment : "(null)", - retval->icon ? retval->icon : "(null)", - retval->flags & DESKTOP_ENTRY_NO_DISPLAY ? "(true)" : "(false)", - retval->flags & DESKTOP_ENTRY_HIDDEN ? "(true)" : "(false)", - retval->flags & DESKTOP_ENTRY_SHOW_IN_XFCE ? "(true)" : "(false)", - retval->flags & DESKTOP_ENTRY_TRYEXEC_FAILED ? "(true)" : "(false)"); - - out: - g_key_file_free (key_file); - - if (!retval) - desktop_entry_unref (entry); - - return retval; -} - -DesktopEntry* desktop_entry_new(const char* path) -{ - DesktopEntryType type; - DesktopEntry *retval; - - menu_verbose ("Loading desktop entry \"%s\"\n", path); - - if (g_str_has_suffix (path, ".desktop")) - { - type = DESKTOP_ENTRY_DESKTOP; - } - else if (g_str_has_suffix (path, ".directory")) - { - type = DESKTOP_ENTRY_DIRECTORY; - } - else - { - menu_verbose ("Unknown desktop entry suffix in \"%s\"\n", - path); - return NULL; - } - - retval = g_new0 (DesktopEntry, 1); - - retval->refcount = 1; - retval->type = type; - retval->basename = g_path_get_basename (path); - retval->path = g_strdup (path); - - return desktop_entry_load (retval); -} - -DesktopEntry* desktop_entry_reload(DesktopEntry* entry) -{ - g_return_val_if_fail (entry != NULL, NULL); - - menu_verbose ("Re-loading desktop entry \"%s\"\n", entry->path); - - g_free (entry->categories); - entry->categories = NULL; - - g_free (entry->name); - entry->name = NULL; - - g_free (entry->generic_name); - entry->generic_name = NULL; - - g_free (entry->full_name); - entry->full_name = NULL; - - g_free (entry->comment); - entry->comment = NULL; - - g_free (entry->icon); - entry->icon = NULL; - - g_free (entry->exec); - entry->exec = NULL; - - entry->terminal = 0; - entry->flags = 0; - - return desktop_entry_load (entry); -} - -DesktopEntry* desktop_entry_ref(DesktopEntry* entry) -{ - g_return_val_if_fail (entry != NULL, NULL); - g_return_val_if_fail (entry->refcount > 0, NULL); - - entry->refcount += 1; - - return entry; -} - -DesktopEntry* desktop_entry_copy(DesktopEntry* entry) -{ - DesktopEntry *retval; - int i; - - menu_verbose ("Copying desktop entry \"%s\"\n", - entry->basename); - - retval = g_new0 (DesktopEntry, 1); - - retval->refcount = 1; - retval->type = entry->type; - retval->basename = g_strdup (entry->basename); - retval->path = g_strdup (entry->path); - retval->name = g_strdup (entry->name); - retval->generic_name = g_strdup (entry->generic_name); - retval->full_name = g_strdup (entry->full_name); - retval->comment = g_strdup (entry->comment); - retval->icon = g_strdup (entry->icon); - retval->exec = g_strdup (entry->exec); - retval->terminal = entry->terminal; - retval->flags = entry->flags; - - i = 0; - if (entry->categories != NULL) - { - for (; entry->categories[i]; i++); - } - - retval->categories = g_new0 (GQuark, i + 1); - - i = 0; - if (entry->categories != NULL) - { - for (; entry->categories[i]; i++) - retval->categories[i] = entry->categories[i]; - } - - return retval; -} - -void desktop_entry_unref(DesktopEntry* entry) -{ - g_return_if_fail (entry != NULL); - g_return_if_fail (entry->refcount > 0); - - entry->refcount -= 1; - if (entry->refcount == 0) - { - g_free (entry->categories); - entry->categories = NULL; - - g_free (entry->name); - entry->name = NULL; - - g_free (entry->generic_name); - entry->generic_name = NULL; - - g_free (entry->full_name); - entry->full_name = NULL; - - g_free (entry->comment); - entry->comment = NULL; - - g_free (entry->icon); - entry->icon = NULL; - - g_free (entry->exec); - entry->exec = NULL; - - g_free (entry->basename); - entry->basename = NULL; - - g_free (entry->path); - entry->path = NULL; - - g_free (entry); - } -} - -DesktopEntryType desktop_entry_get_type(DesktopEntry* entry) -{ - return entry->type; -} - -const char* desktop_entry_get_path(DesktopEntry* entry) -{ - return entry->path; -} - -const char * -desktop_entry_get_basename (DesktopEntry *entry) -{ - return entry->basename; -} - -const char* desktop_entry_get_name(DesktopEntry* entry) -{ - return entry->name; -} - -const char* desktop_entry_get_full_name(DesktopEntry* entry) -{ - return entry->full_name; -} - -const char* desktop_entry_get_exec(DesktopEntry* entry) -{ - return entry->exec; -} - -gboolean desktop_entry_get_hidden(DesktopEntry* entry) -{ - return (entry->flags & DESKTOP_ENTRY_HIDDEN) != 0; -} - -gboolean desktop_entry_get_no_display(DesktopEntry* entry) -{ - return (entry->flags & DESKTOP_ENTRY_NO_DISPLAY) != 0; -} - -gboolean desktop_entry_get_show_in_xfce(DesktopEntry* entry) -{ - return (entry->flags & DESKTOP_ENTRY_SHOW_IN_XFCE) != 0; -} - -gboolean desktop_entry_get_tryexec_failed(DesktopEntry* entry) -{ - return (entry->flags & DESKTOP_ENTRY_TRYEXEC_FAILED) != 0; -} - -gboolean desktop_entry_has_categories(DesktopEntry* entry) -{ - return (entry->categories != NULL && entry->categories[0] != 0); -} - -gboolean desktop_entry_has_category(DesktopEntry* entry, const char* category) -{ - GQuark quark; - int i; - - if (entry->categories == NULL) - return FALSE; - - if (!(quark = g_quark_try_string (category))) - return FALSE; - - for (i = 0; entry->categories[i]; i++) - { - if (quark == entry->categories[i]) - return TRUE; - } - - return FALSE; -} - -void desktop_entry_add_legacy_category(DesktopEntry* entry) -{ - GQuark *categories; - int i; - - menu_verbose ("Adding Legacy category to \"%s\"\n", - entry->basename); - - i = 0; - if (entry->categories != NULL) - { - for (; entry->categories[i]; i++); - } - - categories = g_new0 (GQuark, i + 2); - - i = 0; - if (entry->categories != NULL) - { - for (; entry->categories[i]; i++) - categories[i] = entry->categories[i]; - } - - categories[i] = g_quark_from_string ("Legacy"); - - g_free (entry->categories); - entry->categories = categories; -} - -/* - * Entry sets - */ - -DesktopEntrySet* desktop_entry_set_new(void) -{ - DesktopEntrySet *set; - - set = g_new0 (DesktopEntrySet, 1); - set->refcount = 1; - - menu_verbose (" New entry set %p\n", set); - - return set; -} - -DesktopEntrySet* desktop_entry_set_ref(DesktopEntrySet* set) -{ - g_return_val_if_fail (set != NULL, NULL); - g_return_val_if_fail (set->refcount > 0, NULL); - - set->refcount += 1; - - return set; -} - -void desktop_entry_set_unref(DesktopEntrySet* set) -{ - g_return_if_fail (set != NULL); - g_return_if_fail (set->refcount > 0); - - set->refcount -= 1; - if (set->refcount == 0) - { - menu_verbose (" Deleting entry set %p\n", set); - - if (set->hash) - g_hash_table_destroy (set->hash); - set->hash = NULL; - - g_free (set); - } -} - -void desktop_entry_set_add_entry(DesktopEntrySet* set, DesktopEntry* entry, const char* file_id) -{ - menu_verbose (" Adding to set %p entry %s\n", set, file_id); - - if (set->hash == NULL) - { - set->hash = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) desktop_entry_unref); - } - - g_hash_table_replace (set->hash, - g_strdup (file_id), - desktop_entry_ref (entry)); -} - -DesktopEntry* desktop_entry_set_lookup(DesktopEntrySet* set, const char* file_id) -{ - if (set->hash == NULL) - return NULL; - - return g_hash_table_lookup (set->hash, file_id); -} - -typedef struct { - DesktopEntrySetForeachFunc func; - gpointer user_data; -} EntryHashForeachData; - -static void entry_hash_foreach(const char* file_id, DesktopEntry* entry, EntryHashForeachData* fd) -{ - fd->func(file_id, entry, fd->user_data); -} - -void desktop_entry_set_foreach(DesktopEntrySet* set, DesktopEntrySetForeachFunc func, gpointer user_data) -{ - g_return_if_fail (set != NULL); - g_return_if_fail (func != NULL); - - if (set->hash != NULL) - { - EntryHashForeachData fd; - - fd.func = func; - fd.user_data = user_data; - - g_hash_table_foreach (set->hash, - (GHFunc) entry_hash_foreach, - &fd); - } -} - -static void desktop_entry_set_clear(DesktopEntrySet* set) -{ - menu_verbose (" Clearing set %p\n", set); - - if (set->hash != NULL) - { - g_hash_table_destroy (set->hash); - set->hash = NULL; - } -} - -int desktop_entry_set_get_count(DesktopEntrySet* set) -{ - if (set->hash == NULL) - return 0; - - return g_hash_table_size (set->hash); -} - -static void union_foreach(const char* file_id, DesktopEntry* entry, DesktopEntrySet* set) -{ - /* we are iterating over "with" adding anything not - * already in "set". We unconditionally overwrite - * the stuff in "set" because we can assume - * two entries with the same name are equivalent. - */ - desktop_entry_set_add_entry(set, entry, file_id); -} - -void desktop_entry_set_union(DesktopEntrySet* set, DesktopEntrySet* with) -{ - menu_verbose (" Union of %p and %p\n", set, with); - - if (desktop_entry_set_get_count (with) == 0) - return; /* A fast simple case */ - - g_hash_table_foreach (with->hash, - (GHFunc) union_foreach, - set); -} - -typedef struct { - DesktopEntrySet *set; - DesktopEntrySet *with; -} IntersectData; - -static gboolean intersect_foreach_remove(const char* file_id, DesktopEntry* entry, IntersectData* id) -{ - /* Remove everything in "set" which is not in "with" */ - - if (g_hash_table_lookup (id->with->hash, file_id) != NULL) - return FALSE; - - menu_verbose (" Removing from %p entry %s\n", id->set, file_id); - - return TRUE; /* return TRUE to remove */ -} - -void desktop_entry_set_intersection(DesktopEntrySet* set, DesktopEntrySet* with) -{ - IntersectData id; - - menu_verbose (" Intersection of %p and %p\n", set, with); - - if (desktop_entry_set_get_count (set) == 0 || - desktop_entry_set_get_count (with) == 0) - { - /* A fast simple case */ - desktop_entry_set_clear (set); - return; - } - - id.set = set; - id.with = with; - - g_hash_table_foreach_remove (set->hash, - (GHRFunc) intersect_foreach_remove, - &id); -} - -typedef struct { - DesktopEntrySet *set; - DesktopEntrySet *other; -} SubtractData; - -static gboolean subtract_foreach_remove(const char* file_id, DesktopEntry* entry, SubtractData* sd) -{ - /* Remove everything in "set" which is not in "other" */ - - if (g_hash_table_lookup (sd->other->hash, file_id) == NULL) - return FALSE; - - menu_verbose (" Removing from %p entry %s\n", sd->set, file_id); - - return TRUE; /* return TRUE to remove */ -} - -void desktop_entry_set_subtract(DesktopEntrySet* set, DesktopEntrySet* other) -{ - SubtractData sd; - - menu_verbose (" Subtract from %p set %p\n", set, other); - - if (desktop_entry_set_get_count (set) == 0 || - desktop_entry_set_get_count (other) == 0) - return; /* A fast simple case */ - - sd.set = set; - sd.other = other; - - g_hash_table_foreach_remove (set->hash, - (GHRFunc) subtract_foreach_remove, - &sd); -} diff --git a/src/desktop-entries.h b/src/desktop-entries.h deleted file mode 100644 index b0e1dffe..00000000 --- a/src/desktop-entries.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2002 - 2004 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __DESKTOP_ENTRIES_H__ -#define __DESKTOP_ENTRIES_H__ - -#include <glib.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - DESKTOP_ENTRY_INVALID = 0, - DESKTOP_ENTRY_DESKTOP, - DESKTOP_ENTRY_DIRECTORY -} DesktopEntryType; - -typedef struct DesktopEntry DesktopEntry; - -DesktopEntry* desktop_entry_new(const char* path); - -DesktopEntry* desktop_entry_ref(DesktopEntry* entry); -DesktopEntry* desktop_entry_copy(DesktopEntry* entry); -DesktopEntry* desktop_entry_reload(DesktopEntry* entry); -void desktop_entry_unref(DesktopEntry* entry); - -DesktopEntryType desktop_entry_get_type(DesktopEntry* entry); -const char* desktop_entry_get_path(DesktopEntry* entry); -const char* desktop_entry_get_basename(DesktopEntry* entry); - -const char* desktop_entry_get_name(DesktopEntry* entry); -const char* desktop_entry_get_full_name(DesktopEntry* entry); -const char* desktop_entry_get_exec(DesktopEntry* entry); - -gboolean desktop_entry_get_hidden(DesktopEntry* entry); -gboolean desktop_entry_get_no_display(DesktopEntry* entry); -gboolean desktop_entry_get_show_in_xfce(DesktopEntry* entry); -gboolean desktop_entry_get_tryexec_failed(DesktopEntry* entry); - -gboolean desktop_entry_has_categories(DesktopEntry* entry); -gboolean desktop_entry_has_category(DesktopEntry* entry, const char* category); - -void desktop_entry_add_legacy_category(DesktopEntry* src); - - -typedef struct DesktopEntrySet DesktopEntrySet; - -DesktopEntrySet* desktop_entry_set_new(void); -DesktopEntrySet* desktop_entry_set_ref(DesktopEntrySet* set); -void desktop_entry_set_unref(DesktopEntrySet* set); - -void desktop_entry_set_add_entry(DesktopEntrySet* set, DesktopEntry* entry, const char* file_id); -DesktopEntry* desktop_entry_set_lookup(DesktopEntrySet* set, const char* file_id); -int desktop_entry_set_get_count(DesktopEntrySet* set); - -void desktop_entry_set_union(DesktopEntrySet* set, DesktopEntrySet* with); -void desktop_entry_set_intersection(DesktopEntrySet* set, DesktopEntrySet* with); -void desktop_entry_set_subtract(DesktopEntrySet* set, DesktopEntrySet* other); - -typedef void (*DesktopEntrySetForeachFunc) (const char* file_id, DesktopEntry* entry, gpointer user_data); - -void desktop_entry_set_foreach(DesktopEntrySet* set, DesktopEntrySetForeachFunc func, gpointer user_data); - -#ifdef __cplusplus -} -#endif - -#endif /* __DESKTOP_ENTRIES_H__ */ diff --git a/src/entry-directories.c b/src/entry-directories.c deleted file mode 100644 index 2b59b372..00000000 --- a/src/entry-directories.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* - * Copyright (C) 2002 - 2004 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <config.h> - -#include "entry-directories.h" - -#include <string.h> -#include <errno.h> -#include <sys/types.h> -#include <dirent.h> - -#include "menu-util.h" -#include "menu-monitor.h" -#include "canonicalize.h" - -typedef struct CachedDir CachedDir; -typedef struct CachedDirMonitor CachedDirMonitor; - -struct EntryDirectory { - CachedDir* dir; - char* legacy_prefix; - - guint entry_type: 2; - guint is_legacy: 1; - guint refcount: 24; -}; - -struct EntryDirectoryList { - int refcount; - int length; - GList* dirs; -}; - -struct CachedDir { - CachedDir* parent; - char* name; - - GSList* entries; - GSList* subdirs; - - MenuMonitor* dir_monitor; - GSList* monitors; - - guint have_read_entries: 1; - guint deleted: 1; - - guint references: 28; -}; - -struct CachedDirMonitor { - EntryDirectory* ed; - EntryDirectoryChangedFunc callback; - gpointer user_data; -}; - -static void cached_dir_free(CachedDir* dir); -static gboolean cached_dir_load_entries_recursive(CachedDir* dir, const char* dirname); - -static void handle_cached_dir_changed(MenuMonitor* monitor, MenuMonitorEvent event, const char* path, CachedDir* dir); - -/* - * Entry directory cache - */ - -static CachedDir* dir_cache = NULL; - -static CachedDir* cached_dir_new(const char *name) -{ - CachedDir* dir; - - dir = g_new0(CachedDir, 1); - - dir->name = g_strdup(name); - - return dir; -} - -static void cached_dir_free(CachedDir* dir) -{ - if (dir->dir_monitor) - { - menu_monitor_remove_notify (dir->dir_monitor, - (MenuMonitorNotifyFunc) handle_cached_dir_changed, - dir); - menu_monitor_unref (dir->dir_monitor); - dir->dir_monitor = NULL; - } - - g_slist_foreach (dir->monitors, (GFunc) g_free, NULL); - g_slist_free (dir->monitors); - dir->monitors = NULL; - - g_slist_foreach (dir->entries, - (GFunc) desktop_entry_unref, - NULL); - g_slist_free (dir->entries); - dir->entries = NULL; - - g_slist_foreach (dir->subdirs, - (GFunc) cached_dir_free, - NULL); - g_slist_free (dir->subdirs); - dir->subdirs = NULL; - - g_free (dir->name); - g_free (dir); -} - -static inline CachedDir* find_subdir(CachedDir* dir, const char* subdir) -{ - GSList *tmp; - - tmp = dir->subdirs; - while (tmp != NULL) - { - CachedDir *sub = tmp->data; - - if (strcmp (sub->name, subdir) == 0) - return sub; - - tmp = tmp->next; - } - - return NULL; -} - -static DesktopEntry* find_entry(CachedDir* dir, const char* basename) -{ - GSList *tmp; - - tmp = dir->entries; - while (tmp != NULL) - { - if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0) - return tmp->data; - - tmp = tmp->next; - } - - return NULL; -} - -static DesktopEntry* cached_dir_find_relative_path(CachedDir* dir, const char* relative_path) -{ - DesktopEntry *retval = NULL; - char **split; - int i; - - split = g_strsplit (relative_path, "/", -1); - - i = 0; - while (split[i] != NULL) - { - if (split[i + 1] != NULL) - { - if ((dir = find_subdir (dir, split[i])) == NULL) - break; - } - else - { - retval = find_entry (dir, split[i]); - break; - } - - ++i; - } - - g_strfreev (split); - - return retval; -} - -static CachedDir* cached_dir_lookup(const char* canonical) -{ - CachedDir *dir; - char **split; - int i; - - if (dir_cache == NULL) - dir_cache = cached_dir_new ("/"); - dir = dir_cache; - - g_assert (canonical != NULL && canonical[0] == G_DIR_SEPARATOR); - - menu_verbose ("Looking up cached dir \"%s\"\n", canonical); - - split = g_strsplit (canonical + 1, "/", -1); - - i = 0; - while (split[i] != NULL) - { - CachedDir *subdir; - - if ((subdir = find_subdir (dir, split[i])) == NULL) - { - subdir = cached_dir_new (split[i]); - dir->subdirs = g_slist_prepend (dir->subdirs, subdir); - subdir->parent = dir; - } - - dir = subdir; - - ++i; - } - - g_strfreev (split); - - g_assert (dir != NULL); - - return dir; -} - -static gboolean cached_dir_add_entry(CachedDir* dir, const char* basename, const char* path) -{ - DesktopEntry *entry; - - entry = desktop_entry_new (path); - if (entry == NULL) - return FALSE; - - dir->entries = g_slist_prepend (dir->entries, entry); - - return TRUE; -} - -static gboolean cached_dir_update_entry(CachedDir* dir, const char* basename, const char* path) -{ - GSList *tmp; - - tmp = dir->entries; - while (tmp != NULL) - { - if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0) - { - if (!desktop_entry_reload (tmp->data)) - { - dir->entries = g_slist_delete_link (dir->entries, tmp); - } - - return TRUE; - } - - tmp = tmp->next; - } - - return cached_dir_add_entry (dir, basename, path); -} - -static gboolean cached_dir_remove_entry(CachedDir* dir, const char* basename) -{ - GSList *tmp; - - tmp = dir->entries; - while (tmp != NULL) - { - if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0) - { - desktop_entry_unref (tmp->data); - dir->entries = g_slist_delete_link (dir->entries, tmp); - return TRUE; - } - - tmp = tmp->next; - } - - return FALSE; -} - -static gboolean cached_dir_add_subdir(CachedDir* dir, const char* basename, const char* path) -{ - CachedDir *subdir; - - subdir = find_subdir (dir, basename); - - if (subdir != NULL) - { - subdir->deleted = FALSE; - return TRUE; - } - - subdir = cached_dir_new (basename); - - if (!cached_dir_load_entries_recursive (subdir, path)) - { - cached_dir_free (subdir); - return FALSE; - } - - menu_verbose ("Caching dir \"%s\"\n", basename); - - subdir->parent = dir; - dir->subdirs = g_slist_prepend (dir->subdirs, subdir); - - return TRUE; -} - -static gboolean cached_dir_remove_subdir(CachedDir* dir, const char* basename) -{ - CachedDir *subdir; - - subdir = find_subdir (dir, basename); - - if (subdir != NULL) - { - subdir->deleted = TRUE; - - if (subdir->references == 0) - { - cached_dir_free (subdir); - dir->subdirs = g_slist_remove (dir->subdirs, subdir); - } - - return TRUE; - } - - return FALSE; -} - -static void cached_dir_invoke_monitors(CachedDir* dir) -{ - GSList *tmp; - - tmp = dir->monitors; - while (tmp != NULL) - { - CachedDirMonitor *monitor = tmp->data; - GSList *next = tmp->next; - - monitor->callback (monitor->ed, monitor->user_data); - - tmp = next; - } - - if (dir->parent) - { - cached_dir_invoke_monitors (dir->parent); - } -} - -static void handle_cached_dir_changed (MenuMonitor* monitor, MenuMonitorEvent event, const char* path, CachedDir* dir) -{ - gboolean handled = FALSE; - char *basename; - char *dirname; - - menu_verbose ("'%s' notified of '%s' %s - invalidating cache\n", - dir->name, - path, - event == MENU_MONITOR_EVENT_CREATED ? ("created") : - event == MENU_MONITOR_EVENT_DELETED ? ("deleted") : ("changed")); - - dirname = g_path_get_dirname (path); - basename = g_path_get_basename (path); - - dir = cached_dir_lookup (dirname); - - if (g_str_has_suffix (basename, ".desktop") || - g_str_has_suffix (basename, ".directory")) - { - switch (event) - { - case MENU_MONITOR_EVENT_CREATED: - case MENU_MONITOR_EVENT_CHANGED: - handled = cached_dir_update_entry (dir, basename, path); - break; - - case MENU_MONITOR_EVENT_DELETED: - handled = cached_dir_remove_entry (dir, basename); - break; - - default: - g_assert_not_reached (); - break; - } - } - else /* Try recursing */ - { - switch (event) - { - case MENU_MONITOR_EVENT_CREATED: - handled = cached_dir_add_subdir (dir, basename, path); - break; - - case MENU_MONITOR_EVENT_CHANGED: - break; - - case MENU_MONITOR_EVENT_DELETED: - handled = cached_dir_remove_subdir (dir, basename); - break; - - default: - g_assert_not_reached (); - break; - } - } - - g_free (basename); - g_free (dirname); - - if (handled) - { - /* CHANGED events don't change the set of desktop entries */ - if (event == MENU_MONITOR_EVENT_CREATED || event == MENU_MONITOR_EVENT_DELETED) - { - _entry_directory_list_empty_desktop_cache (); - } - - cached_dir_invoke_monitors (dir); - } -} - -static void cached_dir_ensure_monitor(CachedDir* dir, const char* dirname) -{ - if (dir->dir_monitor == NULL) - { - dir->dir_monitor = menu_get_directory_monitor (dirname); - menu_monitor_add_notify (dir->dir_monitor, - (MenuMonitorNotifyFunc) handle_cached_dir_changed, - dir); - } -} - -static gboolean cached_dir_load_entries_recursive(CachedDir* dir, const char* dirname) -{ - DIR *dp; - struct dirent *dent; - GString *fullpath; - gsize fullpath_len; - - g_assert (dir != NULL); - - if (dir->have_read_entries) - return TRUE; - - menu_verbose ("Attempting to read entries from %s (full path %s)\n", - dir->name, dirname); - - dp = opendir (dirname); - if (dp == NULL) - { - menu_verbose ("Unable to list directory \"%s\"\n", - dirname); - return FALSE; - } - - cached_dir_ensure_monitor (dir, dirname); - - fullpath = g_string_new (dirname); - if (fullpath->str[fullpath->len - 1] != G_DIR_SEPARATOR) - g_string_append_c (fullpath, G_DIR_SEPARATOR); - - fullpath_len = fullpath->len; - - while ((dent = readdir (dp)) != NULL) - { - /* ignore . and .. */ - if (dent->d_name[0] == '.' && - (dent->d_name[1] == '\0' || - (dent->d_name[1] == '.' && - dent->d_name[2] == '\0'))) - continue; - - g_string_append (fullpath, dent->d_name); - - if (g_str_has_suffix (dent->d_name, ".desktop") || - g_str_has_suffix (dent->d_name, ".directory")) - { - cached_dir_add_entry (dir, dent->d_name, fullpath->str); - } - else /* Try recursing */ - { - cached_dir_add_subdir (dir, dent->d_name, fullpath->str); - } - - g_string_truncate (fullpath, fullpath_len); - } - - closedir (dp); - - g_string_free (fullpath, TRUE); - - dir->have_read_entries = TRUE; - - return TRUE; -} - -static void cached_dir_add_monitor(CachedDir* dir, EntryDirectory* ed, EntryDirectoryChangedFunc callback, gpointer user_data) -{ - CachedDirMonitor *monitor; - GSList *tmp; - - tmp = dir->monitors; - while (tmp != NULL) - { - monitor = tmp->data; - - if (monitor->ed == ed && - monitor->callback == callback && - monitor->user_data == user_data) - break; - - tmp = tmp->next; - } - - if (tmp == NULL) - { - monitor = g_new0 (CachedDirMonitor, 1); - monitor->ed = ed; - monitor->callback = callback; - monitor->user_data = user_data; - - dir->monitors = g_slist_append (dir->monitors, monitor); - } -} - -static void cached_dir_remove_monitor(CachedDir* dir, EntryDirectory* ed, EntryDirectoryChangedFunc callback, gpointer user_data) -{ - GSList *tmp; - - tmp = dir->monitors; - while (tmp != NULL) - { - CachedDirMonitor *monitor = tmp->data; - GSList *next = tmp->next; - - if (monitor->ed == ed && - monitor->callback == callback && - monitor->user_data == user_data) - { - dir->monitors = g_slist_delete_link (dir->monitors, tmp); - g_free (monitor); - } - - tmp = next; - } -} - -static void cached_dir_add_reference(CachedDir* dir) -{ - dir->references++; - - if (dir->parent != NULL) - { - cached_dir_add_reference (dir->parent); - } -} - -static void cached_dir_remove_reference(CachedDir* dir) -{ - CachedDir *parent; - - parent = dir->parent; - - if (--dir->references == 0 && dir->deleted) - { - if (dir->parent != NULL) - { - GSList *tmp; - - tmp = parent->subdirs; - while (tmp != NULL) - { - CachedDir *subdir = tmp->data; - - if (!strcmp (subdir->name, dir->name)) - { - parent->subdirs = g_slist_delete_link (parent->subdirs, tmp); - break; - } - - tmp = tmp->next; - } - } - - cached_dir_free (dir); - } - - if (parent != NULL) - { - cached_dir_remove_reference (parent); - } -} - -/* - * Entry directories - */ - -static EntryDirectory* entry_directory_new_full(DesktopEntryType entry_type, const char* path, gboolean is_legacy, const char* legacy_prefix) -{ - EntryDirectory *ed; - char *canonical; - - menu_verbose ("Loading entry directory \"%s\" (legacy %s)\n", - path, - is_legacy ? "<yes>" : "<no>"); - - canonical = menu_canonicalize_file_name (path, FALSE); - if (canonical == NULL) - { - menu_verbose ("Failed to canonicalize \"%s\": %s\n", - path, g_strerror (errno)); - return NULL; - } - - ed = g_new0 (EntryDirectory, 1); - - ed->dir = cached_dir_lookup (canonical); - g_assert (ed->dir != NULL); - - cached_dir_add_reference (ed->dir); - cached_dir_load_entries_recursive (ed->dir, canonical); - - ed->legacy_prefix = g_strdup (legacy_prefix); - ed->entry_type = entry_type; - ed->is_legacy = is_legacy != FALSE; - ed->refcount = 1; - - g_free (canonical); - - return ed; -} - -EntryDirectory* entry_directory_new(DesktopEntryType entry_type, const char* path) -{ - return entry_directory_new_full (entry_type, path, FALSE, NULL); -} - -EntryDirectory* entry_directory_new_legacy(DesktopEntryType entry_type, const char* path, const char* legacy_prefix) -{ - return entry_directory_new_full(entry_type, path, TRUE, legacy_prefix); -} - -EntryDirectory* entry_directory_ref(EntryDirectory* ed) -{ - g_return_val_if_fail(ed != NULL, NULL); - g_return_val_if_fail(ed->refcount > 0, NULL); - - ed->refcount++; - - return ed; -} - -void entry_directory_unref(EntryDirectory* ed) -{ - g_return_if_fail (ed != NULL); - g_return_if_fail (ed->refcount > 0); - - if (--ed->refcount == 0) - { - cached_dir_remove_reference (ed->dir); - - ed->dir = NULL; - ed->entry_type = DESKTOP_ENTRY_INVALID; - ed->is_legacy = FALSE; - - g_free (ed->legacy_prefix); - ed->legacy_prefix = NULL; - - g_free (ed); - } -} - -static void entry_directory_add_monitor(EntryDirectory* ed, EntryDirectoryChangedFunc callback, gpointer user_data) -{ - cached_dir_add_monitor (ed->dir, ed, callback, user_data); -} - -static void entry_directory_remove_monitor(EntryDirectory* ed, EntryDirectoryChangedFunc callback, gpointer user_data) -{ - cached_dir_remove_monitor (ed->dir, ed, callback, user_data); -} - -static DesktopEntry* entry_directory_get_directory(EntryDirectory* ed, const char* relative_path) -{ - DesktopEntry *entry; - - if (ed->entry_type != DESKTOP_ENTRY_DIRECTORY) - return NULL; - - entry = cached_dir_find_relative_path (ed->dir, relative_path); - if (entry == NULL || desktop_entry_get_type (entry) != DESKTOP_ENTRY_DIRECTORY) - return NULL; - - return desktop_entry_ref (entry); -} - -static char* get_desktop_file_id_from_path(EntryDirectory* ed, DesktopEntryType entry_type, const char* relative_path) -{ - char *retval; - - retval = NULL; - - if (entry_type == DESKTOP_ENTRY_DESKTOP) - { - if (!ed->is_legacy) - { - retval = g_strdelimit (g_strdup (relative_path), "/", '-'); - } - else - { - char *basename; - - basename = g_path_get_basename (relative_path); - - if (ed->legacy_prefix) - { - retval = g_strjoin ("-", ed->legacy_prefix, basename, NULL); - g_free (basename); - } - else - { - retval = basename; - } - } - } - else - { - retval = g_strdup (relative_path); - } - - return retval; -} - -typedef gboolean (*EntryDirectoryForeachFunc) (EntryDirectory* ed, DesktopEntry* entry, const char* file_id, DesktopEntrySet* set, gpointer user_data); - -static gboolean entry_directory_foreach_recursive(EntryDirectory* ed, CachedDir* cd, GString* relative_path, EntryDirectoryForeachFunc func, DesktopEntrySet* set, gpointer user_data) -{ - GSList *tmp; - int relative_path_len; - - if (cd->deleted) - return TRUE; - - relative_path_len = relative_path->len; - - tmp = cd->entries; - while (tmp != NULL) - { - DesktopEntry *entry = tmp->data; - - if (desktop_entry_get_type (entry) == ed->entry_type) - { - gboolean ret; - char *file_id; - - g_string_append (relative_path, - desktop_entry_get_basename (entry)); - - file_id = get_desktop_file_id_from_path (ed, - ed->entry_type, - relative_path->str); - - ret = func (ed, entry, file_id, set, user_data); - - g_free (file_id); - - g_string_truncate (relative_path, relative_path_len); - - if (!ret) - return FALSE; - } - - tmp = tmp->next; - } - - tmp = cd->subdirs; - while (tmp != NULL) - { - CachedDir *subdir = tmp->data; - - g_string_append (relative_path, subdir->name); - g_string_append_c (relative_path, G_DIR_SEPARATOR); - - if (!entry_directory_foreach_recursive (ed, - subdir, - relative_path, - func, - set, - user_data)) - return FALSE; - - g_string_truncate (relative_path, relative_path_len); - - tmp = tmp->next; - } - - return TRUE; -} - -static void entry_directory_foreach(EntryDirectory* ed, EntryDirectoryForeachFunc func, DesktopEntrySet* set, gpointer user_data) -{ - GString *path; - - path = g_string_new (NULL); - - entry_directory_foreach_recursive (ed, - ed->dir, - path, - func, - set, - user_data); - - g_string_free (path, TRUE); -} - -void entry_directory_get_flat_contents(EntryDirectory* ed, DesktopEntrySet* desktop_entries, DesktopEntrySet* directory_entries, GSList** subdirs) -{ - GSList *tmp; - - if (subdirs) - *subdirs = NULL; - - tmp = ed->dir->entries; - while (tmp != NULL) - { - DesktopEntry *entry = tmp->data; - const char *basename; - - basename = desktop_entry_get_basename (entry); - - if (desktop_entries && - desktop_entry_get_type (entry) == DESKTOP_ENTRY_DESKTOP) - { - char *file_id; - - file_id = get_desktop_file_id_from_path (ed, - DESKTOP_ENTRY_DESKTOP, - basename); - - desktop_entry_set_add_entry (desktop_entries, - entry, - file_id); - - g_free (file_id); - } - - if (directory_entries && - desktop_entry_get_type (entry) == DESKTOP_ENTRY_DIRECTORY) - { - desktop_entry_set_add_entry (directory_entries, - entry, - basename); - } - - tmp = tmp->next; - } - - if (subdirs) - { - tmp = ed->dir->subdirs; - while (tmp != NULL) - { - CachedDir *cd = tmp->data; - - if (!cd->deleted) - { - *subdirs = g_slist_prepend (*subdirs, g_strdup (cd->name)); - } - - tmp = tmp->next; - } - } - - if (subdirs) - *subdirs = g_slist_reverse (*subdirs); -} - -/* - * Entry directory lists - */ - -EntryDirectoryList* entry_directory_list_new(void) -{ - EntryDirectoryList *list; - - list = g_new0 (EntryDirectoryList, 1); - - list->refcount = 1; - list->dirs = NULL; - list->length = 0; - - return list; -} - -EntryDirectoryList* entry_directory_list_ref(EntryDirectoryList* list) -{ - g_return_val_if_fail (list != NULL, NULL); - g_return_val_if_fail (list->refcount > 0, NULL); - - list->refcount += 1; - - return list; -} - -void entry_directory_list_unref(EntryDirectoryList* list) -{ - g_return_if_fail (list != NULL); - g_return_if_fail (list->refcount > 0); - - list->refcount -= 1; - if (list->refcount == 0) - { - g_list_foreach (list->dirs, (GFunc) entry_directory_unref, NULL); - g_list_free (list->dirs); - list->dirs = NULL; - list->length = 0; - g_free (list); - } -} - -void entry_directory_list_prepend(EntryDirectoryList* list, EntryDirectory* ed) -{ - list->length += 1; - list->dirs = g_list_prepend (list->dirs, - entry_directory_ref (ed)); -} - -int entry_directory_list_get_length(EntryDirectoryList* list) -{ - return list->length; -} - -void entry_directory_list_append_list(EntryDirectoryList* list, EntryDirectoryList* to_append) -{ - GList *tmp; - GList *new_dirs = NULL; - - if (to_append->length == 0) - return; - - tmp = to_append->dirs; - while (tmp != NULL) - { - list->length += 1; - new_dirs = g_list_prepend (new_dirs, - entry_directory_ref (tmp->data)); - - tmp = tmp->next; - } - - new_dirs = g_list_reverse (new_dirs); - list->dirs = g_list_concat (list->dirs, new_dirs); -} - -DesktopEntry* entry_directory_list_get_directory(EntryDirectoryList *list, const char* relative_path) -{ - DesktopEntry *retval = NULL; - GList *tmp; - - tmp = list->dirs; - while (tmp != NULL) - { - if ((retval = entry_directory_get_directory (tmp->data, relative_path)) != NULL) - break; - - tmp = tmp->next; - } - - return retval; -} - -gboolean _entry_directory_list_compare(const EntryDirectoryList* a, const EntryDirectoryList* b) -{ - GList *al, *bl; - - if (a == NULL && b == NULL) - return TRUE; - - if ((a == NULL || b == NULL)) - return FALSE; - - if (a->length != b->length) - return FALSE; - - al = a->dirs; bl = b->dirs; - while (al && bl && al->data == bl->data) - { - al = al->next; - bl = bl->next; - } - - return (al == NULL && bl == NULL); -} - -static gboolean get_all_func(EntryDirectory* ed, DesktopEntry* entry, const char* file_id, DesktopEntrySet* set, gpointer user_data) -{ - if (ed->is_legacy && !desktop_entry_has_categories (entry)) - { - entry = desktop_entry_copy (entry); - desktop_entry_add_legacy_category (entry); - } - else - { - entry = desktop_entry_ref (entry); - } - - desktop_entry_set_add_entry (set, entry, file_id); - desktop_entry_unref (entry); - - return TRUE; -} - -static DesktopEntrySet* entry_directory_last_set = NULL; -static EntryDirectoryList* entry_directory_last_list = NULL; - -void _entry_directory_list_empty_desktop_cache(void) -{ - if (entry_directory_last_set != NULL) - desktop_entry_set_unref (entry_directory_last_set); - entry_directory_last_set = NULL; - - if (entry_directory_last_list != NULL) - entry_directory_list_unref (entry_directory_last_list); - entry_directory_last_list = NULL; -} - -DesktopEntrySet* _entry_directory_list_get_all_desktops(EntryDirectoryList* list) -{ - GList *tmp; - DesktopEntrySet *set; - - /* The only tricky thing here is that desktop files later - * in the search list with the same relative path - * are "hidden" by desktop files earlier in the path, - * so we have to do the earlier files first causing - * the later files to replace the earlier files - * in the DesktopEntrySet - * - * We go from the end of the list so we can just - * g_hash_table_replace and not have to do two - * hash lookups (check for existing entry, then insert new - * entry) - */ - - /* This method is -extremely- slow, so we have a simple - one-entry cache here */ - if (_entry_directory_list_compare (list, entry_directory_last_list)) - { - menu_verbose (" Hit desktop list (%p) cache\n", list); - return desktop_entry_set_ref (entry_directory_last_set); - } - - if (entry_directory_last_set != NULL) - desktop_entry_set_unref (entry_directory_last_set); - if (entry_directory_last_list != NULL) - entry_directory_list_unref (entry_directory_last_list); - - set = desktop_entry_set_new (); - menu_verbose (" Storing all of list %p in set %p\n", - list, set); - - tmp = g_list_last (list->dirs); - while (tmp != NULL) - { - entry_directory_foreach (tmp->data, get_all_func, set, NULL); - - tmp = tmp->prev; - } - - entry_directory_last_list = entry_directory_list_ref (list); - entry_directory_last_set = desktop_entry_set_ref (set); - - return set; -} - -void entry_directory_list_add_monitors(EntryDirectoryList* list, EntryDirectoryChangedFunc callback, gpointer user_data) -{ - GList *tmp; - - tmp = list->dirs; - while (tmp != NULL) - { - entry_directory_add_monitor (tmp->data, callback, user_data); - tmp = tmp->next; - } -} - -void entry_directory_list_remove_monitors(EntryDirectoryList* list, EntryDirectoryChangedFunc callback, gpointer user_data) -{ - GList *tmp; - - tmp = list->dirs; - while (tmp != NULL) - { - entry_directory_remove_monitor (tmp->data, callback, user_data); - tmp = tmp->next; - } -} diff --git a/src/entry-directories.h b/src/entry-directories.h deleted file mode 100644 index 5b9dfae5..00000000 --- a/src/entry-directories.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2002 - 2004 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __ENTRY_DIRECTORIES_H__ -#define __ENTRY_DIRECTORIES_H__ - -#include <glib.h> -#include "desktop-entries.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct EntryDirectory EntryDirectory; - -typedef void (*EntryDirectoryChangedFunc) (EntryDirectory* ed, gpointer user_data); - -EntryDirectory* entry_directory_new(DesktopEntryType entry_type, const char* path); -EntryDirectory* entry_directory_new_legacy(DesktopEntryType entry_type, const char* path, const char* legacy_prefix); - -EntryDirectory* entry_directory_ref(EntryDirectory* ed); -void entry_directory_unref(EntryDirectory* ed); - -void entry_directory_get_flat_contents(EntryDirectory* ed, DesktopEntrySet* desktop_entries, DesktopEntrySet* directory_entries, GSList** subdirs); - - -typedef struct EntryDirectoryList EntryDirectoryList; - -EntryDirectoryList* entry_directory_list_new(void); -EntryDirectoryList* entry_directory_list_ref(EntryDirectoryList* list); -void entry_directory_list_unref(EntryDirectoryList* list); - -int entry_directory_list_get_length(EntryDirectoryList* list); -gboolean _entry_directory_list_compare(const EntryDirectoryList* a, const EntryDirectoryList* b); - -void entry_directory_list_prepend(EntryDirectoryList* list, EntryDirectory* ed); -void entry_directory_list_append_list(EntryDirectoryList* list, EntryDirectoryList* to_append); - -void entry_directory_list_add_monitors(EntryDirectoryList* list, EntryDirectoryChangedFunc callback, gpointer user_data); -void entry_directory_list_remove_monitors(EntryDirectoryList* list, EntryDirectoryChangedFunc callback, gpointer user_data); - -DesktopEntry* entry_directory_list_get_directory (EntryDirectoryList* list, const char* relative_path); - -DesktopEntrySet* _entry_directory_list_get_all_desktops(EntryDirectoryList* list); -void _entry_directory_list_empty_desktop_cache(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __ENTRY_DIRECTORIES_H__ */ diff --git a/src/menu-layout.c b/src/menu-layout.c deleted file mode 100644 index 89e97523..00000000 --- a/src/menu-layout.c +++ /dev/null @@ -1,2359 +0,0 @@ -/* Menu layout in-memory data structure (a custom "DOM tree") */ - -/* - * Copyright (C) 2002 - 2004 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <config.h> - -#include "menu-layout.h" - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> - -#include "canonicalize.h" -#include "entry-directories.h" -#include "menu-util.h" - -typedef struct MenuLayoutNodeMenu MenuLayoutNodeMenu; -typedef struct MenuLayoutNodeRoot MenuLayoutNodeRoot; -typedef struct MenuLayoutNodeLegacyDir MenuLayoutNodeLegacyDir; -typedef struct MenuLayoutNodeMergeFile MenuLayoutNodeMergeFile; -typedef struct MenuLayoutNodeDefaultLayout MenuLayoutNodeDefaultLayout; -typedef struct MenuLayoutNodeMenuname MenuLayoutNodeMenuname; -typedef struct MenuLayoutNodeMerge MenuLayoutNodeMerge; - -struct MenuLayoutNode -{ - /* Node lists are circular, for length-one lists - * prev/next point back to the node itself. - */ - MenuLayoutNode *prev; - MenuLayoutNode *next; - MenuLayoutNode *parent; - MenuLayoutNode *children; - - char *content; - - guint refcount : 20; - guint type : 7; -}; - -struct MenuLayoutNodeRoot -{ - MenuLayoutNode node; - - char *basedir; - char *name; - - GSList *monitors; -}; - -struct MenuLayoutNodeMenu -{ - MenuLayoutNode node; - - MenuLayoutNode *name_node; /* cache of the <Name> node */ - - EntryDirectoryList *app_dirs; - EntryDirectoryList *dir_dirs; -}; - -struct MenuLayoutNodeLegacyDir -{ - MenuLayoutNode node; - - char *prefix; -}; - -struct MenuLayoutNodeMergeFile -{ - MenuLayoutNode node; - - MenuMergeFileType type; -}; - -struct MenuLayoutNodeDefaultLayout -{ - MenuLayoutNode node; - - MenuLayoutValues layout_values; -}; - -struct MenuLayoutNodeMenuname -{ - MenuLayoutNode node; - - MenuLayoutValues layout_values; -}; - -struct MenuLayoutNodeMerge -{ - MenuLayoutNode node; - - MenuLayoutMergeType merge_type; -}; - -typedef struct -{ - MenuLayoutNodeEntriesChangedFunc callback; - gpointer user_data; -} MenuLayoutNodeEntriesMonitor; - - -static inline MenuLayoutNode * -node_next (MenuLayoutNode *node) -{ - /* root nodes (no parent) never have siblings */ - if (node->parent == NULL) - return NULL; - - /* circular list */ - if (node->next == node->parent->children) - return NULL; - - return node->next; -} - -static void -handle_entry_directory_changed (EntryDirectory *dir, - MenuLayoutNode *node) -{ - MenuLayoutNodeRoot *nr; - GSList *tmp; - - g_assert (node->type == MENU_LAYOUT_NODE_MENU); - - nr = (MenuLayoutNodeRoot *) menu_layout_node_get_root (node); - - tmp = nr->monitors; - while (tmp != NULL) - { - MenuLayoutNodeEntriesMonitor *monitor = tmp->data; - GSList *next = tmp->next; - - monitor->callback ((MenuLayoutNode *) nr, monitor->user_data); - - tmp = next; - } -} - -static void -remove_entry_directory_list (MenuLayoutNodeMenu *nm, - EntryDirectoryList **dirs) -{ - if (*dirs) - { - entry_directory_list_remove_monitors (*dirs, - (EntryDirectoryChangedFunc) handle_entry_directory_changed, - nm); - entry_directory_list_unref (*dirs); - *dirs = NULL; - } -} - -MenuLayoutNode * -menu_layout_node_ref (MenuLayoutNode *node) -{ - g_return_val_if_fail (node != NULL, NULL); - - node->refcount += 1; - - return node; -} - -void -menu_layout_node_unref (MenuLayoutNode *node) -{ - g_return_if_fail (node != NULL); - g_return_if_fail (node->refcount > 0); - - node->refcount -= 1; - if (node->refcount == 0) - { - MenuLayoutNode *iter; - - iter = node->children; - while (iter != NULL) - { - MenuLayoutNode *next = node_next (iter); - - menu_layout_node_unref (iter); - - iter = next; - } - - if (node->type == MENU_LAYOUT_NODE_MENU) - { - MenuLayoutNodeMenu *nm = (MenuLayoutNodeMenu *) node; - - if (nm->name_node) - menu_layout_node_unref (nm->name_node); - - remove_entry_directory_list (nm, &nm->app_dirs); - remove_entry_directory_list (nm, &nm->dir_dirs); - } - else if (node->type == MENU_LAYOUT_NODE_LEGACY_DIR) - { - MenuLayoutNodeLegacyDir *legacy = (MenuLayoutNodeLegacyDir *) node; - - g_free (legacy->prefix); - } - else if (node->type == MENU_LAYOUT_NODE_ROOT) - { - MenuLayoutNodeRoot *nr = (MenuLayoutNodeRoot*) node; - - g_slist_foreach (nr->monitors, (GFunc) g_free, NULL); - g_slist_free (nr->monitors); - - g_free (nr->basedir); - g_free (nr->name); - } - - g_free (node->content); - g_free (node); - } -} - -MenuLayoutNode * -menu_layout_node_new (MenuLayoutNodeType type) -{ - MenuLayoutNode *node; - - switch (type) - { - case MENU_LAYOUT_NODE_MENU: - node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMenu, 1); - break; - - case MENU_LAYOUT_NODE_LEGACY_DIR: - node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeLegacyDir, 1); - break; - - case MENU_LAYOUT_NODE_ROOT: - node = (MenuLayoutNode*) g_new0 (MenuLayoutNodeRoot, 1); - break; - - case MENU_LAYOUT_NODE_MERGE_FILE: - node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMergeFile, 1); - break; - - case MENU_LAYOUT_NODE_DEFAULT_LAYOUT: - node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeDefaultLayout, 1); - break; - - case MENU_LAYOUT_NODE_MENUNAME: - node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMenuname, 1); - break; - - case MENU_LAYOUT_NODE_MERGE: - node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMerge, 1); - break; - - default: - node = g_new0 (MenuLayoutNode, 1); - break; - } - - node->type = type; - - node->refcount = 1; - - /* we're in a list of one node */ - node->next = node; - node->prev = node; - - return node; -} - -MenuLayoutNode * -menu_layout_node_get_next (MenuLayoutNode *node) -{ - return node_next (node); -} - -MenuLayoutNode * -menu_layout_node_get_parent (MenuLayoutNode *node) -{ - return node->parent; -} - -MenuLayoutNode * -menu_layout_node_get_children (MenuLayoutNode *node) -{ - return node->children; -} - -MenuLayoutNode * -menu_layout_node_get_root (MenuLayoutNode *node) -{ - MenuLayoutNode *parent; - - parent = node; - while (parent->parent != NULL) - parent = parent->parent; - - g_assert (parent->type == MENU_LAYOUT_NODE_ROOT); - - return parent; -} - -char * -menu_layout_node_get_content_as_path (MenuLayoutNode *node) -{ - if (node->content == NULL) - { - menu_verbose (" (node has no content to get as a path)\n"); - return NULL; - } - - if (g_path_is_absolute (node->content)) - { - return g_strdup (node->content); - } - else - { - MenuLayoutNodeRoot *root; - - root = (MenuLayoutNodeRoot *) menu_layout_node_get_root (node); - - if (root->basedir == NULL) - { - menu_verbose ("No basedir available, using \"%s\" as-is\n", - node->content); - return g_strdup (node->content); - } - else - { - menu_verbose ("Using basedir \"%s\" filename \"%s\"\n", - root->basedir, node->content); - return g_build_filename (root->basedir, node->content, NULL); - } - } -} - -#define RETURN_IF_NO_PARENT(node) G_STMT_START { \ - if ((node)->parent == NULL) \ - { \ - g_warning ("To add siblings to a menu node, " \ - "it must not be the root node, " \ - "and must be linked in below some root node\n" \ - "node parent = %p and type = %d", \ - (node)->parent, (node)->type); \ - return; \ - } \ - } G_STMT_END - -#define RETURN_IF_HAS_ENTRY_DIRS(node) G_STMT_START { \ - if ((node)->type == MENU_LAYOUT_NODE_MENU && \ - (((MenuLayoutNodeMenu*)(node))->app_dirs != NULL || \ - ((MenuLayoutNodeMenu*)(node))->dir_dirs != NULL)) \ - { \ - g_warning ("node acquired ->app_dirs or ->dir_dirs " \ - "while not rooted in a tree\n"); \ - return; \ - } \ - } G_STMT_END \ - -void -menu_layout_node_insert_before (MenuLayoutNode *node, - MenuLayoutNode *new_sibling) -{ - g_return_if_fail (new_sibling != NULL); - g_return_if_fail (new_sibling->parent == NULL); - - RETURN_IF_NO_PARENT (node); - RETURN_IF_HAS_ENTRY_DIRS (new_sibling); - - new_sibling->next = node; - new_sibling->prev = node->prev; - - node->prev = new_sibling; - new_sibling->prev->next = new_sibling; - - new_sibling->parent = node->parent; - - if (node == node->parent->children) - node->parent->children = new_sibling; - - menu_layout_node_ref (new_sibling); -} - -void -menu_layout_node_insert_after (MenuLayoutNode *node, - MenuLayoutNode *new_sibling) -{ - g_return_if_fail (new_sibling != NULL); - g_return_if_fail (new_sibling->parent == NULL); - - RETURN_IF_NO_PARENT (node); - RETURN_IF_HAS_ENTRY_DIRS (new_sibling); - - new_sibling->prev = node; - new_sibling->next = node->next; - - node->next = new_sibling; - new_sibling->next->prev = new_sibling; - - new_sibling->parent = node->parent; - - menu_layout_node_ref (new_sibling); -} - -void -menu_layout_node_prepend_child (MenuLayoutNode *parent, - MenuLayoutNode *new_child) -{ - RETURN_IF_HAS_ENTRY_DIRS (new_child); - - if (parent->children) - { - menu_layout_node_insert_before (parent->children, new_child); - } - else - { - parent->children = menu_layout_node_ref (new_child); - new_child->parent = parent; - } -} - -void -menu_layout_node_append_child (MenuLayoutNode *parent, - MenuLayoutNode *new_child) -{ - RETURN_IF_HAS_ENTRY_DIRS (new_child); - - if (parent->children) - { - menu_layout_node_insert_after (parent->children->prev, new_child); - } - else - { - parent->children = menu_layout_node_ref (new_child); - new_child->parent = parent; - } -} - -void -menu_layout_node_unlink (MenuLayoutNode *node) -{ - g_return_if_fail (node != NULL); - g_return_if_fail (node->parent != NULL); - - menu_layout_node_steal (node); - menu_layout_node_unref (node); -} - -static void -recursive_clean_entry_directory_lists (MenuLayoutNode *node, - gboolean apps) -{ - EntryDirectoryList **dirs; - MenuLayoutNodeMenu *nm; - MenuLayoutNode *iter; - - if (node->type != MENU_LAYOUT_NODE_MENU) - return; - - nm = (MenuLayoutNodeMenu *) node; - - dirs = apps ? &nm->app_dirs : &nm->dir_dirs; - - if (*dirs == NULL || entry_directory_list_get_length (*dirs) == 0) - return; /* child menus continue to have valid lists */ - - remove_entry_directory_list (nm, dirs); - - iter = node->children; - while (iter != NULL) - { - if (iter->type == MENU_LAYOUT_NODE_MENU) - recursive_clean_entry_directory_lists (iter, apps); - - iter = node_next (iter); - } -} - -void -menu_layout_node_steal (MenuLayoutNode *node) -{ - g_return_if_fail (node != NULL); - g_return_if_fail (node->parent != NULL); - - switch (node->type) - { - case MENU_LAYOUT_NODE_NAME: - { - MenuLayoutNodeMenu *nm = (MenuLayoutNodeMenu *) node->parent; - - if (nm->name_node == node) - { - menu_layout_node_unref (nm->name_node); - nm->name_node = NULL; - } - } - break; - - case MENU_LAYOUT_NODE_APP_DIR: - recursive_clean_entry_directory_lists (node->parent, TRUE); - break; - - case MENU_LAYOUT_NODE_DIRECTORY_DIR: - recursive_clean_entry_directory_lists (node->parent, FALSE); - break; - - default: - break; - } - - if (node->parent && node->parent->children == node) - { - if (node->next != node) - node->parent->children = node->next; - else - node->parent->children = NULL; - } - - /* these are no-ops for length-one node lists */ - node->prev->next = node->next; - node->next->prev = node->prev; - - node->parent = NULL; - - /* point to ourselves, now we're length one */ - node->next = node; - node->prev = node; -} - -MenuLayoutNodeType -menu_layout_node_get_type (MenuLayoutNode *node) -{ - return node->type; -} - -const char * -menu_layout_node_get_content (MenuLayoutNode *node) -{ - return node->content; -} - -void -menu_layout_node_set_content (MenuLayoutNode *node, - const char *content) -{ - if (node->content == content) - return; - - g_free (node->content); - node->content = g_strdup (content); -} - -const char * -menu_layout_node_root_get_name (MenuLayoutNode *node) -{ - MenuLayoutNodeRoot *nr; - - g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_ROOT, NULL); - - nr = (MenuLayoutNodeRoot*) node; - - return nr->name; -} - -const char * -menu_layout_node_root_get_basedir (MenuLayoutNode *node) -{ - MenuLayoutNodeRoot *nr; - - g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_ROOT, NULL); - - nr = (MenuLayoutNodeRoot*) node; - - return nr->basedir; -} - -const char * -menu_layout_node_menu_get_name (MenuLayoutNode *node) -{ - MenuLayoutNodeMenu *nm; - - g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MENU, NULL); - - nm = (MenuLayoutNodeMenu*) node; - - if (nm->name_node == NULL) - { - MenuLayoutNode *iter; - - iter = node->children; - while (iter != NULL) - { - if (iter->type == MENU_LAYOUT_NODE_NAME) - { - nm->name_node = menu_layout_node_ref (iter); - break; - } - - iter = node_next (iter); - } - } - - if (nm->name_node == NULL) - return NULL; - - return menu_layout_node_get_content (nm->name_node); -} - -static void -ensure_dir_lists (MenuLayoutNodeMenu *nm) -{ - MenuLayoutNode *node; - MenuLayoutNode *iter; - EntryDirectoryList *app_dirs; - EntryDirectoryList *dir_dirs; - - node = (MenuLayoutNode *) nm; - - if (nm->app_dirs && nm->dir_dirs) - return; - - app_dirs = NULL; - dir_dirs = NULL; - - if (nm->app_dirs == NULL) - { - app_dirs = entry_directory_list_new (); - - if (node->parent && node->parent->type == MENU_LAYOUT_NODE_MENU) - { - EntryDirectoryList *dirs; - - if ((dirs = menu_layout_node_menu_get_app_dirs (node->parent))) - entry_directory_list_append_list (app_dirs, dirs); - } - } - - if (nm->dir_dirs == NULL) - { - dir_dirs = entry_directory_list_new (); - - if (node->parent && node->parent->type == MENU_LAYOUT_NODE_MENU) - { - EntryDirectoryList *dirs; - - if ((dirs = menu_layout_node_menu_get_directory_dirs (node->parent))) - entry_directory_list_append_list (dir_dirs, dirs); - } - } - - iter = node->children; - while (iter != NULL) - { - EntryDirectory *ed; - - if (app_dirs != NULL && iter->type == MENU_LAYOUT_NODE_APP_DIR) - { - char *path; - - path = menu_layout_node_get_content_as_path (iter); - - ed = entry_directory_new (DESKTOP_ENTRY_DESKTOP, path); - if (ed != NULL) - { - entry_directory_list_prepend (app_dirs, ed); - entry_directory_unref (ed); - } - - g_free (path); - } - - if (dir_dirs != NULL && iter->type == MENU_LAYOUT_NODE_DIRECTORY_DIR) - { - char *path; - - path = menu_layout_node_get_content_as_path (iter); - - ed = entry_directory_new (DESKTOP_ENTRY_DIRECTORY, path); - if (ed != NULL) - { - entry_directory_list_prepend (dir_dirs, ed); - entry_directory_unref (ed); - } - - g_free (path); - } - - if (iter->type == MENU_LAYOUT_NODE_LEGACY_DIR) - { - MenuLayoutNodeLegacyDir *legacy = (MenuLayoutNodeLegacyDir *) iter; - char *path; - - path = menu_layout_node_get_content_as_path (iter); - - if (app_dirs != NULL) /* we're loading app dirs */ - { - ed = entry_directory_new_legacy (DESKTOP_ENTRY_DESKTOP, - path, - legacy->prefix); - if (ed != NULL) - { - entry_directory_list_prepend (app_dirs, ed); - entry_directory_unref (ed); - } - } - - if (dir_dirs != NULL) /* we're loading dir dirs */ - { - ed = entry_directory_new_legacy (DESKTOP_ENTRY_DIRECTORY, - path, - legacy->prefix); - if (ed != NULL) - { - entry_directory_list_prepend (dir_dirs, ed); - entry_directory_unref (ed); - } - } - - g_free (path); - } - - iter = node_next (iter); - } - - if (app_dirs) - { - g_assert (nm->app_dirs == NULL); - - nm->app_dirs = app_dirs; - entry_directory_list_add_monitors (nm->app_dirs, - (EntryDirectoryChangedFunc) handle_entry_directory_changed, - nm); - } - - if (dir_dirs) - { - g_assert (nm->dir_dirs == NULL); - - nm->dir_dirs = dir_dirs; - entry_directory_list_add_monitors (nm->dir_dirs, - (EntryDirectoryChangedFunc) handle_entry_directory_changed, - nm); - } -} - -EntryDirectoryList * -menu_layout_node_menu_get_app_dirs (MenuLayoutNode *node) -{ - MenuLayoutNodeMenu *nm; - - g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MENU, NULL); - - nm = (MenuLayoutNodeMenu *) node; - - ensure_dir_lists (nm); - - return nm->app_dirs; -} - -EntryDirectoryList * -menu_layout_node_menu_get_directory_dirs (MenuLayoutNode *node) -{ - MenuLayoutNodeMenu *nm; - - g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MENU, NULL); - - nm = (MenuLayoutNodeMenu *) node; - - ensure_dir_lists (nm); - - return nm->dir_dirs; -} - -const char * -menu_layout_node_move_get_old (MenuLayoutNode *node) -{ - MenuLayoutNode *iter; - - iter = node->children; - while (iter != NULL) - { - if (iter->type == MENU_LAYOUT_NODE_OLD) - return iter->content; - - iter = node_next (iter); - } - - return NULL; -} - -const char * -menu_layout_node_move_get_new (MenuLayoutNode *node) -{ - MenuLayoutNode *iter; - - iter = node->children; - while (iter != NULL) - { - if (iter->type == MENU_LAYOUT_NODE_NEW) - return iter->content; - - iter = node_next (iter); - } - - return NULL; -} - -const char * -menu_layout_node_legacy_dir_get_prefix (MenuLayoutNode *node) -{ - MenuLayoutNodeLegacyDir *legacy; - - g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_LEGACY_DIR, NULL); - - legacy = (MenuLayoutNodeLegacyDir *) node; - - return legacy->prefix; -} - -void -menu_layout_node_legacy_dir_set_prefix (MenuLayoutNode *node, - const char *prefix) -{ - MenuLayoutNodeLegacyDir *legacy; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_LEGACY_DIR); - - legacy = (MenuLayoutNodeLegacyDir *) node; - - g_free (legacy->prefix); - legacy->prefix = g_strdup (prefix); -} - -MenuMergeFileType -menu_layout_node_merge_file_get_type (MenuLayoutNode *node) -{ - MenuLayoutNodeMergeFile *merge_file; - - g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MERGE_FILE, FALSE); - - merge_file = (MenuLayoutNodeMergeFile *) node; - - return merge_file->type; -} - -void -menu_layout_node_merge_file_set_type (MenuLayoutNode *node, - MenuMergeFileType type) -{ - MenuLayoutNodeMergeFile *merge_file; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_MERGE_FILE); - - merge_file = (MenuLayoutNodeMergeFile *) node; - - merge_file->type = type; -} - -MenuLayoutMergeType -menu_layout_node_merge_get_type (MenuLayoutNode *node) -{ - MenuLayoutNodeMerge *merge; - - g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MERGE, 0); - - merge = (MenuLayoutNodeMerge *) node; - - return merge->merge_type; -} - -static void -menu_layout_node_merge_set_type (MenuLayoutNode *node, - const char *merge_type) -{ - MenuLayoutNodeMerge *merge; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_MERGE); - - merge = (MenuLayoutNodeMerge *) node; - - merge->merge_type = MENU_LAYOUT_MERGE_NONE; - - if (strcmp (merge_type, "menus") == 0) - { - merge->merge_type = MENU_LAYOUT_MERGE_MENUS; - } - else if (strcmp (merge_type, "files") == 0) - { - merge->merge_type = MENU_LAYOUT_MERGE_FILES; - } - else if (strcmp (merge_type, "all") == 0) - { - merge->merge_type = MENU_LAYOUT_MERGE_ALL; - } -} - -void -menu_layout_node_default_layout_get_values (MenuLayoutNode *node, - MenuLayoutValues *values) -{ - MenuLayoutNodeDefaultLayout *default_layout; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_DEFAULT_LAYOUT); - g_return_if_fail (values != NULL); - - default_layout = (MenuLayoutNodeDefaultLayout *) node; - - *values = default_layout->layout_values; -} - -void -menu_layout_node_menuname_get_values (MenuLayoutNode *node, - MenuLayoutValues *values) -{ - MenuLayoutNodeMenuname *menuname; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_MENUNAME); - g_return_if_fail (values != NULL); - - menuname = (MenuLayoutNodeMenuname *) node; - - *values = menuname->layout_values; -} - -static void -menu_layout_values_set (MenuLayoutValues *values, - const char *show_empty, - const char *inline_menus, - const char *inline_limit, - const char *inline_header, - const char *inline_alias) -{ - values->mask = MENU_LAYOUT_VALUES_NONE; - values->show_empty = FALSE; - values->inline_menus = FALSE; - values->inline_limit = 4; - values->inline_header = FALSE; - values->inline_alias = FALSE; - - if (show_empty != NULL) - { - values->show_empty = strcmp (show_empty, "true") == 0; - values->mask |= MENU_LAYOUT_VALUES_SHOW_EMPTY; - } - - if (inline_menus != NULL) - { - values->inline_menus = strcmp (inline_menus, "true") == 0; - values->mask |= MENU_LAYOUT_VALUES_INLINE_MENUS; - } - - if (inline_limit != NULL) - { - char *end; - int limit; - - limit = strtol (inline_limit, &end, 10); - if (*end == '\0') - { - values->inline_limit = limit; - values->mask |= MENU_LAYOUT_VALUES_INLINE_LIMIT; - } - } - - if (inline_header != NULL) - { - values->inline_header = strcmp (inline_header, "true") == 0; - values->mask |= MENU_LAYOUT_VALUES_INLINE_HEADER; - } - - if (inline_alias != NULL) - { - values->inline_alias = strcmp (inline_alias, "true") == 0; - values->mask |= MENU_LAYOUT_VALUES_INLINE_ALIAS; - } -} - -static void -menu_layout_node_default_layout_set_values (MenuLayoutNode *node, - const char *show_empty, - const char *inline_menus, - const char *inline_limit, - const char *inline_header, - const char *inline_alias) -{ - MenuLayoutNodeDefaultLayout *default_layout; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_DEFAULT_LAYOUT); - - default_layout = (MenuLayoutNodeDefaultLayout *) node; - - menu_layout_values_set (&default_layout->layout_values, - show_empty, - inline_menus, - inline_limit, - inline_header, - inline_alias); -} - -static void -menu_layout_node_menuname_set_values (MenuLayoutNode *node, - const char *show_empty, - const char *inline_menus, - const char *inline_limit, - const char *inline_header, - const char *inline_alias) -{ - MenuLayoutNodeMenuname *menuname; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_MENUNAME); - - menuname = (MenuLayoutNodeMenuname *) node; - - menu_layout_values_set (&menuname->layout_values, - show_empty, - inline_menus, - inline_limit, - inline_header, - inline_alias); -} - -void -menu_layout_node_root_add_entries_monitor (MenuLayoutNode *node, - MenuLayoutNodeEntriesChangedFunc callback, - gpointer user_data) -{ - MenuLayoutNodeEntriesMonitor *monitor; - MenuLayoutNodeRoot *nr; - GSList *tmp; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_ROOT); - - nr = (MenuLayoutNodeRoot *) node; - - tmp = nr->monitors; - while (tmp != NULL) - { - monitor = tmp->data; - - if (monitor->callback == callback && - monitor->user_data == user_data) - break; - - tmp = tmp->next; - } - - if (tmp == NULL) - { - monitor = g_new0 (MenuLayoutNodeEntriesMonitor, 1); - monitor->callback = callback; - monitor->user_data = user_data; - - nr->monitors = g_slist_append (nr->monitors, monitor); - } -} - -void -menu_layout_node_root_remove_entries_monitor (MenuLayoutNode *node, - MenuLayoutNodeEntriesChangedFunc callback, - gpointer user_data) -{ - MenuLayoutNodeRoot *nr; - GSList *tmp; - - g_return_if_fail (node->type == MENU_LAYOUT_NODE_ROOT); - - nr = (MenuLayoutNodeRoot *) node; - - tmp = nr->monitors; - while (tmp != NULL) - { - MenuLayoutNodeEntriesMonitor *monitor = tmp->data; - GSList *next = tmp->next; - - if (monitor->callback == callback && - monitor->user_data == user_data) - { - nr->monitors = g_slist_delete_link (nr->monitors, tmp); - g_free (monitor); - } - - tmp = next; - } -} - - -/* - * Menu file parsing - */ - -typedef struct -{ - MenuLayoutNode *root; - MenuLayoutNode *stack_top; -} MenuParser; - -static void set_error (GError **err, - GMarkupParseContext *context, - int error_domain, - int error_code, - const char *format, - ...) G_GNUC_PRINTF (5, 6); - -static void add_context_to_error (GError **err, - GMarkupParseContext *context); - -static void start_element_handler (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - gpointer user_data, - GError **error); -static void end_element_handler (GMarkupParseContext *context, - const char *element_name, - gpointer user_data, - GError **error); -static void text_handler (GMarkupParseContext *context, - const char *text, - gsize text_len, - gpointer user_data, - GError **error); -static void passthrough_handler (GMarkupParseContext *context, - const char *passthrough_text, - gsize text_len, - gpointer user_data, - GError **error); - - -static GMarkupParser menu_funcs = { - start_element_handler, - end_element_handler, - text_handler, - passthrough_handler, - NULL -}; - -static void -set_error (GError **err, - GMarkupParseContext *context, - int error_domain, - int error_code, - const char *format, - ...) -{ - int line, ch; - va_list args; - char *str; - - g_markup_parse_context_get_position (context, &line, &ch); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - - g_set_error (err, error_domain, error_code, - "Line %d character %d: %s", - line, ch, str); - - g_free (str); -} - -static void -add_context_to_error (GError **err, - GMarkupParseContext *context) -{ - int line, ch; - char *str; - - if (err == NULL || *err == NULL) - return; - - g_markup_parse_context_get_position (context, &line, &ch); - - str = g_strdup_printf ("Line %d character %d: %s", - line, ch, (*err)->message); - g_free ((*err)->message); - (*err)->message = str; -} - -#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0) - -typedef struct -{ - const char *name; - const char **retloc; -} LocateAttr; - -static gboolean -locate_attributes (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error, - const char *first_attribute_name, - const char **first_attribute_retloc, - ...) -{ -#define MAX_ATTRS 24 - LocateAttr attrs[MAX_ATTRS]; - int n_attrs; - va_list args; - const char *name; - const char **retloc; - gboolean retval; - int i; - - g_return_val_if_fail (first_attribute_name != NULL, FALSE); - g_return_val_if_fail (first_attribute_retloc != NULL, FALSE); - - retval = TRUE; - - n_attrs = 1; - attrs[0].name = first_attribute_name; - attrs[0].retloc = first_attribute_retloc; - *first_attribute_retloc = NULL; - - va_start (args, first_attribute_retloc); - - name = va_arg (args, const char *); - retloc = va_arg (args, const char **); - - while (name != NULL) - { - g_return_val_if_fail (retloc != NULL, FALSE); - - g_assert (n_attrs < MAX_ATTRS); - - attrs[n_attrs].name = name; - attrs[n_attrs].retloc = retloc; - n_attrs += 1; - *retloc = NULL; - - name = va_arg (args, const char *); - retloc = va_arg (args, const char **); - } - - va_end (args); - - i = 0; - while (attribute_names[i]) - { - int j; - - j = 0; - while (j < n_attrs) - { - if (strcmp (attrs[j].name, attribute_names[i]) == 0) - { - retloc = attrs[j].retloc; - - if (*retloc != NULL) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "Attribute \"%s\" repeated twice on the same <%s> element", - attrs[j].name, element_name); - retval = FALSE; - goto out; - } - - *retloc = attribute_values[i]; - break; - } - - ++j; - } - - if (j == n_attrs) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "Attribute \"%s\" is invalid on <%s> element in this context", - attribute_names[i], element_name); - retval = FALSE; - goto out; - } - - ++i; - } - - out: - return retval; - -#undef MAX_ATTRS -} - -static gboolean -check_no_attributes (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error) -{ - if (attribute_names[0] != NULL) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "Attribute \"%s\" is invalid on <%s> element in this context", - attribute_names[0], element_name); - return FALSE; - } - - return TRUE; -} - -static int -has_child_of_type (MenuLayoutNode *node, - MenuLayoutNodeType type) -{ - MenuLayoutNode *iter; - - iter = node->children; - while (iter) - { - if (iter->type == type) - return TRUE; - - iter = node_next (iter); - } - - return FALSE; -} - -static void -push_node (MenuParser *parser, - MenuLayoutNodeType type) -{ - MenuLayoutNode *node; - - node = menu_layout_node_new (type); - menu_layout_node_append_child (parser->stack_top, node); - menu_layout_node_unref (node); - - parser->stack_top = node; -} - -static void -start_menu_element (MenuParser *parser, - GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error) -{ - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - if (!(parser->stack_top->type == MENU_LAYOUT_NODE_ROOT || - parser->stack_top->type == MENU_LAYOUT_NODE_MENU)) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "<Menu> element can only appear below other <Menu> elements or at toplevel\n"); - } - else - { - push_node (parser, MENU_LAYOUT_NODE_MENU); - } -} - -static void -start_menu_child_element (MenuParser *parser, - GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error) -{ - if (ELEMENT_IS ("LegacyDir")) - { - const char *prefix; - - push_node (parser, MENU_LAYOUT_NODE_LEGACY_DIR); - - if (!locate_attributes (context, element_name, - attribute_names, attribute_values, - error, - "prefix", &prefix, - NULL)) - return; - - menu_layout_node_legacy_dir_set_prefix (parser->stack_top, prefix); - } - else if (ELEMENT_IS ("MergeFile")) - { - const char *type; - - push_node (parser, MENU_LAYOUT_NODE_MERGE_FILE); - - if (!locate_attributes (context, element_name, - attribute_names, attribute_values, - error, - "type", &type, - NULL)) - return; - - if (type != NULL && strcmp (type, "parent") == 0) - { - menu_layout_node_merge_file_set_type (parser->stack_top, - MENU_MERGE_FILE_TYPE_PARENT); - } - } - else if (ELEMENT_IS ("DefaultLayout")) - { - const char *show_empty; - const char *inline_menus; - const char *inline_limit; - const char *inline_header; - const char *inline_alias; - - push_node (parser, MENU_LAYOUT_NODE_DEFAULT_LAYOUT); - - locate_attributes (context, element_name, - attribute_names, attribute_values, - error, - "show_empty", &show_empty, - "inline", &inline_menus, - "inline_limit", &inline_limit, - "inline_header", &inline_header, - "inline_alias", &inline_alias, - NULL); - - menu_layout_node_default_layout_set_values (parser->stack_top, - show_empty, - inline_menus, - inline_limit, - inline_header, - inline_alias); - } - else - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - if (ELEMENT_IS ("AppDir")) - { - push_node (parser, MENU_LAYOUT_NODE_APP_DIR); - } - else if (ELEMENT_IS ("DefaultAppDirs")) - { - push_node (parser, MENU_LAYOUT_NODE_DEFAULT_APP_DIRS); - } - else if (ELEMENT_IS ("DirectoryDir")) - { - push_node (parser, MENU_LAYOUT_NODE_DIRECTORY_DIR); - } - else if (ELEMENT_IS ("DefaultDirectoryDirs")) - { - push_node (parser, MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS); - } - else if (ELEMENT_IS ("DefaultMergeDirs")) - { - push_node (parser, MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS); - } - else if (ELEMENT_IS ("Name")) - { - if (has_child_of_type (parser->stack_top, MENU_LAYOUT_NODE_NAME)) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "Multiple <Name> elements in a <Menu> element is not allowed\n"); - return; - } - - push_node (parser, MENU_LAYOUT_NODE_NAME); - } - else if (ELEMENT_IS ("Directory")) - { - push_node (parser, MENU_LAYOUT_NODE_DIRECTORY); - } - else if (ELEMENT_IS ("OnlyUnallocated")) - { - push_node (parser, MENU_LAYOUT_NODE_ONLY_UNALLOCATED); - } - else if (ELEMENT_IS ("NotOnlyUnallocated")) - { - push_node (parser, MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED); - } - else if (ELEMENT_IS ("Include")) - { - push_node (parser, MENU_LAYOUT_NODE_INCLUDE); - } - else if (ELEMENT_IS ("Exclude")) - { - push_node (parser, MENU_LAYOUT_NODE_EXCLUDE); - } - else if (ELEMENT_IS ("MergeDir")) - { - push_node (parser, MENU_LAYOUT_NODE_MERGE_DIR); - } - else if (ELEMENT_IS ("KDELegacyDirs")) - { - push_node (parser, MENU_LAYOUT_NODE_KDE_LEGACY_DIRS); - } - else if (ELEMENT_IS ("Move")) - { - push_node (parser, MENU_LAYOUT_NODE_MOVE); - } - else if (ELEMENT_IS ("Deleted")) - { - push_node (parser, MENU_LAYOUT_NODE_DELETED); - - } - else if (ELEMENT_IS ("NotDeleted")) - { - push_node (parser, MENU_LAYOUT_NODE_NOT_DELETED); - } - else if (ELEMENT_IS ("Layout")) - { - push_node (parser, MENU_LAYOUT_NODE_LAYOUT); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Element <%s> may not appear below <%s>\n", - element_name, "Menu"); - } - } -} - -static void -start_matching_rule_element (MenuParser *parser, - GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error) -{ - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - - if (ELEMENT_IS ("Filename")) - { - push_node (parser, MENU_LAYOUT_NODE_FILENAME); - } - else if (ELEMENT_IS ("Category")) - { - push_node (parser, MENU_LAYOUT_NODE_CATEGORY); - } - else if (ELEMENT_IS ("All")) - { - push_node (parser, MENU_LAYOUT_NODE_ALL); - } - else if (ELEMENT_IS ("And")) - { - push_node (parser, MENU_LAYOUT_NODE_AND); - } - else if (ELEMENT_IS ("Or")) - { - push_node (parser, MENU_LAYOUT_NODE_OR); - } - else if (ELEMENT_IS ("Not")) - { - push_node (parser, MENU_LAYOUT_NODE_NOT); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Element <%s> may not appear in this context\n", - element_name); - } -} - -static void -start_move_child_element (MenuParser *parser, - GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error) -{ - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - if (ELEMENT_IS ("Old")) - { - push_node (parser, MENU_LAYOUT_NODE_OLD); - } - else if (ELEMENT_IS ("New")) - { - push_node (parser, MENU_LAYOUT_NODE_NEW); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Element <%s> may not appear below <%s>\n", - element_name, "Move"); - } -} - -static void -start_layout_child_element (MenuParser *parser, - GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error) -{ - if (ELEMENT_IS ("Menuname")) - { - const char *show_empty; - const char *inline_menus; - const char *inline_limit; - const char *inline_header; - const char *inline_alias; - - push_node (parser, MENU_LAYOUT_NODE_MENUNAME); - - locate_attributes (context, element_name, - attribute_names, attribute_values, - error, - "show_empty", &show_empty, - "inline", &inline_menus, - "inline_limit", &inline_limit, - "inline_header", &inline_header, - "inline_alias", &inline_alias, - NULL); - - menu_layout_node_menuname_set_values (parser->stack_top, - show_empty, - inline_menus, - inline_limit, - inline_header, - inline_alias); - } - else if (ELEMENT_IS ("Merge")) - { - const char *type; - - push_node (parser, MENU_LAYOUT_NODE_MERGE); - - locate_attributes (context, element_name, - attribute_names, attribute_values, - error, - "type", &type, - NULL); - - menu_layout_node_merge_set_type (parser->stack_top, type); - } - else - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - if (ELEMENT_IS ("Filename")) - { - push_node (parser, MENU_LAYOUT_NODE_FILENAME); - } - else if (ELEMENT_IS ("Separator")) - { - push_node (parser, MENU_LAYOUT_NODE_SEPARATOR); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Element <%s> may not appear below <%s>\n", - element_name, "Move"); - } - } -} - -static void -start_element_handler (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - gpointer user_data, - GError **error) -{ - MenuParser *parser = user_data; - - if (ELEMENT_IS ("Menu")) - { - if (parser->stack_top == parser->root && - has_child_of_type (parser->root, MENU_LAYOUT_NODE_MENU)) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "Multiple root elements in menu file, only one toplevel <Menu> is allowed\n"); - return; - } - - start_menu_element (parser, context, element_name, - attribute_names, attribute_values, - error); - } - else if (parser->stack_top == parser->root) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "Root element in a menu file must be <Menu>, not <%s>\n", - element_name); - } - else if (parser->stack_top->type == MENU_LAYOUT_NODE_MENU) - { - start_menu_child_element (parser, context, element_name, - attribute_names, attribute_values, - error); - } - else if (parser->stack_top->type == MENU_LAYOUT_NODE_INCLUDE || - parser->stack_top->type == MENU_LAYOUT_NODE_EXCLUDE || - parser->stack_top->type == MENU_LAYOUT_NODE_AND || - parser->stack_top->type == MENU_LAYOUT_NODE_OR || - parser->stack_top->type == MENU_LAYOUT_NODE_NOT) - { - start_matching_rule_element (parser, context, element_name, - attribute_names, attribute_values, - error); - } - else if (parser->stack_top->type == MENU_LAYOUT_NODE_MOVE) - { - start_move_child_element (parser, context, element_name, - attribute_names, attribute_values, - error); - } - else if (parser->stack_top->type == MENU_LAYOUT_NODE_LAYOUT || - parser->stack_top->type == MENU_LAYOUT_NODE_DEFAULT_LAYOUT) - { - start_layout_child_element (parser, context, element_name, - attribute_names, attribute_values, - error); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Element <%s> may not appear in this context\n", - element_name); - } - - add_context_to_error (error, context); -} - -/* we want to make sure that the <Layout> or <DefaultLayout> is either empty, - * or contain one <Merge> of type "all", or contain one <Merge> of type "menus" - * and one <Merge> of type "files". If this is not the case, we try to clean up - * things: - * + if there is at least one <Merge> of type "all", then we only keep the - * last <Merge> of type "all" and remove all others <Merge> - * + if there is no <Merge> with type "all", we keep only the last <Merge> of - * type "menus" and the last <Merge> of type "files". If there's no <Merge> - * of type "menus" we append one, and then if there's no <Merge> of type - * "files", we append one. (So menus are before files) - */ -static gboolean -fixup_layout_node (GMarkupParseContext *context, - MenuParser *parser, - MenuLayoutNode *node, - GError **error) -{ - MenuLayoutNode *child; - MenuLayoutNode *last_all; - MenuLayoutNode *last_menus; - MenuLayoutNode *last_files; - int n_all; - int n_menus; - int n_files; - - if (!node->children) - { - return TRUE; - } - - last_all = NULL; - last_menus = NULL; - last_files = NULL; - n_all = 0; - n_menus = 0; - n_files = 0; - - child = node->children; - while (child != NULL) - { - switch (child->type) - { - case MENU_LAYOUT_NODE_MERGE: - switch (menu_layout_node_merge_get_type (child)) - { - case MENU_LAYOUT_MERGE_NONE: - break; - - case MENU_LAYOUT_MERGE_MENUS: - last_menus = child; - n_menus++; - break; - - case MENU_LAYOUT_MERGE_FILES: - last_files = child; - n_files++; - break; - - case MENU_LAYOUT_MERGE_ALL: - last_all = child; - n_all++; - break; - - default: - g_assert_not_reached (); - break; - } - break; - - default: - break; - } - - child = node_next (child); - } - - if ((n_all == 1 && n_menus == 0 && n_files == 0) || - (n_all == 0 && n_menus == 1 && n_files == 1)) - { - return TRUE; - } - else if (n_all > 1 || n_menus > 1 || n_files > 1 || - (n_all == 1 && (n_menus != 0 || n_files != 0))) - { - child = node->children; - while (child != NULL) - { - MenuLayoutNode *next; - - next = node_next (child); - - switch (child->type) - { - case MENU_LAYOUT_NODE_MERGE: - switch (menu_layout_node_merge_get_type (child)) - { - case MENU_LAYOUT_MERGE_NONE: - break; - - case MENU_LAYOUT_MERGE_MENUS: - if (n_all || last_menus != child) - { - menu_verbose ("removing duplicated merge menus element\n"); - menu_layout_node_unlink (child); - } - break; - - case MENU_LAYOUT_MERGE_FILES: - if (n_all || last_files != child) - { - menu_verbose ("removing duplicated merge files element\n"); - menu_layout_node_unlink (child); - } - break; - - case MENU_LAYOUT_MERGE_ALL: - if (last_all != child) - { - menu_verbose ("removing duplicated merge all element\n"); - menu_layout_node_unlink (child); - } - break; - - default: - g_assert_not_reached (); - break; - } - break; - - default: - break; - } - - child = next; - } - } - - if (n_all == 0 && n_menus == 0) - { - last_menus = menu_layout_node_new (MENU_LAYOUT_NODE_MERGE); - menu_layout_node_merge_set_type (last_menus, "menus"); - menu_verbose ("appending missing merge menus element\n"); - menu_layout_node_append_child (node, last_menus); - } - - if (n_all == 0 && n_files == 0) - { - last_files = menu_layout_node_new (MENU_LAYOUT_NODE_MERGE); - menu_layout_node_merge_set_type (last_files, "files"); - menu_verbose ("appending missing merge files element\n"); - menu_layout_node_append_child (node, last_files); - } - - return TRUE; -} - -/* we want to a) check that we have old-new pairs and b) canonicalize - * such that each <Move> has exactly one old-new pair - */ -static gboolean -fixup_move_node (GMarkupParseContext *context, - MenuParser *parser, - MenuLayoutNode *node, - GError **error) -{ - MenuLayoutNode *child; - int n_old; - int n_new; - - n_old = 0; - n_new = 0; - - child = node->children; - while (child != NULL) - { - switch (child->type) - { - case MENU_LAYOUT_NODE_OLD: - if (n_new != n_old) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "<Old>/<New> elements not paired properly\n"); - return FALSE; - } - - n_old += 1; - - break; - - case MENU_LAYOUT_NODE_NEW: - n_new += 1; - - if (n_new != n_old) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "<Old>/<New> elements not paired properly\n"); - return FALSE; - } - - break; - - default: - g_assert_not_reached (); - break; - } - - child = node_next (child); - } - - if (n_new == 0 || n_old == 0) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "<Old>/<New> elements missing under <Move>\n"); - return FALSE; - } - - g_assert (n_new == n_old); - g_assert ((n_new + n_old) % 2 == 0); - - if (n_new > 1) - { - MenuLayoutNode *prev; - MenuLayoutNode *append_after; - - /* Need to split the <Move> into multiple <Move> */ - - n_old = 0; - n_new = 0; - prev = NULL; - append_after = node; - - child = node->children; - while (child != NULL) - { - MenuLayoutNode *next; - - next = node_next (child); - - switch (child->type) - { - case MENU_LAYOUT_NODE_OLD: - n_old += 1; - break; - - case MENU_LAYOUT_NODE_NEW: - n_new += 1; - break; - - default: - g_assert_not_reached (); - break; - } - - if (n_old == n_new && - n_old > 1) - { - /* Move the just-completed pair */ - MenuLayoutNode *new_move; - - g_assert (prev != NULL); - - new_move = menu_layout_node_new (MENU_LAYOUT_NODE_MOVE); - menu_verbose ("inserting new_move after append_after\n"); - menu_layout_node_insert_after (append_after, new_move); - append_after = new_move; - - menu_layout_node_steal (prev); - menu_layout_node_steal (child); - - menu_verbose ("appending prev to new_move\n"); - menu_layout_node_append_child (new_move, prev); - menu_verbose ("appending child to new_move\n"); - menu_layout_node_append_child (new_move, child); - - menu_verbose ("Created new move element old = %s new = %s\n", - menu_layout_node_move_get_old (new_move), - menu_layout_node_move_get_new (new_move)); - - menu_layout_node_unref (new_move); - menu_layout_node_unref (prev); - menu_layout_node_unref (child); - - prev = NULL; - } - else - { - prev = child; - } - - prev = child; - child = next; - } - } - - return TRUE; -} - -static void -end_element_handler (GMarkupParseContext *context, - const char *element_name, - gpointer user_data, - GError **error) -{ - MenuParser *parser = user_data; - - g_assert (parser->stack_top != NULL); - - switch (parser->stack_top->type) - { - case MENU_LAYOUT_NODE_APP_DIR: - case MENU_LAYOUT_NODE_DIRECTORY_DIR: - case MENU_LAYOUT_NODE_NAME: - case MENU_LAYOUT_NODE_DIRECTORY: - case MENU_LAYOUT_NODE_FILENAME: - case MENU_LAYOUT_NODE_CATEGORY: - case MENU_LAYOUT_NODE_MERGE_DIR: - case MENU_LAYOUT_NODE_LEGACY_DIR: - case MENU_LAYOUT_NODE_OLD: - case MENU_LAYOUT_NODE_NEW: - case MENU_LAYOUT_NODE_MENUNAME: - if (menu_layout_node_get_content (parser->stack_top) == NULL) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Element <%s> is required to contain text and was empty\n", - element_name); - goto out; - } - break; - - case MENU_LAYOUT_NODE_MENU: - if (!has_child_of_type (parser->stack_top, MENU_LAYOUT_NODE_NAME)) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "<Menu> elements are required to contain a <Name> element\n"); - goto out; - } - break; - - case MENU_LAYOUT_NODE_ROOT: - case MENU_LAYOUT_NODE_PASSTHROUGH: - case MENU_LAYOUT_NODE_DEFAULT_APP_DIRS: - case MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS: - case MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS: - case MENU_LAYOUT_NODE_ONLY_UNALLOCATED: - case MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED: - case MENU_LAYOUT_NODE_INCLUDE: - case MENU_LAYOUT_NODE_EXCLUDE: - case MENU_LAYOUT_NODE_ALL: - case MENU_LAYOUT_NODE_AND: - case MENU_LAYOUT_NODE_OR: - case MENU_LAYOUT_NODE_NOT: - case MENU_LAYOUT_NODE_KDE_LEGACY_DIRS: - case MENU_LAYOUT_NODE_DELETED: - case MENU_LAYOUT_NODE_NOT_DELETED: - case MENU_LAYOUT_NODE_SEPARATOR: - case MENU_LAYOUT_NODE_MERGE: - case MENU_LAYOUT_NODE_MERGE_FILE: - break; - - case MENU_LAYOUT_NODE_LAYOUT: - case MENU_LAYOUT_NODE_DEFAULT_LAYOUT: - if (!fixup_layout_node (context, parser, parser->stack_top, error)) - goto out; - break; - - case MENU_LAYOUT_NODE_MOVE: - if (!fixup_move_node (context, parser, parser->stack_top, error)) - goto out; - break; - } - - out: - parser->stack_top = parser->stack_top->parent; -} - -static gboolean -all_whitespace (const char *text, - int text_len) -{ - const char *p; - const char *end; - - p = text; - end = text + text_len; - - while (p != end) - { - if (!g_ascii_isspace (*p)) - return FALSE; - - p = g_utf8_next_char (p); - } - - return TRUE; -} - -static void -text_handler (GMarkupParseContext *context, - const char *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - MenuParser *parser = user_data; - - switch (parser->stack_top->type) - { - case MENU_LAYOUT_NODE_APP_DIR: - case MENU_LAYOUT_NODE_DIRECTORY_DIR: - case MENU_LAYOUT_NODE_NAME: - case MENU_LAYOUT_NODE_DIRECTORY: - case MENU_LAYOUT_NODE_FILENAME: - case MENU_LAYOUT_NODE_CATEGORY: - case MENU_LAYOUT_NODE_MERGE_FILE: - case MENU_LAYOUT_NODE_MERGE_DIR: - case MENU_LAYOUT_NODE_LEGACY_DIR: - case MENU_LAYOUT_NODE_OLD: - case MENU_LAYOUT_NODE_NEW: - case MENU_LAYOUT_NODE_MENUNAME: - g_assert (menu_layout_node_get_content (parser->stack_top) == NULL); - - menu_layout_node_set_content (parser->stack_top, text); - break; - - case MENU_LAYOUT_NODE_ROOT: - case MENU_LAYOUT_NODE_PASSTHROUGH: - case MENU_LAYOUT_NODE_MENU: - case MENU_LAYOUT_NODE_DEFAULT_APP_DIRS: - case MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS: - case MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS: - case MENU_LAYOUT_NODE_ONLY_UNALLOCATED: - case MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED: - case MENU_LAYOUT_NODE_INCLUDE: - case MENU_LAYOUT_NODE_EXCLUDE: - case MENU_LAYOUT_NODE_ALL: - case MENU_LAYOUT_NODE_AND: - case MENU_LAYOUT_NODE_OR: - case MENU_LAYOUT_NODE_NOT: - case MENU_LAYOUT_NODE_KDE_LEGACY_DIRS: - case MENU_LAYOUT_NODE_MOVE: - case MENU_LAYOUT_NODE_DELETED: - case MENU_LAYOUT_NODE_NOT_DELETED: - case MENU_LAYOUT_NODE_LAYOUT: - case MENU_LAYOUT_NODE_DEFAULT_LAYOUT: - case MENU_LAYOUT_NODE_SEPARATOR: - case MENU_LAYOUT_NODE_MERGE: - if (!all_whitespace (text, text_len)) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "No text is allowed inside element <%s>", - g_markup_parse_context_get_element (context)); - } - break; - } - - add_context_to_error (error, context); -} - -static void -passthrough_handler (GMarkupParseContext *context, - const char *passthrough_text, - gsize text_len, - gpointer user_data, - GError **error) -{ - MenuParser *parser = user_data; - MenuLayoutNode *node; - - /* don't push passthrough on the stack, it's not an element */ - - node = menu_layout_node_new (MENU_LAYOUT_NODE_PASSTHROUGH); - menu_layout_node_set_content (node, passthrough_text); - - menu_layout_node_append_child (parser->stack_top, node); - menu_layout_node_unref (node); - - add_context_to_error (error, context); -} - -static void -menu_parser_init (MenuParser *parser) -{ - parser->root = menu_layout_node_new (MENU_LAYOUT_NODE_ROOT); - parser->stack_top = parser->root; -} - -static void -menu_parser_free (MenuParser *parser) -{ - if (parser->root) - menu_layout_node_unref (parser->root); -} - -MenuLayoutNode * -menu_layout_load (const char *filename, - const char *non_prefixed_basename, - GError **err) -{ - GMarkupParseContext *context; - MenuLayoutNodeRoot *root; - MenuLayoutNode *retval; - MenuParser parser; - GError *error; - GString *str; - char *text; - char *s; - gsize length; - - text = NULL; - length = 0; - retval = NULL; - context = NULL; - - menu_verbose ("Loading \"%s\" from disk\n", filename); - - if (!g_file_get_contents (filename, - &text, - &length, - err)) - { - menu_verbose ("Failed to load \"%s\"\n", - filename); - return NULL; - } - - g_assert (text != NULL); - - menu_parser_init (&parser); - - root = (MenuLayoutNodeRoot *) parser.root; - - root->basedir = g_path_get_dirname (filename); - menu_verbose ("Set basedir \"%s\"\n", root->basedir); - - if (non_prefixed_basename) - s = g_strdup (non_prefixed_basename); - else - s = g_path_get_basename (filename); - str = g_string_new (s); - if (g_str_has_suffix (str->str, ".menu")) - g_string_truncate (str, str->len - strlen (".menu")); - - root->name = str->str; - menu_verbose ("Set menu name \"%s\"\n", root->name); - - g_string_free (str, FALSE); - g_free (s); - - context = g_markup_parse_context_new (&menu_funcs, 0, &parser, NULL); - - error = NULL; - if (!g_markup_parse_context_parse (context, - text, - length, - &error)) - goto out; - - error = NULL; - g_markup_parse_context_end_parse (context, &error); - - out: - if (context) - g_markup_parse_context_free (context); - g_free (text); - - if (error) - { - menu_verbose ("Error \"%s\" loading \"%s\"\n", - error->message, filename); - g_propagate_error (err, error); - } - else if (has_child_of_type (parser.root, MENU_LAYOUT_NODE_MENU)) - { - menu_verbose ("File loaded OK\n"); - retval = parser.root; - parser.root = NULL; - } - else - { - menu_verbose ("Did not have a root element in file\n"); - g_set_error (err, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - "Menu file %s did not contain a root <Menu> element", - filename); - } - - menu_parser_free (&parser); - - return retval; -} diff --git a/src/menu-layout.h b/src/menu-layout.h deleted file mode 100644 index 5d3e81a0..00000000 --- a/src/menu-layout.h +++ /dev/null @@ -1,161 +0,0 @@ -/* Menu layout in-memory data structure (a custom "DOM tree") */ - -/* - * Copyright (C) 2002 - 2004 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __MENU_LAYOUT_H__ -#define __MENU_LAYOUT_H__ - -#include <glib.h> - -#include "entry-directories.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct MenuLayoutNode MenuLayoutNode; - -typedef enum { - MENU_LAYOUT_NODE_ROOT, - MENU_LAYOUT_NODE_PASSTHROUGH, - MENU_LAYOUT_NODE_MENU, - MENU_LAYOUT_NODE_APP_DIR, - MENU_LAYOUT_NODE_DEFAULT_APP_DIRS, - MENU_LAYOUT_NODE_DIRECTORY_DIR, - MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS, - MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS, - MENU_LAYOUT_NODE_NAME, - MENU_LAYOUT_NODE_DIRECTORY, - MENU_LAYOUT_NODE_ONLY_UNALLOCATED, - MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED, - MENU_LAYOUT_NODE_INCLUDE, - MENU_LAYOUT_NODE_EXCLUDE, - MENU_LAYOUT_NODE_FILENAME, - MENU_LAYOUT_NODE_CATEGORY, - MENU_LAYOUT_NODE_ALL, - MENU_LAYOUT_NODE_AND, - MENU_LAYOUT_NODE_OR, - MENU_LAYOUT_NODE_NOT, - MENU_LAYOUT_NODE_MERGE_FILE, - MENU_LAYOUT_NODE_MERGE_DIR, - MENU_LAYOUT_NODE_LEGACY_DIR, - MENU_LAYOUT_NODE_KDE_LEGACY_DIRS, - MENU_LAYOUT_NODE_MOVE, - MENU_LAYOUT_NODE_OLD, - MENU_LAYOUT_NODE_NEW, - MENU_LAYOUT_NODE_DELETED, - MENU_LAYOUT_NODE_NOT_DELETED, - MENU_LAYOUT_NODE_LAYOUT, - MENU_LAYOUT_NODE_DEFAULT_LAYOUT, - MENU_LAYOUT_NODE_MENUNAME, - MENU_LAYOUT_NODE_SEPARATOR, - MENU_LAYOUT_NODE_MERGE -} MenuLayoutNodeType; - -typedef enum { - MENU_MERGE_FILE_TYPE_PATH = 0, - MENU_MERGE_FILE_TYPE_PARENT -} MenuMergeFileType; - -typedef enum { - MENU_LAYOUT_MERGE_NONE, - MENU_LAYOUT_MERGE_MENUS, - MENU_LAYOUT_MERGE_FILES, - MENU_LAYOUT_MERGE_ALL -} MenuLayoutMergeType; - -typedef enum { - MENU_LAYOUT_VALUES_NONE = 0, - MENU_LAYOUT_VALUES_SHOW_EMPTY = 1 << 0, - MENU_LAYOUT_VALUES_INLINE_MENUS = 1 << 1, - MENU_LAYOUT_VALUES_INLINE_LIMIT = 1 << 2, - MENU_LAYOUT_VALUES_INLINE_HEADER = 1 << 3, - MENU_LAYOUT_VALUES_INLINE_ALIAS = 1 << 4 -} MenuLayoutValuesMask; - -typedef struct { - MenuLayoutValuesMask mask; - - guint show_empty: 1; - guint inline_menus: 1; - guint inline_header: 1; - guint inline_alias: 1; - - guint inline_limit; -} MenuLayoutValues; - - -MenuLayoutNode *menu_layout_load (const char* filename, const char *non_prefixed_basename, GError** error); - -MenuLayoutNode *menu_layout_node_new (MenuLayoutNodeType type); -MenuLayoutNode *menu_layout_node_ref (MenuLayoutNode *node); -void menu_layout_node_unref (MenuLayoutNode *node); - -MenuLayoutNodeType menu_layout_node_get_type (MenuLayoutNode *node); - -MenuLayoutNode *menu_layout_node_get_root (MenuLayoutNode *node); -MenuLayoutNode *menu_layout_node_get_parent (MenuLayoutNode *node); -MenuLayoutNode *menu_layout_node_get_children (MenuLayoutNode *node); -MenuLayoutNode *menu_layout_node_get_next (MenuLayoutNode *node); - -void menu_layout_node_insert_before (MenuLayoutNode *node, MenuLayoutNode *new_sibling); -void menu_layout_node_insert_after (MenuLayoutNode *node, MenuLayoutNode *new_sibling); -void menu_layout_node_prepend_child (MenuLayoutNode *parent, MenuLayoutNode *new_child); -void menu_layout_node_append_child (MenuLayoutNode *parent, MenuLayoutNode *new_child); - -void menu_layout_node_unlink (MenuLayoutNode *node); -void menu_layout_node_steal (MenuLayoutNode *node); - -const char *menu_layout_node_get_content (MenuLayoutNode *node); -void menu_layout_node_set_content (MenuLayoutNode *node, const char *content); - -char *menu_layout_node_get_content_as_path (MenuLayoutNode *node); - -const char *menu_layout_node_root_get_name (MenuLayoutNode *node); -const char *menu_layout_node_root_get_basedir (MenuLayoutNode *node); - -const char *menu_layout_node_menu_get_name (MenuLayoutNode *node); -EntryDirectoryList *menu_layout_node_menu_get_app_dirs (MenuLayoutNode *node); -EntryDirectoryList *menu_layout_node_menu_get_directory_dirs (MenuLayoutNode *node); - -const char *menu_layout_node_move_get_old (MenuLayoutNode *node); -const char *menu_layout_node_move_get_new (MenuLayoutNode *node); - -const char *menu_layout_node_legacy_dir_get_prefix (MenuLayoutNode *node); -void menu_layout_node_legacy_dir_set_prefix (MenuLayoutNode *node, const char *prefix); - -MenuMergeFileType menu_layout_node_merge_file_get_type (MenuLayoutNode *node); -void menu_layout_node_merge_file_set_type (MenuLayoutNode *node, MenuMergeFileType type); - -MenuLayoutMergeType menu_layout_node_merge_get_type (MenuLayoutNode *node); - -void menu_layout_node_default_layout_get_values (MenuLayoutNode *node, MenuLayoutValues *values); -void menu_layout_node_menuname_get_values (MenuLayoutNode *node, MenuLayoutValues *values); - -typedef void (*MenuLayoutNodeEntriesChangedFunc) (MenuLayoutNode* node, gpointer user_data); - -void menu_layout_node_root_add_entries_monitor (MenuLayoutNode* node, MenuLayoutNodeEntriesChangedFunc callback, gpointer user_data); -void menu_layout_node_root_remove_entries_monitor (MenuLayoutNode* node, MenuLayoutNodeEntriesChangedFunc callback, gpointer user_data); - -#ifdef __cplusplus -} -#endif - -#endif /* __MENU_LAYOUT_H__ */ diff --git a/src/menu-monitor.c b/src/menu-monitor.c deleted file mode 100644 index bf6130dd..00000000 --- a/src/menu-monitor.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (C) 2005 Red Hat, Inc. - * Copyright (C) 2006 Mark McLoughlin - * Copyright (C) 2007 Sebastian Dröge - * Copyright (C) 2008 Vincent Untz - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <config.h> - -#include "menu-monitor.h" - -#include <gio/gio.h> - -#include "menu-util.h" - -struct MenuMonitor { - char* path; - guint refcount; - - GSList* notifies; - - GFileMonitor* monitor; - - guint is_directory: 1; -}; - -typedef struct { - MenuMonitor* monitor; - MenuMonitorEvent event; - char* path; -} MenuMonitorEventInfo; - -typedef struct { - MenuMonitorNotifyFunc notify_func; - gpointer user_data; - guint refcount; -} MenuMonitorNotify; - -static MenuMonitorNotify* xfce_menu_monitor_notify_ref(MenuMonitorNotify* notify); -static void xfce_menu_monitor_notify_unref(MenuMonitorNotify* notify); - -static GHashTable* monitors_registry = NULL; -static guint events_idle_handler = 0; -static GSList* pending_events = NULL; - -static void invoke_notifies(MenuMonitor* monitor, MenuMonitorEvent event, const char* path) -{ - GSList *copy; - GSList *tmp; - - copy = g_slist_copy (monitor->notifies); - g_slist_foreach (copy, - (GFunc) xfce_menu_monitor_notify_ref, - NULL); - - tmp = copy; - while (tmp != NULL) - { - MenuMonitorNotify *notify = tmp->data; - GSList *next = tmp->next; - - if (notify->notify_func) - { - notify->notify_func (monitor, event, path, notify->user_data); - } - - xfce_menu_monitor_notify_unref(notify); - - tmp = next; - } - - g_slist_free (copy); -} - -static gboolean emit_events_in_idle(void) -{ - GSList *events_to_emit; - GSList *tmp; - - events_to_emit = pending_events; - - pending_events = NULL; - events_idle_handler = 0; - - tmp = events_to_emit; - while (tmp != NULL) - { - MenuMonitorEventInfo *event_info = tmp->data; - - xfce_menu_monitor_ref(event_info->monitor); - - tmp = tmp->next; - } - - tmp = events_to_emit; - while (tmp != NULL) - { - MenuMonitorEventInfo *event_info = tmp->data; - - invoke_notifies (event_info->monitor, - event_info->event, - event_info->path); - - menu_monitor_unref (event_info->monitor); - event_info->monitor = NULL; - - g_free (event_info->path); - event_info->path = NULL; - - event_info->event = MENU_MONITOR_EVENT_INVALID; - - g_free (event_info); - - tmp = tmp->next; - } - - g_slist_free (events_to_emit); - - return FALSE; -} - -static void menu_monitor_queue_event(MenuMonitorEventInfo* event_info) -{ - pending_events = g_slist_append (pending_events, event_info); - - if (events_idle_handler == 0) - { - events_idle_handler = g_idle_add ((GSourceFunc) emit_events_in_idle, NULL); - } -} - -static inline char* get_registry_key(const char* path, gboolean is_directory) -{ - return g_strdup_printf ("%s:%s", - path, - is_directory ? "<dir>" : "<file>"); -} - -static gboolean monitor_callback (GFileMonitor* monitor, GFile* child, GFile* other_file, GFileMonitorEvent eflags, gpointer user_data) -{ - MenuMonitorEventInfo *event_info; - MenuMonitorEvent event; - MenuMonitor *menu_monitor = (MenuMonitor *) user_data; - - event = MENU_MONITOR_EVENT_INVALID; - switch (eflags) - { - case G_FILE_MONITOR_EVENT_CHANGED: - event = MENU_MONITOR_EVENT_CHANGED; - break; - case G_FILE_MONITOR_EVENT_CREATED: - event = MENU_MONITOR_EVENT_CREATED; - break; - case G_FILE_MONITOR_EVENT_DELETED: - event = MENU_MONITOR_EVENT_DELETED; - break; - default: - return TRUE; - } - - event_info = g_new0 (MenuMonitorEventInfo, 1); - - event_info->path = g_file_get_path (child); - event_info->event = event; - event_info->monitor = menu_monitor; - - menu_monitor_queue_event (event_info); - - return TRUE; -} - -static MenuMonitor* register_monitor(const char* path, gboolean is_directory) -{ - MenuMonitor *retval; - GFile *file; - - retval = g_new0 (MenuMonitor, 1); - - retval->path = g_strdup (path); - retval->refcount = 1; - retval->is_directory = is_directory != FALSE; - - file = g_file_new_for_path (retval->path); - - if (file == NULL) - { - menu_verbose ("Not adding monitor on '%s', failed to create GFile\n", - retval->path); - return retval; - } - - if (retval->is_directory) - retval->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, - NULL, NULL); - else - retval->monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, - NULL, NULL); - - g_object_unref (G_OBJECT (file)); - - if (retval->monitor == NULL) - { - menu_verbose ("Not adding monitor on '%s', failed to create monitor\n", - retval->path); - return retval; - } - - g_signal_connect (retval->monitor, "changed", - G_CALLBACK (monitor_callback), retval); - - return retval; -} - -static MenuMonitor* lookup_monitor(const char* path, gboolean is_directory) -{ - MenuMonitor *retval; - char *registry_key; - - retval = NULL; - - registry_key = get_registry_key (path, is_directory); - - if (monitors_registry == NULL) - { - monitors_registry = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); - } - else - { - retval = g_hash_table_lookup (monitors_registry, registry_key); - } - - if (retval == NULL) - { - retval = register_monitor (path, is_directory); - g_hash_table_insert (monitors_registry, registry_key, retval); - - return retval; - } - else - { - g_free (registry_key); - - return xfce_menu_monitor_ref(retval); - } -} - -MenuMonitor* xfce_menu_monitor_file_get(const char* path) -{ - g_return_val_if_fail(path != NULL, NULL); - - return lookup_monitor(path, FALSE); -} - -MenuMonitor* menu_get_directory_monitor(const char* path) -{ - g_return_val_if_fail (path != NULL, NULL); - - return lookup_monitor (path, TRUE); -} - -MenuMonitor* xfce_menu_monitor_ref(MenuMonitor* monitor) -{ - g_return_val_if_fail(monitor != NULL, NULL); - g_return_val_if_fail(monitor->refcount > 0, NULL); - - monitor->refcount++; - - return monitor; -} - -static void menu_monitor_clear_pending_events(MenuMonitor* monitor) -{ - GSList *tmp; - - tmp = pending_events; - while (tmp != NULL) - { - MenuMonitorEventInfo *event_info = tmp->data; - GSList *next = tmp->next; - - if (event_info->monitor == monitor) - { - pending_events = g_slist_delete_link (pending_events, tmp); - - g_free (event_info->path); - event_info->path = NULL; - - event_info->monitor = NULL; - event_info->event = MENU_MONITOR_EVENT_INVALID; - - g_free (event_info); - } - - tmp = next; - } -} - -void menu_monitor_unref(MenuMonitor* monitor) -{ - char *registry_key; - - g_return_if_fail (monitor != NULL); - g_return_if_fail (monitor->refcount > 0); - - if (--monitor->refcount > 0) - return; - - registry_key = get_registry_key (monitor->path, monitor->is_directory); - g_hash_table_remove (monitors_registry, registry_key); - g_free (registry_key); - - if (g_hash_table_size (monitors_registry) == 0) - { - g_hash_table_destroy (monitors_registry); - monitors_registry = NULL; - } - - if (monitor->monitor) - { - g_file_monitor_cancel (monitor->monitor); - g_object_unref (monitor->monitor); - monitor->monitor = NULL; - } - - g_slist_foreach (monitor->notifies, (GFunc) xfce_menu_monitor_notify_unref, NULL); - g_slist_free (monitor->notifies); - monitor->notifies = NULL; - - menu_monitor_clear_pending_events (monitor); - - g_free (monitor->path); - monitor->path = NULL; - - g_free (monitor); -} - -static MenuMonitorNotify* xfce_menu_monitor_notify_ref(MenuMonitorNotify* notify) -{ - g_return_val_if_fail(notify != NULL, NULL); - g_return_val_if_fail(notify->refcount > 0, NULL); - - notify->refcount++; - - return notify; -} - -static void xfce_menu_monitor_notify_unref(MenuMonitorNotify* notify) -{ - g_return_if_fail(notify != NULL); - g_return_if_fail(notify->refcount > 0); - - if (--notify->refcount > 0) - { - return; - } - - g_free(notify); -} - -void menu_monitor_add_notify(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data) -{ - MenuMonitorNotify* notify; - - g_return_if_fail(monitor != NULL); - g_return_if_fail(notify_func != NULL); - - GSList* tmp = monitor->notifies; - - while (tmp != NULL) - { - notify = tmp->data; - - if (notify->notify_func == notify_func && notify->user_data == user_data) - { - break; - } - - tmp = tmp->next; - } - - if (tmp == NULL) - { - notify = g_new0(MenuMonitorNotify, 1); - notify->notify_func = notify_func; - notify->user_data = user_data; - notify->refcount = 1; - - monitor->notifies = g_slist_append(monitor->notifies, notify); - } -} - -void xfce_menu_monitor_notify_remove(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data) -{ - GSList* tmp = monitor->notifies; - - while (tmp != NULL) - { - MenuMonitorNotify* notify = tmp->data; - GSList* next = tmp->next; - - if (notify->notify_func == notify_func && notify->user_data == user_data) - { - notify->notify_func = NULL; - notify->user_data = NULL; - - xfce_menu_monitor_notify_unref(notify); - - monitor->notifies = g_slist_delete_link(monitor->notifies, tmp); - } - - tmp = next; - } -} diff --git a/src/menu-monitor.h b/src/menu-monitor.h deleted file mode 100644 index ad411bef..00000000 --- a/src/menu-monitor.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2005 Red Hat, Inc. - * Copyright (C) 2011 Perberos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __MENU_MONITOR_H__ -#define __MENU_MONITOR_H__ - -#include <glib.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct MenuMonitor MenuMonitor; - -typedef enum { - MENU_MONITOR_EVENT_INVALID = 0, - MENU_MONITOR_EVENT_CREATED = 1, - MENU_MONITOR_EVENT_DELETED = 2, - MENU_MONITOR_EVENT_CHANGED = 3 -} MenuMonitorEvent; - -typedef void (*MenuMonitorNotifyFunc) (MenuMonitor* monitor, MenuMonitorEvent event, const char* path, gpointer user_data); - - -MenuMonitor* menu_get_file_monitor(const char* path); -MenuMonitor* menu_get_directory_monitor(const char* path); - -MenuMonitor* menu_monitor_ref(MenuMonitor* monitor); -void menu_monitor_unref(MenuMonitor* monitor); - -void menu_monitor_add_notify(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data); -void menu_monitor_remove_notify(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data); - - -/* Izquierda a derecha - */ - -#define xfce_menu_monitor_file_get menu_get_file_monitor -#define xfce_menu_monitor_directory_get menu_get_directory_monitor - -#define xfce_menu_monitor_ref menu_monitor_ref -#define xfce_menu_monitor_unref menu_monitor_unref - -#define xfce_menu_monitor_notify_add menu_monitor_add_notify -#define xfce_menu_monitor_notify_remove menu_monitor_remove_notify -#define xfce_menu_monitor_notify_ref menu_monitor_notify_ref /* private */ -#define xfce_menu_monitor_notify_unref menu_monitor_notify_unref /* private */ - -#ifdef __cplusplus -} -#endif - -#endif /* __MENU_MONITOR_H__ */ diff --git a/src/menu-util.c b/src/menu-util.c deleted file mode 100644 index 9d92dc11..00000000 --- a/src/menu-util.c +++ /dev/null @@ -1,436 +0,0 @@ -/* Random utility functions for menu code */ - -/* - * Copyright (C) 2003 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <config.h> - -#include "menu-util.h" - -#include <stdio.h> -#include <stdarg.h> - - -#ifdef G_ENABLE_DEBUG - -static gboolean verbose = FALSE; -static gboolean initted = FALSE; - -static inline gboolean menu_verbose_enabled(void) -{ - if (!initted) - { - verbose = g_getenv("MENU_VERBOSE") != NULL; - initted = TRUE; - } - - return verbose; -} - -static int utf8_fputs(const char* str, FILE* f) -{ - char* l; - int ret; - - l = g_locale_from_utf8(str, -1, NULL, NULL, NULL); - - if (l == NULL) - { - ret = fputs(str, f); /* just print it anyway, better than nothing */ - } - else - { - ret = fputs(l, f); - } - - g_free(l); - - return ret; -} - -void menu_verbose(const char* format, ...) -{ - va_list args; - char* str; - - if (!menu_verbose_enabled()) - { - return; - } - - va_start(args, format); - str = g_strdup_vprintf(format, args); - va_end(args); - - utf8_fputs(str, stderr); - fflush(stderr); - - g_free(str); -} - -static void append_to_string(MenuLayoutNode* node, gboolean onelevel, int depth, GString* str); - -static void append_spaces(GString* str, int depth) -{ - while (depth > 0) - { - g_string_append_c(str, ' '); - --depth; - } -} - -static void append_children(MenuLayoutNode* node, int depth, GString* str) -{ - MenuLayoutNode* iter; - - iter = menu_layout_node_get_children(node); - - while (iter != NULL) - { - append_to_string(iter, FALSE, depth, str); - - iter = menu_layout_node_get_next(iter); - } -} - -static void append_simple_with_attr(MenuLayoutNode* node, int depth, const char* node_name, const char* attr_name, const char* attr_value, GString* str) -{ - const char* content; - - append_spaces(str, depth); - - if ((content = menu_layout_node_get_content(node))) - { - char* escaped; - - escaped = g_markup_escape_text(content, -1); - - if (attr_name && attr_value) - { - char* attr_escaped; - - attr_escaped = g_markup_escape_text(attr_value, -1); - - g_string_append_printf(str, "<%s %s=\"%s\">%s</%s>\n", node_name, attr_name, attr_escaped, escaped, node_name); - - g_free(attr_escaped); - } - else - { - g_string_append_printf(str, "<%s>%s</%s>\n", node_name, escaped, node_name); - } - - g_free(escaped); - } - else - { - if (attr_name && attr_value) - { - char* attr_escaped; - - attr_escaped = g_markup_escape_text(attr_value, -1); - - g_string_append_printf(str, "<%s %s=\"%s\"/>\n", node_name, attr_name, attr_escaped); - - g_free(attr_escaped); - } - else - { - g_string_append_printf(str, "<%s/>\n", node_name); - } - } -} - -static void append_layout(MenuLayoutNode* node, int depth, const char* node_name, MenuLayoutValues* layout_values, GString* str) -{ - const char* content; - - append_spaces(str, depth); - - if ((content = menu_layout_node_get_content(node))) - { - char* escaped; - - escaped = g_markup_escape_text(content, -1); - - g_string_append_printf(str, - "<%s show_empty=\"%s\" inline=\"%s\" inline_header=\"%s\"" - " inline_alias=\"%s\" inline_limit=\"%d\">%s</%s>\n", - node_name, - layout_values->show_empty ? "true" : "false", - layout_values->inline_menus ? "true" : "false", - layout_values->inline_header ? "true" : "false", - layout_values->inline_alias ? "true" : "false", - layout_values->inline_limit, - escaped, - node_name); - - g_free(escaped); - } - else - { - g_string_append_printf(str, - "<%s show_empty=\"%s\" inline=\"%s\" inline_header=\"%s\"" - " inline_alias=\"%s\" inline_limit=\"%d\"/>\n", - node_name, - layout_values->show_empty ? "true" : "false", - layout_values->inline_menus ? "true" : "false", - layout_values->inline_header ? "true" : "false", - layout_values->inline_alias ? "true" : "false", - layout_values->inline_limit); - } -} - -static void append_merge(MenuLayoutNode* node, int depth, const char* node_name, MenuLayoutMergeType merge_type, GString* str) -{ - const char* merge_type_str; - - merge_type_str = NULL; - - switch (merge_type) - { - case MENU_LAYOUT_MERGE_NONE: - merge_type_str = "none"; - break; - - case MENU_LAYOUT_MERGE_MENUS: - merge_type_str = "menus"; - break; - - case MENU_LAYOUT_MERGE_FILES: - merge_type_str = "files"; - break; - - case MENU_LAYOUT_MERGE_ALL: - merge_type_str = "all"; - break; - - default: - g_assert_not_reached(); - break; - } - - append_simple_with_attr(node, depth, node_name, "type", merge_type_str, str); -} - -static void append_simple(MenuLayoutNode* node, int depth, const char* node_name, GString* str) -{ - append_simple_with_attr(node, depth, node_name, NULL, NULL, str); -} - -static void append_start(MenuLayoutNode* node, int depth, const char* node_name, GString* str) -{ - append_spaces(str, depth); - - g_string_append_printf(str, "<%s>\n", node_name); -} - -static void append_end(MenuLayoutNode* node, int depth, const char* node_name, GString* str) -{ - append_spaces(str, depth); - - g_string_append_printf(str, "</%s>\n", node_name); -} - -static void append_container(MenuLayoutNode* node, gboolean onelevel, int depth, const char* node_name, GString* str) -{ - append_start(node, depth, node_name, str); - - if (!onelevel) - { - append_children(node, depth + 2, str); - append_end(node, depth, node_name, str); - } -} - -static void append_to_string(MenuLayoutNode* node, gboolean onelevel, int depth, GString* str) -{ - MenuLayoutValues layout_values; - - switch (menu_layout_node_get_type(node)) - { - case MENU_LAYOUT_NODE_ROOT: - if (!onelevel) - append_children(node, depth - 1, str); /* -1 to ignore depth of root */ - else - append_start(node, depth - 1, "Root", str); - break; - - case MENU_LAYOUT_NODE_PASSTHROUGH: - g_string_append(str, menu_layout_node_get_content(node)); - g_string_append_c(str, '\n'); - break; - - case MENU_LAYOUT_NODE_MENU: - append_container(node, onelevel, depth, "Menu", str); - break; - - case MENU_LAYOUT_NODE_APP_DIR: - append_simple(node, depth, "AppDir", str); - break; - - case MENU_LAYOUT_NODE_DEFAULT_APP_DIRS: - append_simple(node, depth, "DefaultAppDirs", str); - break; - - case MENU_LAYOUT_NODE_DIRECTORY_DIR: - append_simple(node, depth, "DirectoryDir", str); - break; - - case MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS: - append_simple(node, depth, "DefaultDirectoryDirs", str); - break; - - case MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS: - append_simple(node, depth, "DefaultMergeDirs", str); - break; - - case MENU_LAYOUT_NODE_NAME: - append_simple(node, depth, "Name", str); - break; - - case MENU_LAYOUT_NODE_DIRECTORY: - append_simple(node, depth, "Directory", str); - break; - - case MENU_LAYOUT_NODE_ONLY_UNALLOCATED: - append_simple(node, depth, "OnlyUnallocated", str); - break; - - case MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED: - append_simple(node, depth, "NotOnlyUnallocated", str); - break; - - case MENU_LAYOUT_NODE_INCLUDE: - append_container(node, onelevel, depth, "Include", str); - break; - - case MENU_LAYOUT_NODE_EXCLUDE: - append_container(node, onelevel, depth, "Exclude", str); - break; - - case MENU_LAYOUT_NODE_FILENAME: - append_simple(node, depth, "Filename", str); - break; - - case MENU_LAYOUT_NODE_CATEGORY: - append_simple(node, depth, "Category", str); - break; - - case MENU_LAYOUT_NODE_ALL: - append_simple(node, depth, "All", str); - break; - - case MENU_LAYOUT_NODE_AND: - append_container(node, onelevel, depth, "And", str); - break; - - case MENU_LAYOUT_NODE_OR: - append_container(node, onelevel, depth, "Or", str); - break; - - case MENU_LAYOUT_NODE_NOT: - append_container(node, onelevel, depth, "Not", str); - break; - - case MENU_LAYOUT_NODE_MERGE_FILE: - { - MenuMergeFileType type; - - type = menu_layout_node_merge_file_get_type(node); - - append_simple_with_attr(node, depth, "MergeFile", "type", type == MENU_MERGE_FILE_TYPE_PARENT ? "parent" : "path", str); - break; - } - - case MENU_LAYOUT_NODE_MERGE_DIR: - append_simple(node, depth, "MergeDir", str); - break; - - case MENU_LAYOUT_NODE_LEGACY_DIR: - append_simple_with_attr(node, depth, "LegacyDir", "prefix", menu_layout_node_legacy_dir_get_prefix (node), str); - break; - - case MENU_LAYOUT_NODE_KDE_LEGACY_DIRS: - append_simple(node, depth, "KDELegacyDirs", str); - break; - - case MENU_LAYOUT_NODE_MOVE: - append_container(node, onelevel, depth, "Move", str); - break; - - case MENU_LAYOUT_NODE_OLD: - append_simple(node, depth, "Old", str); - break; - - case MENU_LAYOUT_NODE_NEW: - append_simple(node, depth, "New", str); - break; - - case MENU_LAYOUT_NODE_DELETED: - append_simple(node, depth, "Deleted", str); - break; - - case MENU_LAYOUT_NODE_NOT_DELETED: - append_simple(node, depth, "NotDeleted", str); - break; - - case MENU_LAYOUT_NODE_LAYOUT: - append_container(node, onelevel, depth, "Layout", str); - break; - - case MENU_LAYOUT_NODE_DEFAULT_LAYOUT: - menu_layout_node_default_layout_get_values(node, &layout_values); - append_layout(node, depth, "DefaultLayout", &layout_values, str); - break; - - case MENU_LAYOUT_NODE_MENUNAME: - menu_layout_node_menuname_get_values(node, &layout_values); - append_layout(node, depth, "MenuName", &layout_values, str); - break; - - case MENU_LAYOUT_NODE_SEPARATOR: - append_simple(node, depth, "Name", str); - break; - - case MENU_LAYOUT_NODE_MERGE: - append_merge(node, depth, "Merge", menu_layout_node_merge_get_type(node), str); - break; - - default: - g_assert_not_reached(); - break; - } -} - -void menu_debug_print_layout(MenuLayoutNode* node, gboolean onelevel) -{ - if (menu_verbose_enabled()) - { - GString* str = g_string_new(NULL); - append_to_string(node, onelevel, 0, str); - - utf8_fputs(str->str, stderr); - fflush(stderr); - - g_string_free(str, TRUE); - } -} - -#endif /* G_ENABLE_DEBUG */ diff --git a/src/menu-util.h b/src/menu-util.h deleted file mode 100644 index c8721e2f..00000000 --- a/src/menu-util.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Random utility functions for menu code */ - -/* - * Copyright (C) 2003 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __MENU_UTIL_H__ -#define __MENU_UTIL_H__ - -#include <glib.h> - -#include "menu-layout.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -#ifdef G_ENABLE_DEBUG - - void menu_verbose(const char* format, ...) G_GNUC_PRINTF(1, 2); - - void menu_debug_print_layout(MenuLayoutNode* node, gboolean onelevel); - -#else /* !defined(G_ENABLE_DEBUG) */ - - #ifdef G_HAVE_ISO_VARARGS - #define menu_verbose(...) - #elif defined(G_HAVE_GNUC_VARARGS) - #define menu_verbose(format...) - #else - #error "Cannot disable verbose mode due to lack of varargs macros" - #endif - - #define menu_debug_print_layout(n, o) - -#endif /* G_ENABLE_DEBUG */ - -#ifdef __cplusplus -} -#endif - -#endif /* __MENU_UTIL_H__ */ -- GitLab