[Xfce4-commits] <garcon:master> Squashed commit of the following:

Jannis Pohlmann jannis at xfce.org
Wed Aug 12 13:34:01 CEST 2009


Updating branch refs/heads/master
         to daeb451ad49f071bba97be20c23430ddf17da2eb (commit)
       from 131ec8a61226d262abac0b6d9cc72955e8bedf22 (commit)

commit daeb451ad49f071bba97be20c23430ddf17da2eb
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Wed Aug 12 13:31:13 2009 +0200

    Squashed commit of the following:
    
    commit 2f76d64dfe0d9168d4b77dbefe8f0db9acf55385
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun May 10 20:23:47 2009 +0200
    
        Fix references in garcon-docs.xml and garcon-sections.xml
    
    commit 2d993a9d8fc4842ebfae520ee1e3791419daefd0
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun May 10 20:20:58 2009 +0200
    
        Add missing pkg-config file.
    
    commit 4bf640287b217691d9fa738f329e8dd99326d68e
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun May 10 20:17:51 2009 +0200
    
        Rename files from e.g. garconmenudirectory.h to garcon-menu-directory.h.
    
        Also add garcon-config.c.
    
    commit b0e033b87c6bc05c8ad52bcc62a12ecd76003a7d
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun May 10 19:59:49 2009 +0200
    
        Remove gdesktopmenu/ directory.
    
    commit 57bbc1bfda7a0187f2a55cc955a8be7e5097ad63
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun May 10 18:48:28 2009 +0200
    
        Rename gdesktopmenu to garcon. Major work done by Travis Watkins.
    
        This commit renames gdesktop to garcon. It also improves the API docs
        and adds Travis to the AUTHORS file. A few things still might be broken
        due to the rename.
    
    commit fbcf204a5e415add697f1562bc2ae0766c37e936
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Thu May 7 17:49:02 2009 +0200
    
        	* gdesktopmenu/gdesktopmenu.c: Fix typo in g_desktop_menu_get_type().
    
    commit 8ac6ce691f11c31feea6410b473550f180238241
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Thu May 7 17:28:17 2009 +0200
    
        	* gdesktopmenu/gdesktopmenu.{c,h}: Move _GDesktopMenu and
        	  _GDesktopMenuClass into the header file in order for
        	  GObject-introspection to work.
    
    commit cb9270e7bf96f3491afd7e89bd09eaa252a874e4
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Thu May 7 13:33:24 2009 +0200
    
        	* docs/reference/: Improve API docs structure.
        	* gdesktopmenu/Makefile.am, gdesktopmenu/gdesktopmenu.{c,h},
        	  gdesktopmenu/gdesktopmenumain.{c,h}: Move init/shutdown code into
        	  gdesktopmenumain.{c,h}.
    
    commit 69bf037252b6ec66695846f238e8d242df7f3e96
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Thu May 7 04:08:13 2009 +0200
    
        	* Fix compilation errors, missing "lib" prefix and set the API version
        	  to 1 (not the libtool one).
    
    commit cdc2006747cd9ff4a6c2a5b5f6e441e8f92e20fb
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Thu May 7 03:28:33 2009 +0200
    
        	* Rename to gdesktopmenu. This will need a few more commits to work
        	  again though.
    
    commit ca38e06a2bc4f62efa4fa17deb661116175b93c5
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Mon May 4 00:10:56 2009 +0200
    
        	* docs/reference/libxfce4menu-sections.txt,
        	  libxfce4menu/xfce-menu-directory.{c,h},
        	  libxfce4menu/xfce-menu-element.{c,h},
        	  libxfce4menu/xfce-menu-item.{c,h},
        	  libxfce4menu/xfce-menu-separator.c,
        	  libxfce4menu/xfce-menu.c: Add xfce_menu_element_get_no_display() and
        	  xfce_menu_element_get_visible_in_environment() to the
        	  XfceMenuElement interface. Implement this in XfceMenu,
        	  XfceMenuDirectory, XfceMenuItem and XfceMenuSeparator.
    
    commit c5bda99f7d31cadf19978d85afb2da1eb1300698
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun May 3 23:31:17 2009 +0200
    
        	* docs/reference/libxfce4menu-sections.txt, libxfce4menu/xfce-menu.c,
        	  libxfce4menu/xfce-menu-element.{c,h}, libxfce4menu/xfce-menu-item.c,
        	  libxfce4menu/xfce-menu-separator.c: Add new function
        	  xfce_menu_element_get_comment() to the XfceMenuElement interface and
        	  implement it in XfceMenu, XfceMenuItem and XfceMenuSeparator.
    
    commit 681672a4bf447a33ecd36dda83fdc1323bd83745
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sat Apr 4 23:56:19 2009 +0200
    
        	* AUTHORS: Add Travis Watkins as a contributor.
        	* docs/reference: Update API docs.
        	* libxfce4menu/xfce-menu-directory.{c,h},
        	  libxfce4menu/xfce-menu-element.{c,h},
        	  libxfce4menu/xfce-menu-item.c,
        	  libxfce4menu/xfce-menu-separator.c, libxfce4menu/xfce-menu.c: Add
        	  xfce_menu_element_get_visible() to XfceMenuElement. The
        	  XfceMenuSeparator implementation always returns TRUE while the
        	  XfceMenuItem implementation checks the Hidden/OnlyShowIn/NotShowIn
        	  values of the corresponding desktop entry. XfceMenu checks the
        	  Hidden/OnlyShowIn/NotShowIn values of its XfceMenuDirectory as well
        	  as whether there are any visible child elements. Thanks to Travis
        	  Watkins for the patch.
        	* tests/test-display-menu.c, tests/test-menu-spec.c: Update tests to
        	  reflect the latest API changes. Thanks to Travis for updating
        	  test-display-menu.c.
    
    commit 1beaec37e3e59a734660624928b8fbe77b864cf8
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun Mar 15 04:26:59 2009 +0100
    
        	* STATUS: Update STATUS file.
    
    commit 8e9a5a836005b47691c2c35b08230855d3fc57e2
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun Mar 15 04:22:26 2009 +0100
    
        	* docs/reference/: Update API docs.
        	* libxfce4menu/libxfce4menu.c: Set path pointer to NULL after freeing
        	  it to avoid random data in it.
        	* libxfce4menu/xfce-menu-merger.c: Prepend a default layout element
        	  to the root menu so that the root menu and its children have a
        	  layout to use as a fallback. Remove empty layout elements so that
        	  we can fallback to the default layout.
        	* libxfce4menu/xfce-menu-node.{c,h}: Add new function
        	  xfce_menu_node_tree_get_child_node(). Add
        	  XFCE_MENU_NODE_TYPE_DEFAULT_LAYOUT to the XfceMenuNodeType enum.
        	* libxfce4menu/xfce-menu-parser.c: Parse <DefaultLayout> elements.
        	  Attributes are currently ignored.
        	* libxfce4menu/xfce-menu.c: Properly look up the right layout or
        	  default layout in xfce_menu_get_elements().
        	* tests/test-display-menu.c, tests/test-menu-spec.c: Improve error
        	  messages.
        	* POTFILES.in: Remove deleted file xfce-menu-layout.c.
    
    commit 57ea0ddfef80394168f14676f64b7e66c8c10b47
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun Mar 15 03:14:14 2009 +0100
    
        	* docs/reference/libxfce4menu-sections.txt,
        	  docs/reference/libxfce4menu.types, libxfce4menu/Makefile.am,
        	  libxfce4menu/libxfce4menu.h, libxfce4menu/xfce-menu.{c,h},
        	  libxfce4menu/xfce-menu-layout.{c,h}: Remove XfceMenuLayout class.
        	  Also remove xfce_menu_get_items() and rename
        	  xfce_menu_get_layout_elements() to xfce_menu_get_elements(). Make
        	  menu layouts work again with the GNode trees we have instead of
        	  XfceMenuLayout now.
        	* tests/test-display-menu.c, tests/test-menu-spec.c: Update tests to
        	  the latest API.
    
    commit 6370bb67c622e0ec699f6bccc2b2f9d12960e287
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun Mar 15 02:17:10 2009 +0100
    
        	* libxfce4menu/xfce-menu-node.c: Really fix the typo this time.
        	* libxfce4menu/xfce-menu-parser.c: Remove break inside an if statement
        	  and thereby fix the parsing of <Layout> child elements.
    
    commit a45b9bc65f11f8af8edd76359025cb3b2193aadf
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun Mar 15 02:03:08 2009 +0100
    
        	* libxfce4menu/xfce-menu-node.c: Fix type macro typo in
        	  xfce_menu_node_tree_get_layout_merge_type().
    
    commit e9606e53489220c0c418b3b7e597509091666345
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun Mar 15 01:59:42 2009 +0100
    
        	* libxfce4menu/xfce-menu-merger.c: Remove duplicate layout nodes and
        	  only keep the last one.
    
    commit 63a8fc24598d7ed329aaafcf927eab1b2f78fd64
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sat Mar 14 04:05:14 2009 +0100
    
        	* libxfce4menu/*.h: Remove trailing semicolons after G_BEGIN_DECLS and
        	  G_END_DECLS because it makes gobject-introspection freak out and its
        	  also a bit of a syntax error. Reported by Travis Watkins.
    
    commit 0baa89ae693321efea5c71bd84e2924bbb958817
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sat Mar 14 02:09:38 2009 +0100
    
        	* INSTALL: Update the install information.
        	* configure.in.in, libxfce4menu/libxfce4menu-0.1.pc.in,
        	  libxfce4menu/xfce-menu-directory.c,
        	  libxfce4menu/xfce-menu-item-cache.c, libxfce4menu/xfce-menu-item.c,
        	  libxfce4menu/xfce-menu-merger.c, libxfce4menu/xfce-menu-parser.c: Get
        	  rid of libxfce4util and related code like xfce_resource_dirs(). Use
        	  GKeyFile instead of XfceRc. A lot of this code comes from Travis
        	  Watkins <amaranth at ubuntu.com> who was kind enough to provide a
        	  patch.
        	* docs/reference/libxfce4menu-sections.txt: Update sections.
        	* libxfce4menu/libxfce4menu.{c,h}: Rename xfce_menu_init() and
        	  xfce_menu_shutdown() to libxfce4menu_init() and
        	  libxfce4menu_shutdown(). Add new function
        	  xfce_menu_config_lookup().
        	* libxfce4menu/xfce-menu.{c,h}: Use xfce_menu_config_lookup() instead
        	  of xfce_resource_lookup(). Remove xfce_menu_init() and
        	  xfce_menu_shutdown() declaration in the header file.
        	* tdb/: Remove TDB entirely.
        	* tests/test-display-menu.c, tests/test-menu-parser.c,
        	  tests/test-menu-spec.c: Update to new API and get rid of
        	  libxfce4util code.
        	* POTFILES.in: Update translatable source file list.
        	* libxfce4menu-0.1.pot: Update pot file.
    
    commit ae27baffe7adf8d5557296689907f8f6ee045e38
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Thu Mar 12 02:29:11 2009 +0100
    
        	* libxfce4menu/xfce-menu-monitor.h, libxfce4menu/libxfce4menu.c:
        	  Something is wrong with the API docs. Another try to fix them.
    
    commit 916fee3ae4934e3876f8bc0ccc2532d73d8f8baa
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Thu Mar 12 01:06:40 2009 +0100
    
        	* libxfce4menu/xfce-menu-monitor.h, libxfce4menu/xfce-menu.c: Try to
        	  fix broken API docs syntax and add docs for the
        	  XfceMenuMonitorVTable members.
    
    commit e27803e72515c0d22272ffc20ef6450236fd95c1
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Thu Mar 12 00:38:48 2009 +0100
    
        	* libxfce4menu/xfce-menu-directory.{c,h}: Add function
        	  xfce_menu_directory_equal() which compares two XfceMenuDirectory
        	  objects based on their GFile members.
        	* libxfce4menu/xfce-menu-layout.{c,h}: Use GList instead of GSList
        	  everywhere.
        	* libxfce4menu/xfce-menu-merger.{c,h}: Never access GNode data
        	  directly. Instead always use the xfce_menu_node_tree*() functions.
        	* libxfce4menu/xfce-menu-node.{c,h}: Add functions
        	  xfce_menu_node_tree_get_child_nodes(),
        	  xfce_menu_node_tree_get_string_children(),
        	  xfce_menu_node_tree_get_boolean_child() and
        	  xfce_menu_node_tree_get_string_child() to collect the values of
        	  immediate children of a GNode tree.  Add new functions
        	  xfce_menu_node_tree_set_string() and
        	  xfce_menu_node_tree_set_merge_file_filename() so that GNode data
        	  needs to be accessed less often. Fix assertions in a few other
        	  functions.
        	* libxfce4menu/xfce-menu-parser.c: Fix segmentation fault due to an
        	  uninitialized GError in GIO.
        	* libxfce4menu/xfce-menu.{c,h}: Use GList instead of GSList everywhere.
        	  Improve API docs for a few public functions. Change xfce_menu_new()
        	  again to expect a filename as the first parameter. Add a separate
        	  function xfce_menu_new_for_file() to create an XfceMenu from a
        	  GFile. Rename xfce_menu_get_root() to xfce_menu_new_applications().
        	  Replace a lot of traversing code with the new
        	  xfce_menu_node_tree_get*() functions.
        	* tests/test-display-menu.c, tests/test-menu-parser.c,
        	  tests/test-menu-spec.c: Update to new libxfce4menu API.
    
    commit 16f4b0a5bf618c39d7cd00809e80283c92b2854a
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 19:56:11 2009 +0100
    
        	* libxfce4menu/libxfce4menu.c: Add missing source file.
        	* docs/reference/: Try to get the damn docs right.
        	* libxfce4menu/libxfce4menu.{c,h}, libxfce4menu/xfce-menu.c: Move
        	  xfce_menu_init() and xfce_menu_shutdown() into libxfce4menu.{c,h}.
        	  Fix #undef LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H.
        	* libxfce4menu/xfce-menu-node.{c,h}: Make XfceMenuNodeType enum code
        	  private.
    
    commit ddc429f7579481beea1882ed2bcf04b92524dc2e
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 19:52:54 2009 +0100
    
        	* docs/reference/: Try to get the damn docs right.
        	* libxfce4menu/libxfce4menu.{c,h}, libxfce4menu/xfce-menu.c: Move
        	  xfce_menu_init() and xfce_menu_shutdown() into libxfce4menu.{c,h}.
        	  Fix #undef LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H.
        	* libxfce4menu/xfce-menu-node.{c,h}: Make XfceMenuNodeType enum code
        	  private.
    
    commit a59ae46f053fab057408b0fa86011d4a543758d9
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 18:20:34 2009 +0100
    
        	* docs/reference/: Remove tmpl/ subdir.
    
    commit 68b50bdd7ef47fd4734a76729c2961088b49d1a0
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 18:04:53 2009 +0100
    
        	* docs/reference/: Update API docs.
    
    commit b13a8f36fd6d378d100651b0d7e9a2d198656af0
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 17:47:32 2009 +0100
    
        	* libxfce4menu/xfce-menu-node.h: Add missing declaration for
        	  xfce_menu_node_type_get_type().
    
    commit 4efdc16b02338f15aa5563cb455d06664d0a9d94
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 17:43:50 2009 +0100
    
        	* docs/reference/: Update API docs section and stuff.
        	* libxfce4menu/xfce-menu-move.{c,h}: Remove unused source files.
    
    commit ba7f55403348aac3118384b413a28cd9c838ea44
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 17:30:04 2009 +0100
    
        	* libfxce4menu/Makefile.am: Remove non-existent files and missing
        	  ones.
    
    commit 851ebfcb32feabbc572bc11e6e534df725d53cc8
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 17:26:54 2009 +0100
    
        	* libxfce4menu/xfce-menu-gio.{c,h}: Add missing source files for a few
        	  GIO/GFile utility functions.
    
    commit 41296e94a42c1898d7adcb6262539f1d32ae79c9
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Tue Feb 24 17:08:10 2009 +0100
    
        	* STATUS: Big status update.
        	* TODO: Create a TODO list.
        	* configure.in.in, Makefile.am, tdb/: Remove TDB entirely.
        	* libxfce4menu/libxfce4menu.h: Clean up.
        	* libxfce4menu/xfce-menu-and-rules.{c,h},
        	  libxfce4menu/xfce-menu-not-rules.{c,h},
        	  libxfce4menu/xfce-menu-or-rules.{c,h},
        	  libxfce4menu/xfce-menu-standard-rules.{c,h},
        	  libxfce4menu/xfce-menu-rules.{c,h}: Remove all the XfceMenu*Rules
        	  classes. Replace them with one very simple XfceMenuNode function.
        	* libxfce4menu/xfce-menu-directory.{c,h}: Replace the filename string
        	  property with a GFile file property. Replace
        	  xfce_menu_directory_get_filename() with
        	  xfce_menu_directory_get_file() and remove
        	  xfce_menu_directory_set_filename(). Fix typos in the signal
        	  installation code.
        	* libxfce4menu/xfce-menu-item-cache.c: Remove all TDB related code.
        	  Avoid memory leaks when creating new items (same patch as went into
        	  the old trunk a while ago, bug #3812).
        	* libxfce4menu/xfce-menu-item-pool.{c,h}: Update
        	  xfce_menu_item_pool_apply_exclude_rule() and
        	  xfce_menu_item_pool_filter_exclude() to use a GNode instead of an
        	  XfceMenuRuleStandardRules.
        	* libxfce4menu/xfce-menu-item.{c,h}: Accept URIs as input to
        	  xfce_menu_item_new() and convert them to paths using GFile.
        	* libxfce4menu/xfce-menu-merger.{c,h}: Implement the missing merging
        	  and moving code. Fix a lot of bugs in the code. Never access
        	  XfceMenuNodes directly, always use xfce_menu_node_tree_*()
        	  functions.
        	* libxfce4menu/xfce-menu-node.{c,h}: Add more xfce_menu_node_tree*()
        	  functions. Simplify the code. Add support for matching
        	  Include/Exclude/And/Or/etc. rules against XfceMenuItems.
        	* libxfce4menu/xfce-menu-parser.{c,h}: Minor cleanups.
        	* libxfce4menu/xfce-menu.{c,h}: Change the first parameter of
        	  xfce_menu_new() to GFile. Remove all the parsing code. Use
        	  XfceMenuParser and XfceMenuMerger in xfce_menu_load(). Update all
        	  the menu loading code to use GNode DOM trees. Replace the filename
        	  property with a GFile file property. Still waiting to be implemented
        	  again is the layout stuff. Remove functions like
        	  xfce_menu_get_directory_dirs() which were not meant for public use
        	  anyway.
        	* tests/test-display-menu.c, tests/test-menu-parser.c,
        	  tests/test-menu-spec.c: Update to the new API. Cleanups.
    
    commit c066f3c376d29eed1c9919f77e7cfa289d6e1375
    Author: Jannis Pohlmann <jannis at xfce.org>
    Date:   Sun Feb 22 20:43:33 2009 +0100
    
        	* configure.in.in: Depend on GTK+ 2.12 and GLib 2.14. Add dependency
        	  on GIO 2.14 as well.
        	* libxfce4menu/Makefile.am: Add new source and header files.
        	* libxfce4menu/libxfce4menu.h: Add new header files.
        	* libxfce4menu/xfce-menu-node.{c,h}: Add new class XfceMenuNode which
        	  holds the information for one element in the menu DOM tree, e.g.
        	  <MergeFile>, <Name> or <Menu>
        	* libxfce4menu/xfce-menu-tree-provider.{c,h}: Add new interface
        	  XfceMenuTreeProvider for classes which hold a GNode DOM
        	  representation for .menu files.
        	* libxfce4menu/xfce-menu-parser.{c,h}: Add new parser for .menu XML
        	  files. It builds a GNode DOM representation for the XML data. Each
        	  GNode in the tree (except for the menu nodes) contains one
        	  XfceMenuNode for the XML element information. The parser implements
        	  XfceMenuTreeProvider.
        	* libxfce4menu/xfce-menu-merger.{c,h}: Add new class XfceMenuMerger
        	  which takes the DOM tree from the parser or any other
        	  XfceMenuTreeProvider and resolves duplicates, relative paths and,
        	  most importantly, merges and deletes menus according to the
        	  information in the DOM tree. It implements XfceMenuTreeProvider. It
        	  is not complete yet because it doesn't implement <Move> elements
        	  and is not capable of consolidating child menus with the same name
        	  at the moment.
        	* tests/Makefile.am, tests/test-menu-parser.c: Add a small test
        	  program which parses a menu file using XfceMenuParser and then runs
        	  an XfceMenuMerger and prints the output of both.

 AUTHORS                                            |    1 +
 COPYING                                            |    2 +-
 ChangeLog                                          |  306 ++
 HACKING                                            |   14 +-
 INSTALL                                            |   94 +-
 Makefile.am                                        |   26 +-
 NEWS                                               |    4 +
 README                                             |   14 +-
 STATUS                                             |  104 +-
 TODO                                               |    3 +-
 autogen.sh                                         |   27 +-
 configure.in.in                                    |  121 +-
 docs/reference/Makefile.am                         |   33 +-
 docs/reference/garcon-docs.xml                     |  106 +
 ...fce4menu-overrides.txt => garcon-overrides.txt} |    0
 docs/reference/garcon-sections.txt                 |  317 ++
 docs/reference/garcon.types                        |   11 +
 .../reference/gdesktopmenu-overrides.txt           |    0
 docs/reference/gdesktopmenu-sections.txt           |  317 ++
 docs/reference/gdesktopmenu.types                  |   11 +
 docs/reference/libxfce4menu-docs.sgml              |  124 -
 docs/reference/libxfce4menu-sections.txt           |  351 ---
 docs/reference/libxfce4menu.types                  |   15 -
 docs/reference/tmpl/libxfce4menu-config.sgml       |   79 -
 docs/reference/tmpl/libxfce4menu-unused.sgml       |   62 -
 docs/reference/tmpl/libxfce4menu.sgml              |   26 -
 docs/reference/tmpl/xfce-menu-and-rules.sgml       |   39 -
 docs/reference/tmpl/xfce-menu-directory.sgml       |  170 --
 docs/reference/tmpl/xfce-menu-element.sgml         |   52 -
 docs/reference/tmpl/xfce-menu-environment.sgml     |   35 -
 docs/reference/tmpl/xfce-menu-init-shutdown.sgml   |   34 -
 docs/reference/tmpl/xfce-menu-item-cache.sgml      |   66 -
 docs/reference/tmpl/xfce-menu-item-pool.sgml       |   92 -
 docs/reference/tmpl/xfce-menu-item.sgml            |  336 --
 docs/reference/tmpl/xfce-menu-layout.sgml          |  171 --
 docs/reference/tmpl/xfce-menu-monitor.sgml         |   37 -
 docs/reference/tmpl/xfce-menu-move.sgml            |   75 -
 docs/reference/tmpl/xfce-menu-not-rules.sgml       |   39 -
 docs/reference/tmpl/xfce-menu-or-rules.sgml        |   39 -
 docs/reference/tmpl/xfce-menu-rules.sgml           |   82 -
 docs/reference/tmpl/xfce-menu-separator.sgml       |   39 -
 docs/reference/tmpl/xfce-menu-standard-rules.sgml  |   48 -
 docs/reference/tmpl/xfce-menu.sgml                 |  272 --
 garcon/Makefile.am                                 |   98 +
 garcon/garcon-1.pc.in                              |   13 +
 garcon/garcon-config.c                             |   76 +
 garcon/garcon-config.h.in                          |   55 +
 .../garcon-environment.c                           |   39 +-
 garcon/garcon-environment.h                        |   37 +
 garcon/garcon-gio.c                                |  121 +
 garcon/garcon-gio.h                                |   41 +
 garcon/garcon-menu-directory.c                     |  644 ++++
 garcon/garcon-menu-directory.h                     |   71 +
 garcon/garcon-menu-element.c                       |  114 +
 garcon/garcon-menu-element.h                       |   64 +
 garcon/garcon-menu-item-cache.c                    |  268 ++
 garcon/garcon-menu-item-cache.h                    |   63 +
 garcon/garcon-menu-item-pool.c                     |  207 ++
 garcon/garcon-menu-item-pool.h                     |   60 +
 .../xfce-menu-item.c => garcon/garcon-menu-item.c  |  554 ++--
 garcon/garcon-menu-item.h                          |  101 +
 garcon/garcon-menu-merger.c                        | 1196 ++++++++
 garcon/garcon-menu-merger.h                        |   67 +
 garcon/garcon-menu-monitor.c                       |  363 +++
 garcon/garcon-menu-monitor.h                       |  101 +
 garcon/garcon-menu-node.c                          |  842 +++++
 garcon/garcon-menu-node.h                          |  147 +
 garcon/garcon-menu-parser.c                        |  741 +++++
 garcon/garcon-menu-parser.h                        |   66 +
 garcon/garcon-menu-separator.c                     |  212 ++
 garcon/garcon-menu-separator.h                     |   54 +
 garcon/garcon-menu-tree-provider.c                 |   66 +
 garcon/garcon-menu-tree-provider.h                 |   56 +
 garcon/garcon-menu.c                               | 1611 ++++++++++
 garcon/garcon-menu.h                               |   70 +
 garcon/garcon.c                                    |  153 +
 garcon/garcon.h                                    |   54 +
 libxfce4menu/Makefile.am                           |   87 -
 libxfce4menu/libxfce4menu-0.1.pc.in                |   13 -
 libxfce4menu/libxfce4menu-config.h.in              |   55 -
 libxfce4menu/libxfce4menu.h                        |   46 -
 libxfce4menu/xfce-menu-and-rules.c                 |  161 -
 libxfce4menu/xfce-menu-and-rules.h                 |   47 -
 libxfce4menu/xfce-menu-directory.c                 |  638 ----
 libxfce4menu/xfce-menu-directory.h                 |   71 -
 libxfce4menu/xfce-menu-element.c                   |   85 -
 libxfce4menu/xfce-menu-element.h                   |   58 -
 libxfce4menu/xfce-menu-environment.h               |   34 -
 libxfce4menu/xfce-menu-item-cache.c                |  446 ---
 libxfce4menu/xfce-menu-item-cache.h                |   63 -
 libxfce4menu/xfce-menu-item-pool.c                 |  220 --
 libxfce4menu/xfce-menu-item-pool.h                 |   62 -
 libxfce4menu/xfce-menu-item.h                      |  101 -
 libxfce4menu/xfce-menu-layout.c                    |  396 ---
 libxfce4menu/xfce-menu-layout.h                    |   90 -
 libxfce4menu/xfce-menu-monitor.c                   |  360 ---
 libxfce4menu/xfce-menu-monitor.h                   |   97 -
 libxfce4menu/xfce-menu-move.c                      |  292 --
 libxfce4menu/xfce-menu-move.h                      |   57 -
 libxfce4menu/xfce-menu-not-rules.c                 |  160 -
 libxfce4menu/xfce-menu-not-rules.h                 |   47 -
 libxfce4menu/xfce-menu-or-rules.c                  |  161 -
 libxfce4menu/xfce-menu-or-rules.h                  |   47 -
 libxfce4menu/xfce-menu-rules.c                     |  115 -
 libxfce4menu/xfce-menu-rules.h                     |   73 -
 libxfce4menu/xfce-menu-separator.c                 |  176 --
 libxfce4menu/xfce-menu-separator.h                 |   55 -
 libxfce4menu/xfce-menu-standard-rules.c            |  343 ---
 libxfce4menu/xfce-menu-standard-rules.h            |   77 -
 libxfce4menu/xfce-menu.c                           | 3200 --------------------
 libxfce4menu/xfce-menu.h                           |   85 -
 po/ChangeLog                                       |    9 +
 po/POTFILES.in                                     |   34 +-
 po/{libxfce4menu-0.1.pot => garcon.pot}            |   20 +-
 tdb/Makefile.am                                    |   67 -
 tdb/README                                         |  167 -
 tdb/spinlock.c                                     |  494 ---
 tdb/spinlock.h                                     |   77 -
 tdb/tdb.c                                          | 2099 -------------
 tdb/tdb.h                                          |  161 -
 tdb/tdbconfig.h.in                                 |   34 -
 tdb/tdbspeed.c                                     |  208 --
 tdb/tdbtool.c                                      |  514 ----
 tdb/tdbtorture.c                                   |  278 --
 tests/Makefile.am                                  |   46 +-
 tests/test-display-menu.c                          |  154 +-
 tests/test-menu-parser.c                           |  306 ++
 tests/test-menu-spec.c                             |   92 +-
 128 files changed, 10004 insertions(+), 14993 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index c40ddc1..4efd77d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1,2 @@
 Jannis Pohlmann <jannis at xfce.org>
+Travis Watkins <amaranth at ubuntu.com>
diff --git a/COPYING b/COPYING
index 0a9b3ba..e3d2484 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-libxfce4menu's source code is licensed under the LGPLv2,
+garcon's source code is licensed under the LGPLv2,
 while its documentation is licensed under the GFDL 1.1 (with no 
 invariant sections). The text of both licenses follow:
 
diff --git a/ChangeLog b/ChangeLog
index bc9b9d2..1c9f574 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,309 @@
+2009-05-07	Jannis Pohlmann <jannis at xfce.org>
+
+	* gdesktopmenu/gdesktopmenu.c: Fix typo in g_desktop_menu_get_type().
+
+2009-05-07	Jannis Pohlmann <jannis at xfce.org>
+
+	* gdesktopmenu/gdesktopmenu.{c,h}: Move _GDesktopMenu and
+	  _GDesktopMenuClass into the header file in order for
+	  GObject-introspection to work.
+
+2009-05-07	Jannis Pohlmann <jannis at xfce.org>
+
+	* docs/reference/: Improve API docs structure.
+	* gdesktopmenu/Makefile.am, gdesktopmenu/gdesktopmenu.{c,h},
+	  gdesktopmenu/gdesktopmenumain.{c,h}: Move init/shutdown code into
+	  gdesktopmenumain.{c,h}.
+
+2009-05-07	Jannis Pohlmann <jannis at xfce.org>
+
+	* Fix compilation errors, missing "lib" prefix and set the API version
+	  to 1 (not the libtool one).
+
+2009-05-07	Jannis Pohlmann <jannis at xfce.org>
+
+	* Rename to gdesktopmenu. This will need a few more commits to work
+	  again though.
+
+2009-05-04	Travis Watkins <amaranth at ubuntu.com>
+
+	* docs/reference/libxfce4menu-sections.txt,
+	  libxfce4menu/xfce-menu-directory.{c,h},
+	  libxfce4menu/xfce-menu-element.{c,h},
+	  libxfce4menu/xfce-menu-item.{c,h}, 
+	  libxfce4menu/xfce-menu-separator.c,
+	  libxfce4menu/xfce-menu.c: Add xfce_menu_element_get_no_display() and
+	  xfce_menu_element_get_visible_in_environment() to the
+	  XfceMenuElement interface. Implement this in XfceMenu, 
+	  XfceMenuDirectory, XfceMenuItem and XfceMenuSeparator. 
+
+2009-05-03	Travis Watkins <amaranth at ubuntu.com>
+
+	* docs/reference/libxfce4menu-sections.txt, libxfce4menu/xfce-menu.c,
+	  libxfce4menu/xfce-menu-element.{c,h}, libxfce4menu/xfce-menu-item.c,
+	  libxfce4menu/xfce-menu-separator.c: Add new function 
+	  xfce_menu_element_get_comment() to the XfceMenuElement interface and
+	  implement it in XfceMenu, XfceMenuItem and XfceMenuSeparator.
+
+2009-04-04	Jannis Pohlmann <jannis at xfce.org>
+
+	* AUTHORS: Add Travis Watkins as a contributor.
+	* docs/reference: Update API docs.
+	* libxfce4menu/xfce-menu-directory.{c,h},
+	  libxfce4menu/xfce-menu-element.{c,h},
+	  libxfce4menu/xfce-menu-item.c,
+	  libxfce4menu/xfce-menu-separator.c, libxfce4menu/xfce-menu.c: Add
+	  xfce_menu_element_get_visible() to XfceMenuElement. The
+	  XfceMenuSeparator implementation always returns TRUE while the
+	  XfceMenuItem implementation checks the Hidden/OnlyShowIn/NotShowIn
+	  values of the corresponding desktop entry. XfceMenu checks the
+	  Hidden/OnlyShowIn/NotShowIn values of its XfceMenuDirectory as well
+	  as whether there are any visible child elements. Thanks to Travis
+	  Watkins for the patch.
+	* tests/test-display-menu.c, tests/test-menu-spec.c: Update tests to
+	  reflect the latest API changes. Thanks to Travis for updating
+	  test-display-menu.c.
+
+2009-03-15	Jannis Pohlmann <jannis at xfce.org>
+
+	* STATUS: Update STATUS file.
+
+2009-03-15	Jannis Pohlmann <jannis at xfce.org>
+
+	* docs/reference/: Update API docs.
+	* libxfce4menu/libxfce4menu.c: Set path pointer to NULL after freeing
+	  it to avoid random data in it.
+	* libxfce4menu/xfce-menu-merger.c: Prepend a default layout element
+	  to the root menu so that the root menu and its children have a
+	  layout to use as a fallback. Remove empty layout elements so that
+	  we can fallback to the default layout. 
+	* libxfce4menu/xfce-menu-node.{c,h}: Add new function
+	  xfce_menu_node_tree_get_child_node(). Add
+	  XFCE_MENU_NODE_TYPE_DEFAULT_LAYOUT to the XfceMenuNodeType enum.
+	* libxfce4menu/xfce-menu-parser.c: Parse <DefaultLayout> elements.
+	  Attributes are currently ignored.
+	* libxfce4menu/xfce-menu.c: Properly look up the right layout or
+	  default layout in xfce_menu_get_elements().
+	* tests/test-display-menu.c, tests/test-menu-spec.c: Improve error
+	  messages.
+
+2009-03-15	Jannis Pohlmann <jannis at xfce.org>
+
+	* docs/reference/libxfce4menu-sections.txt,
+	  docs/reference/libxfce4menu.types, libxfce4menu/Makefile.am,
+	  libxfce4menu/libxfce4menu.h, libxfce4menu/xfce-menu.{c,h}, 
+	  libxfce4menu/xfce-menu-layout.{c,h}: Remove XfceMenuLayout class.
+	  Also remove xfce_menu_get_items() and rename
+	  xfce_menu_get_layout_elements() to xfce_menu_get_elements(). Make
+	  menu layouts work again with the GNode trees we have instead of
+	  XfceMenuLayout now.
+	* tests/test-display-menu.c, tests/test-menu-spec.c: Update tests to
+	  the latest API.
+
+2009-03-15	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/xfce-menu-node.c: Really fix the typo this time.
+	* libxfce4menu/xfce-menu-parser.c: Remove break inside an if statement
+	  and thereby fix the parsing of <Layout> child elements.
+
+2009-03-15	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/xfce-menu-node.c: Fix type macro typo in
+	  xfce_menu_node_tree_get_layout_merge_type().
+
+2009-03-15	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/xfce-menu-merger.c: Remove duplicate layout nodes and
+	  only keep the last one.
+
+2009-03-14	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/*.h: Remove trailing semicolons after G_BEGIN_DECLS and
+	  G_END_DECLS because it makes gobject-introspection freak out and its
+	  also a bit of a syntax error. Reported by Travis Watkins.
+
+2009-03-14	Jannis Pohlmann <jannis at xfce.org>
+
+	* INSTALL: Update the install information.
+	* configure.in.in, libxfce4menu/libxfce4menu-0.1.pc.in, 
+	  libxfce4menu/xfce-menu-directory.c, 
+	  libxfce4menu/xfce-menu-item-cache.c, libxfce4menu/xfce-menu-item.c,
+	  libxfce4menu/xfce-menu-merger.c, libxfce4menu/xfce-menu-parser.c: Get
+	  rid of libxfce4util and related code like xfce_resource_dirs(). Use 
+	  GKeyFile instead of XfceRc. A lot of this code comes from Travis 
+	  Watkins <amaranth at ubuntu.com> who was kind enough to provide a
+	  patch.
+	* docs/reference/libxfce4menu-sections.txt: Update sections.
+	* libxfce4menu/libxfce4menu.{c,h}: Rename xfce_menu_init() and
+	  xfce_menu_shutdown() to libxfce4menu_init() and
+	  libxfce4menu_shutdown(). Add new function 
+	  xfce_menu_config_lookup(). 
+	* libxfce4menu/xfce-menu.{c,h}: Use xfce_menu_config_lookup() instead 
+	  of xfce_resource_lookup(). Remove xfce_menu_init() and 
+	  xfce_menu_shutdown() declaration in the header file.
+	* tdb/: Remove TDB entirely.
+	* tests/test-display-menu.c, tests/test-menu-parser.c,
+	  tests/test-menu-spec.c: Update to new API and get rid of
+	  libxfce4util code.
+
+2009-03-12	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/xfce-menu-monitor.h, libxfce4menu/libxfce4menu.c:
+	  Something is wrong with the API docs. Another try to fix them.
+
+2009-03-12	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/xfce-menu-monitor.h, libxfce4menu/xfce-menu.c: Try to
+	  fix broken API docs syntax and add docs for the
+	  XfceMenuMonitorVTable members.
+
+2009-03-12	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/xfce-menu-directory.{c,h}: Add function
+	  xfce_menu_directory_equal() which compares two XfceMenuDirectory
+	  objects based on their GFile members.
+	* libxfce4menu/xfce-menu-layout.{c,h}: Use GList instead of GSList
+	  everywhere.
+	* libxfce4menu/xfce-menu-merger.{c,h}: Never access GNode data
+	  directly. Instead always use the xfce_menu_node_tree*() functions.
+	* libxfce4menu/xfce-menu-node.{c,h}: Add functions
+	  xfce_menu_node_tree_get_child_nodes(),
+	  xfce_menu_node_tree_get_string_children(),
+	  xfce_menu_node_tree_get_boolean_child() and
+	  xfce_menu_node_tree_get_string_child() to collect the values of
+	  immediate children of a GNode tree.  Add new functions
+	  xfce_menu_node_tree_set_string() and
+	  xfce_menu_node_tree_set_merge_file_filename() so that GNode data
+	  needs to be accessed less often. Fix assertions in a few other
+	  functions.
+	* libxfce4menu/xfce-menu-parser.c: Fix segmentation fault due to an
+	  uninitialized GError in GIO.
+	* libxfce4menu/xfce-menu.{c,h}: Use GList instead of GSList everywhere.
+	  Improve API docs for a few public functions. Change xfce_menu_new()
+	  again to expect a filename as the first parameter. Add a separate
+	  function xfce_menu_new_for_file() to create an XfceMenu from a
+	  GFile. Rename xfce_menu_get_root() to xfce_menu_new_applications().
+	  Replace a lot of traversing code with the new
+	  xfce_menu_node_tree_get*() functions.
+	* tests/test-display-menu.c, tests/test-menu-parser.c,
+	  tests/test-menu-spec.c: Update to new libxfce4menu API.
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/libxfce4menu.c: Add missing source file.
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* docs/reference/: Try to get the damn docs right.
+	* libxfce4menu/libxfce4menu.{c,h}, libxfce4menu/xfce-menu.c: Move
+	  xfce_menu_init() and xfce_menu_shutdown() into libxfce4menu.{c,h}.
+	  Fix #undef LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H. 
+	* libxfce4menu/xfce-menu-node.{c,h}: Make XfceMenuNodeType enum code
+	  private.
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* docs/reference/: Remove tmpl/ subdir.
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* docs/reference/: Update API docs.
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/xfce-menu-node.h: Add missing declaration for
+	  xfce_menu_node_type_get_type().
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* docs/reference/: Update API docs section and stuff.
+	* libxfce4menu/xfce-menu-move.{c,h}: Remove unused source files.
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* libfxce4menu/Makefile.am: Remove non-existent files and missing
+	  ones.
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* libxfce4menu/xfce-menu-gio.{c,h}: Add missing source files for a few
+	  GIO/GFile utility functions.
+
+2009-02-24	Jannis Pohlmann <jannis at xfce.org>
+
+	* STATUS: Big status update.
+	* TODO: Create a TODO list.
+	* configure.in.in, Makefile.am, tdb/: Remove TDB entirely.
+	* libxfce4menu/libxfce4menu.h: Clean up.
+	* libxfce4menu/xfce-menu-and-rules.{c,h},
+	  libxfce4menu/xfce-menu-not-rules.{c,h},
+	  libxfce4menu/xfce-menu-or-rules.{c,h},
+	  libxfce4menu/xfce-menu-standard-rules.{c,h},
+	  libxfce4menu/xfce-menu-rules.{c,h}: Remove all the XfceMenu*Rules
+	  classes. Replace them with one very simple XfceMenuNode function.
+	* libxfce4menu/xfce-menu-directory.{c,h}: Replace the filename string
+	  property with a GFile file property. Replace
+	  xfce_menu_directory_get_filename() with 
+	  xfce_menu_directory_get_file() and remove
+	  xfce_menu_directory_set_filename(). Fix typos in the signal
+	  installation code. 
+	* libxfce4menu/xfce-menu-item-cache.c: Remove all TDB related code.
+	  Avoid memory leaks when creating new items (same patch as went into
+	  the old trunk a while ago, bug #3812).
+	* libxfce4menu/xfce-menu-item-pool.{c,h}: Update
+	  xfce_menu_item_pool_apply_exclude_rule() and
+	  xfce_menu_item_pool_filter_exclude() to use a GNode instead of an
+	  XfceMenuRuleStandardRules.
+	* libxfce4menu/xfce-menu-item.{c,h}: Accept URIs as input to
+	  xfce_menu_item_new() and convert them to paths using GFile.
+	* libxfce4menu/xfce-menu-merger.{c,h}: Implement the missing merging
+	  and moving code. Fix a lot of bugs in the code. Never access
+	  XfceMenuNodes directly, always use xfce_menu_node_tree_*()
+	  functions.
+	* libxfce4menu/xfce-menu-node.{c,h}: Add more xfce_menu_node_tree*()
+	  functions. Simplify the code. Add support for matching
+	  Include/Exclude/And/Or/etc. rules against XfceMenuItems. 
+	* libxfce4menu/xfce-menu-parser.{c,h}: Minor cleanups.
+	* libxfce4menu/xfce-menu.{c,h}: Change the first parameter of
+	  xfce_menu_new() to GFile. Remove all the parsing code. Use
+	  XfceMenuParser and XfceMenuMerger in xfce_menu_load(). Update all
+	  the menu loading code to use GNode DOM trees. Replace the filename 
+	  property with a GFile file property. Still waiting to be implemented 
+	  again is the layout stuff. Remove functions like
+	  xfce_menu_get_directory_dirs() which were not meant for public use
+	  anyway.
+	* tests/test-display-menu.c, tests/test-menu-parser.c,
+	  tests/test-menu-spec.c: Update to the new API. Cleanups.
+
+2009-02-22	Jannis Pohlmann <jannis at xfce.org>
+
+	* configure.in.in: Depend on GTK+ 2.12 and GLib 2.14. Add dependency
+	  on GIO 2.14 as well. 
+	* libxfce4menu/Makefile.am: Add new source and header files.
+	* libxfce4menu/libxfce4menu.h: Add new header files.
+	* libxfce4menu/xfce-menu-node.{c,h}: Add new class XfceMenuNode which
+	  holds the information for one element in the menu DOM tree, e.g.
+	  <MergeFile>, <Name> or <Menu>
+	* libxfce4menu/xfce-menu-tree-provider.{c,h}: Add new interface
+	  XfceMenuTreeProvider for classes which hold a GNode DOM
+	  representation for .menu files.
+	* libxfce4menu/xfce-menu-parser.{c,h}: Add new parser for .menu XML
+	  files. It builds a GNode DOM representation for the XML data. Each
+	  GNode in the tree (except for the menu nodes) contains one
+	  XfceMenuNode for the XML element information. The parser implements
+	  XfceMenuTreeProvider.
+	* libxfce4menu/xfce-menu-merger.{c,h}: Add new class XfceMenuMerger
+	  which takes the DOM tree from the parser or any other 
+	  XfceMenuTreeProvider and resolves duplicates, relative paths and,
+	  most importantly, merges and deletes menus according to the
+	  information in the DOM tree. It implements XfceMenuTreeProvider. It
+	  is not complete yet because it doesn't implement <Move> elements 
+	  and is not capable of consolidating child menus with the same name
+	  at the moment.
+	* tests/Makefile.am, tests/test-menu-parser.c: Add a small test
+	  program which parses a menu file using XfceMenuParser and then runs
+	  an XfceMenuMerger and prints the output of both.
+
 2009-02-04	Jannis Pohlmann <jannis at xfce.org>
 
 	* NEWS: Update NEWS.
diff --git a/HACKING b/HACKING
index 617dd19..63ad4d3 100644
--- a/HACKING
+++ b/HACKING
@@ -1,7 +1,7 @@
 Bug tracking system
 ===================
 
-libxfce4menu uses the bug tracking system at http://bugzilla.xfce.org/
+garcon uses the bug tracking system at http://bugzilla.xfce.org/
 hosted and maintained by the Xfce project.
 
 
@@ -16,14 +16,14 @@ Please and send a patch against a recent version of this package. Patches
 against the Subversion trunk branch are most preferable. You can always
 access the trunk branch from 
 
-  http://svn.xfce.org/svn/xfce/libxfce4menu/trunk
+  http://svn.xfce.org/svn/xfce/garcon/trunk
 
 
 Feature requests
 ================
 
 Please file feature requests to the Xfce bug tracking system
-(http://bugzilla.xfce.org, product libxfce4menu) with a Severity of
+(http://bugzilla.xfce.org, product garcon) with a Severity of
 enhancement. Make sure that your feature request wasn't reported
 already before; requesting a feature several times won't increase
 the chance that it gets added.
@@ -41,19 +41,19 @@ Release process
 
   1) Check out a fresh copy from Subversion
   2) Increment the version number in configure.in.in and the major version
-     number of the library whenever new functions got added
+     number of the library whenever new functions got added.
   3) Update NEWS and ChangeLog, and don't forget to add a note about the new
      release to ChangeLog, so people can see which changes appeared in which
      release.
   4) Check the gtk-doc.
   5) Run make update-po in po/ and update po/de.po (don't forget the header)!
-  6) Unset libxfce4menu_version_tag in configure.in.in and reset it after the
+  6) Unset garcon_version_tag in configure.in.in and reset it after the
      release is done.
   7) Verify that make dist works.
   8) "svn commit" the changes.
   9) Create a simple tag for the release,
-      "svn copy https://xfce.org/svn/xfce/libxfce4menu/trunk
-       https://xfce.org/svn/xfce/libxfce4menu/tags/libxfce4menu-X.Y.Ztag"
+      "svn copy https://xfce.org/svn/xfce/garcon/trunk
+       https://xfce.org/svn/xfce/garcon/tags/garcon-X.Y.Ztag"
      where X.Y.Z is the version number and tag is the version tag, i.e. beta1.
  10) Upload the tarballs to xfce.org
  11) Upload the new online documentation to www.xfce.org.
diff --git a/INSTALL b/INSTALL
index d3c5b40..8b82ade 100644
--- a/INSTALL
+++ b/INSTALL
@@ -2,15 +2,15 @@ Installation Instructions
 *************************
 
 Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+2006, 2007, 2008 Free Software Foundation, Inc.
 
-This file is free documentation; the Free Software Foundation gives
+   This file is free documentation; the Free Software Foundation gives
 unlimited permission to copy, distribute and modify it.
 
 Basic Installation
 ==================
 
-Briefly, the shell commands `./configure; make; make install' should
+   Briefly, the shell commands `./configure; make; make install' should
 configure, build, and install this package.  The following
 more-detailed instructions are generic; see the `README' file for
 instructions specific to this package.
@@ -73,9 +73,9 @@ The simplest way to compile this package is:
 Compilers and Options
 =====================
 
-Some systems require unusual options for compilation or linking that the
-`configure' script does not know about.  Run `./configure --help' for
-details on some of the pertinent environment variables.
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
 
    You can give `configure' initial values for configuration parameters
 by setting variables in the command line or in the environment.  Here
@@ -88,7 +88,7 @@ is an example:
 Compiling For Multiple Architectures
 ====================================
 
-You can compile the package for more than one kind of computer at the
+   You can compile the package for more than one kind of computer at the
 same time, by placing the object files for each architecture in their
 own directory.  To do this, you can use GNU `make'.  `cd' to the
 directory where you want the object files and executables to go and run
@@ -100,10 +100,24 @@ architecture at a time in the source code directory.  After you have
 installed the package for one architecture, use `make distclean' before
 reconfiguring for another architecture.
 
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
 Installation Names
 ==================
 
-By default, `make install' installs the package's commands under
+   By default, `make install' installs the package's commands under
 `/usr/local/bin', include files under `/usr/local/include', etc.  You
 can specify an installation prefix other than `/usr/local' by giving
 `configure' the option `--prefix=PREFIX'.
@@ -126,7 +140,7 @@ option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
 Optional Features
 =================
 
-Some packages pay attention to `--enable-FEATURE' options to
+   Some packages pay attention to `--enable-FEATURE' options to
 `configure', where FEATURE indicates an optional part of the package.
 They may also pay attention to `--with-PACKAGE' options, where PACKAGE
 is something like `gnu-as' or `x' (for the X Window System).  The
@@ -138,14 +152,36 @@ find the X include and library files automatically, but if it doesn't,
 you can use the `configure' options `--x-includes=DIR' and
 `--x-libraries=DIR' to specify their locations.
 
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
+a workaround.  If GNU CC is not installed, it is therefore recommended
+to try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
 Specifying the System Type
 ==========================
 
-There may be some features `configure' cannot figure out automatically,
-but needs to determine by the type of machine the package will run on.
-Usually, assuming the package is built to be run on the _same_
-architectures, `configure' can figure that out, but if it prints a
-message saying it cannot guess the machine type, give it the
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
 `--build=TYPE' option.  TYPE can either be a short name for the system
 type, such as `sun4', or a canonical name which has the form:
 
@@ -171,9 +207,9 @@ eventually be run) with `--host=TYPE'.
 Sharing Defaults
 ================
 
-If you want to set default values for `configure' scripts to share, you
-can create a site shell script called `config.site' that gives default
-values for variables like `CC', `cache_file', and `prefix'.
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
 `configure' looks for `PREFIX/share/config.site' if it exists, then
 `PREFIX/etc/config.site' if it exists.  Or, you can set the
 `CONFIG_SITE' environment variable to the location of the site script.
@@ -182,7 +218,7 @@ A warning: not all `configure' scripts look for a site script.
 Defining Variables
 ==================
 
-Variables not defined in a site shell script can be set in the
+   Variables not defined in a site shell script can be set in the
 environment passed to `configure'.  However, some packages may run
 configure again during the build, and the customized values of these
 variables may be lost.  In order to avoid this problem, you should set
@@ -201,11 +237,19 @@ an Autoconf bug.  Until the bug is fixed you can use this workaround:
 `configure' Invocation
 ======================
 
-`configure' recognizes the following options to control how it operates.
+   `configure' recognizes the following options to control how it
+operates.
 
 `--help'
 `-h'
-     Print a summary of the options to `configure', and exit.
+     Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+     Print a summary of the options unique to this package's
+     `configure', and exit.  The `short' variant lists options used
+     only in the top level, while the `recursive' variant lists options
+     also present in any nested packages.
 
 `--version'
 `-V'
@@ -232,6 +276,16 @@ an Autoconf bug.  Until the bug is fixed you can use this workaround:
      Look for the package's source code in directory DIR.  Usually
      `configure' can determine that directory automatically.
 
+`--prefix=DIR'
+     Use DIR as the installation prefix.  *Note Installation Names::
+     for more details, including other options available for fine-tuning
+     the installation locations.
+
+`--no-create'
+`-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
 `configure' also accepts some other, not widely useful, options.  Run
 `configure --help' for more details.
 
diff --git a/Makefile.am b/Makefile.am
index cac4668..61cc3d3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,10 +1,24 @@
-# $Id$
-#
-# vi:set ts=8 sw=8 noet ai nocindent:
+# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
+# 
+# Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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 Library General Public License for more details.
+# 
+# You should have received a copy of the GNU Library General 
+# Public License along with this library; if not, write to the 
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
 
 SUBDIRS =								\
-	tdb								\
-	libxfce4menu							\
+	garcon							\
 	docs								\
 	tests								\
 	po
@@ -32,7 +46,7 @@ EXTRA_DIST =								\
 	intltool-update.in
 
 DISTCLEANFILES =							\
-	libxfce4menu.spec						\
+	garcon.spec						\
 	intltool-extract						\
 	intltool-merge							\
 	intltool-update
diff --git a/NEWS b/NEWS
index c62ae11..e91cda1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+=========================
+OLD NEWS FOR libxfce4menu
+=========================
+
 4.5.99.2
 ========
 - Add hint about no invariant sections to COPYING.
diff --git a/README b/README
index e4210fd..a52c92a 100644
--- a/README
+++ b/README
@@ -1,14 +1,14 @@
 What is it?
 ===========
 
-This is libxfce4menu, a freedesktop.org compliant menu implementation for
-Xfce. 
+This is garcon, a freedesktop.org compliant menu implementation based
+on GLib and GIO.
 
 
 Current state
 =============
 
-libxfce4menu already covers the most important parts of the menu specification. 
+garcon already covers the most important parts of the menu specification. 
 It is however still in development and thus, neither stable nor complete.
 
 
@@ -21,14 +21,14 @@ The file 'INSTALL' contains generic installation instructions.
 Debugging Support
 =================
 
-libxfce4menu currently supports three different levels of debugging support, 
+garcon currently supports three different levels of debugging support, 
 which can be setup using the configure flag `--enable-debug' (check the output 
 of `configure --help'):
 
   `yes'         This is the default for SVN snapshot builds. It adds all kinds
                 of checks to the code, and is therefore likely to run slower.
-                Use this for development of libxfce4menu and locating bugs in 
-                libxfce4menu.
+                Use this for development of garcon and locating bugs in 
+                garcon.
 
   `minimum'     This is the default for release builds. This is the recommended
                 behaviour.
@@ -41,7 +41,7 @@ How to report bugs?
 ===================
 
 Bugs should be reported to the Xfce bug tracking system 
-(http://bugzilla.xfce.org, product libxfce4menu). You will need to create an 
+(http://bugzilla.xfce.org, product garcon). You will need to create an 
 account for yourself.
 
 Please read the HACKING file for information on where to send changes or 
diff --git a/STATUS b/STATUS
index 5e3e6ad..7a89abc 100644
--- a/STATUS
+++ b/STATUS
@@ -57,51 +57,37 @@ I. Supported menu file elements
 
   [x] <Not>
 
-  [ ] <MergeFile>
+  [x] <MergeFile>
 
-  [ ] <MergeDir>
+  [x] <MergeDir>
 
-  [ ] <DefaultMergeDirs>
+  [x] <DefaultMergeDirs>
 
-  [-] <LegacyDir>
+  [ ] <LegacyDir>
       
-        <LegacyDir> elements are parsed and added to the menus 
-        which contain them in the menu file. Legacy menus are created
-        for legacy dirs with a .directory file. However, their desktop
-        files are not parsed yet.
-
-  [-] <DefaultLegacyDirs>
+  [ ] <DefaultLegacyDirs>
     
         See <LegacyDir>
 
-  [-] <KDELegacyDirs>
-
-        See <LegacyDir>
-
-  [-] <Move>
+  [ ] <KDELegacyDirs>
 
-        <Move> elements are parsed and functions for applying them
-        do exist. They are incomplete though: they only rename
-        menus if the <New> menu does not exist. Merging is not done
-        yet.
+  [x] <Move>
 
-  [-] <Old>
+  [x] <Old>
 
-        See <Move>
-
-  [-] <New>
-
-        See <Move>
+  [x] <New>
 
   [x] <Layout>
 
-  [ ] <DefaultLayout>
+  [-] <DefaultLayout>
+
+        <DefaultLayout> elements are parsed and work fine but their
+        optional XML attributes (show_empty, inline etc.) are currently
+        being ignored.
 
   [-] <Menuname>
 
-        The <Menuname> element is parsed and applied, but XML 
-        attributes like show_empty, inline, inline_limit etc. are not
-        handled.
+        See <DefaultLayout>.
 
   [x] <Separator>
 
@@ -122,32 +108,15 @@ II. Test suite results
     * All
     * And
     * AppDir-relative
-    * boolean-logic
     * Category
+    * DefaultMergeDirs
     * Deleted
-    * desktop-name-collision
     * DesktopFileID
-    * DirectoryDir-relative
     * Directory
+    * DirectoryDir-relative
     * Exclude
     * Filename
-    * menu-multiple-matching
     * Merge-combined
-    * NoDisplay
-    * NoDisplay2
-    * NotOnlyUnallocated-default
-    * official-categories
-    * OnlyUnallocated
-    * Or
-    * submenu-collision
-
-  Failed tests:
-
-    * AppDir (test suite bug, missing result file)
-    * DefaultMergeDirs
-    * DirectoryDir (test suite bug, missing result file)
-    * LegacyDir-Move
-    * LegacyDir-relative
     * MergeDir-absolute
     * MergeDir-relative
     * MergeFile2
@@ -157,14 +126,27 @@ II. Test suite results
     * MergeFile-path
     * MergeFile-recursive
     * MergeFile-relative
+    * Move
     * Move-collapsing
     * Move-ordering
     * Move-submenu
-    * Move (unverified test suite bug)
+    * NoDisplay
+    * NoDisplay2
+    * NotOnlyUnallocated-default
+    * OnlyUnallocated
+    * Or
+    * boolean-logic
+    * desktop-name-collision
+    * menu-multiple-matching
+    * official-categories
+    * submenu-collision
 
-  A list of test suite bugs I found during testing can be found here:
+  Failed tests:
 
-    http://lunar-linux.org/~jannis/menu-spec-testsuite.txt
+    * AppDir (test suite bug, missing result file)
+    * DirectoryDir (test suite bug, missing result file)
+    * LegacyDir-Move
+    * LegacyDir-relative
 
 
 
@@ -172,21 +154,7 @@ III. Filesystem monitoring
 ==========================
 
   Filesystem monitoring is done by moving the actual work into the 
-  client application. Using XfceMenuMonitorVTable applications can
-  register functions to be called when monitoring of a file or 
+  client application. Using GarconMenuMonitorVTable applications 
+  can register functions to be called when monitoring of a file or
   directory is needed. They then have to care about monitoring 
-  themselves (see xfce-menu-monitor.{c,h} for details.
-
-
-
-IV. UI interaction
-==================
-
-  Using GObject signals it should be easy to connect to menus and
-  menu items in order to update the related widgets.
-
-
-
-Written by Jannis Pohlmann <jannis at xfce.org>.
-
-$Id: STATUS 25194 2007-03-18 15:16:39Z jannis $
+  themselves (see garconmenumonitor.{c,h} for details.
diff --git a/TODO b/TODO
index 382b441..85f8da7 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,5 @@
 TODO
 ========================================================================
 
-  * Add libxfce4menu.spec.in for building RPMs
-  * Re-add test scripts
+  * Add garcon.spec.in for building RPMs
   * Integrate with menu spec test suite
diff --git a/autogen.sh b/autogen.sh
index e7ad211..8aac64d 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,14 +1,23 @@
 #!/bin/sh
 #
-# $Id$
-#
-# vi:set ts=2 sw=2 et ai:
-#
-# Copyright (c) 2007
-#         The Xfce development team. All rights reserved.
-#
-# Written for Xfce by Jannis Pohlmann <jannis at xfce.org>.
-#
+# vi:set et ai sw=2 sts=2 ts=2: */
+# 
+# Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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 Library General Public License for more details.
+# 
+# You should have received a copy of the GNU Library General 
+# Public License along with this library; if not, write to the 
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
 
 (type xdt-autogen) >/dev/null 2>&1 || {
   cat >&2 <<EOF
diff --git a/configure.in.in b/configure.in.in
index d636ace..92f6e61 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -1,38 +1,44 @@
-dnl $Id$
-dnl
-dnl Copyright (c) 2007 The Xfce development team.
-dnl All rights reserved.
-dnl
-dnl Written for Xfce by Jannis Pohlmann <jannis at xfce.org>.
-dnl
+dnl vi:set et ai sw=2 sts=2 ts=2: */
+dnl 
+dnl Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
+dnl 
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Library General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2 of the License, or (at your option) any later version.
+dnl 
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+dnl GNU Library General Public License for more details.
+dnl 
+dnl You should have received a copy of the GNU Library General 
+dnl Public License along with this library; if not, write to the 
+dnl Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+dnl Boston, MA 02110-1301, USA.
 
 dnl ***************************
 dnl *** Version information ***
 dnl ***************************
-m4_define([libxfce4menu_verinfo], [0:0:0])
-m4_define([libxfce4menu_version_api_major], [0])
-m4_define([libxfce4menu_version_api_minor], [1])
-m4_define([libxfce4menu_version_major], [4])
-m4_define([libxfce4menu_version_minor], [5])
-m4_define([libxfce4menu_version_micro], [99])
-m4_define([libxfce4menu_version_nano], [1])
-m4_define([libxfce4menu_version_build], [r at REVISION@])
-m4_define([libxfce4menu_version_tag], [svn])
-m4_define([libxfce4menu_version], [libxfce4menu_version_major().libxfce4menu_version_minor().libxfce4menu_version_micro()ifelse(libxfce4menu_version_nano(), [], [], [.libxfce4menu_version_nano()])ifelse(libxfce4menu_version_tag(), [svn], [libxfce4menu_version_tag()-libxfce4menu_version_build()], [libxfce4menu_version_tag()])])
+m4_define([garcon_verinfo], [0:0:0])
+m4_define([garcon_version_api_major], [1])
+m4_define([garcon_version_major], [0])
+m4_define([garcon_version_minor], [1])
+m4_define([garcon_version_micro], [0])
+m4_define([garcon_version_build], [r at REVISION@])
+m4_define([garcon_version_tag], [svn])
+m4_define([garcon_version], [garcon_version_major().garcon_version_minor().garcon_version_micro()ifelse(garcon_version_tag(), [svn], [garcon_version_tag()-garcon_version_build()], [garcon_version_tag()])])
 
 dnl ********************************************
 dnl *** Full debug support for SVN snapshots ***
 dnl ********************************************
-m4_define([libxfce4menu_debug_default], [ifelse(libxfce4menu_version_tag(), [svn], [full], [minimum])])
+m4_define([garcon_debug_default], [ifelse(garcon_version_tag(), [svn], [full], [minimum])])
 
 dnl ***************************
 dnl *** Initialize autoconf ***
 dnl ***************************
-AC_COPYRIGHT([Copyright (c) 2007 The Xfce development team.
-All rights reserved.
-        
-Written for Xfce by Jannis Pohlmann <jannis at xfce.org>.])
-AC_INIT([libxfce4menu], [libxfce4menu_version], [http://bugzilla.xfce.org/])
+AC_COPYRIGHT([Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>])
+AC_INIT([garcon], [garcon_version], [http://bugzilla.xfce.org/])
 AC_PREREQ([2.50])
 AC_REVISION([$Id$])
 AC_CANONICAL_TARGET()
@@ -47,24 +53,22 @@ AM_MAINTAINER_MODE()
 dnl **************************
 dnl *** Libtool versioning ***
 dnl **************************
-LIBXFCE4MENU_VERINFO=libxfce4menu_verinfo()
-AC_SUBST([LIBXFCE4MENU_VERINFO])
+GARCON_VERINFO=garcon_verinfo()
+AC_SUBST([GARCON_VERINFO])
 
 dnl ****************************
-dnl *** Subst libxfce4menu version ***
+dnl *** Subst garcon version ***
 dnl ****************************
-LIBXFCE4MENU_VERSION_MAJOR=libxfce4menu_version_major()
-LIBXFCE4MENU_VERSION_MINOR=libxfce4menu_version_minor()
-LIBXFCE4MENU_VERSION_MICRO=libxfce4menu_version_micro()
-LIBXFCE4MENU_VERSION_API_MAJOR=libxfce4menu_version_api_major()
-LIBXFCE4MENU_VERSION_API_MINOR=libxfce4menu_version_api_minor()
-LIBXFCE4MENU_VERSION_API=$LIBXFCE4MENU_VERSION_API_MAJOR.$LIBXFCE4MENU_VERSION_API_MINOR
-AC_SUBST([LIBXFCE4MENU_VERSION_MAJOR])
-AC_SUBST([LIBXFCE4MENU_VERSION_MINOR])
-AC_SUBST([LIBXFCE4MENU_VERSION_MICRO])
-AC_SUBST([LIBXFCE4MENU_VERSION_API_MAJOR])
-AC_SUBST([LIBXFCE4MENU_VERSION_API_MINOR])
-AC_SUBST([LIBXFCE4MENU_VERSION_API])
+GARCON_VERSION_MAJOR=garcon_version_major()
+GARCON_VERSION_MINOR=garcon_version_minor()
+GARCON_VERSION_MICRO=garcon_version_micro()
+GARCON_VERSION_API_MAJOR=garcon_version_api_major()
+GARCON_VERSION_API=$GARCON_VERSION_API_MAJOR
+AC_SUBST([GARCON_VERSION_MAJOR])
+AC_SUBST([GARCON_VERSION_MINOR])
+AC_SUBST([GARCON_VERSION_MICRO])
+AC_SUBST([GARCON_VERSION_API_MAJOR])
+AC_SUBST([GARCON_VERSION_API])
 
 dnl *******************************
 dnl *** Check for UNIX variants ***
@@ -83,28 +87,13 @@ AC_PROG_INTLTOOL([0.31], [no-xml])
 AC_PROG_LIBTOOL()
 AM_PROG_CC_C_O()
 
-dnl ***********************************************
-dnl *** Determine the u32 type required for tdb ***
-dnl ***********************************************
-AC_CHECK_SIZEOF([int])
-AC_CHECK_SIZEOF([long])
-AC_CHECK_SIZEOF([short])
-AC_MSG_CHECKING([for 32bit unsigned integer])
-case 4 in
-$ac_cv_sizeof_int)   TDB_U32_TYPE="unsigned int" ;;
-$ac_cv_sizeof_long)  TDB_U32_TYPE="unsigned long" ;;
-$ac_cv_sizeof_short) TDB_U32_TYPE="unsigned short" ;;
-esac
-AC_SUBST([TDB_U32_TYPE])
-AC_MSG_RESULT([$TDB_U32_TYPE])
-
 dnl ***************************************
 dnl *** Check for standard header files ***
 dnl ***************************************
 AC_HEADER_STDC()
 AC_CHECK_HEADERS([fcntl.h errno.h sys/mman.h sys/stat.h sys/wait.h memory.h \
-		  stdlib.h stdio.h string.h sys/types.h sys/time.h unistd.h \
-		  time.h stdarg.h sys/types.h sys/uio.h sched.h ctype.h])
+                  stdlib.h stdio.h string.h sys/types.h sys/time.h unistd.h \
+                  time.h stdarg.h sys/types.h sys/uio.h sched.h ctype.h])
 
 dnl ************************************
 dnl *** Check for standard functions ***
@@ -115,15 +104,15 @@ dnl AC_CHECK_FUNCS([])
 dnl ******************************
 dnl *** Check for i18n support ***
 dnl ******************************
-XDT_I18N([@LINGUAS@], [libxfce4menu-libxfce4menu_version_api_major().libxfce4menu_version_api_minor()])
+XDT_I18N([@LINGUAS@])
 
 dnl ***********************************
 dnl *** Check for required packages ***
 dnl ***********************************
-XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.6.0])
-XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.6.0])
-XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.6.0])
-XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.5.99.1])
+XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.14.0])
+XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.12.0])
+XDT_CHECK_PACKAGE([GIO], [gio-2.0], [2.14.0])
+XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.14.0])
 
 dnl *************************
 dnl *** Check for gtk-doc ***
@@ -134,8 +123,8 @@ dnl ***********************************
 dnl *** Check for debugging support ***
 dnl ***********************************
 AC_ARG_ENABLE([debug],
-AC_HELP_STRING([--enable-debug=@<:@no/minimum/yes@:>@], [Turn on debugging @<:@default=libxfce4menu_debug_default@:>@]),
-  [], [enable_debug=libxfce4menu_debug_default])
+AC_HELP_STRING([--enable-debug=@<:@no/minimum/yes@:>@], [Turn on debugging @<:@default=garcon_debug_default@:>@]),
+  [], [enable_debug=garcon_debug_default])
 AC_MSG_CHECKING([whether to enable debugging support])
 if test x"$enable_debug" = x"yes" -o x"$enable_debug" = x"full"; then
   dnl Print the result
@@ -213,12 +202,10 @@ Makefile
 docs/Makefile
 docs/reference/Makefile
 docs/reference/version.xml
-libxfce4menu/Makefile
-libxfce4menu/libxfce4menu-0.1.pc
-libxfce4menu/libxfce4menu-config.h
+garcon/Makefile
+garcon/garcon-1.pc
+garcon/garcon-config.h
 po/Makefile.in
-tdb/tdbconfig.h
-tdb/Makefile
 tests/Makefile
 ])
 
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 2ebe79f..16b7dfb 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -1,20 +1,37 @@
-# $Id$
-#
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
+# 
+# Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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 Library General Public License for more details.
+# 
+# You should have received a copy of the GNU Library General 
+# Public License along with this library; if not, write to the 
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
 
 AUTOMAKE_OPTIONS = 1.8
 
 # Name of the module
-DOC_MODULE=libxfce4menu
+DOC_MODULE=garcon
 
 # Top-level SGML file
-DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
+
+SCAN_OPTIONS=--rebuild-sections
 
 # Extra options to pass to gtkdoc-scangobj
 SCANGOBJ_OPTIONS=
 
 # Directory containing the source code
-DOC_SOURCE_DIR=../../libxfce4menu
+DOC_SOURCE_DIR=../../garcon
 
 # Extra options to supply to gtkdoc-mkdb
 MKDB_OPTIONS=--sgml-mode --output-format=xml
@@ -23,8 +40,8 @@ MKDB_OPTIONS=--sgml-mode --output-format=xml
 FIXXREF_OPTIONS=
 
 # Used for dependencies
-HFILE_GLOB=$(top_srcdir)/libxfce4menu/*.h
-CFILE_GLOB=$(top_srcdir)/libxfce4menu/*.c
+HFILE_GLOB=$(top_srcdir)/garcon/*.h
+CFILE_GLOB=$(top_srcdir)/garcon/*.c
 
 # Extra files to add when scanning (relative to $srcdir)
 EXTRA_HFILES=
@@ -51,7 +68,7 @@ GTKDOC_LIBS =								\
 	$(GTHREAD_LIBS)							\
 	$(GTK_CFLAGS)							\
 	$(LIBXFCE4UTIL_LIBS)						\
-	$(top_builddir)/libxfce4menu/libxfce4menu-$(LIBXFCE4MENU_VERSION_API).la
+	$(top_builddir)/garcon/libgarcon-$(GARCON_VERSION_API).la
 
 include $(top_srcdir)/gtk-doc.make
 
diff --git a/docs/reference/garcon-docs.xml b/docs/reference/garcon-docs.xml
new file mode 100644
index 0000000..721518a
--- /dev/null
+++ b/docs/reference/garcon-docs.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+                      "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+]>
+
+<book id="index" lang="en">
+  <bookinfo>
+    <title>garcon Reference Manual</title>
+    <releaseinfo>Version <xi:include href="version.xml" parse="text"/></releaseinfo>
+    <copyright>
+      <year>2006</year>
+      <year>2007</year>
+      <year>2008</year>
+      <year>2009</year>
+      <holder>Jannis Pohlmann</holder>
+    </copyright>
+    <legalnotice id="legalnotice">
+      <para>
+        Permission is granted to copy, distribute and/or modify this document
+        under the terms of the GNU Free Documentation License, Version 1.1 or
+        any later version published by the Free Software Foundation; with no
+        Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
+        Texts. The complete license text is available from the <ulink
+        type="http" url="http://www.gnu.org/">Free Software Foundation</ulink>.
+      </para>
+    </legalnotice>
+    <authorgroup>
+      <author>
+        <firstname>Jannis</firstname>
+        <surname>Pohlmann</surname>
+        <affiliation>
+          <address><email>jannis at xfce.org</email></address>
+        </affiliation>
+      </author>
+    </authorgroup>
+  </bookinfo>
+
+  <part>
+    <title>Overview</title>
+    <para>
+      The <application>garcon</application> library depends on the following libraries:
+      <variablelist>
+        <varlistentry>
+          <term>GLib</term>
+          <listitem>
+            <para>
+              A general-purpose utility library, not specific to graphical user interfaces.
+              GLib provides many useful data types, macros, type conversions,
+              string utilities, file utilities, a main loop abstraction, and so on.
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
+    </para>
+  </part>
+
+  <part id="garcon-menus">
+    <title>Menus and Menu Items</title>
+    <xi:include href="xml/garcon-menu.xml"/>
+    <xi:include href="xml/garcon-menu-directory.xml"/>
+    <xi:include href="xml/garcon-menu-element.xml"/>
+    <xi:include href="xml/garcon-menu-item.xml"/>
+    <xi:include href="xml/garcon-menu-item-cache.xml"/>
+    <xi:include href="xml/garcon-menu-item-pool.xml"/>
+    <xi:include href="xml/garcon-menu-separator.xml"/>
+  </part>
+
+  <part id="garcon-parsing">
+    <title>Parsing and Modifying the Menu Tree</title>
+    <xi:include href="xml/garcon-menu-merger.xml"/>
+    <xi:include href="xml/garcon-menu-node.xml"/>
+    <xi:include href="xml/garcon-menu-parser.xml"/>
+    <xi:include href="xml/garcon-menu-tree-provider.xml"/>
+  </part>
+
+  <part id="garcon-monitoring">
+    <title>Monitoring</title>
+    <xi:include href="xml/garcon-menu-monitor.xml"/>
+  </part>
+
+  <part id="garcon-miscellaneous">
+    <title>Miscellaneous</title>
+    <xi:include href="xml/garcon-environment.xml"/>
+    <xi:include href="xml/garcon.xml"/>
+    <xi:include href="xml/garcon-gio.xml"/>
+    <xi:include href="xml/garcon-config.xml"/>
+  </part>
+
+  <part id="object-tree">
+    <title>Object Hierarchy</title>
+    <xi:include href="xml/tree_index.sgml"/>
+  </part>
+
+  <index id="api-index-full">
+    <title>API Index</title>
+    <xi:include href="xml/api-index-full.xml">
+      <xi:fallback />
+    </xi:include>
+  </index>
+
+  <xi:include href="xml/annotation-glossary.xml">
+    <xi:fallback />
+  </xi:include>
+</book>
diff --git a/docs/reference/libxfce4menu-overrides.txt b/docs/reference/garcon-overrides.txt
similarity index 100%
rename from docs/reference/libxfce4menu-overrides.txt
rename to docs/reference/garcon-overrides.txt
diff --git a/docs/reference/garcon-sections.txt b/docs/reference/garcon-sections.txt
new file mode 100644
index 0000000..c91d5e7
--- /dev/null
+++ b/docs/reference/garcon-sections.txt
@@ -0,0 +1,317 @@
+<SECTION>
+<FILE>garcon-menu</FILE>
+GarconMenuPrivate
+garcon_menu_new
+garcon_menu_new_for_file
+garcon_menu_new_applications
+garcon_menu_load
+garcon_menu_get_file
+garcon_menu_get_directory
+garcon_menu_get_menus
+garcon_menu_get_menu_with_name
+garcon_menu_get_parent
+garcon_menu_get_elements
+<TITLE>GarconMenu</TITLE>
+GarconMenu
+<SUBSECTION Standard>
+GARCON_MENU
+GARCON_IS_MENU
+GARCON_TYPE_MENU
+garcon_menu_get_type
+GARCON_MENU_CLASS
+GARCON_IS_MENU_CLASS
+GARCON_MENU_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-element</FILE>
+GarconMenuElement
+GarconMenuElementIface
+garcon_menu_element_get_name
+garcon_menu_element_get_comment
+garcon_menu_element_get_icon_name
+garcon_menu_element_get_visible
+garcon_menu_element_get_show_in_environment
+garcon_menu_element_get_no_display
+<SUBSECTION Standard>
+GARCON_MENU_ELEMENT
+GARCON_IS_MENU_ELEMENT
+GARCON_TYPE_MENU_ELEMENT
+garcon_menu_element_get_type
+GARCON_MENU_ELEMENT_GET_IFACE
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-item</FILE>
+GarconMenuItemPrivate
+GarconMenuItemClass
+GarconMenuItem
+garcon_menu_item_new
+garcon_menu_item_get_desktop_id
+garcon_menu_item_set_desktop_id
+garcon_menu_item_get_filename
+garcon_menu_item_set_filename
+garcon_menu_item_get_command
+garcon_menu_item_set_command
+garcon_menu_item_get_try_exec
+garcon_menu_item_set_try_exec
+garcon_menu_item_get_name
+garcon_menu_item_set_name
+garcon_menu_item_get_generic_name
+garcon_menu_item_set_generic_name
+garcon_menu_item_get_comment
+garcon_menu_item_set_comment
+garcon_menu_item_get_icon_name
+garcon_menu_item_set_icon_name
+garcon_menu_item_get_path
+garcon_menu_item_set_path
+garcon_menu_item_requires_terminal
+garcon_menu_item_set_requires_terminal
+garcon_menu_item_get_no_display
+garcon_menu_item_set_no_display
+garcon_menu_item_supports_startup_notification
+garcon_menu_item_set_supports_startup_notification
+garcon_menu_item_get_categories
+garcon_menu_item_set_categories
+garcon_menu_item_has_category
+garcon_menu_item_get_show_in_environment
+garcon_menu_item_only_show_in_environment
+garcon_menu_item_ref
+garcon_menu_item_unref
+garcon_menu_item_get_allocated
+garcon_menu_item_increment_allocated
+garcon_menu_item_decrement_allocated
+<SUBSECTION Standard>
+GARCON_MENU_ITEM
+GARCON_IS_MENU_ITEM
+GARCON_TYPE_MENU_ITEM
+garcon_menu_item_get_type
+GARCON_MENU_ITEM_CLASS
+GARCON_IS_MENU_ITEM_CLASS
+GARCON_MENU_ITEM_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-directory</FILE>
+GarconMenuDirectoryPrivate
+GarconMenuDirectoryClass
+GarconMenuDirectory
+garcon_menu_directory_get_file
+garcon_menu_directory_get_name
+garcon_menu_directory_set_name
+garcon_menu_directory_get_comment
+garcon_menu_directory_set_comment
+garcon_menu_directory_get_icon
+garcon_menu_directory_set_icon
+garcon_menu_directory_get_no_display
+garcon_menu_directory_set_no_display
+garcon_menu_directory_get_hidden
+garcon_menu_directory_get_show_in_environment
+garcon_menu_directory_get_visible
+garcon_menu_directory_equal
+<SUBSECTION Standard>
+GARCON_MENU_DIRECTORY
+GARCON_IS_MENU_DIRECTORY
+GARCON_TYPE_MENU_DIRECTORY
+garcon_menu_directory_get_type
+GARCON_MENU_DIRECTORY_CLASS
+GARCON_IS_MENU_DIRECTORY_CLASS
+GARCON_MENU_DIRECTORY_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-item-cache</FILE>
+GarconMenuItemCachePrivate
+GarconMenuItemCacheClass
+GarconMenuItemCache
+garcon_menu_item_cache_get_default
+garcon_menu_item_cache_lookup
+garcon_menu_item_cache_foreach
+garcon_menu_item_cache_invalidate
+<SUBSECTION Standard>
+GARCON_MENU_ITEM_CACHE
+GARCON_IS_MENU_ITEM_CACHE
+GARCON_TYPE_MENU_ITEM_CACHE
+garcon_menu_item_cache_get_type
+GARCON_MENU_ITEM_CACHE_CLASS
+GARCON_IS_MENU_ITEM_CACHE_CLASS
+GARCON_MENU_ITEM_CACHE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-parser</FILE>
+GarconMenuParserPrivate
+garcon_menu_parser_new
+garcon_menu_parser_run
+<TITLE>GarconMenuParser</TITLE>
+GarconMenuParser
+<SUBSECTION Standard>
+GARCON_MENU_PARSER
+GARCON_IS_MENU_PARSER
+GARCON_TYPE_MENU_PARSER
+garcon_menu_parser_get_type
+GARCON_MENU_PARSER_CLASS
+GARCON_IS_MENU_PARSER_CLASS
+GARCON_MENU_PARSER_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-tree-provider</FILE>
+GarconMenuTreeProviderIface
+GarconMenuTreeProvider
+garcon_menu_tree_provider_get_tree
+garcon_menu_tree_provider_get_file
+<SUBSECTION Standard>
+GARCON_MENU_TREE_PROVIDER
+GARCON_IS_MENU_TREE_PROVIDER
+GARCON_TYPE_MENU_TREE_PROVIDER
+garcon_menu_tree_provider_get_type
+GARCON_MENU_TREE_PROVIDER_GET_IFACE
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-node</FILE>
+GarconMenuNodeType
+GarconMenuLayoutMergeType
+GarconMenuMergeFileType
+GarconMenuNodeClass
+GarconMenuNode
+garcon_menu_node_new
+garcon_menu_node_get_node_type
+garcon_menu_node_create
+garcon_menu_node_copy
+garcon_menu_node_get_string
+garcon_menu_node_set_string
+garcon_menu_node_get_merge_file_type
+garcon_menu_node_set_merge_file_type
+garcon_menu_node_get_merge_file_filename
+garcon_menu_node_set_merge_file_filename
+garcon_menu_node_tree_get_child_node
+garcon_menu_node_tree_get_child_nodes
+garcon_menu_node_tree_get_string_children
+garcon_menu_node_tree_get_boolean_child
+garcon_menu_node_tree_get_string_child
+garcon_menu_node_tree_rule_matches
+garcon_menu_node_tree_get_node_type
+garcon_menu_node_tree_get_string
+garcon_menu_node_tree_set_string
+garcon_menu_node_tree_get_layout_merge_type
+garcon_menu_node_tree_get_merge_file_type
+garcon_menu_node_tree_get_merge_file_filename
+garcon_menu_node_tree_set_merge_file_filename
+garcon_menu_node_tree_compare
+garcon_menu_node_tree_copy
+garcon_menu_node_tree_free
+garcon_menu_node_tree_free_data
+<SUBSECTION Standard>
+GARCON_MENU_NODE
+GARCON_IS_MENU_NODE
+GARCON_TYPE_MENU_NODE
+garcon_menu_node_get_type
+GARCON_MENU_NODE_CLASS
+GARCON_IS_MENU_NODE_CLASS
+GARCON_MENU_NODE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-separator</FILE>
+GarconMenuSeparatorClass
+GarconMenuSeparator
+garcon_menu_separator_get_default
+<SUBSECTION Standard>
+GARCON_MENU_SEPARATOR
+GARCON_IS_MENU_SEPARATOR
+GARCON_TYPE_MENU_SEPARATOR
+garcon_menu_separator_get_type
+GARCON_MENU_SEPARATOR_CLASS
+GARCON_IS_MENU_SEPARATOR_CLASS
+GARCON_MENU_SEPARATOR_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-item-pool</FILE>
+GarconMenuItemPoolPrivate
+GarconMenuItemPoolClass
+GarconMenuItemPool
+garcon_menu_item_pool_new
+garcon_menu_item_pool_insert
+garcon_menu_item_pool_lookup
+garcon_menu_item_pool_foreach
+garcon_menu_item_pool_apply_exclude_rule
+garcon_menu_item_pool_get_empty
+<SUBSECTION Standard>
+GARCON_MENU_ITEM_POOL
+GARCON_IS_MENU_ITEM_POOL
+GARCON_TYPE_MENU_ITEM_POOL
+garcon_menu_item_pool_get_type
+GARCON_MENU_ITEM_POOL_CLASS
+GARCON_IS_MENU_ITEM_POOL_CLASS
+GARCON_MENU_ITEM_POOL_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-merger</FILE>
+GarconMenuMergerPrivate
+garcon_menu_merger_new
+garcon_menu_merger_run
+<TITLE>GarconMenuMerger</TITLE>
+GarconMenuMerger
+<SUBSECTION Standard>
+GARCON_MENU_MERGER
+GARCON_IS_MENU_MERGER
+GARCON_TYPE_MENU_MERGER
+garcon_menu_merger_get_type
+GARCON_MENU_MERGER_CLASS
+GARCON_IS_MENU_MERGER_CLASS
+GARCON_MENU_MERGER_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>garcon-gio</FILE>
+g_file_new_for_unknown_input
+g_file_new_relative_to_file
+g_file_get_uri_relative_to_file
+</SECTION>
+
+<SECTION>
+<FILE>garcon-environment</FILE>
+garcon_set_environment
+garcon_get_environment
+</SECTION>
+
+<SECTION>
+<FILE>garcon-menu-monitor</FILE>
+GarconMenuMonitorFlags
+GarconMenuMonitorVTable
+garcon_menu_monitor_set_vtable
+garcon_menu_monitor_add_item
+garcon_menu_monitor_remove_item
+garcon_menu_monitor_add_directory
+garcon_menu_monitor_remove_directory
+garcon_menu_monitor_add_file
+garcon_menu_monitor_remove_file
+garcon_menu_monitor_set_flags
+garcon_menu_monitor_get_flags
+garcon_menu_monitor_has_flags
+</SECTION>
+
+<SECTION>
+<FILE>garcon-config</FILE>
+GARCON_MAJOR_VERSION
+GARCON_MINOR_VERSION
+GARCON_MICRO_VERSION
+GARCON_CHECK_VERSION
+garcon_major_version
+garcon_minor_version
+garcon_micro_version
+garcon_check_version
+</SECTION>
+
+<SECTION>
+<FILE>garcon</FILE>
+GARCON_INSIDE_GARCON_H
+garcon_init
+garcon_shutdown
+garcon_config_lookup
+</SECTION>
+
diff --git a/docs/reference/garcon.types b/docs/reference/garcon.types
new file mode 100644
index 0000000..ec7281c
--- /dev/null
+++ b/docs/reference/garcon.types
@@ -0,0 +1,11 @@
+garcon_menu_item_pool_get_type
+garcon_menu_directory_get_type
+garcon_menu_separator_get_type
+garcon_menu_get_type
+garcon_menu_parser_get_type
+garcon_menu_tree_provider_get_type
+garcon_menu_node_get_type
+garcon_menu_item_cache_get_type
+garcon_menu_element_get_type
+garcon_menu_item_get_type
+garcon_menu_merger_get_type
diff --git a/THANKS b/docs/reference/gdesktopmenu-overrides.txt
similarity index 100%
copy from THANKS
copy to docs/reference/gdesktopmenu-overrides.txt
diff --git a/docs/reference/gdesktopmenu-sections.txt b/docs/reference/gdesktopmenu-sections.txt
new file mode 100644
index 0000000..0097040
--- /dev/null
+++ b/docs/reference/gdesktopmenu-sections.txt
@@ -0,0 +1,317 @@
+<SECTION>
+<FILE>gdesktopmenuseparator</FILE>
+GDesktopMenuSeparatorClass
+GDesktopMenuSeparator
+g_desktop_menu_separator_get_default
+<SUBSECTION Standard>
+G_DESKTOP_MENU_SEPARATOR
+G_IS_DESKTOP_MENU_SEPARATOR
+G_TYPE_DESKTOP_MENU_SEPARATOR
+g_desktop_menu_separator_get_type
+G_DESKTOP_MENU_SEPARATOR_CLASS
+G_IS_DESKTOP_MENU_SEPARATOR_CLASS
+G_DESKTOP_MENU_SEPARATOR_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenuparser</FILE>
+GDesktopMenuParserPrivate
+g_desktop_menu_parser_new
+g_desktop_menu_parser_run
+<TITLE>GDesktopMenuParser</TITLE>
+GDesktopMenuParser
+<SUBSECTION Standard>
+G_DESKTOP_MENU_PARSER
+G_IS_DESKTOP_MENU_PARSER
+G_TYPE_DESKTOP_MENU_PARSER
+g_desktop_menu_parser_get_type
+G_DESKTOP_MENU_PARSER_CLASS
+G_IS_DESKTOP_MENU_PARSER_CLASS
+G_DESKTOP_MENU_PARSER_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenuitempool</FILE>
+GDesktopMenuItemPoolPrivate
+GDesktopMenuItemPoolClass
+GDesktopMenuItemPool
+g_desktop_menu_item_pool_new
+g_desktop_menu_item_pool_insert
+g_desktop_menu_item_pool_lookup
+g_desktop_menu_item_pool_foreach
+g_desktop_menu_item_pool_apply_exclude_rule
+g_desktop_menu_item_pool_get_empty
+<SUBSECTION Standard>
+G_DESKTOP_MENU_ITEM_POOL
+G_IS_DESKTOP_MENU_ITEM_POOL
+G_TYPE_DESKTOP_MENU_ITEM_POOL
+g_desktop_menu_item_pool_get_type
+G_DESKTOP_MENU_ITEM_POOL_CLASS
+G_IS_DESKTOP_MENU_ITEM_POOL_CLASS
+G_DESKTOP_MENU_ITEM_POOL_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenunode</FILE>
+GDesktopMenuNodeType
+GDesktopMenuLayoutMergeType
+GDesktopMenuMergeFileType
+GDesktopMenuNodeClass
+GDesktopMenuNode
+g_desktop_menu_node_new
+g_desktop_menu_node_get_node_type
+g_desktop_menu_node_create
+g_desktop_menu_node_copy
+g_desktop_menu_node_get_string
+g_desktop_menu_node_set_string
+g_desktop_menu_node_get_merge_file_type
+g_desktop_menu_node_set_merge_file_type
+g_desktop_menu_node_get_merge_file_filename
+g_desktop_menu_node_set_merge_file_filename
+g_desktop_menu_node_tree_get_child_node
+g_desktop_menu_node_tree_get_child_nodes
+g_desktop_menu_node_tree_get_string_children
+g_desktop_menu_node_tree_get_boolean_child
+g_desktop_menu_node_tree_get_string_child
+g_desktop_menu_node_tree_rule_matches
+g_desktop_menu_node_tree_get_node_type
+g_desktop_menu_node_tree_get_string
+g_desktop_menu_node_tree_set_string
+g_desktop_menu_node_tree_get_layout_merge_type
+g_desktop_menu_node_tree_get_merge_file_type
+g_desktop_menu_node_tree_get_merge_file_filename
+g_desktop_menu_node_tree_set_merge_file_filename
+g_desktop_menu_node_tree_compare
+g_desktop_menu_node_tree_copy
+g_desktop_menu_node_tree_free
+g_desktop_menu_node_tree_free_data
+<SUBSECTION Standard>
+G_DESKTOP_MENU_NODE
+G_IS_DESKTOP_MENU_NODE
+G_TYPE_DESKTOP_MENU_NODE
+g_desktop_menu_node_get_type
+G_DESKTOP_MENU_NODE_CLASS
+G_IS_DESKTOP_MENU_NODE_CLASS
+G_DESKTOP_MENU_NODE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenutreeprovider</FILE>
+GDesktopMenuTreeProviderIface
+GDesktopMenuTreeProvider
+g_desktop_menu_tree_provider_get_tree
+g_desktop_menu_tree_provider_get_file
+<SUBSECTION Standard>
+G_DESKTOP_MENU_TREE_PROVIDER
+G_IS_DESKTOP_MENU_TREE_PROVIDER
+G_TYPE_DESKTOP_MENU_TREE_PROVIDER
+g_desktop_menu_tree_provider_get_type
+G_DESKTOP_MENU_TREE_PROVIDER_GET_IFACE
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenumerger</FILE>
+GDesktopMenuMergerPrivate
+g_desktop_menu_merger_new
+g_desktop_menu_merger_run
+<TITLE>GDesktopMenuMerger</TITLE>
+GDesktopMenuMerger
+<SUBSECTION Standard>
+G_DESKTOP_MENU_MERGER
+G_IS_DESKTOP_MENU_MERGER
+G_TYPE_DESKTOP_MENU_MERGER
+g_desktop_menu_merger_get_type
+G_DESKTOP_MENU_MERGER_CLASS
+G_IS_DESKTOP_MENU_MERGER_CLASS
+G_DESKTOP_MENU_MERGER_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenuelement</FILE>
+GDesktopMenuElement
+GDesktopMenuElementIface
+g_desktop_menu_element_get_name
+g_desktop_menu_element_get_comment
+g_desktop_menu_element_get_icon_name
+g_desktop_menu_element_get_visible
+g_desktop_menu_element_get_show_in_environment
+g_desktop_menu_element_get_no_display
+<SUBSECTION Standard>
+G_DESKTOP_MENU_ELEMENT
+G_IS_DESKTOP_MENU_ELEMENT
+G_TYPE_DESKTOP_MENU_ELEMENT
+g_desktop_menu_element_get_type
+G_DESKTOP_MENU_ELEMENT_GET_IFACE
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenuitemcache</FILE>
+GDesktopMenuItemCachePrivate
+GDesktopMenuItemCacheClass
+GDesktopMenuItemCache
+g_desktop_menu_item_cache_get_default
+g_desktop_menu_item_cache_lookup
+g_desktop_menu_item_cache_foreach
+g_desktop_menu_item_cache_invalidate
+<SUBSECTION Standard>
+G_DESKTOP_MENU_ITEM_CACHE
+G_IS_DESKTOP_MENU_ITEM_CACHE
+G_TYPE_DESKTOP_MENU_ITEM_CACHE
+g_desktop_menu_item_cache_get_type
+G_DESKTOP_MENU_ITEM_CACHE_CLASS
+G_IS_DESKTOP_MENU_ITEM_CACHE_CLASS
+G_DESKTOP_MENU_ITEM_CACHE_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenu</FILE>
+GDESKTOPMENU_INSIDE_GDESKTOPMENU_H
+GDesktopMenuPrivate
+GDesktopMenuClass
+GDesktopMenu
+g_desktop_menu_new
+g_desktop_menu_new_for_file
+g_desktop_menu_new_applications
+g_desktop_menu_load
+g_desktop_menu_get_file
+g_desktop_menu_get_directory
+g_desktop_menu_get_menus
+g_desktop_menu_get_menu_with_name
+g_desktop_menu_get_parent
+g_desktop_menu_get_elements
+<SUBSECTION Standard>
+G_DESKTOP_MENU
+G_IS_DESKTOP_MENU
+g_desktop_menu_get_type
+G_DESKTOP_MENU_CLASS
+G_IS_DESKTOP_MENU_CLASS
+G_DESKTOP_MENU_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenudirectory</FILE>
+GDesktopMenuDirectoryPrivate
+GDesktopMenuDirectoryClass
+GDesktopMenuDirectory
+g_desktop_menu_directory_get_file
+g_desktop_menu_directory_get_name
+g_desktop_menu_directory_set_name
+g_desktop_menu_directory_get_comment
+g_desktop_menu_directory_set_comment
+g_desktop_menu_directory_get_icon
+g_desktop_menu_directory_set_icon
+g_desktop_menu_directory_get_no_display
+g_desktop_menu_directory_set_no_display
+g_desktop_menu_directory_get_hidden
+g_desktop_menu_directory_get_show_in_environment
+g_desktop_menu_directory_get_visible
+g_desktop_menu_directory_equal
+<SUBSECTION Standard>
+G_DESKTOP_MENU_DIRECTORY
+G_IS_DESKTOP_MENU_DIRECTORY
+G_TYPE_DESKTOP_MENU_DIRECTORY
+g_desktop_menu_directory_get_type
+G_DESKTOP_MENU_DIRECTORY_CLASS
+G_IS_DESKTOP_MENU_DIRECTORY_CLASS
+G_DESKTOP_MENU_DIRECTORY_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenuitem</FILE>
+GDesktopMenuItemPrivate
+GDesktopMenuItemClass
+GDesktopMenuItem
+g_desktop_menu_item_new
+g_desktop_menu_item_get_desktop_id
+g_desktop_menu_item_set_desktop_id
+g_desktop_menu_item_get_filename
+g_desktop_menu_item_set_filename
+g_desktop_menu_item_get_command
+g_desktop_menu_item_set_command
+g_desktop_menu_item_get_try_exec
+g_desktop_menu_item_set_try_exec
+g_desktop_menu_item_get_name
+g_desktop_menu_item_set_name
+g_desktop_menu_item_get_generic_name
+g_desktop_menu_item_set_generic_name
+g_desktop_menu_item_get_comment
+g_desktop_menu_item_set_comment
+g_desktop_menu_item_get_icon_name
+g_desktop_menu_item_set_icon_name
+g_desktop_menu_item_get_path
+g_desktop_menu_item_set_path
+g_desktop_menu_item_requires_terminal
+g_desktop_menu_item_set_requires_terminal
+g_desktop_menu_item_get_no_display
+g_desktop_menu_item_set_no_display
+g_desktop_menu_item_supports_startup_notification
+g_desktop_menu_item_set_supports_startup_notification
+g_desktop_menu_item_get_categories
+g_desktop_menu_item_set_categories
+g_desktop_menu_item_has_category
+g_desktop_menu_item_get_show_in_environment
+g_desktop_menu_item_only_show_in_environment
+g_desktop_menu_item_ref
+g_desktop_menu_item_unref
+g_desktop_menu_item_get_allocated
+g_desktop_menu_item_increment_allocated
+g_desktop_menu_item_decrement_allocated
+<SUBSECTION Standard>
+G_DESKTOP_MENU_ITEM
+G_IS_DESKTOP_MENU_ITEM
+G_TYPE_DESKTOP_MENU_ITEM
+g_desktop_menu_item_get_type
+G_DESKTOP_MENU_ITEM_CLASS
+G_IS_DESKTOP_MENU_ITEM_CLASS
+G_DESKTOP_MENU_ITEM_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenumonitor</FILE>
+GDesktopMenuMonitorFlags
+GDesktopMenuMonitorVTable
+g_desktop_menu_monitor_set_vtable
+g_desktop_menu_monitor_add_item
+g_desktop_menu_monitor_remove_item
+g_desktop_menu_monitor_add_directory
+g_desktop_menu_monitor_remove_directory
+g_desktop_menu_monitor_add_file
+g_desktop_menu_monitor_remove_file
+g_desktop_menu_monitor_set_flags
+g_desktop_menu_monitor_get_flags
+g_desktop_menu_monitor_has_flags
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenumain</FILE>
+g_desktop_menu_init
+g_desktop_menu_shutdown
+g_desktop_menu_config_lookup
+G_TYPE_DESKTOP_MENU
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenuenvironment</FILE>
+g_desktop_menu_set_environment
+g_desktop_menu_get_environment
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenugio</FILE>
+g_file_new_for_unknown_input
+g_file_new_relative_to_file
+g_file_get_uri_relative_to_file
+</SECTION>
+
+<SECTION>
+<FILE>gdesktopmenu-config</FILE>
+GDESKTOPMENU_MAJOR_VERSION
+GDESKTOPMENU_MINOR_VERSION
+GDESKTOPMENU_MICRO_VERSION
+GDESKTOPMENU_CHECK_VERSION
+gdesktopmenu_major_version
+gdesktopmenu_minor_version
+gdesktopmenu_micro_version
+gdesktopmenu_check_version
+</SECTION>
+
diff --git a/docs/reference/gdesktopmenu.types b/docs/reference/gdesktopmenu.types
new file mode 100644
index 0000000..1271757
--- /dev/null
+++ b/docs/reference/gdesktopmenu.types
@@ -0,0 +1,11 @@
+g_desktop_menu_item_pool_get_type
+g_desktop_menu_directory_get_type
+g_desktop_menu_separator_get_type
+g_desktop_menu_get_type
+g_desktop_menu_parser_get_type
+g_desktop_menu_tree_provider_get_type
+g_desktop_menu_node_get_type
+g_desktop_menu_item_cache_get_type
+g_desktop_menu_element_get_type
+g_desktop_menu_item_get_type
+g_desktop_menu_merger_get_type
diff --git a/docs/reference/libxfce4menu-docs.sgml b/docs/reference/libxfce4menu-docs.sgml
deleted file mode 100644
index bb6b62f..0000000
--- a/docs/reference/libxfce4menu-docs.sgml
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
-               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-
-<!ENTITY libxfce4menu-config SYSTEM "xml/libxfce4menu-config.xml">
-<!ENTITY xfce-menu SYSTEM "xml/xfce-menu.xml">
-<!ENTITY xfce-menu-and-rules SYSTEM "xml/xfce-menu-and-rules.xml">
-<!ENTITY xfce-menu-directory SYSTEM "xml/xfce-menu-directory.xml">
-<!ENTITY xfce-menu-element SYSTEM "xml/xfce-menu-element.xml">
-<!ENTITY xfce-menu-environment SYSTEM "xml/xfce-menu-environment.xml">
-<!ENTITY xfce-menu-init-shutdown SYSTEM "xml/xfce-menu-init-shutdown.xml">
-<!ENTITY xfce-menu-item SYSTEM "xml/xfce-menu-item.xml">
-<!ENTITY xfce-menu-item-cache SYSTEM "xml/xfce-menu-item-cache.xml">
-<!ENTITY xfce-menu-item-pool SYSTEM "xml/xfce-menu-item-pool.xml">
-<!ENTITY xfce-menu-layout SYSTEM "xml/xfce-menu-layout.xml">
-<!ENTITY xfce-menu-monitor SYSTEM "xml/xfce-menu-monitor.xml">
-<!ENTITY xfce-menu-move SYSTEM "xml/xfce-menu-move.xml">
-<!ENTITY xfce-menu-not-rules SYSTEM "xml/xfce-menu-not-rules.xml">
-<!ENTITY xfce-menu-or-rules SYSTEM "xml/xfce-menu-or-rules.xml">
-<!ENTITY xfce-menu-rules SYSTEM "xml/xfce-menu-rules.xml">
-<!ENTITY xfce-menu-separator SYSTEM "xml/xfce-menu-separator.xml">
-<!ENTITY xfce-menu-standard-rules SYSTEM "xml/xfce-menu-standard-rules.xml">
-
-]>
-
-<book id="index">
-  <bookinfo>
-    <title>libxfce4menu Reference Manual</title>
-    <pubdate>March 2007</pubdate>
-
-    <copyright>
-      <year>2006</year>
-      <year>2007</year>
-      <holder>Jannis Pohlmann</holder>
-    </copyright>
-
-    <legalnotice id="legalnotice">
-      <para>
-        Permission is granted to copy, distribute and/or modify this document
-        under the terms of the GNU Free Documentation License, Version 1.1 or
-        any later version published by the Free Software Foundation; with no
-        Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
-        Texts. The complete license text is available from the <ulink
-        type="http" url="http://www.gnu.org/">Free Software Foundation</ulink>.
-      </para>
-    </legalnotice> 
-
-    <authorgroup>
-      <author>
-        <firstname>Jannis</firstname>
-        <surname>Pohlmann</surname>
-        <affiliation>
-          <address><email>jannis at xfce.org</email></address>
-        </affiliation>
-      </author>
-    </authorgroup>
-  </bookinfo>
-
-  <part id="introduction">
-    <title>Introduction</title>
-    <para>
-      libxfce4menu is a 
-      <ulink url="http://freedesktop.org">freedesktop.org</ulink> compliant 
-      menu library written for <ulink url="http://xfce.org">Xfce</ulink>. It 
-      implements the 
-      <ulink url="http://standards.freedesktop.org/menu-spec/1.0/">Desktop Menu
-      Specification</ulink> version 1.0.
-    </para>
-  </part>
-
-  <part id="fundamentals">
-    <title>Fundamentals</title>
-    &xfce-menu-init-shutdown;
-    &xfce-menu-environment;
-    &libxfce4menu-config;
-  </part>
-
-  <part id="menus">
-    <title>Menus</title>
-    &xfce-menu;
-    &xfce-menu-directory;
-    &xfce-menu-item;
-    &xfce-menu-separator;
-    &xfce-menu-element;
-  </part>
-
-  <part id="utilities">
-    <title>Utilities</title>
-    &xfce-menu-monitor;
-  </part>
-
-  <part id="internals">
-    <title>Internals</title>
-    <chapter id="layout">
-      <title>Layout</title>
-      &xfce-menu-layout;
-    </chapter>
-    <chapter id="items">
-      <title>Menu Items</title>
-      &xfce-menu-item-pool;
-      &xfce-menu-item-cache;
-    </chapter>
-    <chapter id="rules">
-      <title>Include and Exclude Rules</title>
-      &xfce-menu-rules;
-      &xfce-menu-standard-rules;
-      &xfce-menu-or-rules;
-      &xfce-menu-and-rules;
-      &xfce-menu-not-rules;
-    </chapter>
-    <chapter id="move">
-      <title>Move Instructions</title>
-      &xfce-menu-move;
-    </chapter>
-  </part>
-
-  <index>
-    <title>Index</title>
-  </index>
-</book>
-
-<!--
-  vi:set ts=2 sw=2 et ai syntax=docbkxml:
--->
diff --git a/docs/reference/libxfce4menu-sections.txt b/docs/reference/libxfce4menu-sections.txt
deleted file mode 100644
index c61d0c4..0000000
--- a/docs/reference/libxfce4menu-sections.txt
+++ /dev/null
@@ -1,351 +0,0 @@
-<INCLUDE>libxfce4menu/libxfce4menu.h</INCLUDE>
-
-<SECTION>
-<FILE>xfce-menu-and-rules</FILE>
-<TITLE>XfceMenuAndRules</TITLE>
-XfceMenuAndRules
-XfceMenuAndRulesClass
-xfce_menu_and_rules_new
-<SUBSECTION Standard>
-XFCE_MENU_AND_RULES
-XFCE_IS_MENU_AND_RULES
-XFCE_TYPE_MENU_AND_RULES
-xfce_menu_and_rules_get_type
-XFCE_MENU_AND_RULES_CLASS
-XFCE_IS_MENU_AND_RULES_CLASS
-XFCE_MENU_AND_RULES_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-directory</FILE>
-<TITLE>XfceMenuDirectory</TITLE>
-XfceMenuDirectoryPrivate
-XfceMenuDirectoryClass
-XfceMenuDirectory
-xfce_menu_directory_get_filename
-xfce_menu_directory_set_filename
-xfce_menu_directory_get_name
-xfce_menu_directory_set_name
-xfce_menu_directory_get_comment
-xfce_menu_directory_set_comment
-xfce_menu_directory_get_icon
-xfce_menu_directory_set_icon
-xfce_menu_directory_get_no_display
-xfce_menu_directory_set_no_display
-xfce_menu_directory_get_hidden
-xfce_menu_directory_show_in_environment
-<SUBSECTION Standard>
-XFCE_MENU_DIRECTORY
-XFCE_IS_MENU_DIRECTORY
-XFCE_TYPE_MENU_DIRECTORY
-xfce_menu_directory_get_type
-XFCE_MENU_DIRECTORY_CLASS
-XFCE_IS_MENU_DIRECTORY_CLASS
-XFCE_MENU_DIRECTORY_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-element</FILE>
-<TITLE>XfceMenuElement</TITLE>
-XfceMenuElement
-XfceMenuElementIface
-xfce_menu_element_get_name
-xfce_menu_element_get_icon_name
-<SUBSECTION Standard>
-XFCE_MENU_ELEMENT
-XFCE_IS_MENU_ELEMENT
-XFCE_TYPE_MENU_ELEMENT
-xfce_menu_element_get_type
-XFCE_MENU_ELEMENT_GET_IFACE
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu</FILE>
-<TITLE>XfceMenu</TITLE>
-XfceMenuPrivate
-XfceMenuClass
-XfceMenu
-xfce_menu_get_root
-xfce_menu_new
-xfce_menu_get_filename
-xfce_menu_set_filename
-xfce_menu_get_name
-xfce_menu_set_name
-xfce_menu_get_directory
-xfce_menu_set_directory
-xfce_menu_get_directory_dirs
-xfce_menu_get_legacy_dirs
-xfce_menu_get_app_dirs
-xfce_menu_get_only_unallocated
-xfce_menu_set_only_unallocated
-xfce_menu_get_deleted
-xfce_menu_set_deleted
-xfce_menu_get_menus
-xfce_menu_add_menu
-xfce_menu_get_menu_with_name
-xfce_menu_get_parent
-xfce_menu_get_item_pool
-xfce_menu_get_items
-xfce_menu_has_layout
-xfce_menu_get_layout_elements
-<SUBSECTION Standard>
-XFCE_MENU
-XFCE_IS_MENU
-XFCE_TYPE_MENU
-xfce_menu_get_type
-XFCE_MENU_CLASS
-XFCE_IS_MENU_CLASS
-XFCE_MENU_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-item-cache</FILE>
-<TITLE>XfceMenuItemCache</TITLE>
-XfceMenuItemCachePrivate
-XfceMenuItemCacheClass
-XfceMenuItemCache
-xfce_menu_item_cache_get_default
-xfce_menu_item_cache_lookup
-xfce_menu_item_cache_foreach
-<SUBSECTION Standard>
-XFCE_MENU_ITEM_CACHE
-XFCE_IS_MENU_ITEM_CACHE
-XFCE_TYPE_MENU_ITEM_CACHE
-xfce_menu_item_cache_get_type
-XFCE_MENU_ITEM_CACHE_CLASS
-XFCE_IS_MENU_ITEM_CACHE_CLASS
-XFCE_MENU_ITEM_CACHE_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-item</FILE>
-<TITLE>XfceMenuItem</TITLE>
-XfceMenuItemPrivate
-XfceMenuItemClass
-XfceMenuItem
-xfce_menu_item_new
-xfce_menu_item_get_desktop_id
-xfce_menu_item_set_desktop_id
-xfce_menu_item_get_filename
-xfce_menu_item_set_filename
-xfce_menu_item_get_command
-xfce_menu_item_set_command
-xfce_menu_item_get_try_exec
-xfce_menu_item_set_try_exec
-xfce_menu_item_get_name
-xfce_menu_item_set_name
-xfce_menu_item_get_icon_name
-xfce_menu_item_set_icon_name
-xfce_menu_item_requires_terminal
-xfce_menu_item_set_requires_terminal
-xfce_menu_item_get_no_display
-xfce_menu_item_set_no_display
-xfce_menu_item_supports_startup_notification
-xfce_menu_item_set_supports_startup_notification
-xfce_menu_item_get_categories
-xfce_menu_item_set_categories
-xfce_menu_item_show_in_environment
-xfce_menu_item_ref
-xfce_menu_item_unref
-xfce_menu_item_get_allocated
-xfce_menu_item_increment_allocated
-xfce_menu_item_decrement_allocated
-<SUBSECTION Standard>
-XFCE_MENU_ITEM
-XFCE_IS_MENU_ITEM
-XFCE_TYPE_MENU_ITEM
-xfce_menu_item_get_type
-XFCE_MENU_ITEM_CLASS
-XFCE_IS_MENU_ITEM_CLASS
-XFCE_MENU_ITEM_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-item-pool</FILE>
-<TITLE>XfceMenuItemPool</TITLE>
-XfceMenuItemPoolPrivate
-XfceMenuItemPoolClass
-XfceMenuItemPool
-xfce_menu_item_pool_new
-xfce_menu_item_pool_insert
-xfce_menu_item_pool_lookup
-xfce_menu_item_pool_foreach
-xfce_menu_item_pool_apply_exclude_rule
-xfce_menu_item_pool_get_empty
-<SUBSECTION Standard>
-XFCE_MENU_ITEM_POOL
-XFCE_IS_MENU_ITEM_POOL
-XFCE_TYPE_MENU_ITEM_POOL
-xfce_menu_item_pool_get_type
-XFCE_MENU_ITEM_POOL_CLASS
-XFCE_IS_MENU_ITEM_POOL_CLASS
-XFCE_MENU_ITEM_POOL_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-layout</FILE>
-<TITLE>XfceMenuLayout</TITLE>
-XfceMenuLayoutMergeType
-XfceMenuLayoutNodeType
-XfceMenuLayoutNode
-XfceMenuLayoutPrivate
-XfceMenuLayoutClass
-XfceMenuLayout
-xfce_menu_layout_new
-xfce_menu_layout_add_filename
-xfce_menu_layout_add_menuname
-xfce_menu_layout_add_separator
-xfce_menu_layout_add_merge
-xfce_menu_layout_get_nodes
-xfce_menu_layout_get_filename_used
-xfce_menu_layout_get_menuname_used
-xfce_menu_layout_node_get_type
-xfce_menu_layout_node_get_filename
-xfce_menu_layout_node_get_menuname
-xfce_menu_layout_node_get_merge_type
-<SUBSECTION Standard>
-XFCE_MENU_LAYOUT
-XFCE_IS_MENU_LAYOUT
-XFCE_TYPE_MENU_LAYOUT
-xfce_menu_layout_get_type
-XFCE_MENU_LAYOUT_CLASS
-XFCE_IS_MENU_LAYOUT_CLASS
-XFCE_MENU_LAYOUT_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-monitor</FILE>
-<TITLE>Monitoring</TITLE>
-XfceMenuMonitorVTable
-xfce_menu_monitor_set_vtable
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-move</FILE>
-<TITLE>XfceMenuMove</TITLE>
-XfceMenuMoveClass
-XfceMenuMove
-xfce_menu_move_new
-xfce_menu_move_get_old
-xfce_menu_move_set_old
-xfce_menu_move_get_new
-xfce_menu_move_set_new
-<SUBSECTION Standard>
-XFCE_MENU_MOVE
-XFCE_IS_MENU_MOVE
-XFCE_TYPE_MENU_MOVE
-xfce_menu_move_get_type
-XFCE_MENU_MOVE_CLASS
-XFCE_IS_MENU_MOVE_CLASS
-XFCE_MENU_MOVE_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-not-rules</FILE>
-<TITLE>XfceMenuNotRules</TITLE>
-XfceMenuNotRules
-XfceMenuNotRulesClass
-xfce_menu_not_rules_new
-<SUBSECTION Standard>
-XFCE_MENU_NOT_RULES
-XFCE_IS_MENU_NOT_RULES
-XFCE_TYPE_MENU_NOT_RULES
-xfce_menu_not_rules_get_type
-XFCE_MENU_NOT_RULES_CLASS
-XFCE_IS_MENU_NOT_RULES_CLASS
-XFCE_MENU_NOT_RULES_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-or-rules</FILE>
-<TITLE>XfceMenuOrRules</TITLE>
-XfceMenuOrRules
-XfceMenuOrRulesClass
-xfce_menu_or_rules_new
-<SUBSECTION Standard>
-XFCE_MENU_OR_RULES
-XFCE_IS_MENU_OR_RULES
-XFCE_TYPE_MENU_OR_RULES
-xfce_menu_or_rules_get_type
-XFCE_MENU_OR_RULES_CLASS
-XFCE_IS_MENU_OR_RULES_CLASS
-XFCE_MENU_OR_RULES_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-rules</FILE>
-<TITLE>XfceMenuRules</TITLE>
-XfceMenuRules
-XfceMenuRulesIface
-xfce_menu_rules_match
-xfce_menu_rules_add_all
-xfce_menu_rules_add_rules
-xfce_menu_rules_add_filename
-xfce_menu_rules_add_category
-<SUBSECTION Standard>
-XFCE_MENU_RULES
-XFCE_IS_MENU_RULES
-XFCE_TYPE_MENU_RULES
-xfce_menu_rules_get_type
-XFCE_MENU_RULES_GET_IFACE
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-standard-rules</FILE>
-<TITLE>XfceMenuStandardRules</TITLE>
-XfceMenuStandardRules
-xfce_menu_standard_rules_get_include
-xfce_menu_standard_rules_set_include
-<SUBSECTION Standard>
-XFCE_MENU_STANDARD_RULES
-XFCE_IS_MENU_STANDARD_RULES
-XFCE_TYPE_MENU_STANDARD_RULES
-xfce_menu_standard_rules_get_type
-XFCE_MENU_STANDARD_RULES_CLASS
-XFCE_IS_MENU_STANDARD_RULES_CLASS
-XFCE_MENU_STANDARD_RULES_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-separator</FILE>
-<TITLE>XfceMenuSeparator</TITLE>
-XfceMenuSeparatorClass
-XfceMenuSeparator
-xfce_menu_separator_get_default
-<SUBSECTION Standard>
-XFCE_MENU_SEPARATOR
-XFCE_IS_MENU_SEPARATOR
-XFCE_TYPE_MENU_SEPARATOR
-xfce_menu_separator_get_type
-XFCE_MENU_SEPARATOR_CLASS
-XFCE_IS_MENU_SEPARATOR_CLASS
-XFCE_MENU_SEPARATOR_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-environment</FILE>
-<TITLE>Desktop Environment</TITLE>
-xfce_menu_set_environment
-xfce_menu_get_environment
-</SECTION>
-
-<SECTION>
-<FILE>libxfce4menu-config</FILE>
-<TITLE>Version Information</TITLE>
-LIBXFCE4MENU_MAJOR_VERSION
-LIBXFCE4MENU_MINOR_VERSION
-LIBXFCE4MENU_MICRO_VERSION
-LIBXFCE4MENU_CHECK_VERSION
-libxfce4menu_major_version
-libxfce4menu_minor_version
-libxfce4menu_micro_version
-libxfce4menu_check_version
-</SECTION>
-
-<SECTION>
-<FILE>xfce-menu-init-shutdown</FILE>
-<TITLE>Initialization and Shutdown</TITLE>
-xfce_menu_init
-xfce_menu_shutdown
-</SECTION>
-
diff --git a/docs/reference/libxfce4menu.types b/docs/reference/libxfce4menu.types
deleted file mode 100644
index c997268..0000000
--- a/docs/reference/libxfce4menu.types
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <libxfce4menu/libxfce4menu.h>
-
-xfce_menu_get_type
-xfce_menu_element_get_type
-xfce_menu_directory_get_type
-xfce_menu_item_get_type
-xfce_menu_item_pool_get_type
-xfce_menu_item_cache_get_type
-xfce_menu_rules_get_type
-xfce_menu_standard_rules_get_type
-xfce_menu_or_rules_get_type
-xfce_menu_and_rules_get_type
-xfce_menu_not_rules_get_type
-xfce_menu_layout_get_type
-xfce_menu_separator_get_type
diff --git a/docs/reference/tmpl/libxfce4menu-config.sgml b/docs/reference/tmpl/libxfce4menu-config.sgml
deleted file mode 100644
index fccbad7..0000000
--- a/docs/reference/tmpl/libxfce4menu-config.sgml
+++ /dev/null
@@ -1,79 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-Version Information
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### MACRO LIBXFCE4MENU_MAJOR_VERSION ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### MACRO LIBXFCE4MENU_MINOR_VERSION ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### MACRO LIBXFCE4MENU_MICRO_VERSION ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### MACRO LIBXFCE4MENU_CHECK_VERSION ##### -->
-<para>
-
-</para>
-
- at major: 
- at minor: 
- at micro: 
-
-
-<!-- ##### VARIABLE libxfce4menu_major_version ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### VARIABLE libxfce4menu_minor_version ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### VARIABLE libxfce4menu_micro_version ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION libxfce4menu_check_version ##### -->
-<para>
-
-</para>
-
- at required_major: 
- at required_minor: 
- at required_micro: 
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/libxfce4menu-unused.sgml b/docs/reference/tmpl/libxfce4menu-unused.sgml
deleted file mode 100644
index 49a1a68..0000000
--- a/docs/reference/tmpl/libxfce4menu-unused.sgml
+++ /dev/null
@@ -1,62 +0,0 @@
-<!-- ##### SECTION ./tmpl/config.sgml:Long_Description ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### SECTION ./tmpl/config.sgml:See_Also ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### SECTION ./tmpl/config.sgml:Short_Description ##### -->
-
-
-
-<!-- ##### SECTION ./tmpl/config.sgml:Stability_Level ##### -->
-
-
-
-<!-- ##### SECTION ./tmpl/config.sgml:Title ##### -->
-config
-
-
-<!-- ##### SECTION ./tmpl/libxfce4menu.sgml:Long_Description ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### SECTION ./tmpl/libxfce4menu.sgml:See_Also ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### SECTION ./tmpl/libxfce4menu.sgml:Short_Description ##### -->
-
-
-
-<!-- ##### SECTION ./tmpl/libxfce4menu.sgml:Stability_Level ##### -->
-
-
-
-<!-- ##### SECTION ./tmpl/libxfce4menu.sgml:Title ##### -->
-libxfce4menu
-
-
-<!-- ##### MACRO LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_get_layout_items ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
diff --git a/docs/reference/tmpl/libxfce4menu.sgml b/docs/reference/tmpl/libxfce4menu.sgml
deleted file mode 100644
index 659557a..0000000
--- a/docs/reference/tmpl/libxfce4menu.sgml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-libxfce4menu
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### MACRO LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H ##### -->
-<para>
-
-</para>
-
-
-
diff --git a/docs/reference/tmpl/xfce-menu-and-rules.sgml b/docs/reference/tmpl/xfce-menu-and-rules.sgml
deleted file mode 100644
index 7fcfe8c..0000000
--- a/docs/reference/tmpl/xfce-menu-and-rules.sgml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuAndRules
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuAndRules ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuAndRulesClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_and_rules_new ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-directory.sgml b/docs/reference/tmpl/xfce-menu-directory.sgml
deleted file mode 100644
index 9ef07da..0000000
--- a/docs/reference/tmpl/xfce-menu-directory.sgml
+++ /dev/null
@@ -1,170 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuDirectory
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuDirectoryPrivate ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuDirectoryClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuDirectory ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### ARG XfceMenuDirectory:comment ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuDirectory:filename ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuDirectory:icon ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuDirectory:name ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuDirectory:no-display ##### -->
-<para>
-
-</para>
-
-<!-- ##### FUNCTION xfce_menu_directory_get_filename ##### -->
-<para>
-
-</para>
-
- at directory: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_set_filename ##### -->
-<para>
-
-</para>
-
- at directory: 
- at name: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_get_name ##### -->
-<para>
-
-</para>
-
- at directory: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_set_name ##### -->
-<para>
-
-</para>
-
- at directory: 
- at name: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_get_comment ##### -->
-<para>
-
-</para>
-
- at directory: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_set_comment ##### -->
-<para>
-
-</para>
-
- at directory: 
- at comment: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_get_icon ##### -->
-<para>
-
-</para>
-
- at directory: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_set_icon ##### -->
-<para>
-
-</para>
-
- at directory: 
- at icon: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_get_no_display ##### -->
-<para>
-
-</para>
-
- at directory: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_set_no_display ##### -->
-<para>
-
-</para>
-
- at directory: 
- at no_display: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_get_hidden ##### -->
-<para>
-
-</para>
-
- at directory: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_directory_show_in_environment ##### -->
-<para>
-
-</para>
-
- at directory: 
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-element.sgml b/docs/reference/tmpl/xfce-menu-element.sgml
deleted file mode 100644
index 27fab9b..0000000
--- a/docs/reference/tmpl/xfce-menu-element.sgml
+++ /dev/null
@@ -1,52 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuElement
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuElement ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuElementIface ##### -->
-<para>
-
-</para>
-
- at __parent__: 
- at get_name: 
- at get_icon_name: 
-
-<!-- ##### FUNCTION xfce_menu_element_get_name ##### -->
-<para>
-
-</para>
-
- at element: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_element_get_icon_name ##### -->
-<para>
-
-</para>
-
- at element: 
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-environment.sgml b/docs/reference/tmpl/xfce-menu-environment.sgml
deleted file mode 100644
index 0420676..0000000
--- a/docs/reference/tmpl/xfce-menu-environment.sgml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-Desktop Environment
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### FUNCTION xfce_menu_set_environment ##### -->
-<para>
-
-</para>
-
- at env: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_environment ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-init-shutdown.sgml b/docs/reference/tmpl/xfce-menu-init-shutdown.sgml
deleted file mode 100644
index b024aa9..0000000
--- a/docs/reference/tmpl/xfce-menu-init-shutdown.sgml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-Initialization and Shutdown
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### FUNCTION xfce_menu_init ##### -->
-<para>
-
-</para>
-
- at env: 
-
-
-<!-- ##### FUNCTION xfce_menu_shutdown ##### -->
-<para>
-
-</para>
-
-
-
diff --git a/docs/reference/tmpl/xfce-menu-item-cache.sgml b/docs/reference/tmpl/xfce-menu-item-cache.sgml
deleted file mode 100644
index 3131835..0000000
--- a/docs/reference/tmpl/xfce-menu-item-cache.sgml
+++ /dev/null
@@ -1,66 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuItemCache
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuItemCachePrivate ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuItemCacheClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuItemCache ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_item_cache_get_default ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_cache_lookup ##### -->
-<para>
-
-</para>
-
- at cache: 
- at filename: 
- at desktop_id: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_cache_foreach ##### -->
-<para>
-
-</para>
-
- at cache: 
- at func: 
- at user_data: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-item-pool.sgml b/docs/reference/tmpl/xfce-menu-item-pool.sgml
deleted file mode 100644
index 9567a2f..0000000
--- a/docs/reference/tmpl/xfce-menu-item-pool.sgml
+++ /dev/null
@@ -1,92 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuItemPool
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuItemPoolPrivate ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuItemPoolClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuItemPool ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_item_pool_new ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_pool_insert ##### -->
-<para>
-
-</para>
-
- at pool: 
- at item: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_pool_lookup ##### -->
-<para>
-
-</para>
-
- at pool: 
- at desktop_id: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_pool_foreach ##### -->
-<para>
-
-</para>
-
- at pool: 
- at func: 
- at user_data: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_pool_apply_exclude_rule ##### -->
-<para>
-
-</para>
-
- at pool: 
- at rule: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_pool_get_empty ##### -->
-<para>
-
-</para>
-
- at pool: 
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-item.sgml b/docs/reference/tmpl/xfce-menu-item.sgml
deleted file mode 100644
index db83fab..0000000
--- a/docs/reference/tmpl/xfce-menu-item.sgml
+++ /dev/null
@@ -1,336 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuItem
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuItemPrivate ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuItemClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuItem ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### ARG XfceMenuItem:command ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:comment ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:desktop-id ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:filename ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:generic-name ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:icon-name ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:name ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:no-display ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:path ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:requires-terminal ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:supports-startup-notification ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenuItem:try-exec ##### -->
-<para>
-
-</para>
-
-<!-- ##### FUNCTION xfce_menu_item_new ##### -->
-<para>
-
-</para>
-
- at filename: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_desktop_id ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_desktop_id ##### -->
-<para>
-
-</para>
-
- at item: 
- at desktop_id: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_filename ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_filename ##### -->
-<para>
-
-</para>
-
- at item: 
- at filename: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_command ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_command ##### -->
-<para>
-
-</para>
-
- at item: 
- at command: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_try_exec ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_try_exec ##### -->
-<para>
-
-</para>
-
- at item: 
- at try_exec: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_name ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_name ##### -->
-<para>
-
-</para>
-
- at item: 
- at name: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_icon_name ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_icon_name ##### -->
-<para>
-
-</para>
-
- at item: 
- at icon_name: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_requires_terminal ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_requires_terminal ##### -->
-<para>
-
-</para>
-
- at item: 
- at requires_terminal: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_no_display ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_no_display ##### -->
-<para>
-
-</para>
-
- at item: 
- at no_display: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_supports_startup_notification ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_supports_startup_notification ##### -->
-<para>
-
-</para>
-
- at item: 
- at supports_startup_notification: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_categories ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_set_categories ##### -->
-<para>
-
-</para>
-
- at item: 
- at categories: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_show_in_environment ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_ref ##### -->
-<para>
-
-</para>
-
- at item: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_unref ##### -->
-<para>
-
-</para>
-
- at item: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_get_allocated ##### -->
-<para>
-
-</para>
-
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_increment_allocated ##### -->
-<para>
-
-</para>
-
- at item: 
-
-
-<!-- ##### FUNCTION xfce_menu_item_decrement_allocated ##### -->
-<para>
-
-</para>
-
- at item: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-layout.sgml b/docs/reference/tmpl/xfce-menu-layout.sgml
deleted file mode 100644
index cf9f6e6..0000000
--- a/docs/reference/tmpl/xfce-menu-layout.sgml
+++ /dev/null
@@ -1,171 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuLayout
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### ENUM XfceMenuLayoutMergeType ##### -->
-<para>
-
-</para>
-
- at XFCE_MENU_LAYOUT_MERGE_MENUS: 
- at XFCE_MENU_LAYOUT_MERGE_FILES: 
- at XFCE_MENU_LAYOUT_MERGE_ALL: 
-
-<!-- ##### ENUM XfceMenuLayoutNodeType ##### -->
-<para>
-
-</para>
-
- at XFCE_MENU_LAYOUT_NODE_INVALID: 
- at XFCE_MENU_LAYOUT_NODE_FILENAME: 
- at XFCE_MENU_LAYOUT_NODE_MENUNAME: 
- at XFCE_MENU_LAYOUT_NODE_SEPARATOR: 
- at XFCE_MENU_LAYOUT_NODE_MERGE: 
-
-<!-- ##### STRUCT XfceMenuLayoutNode ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuLayoutPrivate ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuLayoutClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuLayout ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_layout_new ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_add_filename ##### -->
-<para>
-
-</para>
-
- at layout: 
- at filename: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_add_menuname ##### -->
-<para>
-
-</para>
-
- at layout: 
- at menuname: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_add_separator ##### -->
-<para>
-
-</para>
-
- at layout: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_add_merge ##### -->
-<para>
-
-</para>
-
- at layout: 
- at type: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_get_nodes ##### -->
-<para>
-
-</para>
-
- at layout: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_get_filename_used ##### -->
-<para>
-
-</para>
-
- at layout: 
- at filename: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_get_menuname_used ##### -->
-<para>
-
-</para>
-
- at layout: 
- at menuname: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_node_get_type ##### -->
-<para>
-
-</para>
-
- at node: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_node_get_filename ##### -->
-<para>
-
-</para>
-
- at node: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_node_get_menuname ##### -->
-<para>
-
-</para>
-
- at node: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_layout_node_get_merge_type ##### -->
-<para>
-
-</para>
-
- at node: 
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-monitor.sgml b/docs/reference/tmpl/xfce-menu-monitor.sgml
deleted file mode 100644
index 0700232..0000000
--- a/docs/reference/tmpl/xfce-menu-monitor.sgml
+++ /dev/null
@@ -1,37 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-Monitoring
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuMonitorVTable ##### -->
-<para>
-
-</para>
-
- at monitor_file: 
- at monitor_directory: 
- at remove_monitor: 
-
-<!-- ##### FUNCTION xfce_menu_monitor_set_vtable ##### -->
-<para>
-
-</para>
-
- at vtable: 
- at user_data: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-move.sgml b/docs/reference/tmpl/xfce-menu-move.sgml
deleted file mode 100644
index 280b766..0000000
--- a/docs/reference/tmpl/xfce-menu-move.sgml
+++ /dev/null
@@ -1,75 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuMove
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuMoveClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuMove ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_move_new ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_move_get_old ##### -->
-<para>
-
-</para>
-
- at move: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_move_set_old ##### -->
-<para>
-
-</para>
-
- at move: 
- at old: 
-
-
-<!-- ##### FUNCTION xfce_menu_move_get_new ##### -->
-<para>
-
-</para>
-
- at move: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_move_set_new ##### -->
-<para>
-
-</para>
-
- at move: 
- at new: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-not-rules.sgml b/docs/reference/tmpl/xfce-menu-not-rules.sgml
deleted file mode 100644
index 287213a..0000000
--- a/docs/reference/tmpl/xfce-menu-not-rules.sgml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuNotRules
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuNotRules ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuNotRulesClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_not_rules_new ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-or-rules.sgml b/docs/reference/tmpl/xfce-menu-or-rules.sgml
deleted file mode 100644
index 1330dee..0000000
--- a/docs/reference/tmpl/xfce-menu-or-rules.sgml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuOrRules
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuOrRules ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuOrRulesClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_or_rules_new ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-rules.sgml b/docs/reference/tmpl/xfce-menu-rules.sgml
deleted file mode 100644
index fa19214..0000000
--- a/docs/reference/tmpl/xfce-menu-rules.sgml
+++ /dev/null
@@ -1,82 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuRules
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuRules ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuRulesIface ##### -->
-<para>
-
-</para>
-
- at __parent__: 
- at match: 
- at add_rules: 
- at add_all: 
- at add_filename: 
- at add_category: 
-
-<!-- ##### FUNCTION xfce_menu_rules_match ##### -->
-<para>
-
-</para>
-
- at rules: 
- at item: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_rules_add_all ##### -->
-<para>
-
-</para>
-
- at rules: 
-
-
-<!-- ##### FUNCTION xfce_menu_rules_add_rules ##### -->
-<para>
-
-</para>
-
- at rules: 
- at additional_rules: 
-
-
-<!-- ##### FUNCTION xfce_menu_rules_add_filename ##### -->
-<para>
-
-</para>
-
- at rules: 
- at filename: 
-
-
-<!-- ##### FUNCTION xfce_menu_rules_add_category ##### -->
-<para>
-
-</para>
-
- at rules: 
- at category: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-separator.sgml b/docs/reference/tmpl/xfce-menu-separator.sgml
deleted file mode 100644
index 940550c..0000000
--- a/docs/reference/tmpl/xfce-menu-separator.sgml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuSeparator
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuSeparatorClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuSeparator ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION xfce_menu_separator_get_default ##### -->
-<para>
-
-</para>
-
- at Returns: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu-standard-rules.sgml b/docs/reference/tmpl/xfce-menu-standard-rules.sgml
deleted file mode 100644
index 0123182..0000000
--- a/docs/reference/tmpl/xfce-menu-standard-rules.sgml
+++ /dev/null
@@ -1,48 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenuStandardRules
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuStandardRules ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### ARG XfceMenuStandardRules:include ##### -->
-<para>
-
-</para>
-
-<!-- ##### FUNCTION xfce_menu_standard_rules_get_include ##### -->
-<para>
-
-</para>
-
- at rules: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_standard_rules_set_include ##### -->
-<para>
-
-</para>
-
- at rules: 
- at include: 
-
-
diff --git a/docs/reference/tmpl/xfce-menu.sgml b/docs/reference/tmpl/xfce-menu.sgml
deleted file mode 100644
index c344bcc..0000000
--- a/docs/reference/tmpl/xfce-menu.sgml
+++ /dev/null
@@ -1,272 +0,0 @@
-<!-- ##### SECTION Title ##### -->
-XfceMenu
-
-<!-- ##### SECTION Short_Description ##### -->
-
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-XfceMenu is the most important part of libxfce4menu. In almost all use 
-cases the first thing to be created is an XfceMenu based on a filename.
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### SECTION Stability_Level ##### -->
-
-
-<!-- ##### STRUCT XfceMenuPrivate ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenuClass ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT XfceMenu ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### ARG XfceMenu:deleted ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenu:directory ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenu:filename ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenu:name ##### -->
-<para>
-
-</para>
-
-<!-- ##### ARG XfceMenu:only-unallocated ##### -->
-<para>
-
-</para>
-
-<!-- ##### FUNCTION xfce_menu_get_root ##### -->
-<para>
-
-</para>
-
- at error: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_new ##### -->
-<para>
-
-</para>
-
- at filename: 
- at error: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_filename ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_set_filename ##### -->
-<para>
-
-</para>
-
- at menu: 
- at filename: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_name ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_set_name ##### -->
-<para>
-
-</para>
-
- at menu: 
- at name: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_directory ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_set_directory ##### -->
-<para>
-
-</para>
-
- at menu: 
- at directory: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_directory_dirs ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_legacy_dirs ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_app_dirs ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_only_unallocated ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_set_only_unallocated ##### -->
-<para>
-
-</para>
-
- at menu: 
- at only_unallocated: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_deleted ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_set_deleted ##### -->
-<para>
-
-</para>
-
- at menu: 
- at deleted: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_menus ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_add_menu ##### -->
-<para>
-
-</para>
-
- at menu: 
- at submenu: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_menu_with_name ##### -->
-<para>
-
-</para>
-
- at menu: 
- at name: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_parent ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_item_pool ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_items ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_has_layout ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
-<!-- ##### FUNCTION xfce_menu_get_layout_elements ##### -->
-<para>
-
-</para>
-
- at menu: 
- at Returns: 
-
-
diff --git a/garcon/Makefile.am b/garcon/Makefile.am
new file mode 100644
index 0000000..901ee48
--- /dev/null
+++ b/garcon/Makefile.am
@@ -0,0 +1,98 @@
+# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
+# 
+# Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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 Library General Public License for more details.
+# 
+# You should have received a copy of the GNU Library General 
+# Public License along with this library; if not, write to the 
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+INCLUDES = 								\
+	-I$(top_srcdir)							\
+	-DGARCON_COMPILATION						\
+	-DGARCON_VERSION_API=\"$(GARCON_VERSION_API)\"			\
+	-DG_LOG_DOMAIN=\"garcon\"					\
+	$(PLATFORM_CFLAGS)
+
+lib_LTLIBRARIES = 							\
+	libgarcon-1.la
+
+libgarcon_headers =							\
+	garcon.h							\
+	garcon-config.h							\
+	garcon-gio.h							\
+	garcon-menu-element.h						\
+	garcon-menu-separator.h						\
+	garcon-menu-directory.h						\
+	garcon-menu-item-pool.h						\
+	garcon-menu-item-cache.h					\
+	garcon-environment.h						\
+	garcon-menu.h							\
+	garcon-menu-monitor.h						\
+	garcon-menu-item.h						\
+	garcon-menu-node.h						\
+	garcon-menu-tree-provider.h					\
+	garcon-menu-merger.h						\
+	garcon-menu-parser.h
+
+libgarcon_sources =							\
+	garcon.c							\
+	garcon-config.c							\
+	garcon-gio.c							\
+	garcon-menu-element.c						\
+	garcon-menu-separator.c						\
+	garcon-menu-directory.c						\
+	garcon-menu-item-pool.c						\
+	garcon-menu-item-cache.c					\
+	garcon-environment.c						\
+	garcon-menu.c							\
+	garcon-menu-monitor.c						\
+	garcon-menu-item.c						\
+	garcon-menu-node.c						\
+	garcon-menu-tree-provider.c					\
+	garcon-menu-merger.c						\
+	garcon-menu-parser.c
+
+libgarconincludedir = $(includedir)/garcon-1/garcon
+
+libgarconinclude_HEADERS =						\
+	$(libgarcon_headers)						\
+	garcon.h							\
+	garcon-config.h
+
+libgarcon_1_la_SOURCES =						\
+	$(libgarcon_sources)						\
+	$(libgarcon_headers)
+
+libgarcon_1_la_CFLAGS = 						\
+	$(GLIB_CFLAGS)							\
+	$(GTHREAD_CFLAGS)						\
+	$(GIO_CFLAGS)							\
+	$(PLATFORM_CFLAGS)
+
+libgarcon_1_la_LDFLAGS =						\
+	-no-undefined							\
+	-export-dynamic							\
+	-version-info $(GARCON_VERINFO)					\
+	$(PLATFORM_LDFLAGS)
+	
+libgarcon_1_la_LIBADD = 						\
+	$(GLIB_LIBS)							\
+	$(GTHREAD_LIBS)							\
+	$(GIO_LIBS)
+
+EXTRA_DIST =								\
+	garcon-config.h.in
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = garcon-1.pc
diff --git a/garcon/garcon-1.pc.in b/garcon/garcon-1.pc.in
new file mode 100644
index 0000000..10e4356
--- /dev/null
+++ b/garcon/garcon-1.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+garcon_api_version=@GARCON_VERSION_API@
+
+Name: @PACKAGE_TARNAME@
+Description: Freedesktop.org compliant menu library
+Requires: glib-2.0 gio-2.0 gthread-2.0 gobject-2.0
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lgarcon-${garcon_api_version}
+Cflags: -I${includedir}/garcon-${garcon_api_version}
diff --git a/garcon/garcon-config.c b/garcon/garcon-config.c
new file mode 100644
index 0000000..64c7bd4
--- /dev/null
+++ b/garcon/garcon-config.c
@@ -0,0 +1,76 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <garcon/garcon-config.h>
+
+
+
+const guint garcon_major_version = GARCON_MAJOR_VERSION;
+const guint garcon_minor_version = GARCON_MINOR_VERSION;
+const guint garcon_micro_version = GARCON_MICRO_VERSION;
+
+
+
+
+/**
+ * garcon_check_version:
+ * @required_major : the required major version.
+ * @required_minor : the required minor version.
+ * @required_micro : the required micro version.
+ *
+ * Checks that the <systemitem class="library">garcon</systemitem> 
+ * library in use is compatible with the given version. Generally you 
+ * would pass in the constants #GARCON_MAJOR_VERSION, 
+ * #GARCON_MINOR_VERSION and #GARCON_MICRO_VERSION as the three 
+ * arguments to this function; that produces a check that the library
+ * in use is compatible with the version of 
+ * <systemitem class="library">garcon</systemitem> the application was
+ * compiled against.
+ *
+ * <example>
+ * <title>Checking the runtime version of the garcon library</title>
+ * <programlisting>
+ * const gchar *mismatch;
+ * mismatch = garcon_check_version (GARCON_VERSION_MAJOR,
+ *                                  GARCON_VERSION_MINOR,
+ *                                  GARCON_VERSION_MICRO);
+ * if (G_UNLIKELY (mismatch != NULL))
+ *   g_error ("Version mismatch: %<!---->s", mismatch);
+ * </programlisting>
+ * </example>
+ *
+ * Return value: %NULL if the library is compatible with the given version,
+ *               or a string describing the version mismatch. The returned
+ *               string is owned by the library and must not be freed or
+ *               modified by the caller.
+ *
+ * Since: 0.3.1
+ **/
+const gchar*
+garcon_check_version (guint required_major,
+                      guint required_minor,
+                      guint required_micro)
+{
+  return NULL;
+}
diff --git a/garcon/garcon-config.h.in b/garcon/garcon-config.h.in
new file mode 100644
index 0000000..a4727e9
--- /dev/null
+++ b/garcon/garcon-config.h.in
@@ -0,0 +1,55 @@
+/* $Id$ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2008 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if !defined (GARCON_INSIDE_GARCON_H) && !defined (GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_CONFIG_H__
+#define __GARCON_CONFIG_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_MAJOR_VERSION @GARCON_VERSION_MAJOR@
+#define GARCON_MINOR_VERSION @GARCON_VERSION_MINOR@
+#define GARCON_MICRO_VERSION @GARCON_VERSION_MICRO@
+
+#define GARCON_CHECK_VERSION(major,minor,micro) \
+  (GARCON_MAJOR_VERSION > (major) \
+   || (GARCON_MAJOR_VERSION == (major) \
+       && GARCON_MINOR_VERSION > (minor)) \
+   || (GARCON_MAJOR_VERSION == (major) \
+       && GARCON_MINOR_VERSION == (minor) \
+       && GARCON_MICRO_VERSION >= (micro)))
+
+extern const guint garcon_major_version;
+extern const guint garcon_minor_version;
+extern const guint garcon_micro_version;
+
+const gchar *garcon_check_version (guint required_major,
+                                   guint required_minor,
+                                   guint required_micro);
+
+G_END_DECLS
+
+#endif /* !__GARCON_CONFIG_H__ */
diff --git a/libxfce4menu/xfce-menu-environment.c b/garcon/garcon-environment.c
similarity index 62%
rename from libxfce4menu/xfce-menu-environment.c
rename to garcon/garcon-environment.c
index be33013..61d630b 100644
--- a/libxfce4menu/xfce-menu-environment.c
+++ b/garcon/garcon-environment.c
@@ -1,7 +1,6 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
+/* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
- * Copyright (c) 2007 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -10,20 +9,30 @@
  *
  * 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
- * Library General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU Library General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#include <libxfce4menu/xfce-menu-environment.h>
+#include <garcon/garcon-environment.h>
+
+
+
+/**
+ * SECTION:garcon-menu-environment
+ * @title: Desktop Environment Configuration
+ *
+ * Desktop Environment Configuration
+ **/
 
 
 
@@ -32,7 +41,7 @@ static gchar *environment = NULL;
 
 
 /**
- * xfce_menu_set_environment:
+ * garcon_set_environment:
  * @env : Name of the desktop environment for which menus will
  *        be generated (e.g. XFCE, KDE, GNOME or %NULL).
  *
@@ -41,7 +50,7 @@ static gchar *environment = NULL;
  * ignored. If set to %NULL, all menu items are used.
  */
 void
-xfce_menu_set_environment (const gchar *env)
+garcon_set_environment (const gchar *env)
 {
   if (G_LIKELY (environment != NULL))
     g_free (environment);
@@ -52,13 +61,13 @@ xfce_menu_set_environment (const gchar *env)
 
 
 /**
- * xfce_menu_get_environment:
+ * garcon_get_environment:
  * 
  * Return value: Name of the desktop environment (e.g. XFCE, KDE, GNOME) 
  * which is used or %NULL.
  */
-G_CONST_RETURN gchar*
-xfce_menu_get_environment (void)
+const gchar *
+garcon_get_environment (void)
 {
   return environment;
 }
diff --git a/garcon/garcon-environment.h b/garcon/garcon-environment.h
new file mode 100644
index 0000000..b7eeedc
--- /dev/null
+++ b/garcon/garcon-environment.h
@@ -0,0 +1,37 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined(GARCON_INSIDE_GARCON_H) && !defined(GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_ENVIRONMENT_H__
+#define __GARCON_MENU_ENVIRONMENT_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+void         garcon_set_environment (const gchar *env);
+const gchar *garcon_get_environment (void);
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_ENVIRONMENT_H__ */
diff --git a/garcon/garcon-gio.c b/garcon/garcon-gio.c
new file mode 100644
index 0000000..4c381c0
--- /dev/null
+++ b/garcon/garcon-gio.c
@@ -0,0 +1,121 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gio/gio.h>
+
+#include <garcon/garcon-gio.h>
+
+
+
+static gboolean
+is_valid_scheme_character (char c)
+{
+  return g_ascii_isalnum (c) || c == '+' || c == '-' || c == '.';
+}
+
+
+
+/* Following RFC 2396, valid schemes are built like:
+ *       scheme        = alpha *( alpha | digit | "+" | "-" | "." )
+ */
+static gboolean
+has_valid_scheme (const char *uri)
+{
+  const char *p;
+
+  p = uri;
+
+  if (!g_ascii_isalpha (*p))
+    return FALSE;
+
+  do 
+    {
+      p++;
+    } 
+  while (is_valid_scheme_character (*p));
+
+  return *p == ':';
+}
+
+
+
+GFile *
+g_file_new_for_unknown_input (const gchar *path,
+                              GFile       *parent)
+{
+  g_return_val_if_fail (path != NULL, NULL);
+
+  if (g_path_is_absolute (path))
+    return g_file_new_for_path (path);
+
+  if (has_valid_scheme (path))
+    return g_file_new_for_uri (path);
+
+  if (G_LIKELY (parent != NULL))
+    return g_file_resolve_relative_path (parent, path);
+  else
+    return g_file_new_for_path (path);
+}
+
+
+
+GFile *
+g_file_new_relative_to_file (const gchar *path,
+                             GFile       *file)
+{
+  GFileType type;
+  GFile    *result;
+  GFile    *dir;
+
+  g_return_val_if_fail (path != NULL, NULL);
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+  
+  type = g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL);
+
+  if (G_UNLIKELY (type == G_FILE_TYPE_DIRECTORY))
+    dir = g_object_ref (file);
+  else
+    dir = g_file_get_parent (file);
+
+  result = g_file_new_for_unknown_input (path, dir);
+  g_object_unref (dir);
+  
+  return result;
+}
+
+
+
+gchar *
+g_file_get_uri_relative_to_file (const gchar *path,
+                                 GFile       *file)
+{
+  GFile *absolute_file;
+  gchar *uri;
+
+  absolute_file = g_file_new_relative_to_file (path, file);
+  uri = g_file_get_uri (absolute_file);
+  g_object_unref (absolute_file);
+  
+  return uri;
+}
diff --git a/garcon/garcon-gio.h b/garcon/garcon-gio.h
new file mode 100644
index 0000000..2908e1d
--- /dev/null
+++ b/garcon/garcon-gio.h
@@ -0,0 +1,41 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined(GARCON_INSIDE_GARCON_H) && !defined(GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_GIO_H__
+#define __GARCON_GIO_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+GFile *g_file_new_for_unknown_input    (const gchar *path,
+                                        GFile       *parent);
+GFile *g_file_new_relative_to_file     (const gchar *path,
+                                        GFile       *file);
+gchar *g_file_get_uri_relative_to_file (const gchar *path,
+                                        GFile       *file);
+
+G_END_DECLS
+
+#endif /* !__GARCON_GIO_H__ */
diff --git a/garcon/garcon-menu-directory.c b/garcon/garcon-menu-directory.c
new file mode 100644
index 0000000..e5bf627
--- /dev/null
+++ b/garcon/garcon-menu-directory.c
@@ -0,0 +1,644 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <locale.h>
+#include <glib.h>
+
+#include <garcon/garcon-environment.h>
+#include <garcon/garcon-menu-directory.h>
+
+
+
+void
+_garcon_menu_directory_init (void)
+{
+}
+
+
+
+void
+_garcon_menu_directory_shutdown (void)
+{
+}
+
+
+
+#define GARCON_MENU_DIRECTORY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GARCON_TYPE_MENU_DIRECTORY, GarconMenuDirectoryPrivate))
+
+
+
+/* Desktop entry keys */
+#if 0
+static const gchar *desktop_entry_keys[] = 
+{
+  "Name",
+  "Comment",
+  "Icon",
+  "Categories",
+  "OnlyShowIn",
+  "NotShowIn",
+  "NoDisplay",
+  "Hidden",
+  NULL
+};
+#endif
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+  PROP_FILE,
+  PROP_NAME,
+  PROP_COMMENT,
+  PROP_NO_DISPLAY,
+  PROP_ICON,
+};
+
+
+
+static void garcon_menu_directory_class_init   (GarconMenuDirectoryClass *klass);
+static void garcon_menu_directory_init         (GarconMenuDirectory      *directory);
+static void garcon_menu_directory_constructed  (GObject                  *object);
+static void garcon_menu_directory_finalize     (GObject                  *object);
+static void garcon_menu_directory_get_property (GObject                  *object,
+                                                guint                     prop_id,
+                                                GValue                   *value,
+                                                GParamSpec               *pspec);
+static void garcon_menu_directory_set_property (GObject                  *object,
+                                                guint                     prop_id,
+                                                const GValue             *value,
+                                                GParamSpec               *pspec);
+static void garcon_menu_directory_free_private (GarconMenuDirectory      *directory);
+static void garcon_menu_directory_load         (GarconMenuDirectory      *directory);
+
+
+
+struct _GarconMenuDirectoryPrivate
+{
+  /* Directory file */
+  GFile  *file;
+
+  /* Directory name */
+  gchar  *name;
+
+  /* Directory description (comment) */
+  gchar  *comment;
+
+  /* Icon */
+  gchar  *icon;
+
+  /* Environments in which the menu should be displayed only */
+  gchar **only_show_in;
+
+  /* Environments in which the menu should be hidden */
+  gchar **not_show_in;
+
+  /* Whether the menu should be ignored completely */
+  guint   hidden : 1;
+
+  /* Whether the menu should be hidden */
+  guint   no_display : 1;
+};
+
+struct _GarconMenuDirectoryClass
+{
+  GObjectClass __parent__;
+};
+
+struct _GarconMenuDirectory
+{
+  GObject                        __parent__;
+
+  /* < private > */
+  GarconMenuDirectoryPrivate *priv;
+};
+
+
+
+static GObjectClass *garcon_menu_directory_parent_class = NULL;
+
+
+
+GType
+garcon_menu_directory_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            "GarconMenuDirectory",
+                                            sizeof (GarconMenuDirectoryClass),
+                                            (GClassInitFunc) garcon_menu_directory_class_init,
+                                            sizeof (GarconMenuDirectory),
+                                            (GInstanceInitFunc) garcon_menu_directory_init,
+                                            0);
+    }
+
+  return type;
+}
+
+
+
+static void
+garcon_menu_directory_class_init (GarconMenuDirectoryClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof(GarconMenuDirectoryPrivate));
+
+  /* Determine the parent type class */
+  garcon_menu_directory_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->constructed = garcon_menu_directory_constructed;
+  gobject_class->finalize = garcon_menu_directory_finalize; 
+  gobject_class->get_property = garcon_menu_directory_get_property;
+  gobject_class->set_property = garcon_menu_directory_set_property;
+
+  /**
+   * GarconMenuDirectory:filename:
+   *
+   * The @GFile of an %GarconMenuDirectory. 
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILE,
+                                   g_param_spec_object ("file",
+                                                        "File",
+                                                        "File",
+                                                        G_TYPE_FILE,
+                                                        G_PARAM_READWRITE | 
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GarconMenuDirectory:name:
+   *
+   * Name of the directory.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_NAME,
+                                   g_param_spec_string ("name",
+                                                        "Name",
+                                                        "Directory name",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
+
+  /**
+   * GarconMenuDirectory:comment:
+   *
+   * Directory description (comment).
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_COMMENT,
+                                   g_param_spec_string ("comment",
+                                                        "Description",
+                                                        "Directory description",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
+
+  /**
+   * GarconMenuDirectory:icon:
+   *
+   * Icon associated with this directory.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_ICON,
+                                   g_param_spec_string ("icon",
+                                                        "Icon",
+                                                        "Directory icon",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
+
+  /**
+   * GarconMenuDirectory:no-display:
+   *
+   * Whether this menu item is hidden in menus.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_NO_DISPLAY,
+                                   g_param_spec_boolean ("no-display",
+                                                         "No Display",
+                                                         "Visibility state of the related menu",
+                                                         FALSE,
+                                                         G_PARAM_READWRITE));
+
+}
+
+
+
+static void
+garcon_menu_directory_init (GarconMenuDirectory *directory)
+{
+  directory->priv = GARCON_MENU_DIRECTORY_GET_PRIVATE (directory);
+  directory->priv->file = NULL;
+  directory->priv->name = NULL;
+  directory->priv->icon = NULL;
+  directory->priv->only_show_in = NULL;
+  directory->priv->not_show_in = NULL;
+  directory->priv->hidden = FALSE;
+  directory->priv->no_display = FALSE;
+}
+
+
+
+static void 
+garcon_menu_directory_constructed (GObject *object)
+{
+  GarconMenuDirectory *directory = GARCON_MENU_DIRECTORY (object);
+  garcon_menu_directory_load (directory);
+}
+
+
+
+static void
+garcon_menu_directory_finalize (GObject *object)
+{
+  GarconMenuDirectory *directory = GARCON_MENU_DIRECTORY (object);
+
+  /* Free private data */
+  garcon_menu_directory_free_private (directory);
+
+  /* Free file */
+  g_object_unref (directory->priv->file);
+
+  (*G_OBJECT_CLASS (garcon_menu_directory_parent_class)->finalize) (object);
+}
+
+
+
+static void
+garcon_menu_directory_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  GarconMenuDirectory *directory = GARCON_MENU_DIRECTORY (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILE:
+      g_value_set_object (value, garcon_menu_directory_get_file (directory));
+      break;
+
+    case PROP_NAME:
+      g_value_set_string (value, garcon_menu_directory_get_name (directory));
+      break;
+
+    case PROP_COMMENT:
+      g_value_set_string (value, garcon_menu_directory_get_comment (directory));
+      break;
+
+    case PROP_ICON:
+      g_value_set_string (value, garcon_menu_directory_get_icon (directory));
+      break;
+
+    case PROP_NO_DISPLAY:
+      g_value_set_boolean (value, garcon_menu_directory_get_no_display (directory));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+garcon_menu_directory_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  GarconMenuDirectory *directory = GARCON_MENU_DIRECTORY (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILE:
+      directory->priv->file = g_object_ref (g_value_get_object (value));
+      break;
+
+    case PROP_NAME:
+      garcon_menu_directory_set_name (directory, g_value_get_string (value));
+      break;
+
+    case PROP_COMMENT:
+      garcon_menu_directory_set_comment (directory, g_value_get_string (value));
+      break;
+
+    case PROP_ICON:
+      garcon_menu_directory_set_icon (directory, g_value_get_string (value));
+      break;
+
+    case PROP_NO_DISPLAY:
+      garcon_menu_directory_set_no_display (directory, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+GFile *
+garcon_menu_directory_get_file (GarconMenuDirectory *directory)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), NULL);
+  return directory->priv->file;
+}
+
+
+
+const gchar*
+garcon_menu_directory_get_name (GarconMenuDirectory *directory)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), NULL);
+  return directory->priv->name;
+}
+
+
+
+void
+garcon_menu_directory_set_name (GarconMenuDirectory *directory, 
+                                const gchar         *name)
+{
+  g_return_if_fail (GARCON_IS_MENU_DIRECTORY (directory));
+  g_return_if_fail (name != NULL);
+
+  /* Free old name */
+  if (G_UNLIKELY (directory->priv->name != NULL))
+    g_free (directory->priv->name);
+
+  /* Set the new filename */
+  directory->priv->name = g_strdup (name);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (directory), "name");
+}
+
+
+
+const gchar*
+garcon_menu_directory_get_comment (GarconMenuDirectory *directory)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), NULL);
+  return directory->priv->comment;
+}
+
+
+
+void
+garcon_menu_directory_set_comment (GarconMenuDirectory *directory, 
+                                   const gchar         *comment)
+{
+  g_return_if_fail (GARCON_IS_MENU_DIRECTORY (directory));
+
+  /* Free old name */
+  if (G_UNLIKELY (directory->priv->comment != NULL))
+    g_free (directory->priv->comment);
+
+  /* Set the new filename */
+  directory->priv->comment = g_strdup (comment);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (directory), "comment");
+}
+
+
+const gchar*
+garcon_menu_directory_get_icon (GarconMenuDirectory *directory)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), NULL);
+  return directory->priv->icon;
+}
+
+
+
+void
+garcon_menu_directory_set_icon (GarconMenuDirectory *directory, 
+                                const gchar         *icon)
+{
+  g_return_if_fail (GARCON_IS_MENU_DIRECTORY (directory));
+
+  /* Free old name */
+  if (G_UNLIKELY (directory->priv->icon != NULL))
+    g_free (directory->priv->icon);
+
+  /* Set the new filename */
+  directory->priv->icon = g_strdup (icon);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (directory), "icon");
+}
+
+
+
+gboolean
+garcon_menu_directory_get_no_display (GarconMenuDirectory *directory)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), FALSE);
+  return directory->priv->no_display;
+}
+
+
+
+void        
+garcon_menu_directory_set_no_display (GarconMenuDirectory *directory,
+                                      gboolean             no_display)
+{
+  g_return_if_fail (GARCON_IS_MENU_DIRECTORY (directory));
+  
+  /* Abort if old and new value are equal */
+  if (directory->priv->no_display == no_display)
+    return;
+
+  /* Assign new value */
+  directory->priv->no_display = no_display;
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (directory), "no-display");
+}
+
+
+
+static void
+garcon_menu_directory_free_private (GarconMenuDirectory *directory)
+{
+  g_return_if_fail (GARCON_IS_MENU_DIRECTORY (directory));
+
+  /* Free name */
+  g_free (directory->priv->name);
+
+  /* Free comment */
+  g_free (directory->priv->comment);
+
+  /* Free icon */
+  g_free (directory->priv->icon);
+
+  /* Free environment lists */
+  g_strfreev (directory->priv->only_show_in);
+  g_strfreev (directory->priv->not_show_in);
+}
+
+
+
+static void
+garcon_menu_directory_load (GarconMenuDirectory *directory)
+{
+  GKeyFile    *entry;
+  GError      *error = NULL;
+  const gchar *name;
+  const gchar *comment;
+  const gchar *icon;
+  gchar       *filename;
+
+  g_return_if_fail (GARCON_IS_MENU_DIRECTORY (directory));
+
+  /* TODO: Use get_uri() here, together with g_file_read() and
+   * g_key_file_load_from_data() */
+
+  filename = g_file_get_path (directory->priv->file);
+  entry = g_key_file_new ();
+  g_key_file_load_from_file (entry, filename, G_KEY_FILE_NONE, &error);
+  g_free (filename);
+
+  if (G_UNLIKELY (error != NULL))
+    {
+      g_error_free (error);
+      return;
+    }
+
+  /* Read directory information */
+  name = g_key_file_get_locale_string (entry, "Desktop Entry", "Name", NULL, NULL);
+  comment = g_key_file_get_locale_string (entry, "Desktop Entry", "Comment", NULL, NULL);
+  icon = g_key_file_get_locale_string (entry, "Desktop Entry", "Icon", NULL, NULL);
+
+  /* Pass data to the directory */
+  garcon_menu_directory_set_name (directory, name);
+  garcon_menu_directory_set_comment (directory, comment);
+  garcon_menu_directory_set_icon (directory, icon);
+  garcon_menu_directory_set_no_display (directory, g_key_file_get_boolean (entry, "Desktop Entry", "NoDisplay", NULL));
+
+  /* Set rest of the private data directly */
+  directory->priv->only_show_in = g_key_file_get_string_list (entry, "Desktop Entry", "OnlyShowIn", NULL, NULL);
+  directory->priv->not_show_in = g_key_file_get_string_list (entry, "Desktop Entry", "NotShowIn", NULL, NULL);
+  directory->priv->hidden = g_key_file_get_boolean (entry, "Desktop Entry", "Hidden", NULL);
+
+  g_key_file_free (entry);
+}
+
+
+
+gboolean
+garcon_menu_directory_get_hidden (GarconMenuDirectory *directory)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), FALSE);
+  return directory->priv->hidden;
+}
+
+
+
+gboolean
+garcon_menu_directory_get_show_in_environment (GarconMenuDirectory *directory)
+{
+  const gchar *env;
+  gboolean     show = TRUE;
+  gboolean     included;
+  int          i;
+
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), FALSE);
+  
+  /* Determine current environment */
+  env = garcon_get_environment ();
+
+  /* If no environment has been set, the menu is displayed no matter what
+   * OnlyShowIn or NotShowIn contain */
+  if (G_UNLIKELY (env == NULL))
+    return TRUE;
+
+  /* Check if we have a OnlyShowIn OR a NotShowIn list (only one of them will be
+   * there, according to the desktop entry specification) */
+  if (G_UNLIKELY (directory->priv->only_show_in != NULL))
+    {
+      /* Determine whether our environment is included in this list */
+      included = FALSE;
+      for (i = 0; i < g_strv_length (directory->priv->only_show_in); ++i) 
+        {
+          if (G_UNLIKELY (g_utf8_collate (directory->priv->only_show_in[i], env) == 0))
+            included = TRUE;
+        }
+
+      /* If it's not, don't show the menu */
+      if (G_LIKELY (!included))
+        show = FALSE;
+    }
+  else if (G_UNLIKELY (directory->priv->not_show_in != NULL))
+    {
+      /* Determine whether our environment is included in this list */
+      included = FALSE;
+      for (i = 0; i < g_strv_length (directory->priv->not_show_in); ++i)
+        {
+          if (G_UNLIKELY (g_utf8_collate (directory->priv->not_show_in[i], env) == 0))
+            included = TRUE;
+        }
+
+      /* If it is, hide the menu */
+      if (G_UNLIKELY (included))
+        show = FALSE;
+    }
+
+  return show;
+}
+
+
+
+gboolean
+garcon_menu_directory_get_visible (GarconMenuDirectory *directory)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), FALSE);
+
+  if (!garcon_menu_directory_get_show_in_environment (directory))
+    return FALSE;
+  else if (garcon_menu_directory_get_hidden (directory))
+    return FALSE;
+  else if (garcon_menu_directory_get_no_display (directory))
+    return FALSE;
+
+  return TRUE;
+}
+
+
+
+gboolean
+garcon_menu_directory_equal (GarconMenuDirectory *directory,
+                             GarconMenuDirectory *other)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (directory), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_DIRECTORY (other), FALSE);
+  return g_file_equal (directory->priv->file, other->priv->file);
+}
diff --git a/garcon/garcon-menu-directory.h b/garcon/garcon-menu-directory.h
new file mode 100644
index 0000000..9b1131a
--- /dev/null
+++ b/garcon/garcon-menu-directory.h
@@ -0,0 +1,71 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined(GARCON_INSIDE_GARCON_H) && !defined(GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_DIRECTORY_H__
+#define __GARCON_MENU_DIRECTORY_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU_DIRECTORY            (garcon_menu_directory_get_type ())
+#define GARCON_MENU_DIRECTORY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_DIRECTORY, GarconMenuDirectory))
+#define GARCON_MENU_DIRECTORY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU_DIRECTORY, GarconMenuDirectoryClass))
+#define GARCON_IS_MENU_DIRECTORY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_DIRECTORY))
+#define GARCON_IS_MENU_DIRECTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU_DIRECTORY))
+#define GARCON_MENU_DIRECTORY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU_DIRECTORY, GarconMenuDirectoryClass))
+
+typedef struct _GarconMenuDirectoryPrivate GarconMenuDirectoryPrivate;
+typedef struct _GarconMenuDirectoryClass   GarconMenuDirectoryClass;
+typedef struct _GarconMenuDirectory        GarconMenuDirectory;
+
+GType        garcon_menu_directory_get_type                (void) G_GNUC_CONST;
+
+GFile       *garcon_menu_directory_get_file                (GarconMenuDirectory *directory);
+const gchar *garcon_menu_directory_get_name                (GarconMenuDirectory *directory);
+void         garcon_menu_directory_set_name                (GarconMenuDirectory *directory,
+                                                            const gchar         *name);
+const gchar *garcon_menu_directory_get_comment             (GarconMenuDirectory *directory);
+void         garcon_menu_directory_set_comment             (GarconMenuDirectory *directory,
+                                                            const gchar         *comment);
+const gchar *garcon_menu_directory_get_icon                (GarconMenuDirectory *directory);
+void         garcon_menu_directory_set_icon                (GarconMenuDirectory *directory,
+                                                            const gchar         *icon);
+gboolean     garcon_menu_directory_get_no_display          (GarconMenuDirectory *directory);
+void         garcon_menu_directory_set_no_display          (GarconMenuDirectory *directory,
+                                                            gboolean             no_display);
+gboolean     garcon_menu_directory_get_hidden              (GarconMenuDirectory *directory);
+gboolean     garcon_menu_directory_get_show_in_environment (GarconMenuDirectory *directory);
+gboolean     garcon_menu_directory_get_visible             (GarconMenuDirectory *directory);
+gboolean     garcon_menu_directory_equal                   (GarconMenuDirectory *directory,
+                                                            GarconMenuDirectory *other);
+
+#if defined(GARCON_COMPILATION)
+void _garcon_menu_directory_init     (void) G_GNUC_INTERNAL;
+void _garcon_menu_directory_shutdown (void) G_GNUC_INTERNAL;
+#endif
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_DIRECTORY_H__ */
diff --git a/garcon/garcon-menu-element.c b/garcon/garcon-menu-element.c
new file mode 100644
index 0000000..2e595c2
--- /dev/null
+++ b/garcon/garcon-menu-element.c
@@ -0,0 +1,114 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <garcon/garcon-menu-element.h>
+
+
+
+static void garcon_menu_element_class_init (GarconMenuElementIface *klass);
+
+
+
+GType
+garcon_menu_element_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      type = g_type_register_static_simple (G_TYPE_INTERFACE,
+                                            "GarconMenuElement",
+                                            sizeof (GarconMenuElementIface),
+                                            (GClassInitFunc) garcon_menu_element_class_init,
+                                            0,
+                                            NULL,
+                                            0);
+
+      g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+    }
+
+  return type;
+}
+
+
+
+static void
+garcon_menu_element_class_init (GarconMenuElementIface *klass)
+{
+}
+
+
+
+const gchar*
+garcon_menu_element_get_name (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ELEMENT (element), NULL);
+  return (*GARCON_MENU_ELEMENT_GET_IFACE (element)->get_name) (element);
+}
+
+
+
+const gchar*
+garcon_menu_element_get_comment (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ELEMENT (element), NULL);
+  return (*GARCON_MENU_ELEMENT_GET_IFACE (element)->get_comment) (element);
+}
+
+
+
+const gchar*
+garcon_menu_element_get_icon_name (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ELEMENT (element), NULL);
+  return (*GARCON_MENU_ELEMENT_GET_IFACE (element)->get_icon_name) (element);
+}
+
+
+
+gboolean
+garcon_menu_element_get_visible (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ELEMENT (element), FALSE);
+  return (*GARCON_MENU_ELEMENT_GET_IFACE (element)->get_visible) (element);
+}
+
+
+
+gboolean
+garcon_menu_element_get_show_in_environment (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ELEMENT (element), FALSE);
+  return (*GARCON_MENU_ELEMENT_GET_IFACE (element)->get_show_in_environment) (element);
+}
+
+
+
+gboolean
+garcon_menu_element_get_no_display (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ELEMENT (element), FALSE);
+  return (*GARCON_MENU_ELEMENT_GET_IFACE (element)->get_no_display) (element);
+}
+
diff --git a/garcon/garcon-menu-element.h b/garcon/garcon-menu-element.h
new file mode 100644
index 0000000..9270688
--- /dev/null
+++ b/garcon/garcon-menu-element.h
@@ -0,0 +1,64 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined (GARCON_INSIDE_GARCON_H) && !defined (GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_ELEMENT_H__
+#define __GARCON_MENU_ELEMENT_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU_ELEMENT           (garcon_menu_element_get_type ())
+#define GARCON_MENU_ELEMENT(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_ELEMENT, GarconMenuElement))
+#define GARCON_IS_MENU_ELEMENT(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_ELEMENT))
+#define GARCON_MENU_ELEMENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GARCON_TYPE_MENU_ELEMENT, GarconMenuElementIface))
+
+typedef struct _GarconMenuElement      GarconMenuElement;
+typedef struct _GarconMenuElementIface GarconMenuElementIface;
+
+struct _GarconMenuElementIface
+{
+  GTypeInterface __parent__;
+
+  /* Virtual methods */
+  const gchar *(*get_name)                (GarconMenuElement *element);
+  const gchar *(*get_comment)             (GarconMenuElement *element);
+  const gchar *(*get_icon_name)           (GarconMenuElement *element);
+  gboolean     (*get_visible)             (GarconMenuElement *element);
+  gboolean     (*get_show_in_environment) (GarconMenuElement *element);
+  gboolean     (*get_no_display)          (GarconMenuElement *element);
+};
+
+GType        garcon_menu_element_get_type                (void) G_GNUC_CONST;
+
+const gchar *garcon_menu_element_get_name                (GarconMenuElement *element);
+const gchar *garcon_menu_element_get_comment             (GarconMenuElement *element);
+const gchar *garcon_menu_element_get_icon_name           (GarconMenuElement *element);
+gboolean     garcon_menu_element_get_visible             (GarconMenuElement *element);
+gboolean     garcon_menu_element_get_show_in_environment (GarconMenuElement *element);
+gboolean     garcon_menu_element_get_no_display          (GarconMenuElement *element);
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_ELEMENT_H__ */
diff --git a/garcon/garcon-menu-item-cache.c b/garcon/garcon-menu-item-cache.c
new file mode 100644
index 0000000..395673d
--- /dev/null
+++ b/garcon/garcon-menu-item-cache.c
@@ -0,0 +1,268 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <garcon/garcon-menu-item.h>
+#include <garcon/garcon-menu-item-cache.h>
+
+
+
+#define GARCON_MENU_ITEM_CACHE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GARCON_TYPE_MENU_ITEM_CACHE, GarconMenuItemCachePrivate))
+
+
+
+static void garcon_menu_item_cache_class_init (GarconMenuItemCacheClass *klass);
+static void garcon_menu_item_cache_init       (GarconMenuItemCache      *cache);
+static void garcon_menu_item_cache_finalize   (GObject                  *object);
+
+
+
+
+static GarconMenuItemCache *_garcon_menu_item_cache = NULL;
+
+
+
+void
+_garcon_menu_item_cache_init (void)
+{
+  if (G_LIKELY (_garcon_menu_item_cache == NULL))
+    {
+      _garcon_menu_item_cache = g_object_new (GARCON_TYPE_MENU_ITEM_CACHE, NULL);
+      g_object_add_weak_pointer (G_OBJECT (_garcon_menu_item_cache), 
+                                 (gpointer) &_garcon_menu_item_cache);
+    }
+}
+
+
+
+void
+_garcon_menu_item_cache_shutdown (void)
+{
+  if (G_LIKELY (_garcon_menu_item_cache != NULL))
+    g_object_unref (G_OBJECT (_garcon_menu_item_cache));
+      
+}
+
+
+
+struct _GarconMenuItemCacheClass
+{
+  GObjectClass __parent__;
+};
+
+struct _GarconMenuItemCachePrivate
+{
+  /* Hash table for mapping absolute filenames to GarconMenuItem's */
+  GHashTable *items;
+
+  /* Mutex lock */
+  GMutex     *lock;
+};
+
+struct _GarconMenuItemCache
+{
+  GObject                     __parent__;
+
+  /* Private data */
+  GarconMenuItemCachePrivate *priv;
+};
+
+
+
+static GObjectClass *garcon_menu_item_cache_parent_class = NULL;
+
+
+
+GType
+garcon_menu_item_cache_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            "GarconMenuItemCache",
+                                            sizeof (GarconMenuItemCacheClass),
+                                            (GClassInitFunc) garcon_menu_item_cache_class_init,
+                                            sizeof (GarconMenuItemCache),
+                                            (GInstanceInitFunc) garcon_menu_item_cache_init,
+                                            0);
+    }
+  
+  return type;
+}
+
+
+
+static void
+garcon_menu_item_cache_class_init (GarconMenuItemCacheClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (GarconMenuItemCachePrivate));
+
+  /* Determine the parent type class */
+  garcon_menu_item_cache_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = garcon_menu_item_cache_finalize;
+}
+
+
+
+static void
+garcon_menu_item_cache_init (GarconMenuItemCache *cache)
+{
+  cache->priv = GARCON_MENU_ITEM_CACHE_GET_PRIVATE (cache);
+
+  /* Initialize the mutex lock */
+  cache->priv->lock = g_mutex_new ();
+
+  /* Create empty hash table */
+  cache->priv->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
+                                              (GDestroyNotify) garcon_menu_item_unref);
+}
+
+
+
+GarconMenuItemCache*
+garcon_menu_item_cache_get_default (void)
+{
+  return g_object_ref (G_OBJECT (_garcon_menu_item_cache));
+}
+
+
+
+static void
+garcon_menu_item_cache_finalize (GObject *object)
+{
+  GarconMenuItemCache *cache = GARCON_MENU_ITEM_CACHE (object);
+
+  /* Free hash table */
+  g_hash_table_unref (cache->priv->items);
+
+  /* Destroy the mutex */
+  g_mutex_free (cache->priv->lock);
+
+  (*G_OBJECT_CLASS (garcon_menu_item_cache_parent_class)->finalize) (object);
+}
+
+
+
+GarconMenuItem*
+garcon_menu_item_cache_lookup (GarconMenuItemCache *cache,
+                               const gchar         *uri,
+                               const gchar         *desktop_id)
+{
+  GarconMenuItem *item = NULL;
+
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM_CACHE (cache), NULL);
+  g_return_val_if_fail (uri != NULL, NULL);
+  g_return_val_if_fail (desktop_id != NULL, NULL);
+
+  /* Acquire lock on the item cache as it's likely that we need to load 
+   * items from the hard drive and store it in the hash table of the 
+   * item cache */
+  g_mutex_lock (cache->priv->lock);
+
+  /* Search uri in the hash table */
+  item = g_hash_table_lookup (cache->priv->items, uri);
+
+  /* Return the item if we we found one */
+  if (item != NULL)
+    {
+      /* Update desktop id, if necessary */
+      garcon_menu_item_set_desktop_id (item, desktop_id);
+
+      /* Release item cache lock */
+      g_mutex_unlock (cache->priv->lock);
+
+      return item;
+    }
+
+  /* Last chance is to load it directly from the file */
+  item = garcon_menu_item_new (uri);
+
+  if (G_LIKELY (item != NULL))
+    {
+      /* Update desktop id */
+      garcon_menu_item_set_desktop_id (item, desktop_id);
+
+      /* The file has been loaded, add the item to the hash table */
+      g_hash_table_replace (cache->priv->items, g_strdup (uri), item);
+    }
+
+  /* Release item cache lock */
+  g_mutex_unlock (cache->priv->lock);
+
+  return item;
+}
+
+
+
+void 
+garcon_menu_item_cache_foreach (GarconMenuItemCache *cache,
+                                GHFunc               func,
+                                gpointer             user_data)
+{
+  g_return_if_fail (GARCON_IS_MENU_ITEM_CACHE (cache));
+
+  /* Acquire lock on the item cache */
+  g_mutex_lock (cache->priv->lock);
+
+  g_hash_table_foreach (cache->priv->items, func, user_data);
+
+  /* Release item cache lock */
+  g_mutex_unlock (cache->priv->lock);
+}
+
+
+
+void
+garcon_menu_item_cache_invalidate (GarconMenuItemCache *cache)
+{
+  g_return_if_fail (GARCON_IS_MENU_ITEM_CACHE (cache));
+
+  /* Destroy the hash table */
+  g_hash_table_unref (cache->priv->items);
+  
+  /* Create a new, empty hash table */
+  cache->priv->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
+                                              (GDestroyNotify) garcon_menu_item_unref);
+}
diff --git a/garcon/garcon-menu-item-cache.h b/garcon/garcon-menu-item-cache.h
new file mode 100644
index 0000000..690511d
--- /dev/null
+++ b/garcon/garcon-menu-item-cache.h
@@ -0,0 +1,63 @@
+/* $Id$ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if !defined(GARCON_INSIDE_GARCON_H) && !defined(GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_ITEM_CACHE_H__
+#define __GARCON_MENU_ITEM_CACHE_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GarconMenuItemCachePrivate GarconMenuItemCachePrivate;
+typedef struct _GarconMenuItemCacheClass   GarconMenuItemCacheClass;
+typedef struct _GarconMenuItemCache        GarconMenuItemCache;
+
+#define GARCON_TYPE_MENU_ITEM_CACHE            (garcon_menu_item_cache_get_type ())
+#define GARCON_MENU_ITEM_CACHE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_ITEM_CACHE, GarconMenuItemCache))
+#define GARCON_MENU_ITEM_CACHE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU_ITEM_CACHE, GarconMenuItemCacheClass))
+#define GARCON_IS_MENU_ITEM_CACHE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_ITEM_CACHE))
+#define GARCON_IS_MENU_ITEM_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU_ITEM_CACHE))
+#define GARCON_MENU_ITEM_CACHE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU_ITEM_CACHE, GarconMenuItemCacheClass))
+
+GType                garcon_menu_item_cache_get_type    (void) G_GNUC_CONST;
+
+GarconMenuItemCache *garcon_menu_item_cache_get_default (void);
+
+GarconMenuItem      *garcon_menu_item_cache_lookup      (GarconMenuItemCache *cache,
+                                                         const gchar         *filename,
+                                                         const gchar         *desktop_id);
+void                 garcon_menu_item_cache_foreach     (GarconMenuItemCache *cache,
+                                                         GHFunc               func, 
+                                                         gpointer             user_data);
+void                 garcon_menu_item_cache_invalidate  (GarconMenuItemCache *cache);
+
+#if defined(GARCON_COMPILATION)
+void                 _garcon_menu_item_cache_init       (void) G_GNUC_INTERNAL;
+void                 _garcon_menu_item_cache_shutdown   (void) G_GNUC_INTERNAL;
+#endif
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_ITEM_CACHE_H__ */
diff --git a/garcon/garcon-menu-item-pool.c b/garcon/garcon-menu-item-pool.c
new file mode 100644
index 0000000..b5c23da
--- /dev/null
+++ b/garcon/garcon-menu-item-pool.c
@@ -0,0 +1,207 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <garcon/garcon-menu-item.h>
+#include <garcon/garcon-menu-node.h>
+#include <garcon/garcon-menu-item-pool.h>
+
+
+
+#define GARCON_MENU_ITEM_POOL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GARCON_TYPE_MENU_ITEM_POOL, GarconMenuItemPoolPrivate))
+
+
+
+static void     garcon_menu_item_pool_class_init     (GarconMenuItemPoolClass *klass);
+static void     garcon_menu_item_pool_init           (GarconMenuItemPool      *pool);
+static void     garcon_menu_item_pool_finalize       (GObject                 *object);
+static gboolean garcon_menu_item_pool_filter_exclude (const gchar             *desktop_id,
+                                                      GarconMenuItem          *item,
+                                                      GNode                   *node);
+
+
+
+struct _GarconMenuItemPoolClass
+{
+  GObjectClass __parent__;
+};
+
+struct _GarconMenuItemPoolPrivate
+{
+  /* Hash table for mapping desktop-file id's to GarconMenuItem's */
+  GHashTable *items;
+};
+
+struct _GarconMenuItemPool
+{
+  GObject                    __parent__;
+
+  /* < private > */
+  GarconMenuItemPoolPrivate *priv;
+};
+
+
+
+static GObjectClass *garcon_menu_item_pool_parent_class = NULL;
+
+
+
+GType
+garcon_menu_item_pool_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            "GarconMenuItemPool",
+                                            sizeof (GarconMenuItemPoolClass),
+                                            (GClassInitFunc) garcon_menu_item_pool_class_init,
+                                            sizeof (GarconMenuItemPool),
+                                            (GInstanceInitFunc) garcon_menu_item_pool_init,
+                                            0);
+    }
+  
+  return type;
+}
+
+
+
+static void
+garcon_menu_item_pool_class_init (GarconMenuItemPoolClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (GarconMenuItemPoolPrivate));
+
+  /* Determine the parent type class */
+  garcon_menu_item_pool_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = garcon_menu_item_pool_finalize;
+}
+
+
+
+static void
+garcon_menu_item_pool_init (GarconMenuItemPool *pool)
+{
+  pool->priv = GARCON_MENU_ITEM_POOL_GET_PRIVATE (pool);
+  pool->priv->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
+                                             (GDestroyNotify) garcon_menu_item_unref);
+}
+
+
+
+static void
+garcon_menu_item_pool_finalize (GObject *object)
+{
+  GarconMenuItemPool *pool = GARCON_MENU_ITEM_POOL (object);
+
+  g_hash_table_unref (pool->priv->items);
+
+  (*G_OBJECT_CLASS (garcon_menu_item_pool_parent_class)->finalize) (object);
+}
+
+
+
+GarconMenuItemPool*
+garcon_menu_item_pool_new (void)
+{
+  return g_object_new (GARCON_TYPE_MENU_ITEM_POOL, NULL);
+}
+
+
+
+void
+garcon_menu_item_pool_insert (GarconMenuItemPool *pool,
+                              GarconMenuItem     *item)
+{
+  g_return_if_fail (GARCON_IS_MENU_ITEM_POOL (pool));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
+
+  /* Insert into the hash table and remove old item (if any) */
+  g_hash_table_replace (pool->priv->items, g_strdup (garcon_menu_item_get_desktop_id (item)), item);
+
+  /* Grab a reference on the item */
+  garcon_menu_item_ref (item);
+}
+
+
+
+GarconMenuItem*
+garcon_menu_item_pool_lookup (GarconMenuItemPool *pool,
+                              const gchar        *desktop_id)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM_POOL (pool), NULL);
+  g_return_val_if_fail (desktop_id != NULL, NULL);
+
+  return g_hash_table_lookup (pool->priv->items, desktop_id);
+}
+
+
+
+void 
+garcon_menu_item_pool_foreach (GarconMenuItemPool *pool,
+                               GHFunc              func,
+                               gpointer            user_data)
+{
+  g_return_if_fail (GARCON_IS_MENU_ITEM_POOL (pool));
+
+  g_hash_table_foreach (pool->priv->items, func, user_data);
+}
+
+
+
+void
+garcon_menu_item_pool_apply_exclude_rule (GarconMenuItemPool *pool,
+                                          GNode              *node)
+{
+  g_return_if_fail (GARCON_IS_MENU_ITEM_POOL (pool));
+  g_return_if_fail (node != NULL);
+
+  /* Remove all items which match this exclude rule */
+  g_hash_table_foreach_remove (pool->priv->items, (GHRFunc) garcon_menu_item_pool_filter_exclude, node);
+}
+
+
+
+static gboolean
+garcon_menu_item_pool_filter_exclude (const gchar    *desktop_id,
+                                      GarconMenuItem *item,
+                                      GNode          *node)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
+  g_return_val_if_fail (node != NULL, FALSE);
+  
+  return garcon_menu_node_tree_rule_matches (node, item);
+}
+
+
+
+gboolean
+garcon_menu_item_pool_get_empty (GarconMenuItemPool *pool)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM_POOL (pool), TRUE);
+  return (g_hash_table_size (pool->priv->items) == 0);
+}
diff --git a/garcon/garcon-menu-item-pool.h b/garcon/garcon-menu-item-pool.h
new file mode 100644
index 0000000..db5844c
--- /dev/null
+++ b/garcon/garcon-menu-item-pool.h
@@ -0,0 +1,60 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined(GARCON_INSIDE_GARCON_H) && !defined(GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_ITEM_POOL_H__
+#define __GARCON_MENU_ITEM_POOL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU_ITEM_POOL            (garcon_menu_item_pool_get_type ())
+#define GARCON_MENU_ITEM_POOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_ITEM_POOL, GarconMenuItemPool))
+#define GARCON_MENU_ITEM_POOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU_ITEM_POOL, GarconMenuItemPoolClass))
+#define GARCON_IS_MENU_ITEM_POOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_ITEM_POOL))
+#define GARCON_IS_MENU_ITEM_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU_ITEM_POOL))
+#define GARCON_MENU_ITEM_POOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU_ITEM_POOL, GarconMenuItemPoolClass))
+
+typedef struct _GarconMenuItemPoolPrivate GarconMenuItemPoolPrivate;
+typedef struct _GarconMenuItemPoolClass   GarconMenuItemPoolClass;
+typedef struct _GarconMenuItemPool        GarconMenuItemPool;
+
+GType               garcon_menu_item_pool_get_type           (void) G_GNUC_CONST;
+
+GarconMenuItemPool *garcon_menu_item_pool_new                (void) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+void                garcon_menu_item_pool_insert             (GarconMenuItemPool *pool,
+                                                              GarconMenuItem     *item);
+GarconMenuItem     *garcon_menu_item_pool_lookup             (GarconMenuItemPool *pool,
+                                                              const gchar        *desktop_id);
+void                garcon_menu_item_pool_foreach            (GarconMenuItemPool *pool,
+                                                              GHFunc              func, 
+                                                              gpointer            user_data);
+void                garcon_menu_item_pool_apply_exclude_rule (GarconMenuItemPool *pool,
+                                                              GNode              *node);
+gboolean            garcon_menu_item_pool_get_empty          (GarconMenuItemPool *pool);
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_ITEM_POOL_H__ */
diff --git a/libxfce4menu/xfce-menu-item.c b/garcon/garcon-menu-item.c
similarity index 59%
rename from libxfce4menu/xfce-menu-item.c
rename to garcon/garcon-menu-item.c
index f188e4f..5c3dacd 100644
--- a/libxfce4menu/xfce-menu-item.c
+++ b/garcon/garcon-menu-item.c
@@ -1,7 +1,6 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
+/* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
- * Copyright (c) 2006-2008 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -10,28 +9,28 @@
  *
  * 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
- * Library General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU Library General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#include <libxfce4util/libxfce4util.h>
+#include <gio/gio.h>
 
-#include <libxfce4menu/xfce-menu-environment.h>
-#include <libxfce4menu/xfce-menu-element.h>
-#include <libxfce4menu/xfce-menu-item.h>
+#include <garcon/garcon-environment.h>
+#include <garcon/garcon-menu-element.h>
+#include <garcon/garcon-menu-item.h>
 
 
 
-#define XFCE_MENU_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_MENU_ITEM, XfceMenuItemPrivate))
+#define GARCON_MENU_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GARCON_TYPE_MENU_ITEM, GarconMenuItemPrivate))
 
 
 
@@ -55,29 +54,32 @@ enum
 
 
 
-static void         xfce_menu_item_class_init             (XfceMenuItemClass    *klass);
-static void         xfce_menu_item_element_init           (XfceMenuElementIface *iface);
-static void         xfce_menu_item_init                   (XfceMenuItem         *item);
-static void         xfce_menu_item_finalize               (GObject              *object);
-static void         xfce_menu_item_get_property           (GObject              *object,
-                                                           guint                 prop_id,
-                                                           GValue               *value,
-                                                           GParamSpec           *pspec);
-static void         xfce_menu_item_set_property           (GObject              *object,
-                                                           guint                 prop_id,
-                                                           const GValue         *value,
-                                                           GParamSpec           *pspec);
-static const gchar *xfce_menu_item_get_element_name       (XfceMenuElement      *element);
-static const gchar *xfce_menu_item_get_element_icon_name  (XfceMenuElement      *element);
-
-
-
-struct _XfceMenuItemClass
+static void         garcon_menu_item_class_init                      (GarconMenuItemClass    *klass);
+static void         garcon_menu_item_element_init                    (GarconMenuElementIface *iface);
+static void         garcon_menu_item_init                            (GarconMenuItem         *item);
+static void         garcon_menu_item_finalize                        (GObject                *object);
+static void         garcon_menu_item_get_property                    (GObject                *object,
+                                                                      guint                   prop_id,
+                                                                      GValue                 *value,
+                                                                      GParamSpec             *pspec);
+static void         garcon_menu_item_set_property                    (GObject                *object,
+                                                                      guint                   prop_id,
+                                                                      const GValue           *value,
+                                                                      GParamSpec             *pspec);
+static const gchar *garcon_menu_item_get_element_name                (GarconMenuElement      *element);
+static const gchar *garcon_menu_item_get_element_comment             (GarconMenuElement      *element);
+static const gchar *garcon_menu_item_get_element_icon_name           (GarconMenuElement      *element);
+static gboolean     garcon_menu_item_get_element_visible             (GarconMenuElement      *element);
+static gboolean     garcon_menu_item_get_element_show_in_environment (GarconMenuElement      *element);
+static gboolean     garcon_menu_item_get_element_no_display          (GarconMenuElement      *element);
+
+
+struct _GarconMenuItemClass
 {
   GObjectClass __parent__;
 };
 
-struct _XfceMenuItemPrivate
+struct _GarconMenuItemPrivate
 {
   /* Desktop file id */
   gchar    *desktop_id;
@@ -125,55 +127,48 @@ struct _XfceMenuItemPrivate
   gchar    *path;
 
   /* Counter keeping the number of menus which use this item. This works
-   * like a reference counter and should be increased / decreased by XfceMenu
+   * like a reference counter and should be increased / decreased by GarconMenu
    * items whenever the item is added to or removed from the menu. */
   guint     num_allocated;
 };
 
-struct _XfceMenuItem
+struct _GarconMenuItem
 {
-  GObject __parent__;
+  GObject                  __parent__;
 
   /* < private > */
-  XfceMenuItemPrivate *priv;
+  GarconMenuItemPrivate *priv;
 };
 
 
 
-static GObjectClass *xfce_menu_item_parent_class = NULL;
+static GObjectClass *garcon_menu_item_parent_class = NULL;
 
 
 
 GType
-xfce_menu_item_get_type (void)
+garcon_menu_item_get_type (void)
 {
   static GType type = G_TYPE_INVALID;
 
   if (G_UNLIKELY (type == G_TYPE_INVALID))
     {
-      static const GTypeInfo info = 
-      {
-        sizeof (XfceMenuItemClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_item_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuItem),
-        0,
-        (GInstanceInitFunc) xfce_menu_item_init,
-        NULL,
-      };
-
       static const GInterfaceInfo element_info =
       {
-        (GInterfaceInitFunc) xfce_menu_item_element_init,
+        (GInterfaceInitFunc) garcon_menu_item_element_init,
         NULL,
         NULL,
       };
 
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenuItem", &info, 0);
-      g_type_add_interface_static (type, XFCE_TYPE_MENU_ELEMENT, &element_info);
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            "GarconMenuItem",
+                                            sizeof (GarconMenuItemClass),
+                                            (GClassInitFunc) garcon_menu_item_class_init,
+                                            sizeof (GarconMenuItem),
+                                            (GInstanceInitFunc) garcon_menu_item_init,
+                                            0);
+
+      g_type_add_interface_static (type, GARCON_TYPE_MENU_ELEMENT, &element_info);
     }
   
   return type;
@@ -182,22 +177,22 @@ xfce_menu_item_get_type (void)
 
 
 static void
-xfce_menu_item_class_init (XfceMenuItemClass *klass)
+garcon_menu_item_class_init (GarconMenuItemClass *klass)
 {
   GObjectClass *gobject_class;
 
-  g_type_class_add_private (klass, sizeof (XfceMenuItemPrivate));
+  g_type_class_add_private (klass, sizeof (GarconMenuItemPrivate));
 
   /* Determine the parent type class */
-  xfce_menu_item_parent_class = g_type_class_peek_parent (klass);
+  garcon_menu_item_parent_class = g_type_class_peek_parent (klass);
 
   gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_item_finalize;
-  gobject_class->get_property = xfce_menu_item_get_property;
-  gobject_class->set_property = xfce_menu_item_set_property;
+  gobject_class->finalize = garcon_menu_item_finalize;
+  gobject_class->get_property = garcon_menu_item_get_property;
+  gobject_class->set_property = garcon_menu_item_set_property;
 
   /**
-   * XfceMenuItem:desktop-id:
+   * GarconMenuItem:desktop-id:
    *
    * The desktop-file id of this application.
    **/
@@ -210,9 +205,9 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                         G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:filename:
+   * GarconMenuItem:filename:
    *
-   * The (absolute) filename of the %XfceMenuItem. Whenever this changes, the
+   * The (absolute) filename of the %GarconMenuItem. Whenever this changes, the
    * complete file is reloaded. 
    **/
   g_object_class_install_property (gobject_class,
@@ -224,7 +219,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                         G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:requires-terminal:
+   * GarconMenuItem:requires-terminal:
    *
    * Whether this application requires a terinal to be started in.
    **/
@@ -237,7 +232,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                          G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:no-display:
+   * GarconMenuItem:no-display:
    *
    * Whether this menu item is hidden in menus.
    **/
@@ -250,7 +245,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                          G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:startup-notification:
+   * GarconMenuItem:startup-notification:
    *
    * Whether this application supports startup notification.
    **/
@@ -263,7 +258,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                          G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:name:
+   * GarconMenuItem:name:
    *
    * Name of the application (will be displayed in menus etc.).
    **/
@@ -276,7 +271,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                         G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:generic-name:
+   * GarconMenuItem:generic-name:
    *
    * GenericName of the application (will be displayed in menus etc.).
    **/
@@ -289,7 +284,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                         G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:comment:
+   * GarconMenuItem:comment:
    *
    * Comment/description for the application. To be displayed e.g. in tooltips of
    * GtkMenuItems.
@@ -303,7 +298,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                         G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:command:
+   * GarconMenuItem:command:
    *
    * Command to be executed when the menu item is clicked.
    **/
@@ -316,7 +311,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                         G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:try-exec:
+   * GarconMenuItem:try-exec:
    *
    * TryExec value of the item's desktop entry.
    **/
@@ -329,7 +324,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                         G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:icon-name:
+   * GarconMenuItem:icon-name:
    *
    * Name of the icon to be displayed for this menu item.
    **/
@@ -342,7 +337,7 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
                                                         G_PARAM_READWRITE));
 
   /**
-   * XfceMenuItem:path:
+   * GarconMenuItem:path:
    *
    * Working directory the application should be started in.
    **/
@@ -358,18 +353,22 @@ xfce_menu_item_class_init (XfceMenuItemClass *klass)
 
 
 static void
-xfce_menu_item_element_init (XfceMenuElementIface *iface)
+garcon_menu_item_element_init (GarconMenuElementIface *iface)
 {
-  iface->get_name = xfce_menu_item_get_element_name;
-  iface->get_icon_name = xfce_menu_item_get_element_icon_name;
+  iface->get_name = garcon_menu_item_get_element_name;
+  iface->get_comment = garcon_menu_item_get_element_comment;
+  iface->get_icon_name = garcon_menu_item_get_element_icon_name;
+  iface->get_visible = garcon_menu_item_get_element_visible;
+  iface->get_show_in_environment = garcon_menu_item_get_element_show_in_environment;
+  iface->get_no_display = garcon_menu_item_get_element_no_display;
 }
 
 
 
 static void
-xfce_menu_item_init (XfceMenuItem *item)
+garcon_menu_item_init (GarconMenuItem *item)
 {
-  item->priv = XFCE_MENU_ITEM_GET_PRIVATE (item);
+  item->priv = GARCON_MENU_ITEM_GET_PRIVATE (item);
   item->priv->desktop_id = NULL;
   item->priv->name = NULL;
   item->priv->generic_name = NULL;
@@ -388,9 +387,9 @@ xfce_menu_item_init (XfceMenuItem *item)
 
 
 static void
-xfce_menu_item_finalize (GObject *object)
+garcon_menu_item_finalize (GObject *object)
 {
-  XfceMenuItem *item = XFCE_MENU_ITEM (object);
+  GarconMenuItem *item = GARCON_MENU_ITEM (object);
 
   g_free (item->priv->desktop_id);
   g_free (item->priv->name);
@@ -409,31 +408,31 @@ xfce_menu_item_finalize (GObject *object)
   g_list_foreach (item->priv->categories, (GFunc) g_free, NULL);
   g_list_free (item->priv->categories);
 
-  (*G_OBJECT_CLASS (xfce_menu_item_parent_class)->finalize) (object);
+  (*G_OBJECT_CLASS (garcon_menu_item_parent_class)->finalize) (object);
 }
 
 
 
 static void
-xfce_menu_item_get_property (GObject    *object,
-                             guint       prop_id,
-                             GValue     *value,
-                             GParamSpec *pspec)
+garcon_menu_item_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
 {
-  XfceMenuItem *item = XFCE_MENU_ITEM (object);
+  GarconMenuItem *item = GARCON_MENU_ITEM (object);
 
   switch (prop_id)
     {
     case PROP_DESKTOP_ID:
-      g_value_set_string (value, xfce_menu_item_get_desktop_id (item));
+      g_value_set_string (value, garcon_menu_item_get_desktop_id (item));
       break;
 
     case PROP_FILENAME:
-      g_value_set_string (value, xfce_menu_item_get_filename (item));
+      g_value_set_string (value, garcon_menu_item_get_filename (item));
       break;
 
     case PROP_COMMENT:
-      g_value_set_string (value, xfce_menu_item_get_comment (item));
+      g_value_set_string (value, garcon_menu_item_get_comment (item));
       break;
 
     case PROP_REQUIRES_TERMINAL:
@@ -447,7 +446,7 @@ xfce_menu_item_get_property (GObject    *object,
       break;
 
     case PROP_PATH:
-      g_value_set_string (value, xfce_menu_item_get_path (item));
+      g_value_set_string (value, garcon_menu_item_get_path (item));
       break;
 
     default:
@@ -459,61 +458,61 @@ xfce_menu_item_get_property (GObject    *object,
 
 
 static void
-xfce_menu_item_set_property (GObject      *object,
-                             guint         prop_id,
-                             const GValue *value,
-                             GParamSpec   *pspec)
+garcon_menu_item_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
 {
-  XfceMenuItem *item = XFCE_MENU_ITEM (object);
+  GarconMenuItem *item = GARCON_MENU_ITEM (object);
 
   switch (prop_id)
     {
     case PROP_DESKTOP_ID:
-      xfce_menu_item_set_desktop_id (item, g_value_get_string (value));
+      garcon_menu_item_set_desktop_id (item, g_value_get_string (value));
       break;
 
     case PROP_FILENAME:
-      xfce_menu_item_set_filename (item, g_value_get_string (value));
+      garcon_menu_item_set_filename (item, g_value_get_string (value));
       break;
 
     case PROP_REQUIRES_TERMINAL:
-      xfce_menu_item_set_requires_terminal (item, g_value_get_boolean (value));
+      garcon_menu_item_set_requires_terminal (item, g_value_get_boolean (value));
       break;
 
     case PROP_NO_DISPLAY:
-      xfce_menu_item_set_no_display (item, g_value_get_boolean (value));
+      garcon_menu_item_set_no_display (item, g_value_get_boolean (value));
       break;
 
     case PROP_STARTUP_NOTIFICATION:
-      xfce_menu_item_set_supports_startup_notification (item, g_value_get_boolean (value));
+      garcon_menu_item_set_supports_startup_notification (item, g_value_get_boolean (value));
       break;
 
     case PROP_NAME:
-      xfce_menu_item_set_name (item, g_value_get_string (value));
+      garcon_menu_item_set_name (item, g_value_get_string (value));
       break;
 
     case PROP_GENERIC_NAME:
-      xfce_menu_item_set_generic_name (item, g_value_get_string (value));
+      garcon_menu_item_set_generic_name (item, g_value_get_string (value));
       break;
 
     case PROP_COMMENT:
-      xfce_menu_item_set_comment (item, g_value_get_string (value));
+      garcon_menu_item_set_comment (item, g_value_get_string (value));
       break;
 
     case PROP_COMMAND:
-      xfce_menu_item_set_command (item, g_value_get_string (value));
+      garcon_menu_item_set_command (item, g_value_get_string (value));
       break;
 
     case PROP_TRY_EXEC:
-      xfce_menu_item_set_try_exec (item, g_value_get_string (value));
+      garcon_menu_item_set_try_exec (item, g_value_get_string (value));
       break;
 
     case PROP_ICON_NAME:
-      xfce_menu_item_set_icon_name (item, g_value_get_string (value));
+      garcon_menu_item_set_icon_name (item, g_value_get_string (value));
       break;
 
     case PROP_PATH:
-      xfce_menu_item_set_path (item, g_value_get_string (value));
+      garcon_menu_item_set_path (item, g_value_get_string (value));
       break;
 
     default:
@@ -524,63 +523,74 @@ xfce_menu_item_set_property (GObject      *object,
 
 
 
-XfceMenuItem*
-xfce_menu_item_new (const gchar *filename)
+GarconMenuItem *
+garcon_menu_item_new (const gchar *uri)
 {
-  XfceMenuItem *item = NULL;
-  XfceRc       *rc;
-  const gchar  *path;
-  const gchar  *name;
-  const gchar  *generic_name;
-  const gchar  *comment;
-  const gchar  *exec;
-  const gchar  *try_exec;
-  const gchar  *icon;
-  gchar       **mt;
-  gchar       **str_list;
-  GList        *categories = NULL;
-  gboolean      terminal;
-  gboolean      no_display;
-  gboolean      startup_notify;
+  GarconMenuItem *item = NULL;
+  GKeyFile       *rc;
+  GError         *error = NULL;
+  GFile          *file;
+  GList          *categories = NULL;
+  gboolean        terminal;
+  gboolean        no_display;
+  gboolean        startup_notify;
+  gchar          *path;
+  gchar          *name;
+  gchar          *generic_name;
+  gchar          *comment;
+  gchar          *exec;
+  gchar          *try_exec;
+  gchar          *icon;
+  gchar          *filename;
+  gchar         **mt;
+  gchar         **str_list;
+
+  g_return_val_if_fail (uri != NULL, NULL);
+
+  file = g_file_new_for_uri (uri);
+  filename = g_file_get_path (file);
+  g_object_unref (file);
 
   /* Return NULL if the filename is not an absolute path or if the file does not exists */
   if (G_UNLIKELY (!g_path_is_absolute (filename) || !g_file_test (filename, G_FILE_TEST_EXISTS)))
     return NULL;
 
   /* Try to open the .desktop file */
-  rc = xfce_rc_simple_open (filename, TRUE);
-  if (G_UNLIKELY (rc == NULL))
-    return NULL;
-
-  /* Use the Desktop Entry section of the desktop file */
-  xfce_rc_set_group (rc, "Desktop Entry");
+  rc = g_key_file_new ();
+  g_key_file_load_from_file (rc, filename, G_KEY_FILE_NONE, &error);
+  if (G_UNLIKELY (error != NULL))
+    {
+      g_error_free (error);
+      return NULL;
+    }
 
   /* Abort if the file has been marked as "deleted"/hidden */
-  if (G_UNLIKELY (xfce_rc_read_bool_entry (rc, "Hidden", FALSE)))
+  if (G_UNLIKELY (g_key_file_get_boolean (rc, "Desktop Entry", "Hidden", NULL)))
     {
-      xfce_rc_close (rc);
+      g_key_file_free (rc);
       return NULL;
     }
 
   /* Parse name, exec command and icon name */
-  name = xfce_rc_read_entry (rc, "Name", NULL);
-  generic_name = xfce_rc_read_entry (rc, "GenericName", NULL);
-  comment = xfce_rc_read_entry (rc, "Comment", NULL);
-  exec = xfce_rc_read_entry (rc, "Exec", NULL);
-  try_exec = xfce_rc_read_entry (rc, "TryExec", NULL);
-  icon = xfce_rc_read_entry (rc, "Icon", NULL);
-  path = xfce_rc_read_entry (rc, "Path", NULL);
+  name = g_key_file_get_locale_string (rc, "Desktop Entry", "Name", NULL, NULL);
+  generic_name = g_key_file_get_locale_string (rc, "Desktop Entry", "GenericName", NULL, NULL);
+  comment = g_key_file_get_locale_string (rc, "Desktop Entry", "Comment", NULL, NULL);
+  exec = g_key_file_get_string (rc, "Desktop Entry", "Exec", NULL);
+  try_exec = g_key_file_get_string (rc, "Desktop Entry", "TryExec", NULL);
+  icon = g_key_file_get_string (rc, "Desktop Entry", "Icon", NULL);
+  path = g_key_file_get_string (rc, "Desktop Entry", "Path", NULL);
 
   /* Validate Name and Exec fields */
   if (G_LIKELY (exec != NULL && name != NULL && g_utf8_validate (name, -1, NULL)))
     {
       /* Determine other application properties */
-      terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE);
-      no_display = xfce_rc_read_bool_entry (rc, "NoDisplay", FALSE);
-      startup_notify = xfce_rc_read_bool_entry (rc, "StartupNotify", FALSE) || xfce_rc_read_bool_entry (rc, "X-KDE-StartupNotify", FALSE);
+      terminal = g_key_file_get_boolean (rc, "Desktop Entry", "Terminal", NULL);
+      no_display = g_key_file_get_boolean (rc, "Desktop Entry", "NoDisplay", NULL);
+      startup_notify = g_key_file_get_boolean (rc, "Desktop Entry", "StartupNotify", NULL) ||
+                       g_key_file_get_boolean (rc, "Desktop Entry", "X-KDE-StartupNotify", NULL);
 
       /* Allocate a new menu item instance */
-      item = g_object_new (XFCE_TYPE_MENU_ITEM, 
+      item = g_object_new (GARCON_TYPE_MENU_ITEM, 
                            "filename", filename,
                            "command", exec, 
                            "try-exec", try_exec,
@@ -595,7 +605,7 @@ xfce_menu_item_new (const gchar *filename)
                            NULL);
 
       /* Determine the categories this application should be shown in */
-      str_list = xfce_rc_read_list_entry (rc, "Categories", ";");
+      str_list = g_key_file_get_string_list (rc, "Desktop Entry", "Categories", NULL, NULL);
       if (G_LIKELY (str_list != NULL))
         {
           for (mt = str_list; *mt != NULL; ++mt)
@@ -608,36 +618,45 @@ xfce_menu_item_new (const gchar *filename)
           g_strfreev (str_list);
 
           /* Assign categories list to the menu item */
-          xfce_menu_item_set_categories (item, categories);
+          garcon_menu_item_set_categories (item, categories);
         }
 
       /* Set the rest of the private data directly */
-      item->priv->only_show_in = xfce_rc_read_list_entry (rc, "OnlyShowIn", ";");
-      item->priv->not_show_in = xfce_rc_read_list_entry (rc, "NotShowIn", ";");
+      item->priv->only_show_in = g_key_file_get_string_list (rc, "Desktop Entry", "OnlyShowIn", NULL, NULL);
+      item->priv->not_show_in = g_key_file_get_string_list (rc, "Desktop Entry", "NotShowIn", NULL, NULL);
     }
 
+  /* Free strings */
+  g_free (name);
+  g_free (generic_name);
+  g_free (comment);
+  g_free (exec);
+  g_free (try_exec);
+  g_free (icon);
+  g_free (path);
+
   /* Close file handle */
-  xfce_rc_close (rc);
+  g_key_file_free (rc);
 
   return item;
 }
 
 
 
-const gchar*
-xfce_menu_item_get_desktop_id (XfceMenuItem *item)
+const gchar *
+garcon_menu_item_get_desktop_id (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->desktop_id;
 }
 
 
 
 void
-xfce_menu_item_set_desktop_id (XfceMenuItem *item,
-                               const gchar  *desktop_id)
+garcon_menu_item_set_desktop_id (GarconMenuItem *item,
+                                 const gchar    *desktop_id)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
   g_return_if_fail (desktop_id != NULL);
 
   /* Free old desktop_id */
@@ -660,20 +679,20 @@ xfce_menu_item_set_desktop_id (XfceMenuItem *item,
 
 
 
-const gchar*
-xfce_menu_item_get_filename (XfceMenuItem *item)
+const gchar *
+garcon_menu_item_get_filename (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->filename;
 }
 
 
 
 void
-xfce_menu_item_set_filename (XfceMenuItem *item,
-                             const gchar  *filename)
+garcon_menu_item_set_filename (GarconMenuItem *item,
+                               const gchar    *filename)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
   g_return_if_fail (filename != NULL);
   g_return_if_fail (g_path_is_absolute (filename));
 
@@ -699,19 +718,19 @@ xfce_menu_item_set_filename (XfceMenuItem *item,
 
 
 GList*
-xfce_menu_item_get_categories (XfceMenuItem *item)
+garcon_menu_item_get_categories (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->categories;
 }
 
 
 
 void
-xfce_menu_item_set_categories (XfceMenuItem *item,
-                               GList        *categories)
+garcon_menu_item_set_categories (GarconMenuItem *item,
+                                 GList          *categories)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (G_UNLIKELY (item->priv->categories != NULL))
     {
@@ -731,19 +750,19 @@ xfce_menu_item_set_categories (XfceMenuItem *item,
 
 
 const gchar*
-xfce_menu_item_get_command (XfceMenuItem *item)
+garcon_menu_item_get_command (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->command;
 }
 
 
 
 void
-xfce_menu_item_set_command (XfceMenuItem *item,
-                            const gchar  *command)
+garcon_menu_item_set_command (GarconMenuItem *item,
+                              const gchar    *command)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (G_UNLIKELY (item->priv->command != NULL))
     {
@@ -765,19 +784,19 @@ xfce_menu_item_set_command (XfceMenuItem *item,
 
 
 const gchar*
-xfce_menu_item_get_try_exec (XfceMenuItem *item)
+garcon_menu_item_get_try_exec (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->try_exec;
 }
 
 
 
 void
-xfce_menu_item_set_try_exec (XfceMenuItem *item,
-                             const gchar  *try_exec)
+garcon_menu_item_set_try_exec (GarconMenuItem *item,
+                               const gchar    *try_exec)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (G_UNLIKELY (item->priv->try_exec != NULL))
     {
@@ -799,19 +818,19 @@ xfce_menu_item_set_try_exec (XfceMenuItem *item,
 
 
 const gchar*
-xfce_menu_item_get_name (XfceMenuItem *item)
+garcon_menu_item_get_name (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->name;
 }
 
 
 
 void
-xfce_menu_item_set_name (XfceMenuItem *item,
-                         const gchar  *name)
+garcon_menu_item_set_name (GarconMenuItem *item,
+                           const gchar    *name)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (G_UNLIKELY (item->priv->name != NULL))
     {
@@ -833,19 +852,19 @@ xfce_menu_item_set_name (XfceMenuItem *item,
 
 
 const gchar*
-xfce_menu_item_get_generic_name (XfceMenuItem *item)
+garcon_menu_item_get_generic_name (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->generic_name;
 }
 
 
 
 void
-xfce_menu_item_set_generic_name (XfceMenuItem *item,
-                                 const gchar  *generic_name)
+garcon_menu_item_set_generic_name (GarconMenuItem *item,
+                                   const gchar    *generic_name)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (G_UNLIKELY (item->priv->generic_name != NULL))
     {
@@ -867,19 +886,19 @@ xfce_menu_item_set_generic_name (XfceMenuItem *item,
 
 
 const gchar*
-xfce_menu_item_get_comment (XfceMenuItem *item)
+garcon_menu_item_get_comment (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->comment;
 }
 
 
 
 void
-xfce_menu_item_set_comment (XfceMenuItem *item,
-                                 const gchar  *comment)
+garcon_menu_item_set_comment (GarconMenuItem *item,
+                              const gchar    *comment)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (G_UNLIKELY (item->priv->comment != NULL))
     {
@@ -901,19 +920,19 @@ xfce_menu_item_set_comment (XfceMenuItem *item,
 
 
 const gchar*
-xfce_menu_item_get_icon_name (XfceMenuItem *item)
+garcon_menu_item_get_icon_name (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->icon_name;
 }
 
 
 
 void        
-xfce_menu_item_set_icon_name (XfceMenuItem *item,
-                              const gchar  *icon_name)
+garcon_menu_item_set_icon_name (GarconMenuItem *item,
+                                const gchar    *icon_name)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (G_UNLIKELY (item->priv->icon_name != NULL))
     {
@@ -935,19 +954,19 @@ xfce_menu_item_set_icon_name (XfceMenuItem *item,
 
 
 const gchar*
-xfce_menu_item_get_path (XfceMenuItem *item)
+garcon_menu_item_get_path (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
   return item->priv->path;
 }
 
 
 
 void        
-xfce_menu_item_set_path (XfceMenuItem *item,
-                         const gchar  *path)
+garcon_menu_item_set_path (GarconMenuItem *item,
+                           const gchar    *path)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (G_UNLIKELY (item->priv->path != NULL))
     {
@@ -969,19 +988,19 @@ xfce_menu_item_set_path (XfceMenuItem *item,
 
 
 gboolean
-xfce_menu_item_requires_terminal (XfceMenuItem *item)
+garcon_menu_item_requires_terminal (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
   return item->priv->requires_terminal;
 }
 
 
 
 void        
-xfce_menu_item_set_requires_terminal (XfceMenuItem *item,
-                                      gboolean      requires_terminal)
+garcon_menu_item_set_requires_terminal (GarconMenuItem *item,
+                                        gboolean        requires_terminal)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
   
   /* Abort if old and new value are equal */
   if (item->priv->requires_terminal == requires_terminal)
@@ -997,19 +1016,19 @@ xfce_menu_item_set_requires_terminal (XfceMenuItem *item,
 
 
 gboolean    
-xfce_menu_item_get_no_display (XfceMenuItem *item)
+garcon_menu_item_get_no_display (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
   return item->priv->no_display;
 }
 
 
 
 void        
-xfce_menu_item_set_no_display (XfceMenuItem *item,
-                               gboolean      no_display)
+garcon_menu_item_set_no_display (GarconMenuItem *item,
+                                 gboolean        no_display)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
   
   /* Abort if old and new value are equal */
   if (item->priv->no_display == no_display)
@@ -1025,19 +1044,19 @@ xfce_menu_item_set_no_display (XfceMenuItem *item,
 
 
 gboolean    
-xfce_menu_item_supports_startup_notification (XfceMenuItem *item)
+garcon_menu_item_supports_startup_notification (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
   return item->priv->supports_startup_notification;
 }
 
 
 
 void        
-xfce_menu_item_set_supports_startup_notification (XfceMenuItem *item,
-                                                  gboolean      supports_startup_notification)
+garcon_menu_item_set_supports_startup_notification (GarconMenuItem *item,
+                                                    gboolean        supports_startup_notification)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
   
   /* Abort if old and new value are equal */
   if (item->priv->supports_startup_notification == supports_startup_notification)
@@ -1053,13 +1072,13 @@ xfce_menu_item_set_supports_startup_notification (XfceMenuItem *item,
 
 
 gboolean
-xfce_menu_item_has_category (XfceMenuItem *item,
-                             const gchar  *category)
+garcon_menu_item_has_category (GarconMenuItem *item,
+                               const gchar    *category)
 {
   GList   *iter;
   gboolean found = FALSE;
 
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
   g_return_val_if_fail (category != NULL, FALSE);
 
   for (iter = item->priv->categories; iter != NULL; iter = g_list_next (iter))
@@ -1075,17 +1094,17 @@ xfce_menu_item_has_category (XfceMenuItem *item,
 
 
 gboolean
-xfce_menu_item_show_in_environment (XfceMenuItem *item)
+garcon_menu_item_get_show_in_environment (GarconMenuItem *item)
 {
   const gchar *env;
   gboolean     show = TRUE;
   gboolean     included;
   int          i;
 
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
 
   /* Determine current environment */
-  env = xfce_menu_get_environment ();
+  env = garcon_get_environment ();
 
   /* If no environment has been set, the menu item is displayed no matter what
    * OnlyShowIn or NotShowIn contain */
@@ -1129,16 +1148,16 @@ xfce_menu_item_show_in_environment (XfceMenuItem *item)
 
 
 gboolean
-xfce_menu_item_only_show_in_environment (XfceMenuItem *item)
+garcon_menu_item_only_show_in_environment (GarconMenuItem *item)
 {
   const gchar *env;
   gboolean     show = FALSE;
   int          i;
 
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
 
   /* Determine current environment */
-  env = xfce_menu_get_environment ();
+  env = garcon_get_environment ();
 
   /* If no environment has been set, the contents of OnlyShowIn don't matter */
   if (G_LIKELY (env == NULL))
@@ -1161,12 +1180,12 @@ xfce_menu_item_only_show_in_environment (XfceMenuItem *item)
 
 
 void
-xfce_menu_item_ref (XfceMenuItem *item)
+garcon_menu_item_ref (GarconMenuItem *item)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   /* Increment the allocation counter */
-  xfce_menu_item_increment_allocated (item);
+  garcon_menu_item_increment_allocated (item);
 
   /* Grab a reference on the object */
   g_object_ref (G_OBJECT (item));
@@ -1175,9 +1194,9 @@ xfce_menu_item_ref (XfceMenuItem *item)
 
 
 void
-xfce_menu_item_unref (XfceMenuItem *item)
+garcon_menu_item_unref (GarconMenuItem *item)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   /* Decrement the reference counter */
   g_object_unref (G_OBJECT (item));
@@ -1186,27 +1205,27 @@ xfce_menu_item_unref (XfceMenuItem *item)
 
 
 gint
-xfce_menu_item_get_allocated (XfceMenuItem *item)
+garcon_menu_item_get_allocated (GarconMenuItem *item)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE);
   return item->priv->num_allocated;
 }
 
 
 
 void
-xfce_menu_item_increment_allocated (XfceMenuItem *item)
+garcon_menu_item_increment_allocated (GarconMenuItem *item)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
   item->priv->num_allocated++;
 }
 
 
 
 void
-xfce_menu_item_decrement_allocated (XfceMenuItem *item)
+garcon_menu_item_decrement_allocated (GarconMenuItem *item)
 {
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
   if (item->priv->num_allocated > 0)
     item->priv->num_allocated--;
@@ -1215,17 +1234,66 @@ xfce_menu_item_decrement_allocated (XfceMenuItem *item)
 
 
 static const gchar*
-xfce_menu_item_get_element_name (XfceMenuElement *element)
+garcon_menu_item_get_element_name (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (element), NULL);
+  return GARCON_MENU_ITEM (element)->priv->name;
+}
+
+
+
+static const gchar*
+garcon_menu_item_get_element_comment (GarconMenuElement *element)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (element), NULL);
-  return XFCE_MENU_ITEM (element)->priv->name;
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (element), NULL);
+  return GARCON_MENU_ITEM (element)->priv->comment;
 }
 
 
 
 static const gchar*
-xfce_menu_item_get_element_icon_name (XfceMenuElement *element)
+garcon_menu_item_get_element_icon_name (GarconMenuElement *element)
 {
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (element), NULL);
-  return XFCE_MENU_ITEM (element)->priv->icon_name;
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (element), NULL);
+  return GARCON_MENU_ITEM (element)->priv->icon_name;
 }
+
+
+
+gboolean
+garcon_menu_item_get_element_visible (GarconMenuElement *element)
+{
+  GarconMenuItem *item;
+
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (element), FALSE);
+
+  item = GARCON_MENU_ITEM (element);
+
+  if (!garcon_menu_item_get_show_in_environment (item))
+    return FALSE;
+  else if (garcon_menu_item_get_no_display (item))
+    return FALSE;
+
+  /* TODO Check TryExec as well */
+
+  return TRUE;
+}
+
+
+
+gboolean
+garcon_menu_item_get_element_show_in_environment (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (element), FALSE);
+  return garcon_menu_item_get_show_in_environment (GARCON_MENU_ITEM (element));
+}
+
+
+
+gboolean
+garcon_menu_item_get_element_no_display (GarconMenuElement *element)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (element), FALSE);
+  return garcon_menu_item_get_no_display (GARCON_MENU_ITEM (element));
+}
+
diff --git a/garcon/garcon-menu-item.h b/garcon/garcon-menu-item.h
new file mode 100644
index 0000000..779864b
--- /dev/null
+++ b/garcon/garcon-menu-item.h
@@ -0,0 +1,101 @@
+/* $Id$ */
+/*-
+ * vi:set et ai sts=2 sw=2 cindent:
+ *
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if !defined(GARCON_INSIDE_GARCON_H) && !defined(GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_ITEM_H__
+#define __GARCON_MENU_ITEM_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU_ITEM            (garcon_menu_item_get_type())
+#define GARCON_MENU_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_ITEM, GarconMenuItem))
+#define GARCON_MENU_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU_ITEM, GarconMenuItemClass))
+#define GARCON_IS_MENU_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_ITEM))
+#define GARCON_IS_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU_ITEM))
+#define GARCON_MENU_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU_ITEM, GarconMenuItemClass))
+
+typedef struct _GarconMenuItemPrivate GarconMenuItemPrivate;
+typedef struct _GarconMenuItemClass   GarconMenuItemClass;
+typedef struct _GarconMenuItem        GarconMenuItem;
+
+GType           garcon_menu_item_get_type                          (void) G_GNUC_CONST;
+
+GarconMenuItem *garcon_menu_item_new                               (const gchar  *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+const gchar    *garcon_menu_item_get_desktop_id                    (GarconMenuItem *item);
+void            garcon_menu_item_set_desktop_id                    (GarconMenuItem *item,
+                                                                    const gchar    *desktop_id);
+
+const gchar    *garcon_menu_item_get_filename                      (GarconMenuItem *item);
+void            garcon_menu_item_set_filename                      (GarconMenuItem *item,
+                                                                    const gchar    *filename);
+const gchar    *garcon_menu_item_get_command                       (GarconMenuItem *item);
+void            garcon_menu_item_set_command                       (GarconMenuItem *item,
+                                                                    const gchar    *command);
+const gchar    *garcon_menu_item_get_try_exec                      (GarconMenuItem *item);
+void            garcon_menu_item_set_try_exec                      (GarconMenuItem *item,
+                                                                    const gchar    *try_exec);
+const gchar    *garcon_menu_item_get_name                          (GarconMenuItem *item);
+void            garcon_menu_item_set_name                          (GarconMenuItem *item,
+                                                                    const gchar    *name);
+const gchar    *garcon_menu_item_get_generic_name                  (GarconMenuItem *item);
+void            garcon_menu_item_set_generic_name                  (GarconMenuItem *item,
+                                                                    const gchar    *generic_name);
+const gchar    *garcon_menu_item_get_comment                       (GarconMenuItem *item);
+void            garcon_menu_item_set_comment                       (GarconMenuItem *item,
+                                                                    const gchar    *comment);
+const gchar    *garcon_menu_item_get_icon_name                     (GarconMenuItem *item);
+void            garcon_menu_item_set_icon_name                     (GarconMenuItem *item,
+                                                                    const gchar    *icon_name);
+const gchar    *garcon_menu_item_get_path                          (GarconMenuItem *item);
+void            garcon_menu_item_set_path                          (GarconMenuItem *item,
+                                                                    const gchar    *path);
+gboolean        garcon_menu_item_requires_terminal                 (GarconMenuItem *item);
+void            garcon_menu_item_set_requires_terminal             (GarconMenuItem *item,
+                                                                    gboolean        requires_terminal);
+gboolean        garcon_menu_item_get_no_display                    (GarconMenuItem *item);
+void            garcon_menu_item_set_no_display                    (GarconMenuItem *item,
+                                                                    gboolean        no_display);
+gboolean        garcon_menu_item_supports_startup_notification     (GarconMenuItem *item);
+void            garcon_menu_item_set_supports_startup_notification (GarconMenuItem *item,
+                                                                    gboolean        supports_startup_notification);
+GList          *garcon_menu_item_get_categories                    (GarconMenuItem *item);
+void            garcon_menu_item_set_categories                    (GarconMenuItem *item,
+                                                                    GList          *categories);
+gboolean        garcon_menu_item_has_category                      (GarconMenuItem *item,
+                                                                    const gchar    *category);
+gboolean        garcon_menu_item_get_show_in_environment           (GarconMenuItem *item);
+gboolean        garcon_menu_item_only_show_in_environment          (GarconMenuItem *item);
+void            garcon_menu_item_ref                               (GarconMenuItem *item);
+void            garcon_menu_item_unref                             (GarconMenuItem *item);
+gint            garcon_menu_item_get_allocated                     (GarconMenuItem *item);
+void            garcon_menu_item_increment_allocated               (GarconMenuItem *item);
+void            garcon_menu_item_decrement_allocated               (GarconMenuItem *item);
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_ITEM_H__ */
diff --git a/garcon/garcon-menu-merger.c b/garcon/garcon-menu-merger.c
new file mode 100644
index 0000000..42a05d3
--- /dev/null
+++ b/garcon/garcon-menu-merger.c
@@ -0,0 +1,1196 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <garcon/garcon-menu-node.h>
+#include <garcon/garcon-menu-tree-provider.h>
+#include <garcon/garcon-menu-parser.h>
+#include <garcon/garcon-menu-merger.h>
+#include <garcon/garcon-gio.h>
+
+
+
+typedef struct _GarconMenuMergerContext GarconMenuMergerContext;
+
+struct _GarconMenuMergerContext
+{
+  GarconMenuNodeType node_type;
+  GarconMenuMerger  *merger;
+  GCancellable      *cancellable;
+  GError           **error;
+  gboolean           success;
+  GList             *file_stack;
+};
+
+
+
+#define GARCON_MENU_MERGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GARCON_TYPE_MENU_MERGER, GarconMenuMergerPrivate))
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+  PROP_TREE_PROVIDER,
+};
+
+
+
+static void     garcon_menu_merger_class_init              (GarconMenuMergerClass       *klass);
+static void     garcon_menu_merger_provider_init           (GarconMenuTreeProviderIface *iface);
+static void     garcon_menu_merger_init                    (GarconMenuMerger            *merger);
+static void     garcon_menu_merger_constructed             (GObject                     *object);
+static void     garcon_menu_merger_finalize                (GObject                     *object);
+static void     garcon_menu_merger_get_property            (GObject                     *object,
+                                                            guint                        prop_id,
+                                                            GValue                      *value,
+                                                            GParamSpec                  *pspec);
+static void     garcon_menu_merger_set_property            (GObject                     *object,
+                                                            guint                        prop_id,
+                                                            const GValue                *value,
+                                                            GParamSpec                  *pspec);
+static GNode   *garcon_menu_merger_get_tree                (GarconMenuTreeProvider      *provider);
+static GFile   *garcon_menu_merger_get_file                (GarconMenuTreeProvider      *provider);
+static gboolean garcon_menu_merger_resolve_default_dirs    (GNode                       *node,
+                                                            GarconMenuMergerContext     *context);
+static gboolean garcon_menu_merger_resolve_relative_paths  (GNode                       *node,
+                                                            GarconMenuMergerContext     *context);
+static void     garcon_menu_merger_remove_duplicate_paths  (GNode                       *node,
+                                                            GarconMenuNodeType           type);
+static void     garcon_menu_merger_consolidate_child_menus (GNode                       *node);
+static gboolean garcon_menu_merger_resolve_merge_dirs      (GNode                       *node,
+                                                            GarconMenuMergerContext     *context);
+static gboolean garcon_menu_merger_process_merge_files     (GNode                       *node,
+                                                            GarconMenuMergerContext     *context);
+static void     garcon_menu_merger_clean_up_elements       (GNode                       *node,
+                                                            GarconMenuNodeType           type);
+static void     garcon_menu_merger_resolve_moves           (GNode                       *node);
+static void     garcon_menu_merger_prepend_default_layout  (GNode                       *node);
+
+
+
+struct _GarconMenuMergerPrivate
+{
+  GarconMenuTreeProvider *tree_provider;
+  GNode                  *menu;
+  GList                  *file_stack;
+};
+
+
+
+static GObjectClass *garcon_menu_merger_parent_class = NULL;
+
+
+
+GType
+garcon_menu_merger_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GInterfaceInfo provider_info = 
+      {
+        (GInterfaceInitFunc) garcon_menu_merger_provider_init,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static_simple (G_TYPE_OBJECT, 
+                                            "GarconMenuMerger",
+                                            sizeof (GarconMenuMergerClass),
+                                            (GClassInitFunc) garcon_menu_merger_class_init,
+                                            sizeof (GarconMenuMerger),
+                                            (GInstanceInitFunc) garcon_menu_merger_init,
+                                            0);
+
+      g_type_add_interface_static (type, GARCON_TYPE_MENU_TREE_PROVIDER, &provider_info);
+    }
+
+  return type;
+}
+
+
+
+static void
+garcon_menu_merger_class_init (GarconMenuMergerClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (GarconMenuMergerPrivate));
+
+  /* Determine the parent type class */
+  garcon_menu_merger_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = garcon_menu_merger_finalize; 
+  gobject_class->constructed = garcon_menu_merger_constructed;
+  gobject_class->get_property = garcon_menu_merger_get_property;
+  gobject_class->set_property = garcon_menu_merger_set_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_TREE_PROVIDER,
+                                   g_param_spec_object ("tree-provider",
+                                                        "tree-provider",
+                                                        "tree-provider",
+                                                        GARCON_TYPE_MENU_TREE_PROVIDER,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+
+
+static void 
+garcon_menu_merger_provider_init (GarconMenuTreeProviderIface *iface)
+{
+  iface->get_tree = garcon_menu_merger_get_tree;
+  iface->get_file = garcon_menu_merger_get_file;
+}
+
+
+
+static void
+garcon_menu_merger_init (GarconMenuMerger *merger)
+{
+  merger->priv = GARCON_MENU_MERGER_GET_PRIVATE (merger);
+  merger->priv->tree_provider = NULL;
+  merger->priv->menu = NULL;
+  merger->priv->file_stack = NULL;
+}
+
+
+
+static void
+garcon_menu_merger_constructed (GObject *object)
+{
+  GarconMenuMerger *merger = GARCON_MENU_MERGER (object);
+
+  merger->priv->menu = garcon_menu_tree_provider_get_tree (merger->priv->tree_provider);
+}
+
+
+
+static void
+garcon_menu_merger_finalize (GObject *object)
+{
+  GarconMenuMerger *merger = GARCON_MENU_MERGER (object);
+
+  garcon_menu_node_tree_free (merger->priv->menu);
+
+  g_object_unref (merger->priv->tree_provider);
+
+  (*G_OBJECT_CLASS (garcon_menu_merger_parent_class)->finalize) (object);
+}
+
+
+
+static void
+garcon_menu_merger_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  GarconMenuMerger *merger = GARCON_MENU_MERGER (object);
+
+  switch (prop_id)
+    {
+    case PROP_TREE_PROVIDER:
+      g_value_set_object (value, g_object_ref (merger->priv->tree_provider));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+garcon_menu_merger_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  GarconMenuMerger *merger = GARCON_MENU_MERGER (object);
+
+  switch (prop_id)
+    {
+    case PROP_TREE_PROVIDER:
+      merger->priv->tree_provider = g_object_ref (g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+GarconMenuMerger *
+garcon_menu_merger_new (GarconMenuTreeProvider *provider)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_TREE_PROVIDER (provider), NULL);
+  return g_object_new (GARCON_TYPE_MENU_MERGER, "tree-provider", provider, NULL);
+}
+
+
+
+gboolean
+garcon_menu_merger_prepare_merging (GarconMenuMerger        *merger,
+                                    GNode                   *tree,
+                                    GarconMenuMergerContext *context)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_MERGER (merger), FALSE);
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  context->node_type = GARCON_MENU_NODE_TYPE_INVALID;
+  g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_resolve_default_dirs, 
+                   context);
+
+  context->node_type = GARCON_MENU_NODE_TYPE_MERGE_DIR;
+  g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_resolve_relative_paths,
+                   context);
+
+  context->node_type = GARCON_MENU_NODE_TYPE_MERGE_FILE;
+  g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_resolve_relative_paths,
+                   context);
+
+  garcon_menu_merger_remove_duplicate_paths (tree, GARCON_MENU_NODE_TYPE_MERGE_DIR);
+
+  g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_resolve_merge_dirs,
+                   context);
+
+  garcon_menu_merger_remove_duplicate_paths (tree, GARCON_MENU_NODE_TYPE_MERGE_FILE);
+
+  return context->success;
+}
+
+
+
+gboolean
+garcon_menu_merger_run (GarconMenuMerger *merger,
+                        GCancellable     *cancellable,
+                        GError          **error)
+{
+  GarconMenuMergerContext context;
+  GFile                  *file;
+
+  g_return_val_if_fail (GARCON_IS_MENU_MERGER (merger), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  context.merger = merger;
+  context.cancellable = cancellable;
+  context.error = error;
+  context.success = TRUE;
+  context.file_stack = NULL;
+
+  file = garcon_menu_tree_provider_get_file (GARCON_MENU_TREE_PROVIDER (merger));
+  context.file_stack = g_list_concat (context.file_stack, merger->priv->file_stack);
+  context.file_stack = g_list_prepend (context.file_stack, file);
+
+  garcon_menu_merger_prepare_merging (merger, merger->priv->menu, &context);
+
+  g_node_traverse (merger->priv->menu, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_process_merge_files,
+                   &context);
+
+  garcon_menu_merger_consolidate_child_menus (merger->priv->menu);
+
+  context.node_type = GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS;
+  g_node_traverse (merger->priv->menu, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_resolve_default_dirs,
+                   &context);
+
+  context.node_type = GARCON_MENU_NODE_TYPE_APP_DIR;
+  g_node_traverse (merger->priv->menu, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_resolve_relative_paths,
+                   &context);
+
+  garcon_menu_merger_remove_duplicate_paths (merger->priv->menu, GARCON_MENU_NODE_TYPE_APP_DIR);
+
+  context.node_type = GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS;
+  g_node_traverse (merger->priv->menu, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_resolve_default_dirs,
+                   &context);
+
+  context.node_type = GARCON_MENU_NODE_TYPE_DIRECTORY_DIR;
+  g_node_traverse (merger->priv->menu, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                   (GNodeTraverseFunc) garcon_menu_merger_resolve_relative_paths,
+                   &context);
+
+  garcon_menu_merger_remove_duplicate_paths (merger->priv->menu,GARCON_MENU_NODE_TYPE_DIRECTORY_DIR);
+  garcon_menu_merger_remove_duplicate_paths (merger->priv->menu, GARCON_MENU_NODE_TYPE_DIRECTORY);
+
+  garcon_menu_merger_resolve_moves (merger->priv->menu);
+
+  garcon_menu_merger_consolidate_child_menus (merger->priv->menu);
+
+  garcon_menu_merger_clean_up_elements (merger->priv->menu, GARCON_MENU_NODE_TYPE_DELETED);
+  garcon_menu_merger_clean_up_elements (merger->priv->menu, GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED);
+
+  garcon_menu_merger_prepend_default_layout (merger->priv->menu);
+  garcon_menu_merger_clean_up_elements (merger->priv->menu, GARCON_MENU_NODE_TYPE_LAYOUT);
+
+  g_list_foreach (context.file_stack, (GFunc) g_object_unref, NULL);
+  g_list_free (context.file_stack);
+
+  return context.success;
+}
+
+
+
+static GNode *
+garcon_menu_merger_get_tree (GarconMenuTreeProvider *provider)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_MERGER (provider), NULL);
+  return garcon_menu_node_tree_copy (GARCON_MENU_MERGER (provider)->priv->menu);
+}
+
+
+
+static GFile *
+garcon_menu_merger_get_file (GarconMenuTreeProvider *provider)
+{
+  GarconMenuTreeProvider *provider_;
+
+  g_return_val_if_fail (GARCON_IS_MENU_MERGER (provider), NULL);
+
+  provider_ = GARCON_MENU_MERGER (provider)->priv->tree_provider;
+  return garcon_menu_tree_provider_get_file (provider_);
+}
+
+
+
+static void
+garcon_menu_merger_insert_default_dirs (GNode *parent,
+                                        GNode *defaults_node)
+{
+  GarconMenuNodeType   type;
+  GNode               *node;
+  GNode               *prev_node;
+  const gchar * const *dirs;
+  const gchar         *kde_dir;
+  int                  i;
+  gchar               *path;
+  gchar               *kde_data_dir;
+  const gchar         *basename;
+
+  g_return_if_fail (parent != NULL);
+  g_return_if_fail (defaults_node != NULL);
+
+  prev_node = defaults_node;
+
+  if  (garcon_menu_node_tree_get_node_type (defaults_node) == GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS)
+    {
+      basename = "desktop-directories";
+      type = GARCON_MENU_NODE_TYPE_DIRECTORY_DIR;
+    }
+  else
+    {
+      basename = "applications";
+      type = GARCON_MENU_NODE_TYPE_APP_DIR;
+    }
+
+  /* Append $KDEDIR/share/desktop-directories and $KDEDIR/share/applications 
+   * as a workaround for distributions not installing KDE menu files 
+   * properly into $XDG_DATA_DIRS */
+
+  /* Get KDEDIR environment variable */
+  kde_dir = g_getenv ("KDEDIR");
+
+  /* Check if this variable is set */
+  if (G_UNLIKELY (kde_dir != NULL))
+    {
+      /* Build KDE data dir */
+      kde_data_dir = g_build_filename (kde_dir, "share", basename, NULL);
+
+      /* Add it as a directory dir if it exists */
+      if (G_LIKELY (g_file_test (kde_data_dir, G_FILE_TEST_IS_DIR)))
+        {
+          node = g_node_new (garcon_menu_node_create (type, kde_data_dir));
+          prev_node = g_node_insert_after (parent, prev_node, node);
+        }
+
+      /* Free the KDE data dir */
+      g_free (kde_data_dir);
+    }
+
+  /* The $KDEDIR workaround ends here */
+
+  /* Append system-wide data dirs */
+  dirs = g_get_system_data_dirs ();
+  for (i = 0; dirs[i] != NULL; i++)
+    {
+      path = g_build_path (G_DIR_SEPARATOR_S, dirs[i], basename, NULL);
+      if (G_LIKELY (g_file_test (path, G_FILE_TEST_IS_DIR)))
+        {
+          node = g_node_new (garcon_menu_node_create (type, path));
+          prev_node = g_node_insert_after (parent, prev_node, node);
+        }
+      g_free (path);
+    }
+
+  /* Append user data dir */
+  path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), basename, NULL);
+  if (G_LIKELY (g_file_test (path, G_FILE_TEST_IS_DIR)))
+    {
+      node = g_node_new (garcon_menu_node_create (type, path));
+      prev_node = g_node_insert_after (parent, prev_node, node);
+    }
+  g_free (path);
+}
+
+
+
+static void
+garcon_menu_merger_insert_default_merge_dirs (GNode *parent,
+                                              GNode *defaults_node)
+{
+  GNode               *node;
+  GNode               *prev_node;
+  const gchar * const *dirs;
+  int                  i;
+  gchar               *path;
+
+  g_return_if_fail (parent != NULL);
+  g_return_if_fail (defaults_node != NULL);
+
+  prev_node = defaults_node;
+
+  /* Append system-wide config dirs */
+  dirs = g_get_system_config_dirs ();
+  for (i = 0; dirs[i] != NULL; i++)
+    {
+      path = g_build_path (G_DIR_SEPARATOR_S, dirs[i], "menus", "applications-merged", NULL);
+      if (G_LIKELY (g_file_test (path, G_FILE_TEST_IS_DIR)))
+        {
+          node = g_node_new (garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE_DIR, path));
+          prev_node = g_node_insert_after (parent, prev_node, node);
+        }
+      g_free (path);
+    }
+
+  /* Append user config dir */
+  path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_config_dir (), "menus", 
+                       "applications-merged", NULL);
+  if (G_LIKELY (g_file_test (path, G_FILE_TEST_IS_DIR)))
+    {
+      node = g_node_new (garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE_DIR, path));
+      prev_node = g_node_insert_after (parent, prev_node, node);
+    }
+  g_free (path);
+}
+
+
+
+static gboolean 
+garcon_menu_merger_resolve_default_dirs (GNode                   *node,
+                                         GarconMenuMergerContext *context)
+{
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  if (garcon_menu_node_tree_get_node_type (node) == context->node_type)
+    {
+      garcon_menu_merger_insert_default_dirs (node->parent, node);
+      garcon_menu_node_tree_free (node);
+    }
+  else if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS)
+    {
+      garcon_menu_merger_insert_default_merge_dirs (node->parent, node);
+      garcon_menu_node_tree_free (node);
+    }
+
+  return FALSE;
+}
+
+
+
+static gboolean 
+garcon_menu_merger_resolve_relative_paths (GNode                   *node,
+                                           GarconMenuMergerContext *context)
+{
+  GFile               *source_file;
+  const gchar * const *system_config_dirs;
+  const gchar        **config_dirs;
+  gchar               *absolute_path = NULL;
+  gchar               *relative_path = NULL;
+  gint                 i;
+
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  if (garcon_menu_node_tree_get_node_type (node) != context->node_type)
+    return FALSE;
+
+  source_file = g_list_first (context->file_stack)->data;
+
+  if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_APP_DIR ||
+      garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_DIRECTORY_DIR ||
+      garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_MERGE_DIR)
+    {
+      relative_path = (gchar *)garcon_menu_node_tree_get_string (node);
+      absolute_path = g_file_get_uri_relative_to_file (relative_path, source_file);
+      garcon_menu_node_tree_set_string (node, absolute_path);
+      g_free (absolute_path);
+    }
+  else if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_MERGE_FILE)
+    {
+      if (garcon_menu_node_tree_get_merge_file_type (node) == GARCON_MENU_MERGE_FILE_PATH)
+        {
+          relative_path = (gchar *)garcon_menu_node_tree_get_merge_file_filename (node);
+          absolute_path = g_file_get_uri_relative_to_file (relative_path, source_file);
+          garcon_menu_node_tree_set_merge_file_filename (node, absolute_path);
+          g_free (absolute_path);
+        }
+      else
+        {
+          system_config_dirs = g_get_system_config_dirs ();
+
+          config_dirs = g_new0 (const gchar *, 2 + g_strv_length ((gchar **)system_config_dirs));
+
+          config_dirs[0] = g_get_user_config_dir ();
+          config_dirs[1 + g_strv_length ((gchar **)system_config_dirs)] = NULL;
+
+          for (i = 0; system_config_dirs[i] != NULL; ++i)
+            config_dirs[i+1] = system_config_dirs[i];
+
+          /* Find the parent XDG_CONFIG_DIRS entry for the current menu file */
+          for (i = 0; relative_path == NULL && config_dirs[i] != NULL; ++i)
+            {
+              GFile *config_dir = g_file_new_for_unknown_input (config_dirs[i], NULL);
+              relative_path = g_file_get_relative_path (config_dir, source_file);
+              g_object_unref (config_dir);
+            }
+
+          /* Look for the same relative path in the XDG_CONFIG_DIRS entries after the parent 
+           * of the current menu file */
+          for (; relative_path != NULL && config_dirs[i] != NULL; ++i)
+            {
+              GFile *config_dir = g_file_new_for_unknown_input (config_dirs[i], NULL);
+              GFile *absolute = g_file_resolve_relative_path (config_dir, relative_path);
+
+              if (G_LIKELY (absolute != NULL))
+                {
+                  if (G_UNLIKELY (g_file_query_exists (absolute, NULL)))
+                    {
+                      absolute_path = g_file_get_uri (absolute);
+
+                      /* Destroy the MenuFile type="parent" information */
+                      garcon_menu_node_tree_free_data (node);
+
+                      /* Replace it with a MergeFile type="path" element */
+                      node->data = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE_FILE,
+                                                            GUINT_TO_POINTER (GARCON_MENU_MERGE_FILE_PATH));
+                      garcon_menu_node_tree_set_merge_file_filename (node, absolute_path);
+                    }
+                  g_object_unref (absolute);
+                  break;
+                }
+              g_object_unref (config_dir);
+            }
+
+          /* No file with the same relative filename found in XDG_CONFIG_DIRS */
+          if (absolute_path == NULL || i >= g_strv_length ((gchar **)config_dirs))
+            {
+              /* Remove the MenuFile type="parent" node */
+              garcon_menu_node_tree_free (node);
+            }
+
+          g_free (absolute_path);
+          g_free (relative_path);
+          g_free (config_dirs);
+        }
+    }
+
+  return FALSE;
+}
+
+
+
+static void
+garcon_menu_merger_remove_duplicate_paths (GNode             *node,
+                                           GarconMenuNodeType type)
+{
+  GList *destroy_nodes = NULL;
+  GList *remaining_nodes = NULL;
+  GNode *child;
+
+  g_return_if_fail (node != NULL);
+
+  if (garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_MENU)
+    return;
+
+  for (child = g_node_last_child (node); child != NULL; child = g_node_prev_sibling (child))
+    {
+      if (garcon_menu_node_tree_get_node_type (child) == GARCON_MENU_NODE_TYPE_MENU)
+        {
+          garcon_menu_merger_remove_duplicate_paths (child, type);
+          continue;
+        }
+
+      if (garcon_menu_node_tree_get_node_type (child) != type)
+        continue;
+
+      if (G_LIKELY (g_list_find_custom (remaining_nodes, child, 
+                                        (GCompareFunc) garcon_menu_node_tree_compare) == NULL))
+        {
+          remaining_nodes = g_list_prepend (remaining_nodes, child);
+        }
+      else
+        destroy_nodes = g_list_prepend (destroy_nodes, child);
+    }
+
+  g_list_foreach (destroy_nodes, (GFunc) garcon_menu_node_tree_free, NULL);
+  g_list_free (destroy_nodes);
+  g_list_free (remaining_nodes);
+}
+
+
+
+static gboolean
+collect_name (GNode        *node,
+              const gchar **name)
+{
+  if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_NAME)
+    {
+      *name = garcon_menu_node_tree_get_string (node);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+
+
+static void
+garcon_menu_merger_move_nodes (GNode *source,
+                               GNode *target,
+                               GNode *position)
+{
+  GNode *child;
+
+  for (child = g_node_first_child (source); child != NULL; child = g_node_next_sibling (child))
+    if (garcon_menu_node_tree_get_node_type (child) != GARCON_MENU_NODE_TYPE_NAME)
+      g_node_insert_before (target, position, g_node_copy (child));
+}
+
+
+
+static void
+garcon_menu_merger_consolidate_child_menus (GNode *node)
+{
+  GHashTable  *table;
+  GNode       *child;
+  GNode       *next_child;
+  GNode       *target;
+  const gchar *name;
+
+  if (garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_MENU)
+    return;
+
+  table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+  /* Determine the last child menu for each child menu name */
+  for (child = g_node_last_child (node); child != NULL; child = g_node_prev_sibling (child))
+    {
+      if (garcon_menu_node_tree_get_node_type (child) != GARCON_MENU_NODE_TYPE_MENU)
+        continue;
+
+      name = NULL;
+      g_node_traverse (child, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                       (GNodeTraverseFunc) collect_name, &name);
+
+      if (G_UNLIKELY (g_hash_table_lookup (table, name) == NULL))
+        g_hash_table_insert (table, g_strdup (name), child);
+    }
+
+  for (child = g_node_first_child (node); child != NULL; )
+    {
+      if (garcon_menu_node_tree_get_node_type (child) == GARCON_MENU_NODE_TYPE_MENU)
+        {
+          name = NULL;
+          g_node_traverse (child, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                           (GNodeTraverseFunc) collect_name, &name);
+
+          target = g_hash_table_lookup (table, name);
+
+          if (G_LIKELY (target != NULL && child != target))
+            {
+              garcon_menu_merger_move_nodes (child, target, g_node_first_child (target));
+
+              next_child = g_node_next_sibling (child);
+              g_node_destroy (child);
+              child = g_node_prev_sibling (next_child);
+            }
+        }
+
+        child = g_node_next_sibling (child);
+    }
+
+  for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
+    garcon_menu_merger_consolidate_child_menus (child);
+
+  g_hash_table_unref (table);
+}
+
+
+
+static gboolean
+garcon_menu_merger_resolve_merge_dirs (GNode                   *node,
+                                       GarconMenuMergerContext *context)
+{
+  GFileEnumerator *enumerator;
+  GFileInfo       *file_info;
+  GFile           *file;
+  GFile           *dir;
+  GNode           *file_node;
+  gchar           *uri;
+
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  /* Skip elements that are not MergeDirs */
+  if (garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_MERGE_DIR)
+    return FALSE;
+
+  dir = g_file_new_for_unknown_input (garcon_menu_node_tree_get_string (node), NULL);
+
+  enumerator = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 
+                                          G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+  if (G_UNLIKELY (enumerator != NULL))
+    {
+      while (TRUE)
+        {
+          file_info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+
+          if (G_UNLIKELY (file_info == NULL))
+            break;
+
+          if (G_LIKELY (g_str_has_suffix (g_file_info_get_name (file_info), ".menu")))
+            {
+              file_node = g_node_new (garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE_FILE,
+                                                               GARCON_MENU_MERGE_FILE_PATH));
+
+              file = g_file_resolve_relative_path (dir, g_file_info_get_name (file_info));
+              uri = g_file_get_uri (file);
+
+              garcon_menu_node_tree_set_merge_file_filename (file_node, uri);
+
+              g_free (uri);
+              g_object_unref (file);
+
+              g_node_insert_after (node->parent, node, file_node);
+            }
+          
+          g_object_unref (file_info);
+        }
+
+      g_object_unref (enumerator);
+    }
+
+  garcon_menu_node_tree_free (node);
+
+  g_object_unref (dir);
+
+  return FALSE;
+}
+
+
+
+static gboolean
+garcon_menu_parser_insert_elements (GNode *node,
+                                    GNode *origin)
+{
+  if (node == origin)
+    return FALSE;
+
+  if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_NAME)
+    {
+      garcon_menu_node_tree_free (node);
+      return FALSE;
+    }
+
+  g_node_insert_before (origin->parent, origin, g_node_copy (node));
+
+  return FALSE;
+}
+
+
+
+static gint
+compare_files (GFile *file,
+               GFile *other_file)
+{
+  return g_file_equal (file, other_file) ? 0 : 1;
+}
+
+
+
+
+static gboolean
+garcon_menu_merger_process_merge_files (GNode                   *node,
+                                        GarconMenuMergerContext *context)
+{
+  GarconMenuMerger *merger;
+  GarconMenuParser *parser;
+  GFile            *file;
+  GNode            *tree;
+
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  if (garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_MERGE_FILE ||
+      garcon_menu_node_tree_get_merge_file_type (node) != GARCON_MENU_MERGE_FILE_PATH)
+    {
+      return FALSE;
+    }
+
+  file = g_file_new_for_uri (garcon_menu_node_tree_get_merge_file_filename (node));
+
+  if (G_UNLIKELY (g_list_find_custom (context->file_stack, file, 
+                                      (GCompareFunc) compare_files) != NULL))
+    {
+      g_object_unref (file);
+      return FALSE;
+    }
+
+  parser = garcon_menu_parser_new (file);
+  g_object_unref (file);
+
+  if (G_LIKELY (garcon_menu_parser_run (parser, NULL, NULL)))
+    {
+      merger = garcon_menu_merger_new (GARCON_MENU_TREE_PROVIDER (parser));
+      g_object_unref (parser);
+
+      merger->priv->file_stack = g_list_copy (context->file_stack);
+      g_list_foreach (merger->priv->file_stack, (GFunc) g_object_ref, NULL);
+
+      if (G_LIKELY (garcon_menu_merger_run (merger, NULL, NULL)))
+        {
+          tree = garcon_menu_tree_provider_get_tree (GARCON_MENU_TREE_PROVIDER (merger));
+          g_object_unref (merger);
+
+          g_node_insert_after (node->parent, node, tree);
+          g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                           (GNodeTraverseFunc) garcon_menu_parser_insert_elements, tree);
+          g_node_destroy (tree);
+        }
+    }
+  
+  garcon_menu_node_tree_free (node);
+
+  return FALSE;
+}
+
+
+
+static void 
+garcon_menu_merger_clean_up_elements (GNode             *node,
+                                      GarconMenuNodeType type)
+{
+  GNode *child;
+  GNode *remaining_node = NULL;
+  GList *destroy_list = NULL;
+
+  for (child = g_node_last_child (node); child != NULL; child = g_node_prev_sibling (child))
+    {
+      if (garcon_menu_node_tree_get_node_type (child) == GARCON_MENU_NODE_TYPE_MENU)
+        {
+          garcon_menu_merger_clean_up_elements (child, type);
+          continue;
+        }
+
+      if (type == GARCON_MENU_NODE_TYPE_DELETED 
+          && garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_DELETED
+          && garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_NOT_DELETED)
+        {
+          continue;
+        }
+
+      if (type == GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED
+          && garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED
+          && garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED)
+        {
+          continue;
+        }
+      
+      if (type == GARCON_MENU_NODE_TYPE_LAYOUT 
+          && garcon_menu_node_tree_get_node_type (child) != GARCON_MENU_NODE_TYPE_LAYOUT)
+        {
+          continue;
+        }
+      
+      if (remaining_node != NULL)
+        destroy_list = g_list_prepend (destroy_list, child);
+      else
+        remaining_node = child;
+    }
+
+  g_list_foreach (destroy_list, (GFunc) garcon_menu_node_tree_free, NULL);
+  g_list_free (destroy_list);
+
+  if (type == GARCON_MENU_NODE_TYPE_LAYOUT 
+      && remaining_node != NULL 
+      && G_NODE_IS_LEAF (remaining_node))
+    {
+      garcon_menu_node_tree_free (remaining_node);
+    }
+}
+
+
+
+static gboolean
+collect_moves (GNode  *node,
+               GList **list)
+{
+  if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_MOVE)
+    *list = g_list_append (*list, node);
+
+  return FALSE;
+}
+
+
+
+static gboolean
+remove_moves (GNode *node)
+{
+  if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_MOVE)
+    garcon_menu_node_tree_free (node);
+
+  return FALSE;
+}
+
+
+
+static gboolean
+collect_old_new (GNode  *node,
+                 GList **list)
+{
+  if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_OLD)
+    *list = g_list_append (*list, g_strdup (garcon_menu_node_tree_get_string (node)));
+  else if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_NEW)
+    *list = g_list_append (*list, g_strdup (garcon_menu_node_tree_get_string (node)));
+
+  return FALSE;
+}
+
+
+
+static GNode *
+garcon_menu_merger_find_menu_with_name (GNode       *node,
+                                        const gchar *name)
+{
+  GNode       *result = NULL;
+  GNode       *child;
+  const gchar *child_name;
+
+  for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
+    if (garcon_menu_node_tree_get_node_type (child) == GARCON_MENU_NODE_TYPE_MENU)
+      {
+        child_name = NULL;
+        g_node_traverse (child, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                         (GNodeTraverseFunc) collect_name, &child_name);
+
+        if (g_str_equal (child_name, name))
+          {
+            result = child;
+            break;
+          }
+      }
+
+  return result;
+}
+
+
+
+static GNode *
+garcon_menu_merger_find_menu (GNode  *node,
+                              gchar **path,
+                              gint    position,
+                              gint    depth,
+                              GNode **parent)
+{
+  GNode *result = NULL;
+  GNode *child;
+
+  g_return_val_if_fail (position <= depth, NULL);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (path != NULL, NULL);
+
+  /* Make sure to set parent to NULL unless the path is valid */
+  if (parent != NULL)
+    *parent = NULL;
+
+  /* Search for the direct child which has the name equal to the current
+   * path componenent */
+  child = garcon_menu_merger_find_menu_with_name (node, path[position]);
+
+  if (G_UNLIKELY (child == NULL))
+    return NULL;
+
+  if (G_LIKELY (position == depth))
+    {
+      result = child;
+
+      if (parent != NULL)
+        *parent = node;
+    }
+  else
+    result = garcon_menu_merger_find_menu (child, path, position+1, depth, parent);
+
+  return result;
+}
+
+
+
+static GNode *
+garcon_menu_merger_create_menu (GNode  *node,
+                                gchar **path,
+                                gint    position,
+                                gint    depth)
+{
+  GNode *result = NULL;
+  GNode *child;
+
+  g_return_val_if_fail (position <= depth, NULL);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (path != NULL, NULL);
+
+  /* Search for the direct child which has the name equal to the current
+   * path componenent */
+  child = garcon_menu_merger_find_menu_with_name (node, path[position]);
+
+  /* Create it if it doesn't exist */
+  if (G_LIKELY (child == NULL))
+    {
+      child = g_node_append_data (node, NULL);
+      g_node_append_data (child, garcon_menu_node_create (GARCON_MENU_NODE_TYPE_NAME, 
+                                                          path[position]));
+    }
+
+  if (G_LIKELY (position == depth))
+    result = child;
+  else
+    result = garcon_menu_merger_create_menu (child, path, position+1, depth);
+
+  return result;
+}
+
+
+
+static void
+garcon_menu_merger_resolve_moves (GNode *node)
+{
+  GNode  *child;
+  GNode  *old_node;
+  GNode  *new_node;
+  GList  *moves = NULL;
+  GList  *pairs = NULL;
+  GList  *iter;
+  gchar **old_path;
+  gchar **new_path;
+
+  if (garcon_menu_node_tree_get_node_type (node) != GARCON_MENU_NODE_TYPE_MENU)
+    return;
+
+  for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
+    garcon_menu_merger_resolve_moves (child);
+
+  g_node_traverse (node, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                   (GNodeTraverseFunc) collect_moves, &moves);
+
+  for (iter = moves; iter != NULL; iter = g_list_next (iter))
+    {
+      g_node_traverse (iter->data, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                       (GNodeTraverseFunc) collect_old_new, &pairs);
+    }
+
+  g_node_traverse (node, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                   (GNodeTraverseFunc) remove_moves, &moves);
+
+  for (iter = pairs; iter != NULL; iter = g_list_next (iter))
+    {
+      if (g_list_length (iter) < 2)
+        break;
+
+      old_path = g_strsplit (iter->data, "/", -1);
+      iter = g_list_next (iter);
+      new_path = g_strsplit (iter->data, "/", -1);
+
+      old_node = garcon_menu_merger_find_menu (node, old_path, 0, 
+                                               g_strv_length (old_path)-1, NULL);
+      new_node = garcon_menu_merger_find_menu (node, new_path, 0, 
+                                               g_strv_length (new_path)-1, NULL);
+
+      if (G_LIKELY (old_node != NULL && old_node != new_node))
+        {
+          if (G_LIKELY (new_node == NULL))
+            {
+              new_node = garcon_menu_merger_create_menu (node, new_path, 0,
+                                                         g_strv_length (new_path)-1);
+
+              garcon_menu_merger_move_nodes (old_node, new_node, NULL);
+            }
+          else
+            garcon_menu_merger_move_nodes (old_node, new_node, 
+                                           g_node_first_child (new_node));
+
+          g_node_destroy (old_node);
+        }
+
+      g_strfreev (old_path);
+      g_strfreev (new_path);
+    }
+
+  g_list_foreach (pairs, (GFunc) g_free, NULL);
+  g_list_free (pairs);
+}
+
+
+
+static void
+garcon_menu_merger_prepend_default_layout (GNode *node)
+{
+  GarconMenuNode *node_;
+  GNode        *layout;
+
+  if (garcon_menu_node_tree_get_node_type (node) == GARCON_MENU_NODE_TYPE_MENU)
+    {
+      node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT, NULL);
+      layout = g_node_prepend_data (node, node_);
+
+      node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE, 
+                                       GUINT_TO_POINTER (GARCON_MENU_LAYOUT_MERGE_MENUS));
+      g_node_append_data (layout, node_);
+
+      node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE,
+                                       GUINT_TO_POINTER (GARCON_MENU_LAYOUT_MERGE_FILES));
+      g_node_append_data (layout, node_);
+    }
+}
+
diff --git a/garcon/garcon-menu-merger.h b/garcon/garcon-menu-merger.h
new file mode 100644
index 0000000..45a63ca
--- /dev/null
+++ b/garcon/garcon-menu-merger.h
@@ -0,0 +1,67 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined (GARCON_INSIDE_GARCON_H) && !defined (GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_MERGER_H__
+#define __GARCON_MENU_MERGER_H__
+
+#include <garcon/garcon.h>
+#include <garcon/garcon-menu-tree-provider.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU_MERGER            (garcon_menu_merger_get_type ())
+#define GARCON_MENU_MERGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_MERGER, GarconMenuMerger))
+#define GARCON_MENU_MERGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU_MERGER, GarconMenuMergerClass))
+#define GARCON_IS_MENU_MERGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_MERGER))
+#define GARCON_IS_MENU_MERGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU_MERGER)
+#define GARCON_MENU_MERGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU_MERGER, GarconMenuMergerClass))
+
+typedef struct _GarconMenuMergerPrivate GarconMenuMergerPrivate;
+typedef struct _GarconMenuMergerClass   GarconMenuMergerClass;
+typedef struct _GarconMenuMerger        GarconMenuMerger;
+
+GType             garcon_menu_merger_get_type (void) G_GNUC_CONST;
+
+GarconMenuMerger *garcon_menu_merger_new      (GarconMenuTreeProvider *provider) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+gboolean          garcon_menu_merger_run      (GarconMenuMerger       *merger,
+                                               GCancellable           *cancellable,
+                                               GError                **error);
+
+
+
+struct _GarconMenuMergerClass
+{
+  GObjectClass __parent__;
+};
+
+struct _GarconMenuMerger
+{
+  GObject                  __parent__;
+
+  GarconMenuMergerPrivate *priv;
+};
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_MERGER_H__ */
diff --git a/garcon/garcon-menu-monitor.c b/garcon/garcon-menu-monitor.c
new file mode 100644
index 0000000..cf69832
--- /dev/null
+++ b/garcon/garcon-menu-monitor.c
@@ -0,0 +1,363 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <garcon/garcon-menu-monitor.h>
+#include <garcon/garcon-menu-item.h>
+#include <garcon/garcon.h>
+
+
+
+/* Initial vtable configuration */
+static GarconMenuMonitorVTable garcon_menu_monitor_vtable = {
+  NULL,
+  NULL,
+  NULL,
+};
+
+/* Monitor flags */
+static GarconMenuMonitorFlags garcon_menu_monitor_flags;
+
+/* User data as provided by the client */
+static gpointer               garcon_menu_monitor_user_data = NULL;
+
+/* Hash table with (GarconMenuItem => gpointer) pairs */
+static GHashTable            *garcon_menu_monitor_item_handles;
+
+/* Hash table with (Directory => gpointer) pairs */
+static GHashTable            *garcon_menu_monitor_shared_handles;
+
+/* Structure for directory handles */
+typedef struct _SharedHandle  
+{
+  gpointer monitor_handle;
+  int      references;
+} SharedHandle;
+
+
+
+void 
+_garcon_menu_monitor_init (void)
+{
+  /* Initialize hash tables */
+  garcon_menu_monitor_item_handles = g_hash_table_new (NULL, NULL);
+  garcon_menu_monitor_shared_handles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+  garcon_menu_monitor_flags = GARCON_MENU_MONITOR_DIRECTORIES
+                              | GARCON_MENU_MONITOR_MENU_FILES
+                              | GARCON_MENU_MONITOR_DIRECTORY_FILES
+                              | GARCON_MENU_MONITOR_DESKTOP_FILES;
+}
+
+
+
+void
+_garcon_menu_monitor_shutdown (void)
+{
+  g_hash_table_unref (garcon_menu_monitor_item_handles);
+  g_hash_table_unref (garcon_menu_monitor_shared_handles);
+}
+
+
+
+/**
+ * garcon_menu_monitor_set_vtable:
+ * @vtable    : a #GarconMenuMonitorVTable
+ * @user_data : custom pointer to be passed to the vtable functions.
+ *
+ * Sets the functions to be called when monitoring a file or directory
+ * becomes necessary. See #GarconMenuMonitorVTable for more detailled
+ * information. Be careful with redefining the #GarconMenuMonitorVTable 
+ * (e.g. don't redefine it while there are any #GarconMenu's around).
+ *
+ * In order to change the user data, just pass the same 
+ * #GarconMenuMonitorVTable as you did before. Pass NULL to clear the
+ * vtable (e.g. if you want to disable monitoring support).
+ */
+void
+garcon_menu_monitor_set_vtable (GarconMenuMonitorVTable *vtable,
+                                gpointer                 user_data)
+{
+  if (G_UNLIKELY (vtable == NULL))
+    {
+      garcon_menu_monitor_vtable.monitor_file = NULL;
+      garcon_menu_monitor_vtable.monitor_directory = NULL;
+      garcon_menu_monitor_vtable.remove_monitor = NULL;
+    }
+  else
+    {
+      garcon_menu_monitor_vtable.monitor_file = vtable->monitor_file;
+      garcon_menu_monitor_vtable.monitor_directory = vtable->monitor_directory;
+      garcon_menu_monitor_vtable.remove_monitor = vtable->remove_monitor;
+    }
+
+  garcon_menu_monitor_user_data = user_data;
+}
+
+
+
+gpointer
+garcon_menu_monitor_add_item (GarconMenu     *menu,
+                              GarconMenuItem *item)
+{
+  gpointer monitor_handle;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), NULL);
+  
+  if (G_UNLIKELY (garcon_menu_monitor_vtable.monitor_file == NULL))
+    return NULL;
+
+  /* Request monitor handle from the library client */
+  monitor_handle = garcon_menu_monitor_vtable.monitor_file (menu, garcon_menu_item_get_filename (item), 
+                                                            garcon_menu_monitor_user_data);
+
+  if (G_LIKELY (monitor_handle != NULL))
+    {
+      /* Store the item => handle pair in the hash table */
+      g_hash_table_insert (garcon_menu_monitor_item_handles, item, monitor_handle);
+    }
+
+  return monitor_handle;
+}
+
+
+
+void
+garcon_menu_monitor_remove_item (GarconMenu     *menu,
+                                 GarconMenuItem *item)
+{
+  gpointer monitor_handle;
+
+  g_return_if_fail (GARCON_IS_MENU_ITEM (item));
+  
+  if (G_UNLIKELY (garcon_menu_monitor_vtable.remove_monitor == NULL))
+    return;
+
+  /* Lookup the monitor handle for this item */
+  monitor_handle = g_hash_table_lookup (garcon_menu_monitor_item_handles, item);
+
+  if (G_LIKELY (monitor_handle != NULL))
+    {
+      /* Remove monitor handle from the library client */
+      garcon_menu_monitor_vtable.remove_monitor (menu, monitor_handle);
+
+      /* ... and remove the item from the hash table */
+      g_hash_table_remove (garcon_menu_monitor_item_handles, item);
+    }
+}
+
+
+
+gpointer
+garcon_menu_monitor_add_directory (GarconMenu  *menu,
+                                   const gchar *directory)
+{
+  SharedHandle *shared_handle;
+  gpointer         monitor_handle;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  g_return_val_if_fail (directory != NULL, NULL);
+  
+  if (G_UNLIKELY (garcon_menu_monitor_vtable.monitor_directory == NULL))
+    return NULL;
+
+  /* Load directory handle from the hash table */
+  shared_handle = (SharedHandle *)g_hash_table_lookup (garcon_menu_monitor_shared_handles, 
+                                                       directory);
+
+  /* Check if the directory is already monitored */
+  if (G_LIKELY (shared_handle != NULL))
+    {
+      /* Increment reference counter */
+      shared_handle->references++;
+
+      /* Return the monitor handle */
+      monitor_handle = shared_handle->monitor_handle;
+    }
+  else
+    {
+      /* Request monitor handle from the library client */
+      monitor_handle = garcon_menu_monitor_vtable.monitor_directory (menu, directory, 
+                                                                     garcon_menu_monitor_user_data);
+
+      if (G_LIKELY (monitor_handle != NULL))
+        {
+          /* Allocate new directory handle */
+          shared_handle = g_new0 (SharedHandle, 1);
+
+          /* Set values (reference counter starts with 1) */
+          shared_handle->references = 1;
+          shared_handle->monitor_handle = monitor_handle;
+
+          /* Store the item => handle pair in the hash table */
+          g_hash_table_insert (garcon_menu_monitor_shared_handles, 
+                               g_strdup (directory), shared_handle);
+        }
+    }
+
+  return monitor_handle;
+}
+
+
+
+void
+garcon_menu_monitor_remove_directory (GarconMenu  *menu,
+                                      const gchar *directory)
+{
+  SharedHandle *shared_handle;
+
+  g_return_if_fail (directory != NULL);
+  
+  if (G_UNLIKELY (garcon_menu_monitor_vtable.remove_monitor == NULL))
+    return;
+
+  /* Lookup the directory handle for this directory */
+  shared_handle = g_hash_table_lookup (garcon_menu_monitor_shared_handles, directory);
+
+  if (G_LIKELY (shared_handle != NULL))
+    {
+      /* Decrement the reference counter */
+      shared_handle->references--;
+
+      /* Check if there are no references left */
+      if (G_UNLIKELY (shared_handle->references == 0)) 
+        {
+          /* Remove monitor handle from the library client */
+          garcon_menu_monitor_vtable.remove_monitor (menu, shared_handle->monitor_handle);
+
+          /* Remove directory handle from the hash table and destroy it */
+          g_hash_table_remove (garcon_menu_monitor_shared_handles, directory);
+        }
+    }
+}
+
+
+
+gpointer
+garcon_menu_monitor_add_file (GarconMenu  *menu,
+                              const gchar *filename)
+{
+  SharedHandle *shared_handle;
+  gpointer      monitor_handle;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  g_return_val_if_fail (filename != NULL, NULL);
+  
+  if (G_UNLIKELY (garcon_menu_monitor_vtable.monitor_file == NULL))
+    return NULL;
+
+  /* Load filename handle from the hash table */
+  shared_handle = (SharedHandle *)g_hash_table_lookup (garcon_menu_monitor_shared_handles, 
+                                                       filename);
+
+  /* Check if the file is already monitored */
+  if (G_LIKELY (shared_handle != NULL))
+    {
+      /* Increment reference counter */
+      shared_handle->references++;
+
+      /* Return the monitor handle */
+      monitor_handle = shared_handle->monitor_handle;
+    }
+  else
+    {
+      /* Request monitor handle from the library client */
+      monitor_handle = garcon_menu_monitor_vtable.monitor_file (menu, filename, 
+                                                                garcon_menu_monitor_user_data);
+
+      if (G_LIKELY (monitor_handle != NULL))
+        {
+          /* Allocate new filename handle */
+          shared_handle = g_new0 (SharedHandle, 1);
+
+          /* Set values (reference counter starts with 1) */
+          shared_handle->references = 1;
+          shared_handle->monitor_handle = monitor_handle;
+
+          /* Store the item => handle pair in the hash table */
+          g_hash_table_insert (garcon_menu_monitor_shared_handles, 
+                               g_strdup (filename), shared_handle);
+        }
+    }
+
+  return monitor_handle;
+}
+
+
+
+void
+garcon_menu_monitor_remove_file (GarconMenu  *menu,
+                                 const gchar *filename)
+{
+  SharedHandle *shared_handle;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+  g_return_if_fail (filename != NULL);
+  
+  if (G_UNLIKELY (garcon_menu_monitor_vtable.remove_monitor == NULL))
+    return;
+
+  /* Lookup the filename handle for this file */
+  shared_handle = g_hash_table_lookup (garcon_menu_monitor_shared_handles, filename);
+
+  if (G_LIKELY (shared_handle != NULL))
+    {
+      /* Decrement the reference counter */
+      shared_handle->references--;
+
+      /* Check if there are no references left */
+      if (G_UNLIKELY (shared_handle->references == 0)) 
+        {
+          /* Remove monitor handle from the library client */
+          garcon_menu_monitor_vtable.remove_monitor (menu, shared_handle->monitor_handle);
+
+          /* Remove filename handle from the hash table and destroy it */
+          g_hash_table_remove (garcon_menu_monitor_shared_handles, shared_handle);
+        }
+    }
+}
+
+
+
+void 
+garcon_menu_monitor_set_flags (GarconMenuMonitorFlags flags)
+{
+  garcon_menu_monitor_flags = flags;
+}
+
+
+
+GarconMenuMonitorFlags 
+garcon_menu_monitor_get_flags (void)
+{
+  return garcon_menu_monitor_flags;
+}
+
+
+
+gboolean
+garcon_menu_monitor_has_flags (GarconMenuMonitorFlags flags)
+{
+  return (garcon_menu_monitor_flags & flags) != 0;
+}
+
diff --git a/garcon/garcon-menu-monitor.h b/garcon/garcon-menu-monitor.h
new file mode 100644
index 0000000..ce8e4f4
--- /dev/null
+++ b/garcon/garcon-menu-monitor.h
@@ -0,0 +1,101 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined (GARCON_INSIDE_GARCON_H) && !defined (GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_MONITOR_H__
+#define __GARCON_MENU_MONITOR_H__
+
+#include <garcon/garcon.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+  GARCON_MENU_MONITOR_DIRECTORIES     = 1 << 0,
+  GARCON_MENU_MONITOR_MENU_FILES      = 1 << 1,
+  GARCON_MENU_MONITOR_DIRECTORY_FILES = 1 << 2,
+  GARCON_MENU_MONITOR_DESKTOP_FILES   = 1 << 3
+} GarconMenuMonitorFlags;
+
+typedef struct _GarconMenuMonitorVTable GarconMenuMonitorVTable;
+
+void                   garcon_menu_monitor_set_vtable       (GarconMenuMonitorVTable *vtable, 
+                                                             gpointer                 user_data);
+gpointer               garcon_menu_monitor_add_item         (GarconMenu              *menu,
+                                                             GarconMenuItem          *item);
+void                   garcon_menu_monitor_remove_item      (GarconMenu              *menu,
+                                                             GarconMenuItem          *item);
+gpointer               garcon_menu_monitor_add_directory    (GarconMenu              *menu,
+                                                             const gchar             *directory);
+void                   garcon_menu_monitor_remove_directory (GarconMenu              *menu,
+                                                             const gchar             *directory);
+gpointer               garcon_menu_monitor_add_file         (GarconMenu              *menu,
+                                                             const gchar             *filename);
+void                   garcon_menu_monitor_remove_file      (GarconMenu              *menu,
+                                                             const gchar             *filename);
+void                   garcon_menu_monitor_set_flags        (GarconMenuMonitorFlags   flags);
+GarconMenuMonitorFlags garcon_menu_monitor_get_flags        (void);
+gboolean               garcon_menu_monitor_has_flags        (GarconMenuMonitorFlags   flags);
+
+/**
+ * GarconMenuMonitorVTable:
+ * @monitor_file      : Function called by garcon to request that
+ *                      a file should be monitored.
+ * @monitor_directory : Function called by garcon to request that
+ *                      a directory should be monitored.
+ * @remove_monitor    : Function called by garcon to request that
+ *                      a file or directory monitor should be 
+ *                      cancelled/removed.
+ *
+ * This structure can be used by clients of the garcon API to 
+ * register functions which will be called whenever monitoring a
+ * certain file or directory becomes necessary. This way garcon
+ * only has to manage the monitor handles and leaves the monitoring
+ * implementations to the client.
+ *
+ * This mechanism was invented because the two main API clients, 
+ * Thunar and xfdesktop are already linked to ThunarVFS which has
+ * monitoring capabilities.
+ **/
+struct _GarconMenuMonitorVTable
+{
+  gpointer (*monitor_file)      (GarconMenu    *menu,
+                                 const gchar *filename,
+                                 gpointer     user_data);
+
+  gpointer (*monitor_directory) (GarconMenu    *menu,
+                                 const gchar *filename,
+                                 gpointer     user_data);
+
+  void     (*remove_monitor)    (GarconMenu    *menu,
+                                 gpointer     monitor_handle);
+};
+
+#if defined(GARCON_COMPILATION)
+void _garcon_menu_monitor_init     (void) G_GNUC_INTERNAL;
+void _garcon_menu_monitor_shutdown (void) G_GNUC_INTERNAL;
+#endif
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_MONITOR_H__ */
diff --git a/garcon/garcon-menu-node.c b/garcon/garcon-menu-node.c
new file mode 100644
index 0000000..fd686bb
--- /dev/null
+++ b/garcon/garcon-menu-node.c
@@ -0,0 +1,842 @@
+/* vi:set sw=2 sts=2 ts=2 et ai: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU General Public License as published by 
+ * the Free Software Foundation; either version 2 of the License, or (at 
+ * your option) any later version.
+ *
+ * This program 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 
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ * MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <garcon/garcon-menu-item.h>
+#include <garcon/garcon-menu-node.h>
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+  PROP_NODE_TYPE,
+};
+
+
+
+static void garcon_menu_node_class_init   (GarconMenuNodeClass *klass);
+static void garcon_menu_node_init         (GarconMenuNode      *node);
+static void garcon_menu_node_finalize     (GObject             *object);
+static void garcon_menu_node_get_property (GObject             *object,
+                                           guint                prop_id,
+                                           GValue              *value,
+                                           GParamSpec          *pspec);
+static void garcon_menu_node_set_property (GObject             *object,
+                                           guint                prop_id,
+                                           const GValue        *value,
+                                           GParamSpec          *pspec);
+static void garcon_menu_node_free_data    (GarconMenuNode      *node);
+
+
+
+struct _GarconMenuNodeClass
+{
+  GObjectClass __parent__;
+};
+
+union _GarconMenuNodeData
+{
+  GarconMenuLayoutMergeType layout_merge_type;
+  struct 
+  {
+    GarconMenuMergeFileType type;
+    gchar                  *filename;
+  } merge_file;
+  gchar                    *string;
+};
+
+struct _GarconMenuNode
+{
+  GObject            __parent__;
+
+  GarconMenuNodeType node_type;
+  GarconMenuNodeData data;
+};
+
+
+
+static GObjectClass *garcon_menu_node_parent_class = NULL;
+
+
+
+GType
+garcon_menu_node_type_get_type (void)
+{
+  static GType      type = G_TYPE_INVALID;
+  static GEnumValue values[] = 
+  {
+    { GARCON_MENU_NODE_TYPE_INVALID, "GARCON_MENU_NODE_TYPE_INVALID", "Invalid" },
+    { GARCON_MENU_NODE_TYPE_MENU, "GARCON_MENU_NODE_TYPE_MENU", "Menu" },
+    { GARCON_MENU_NODE_TYPE_NAME, "GARCON_MENU_NODE_TYPE_NAME", "Name" },
+    { GARCON_MENU_NODE_TYPE_DIRECTORY, "GARCON_MENU_NODE_TYPE_DIRECTORY", "Directory" },
+    { GARCON_MENU_NODE_TYPE_DIRECTORY_DIR, "GARCON_MENU_NODE_TYPE_DIRECTORY_DIR", "DirectoryDir" },
+    { GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS", "DefaultDirectoryDirs" },
+    { GARCON_MENU_NODE_TYPE_APP_DIR, "GARCON_MENU_NODE_TYPE_APP_DIR", "AppDir" },
+    { GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS", "DefaultAppDirs" },
+    { GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED, "GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED", "OnlyUnallocated" },
+    { GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED, "GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED", "NotOnlyUnallocated" },
+    { GARCON_MENU_NODE_TYPE_DELETED, "GARCON_MENU_NODE_TYPE_DELETED", "Deleted" },
+    { GARCON_MENU_NODE_TYPE_NOT_DELETED, "GARCON_MENU_NODE_TYPE_NOT_DELETED", "NotDeleted" },
+    { GARCON_MENU_NODE_TYPE_INCLUDE, "GARCON_MENU_NODE_TYPE_INCLUDE", "Include" },
+    { GARCON_MENU_NODE_TYPE_EXCLUDE, "GARCON_MENU_NODE_TYPE_EXCLUDE", "Exclude" },
+    { GARCON_MENU_NODE_TYPE_ALL, "GARCON_MENU_NODE_TYPE_ALL", "All" },
+    { GARCON_MENU_NODE_TYPE_FILENAME, "GARCON_MENU_NODE_TYPE_FILENAME", "Filename" },
+    { GARCON_MENU_NODE_TYPE_CATEGORY, "GARCON_MENU_NODE_TYPE_CATEGORY", "Category" },
+    { GARCON_MENU_NODE_TYPE_OR, "GARCON_MENU_NODE_TYPE_OR", "Or" },
+    { GARCON_MENU_NODE_TYPE_AND, "GARCON_MENU_NODE_TYPE_AND", "And" },
+    { GARCON_MENU_NODE_TYPE_NOT, "GARCON_MENU_NODE_TYPE_NOT", "Not" },
+    { GARCON_MENU_NODE_TYPE_MOVE, "GARCON_MENU_NODE_TYPE_MOVE", "Move" },
+    { GARCON_MENU_NODE_TYPE_OLD, "GARCON_MENU_NODE_TYPE_OLD", "Old" },
+    { GARCON_MENU_NODE_TYPE_NEW, "GARCON_MENU_NODE_TYPE_NEW", "New" },
+    { GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT, "GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT", "DefaultLayout" },
+    { GARCON_MENU_NODE_TYPE_LAYOUT, "GARCON_MENU_NODE_TYPE_LAYOUT", "Layout" },
+    { GARCON_MENU_NODE_TYPE_MENUNAME, "GARCON_MENU_NODE_TYPE_MENUNAME", "Menuname" },
+    { GARCON_MENU_NODE_TYPE_SEPARATOR, "GARCON_MENU_NODE_TYPE_SEPARATOR", "Separator" },
+    { GARCON_MENU_NODE_TYPE_MERGE, "GARCON_MENU_NODE_TYPE_MERGE", "Merge" },
+    { GARCON_MENU_NODE_TYPE_MERGE_FILE, "GARCON_MENU_NODE_TYPE_MERGE_FILE", "MergeFile" },
+    { GARCON_MENU_NODE_TYPE_MERGE_DIR, "GARCON_MENU_NODE_TYPE_MERGE_DIR", "MergeDir" },
+    { GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS", "MergeDirs" },
+    { 0, NULL, NULL },
+  };
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    type = g_enum_register_static ("GarconMenuNodeType", values);
+
+  return type;
+}
+
+
+
+GType
+garcon_menu_node_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      type = g_type_register_static_simple (G_TYPE_OBJECT, 
+                                            "GarconMenuNode",
+                                            sizeof (GarconMenuNodeClass),
+                                            (GClassInitFunc) garcon_menu_node_class_init,
+                                            sizeof (GarconMenuNode),
+                                            (GInstanceInitFunc) garcon_menu_node_init,
+                                            0);
+    }
+
+  return type;
+}
+
+
+
+static void
+garcon_menu_node_class_init (GarconMenuNodeClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  /* Determine the parent type class */
+  garcon_menu_node_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = garcon_menu_node_finalize; 
+  gobject_class->get_property = garcon_menu_node_get_property;
+  gobject_class->set_property = garcon_menu_node_set_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_NODE_TYPE,
+                                   g_param_spec_enum ("node-type",
+                                                      "node-type",
+                                                      "node-type",
+                                                      garcon_menu_node_type_get_type (),
+                                                      GARCON_MENU_NODE_TYPE_MENU,
+                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
+}
+
+
+
+static void
+garcon_menu_node_init (GarconMenuNode *node)
+{
+}
+
+
+
+static void
+garcon_menu_node_finalize (GObject *object)
+{
+  GarconMenuNode *node = GARCON_MENU_NODE (object);
+
+  garcon_menu_node_free_data (node);
+
+  (*G_OBJECT_CLASS (garcon_menu_node_parent_class)->finalize) (object);
+}
+
+
+
+static void
+garcon_menu_node_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  GarconMenuNode *node = GARCON_MENU_NODE (object);
+
+  switch (prop_id)
+    {
+    case PROP_NODE_TYPE:
+      g_value_set_enum (value, node->node_type);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+garcon_menu_node_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  GarconMenuNode *node = GARCON_MENU_NODE (object);
+
+  switch (prop_id)
+    {
+    case PROP_NODE_TYPE:
+      node->node_type = g_value_get_enum (value);
+      g_object_notify (G_OBJECT (node), "node-type");
+      break;
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+GarconMenuNode *
+garcon_menu_node_new (GarconMenuNodeType node_type)
+{
+  return g_object_new (GARCON_TYPE_MENU_NODE, "node-type", node_type, NULL);
+}
+
+
+
+GarconMenuNodeType garcon_menu_node_get_node_type (GarconMenuNode *node)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_NODE (node), 0);
+  return node->node_type;
+}
+
+
+
+GarconMenuNode *
+garcon_menu_node_create (GarconMenuNodeType node_type,
+                         gpointer           first_value,
+                         ...)
+{
+  GarconMenuNode *node;
+
+  node = garcon_menu_node_new (node_type);
+
+  switch (node_type)
+    {
+    case GARCON_MENU_NODE_TYPE_NAME:
+    case GARCON_MENU_NODE_TYPE_DIRECTORY:
+    case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
+    case GARCON_MENU_NODE_TYPE_APP_DIR:
+    case GARCON_MENU_NODE_TYPE_FILENAME:
+    case GARCON_MENU_NODE_TYPE_CATEGORY:
+    case GARCON_MENU_NODE_TYPE_OLD:
+    case GARCON_MENU_NODE_TYPE_NEW:
+    case GARCON_MENU_NODE_TYPE_MENUNAME:
+    case GARCON_MENU_NODE_TYPE_MERGE_DIR:
+      node->data.string = g_strdup (first_value);
+      break;
+
+    case GARCON_MENU_NODE_TYPE_MERGE:
+      node->data.layout_merge_type = GPOINTER_TO_UINT (first_value);
+      break;
+
+    case GARCON_MENU_NODE_TYPE_MERGE_FILE:
+      node->data.merge_file.type = GPOINTER_TO_UINT (first_value);
+      node->data.merge_file.filename = NULL;
+      break;
+
+    default:
+      break;
+    }
+
+  return node;
+}
+
+
+
+GarconMenuNode *
+garcon_menu_node_copy (GarconMenuNode *node)
+{
+  GarconMenuNode *copy;
+
+  if (node == NULL || !GARCON_IS_MENU_NODE (node))
+    return NULL;
+
+  copy = garcon_menu_node_new (node->node_type);
+
+  switch (copy->node_type)
+    {
+    case GARCON_MENU_NODE_TYPE_NAME:
+    case GARCON_MENU_NODE_TYPE_DIRECTORY:
+    case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
+    case GARCON_MENU_NODE_TYPE_APP_DIR:
+    case GARCON_MENU_NODE_TYPE_FILENAME:
+    case GARCON_MENU_NODE_TYPE_CATEGORY:
+    case GARCON_MENU_NODE_TYPE_OLD:
+    case GARCON_MENU_NODE_TYPE_NEW:
+    case GARCON_MENU_NODE_TYPE_MENUNAME:
+    case GARCON_MENU_NODE_TYPE_MERGE_DIR:
+      copy->data.string = g_strdup (node->data.string);
+      break;
+
+    case GARCON_MENU_NODE_TYPE_MERGE:
+      copy->data.layout_merge_type = node->data.layout_merge_type;
+      break;
+
+    case GARCON_MENU_NODE_TYPE_MERGE_FILE:
+      copy->data.merge_file.type = node->data.merge_file.type;
+      copy->data.merge_file.filename = g_strdup (node->data.merge_file.filename);
+      break;
+
+    default:
+      break;
+    }
+
+  return copy;
+}
+
+
+
+static void
+garcon_menu_node_free_data (GarconMenuNode *node)
+{
+  g_return_if_fail (GARCON_IS_MENU_NODE (node));
+
+  switch (node->node_type)
+    {
+    case GARCON_MENU_NODE_TYPE_NAME:
+    case GARCON_MENU_NODE_TYPE_DIRECTORY:
+    case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
+    case GARCON_MENU_NODE_TYPE_APP_DIR:
+    case GARCON_MENU_NODE_TYPE_FILENAME:
+    case GARCON_MENU_NODE_TYPE_CATEGORY:
+    case GARCON_MENU_NODE_TYPE_OLD:
+    case GARCON_MENU_NODE_TYPE_NEW:
+    case GARCON_MENU_NODE_TYPE_MENUNAME:
+    case GARCON_MENU_NODE_TYPE_MERGE_DIR:
+      g_free (node->data.string);
+      break;
+
+    default:
+      break;
+    }
+}
+
+
+
+const gchar *
+garcon_menu_node_get_string (GarconMenuNode *node)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_NODE (node), NULL);
+  return node->data.string;
+}
+
+
+
+void
+garcon_menu_node_set_string (GarconMenuNode *node,
+                             const gchar    *value)
+{
+  g_return_if_fail (GARCON_IS_MENU_NODE (node));
+  g_return_if_fail (value != NULL);
+
+  g_free (node->data.string);
+  node->data.string = g_strdup (value);
+}
+
+
+
+GarconMenuMergeFileType
+garcon_menu_node_get_merge_file_type (GarconMenuNode *node)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_NODE (node), 0);
+  g_return_val_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE, 0);
+  return node->data.merge_file.type;
+}
+
+
+
+void
+garcon_menu_node_set_merge_file_type (GarconMenuNode         *node,
+                                      GarconMenuMergeFileType type)
+{
+  g_return_if_fail (GARCON_IS_MENU_NODE (node));
+  g_return_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE);
+  node->data.merge_file.type = type;
+}
+
+
+
+const gchar *
+garcon_menu_node_get_merge_file_filename (GarconMenuNode *node)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_NODE (node), NULL);
+  g_return_val_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE, NULL);
+  return node->data.merge_file.filename;
+}
+
+
+
+void
+garcon_menu_node_set_merge_file_filename (GarconMenuNode *node,
+                                          const gchar    *filename)
+{
+  g_return_if_fail (GARCON_IS_MENU_NODE (node));
+  g_return_if_fail (filename != NULL);
+  g_return_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE);
+
+  g_free (node->data.merge_file.filename);
+  node->data.merge_file.filename = g_strdup (filename);
+}
+
+
+
+typedef struct
+{
+  GarconMenuNodeType type;
+  GNode             *self;
+  gboolean           reverse;
+  gpointer           value;
+} Pair;
+
+
+
+gboolean
+collect_children (GNode *node,
+                  Pair  *pair)
+{
+  if (node == pair->self)
+    return FALSE;
+
+  if (garcon_menu_node_tree_get_node_type (node) == pair->type)
+    {
+      if (pair->reverse)
+        pair->value = g_list_prepend (pair->value, node);
+      else
+        pair->value = g_list_append (pair->value, node);
+    }
+
+  return FALSE;
+}
+
+
+
+GNode *
+garcon_menu_node_tree_get_child_node (GNode             *tree,
+                                      GarconMenuNodeType type,
+                                      gboolean           reverse)
+{
+  GNode *node = NULL;
+  GNode *child;
+
+  for (child = reverse ? g_node_last_child (tree) : g_node_first_child (tree); 
+       node == NULL && child != NULL; 
+       child = reverse ? g_node_prev_sibling (child) : g_node_next_sibling (child))
+    {
+      if (garcon_menu_node_tree_get_node_type (child) == type)
+        node = child;
+    }
+
+  return node;
+}
+
+
+
+GList *
+garcon_menu_node_tree_get_child_nodes (GNode             *tree,
+                                       GarconMenuNodeType type,
+                                       gboolean           reverse)
+{
+  Pair pair;
+
+  pair.type = type;
+  pair.reverse = reverse;
+  pair.value = NULL;
+  pair.self = tree;
+
+  g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                   (GNodeTraverseFunc) collect_children, &pair);
+
+  return pair.value;
+}
+
+
+
+gboolean
+collect_strings (GNode *node,
+                 Pair  *pair)
+{
+  gpointer string;
+
+  if (node == pair->self)
+    return FALSE;
+
+  if (garcon_menu_node_tree_get_node_type (node) == pair->type)
+    {
+      string = (gpointer) garcon_menu_node_tree_get_string (node);
+
+      if (pair->reverse)
+        pair->value = g_list_prepend (pair->value, string);
+      else
+        pair->value = g_list_append (pair->value, string);
+    }
+
+  return FALSE;
+}
+
+
+
+GList *
+garcon_menu_node_tree_get_string_children (GNode             *tree,
+                                           GarconMenuNodeType type,
+                                           gboolean           reverse)
+{
+  Pair pair;
+
+  pair.type = type;
+  pair.reverse = reverse;
+  pair.value = NULL;
+  pair.self = tree;
+
+  g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                   (GNodeTraverseFunc) collect_strings, &pair);
+
+  return pair.value;
+}
+
+
+
+static gboolean
+collect_boolean (GNode *node,
+                 Pair  *pair)
+{
+  if (node == pair->self)
+    return FALSE;
+
+  if (garcon_menu_node_tree_get_node_type (node) == pair->type)
+    {
+      pair->value = GUINT_TO_POINTER (1);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+
+gboolean 
+garcon_menu_node_tree_get_boolean_child (GNode             *tree,
+                                         GarconMenuNodeType type)
+{
+  Pair pair;
+
+  pair.value = GUINT_TO_POINTER (0);
+  pair.self = tree;
+  pair.type = type;
+
+  g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                   (GNodeTraverseFunc) collect_boolean, &pair);
+
+  return !!GPOINTER_TO_UINT (pair.value);
+}
+
+
+
+static gboolean
+collect_string (GNode *node,
+                Pair  *pair)
+{
+  const gchar **string = pair->value;
+
+  if (node == pair->self)
+    return FALSE;
+
+  if (garcon_menu_node_tree_get_node_type (node) == pair->type)
+    {
+      *string = garcon_menu_node_tree_get_string (node);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+
+const gchar *
+garcon_menu_node_tree_get_string_child (GNode             *tree,
+                                        GarconMenuNodeType type)
+{
+  Pair         pair;
+  const gchar *string = NULL;
+
+  pair.type = type;
+  pair.value = &string;
+  pair.self = tree;
+
+  g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                   (GNodeTraverseFunc) collect_string, &pair);
+
+  return string;
+}
+
+
+
+gboolean
+garcon_menu_node_tree_rule_matches (GNode          *node,
+                                    GarconMenuItem *item)
+{
+  GNode   *child;
+  gboolean matches = FALSE;
+  gboolean child_matches = FALSE;
+
+  switch (garcon_menu_node_tree_get_node_type (node))
+    {
+    case GARCON_MENU_NODE_TYPE_INCLUDE:
+    case GARCON_MENU_NODE_TYPE_EXCLUDE:
+    case GARCON_MENU_NODE_TYPE_OR:
+      for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
+        matches = matches || garcon_menu_node_tree_rule_matches (child, item);
+      break;
+
+    case GARCON_MENU_NODE_TYPE_AND:
+      matches = TRUE;
+      for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
+        matches = matches && garcon_menu_node_tree_rule_matches (child, item);
+      break;
+
+    case GARCON_MENU_NODE_TYPE_NOT:
+      for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
+        child_matches = child_matches || garcon_menu_node_tree_rule_matches (child, item);
+      matches = !child_matches;
+      break;
+
+    case GARCON_MENU_NODE_TYPE_FILENAME:
+      matches = g_str_equal (garcon_menu_node_tree_get_string (node),
+                             garcon_menu_item_get_desktop_id (item));
+      break;
+
+    case GARCON_MENU_NODE_TYPE_CATEGORY:
+      matches = garcon_menu_item_has_category (item, garcon_menu_node_tree_get_string (node));
+      break;
+
+    case GARCON_MENU_NODE_TYPE_ALL:
+      matches = TRUE;
+      break;
+
+    default:
+      break;
+    }
+
+  return matches;
+}
+
+
+
+
+
+
+GarconMenuNodeType 
+garcon_menu_node_tree_get_node_type (GNode *tree)
+{
+  if (tree == NULL)
+    return GARCON_MENU_NODE_TYPE_INVALID;
+
+  if (tree->data == NULL)
+    return GARCON_MENU_NODE_TYPE_MENU;
+
+  return garcon_menu_node_get_node_type (tree->data);
+}
+
+
+
+const gchar * 
+garcon_menu_node_tree_get_string (GNode *tree)
+{
+  if (tree == NULL || tree->data == NULL)
+    return NULL;
+  else
+    return garcon_menu_node_get_string (tree->data);
+}
+
+
+
+void
+garcon_menu_node_tree_set_string (GNode       *tree,
+                                  const gchar *value)
+{
+  GarconMenuNodeType type;
+
+  type = garcon_menu_node_tree_get_node_type (tree);
+
+  g_return_if_fail (type == GARCON_MENU_NODE_TYPE_NAME ||
+                    type == GARCON_MENU_NODE_TYPE_DIRECTORY ||
+                    type == GARCON_MENU_NODE_TYPE_DIRECTORY_DIR ||
+                    type == GARCON_MENU_NODE_TYPE_APP_DIR ||
+                    type == GARCON_MENU_NODE_TYPE_FILENAME ||
+                    type == GARCON_MENU_NODE_TYPE_CATEGORY ||
+                    type == GARCON_MENU_NODE_TYPE_OLD ||
+                    type == GARCON_MENU_NODE_TYPE_NEW ||
+                    type == GARCON_MENU_NODE_TYPE_MENUNAME ||
+                    type == GARCON_MENU_NODE_TYPE_MERGE_DIR);
+
+  garcon_menu_node_set_string (tree->data, value);
+}
+
+
+GarconMenuLayoutMergeType
+garcon_menu_node_tree_get_layout_merge_type (GNode *tree)
+{
+  g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE, 0);
+  return ((GarconMenuNode *)tree->data)->data.layout_merge_type;
+}
+
+
+
+GarconMenuMergeFileType 
+garcon_menu_node_tree_get_merge_file_type (GNode *tree)
+{
+  g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE, 0);
+  return garcon_menu_node_get_merge_file_type (tree->data);
+}
+
+
+
+const gchar *
+garcon_menu_node_tree_get_merge_file_filename (GNode *tree)
+{
+  g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE, NULL);
+  return garcon_menu_node_get_merge_file_filename (tree->data);
+}
+
+
+
+void
+garcon_menu_node_tree_set_merge_file_filename (GNode       *tree,
+                                                  const gchar *filename)
+{
+  g_return_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE);
+  garcon_menu_node_set_merge_file_filename (tree->data, filename);
+}
+
+
+
+gint
+garcon_menu_node_tree_compare (GNode *tree,
+                               GNode *other_tree)
+{
+  GarconMenuNode *node;
+  GarconMenuNode *other_node;
+
+  if (tree == NULL || other_tree == NULL)
+    return 0;
+
+  node = tree->data;
+  other_node = other_tree->data;
+
+  if (node->node_type != other_node->node_type)
+    return 0;
+
+  switch (node->node_type)
+    {
+    case GARCON_MENU_NODE_TYPE_NAME:
+    case GARCON_MENU_NODE_TYPE_DIRECTORY:
+    case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
+    case GARCON_MENU_NODE_TYPE_APP_DIR:
+    case GARCON_MENU_NODE_TYPE_FILENAME:
+    case GARCON_MENU_NODE_TYPE_CATEGORY:
+    case GARCON_MENU_NODE_TYPE_OLD:
+    case GARCON_MENU_NODE_TYPE_NEW:
+    case GARCON_MENU_NODE_TYPE_MENUNAME:
+    case GARCON_MENU_NODE_TYPE_MERGE_DIR:
+      return g_utf8_collate (node->data.string, other_node->data.string);
+      break;
+
+    case GARCON_MENU_NODE_TYPE_MERGE_FILE:
+      return g_utf8_collate (node->data.merge_file.filename, 
+                             other_node->data.merge_file.filename);
+      break;
+
+    default:
+      return 0;
+      break;
+    }
+
+  return 0;
+}
+
+
+
+GNode *
+garcon_menu_node_tree_copy (GNode *tree)
+{
+  return g_node_copy_deep (tree, (GCopyFunc) garcon_menu_node_copy, NULL);
+}
+
+
+
+void
+garcon_menu_node_tree_free (GNode *tree)
+{
+  if (tree != NULL)
+    {
+      g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+                       (GNodeTraverseFunc) garcon_menu_node_tree_free_data, NULL);
+
+      g_node_destroy (tree);
+    }
+}
+
+
+
+void
+garcon_menu_node_tree_free_data (GNode *tree)
+{
+  if (tree != NULL && tree->data != NULL)
+    g_object_unref (tree->data);
+}
+
diff --git a/garcon/garcon-menu-node.h b/garcon/garcon-menu-node.h
new file mode 100644
index 0000000..38ccd08
--- /dev/null
+++ b/garcon/garcon-menu-node.h
@@ -0,0 +1,147 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined (GARCON_INSIDE_GARCON_H) && !defined (GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_NODE_H__
+#define __GARCON_MENU_NODE_H__
+
+#include <garcon/garcon.h>
+
+G_BEGIN_DECLS
+
+/* Types for the menu nodes */
+typedef enum
+{
+  GARCON_MENU_NODE_TYPE_INVALID,
+  GARCON_MENU_NODE_TYPE_MENU,
+  GARCON_MENU_NODE_TYPE_NAME,
+  GARCON_MENU_NODE_TYPE_DIRECTORY,
+  GARCON_MENU_NODE_TYPE_DIRECTORY_DIR,
+  GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS,
+  GARCON_MENU_NODE_TYPE_APP_DIR,
+  GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS,
+  GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED,
+  GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED,
+  GARCON_MENU_NODE_TYPE_DELETED,
+  GARCON_MENU_NODE_TYPE_NOT_DELETED,
+  GARCON_MENU_NODE_TYPE_INCLUDE,
+  GARCON_MENU_NODE_TYPE_EXCLUDE,
+  GARCON_MENU_NODE_TYPE_ALL,
+  GARCON_MENU_NODE_TYPE_FILENAME,
+  GARCON_MENU_NODE_TYPE_CATEGORY,
+  GARCON_MENU_NODE_TYPE_OR,
+  GARCON_MENU_NODE_TYPE_AND,
+  GARCON_MENU_NODE_TYPE_NOT,
+  GARCON_MENU_NODE_TYPE_MOVE,
+  GARCON_MENU_NODE_TYPE_OLD,
+  GARCON_MENU_NODE_TYPE_NEW,
+  GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT,
+  GARCON_MENU_NODE_TYPE_LAYOUT,
+  GARCON_MENU_NODE_TYPE_MENUNAME,
+  GARCON_MENU_NODE_TYPE_SEPARATOR,
+  GARCON_MENU_NODE_TYPE_MERGE,
+  GARCON_MENU_NODE_TYPE_MERGE_FILE,
+  GARCON_MENU_NODE_TYPE_MERGE_DIR,
+  GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS,
+} GarconMenuNodeType;
+
+
+
+typedef enum
+{
+  GARCON_MENU_LAYOUT_MERGE_MENUS,
+  GARCON_MENU_LAYOUT_MERGE_FILES,
+  GARCON_MENU_LAYOUT_MERGE_ALL,
+} GarconMenuLayoutMergeType;
+
+typedef enum
+{
+  GARCON_MENU_MERGE_FILE_PATH,
+  GARCON_MENU_MERGE_FILE_PARENT,
+} GarconMenuMergeFileType;
+
+
+
+typedef union  _GarconMenuNodeData  GarconMenuNodeData;
+typedef struct _GarconMenuNodeClass GarconMenuNodeClass;
+typedef struct _GarconMenuNode      GarconMenuNode;
+
+#define GARCON_TYPE_MENU_NODE            (garcon_menu_node_get_type ())
+#define GARCON_MENU_NODE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_NODE, GarconMenuNode))
+#define GARCON_MENU_NODE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU_NODE, GarconMenuNodeClass))
+#define GARCON_IS_MENU_NODE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_NODE))
+#define GARCON_IS_MENU_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU_NODE)
+#define GARCON_MENU_NODE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU_NODE, GarconMenuNodeClass))
+
+GType                     garcon_menu_node_get_type                     (void) G_GNUC_CONST;
+
+GarconMenuNode           *garcon_menu_node_new                          (GarconMenuNodeType      node_type) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+GarconMenuNodeType        garcon_menu_node_get_node_type                (GarconMenuNode         *node);
+GarconMenuNode           *garcon_menu_node_create                       (GarconMenuNodeType      node_type,
+                                                                         gpointer                first_value,
+                                                                         ...) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+GarconMenuNode           *garcon_menu_node_copy                         (GarconMenuNode         *node) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+const gchar              *garcon_menu_node_get_string                   (GarconMenuNode         *node);
+void                      garcon_menu_node_set_string                   (GarconMenuNode         *node,
+                                                                         const gchar            *value);
+GarconMenuMergeFileType   garcon_menu_node_get_merge_file_type          (GarconMenuNode         *node);
+void                      garcon_menu_node_set_merge_file_type          (GarconMenuNode         *node,
+                                                                         GarconMenuMergeFileType type);
+const gchar              *garcon_menu_node_get_merge_file_filename      (GarconMenuNode         *node);
+void                      garcon_menu_node_set_merge_file_filename      (GarconMenuNode         *node,
+                                                                         const gchar            *filename);
+
+GNode                    *garcon_menu_node_tree_get_child_node          (GNode                  *tree,
+                                                                         GarconMenuNodeType      type,
+                                                                         gboolean                reverse);
+GList                    *garcon_menu_node_tree_get_child_nodes         (GNode                  *tree,
+                                                                         GarconMenuNodeType      type,
+                                                                         gboolean                reverse);
+GList                    *garcon_menu_node_tree_get_string_children     (GNode                  *tree,
+                                                                         GarconMenuNodeType      type,
+                                                                         gboolean                reverse);
+gboolean                  garcon_menu_node_tree_get_boolean_child       (GNode                  *tree,
+                                                                         GarconMenuNodeType      type);
+const gchar              *garcon_menu_node_tree_get_string_child        (GNode                  *tree,
+                                                                         GarconMenuNodeType      type);
+gboolean                  garcon_menu_node_tree_rule_matches            (GNode                  *tree,
+                                                                         GarconMenuItem         *item);
+GarconMenuNodeType        garcon_menu_node_tree_get_node_type           (GNode                  *tree);
+const gchar              *garcon_menu_node_tree_get_string              (GNode                  *tree);
+void                      garcon_menu_node_tree_set_string              (GNode                  *tree,
+                                                                         const gchar            *value);
+GarconMenuLayoutMergeType garcon_menu_node_tree_get_layout_merge_type   (GNode                  *tree);
+GarconMenuMergeFileType   garcon_menu_node_tree_get_merge_file_type     (GNode                  *tree);
+const gchar              *garcon_menu_node_tree_get_merge_file_filename (GNode                  *tree);
+void                      garcon_menu_node_tree_set_merge_file_filename (GNode                  *tree,
+                                                                         const gchar            *filename);
+gint                      garcon_menu_node_tree_compare                 (GNode                  *tree,
+                                                                         GNode                  *other_tree);
+GNode                    *garcon_menu_node_tree_copy                    (GNode                  *tree);
+void                      garcon_menu_node_tree_free                    (GNode                  *tree);
+void                      garcon_menu_node_tree_free_data               (GNode                  *tree);
+
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_NODE_H__ */
diff --git a/garcon/garcon-menu-parser.c b/garcon/garcon-menu-parser.c
new file mode 100644
index 0000000..31561c8
--- /dev/null
+++ b/garcon/garcon-menu-parser.c
@@ -0,0 +1,741 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <gio/gio.h>
+
+#include <garcon/garcon-menu-node.h>
+#include <garcon/garcon-menu-tree-provider.h>
+#include <garcon/garcon-menu-parser.h>
+
+
+
+/* Menu file parser states */
+typedef enum
+{
+  GARCON_MENU_PARSER_STATE_START,
+  GARCON_MENU_PARSER_STATE_ROOT,
+  GARCON_MENU_PARSER_STATE_MENU,
+  GARCON_MENU_PARSER_STATE_RULE,
+  GARCON_MENU_PARSER_STATE_MOVE,
+  GARCON_MENU_PARSER_STATE_LAYOUT,
+  GARCON_MENU_PARSER_STATE_END,
+} GarconMenuParserState;
+
+/* Node types */
+typedef enum
+{
+  GARCON_MENU_PARSER_NODE_TYPE_NONE,
+  GARCON_MENU_PARSER_NODE_TYPE_NAME,
+  GARCON_MENU_PARSER_NODE_TYPE_DIRECTORY,
+  GARCON_MENU_PARSER_NODE_TYPE_DIRECTORY_DIR,
+  GARCON_MENU_PARSER_NODE_TYPE_APP_DIR,
+  GARCON_MENU_PARSER_NODE_TYPE_FILENAME,
+  GARCON_MENU_PARSER_NODE_TYPE_CATEGORY,
+  GARCON_MENU_PARSER_NODE_TYPE_OLD,
+  GARCON_MENU_PARSER_NODE_TYPE_NEW,
+  GARCON_MENU_PARSER_NODE_TYPE_MENUNAME,
+  GARCON_MENU_PARSER_NODE_TYPE_MERGE_FILE,
+  GARCON_MENU_PARSER_NODE_TYPE_MERGE_DIR,
+} GarconMenuParserNodeType;
+
+typedef struct _GarconMenuParserContext GarconMenuParserContext;
+
+struct _GarconMenuParserContext
+{
+  GarconMenuParserNodeType node_type;
+  GarconMenuParserState    state;
+  GarconMenuParser        *parser;
+  GNode                   *node;
+};
+
+
+
+#define GARCON_MENU_PARSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GARCON_TYPE_MENU_PARSER, GarconMenuParserPrivate))
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+  PROP_FILE,
+};
+
+
+
+static void   garcon_menu_parser_class_init    (GarconMenuParserClass       *klass);
+static void   garcon_menu_parser_provider_init (GarconMenuTreeProviderIface *iface);
+static void   garcon_menu_parser_init          (GarconMenuParser            *parser);
+static void   garcon_menu_parser_finalize      (GObject                     *object);
+static void   garcon_menu_parser_get_property  (GObject                     *object,
+                                                guint                        prop_id,
+                                                GValue                      *value,
+                                                GParamSpec                  *pspec);
+static void   garcon_menu_parser_set_property  (GObject                     *object,
+                                                guint                        prop_id,
+                                                const GValue                *value,
+                                                GParamSpec                  *pspec);
+static void   garcon_menu_parser_start_element (GMarkupParseContext         *context,
+                                                const gchar                 *element_name,
+                                                const gchar                **attribute_names,
+                                                const gchar                **attribute_values,
+                                                gpointer                     user_data,
+                                                GError                     **error);
+static void   garcon_menu_parser_end_element   (GMarkupParseContext         *context,
+                                                const gchar                 *element_name,
+                                                gpointer                     user_data,
+                                                GError                     **error);
+static void   garcon_menu_parser_characters    (GMarkupParseContext         *context,
+                                                const gchar                 *text,
+                                                gsize                        text_len,
+                                                gpointer                     user_data,
+                                                GError                     **error);
+static GNode *garcon_menu_parser_get_tree      (GarconMenuTreeProvider      *provider);
+static GFile *garcon_menu_parser_get_file      (GarconMenuTreeProvider      *provider);
+
+
+
+struct _GarconMenuParserPrivate
+{
+  /* .menu file */
+  GFile *file;
+
+  /* Root menu node */
+  GNode *menu;
+};
+
+
+
+static GObjectClass *garcon_menu_parser_parent_class = NULL;
+
+
+
+GType
+garcon_menu_parser_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GInterfaceInfo provider_info = 
+      {
+        (GInterfaceInitFunc) garcon_menu_parser_provider_init,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            "GarconMenuParser",
+                                            sizeof (GarconMenuParserClass),
+                                            (GClassInitFunc) garcon_menu_parser_class_init,
+                                            sizeof (GarconMenuParser),
+                                            (GInstanceInitFunc) garcon_menu_parser_init,
+                                            0);
+
+      g_type_add_interface_static (type, GARCON_TYPE_MENU_TREE_PROVIDER, &provider_info);
+    }
+
+  return type;
+}
+
+
+
+static void
+garcon_menu_parser_class_init (GarconMenuParserClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (GarconMenuParserPrivate));
+
+  /* Determine the parent type class */
+  garcon_menu_parser_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = garcon_menu_parser_finalize; 
+  gobject_class->get_property = garcon_menu_parser_get_property;
+  gobject_class->set_property = garcon_menu_parser_set_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILE,
+                                   g_param_spec_object ("file",
+                                                        "file",
+                                                        "file",
+                                                        G_TYPE_FILE,
+                                                        G_PARAM_READWRITE 
+                                                        | G_PARAM_CONSTRUCT_ONLY));
+}
+
+
+
+static void 
+garcon_menu_parser_provider_init (GarconMenuTreeProviderIface *iface)
+{
+  iface->get_tree = garcon_menu_parser_get_tree;
+  iface->get_file = garcon_menu_parser_get_file;
+}
+
+
+
+static void
+garcon_menu_parser_init (GarconMenuParser *parser)
+{
+  parser->priv = GARCON_MENU_PARSER_GET_PRIVATE (parser);
+  parser->priv->file = NULL;
+  parser->priv->menu = NULL;
+}
+
+
+
+static void
+garcon_menu_parser_finalize (GObject *object)
+{
+  GarconMenuParser *parser = GARCON_MENU_PARSER (object);
+
+  garcon_menu_node_tree_free (parser->priv->menu);
+
+  g_object_unref (parser->priv->file);
+
+  (*G_OBJECT_CLASS (garcon_menu_parser_parent_class)->finalize) (object);
+}
+
+
+
+static void
+garcon_menu_parser_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  GarconMenuParser *parser = GARCON_MENU_PARSER (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILE:
+      g_value_set_object (value, parser->priv->file);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+garcon_menu_parser_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  GarconMenuParser *parser = GARCON_MENU_PARSER (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILE:
+      parser->priv->file = g_object_ref (g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+GarconMenuParser *
+garcon_menu_parser_new (GFile *file)
+{
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+  return g_object_new (GARCON_TYPE_MENU_PARSER, "file", file, NULL);
+}
+
+
+
+gboolean
+garcon_menu_parser_run (GarconMenuParser *parser,
+                        GCancellable     *cancellable,
+                        GError          **error)
+{
+  GarconMenuParserContext parser_context;
+  GMarkupParseContext      *context;
+  GMarkupParser             markup_parser = {
+    garcon_menu_parser_start_element,
+    garcon_menu_parser_end_element,
+    garcon_menu_parser_characters,
+    NULL,
+  };
+  gboolean                  result = TRUE;
+  gchar                    *data;
+  gsize                     data_length;
+
+  g_return_val_if_fail (GARCON_IS_MENU_PARSER (parser), FALSE);
+  g_return_val_if_fail (G_IS_FILE (parser->priv->file), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  /* Try to open and read the file */
+  if (G_UNLIKELY (!g_file_load_contents (parser->priv->file, cancellable,
+                                         &data, &data_length, NULL, error)))
+    {
+      gchar *uri = g_file_get_uri (parser->priv->file);
+      
+      if (error != NULL)
+        {
+          g_warning (_("Could not load menu file data from %s: %s"), 
+                     uri, (*error)->message);
+          g_error_free (*error);
+        }
+      else
+        g_warning (_("Could not load menu file data from %s"), uri);
+
+      g_free (uri);
+      return FALSE;
+    }
+
+  /* Create parser context */
+  parser_context.parser = parser;
+  parser_context.node_type = GARCON_MENU_PARSER_NODE_TYPE_NONE;
+  parser_context.state = GARCON_MENU_PARSER_STATE_START;
+  parser_context.node = NULL;
+
+  /* Create markup parse context */
+  context = g_markup_parse_context_new (&markup_parser, 0, &parser_context, NULL); 
+
+  /* Try to parse the menu file */
+  if (!g_markup_parse_context_parse (context, data, data_length, error) ||
+      !g_markup_parse_context_end_parse (context, error))
+    {
+      result = FALSE;
+    }
+
+  g_markup_parse_context_free (context);
+  g_free (data);
+
+  return result;
+}
+
+
+
+static GNode *
+garcon_menu_parser_get_tree (GarconMenuTreeProvider *provider)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_PARSER (provider), NULL);
+  return garcon_menu_node_tree_copy (GARCON_MENU_PARSER (provider)->priv->menu);
+}
+
+
+
+static GFile *
+garcon_menu_parser_get_file (GarconMenuTreeProvider *provider)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_PARSER (provider), NULL);
+  return g_object_ref (GARCON_MENU_PARSER (provider)->priv->file);
+}
+
+
+
+static void
+garcon_menu_parser_start_element (GMarkupParseContext *context,
+                                  const gchar         *element_name,
+                                  const gchar        **attribute_names,
+                                  const gchar        **attribute_values,
+                                  gpointer             user_data,
+                                  GError             **error)
+{
+  GarconMenuParserContext *parser_context = (GarconMenuParserContext *)user_data;
+  GarconMenuNode          *node_;
+
+  switch (parser_context->state)
+    {
+    case GARCON_MENU_PARSER_STATE_START:
+      if (g_str_equal (element_name, "Menu"))
+        {
+          parser_context->parser->priv->menu = g_node_new (NULL);
+
+          parser_context->state = GARCON_MENU_PARSER_STATE_ROOT;
+          parser_context->node = parser_context->parser->priv->menu;
+        }
+      break;
+
+    case GARCON_MENU_PARSER_STATE_ROOT:
+    case GARCON_MENU_PARSER_STATE_MENU:
+      if (g_str_equal (element_name, "Name"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_NAME;
+
+      else if (g_str_equal (element_name, "Directory"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_DIRECTORY;
+      else if (g_str_equal (element_name, "DirectoryDir"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_DIRECTORY_DIR;
+      else if (g_str_equal (element_name, "DefaultDirectoryDirs"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+
+      else if (g_str_equal (element_name, "AppDir"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_APP_DIR;
+      else if (g_str_equal (element_name, "DefaultAppDirs"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+
+      else if (g_str_equal (element_name, "Deleted"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_DELETED, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+      else if (g_str_equal (element_name, "NotDeleted"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_NOT_DELETED, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+      else if (g_str_equal (element_name, "OnlyUnallocated"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+      else if (g_str_equal (element_name, "NotOnlyUnallocated"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+
+      else if (g_str_equal (element_name, "Include"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_INCLUDE, NULL);
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+          parser_context->state = GARCON_MENU_PARSER_STATE_RULE;
+        }
+      else if (g_str_equal (element_name, "Exclude"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_EXCLUDE, NULL);
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+          parser_context->state = GARCON_MENU_PARSER_STATE_RULE;
+        }
+
+      else if (g_str_equal (element_name, "Menu"))
+        {
+          parser_context->node = g_node_append_data (parser_context->node, NULL);
+          parser_context->state = GARCON_MENU_PARSER_STATE_MENU;
+        }
+
+      else if (g_str_equal (element_name, "Move"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MOVE, NULL);
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+          parser_context->state = GARCON_MENU_PARSER_STATE_MOVE;
+        }
+
+      else if (g_str_equal (element_name, "DefaultLayout"))
+        {
+          /* TODO Parse attributes */
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT, NULL);
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+          parser_context->state = GARCON_MENU_PARSER_STATE_LAYOUT;
+        }
+      else if (g_str_equal (element_name, "Layout"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_LAYOUT, NULL);
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+          parser_context->state = GARCON_MENU_PARSER_STATE_LAYOUT;
+        }
+
+      else if (g_str_equal (element_name, "MergeFile"))
+        {
+          GarconMenuMergeFileType type = GARCON_MENU_MERGE_FILE_PATH;
+
+          if (g_strv_length ((gchar **)attribute_names) == 1 &&
+              g_str_equal (attribute_names[0], "type"))
+            {
+              if (g_str_equal (attribute_values[0], "parent"))
+                type = GARCON_MENU_MERGE_FILE_PARENT;
+            }
+
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE_FILE, GUINT_TO_POINTER (type));
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+          parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_MERGE_FILE;
+        }
+      else if (g_str_equal (element_name, "MergeDir"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_MERGE_DIR;
+      else if (g_str_equal (element_name, "DefaultMergeDirs"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+      break;
+
+    case GARCON_MENU_PARSER_STATE_RULE:
+      if (g_str_equal (element_name, "All"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_ALL, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+      else if (g_str_equal (element_name, "Filename"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_FILENAME;
+      else if (g_str_equal (element_name, "Category"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_CATEGORY;
+      else if (g_str_equal (element_name, "Or"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_OR, NULL);
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+        }
+      else if (g_str_equal (element_name, "And"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_AND, NULL);
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+        }
+      else if (g_str_equal (element_name, "Not"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_NOT, NULL);
+          parser_context->node = g_node_append_data (parser_context->node, node_);
+        }
+      break;
+
+    case GARCON_MENU_PARSER_STATE_MOVE:
+      if (g_str_equal (element_name, "Old"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_OLD;
+      else if (g_str_equal (element_name, "New"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_NEW;
+      break;
+
+    case GARCON_MENU_PARSER_STATE_LAYOUT:
+      if (g_str_equal (element_name, "Filename"))
+        parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_FILENAME;
+      else if (g_str_equal (element_name, "Menuname"))
+        {
+          /* TODO Parse attributes */
+          parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_MENUNAME;
+        }
+      else if (g_str_equal (element_name, "Separator"))
+        {
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_SEPARATOR, NULL);
+          g_node_append_data (parser_context->node, node_);
+        }
+      else if (g_str_equal (element_name, "Merge"))
+        {
+          GarconMenuLayoutMergeType type = GARCON_MENU_LAYOUT_MERGE_ALL;
+
+          if (g_strv_length ((gchar **)attribute_names) == 1 &&
+              g_str_equal (attribute_names[0], "type"))
+            {
+              if (g_str_equal (attribute_values[0], "menus"))
+                type = GARCON_MENU_LAYOUT_MERGE_MENUS;
+              else if (g_str_equal (attribute_values[0], "files"))
+                type = GARCON_MENU_LAYOUT_MERGE_FILES;
+            }
+
+          node_ = garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE, GUINT_TO_POINTER (type));
+          g_node_append_data (parser_context->node, node_);
+        }
+      break;
+
+    default: 
+      break;
+    }
+}
+
+
+
+static void 
+garcon_menu_parser_end_element (GMarkupParseContext *context,
+                                const gchar         *element_name,
+                                gpointer             user_data,
+                                GError             **error)
+{
+  GarconMenuParserContext *parser_context = (GarconMenuParserContext *)user_data;
+
+  switch (parser_context->state)
+    {
+    case GARCON_MENU_PARSER_STATE_ROOT:
+    case GARCON_MENU_PARSER_STATE_MENU:
+      if (g_str_equal (element_name, "Menu"))
+        {
+          /* We no longer have a menu on the stack */
+          parser_context->node = parser_context->node->parent;
+
+          if (parser_context->node == NULL)
+            parser_context->state = GARCON_MENU_PARSER_STATE_END;
+          else if (parser_context->node->parent == NULL)
+            parser_context->state = GARCON_MENU_PARSER_STATE_ROOT;
+        }
+      else if (g_str_equal (element_name, "MergeFile"))
+        {
+          parser_context->node = parser_context->node->parent;
+
+          if (parser_context->node->parent == NULL)
+            parser_context->state = GARCON_MENU_PARSER_STATE_ROOT;
+          else 
+            parser_context->state = GARCON_MENU_PARSER_STATE_MENU;
+        }
+      break;
+
+    case GARCON_MENU_PARSER_STATE_RULE:
+      if (g_str_equal (element_name, "Include") ||
+          g_str_equal (element_name, "Exclude") ||
+          g_str_equal (element_name, "Or") ||
+          g_str_equal (element_name, "And") ||
+          g_str_equal (element_name, "Not"))
+        {
+          /* Switch to the parent rule or menu */
+          parser_context->node = parser_context->node->parent;
+
+          /* Set the parse state according to the parent type */
+          if (parser_context->node->data == NULL)
+            {
+              if (parser_context->node->parent == NULL)
+                parser_context->state = GARCON_MENU_PARSER_STATE_ROOT;
+              else
+                parser_context->state = GARCON_MENU_PARSER_STATE_MENU;
+            }
+        }
+      break;
+
+    case GARCON_MENU_PARSER_STATE_MOVE:
+      if (g_str_equal (element_name, "Move"))
+        {
+          parser_context->node = parser_context->node->parent;
+
+          /* Set the parse state according to the parent type */
+          if (parser_context->node->data == NULL)
+            {
+              if (parser_context->node->parent == NULL)
+                parser_context->state = GARCON_MENU_PARSER_STATE_ROOT;
+              else
+                parser_context->state = GARCON_MENU_PARSER_STATE_MENU;
+            }
+        }
+      break;
+
+    case GARCON_MENU_PARSER_STATE_LAYOUT:
+      if (g_str_equal (element_name, "Layout") || g_str_equal (element_name, "DefaultLayout"))
+        {
+          parser_context->node = parser_context->node->parent;
+
+          /* Set the parse state according to the parent type */
+          if (parser_context->node->data == NULL)
+            {
+              if (parser_context->node->parent == NULL)
+                parser_context->state = GARCON_MENU_PARSER_STATE_ROOT;
+              else
+                parser_context->state = GARCON_MENU_PARSER_STATE_MENU;
+            }
+        }
+      break;
+
+    default:
+      break;
+    }
+}
+
+
+
+static void
+garcon_menu_parser_characters (GMarkupParseContext *context,
+                               const gchar         *text,
+                               gsize                text_len,
+                               gpointer             user_data,
+                               GError             **error)
+{
+  GarconMenuParserContext *parser_context = (GarconMenuParserContext *)user_data;
+  gchar                 *data;
+
+  /* Ignore characters outside the root <Menu> element */
+  if (G_UNLIKELY (parser_context->node_type == GARCON_MENU_PARSER_NODE_TYPE_NONE))
+    return;
+
+  /* Generate NUL-terminated string */
+  data = g_strndup (text, text_len);
+
+  switch (parser_context->node_type)
+    {
+    case GARCON_MENU_PARSER_NODE_TYPE_NAME:
+      g_node_append_data (parser_context->node, 
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_NAME, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_DIRECTORY:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_DIRECTORY, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_DIRECTORY_DIR:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_DIRECTORY_DIR, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_APP_DIR:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_APP_DIR, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_FILENAME:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_FILENAME, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_CATEGORY:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_CATEGORY, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_OLD:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_OLD, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_NEW:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_NEW, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_MENUNAME:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MENUNAME, data));
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_MERGE_FILE:
+      if (garcon_menu_node_tree_get_node_type (parser_context->node) == GARCON_MENU_NODE_TYPE_MERGE_FILE)
+        garcon_menu_node_set_merge_file_filename (parser_context->node->data, data);
+      break;
+
+    case GARCON_MENU_PARSER_NODE_TYPE_MERGE_DIR:
+      g_node_append_data (parser_context->node,
+                          garcon_menu_node_create (GARCON_MENU_NODE_TYPE_MERGE_DIR, data));
+      break;
+
+    default:
+      break;
+    }
+
+  /* Free NUL-terminated string */
+  g_free (data);
+
+  /* Invalidate node type information */
+  parser_context->node_type = GARCON_MENU_PARSER_NODE_TYPE_NONE;
+}
+
diff --git a/garcon/garcon-menu-parser.h b/garcon/garcon-menu-parser.h
new file mode 100644
index 0000000..8d5095d
--- /dev/null
+++ b/garcon/garcon-menu-parser.h
@@ -0,0 +1,66 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined (GARCON_INSIDE_GARCON_H) && !defined (GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_PARSER_H__
+#define __GARCON_MENU_PARSER_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU_PARSER            (garcon_menu_parser_get_type ())
+#define GARCON_MENU_PARSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_PARSER, GarconMenuParser))
+#define GARCON_MENU_PARSER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU_PARSER, GarconMenuParserClass))
+#define GARCON_IS_MENU_PARSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_PARSER))
+#define GARCON_IS_MENU_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU_PARSER)
+#define GARCON_MENU_PARSER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU_PARSER, GarconMenuParserClass))
+
+typedef struct _GarconMenuParserPrivate GarconMenuParserPrivate;
+typedef struct _GarconMenuParserClass   GarconMenuParserClass;
+typedef struct _GarconMenuParser        GarconMenuParser;
+
+GType             garcon_menu_parser_get_type (void) G_GNUC_CONST;
+
+GarconMenuParser *garcon_menu_parser_new      (GFile              *file) G_GNUC_MALLOC;
+gboolean          garcon_menu_parser_run      (GarconMenuParser *parser,
+                                               GCancellable     *cancellable,
+                                               GError          **error);
+
+
+
+struct _GarconMenuParserClass
+{
+  GObjectClass __parent__;
+};
+
+struct _GarconMenuParser
+{
+  GObject                  __parent__;
+
+  GarconMenuParserPrivate *priv;
+};
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_PARSER_H__ */
diff --git a/garcon/garcon-menu-separator.c b/garcon/garcon-menu-separator.c
new file mode 100644
index 0000000..469c40c
--- /dev/null
+++ b/garcon/garcon-menu-separator.c
@@ -0,0 +1,212 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <garcon/garcon-menu-element.h>
+#include <garcon/garcon-menu-separator.h>
+
+
+
+static void         garcon_menu_separator_class_init                      (GarconMenuSeparatorClass *klass);
+static void         garcon_menu_separator_element_init                    (GarconMenuElementIface   *iface);
+static void         garcon_menu_separator_init                            (GarconMenuSeparator      *separator);
+static void         garcon_menu_separator_finalize                        (GObject                  *object);
+
+static const gchar *garcon_menu_separator_get_element_name                (GarconMenuElement        *element);
+static const gchar *garcon_menu_separator_get_element_comment             (GarconMenuElement        *element);
+static const gchar *garcon_menu_separator_get_element_icon_name           (GarconMenuElement        *element);
+static gboolean     garcon_menu_separator_get_element_visible             (GarconMenuElement        *element);
+static gboolean     garcon_menu_separator_get_element_show_in_environment (GarconMenuElement        *element);
+static gboolean     garcon_menu_separator_get_element_no_display          (GarconMenuElement        *element);
+
+
+static GarconMenuSeparator *_garcon_menu_separator = NULL;
+
+
+
+void
+_garcon_menu_separator_init (void)
+{
+  if (G_LIKELY (_garcon_menu_separator == NULL))
+    {
+      _garcon_menu_separator = g_object_new (GARCON_TYPE_MENU_SEPARATOR, NULL);
+      g_object_add_weak_pointer (G_OBJECT (_garcon_menu_separator), 
+                                 (gpointer) &_garcon_menu_separator);
+    }
+}
+
+
+
+void
+_garcon_menu_separator_shutdown (void)
+{
+  if (G_LIKELY (_garcon_menu_separator != NULL))
+    g_object_unref (G_OBJECT (_garcon_menu_separator));
+}
+
+
+
+struct _GarconMenuSeparatorClass
+{
+  GObjectClass __parent__;
+};
+
+struct _GarconMenuSeparator
+{
+  GObject __parent__;
+
+
+};
+
+
+
+static GObjectClass *garcon_menu_separator_parent_class = NULL;
+
+
+
+GType
+garcon_menu_separator_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GInterfaceInfo element_info =
+      {
+        (GInterfaceInitFunc) garcon_menu_separator_element_init,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            "GarconMenuSeparator",
+                                            sizeof (GarconMenuSeparatorClass),
+                                            (GClassInitFunc) garcon_menu_separator_class_init,
+                                            sizeof (GarconMenuSeparator),
+                                            (GInstanceInitFunc) garcon_menu_separator_init,
+                                            0);
+
+      g_type_add_interface_static (type, GARCON_TYPE_MENU_ELEMENT, &element_info);
+    }
+
+  return type;
+}
+
+
+
+static void
+garcon_menu_separator_class_init (GarconMenuSeparatorClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  /* Determine parent type class */
+  garcon_menu_separator_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = garcon_menu_separator_finalize;
+}
+
+
+
+static void
+garcon_menu_separator_element_init (GarconMenuElementIface *iface)
+{
+  iface->get_name = garcon_menu_separator_get_element_name;
+  iface->get_comment = garcon_menu_separator_get_element_comment;
+  iface->get_icon_name = garcon_menu_separator_get_element_icon_name;
+  iface->get_visible = garcon_menu_separator_get_element_visible;
+  iface->get_show_in_environment = garcon_menu_separator_get_element_show_in_environment;
+  iface->get_no_display = garcon_menu_separator_get_element_no_display;
+}
+
+
+
+static void
+garcon_menu_separator_init (GarconMenuSeparator *separator)
+{
+}
+
+
+
+static void
+garcon_menu_separator_finalize (GObject *object)
+{
+  (*G_OBJECT_CLASS (garcon_menu_separator_parent_class)->finalize) (object);
+}
+
+
+
+GarconMenuSeparator*
+garcon_menu_separator_get_default (void)
+{
+  return _garcon_menu_separator;
+}
+
+
+
+static const gchar*
+garcon_menu_separator_get_element_name (GarconMenuElement *element)
+{
+  return NULL;
+}
+
+
+
+static const gchar*
+garcon_menu_separator_get_element_comment (GarconMenuElement *element)
+{
+  return NULL;
+}
+
+
+
+static const gchar*
+garcon_menu_separator_get_element_icon_name (GarconMenuElement *element)
+{
+  return NULL;
+}
+
+
+
+static gboolean
+garcon_menu_separator_get_element_visible (GarconMenuElement *element)
+{
+  return TRUE;
+}
+
+
+
+static gboolean
+garcon_menu_separator_get_element_show_in_environment (GarconMenuElement *element)
+{
+  return TRUE;
+}
+
+
+
+static gboolean
+garcon_menu_separator_get_element_no_display (GarconMenuElement *element)
+{
+  return FALSE;
+}
+
diff --git a/garcon/garcon-menu-separator.h b/garcon/garcon-menu-separator.h
new file mode 100644
index 0000000..ccc920b
--- /dev/null
+++ b/garcon/garcon-menu-separator.h
@@ -0,0 +1,54 @@
+/* $Id$ */
+/* vi:set et ai sw=2 sts=2: */
+/*-
+ * Copyright (c) 2007 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if !defined(GARCON_INSIDE_GARCON_H) && !defined(GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_SEPARATOR_H__
+#define __GARCON_MENU_SEPARATOR_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU_SEPARATOR            (garcon_menu_separator_get_type())
+#define GARCON_MENU_SEPARATOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_SEPARATOR, GarconMenuSeparator))
+#define GARCON_MENU_SEPARATOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU_SEPARATOR, GarconMenuSeparatorClass))
+#define GARCON_IS_MENU_SEPARATOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_SEPARATOR))
+#define GARCON_IS_MENU_SEPARATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU_SEPARATOR))
+#define GARCON_MENU_SEPARATOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU_SEPARATOR, GarconMenuSeparatorClass))
+
+typedef struct _GarconMenuSeparatorClass GarconMenuSeparatorClass;
+typedef struct _GarconMenuSeparator      GarconMenuSeparator;
+
+GType                garcon_menu_separator_get_type    (void) G_GNUC_CONST;
+
+GarconMenuSeparator *garcon_menu_separator_get_default (void);
+
+#if defined(GARCON_COMPILATION)
+void                 _garcon_menu_separator_init       (void) G_GNUC_INTERNAL;
+void                 _garcon_menu_separator_shutdown   (void) G_GNUC_INTERNAL;
+#endif
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_SEPARATOR_H__ */
diff --git a/garcon/garcon-menu-tree-provider.c b/garcon/garcon-menu-tree-provider.c
new file mode 100644
index 0000000..89075ad
--- /dev/null
+++ b/garcon/garcon-menu-tree-provider.c
@@ -0,0 +1,66 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <garcon/garcon-menu-tree-provider.h>
+
+
+
+GType
+garcon_menu_tree_provider_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      type = g_type_register_static_simple (G_TYPE_INTERFACE, 
+                                            "GarconMenuTreeProvider",
+                                            sizeof (GarconMenuTreeProviderIface),
+                                            NULL,
+                                            0,
+                                            NULL,
+                                            0);
+
+      g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+    }
+
+  return type;
+}
+
+
+
+GNode *
+garcon_menu_tree_provider_get_tree (GarconMenuTreeProvider *provider)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_TREE_PROVIDER (provider), NULL);
+  return (*GARCON_MENU_TREE_PROVIDER_GET_IFACE (provider)->get_tree) (provider);
+}
+
+
+
+GFile *
+garcon_menu_tree_provider_get_file (GarconMenuTreeProvider *provider)
+{
+  g_return_val_if_fail (GARCON_IS_MENU_TREE_PROVIDER (provider), NULL);
+  return (*GARCON_MENU_TREE_PROVIDER_GET_IFACE (provider)->get_file) (provider);
+}
diff --git a/garcon/garcon-menu-tree-provider.h b/garcon/garcon-menu-tree-provider.h
new file mode 100644
index 0000000..d22ffc6
--- /dev/null
+++ b/garcon/garcon-menu-tree-provider.h
@@ -0,0 +1,56 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined (GARCON_INSIDE_GARCON_H) && !defined (GARCON_COMPILATION)
+#error "Only <garcon/garcon.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __GARCON_MENU_TREE_PROVIDER_H__
+#define __GARCON_MENU_TREE_PROVIDER_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU_TREE_PROVIDER            (garcon_menu_tree_provider_get_type ())
+#define GARCON_MENU_TREE_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU_TREE_PROVIDER, GarconMenuTreeProvider))
+#define GARCON_IS_MENU_TREE_PROVIDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU_TREE_PROVIDER))
+#define GARCON_MENU_TREE_PROVIDER_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GARCON_TYPE_MENU_TREE_PROVIDER, GarconMenuTreeProviderIface))
+
+typedef struct _GarconMenuTreeProviderIface GarconMenuTreeProviderIface;
+typedef struct _GarconMenuTreeProvider      GarconMenuTreeProvider;
+
+GType  garcon_menu_tree_provider_get_type (void) G_GNUC_CONST;
+
+GNode *garcon_menu_tree_provider_get_tree (GarconMenuTreeProvider *provider) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+GFile *garcon_menu_tree_provider_get_file (GarconMenuTreeProvider *provider) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+struct _GarconMenuTreeProviderIface
+{
+  GTypeInterface __parent__;
+
+  /* Virtual methods */
+  GNode       *(*get_tree) (GarconMenuTreeProvider *provider);
+  GFile       *(*get_file) (GarconMenuTreeProvider *provider);
+};
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_TREE_PROVIDER_H__ */
diff --git a/garcon/garcon-menu.c b/garcon/garcon-menu.c
new file mode 100644
index 0000000..8b8146e
--- /dev/null
+++ b/garcon/garcon-menu.c
@@ -0,0 +1,1611 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2007-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include <garcon/garcon-environment.h>
+#include <garcon/garcon-menu-element.h>
+#include <garcon/garcon-menu-item.h>
+#include <garcon/garcon-menu-directory.h>
+#include <garcon/garcon-menu-item-pool.h>
+#include <garcon/garcon-menu-item-cache.h>
+#include <garcon/garcon-menu-separator.h>
+#include <garcon/garcon-menu-monitor.h>
+#include <garcon/garcon-menu-node.h>
+#include <garcon/garcon-menu-parser.h>
+#include <garcon/garcon-menu-merger.h>
+#include <garcon/garcon-gio.h>
+#include <garcon/garcon.h>
+
+
+
+/* Use g_access() on win32 */
+#if defined(G_OS_WIN32)
+#include <glib/gstdio.h>
+#else
+#define g_access(filename, mode) (access ((filename), (mode)))
+#endif
+
+
+
+/**
+ * SECTION:garcon
+ * @title: GarconMenu
+ **/
+
+
+
+/* Potential root menu files */
+static const gchar GARCON_MENU_ROOT_SPECS[][30] = 
+{
+  "menus/applications.menu",
+  "menus/xfce-applications.menu",
+  "menus/gnome-applications.menu",
+  "menus/kde-applications.menu",
+};
+
+
+
+#define GARCON_MENU_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GARCON_TYPE_MENU, GarconMenuPrivate))
+
+
+
+typedef struct _GarconMenuPair
+{
+  gpointer first;
+  gpointer second;
+} GarconMenuPair;
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+  PROP_ENVIRONMENT,
+  PROP_FILE,
+  PROP_DIRECTORY,
+  PROP_PARENT, /* TODO */
+};
+
+
+
+static void                 garcon_menu_class_init                      (GarconMenuClass         *klass);
+static void                 garcon_menu_element_init                    (GarconMenuElementIface  *iface);
+static void                 garcon_menu_instance_init                   (GarconMenu              *menu);
+static void                 garcon_menu_finalize                        (GObject                 *object);
+static void                 garcon_menu_get_property                    (GObject                 *object,
+                                                                         guint                    prop_id,
+                                                                         GValue                  *value,
+                                                                         GParamSpec              *pspec);
+static void                 garcon_menu_set_property                    (GObject                 *object,
+                                                                         guint                    prop_id,
+                                                                         const GValue            *value,
+                                                                         GParamSpec              *pspec);
+static void                 garcon_menu_set_directory                   (GarconMenu              *menu,
+                                                                         GarconMenuDirectory     *directory);
+static void                 garcon_menu_resolve_menus                   (GarconMenu              *menu);
+static void                 garcon_menu_resolve_directory               (GarconMenu              *menu);
+static GarconMenuDirectory *garcon_menu_lookup_directory                (GarconMenu              *menu,
+                                                                         const gchar             *filename);
+static void                 garcon_menu_collect_files                   (GarconMenu              *menu,
+                                                                         GHashTable              *desktop_id_table);
+static void                 garcon_menu_collect_files_from_path         (GarconMenu              *menu,
+                                                                         GHashTable              *desktop_id_table,
+                                                                         GFile                   *path,
+                                                                         const gchar             *id_prefix);
+static void                 garcon_menu_resolve_items                   (GarconMenu              *menu,
+                                                                         GHashTable              *desktop_id_table,
+                                                                         gboolean                 only_unallocated);
+static void                 garcon_menu_resolve_items_by_rule           (GarconMenu              *menu,
+                                                                         GHashTable              *desktop_id_table,
+                                                                         GNode                   *node);
+static void                 garcon_menu_resolve_item_by_rule            (const gchar             *desktop_id,
+                                                                         const gchar             *uri,
+                                                                         GarconMenuPair          *data);
+static void                 garcon_menu_remove_deleted_menus            (GarconMenu              *menu);
+static gint                 garcon_menu_compare_items                   (gconstpointer           *a,
+                                                                         gconstpointer           *b);
+static const gchar         *garcon_menu_get_element_name                (GarconMenuElement       *element);
+static const gchar         *garcon_menu_get_element_comment             (GarconMenuElement       *element);
+static const gchar         *garcon_menu_get_element_icon_name           (GarconMenuElement       *element);
+static gboolean             garcon_menu_get_element_visible             (GarconMenuElement       *element);
+static gboolean             garcon_menu_get_element_show_in_environment (GarconMenuElement       *element);
+static gboolean             garcon_menu_get_element_no_display          (GarconMenuElement       *element);
+static void                 garcon_menu_monitor_start                   (GarconMenu              *menu);
+static void                 garcon_menu_monitor_stop                    (GarconMenu              *menu);
+
+
+
+struct _GarconMenuPrivate
+{
+  /* Menu file */
+  GFile               *file;
+
+  /* DOM tree */
+  GNode               *tree;
+
+  /* Directory */
+  GarconMenuDirectory *directory;
+
+  /* Submenus */
+  GList               *submenus;
+
+  /* Parent menu */
+  GarconMenu          *parent;
+
+  /* Menu item pool */
+  GarconMenuItemPool  *pool;
+
+  /* Shared menu item cache */
+  GarconMenuItemCache *cache;
+};
+
+
+
+static GObjectClass *garcon_menu_parent_class = NULL;
+
+
+
+GType
+garcon_menu_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GInterfaceInfo element_info =
+      {
+        (GInterfaceInitFunc) garcon_menu_element_init,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                            "GarconMenu",
+                                            sizeof (GarconMenuClass),
+                                            (GClassInitFunc) garcon_menu_class_init,
+                                            sizeof (GarconMenu),
+                                            (GInstanceInitFunc) garcon_menu_instance_init,
+                                            0);
+
+      g_type_add_interface_static (type, GARCON_TYPE_MENU_ELEMENT, &element_info);
+    }
+
+  return type;
+}
+
+
+
+static void
+garcon_menu_class_init (GarconMenuClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (GarconMenuPrivate));
+
+  /* Determine the parent type class */
+  garcon_menu_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = garcon_menu_finalize; 
+  gobject_class->get_property = garcon_menu_get_property;
+  gobject_class->set_property = garcon_menu_set_property;
+
+  /**
+   * GarconMenu:file:
+   *
+   * The #GFile from which the %GarconMenu was loaded. 
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILE,
+                                   g_param_spec_object ("file",
+                                                        "file",
+                                                        "file",
+                                                        G_TYPE_FILE,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * GarconMenu:directory:
+   *
+   * The directory entry associated with this menu. 
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_DIRECTORY,
+                                   g_param_spec_object ("directory",
+                                                        "Directory",
+                                                        "Directory entry associated with this menu",
+                                                        GARCON_TYPE_MENU_DIRECTORY,
+                                                        G_PARAM_READWRITE));
+}
+
+
+
+static void
+garcon_menu_element_init (GarconMenuElementIface *iface)
+{
+  iface->get_name = garcon_menu_get_element_name;
+  iface->get_comment = garcon_menu_get_element_comment;
+  iface->get_icon_name = garcon_menu_get_element_icon_name;
+  iface->get_visible = garcon_menu_get_element_visible;
+  iface->get_show_in_environment = garcon_menu_get_element_show_in_environment;
+  iface->get_no_display = garcon_menu_get_element_no_display;
+}
+
+
+
+static void
+garcon_menu_instance_init (GarconMenu *menu)
+{
+  menu->priv = GARCON_MENU_GET_PRIVATE (menu);
+  menu->priv->file = NULL;
+  menu->priv->tree = NULL;
+  menu->priv->directory = NULL;
+  menu->priv->submenus = NULL;
+  menu->priv->parent = NULL;
+  menu->priv->pool = garcon_menu_item_pool_new ();
+
+  /* Take reference on the menu item cache */
+  menu->priv->cache = garcon_menu_item_cache_get_default ();
+}
+
+
+
+static void
+garcon_menu_finalize (GObject *object)
+{
+  GarconMenu *menu = GARCON_MENU (object);
+
+  /* Stop monitoring */
+  garcon_menu_monitor_stop (menu);
+
+  /* Destroy the menu tree */
+  if (menu->priv->parent == NULL)
+    garcon_menu_node_tree_free (menu->priv->tree);
+
+  /* Free file */
+  g_object_unref (menu->priv->file);
+
+  /* Free directory */
+  if (G_LIKELY (menu->priv->directory != NULL))
+    g_object_unref (menu->priv->directory);
+
+  /* Free submenus */
+  g_list_foreach (menu->priv->submenus, (GFunc) g_object_unref, NULL);
+  g_list_free (menu->priv->submenus);
+
+  /* Free item pool */
+  g_object_unref (menu->priv->pool);
+
+  /* Release item cache reference */
+  g_object_unref (menu->priv->cache);
+
+  (*G_OBJECT_CLASS (garcon_menu_parent_class)->finalize) (object);
+}
+
+
+
+static void
+garcon_menu_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  GarconMenu *menu = GARCON_MENU (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILE:
+      g_value_set_object (value, garcon_menu_get_file (menu));
+      break;
+
+    case PROP_DIRECTORY:
+      g_value_set_object (value, garcon_menu_get_directory (menu));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+garcon_menu_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  GarconMenu *menu = GARCON_MENU (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILE:
+      menu->priv->file = g_object_ref (g_value_get_object (value));
+      break;
+
+    case PROP_DIRECTORY:
+      garcon_menu_set_directory (menu, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+/**
+ * garcon_menu_new:
+ * @filename : Path/URI of the .menu file you want to load.
+ *
+ * Creates a new #GarconMenu for the .menu file referred to by @filename.
+ * This operation only fails if the filename is NULL. To load the menu 
+ * tree from the file, you need to call garcon_menu_load() with the
+ * returned #GarconMenu. 
+ *
+ * <informalexample><programlisting>
+ * GarconMenu *menu = garcon_menu_new (filename);
+ * 
+ * if (garcon_menu_load (menu, &error))
+ *   ...
+ * else
+ *   ...
+ *
+ * g_object_unref (menu);
+ * </programlisting></informalexample>
+ *
+ * The caller is responsible to destroy the returned #GarconMenu
+ * using g_object_unref().
+ *
+ * Return value: a new #GarconMenu for @filename.
+ **/
+GarconMenu *
+garcon_menu_new (const gchar *filename)
+{
+  GarconMenu *menu;
+  GFile      *file;
+
+  g_return_val_if_fail (filename != NULL, NULL);
+
+  /* Create new menu */
+  file = g_file_new_for_unknown_input (filename, NULL);
+  menu = g_object_new (GARCON_TYPE_MENU, "file", file, NULL);
+  g_object_unref (file);
+
+  return menu;
+}
+
+
+
+/**
+ * garcon_menu_new_for_file:
+ * @file  : #GFile for the .menu file you want to load.
+ *
+ * Creates a new #GarconMenu for the .menu file referred to by @file.
+ * This operation only fails @file is invalid. To load the menu 
+ * tree from the file, you need to call garcon_menu_load() with the
+ * returned #GarconMenu. 
+ *
+ * The caller is responsible to destroy the returned #GarconMenu
+ * using g_object_unref().
+ *
+ * For more information about the usage @see garcon_menu_new().
+ *
+ * Return value: a new #GarconMenu for @file.
+ **/
+GarconMenu *
+garcon_menu_new_for_file (GFile *file)
+{
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+  return g_object_new (GARCON_TYPE_MENU, "file", file, NULL);
+}
+
+
+
+/**
+ * garcon_menu_new_applications:
+ *
+ * Creates a new #GarconMenu for the applications.menu file
+ * which is being used to display installed applications.
+ *
+ * For more information about the usage @see garcon_menu_new().
+ *
+ * Return value: a new #GarconMenu for applications.menu.
+ **/
+GarconMenu *
+garcon_menu_new_applications (void)
+{
+  GarconMenu *menu = NULL;
+  GFile      *file;
+  gchar      *filename;
+  guint       n;
+
+  /* Search for a usable applications menu file */
+  for (n = 0; menu == NULL && n < G_N_ELEMENTS (GARCON_MENU_ROOT_SPECS); ++n)
+    {
+      /* Search for the applications menu file */
+      filename = garcon_config_lookup (GARCON_MENU_ROOT_SPECS[n]);
+
+      /* Create menu if the file exists */
+      if (G_UNLIKELY (filename != NULL))
+        {
+          file = g_file_new_for_unknown_input (filename, NULL);
+          menu = garcon_menu_new_for_file (file);
+          g_object_unref (file);
+        }
+
+      g_free (filename);
+    }
+  
+  return menu;
+}
+
+
+
+/**
+ * garcon_menu_get_file:
+ * @menu : a #GarconMenu.
+ *
+ * Returns the #GFile of @menu. It refers to the .menu file from which 
+ * @menu was or will be loaded.
+ * 
+ * Return value: the @GFile of @menu.
+ */
+GFile *
+garcon_menu_get_file (GarconMenu *menu)
+{
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  return g_object_ref (menu->priv->file);
+}
+
+
+
+static const gchar *
+garcon_menu_get_name (GarconMenu *menu)
+{
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  return garcon_menu_node_tree_get_string_child (menu->priv->tree,
+                                                 GARCON_MENU_NODE_TYPE_NAME);
+}
+
+
+
+/**
+ * garcon_menu_get_directory:
+ * @menu : a #GarconMenu.
+ *
+ * Returns the #GarconMenuDirectory of @menu or %NULL if the <Menu>
+ * element that corresponds to @menu has no valid <Directory> element.
+ * The menu directory may contain a lot of useful information about 
+ * the menu like the display and icon name, desktop environments it 
+ * should show up in etc.
+ *
+ * Return value: #GarconMenuDirectory of @menu or %NULL if
+ *               @menu has no valid directory element.
+ */
+GarconMenuDirectory*
+garcon_menu_get_directory (GarconMenu *menu)
+{
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  return menu->priv->directory;
+}
+
+
+
+static void
+garcon_menu_set_directory (GarconMenu          *menu,
+                           GarconMenuDirectory *directory)
+{
+  g_return_if_fail (GARCON_IS_MENU (menu));
+  g_return_if_fail (GARCON_IS_MENU_DIRECTORY (directory));
+
+  /* Abort if directories are equal */
+  if (garcon_menu_directory_equal (directory, menu->priv->directory))
+    return;
+  
+  /* Destroy old directory */
+  if (menu->priv->directory != NULL)
+    g_object_unref (menu->priv->directory);
+
+  /* Remove the floating reference and acquire a normal one */
+  g_object_ref_sink (directory);
+
+  /* Set the new directory */
+  menu->priv->directory = directory;
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (menu), "directory");
+}
+
+
+
+/**
+ * garcon_menu_load:
+ * @menu        : a #GarconMenu
+ * @cancellable : a #GCancellable
+ * @error       : #GError return location
+ *
+ * This function loads the entire menu tree from the file referred to 
+ * by @menu. It resolves merges, moves and everything else defined
+ * in the menu specification. The resulting tree information is
+ * stored within @menu and can be accessed using the public #GarconMenu 
+ * API afterwards.
+ *
+ * @cancellable can be used to handle blocking I/O when reading data
+ * from files during the loading process. 
+ *
+ * @error should either be NULL or point to a #GError return location
+ * where errors should be stored in.
+ *
+ * Return value: %TRUE if the menu was loaded successfully or
+ *               %FALSE if there was an error or the process was 
+ *               cancelled.
+ **/
+gboolean
+garcon_menu_load (GarconMenu   *menu, 
+                  GCancellable *cancellable,
+                  GError      **error)
+{
+  GarconMenuParser *parser;
+  GarconMenuMerger *merger;
+  GHashTable       *desktop_id_table;
+  gboolean          success = TRUE;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), FALSE);
+
+  parser = garcon_menu_parser_new (menu->priv->file);
+
+  if (G_LIKELY (garcon_menu_parser_run (parser, cancellable, error)))
+    {
+      merger = garcon_menu_merger_new (GARCON_MENU_TREE_PROVIDER (parser));
+
+      if (garcon_menu_merger_run (merger, cancellable, error))
+        menu->priv->tree = garcon_menu_tree_provider_get_tree (GARCON_MENU_TREE_PROVIDER (merger));
+      else
+        success = FALSE;
+
+      g_object_unref (merger);
+    }
+  else
+    success = FALSE;
+
+  g_object_unref (parser);
+
+  if (G_LIKELY (!success))
+    return FALSE;
+
+  /* Generate submenus */
+  garcon_menu_resolve_menus (menu);
+
+  /* Resolve the menu directory */
+  garcon_menu_resolve_directory (menu);
+
+  desktop_id_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+  /* Load menu items */
+  garcon_menu_collect_files (menu, desktop_id_table);
+  garcon_menu_resolve_items (menu, desktop_id_table, FALSE);
+  garcon_menu_resolve_items (menu, desktop_id_table, TRUE);
+
+  /* Remove deleted menus */
+  garcon_menu_remove_deleted_menus (menu);
+
+  g_hash_table_unref (desktop_id_table);
+
+  /* Start monitoring */
+  garcon_menu_monitor_start (menu);
+
+  return TRUE;
+}
+
+
+
+GList *
+garcon_menu_get_menus (GarconMenu *menu)
+{
+  GList *menus = NULL;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  
+  /* Copy submenu list */
+  menus = g_list_copy (menu->priv->submenus);
+
+  /* Sort submenus */
+  menus = g_list_sort (menus, (GCompareFunc) garcon_menu_compare_items);
+
+  return menus;
+}
+
+
+
+void
+garcon_menu_add_menu (GarconMenu *menu,
+                      GarconMenu *submenu)
+{
+  g_return_if_fail (GARCON_IS_MENU (menu));
+  g_return_if_fail (GARCON_IS_MENU (submenu));
+
+  /* Remove floating reference and acquire a 'real' one */
+  g_object_ref_sink (G_OBJECT (submenu));
+
+  /* Append menu to the list */
+  menu->priv->submenus = g_list_append (menu->priv->submenus, submenu);
+
+  /* TODO: Use property method here */
+  submenu->priv->parent = menu;
+}
+
+
+
+GarconMenu *
+garcon_menu_get_menu_with_name (GarconMenu  *menu,
+                                const gchar *name)
+{
+  GarconMenu *result = NULL;
+  GList      *iter;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  /* Iterate over the submenu list */
+  for (iter = menu->priv->submenus; result == NULL && iter != NULL; iter = g_list_next (iter))
+    {
+      /* End loop when a matching submenu is found */
+      if (G_UNLIKELY (g_utf8_collate (garcon_menu_get_name (iter->data), name) == 0))
+        result = iter->data;
+    }
+
+  return result;
+}
+
+
+
+GarconMenu *
+garcon_menu_get_parent (GarconMenu *menu)
+{
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  return menu->priv->parent;
+}
+
+
+
+static void
+garcon_menu_resolve_menus (GarconMenu *menu)
+{
+  GarconMenu *submenu;
+  GList      *menus = NULL;
+  GList      *iter;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+
+  menus = garcon_menu_node_tree_get_child_nodes (menu->priv->tree, 
+                                                 GARCON_MENU_NODE_TYPE_MENU, 
+                                                 FALSE);
+
+  for (iter = menus; iter != NULL; iter = g_list_next (iter))
+    {
+      submenu = g_object_new (GARCON_TYPE_MENU, "file", menu->priv->file, NULL);
+      submenu->priv->tree = iter->data;
+      garcon_menu_add_menu (menu, submenu);
+      g_object_unref (submenu);
+    }
+
+  g_list_free (menus);
+
+  for (iter = menu->priv->submenus; iter != NULL; iter = g_list_next (iter))
+    garcon_menu_resolve_menus (iter->data);
+}
+
+
+
+static GList *
+garcon_menu_get_directories (GarconMenu *menu)
+{
+  GList *dirs = NULL;
+
+  /* Fetch all application directories */
+  dirs = garcon_menu_node_tree_get_string_children (menu->priv->tree, 
+                                                    GARCON_MENU_NODE_TYPE_DIRECTORY, 
+                                                    TRUE);
+
+  if (menu->priv->parent != NULL)
+    dirs = g_list_concat (dirs, garcon_menu_get_directories (menu->priv->parent));
+
+  return dirs;
+}
+
+
+
+static void
+garcon_menu_resolve_directory (GarconMenu *menu)
+{
+  GarconMenuDirectory *directory = NULL;
+  GList               *directories = NULL;
+  GList               *iter;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+
+  /* Determine all directories for this menu */
+  directories = garcon_menu_get_directories (menu);
+
+  /* Try to load one directory name after another */
+  for (iter = directories; directory == NULL && iter != NULL; iter = g_list_next (iter))
+    {
+      /* Try to load the directory with this name */
+      directory = garcon_menu_lookup_directory (menu, iter->data);
+    }
+
+  if (G_LIKELY (directory != NULL)) 
+    {
+      /* Set the directory (assuming that we found at least one valid name) */
+      menu->priv->directory = directory;
+    }
+
+  /* Free reverse list copy */
+  g_list_free (directories);
+
+  /* Resolve directories of submenus recursively */
+  for (iter = menu->priv->submenus; iter != NULL; iter = g_list_next (iter))
+    garcon_menu_resolve_directory (iter->data);
+}
+
+
+
+static GList *
+garcon_menu_get_directory_dirs (GarconMenu *menu)
+{
+  GList *dirs = NULL;
+
+  /* Fetch all application directories */
+  dirs = garcon_menu_node_tree_get_string_children (menu->priv->tree, 
+                                                    GARCON_MENU_NODE_TYPE_DIRECTORY_DIR, 
+                                                    TRUE);
+
+  if (menu->priv->parent != NULL)
+    dirs = g_list_concat (dirs, garcon_menu_get_directory_dirs (menu->priv->parent));
+
+  return dirs;
+}
+
+
+
+static GarconMenuDirectory *
+garcon_menu_lookup_directory (GarconMenu  *menu,
+                              const gchar *filename)
+{
+  GarconMenuDirectory *directory = NULL;
+  GList               *dirs = NULL;
+  GList               *iter;
+  GFile               *file;
+  GFile               *dir;
+  gboolean             found = FALSE;
+  
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+  g_return_val_if_fail (filename != NULL, NULL);
+
+  dirs = garcon_menu_get_directory_dirs (menu);
+
+  /* Iterate through all directories */
+  for (iter = dirs; !found && iter != NULL; iter = g_list_next (iter))
+    {
+      dir = g_file_new_relative_to_file (iter->data, menu->priv->file);
+      file = g_file_new_relative_to_file (filename, dir);
+
+      /* Check if the file exists and is readable */
+      if (G_LIKELY (g_file_query_exists (file, NULL)))
+        {
+          /* Load menu directory */
+          directory = g_object_new (GARCON_TYPE_MENU_DIRECTORY, "file", file, NULL);
+
+          /* Update search status */
+          found = TRUE;
+        }
+      
+      /* Destroy the file objects */
+      g_object_unref (file);
+      g_object_unref (dir);
+    }
+
+  /* Free reverse copy */
+  g_list_free (dirs);
+
+  return directory;
+}
+
+
+
+static GList *
+garcon_menu_get_app_dirs (GarconMenu *menu)
+{
+  GList *dirs = NULL;
+
+  /* Fetch all application directories */
+  dirs = garcon_menu_node_tree_get_string_children (menu->priv->tree, 
+                                                    GARCON_MENU_NODE_TYPE_APP_DIR,
+                                                    TRUE);
+
+  if (menu->priv->parent != NULL)
+    dirs = g_list_concat (dirs, garcon_menu_get_app_dirs (menu->priv->parent));
+
+  return dirs;
+}
+
+
+
+static void
+garcon_menu_collect_files (GarconMenu *menu,
+                           GHashTable *desktop_id_table)
+{
+  GList *app_dirs = NULL;
+  GList *iter;
+  GFile *file;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+
+  app_dirs = garcon_menu_get_app_dirs (menu);
+
+  /* Collect desktop entry filenames */
+  for (iter = app_dirs; iter != NULL; iter = g_list_next (iter))
+    {
+      file = g_file_new_for_uri (iter->data);
+      garcon_menu_collect_files_from_path (menu, desktop_id_table, file, NULL);
+      g_object_unref (file);
+    }
+
+  /* Free directory list */
+  g_list_free (app_dirs);
+
+  /* Collect filenames for submenus */
+  for (iter = menu->priv->submenus; iter != NULL; iter = g_list_next (iter))
+    garcon_menu_collect_files (iter->data, desktop_id_table);
+}
+
+
+
+static void
+garcon_menu_collect_files_from_path (GarconMenu  *menu,
+                                     GHashTable  *desktop_id_table,
+                                     GFile       *dir,
+                                     const gchar *id_prefix)
+{
+  GFileEnumerator *enumerator;
+  GFileInfo       *file_info;
+  GFile           *file;
+  gchar           *basename;
+  gchar           *new_id_prefix;
+  gchar           *desktop_id;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+
+  /* Skip directory if it doesn't exist */
+  if (G_UNLIKELY (!g_file_query_exists (dir, NULL)))
+    return;
+
+  /* Skip directory if it's not a directory */
+  if (G_UNLIKELY (g_file_query_file_type (dir, 
+                                          G_FILE_QUERY_INFO_NONE, 
+                                          NULL) != G_FILE_TYPE_DIRECTORY))
+    {
+      return;
+    }
+
+  /* Open directory for reading */
+  enumerator = g_file_enumerate_children (dir, "standard::name,standard::type",
+                                          G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+  /* Abort if directory cannot be opened */
+  if (G_UNLIKELY (enumerator == NULL))
+    return;
+
+  /* Read file by file */
+  while (TRUE)
+    {
+      file_info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+
+      if (G_UNLIKELY (file_info == NULL))
+        break;
+
+      file = g_file_resolve_relative_path (dir, g_file_info_get_name (file_info));
+      basename = g_file_get_basename (file);
+
+      /* Treat files and directories differently */
+      if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
+        {
+          /* Create new desktop-file id prefix */
+          if (G_LIKELY (id_prefix == NULL))
+            new_id_prefix = g_strdup (basename);
+          else
+            new_id_prefix = g_strjoin ("-", id_prefix, basename, NULL);
+
+          /* Collect files in the directory */
+          garcon_menu_collect_files_from_path (menu, desktop_id_table, file, new_id_prefix);
+
+          /* Free id prefix */
+          g_free (new_id_prefix);
+        }
+      else
+        {
+          /* Skip all filenames which do not end with .desktop */
+          if (G_LIKELY (g_str_has_suffix (basename, ".desktop")))
+            {
+              /* Create desktop-file id */
+              if (G_LIKELY (id_prefix == NULL))
+                desktop_id = g_strdup (basename);
+              else
+                desktop_id = g_strjoin ("-", id_prefix, basename, NULL);
+
+              /* Insert into the files hash table if the desktop-file id does not exist there yet */
+              if (G_LIKELY (g_hash_table_lookup (desktop_id_table, desktop_id) == NULL))
+                g_hash_table_insert (desktop_id_table, desktop_id, g_file_get_uri (file));
+              else
+                g_free (desktop_id);
+            }
+        }
+
+      /* Free absolute path */
+      g_free (basename);
+
+      /* Destroy file */
+      g_object_unref (file);
+    }
+
+  g_object_unref (enumerator);
+}
+
+
+
+static gboolean
+collect_rules (GNode  *node,
+               GList **list)
+{
+  GarconMenuNodeType type;
+
+  type = garcon_menu_node_tree_get_node_type (node);
+
+  if (type == GARCON_MENU_NODE_TYPE_INCLUDE ||
+      type == GARCON_MENU_NODE_TYPE_EXCLUDE)
+    {
+      *list = g_list_append (*list, node);
+    }
+
+  return FALSE;
+}
+
+
+
+static void
+garcon_menu_resolve_items (GarconMenu *menu,
+                           GHashTable *desktop_id_table,
+                           gboolean    only_unallocated)
+{
+  GList  *rules = NULL;
+  GList  *iter;
+  gboolean menu_only_unallocated = FALSE;
+
+  g_return_if_fail (menu != NULL && GARCON_IS_MENU (menu));
+
+  menu_only_unallocated = garcon_menu_node_tree_get_boolean_child (menu->priv->tree, 
+                                                                   GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED);
+
+  /* Resolve items in this menu (if it matches the only_unallocated argument.
+   * This means that in the first pass, all items of menus without 
+   * <OnlyUnallocated /> are resolved and in the second pass, only items of 
+   * menus with <OnlyUnallocated /> are resolved */
+  if (menu_only_unallocated == only_unallocated)
+    {
+      g_node_traverse (menu->priv->tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
+                       (GNodeTraverseFunc) collect_rules, &rules);
+
+      /* Iterate over all rules */
+      for (iter = rules; iter != NULL; iter = g_list_next (iter))
+        {
+          if (G_LIKELY (garcon_menu_node_tree_get_node_type (iter->data) == GARCON_MENU_NODE_TYPE_INCLUDE))
+            {
+              /* Resolve available items and match them against this rule */
+              garcon_menu_resolve_items_by_rule (menu, desktop_id_table, iter->data);
+            }
+          else
+            {
+              /* Remove all items matching this exclude rule from the item pool */
+              garcon_menu_item_pool_apply_exclude_rule (menu->priv->pool, iter->data);
+            }
+        }
+    }
+
+  /* Iterate over all submenus */
+  for (iter = menu->priv->submenus; iter != NULL; iter = g_list_next (iter))
+    {
+      /* Resolve items of the submenu */
+      garcon_menu_resolve_items (GARCON_MENU (iter->data), desktop_id_table, only_unallocated);
+    }
+}
+
+
+
+static void
+garcon_menu_resolve_items_by_rule (GarconMenu *menu,
+                                   GHashTable *desktop_id_table,
+                                   GNode      *node)
+{
+  GarconMenuPair pair;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+
+  /* Store menu and rule pointer in the pair */
+  pair.first = menu;
+  pair.second = node;
+
+  /* Try to insert each of the collected desktop entry filenames into the menu */
+  g_hash_table_foreach (desktop_id_table, (GHFunc) garcon_menu_resolve_item_by_rule, &pair);
+}
+
+
+
+static void
+garcon_menu_resolve_item_by_rule (const gchar    *desktop_id,
+                                  const gchar    *uri,
+                                  GarconMenuPair *data)
+{
+  GarconMenuItem *item = NULL;
+  GarconMenu     *menu = NULL;
+  GNode          *node = NULL;
+  gboolean        only_unallocated = FALSE;
+
+  g_return_if_fail (GARCON_IS_MENU (data->first));
+  g_return_if_fail (data->second != NULL);
+
+  /* Restore menu and rule from the data pair */
+  menu = data->first;
+  node = data->second;
+
+  /* Try to load the menu item from the cache */
+  item = garcon_menu_item_cache_lookup (menu->priv->cache, uri, desktop_id);
+
+  if (G_LIKELY (item != NULL))
+    {
+      only_unallocated = garcon_menu_node_tree_get_boolean_child (menu->priv->tree,
+                                                                  GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED);
+
+      /* Only include item if menu not only includes unallocated items
+       * or if the item is not allocated yet */
+      if (!only_unallocated || garcon_menu_item_get_allocated (item) == 0)
+        {
+          /* Add item to the pool if it matches the include rule */
+          if (G_LIKELY (garcon_menu_node_tree_rule_matches (node, item)))
+            garcon_menu_item_pool_insert (menu->priv->pool, item);
+        }
+    }
+}
+
+
+
+static void
+garcon_menu_remove_deleted_menus (GarconMenu *menu)
+{
+  GarconMenu *submenu;
+  GList      *iter;
+  gboolean    deleted;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+
+  /* Note: There's a limitation: if the root menu has a <Deleted/> we
+   * can't just free the pointer here. Therefor we only check child menus. */
+
+  for (iter = menu->priv->submenus; iter != NULL; iter = g_list_next (iter))
+    {
+      submenu = iter->data;
+
+      /* Check whether there is a <Deleted/> element */
+      deleted = garcon_menu_node_tree_get_boolean_child (submenu->priv->tree, 
+                                                         GARCON_MENU_NODE_TYPE_DELETED);
+
+      /* Determine whether this submenu was deleted */
+      if (G_LIKELY (submenu->priv->directory != NULL))
+        deleted = deleted || garcon_menu_directory_get_hidden (submenu->priv->directory);
+
+      /* Remove submenu if it is deleted, otherwise check submenus of the submenu */
+      if (G_UNLIKELY (deleted))
+        {
+          /* Remove submenu from the list ... */
+          menu->priv->submenus = g_list_remove_link (menu->priv->submenus, iter);
+
+          /* ... and destroy it */
+          g_object_unref (submenu);
+        }
+      else
+        garcon_menu_remove_deleted_menus (submenu);
+    }
+}
+
+
+
+GarconMenuItemPool*
+garcon_menu_get_item_pool (GarconMenu *menu)
+{
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+
+  return menu->priv->pool;
+}
+
+
+
+static void
+items_collect (const gchar    *desktop_id,
+               GarconMenuItem *item,
+               GList         **listp)
+{
+  *listp = g_list_prepend (*listp, item);
+}
+
+
+
+/**
+ * garcon_menu_get_items:
+ * @menu : a #GarconMenu.
+ *
+ * Returns all #GarconMenuItem<!---->s included in @menu. The items are 
+ * sorted by their display names in ascending order.
+ *
+ * The caller is responsible to free the returned list using
+ * <informalexample><programlisting>
+ * g_list_free (list);
+ * </programlisting></informalexample>
+ * when no longer needed.
+ * 
+ * Return value: list of #GarconMenuItem<!---->s included in @menu.
+ **/
+GList *
+garcon_menu_get_items (GarconMenu *menu)
+{
+  GList *items = NULL;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+
+  /* Collect the items in the pool */
+  garcon_menu_item_pool_foreach (menu->priv->pool, (GHFunc) items_collect, &items);
+
+  /* Sort items */
+  items = g_list_sort (items, (GCompareFunc) garcon_menu_compare_items);
+
+  return items;
+}
+
+
+
+static GNode *
+garcon_menu_get_layout (GarconMenu *menu,
+                        gboolean    default_only)
+{
+  GNode *layout = NULL;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+
+  if (G_LIKELY (!default_only))
+    {
+      layout = garcon_menu_node_tree_get_child_node (menu->priv->tree, 
+                                                     GARCON_MENU_NODE_TYPE_LAYOUT,
+                                                     TRUE);
+    }
+
+  if (layout == NULL)
+    {
+      layout = garcon_menu_node_tree_get_child_node (menu->priv->tree,
+                                                     GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT,
+                                                     TRUE);
+
+      if (layout == NULL && menu->priv->parent != NULL)
+        layout = garcon_menu_get_layout (menu->priv->parent, TRUE);
+    }
+
+  return layout;
+}
+
+
+
+static gboolean
+layout_has_menuname (GNode       *layout,
+                     const gchar *name)
+{
+  GList   *nodes;
+  GList   *iter;
+  gboolean has_menuname = FALSE;  
+
+  nodes = garcon_menu_node_tree_get_child_nodes (layout, GARCON_MENU_NODE_TYPE_MENUNAME, 
+                                                 FALSE);
+
+  for (iter = g_list_first (nodes); !has_menuname && iter != NULL; iter = g_list_next (iter))
+    if (g_str_equal (garcon_menu_node_tree_get_string (iter->data), name))
+      has_menuname = TRUE;
+
+  g_list_free (nodes);
+
+  return has_menuname;
+}
+
+
+
+static gboolean
+layout_has_filename (GNode       *layout,
+                     const gchar *desktop_id)
+{
+  GList   *nodes;
+  GList   *iter;
+  gboolean has_filename = FALSE;  
+
+  nodes = garcon_menu_node_tree_get_child_nodes (layout, GARCON_MENU_NODE_TYPE_FILENAME, 
+                                                 FALSE);
+
+  for (iter = g_list_first (nodes); !has_filename && iter != NULL; iter = g_list_next (iter))
+    if (g_str_equal (garcon_menu_node_tree_get_string (iter->data), desktop_id))
+      has_filename = TRUE;
+
+  g_list_free (nodes);
+
+  return has_filename;
+}
+
+
+
+static void
+layout_elements_collect (GList **dest_list,
+                         GList  *src_list,
+                         GNode  *layout)
+{
+  GList *iter;
+
+  for (iter = src_list; iter != NULL; iter = g_list_next (iter))
+    {
+      if (GARCON_IS_MENU (iter->data))
+        {
+          if (G_LIKELY (!layout_has_menuname (layout, garcon_menu_get_name (iter->data))))
+            *dest_list = g_list_append (*dest_list, iter->data);
+        }
+      else if (GARCON_IS_MENU_ITEM (iter->data))
+        {
+          if (G_LIKELY (!layout_has_filename (layout, garcon_menu_item_get_desktop_id (iter->data))))
+            *dest_list = g_list_append (*dest_list, iter->data);
+        }
+    }
+}
+
+
+
+GList *
+garcon_menu_get_elements (GarconMenu *menu)
+{
+  GarconMenuLayoutMergeType merge_type;
+  GarconMenuNodeType        type;
+  GarconMenuItem           *item;
+  GarconMenu               *submenu;
+  GList                    *items = NULL;
+  GList                    *menu_items;
+  GNode                    *layout = NULL;
+  GNode                    *node;
+
+  g_return_val_if_fail (GARCON_IS_MENU (menu), NULL);
+
+  /* Determine layout node */
+  layout = garcon_menu_get_layout (menu, FALSE);
+
+  /* There should always be a layout, otherwise GarconMenuMerger is broken */
+  g_return_val_if_fail (layout != NULL, NULL);
+
+  /* Process layout nodes in order */
+  for (node = g_node_first_child (layout); node != NULL; node = g_node_next_sibling (node))
+    {
+      /* Determine layout node type */
+      type = garcon_menu_node_tree_get_node_type (node);
+
+      if (type == GARCON_MENU_NODE_TYPE_FILENAME)
+        {
+          /* Search for desktop ID in the item pool */
+          item = garcon_menu_item_pool_lookup (menu->priv->pool, 
+                                               garcon_menu_node_tree_get_string (node));
+
+          /* If the item with this desktop ID is included in the menu, append it to the list */
+          if (G_LIKELY (item != NULL))
+            items = g_list_append (items, item);
+        }
+      if (type == GARCON_MENU_NODE_TYPE_MENUNAME)
+        {
+          /* Search submenu with this name */
+          submenu = garcon_menu_get_menu_with_name (menu, 
+                                                    garcon_menu_node_tree_get_string (node));
+
+          /* If there is such a menu, append it to the list */
+          if (G_LIKELY (submenu != NULL))
+            items = g_list_append (items, submenu);
+        }
+      else if (type == GARCON_MENU_NODE_TYPE_SEPARATOR)
+        {
+          /* Append separator to the list */
+          items = g_list_append (items, garcon_menu_separator_get_default ());
+        }
+      else if (type == GARCON_MENU_NODE_TYPE_MERGE)
+        {
+          /* Determine merge type */
+          merge_type = garcon_menu_node_tree_get_layout_merge_type (node);
+
+          if (merge_type == GARCON_MENU_LAYOUT_MERGE_ALL)
+            {
+              /* Get all menu items of this menu */
+              menu_items = garcon_menu_get_items (menu);
+              
+              /* Append submenus */
+              menu_items = g_list_concat (menu_items, garcon_menu_get_menus (menu));
+
+              /* Sort menu items */
+              menu_items = g_list_sort (menu_items, (GCompareFunc) garcon_menu_compare_items);
+
+              /* Append menu items to the returned item list */
+              layout_elements_collect (&items, menu_items, layout);
+            }
+          else if (merge_type == GARCON_MENU_LAYOUT_MERGE_FILES)
+            {
+              /* Get all menu items of this menu */
+              menu_items = garcon_menu_get_items (menu);
+
+              /* Append menu items to the returned item list */
+              layout_elements_collect (&items, menu_items, layout);
+            }
+          else if (merge_type == GARCON_MENU_LAYOUT_MERGE_MENUS)
+            {
+              /* Get all submenus */
+              menu_items = garcon_menu_get_menus (menu);
+
+              /* Append submenus to the returned item list */
+              layout_elements_collect (&items, menu_items, layout);
+            }
+        }
+    }
+  
+  return items;
+}
+
+
+
+static gint
+garcon_menu_compare_items (gconstpointer *a,
+                           gconstpointer *b)
+{
+  return g_utf8_collate (garcon_menu_element_get_name (GARCON_MENU_ELEMENT (a)), 
+                         garcon_menu_element_get_name (GARCON_MENU_ELEMENT (b)));
+}
+
+
+
+static const gchar*
+garcon_menu_get_element_name (GarconMenuElement *element)
+{
+  GarconMenu    *menu;
+  const gchar   *name = NULL;
+
+  g_return_val_if_fail (GARCON_IS_MENU (element), NULL);
+
+  menu = GARCON_MENU (element);
+
+  /* Try directory name first */
+  if (menu->priv->directory != NULL)
+    name = garcon_menu_directory_get_name (menu->priv->directory);
+
+  /* Otherwise use the menu name as a fallback */
+  if (name == NULL)
+    name = garcon_menu_get_name (menu);
+
+  return name;
+}
+
+
+
+static const gchar*
+garcon_menu_get_element_comment (GarconMenuElement *element)
+{
+  GarconMenu *menu;
+
+  g_return_val_if_fail (GARCON_IS_MENU (element), NULL);
+
+  menu = GARCON_MENU (element);
+
+  if (menu->priv->directory == NULL)
+    return NULL;
+  else
+    return garcon_menu_directory_get_comment (menu->priv->directory);
+}
+
+
+
+static const gchar*
+garcon_menu_get_element_icon_name (GarconMenuElement *element)
+{
+  GarconMenu *menu;
+  
+  g_return_val_if_fail (GARCON_IS_MENU (element), NULL);
+
+  menu = GARCON_MENU (element);
+
+  if (menu->priv->directory == NULL)
+    return NULL;
+  else
+    return garcon_menu_directory_get_icon (menu->priv->directory);
+}
+
+
+
+static gboolean
+garcon_menu_get_element_visible (GarconMenuElement *element)
+{
+  GarconMenu *menu;
+  GList      *items;
+  GList      *iter;
+  gboolean    visible = FALSE;
+
+  g_return_val_if_fail (GARCON_IS_MENU (element), FALSE);
+
+  menu = GARCON_MENU (element);
+
+  if (menu->priv->directory != NULL)
+    {
+      if (!garcon_menu_directory_get_visible (menu->priv->directory))
+        return FALSE;
+    }
+
+  /* if a menu has no visible children it shouldn't be visible */
+  items = garcon_menu_get_elements (menu);
+  for (iter = items; visible != TRUE && iter != NULL; iter = g_list_next (iter))
+    {
+      if (garcon_menu_element_get_visible (GARCON_MENU_ELEMENT (iter->data)))
+        visible = TRUE;
+    }
+
+  g_list_free (items);
+  return visible;
+}
+
+
+
+static gboolean
+garcon_menu_get_element_show_in_environment (GarconMenuElement *element)
+{
+  GarconMenu *menu;
+
+  g_return_val_if_fail (GARCON_IS_MENU (element), FALSE);
+
+  menu = GARCON_MENU (element);
+
+  if (menu->priv->directory == NULL)
+    return FALSE;
+  else
+    return garcon_menu_directory_get_show_in_environment (menu->priv->directory);
+}
+
+
+
+static gboolean
+garcon_menu_get_element_no_display (GarconMenuElement *element)
+{
+  GarconMenu *menu;
+
+  g_return_val_if_fail (GARCON_IS_MENU (element), FALSE);
+
+  menu = GARCON_MENU (element);
+
+  if (menu->priv->directory == NULL)
+    return FALSE;
+  else
+    return garcon_menu_directory_get_no_display (menu->priv->directory);
+}
+
+
+
+static void
+item_monitor_start (const gchar    *desktop_id,
+                    GarconMenuItem *item,
+                    GarconMenu     *menu)
+{
+  garcon_menu_monitor_add_item (menu, item);
+}
+
+
+
+static void
+garcon_menu_monitor_start (GarconMenu *menu)
+{
+  GList *iter;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+
+  /* TODO Make monitoring work properly again */
+#if 0
+  /* Monitor the menu file */
+  if (G_LIKELY (garcon_menu_monitor_has_flags (GARCON_MENU_MONITOR_MENU_FILES)))
+    garcon_menu_monitor_add_file (menu, menu->priv->filename);
+
+  /* Monitor the menu directory file */
+  if (G_LIKELY (GARCON_IS_MENU_DIRECTORY (menu->priv->directory) 
+                && garcon_menu_monitor_has_flags (GARCON_MENU_MONITOR_DIRECTORY_FILES)))
+    {
+      garcon_menu_monitor_add_file (menu, garcon_menu_directory_get_filename (menu->priv->directory));
+    }
+
+  /* Monitor the application directories */
+  if (G_LIKELY (garcon_menu_monitor_has_flags (GARCON_MENU_MONITOR_DIRECTORIES)))
+    for (iter = menu->priv->app_dirs; iter != NULL; iter = g_list_next (iter))
+      garcon_menu_monitor_add_directory (menu, (const gchar *)iter->data);
+#endif
+
+  /* Monitor items in the menu pool */
+  if (G_LIKELY (garcon_menu_monitor_has_flags (GARCON_MENU_MONITOR_DESKTOP_FILES)))
+    garcon_menu_item_pool_foreach (menu->priv->pool, (GHFunc) item_monitor_start, menu);
+
+  /* Monitor items in submenus */
+  for (iter = menu->priv->submenus; iter != NULL; iter = g_list_next (iter))
+    garcon_menu_monitor_start (GARCON_MENU (iter->data));
+}
+
+
+
+static void
+item_monitor_stop (const gchar    *desktop_id,
+                   GarconMenuItem *item,
+                   GarconMenu     *menu)
+{
+  garcon_menu_monitor_remove_item (menu, item);
+}
+
+
+
+static void
+garcon_menu_monitor_stop (GarconMenu *menu)
+{
+  GList *iter;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+
+  /* Stop monitoring items in submenus */
+  for (iter = menu->priv->submenus; iter != NULL; iter = g_list_next (iter))
+    garcon_menu_monitor_stop (GARCON_MENU (iter->data));
+
+  /* Stop monitoring the items */
+  garcon_menu_item_pool_foreach (menu->priv->pool, (GHFunc) item_monitor_stop, menu);
+
+  /* TODO Make monitoring work properly again */
+#if 0
+  /* Stop monitoring the application directories */
+  for (iter = menu->priv->app_dirs; iter != NULL; iter = g_list_next (iter))
+    garcon_menu_monitor_remove_directory (menu, (const gchar *)iter->data);
+
+  /* Stop monitoring the menu directory file */
+  if (GARCON_IS_MENU_DIRECTORY (menu->priv->directory))
+    garcon_menu_monitor_remove_file (menu, garcon_menu_directory_get_filename (menu->priv->directory));
+
+  /* Stop monitoring the menu file */
+  garcon_menu_monitor_remove_file (menu, menu->priv->filename);
+#endif
+}
diff --git a/garcon/garcon-menu.h b/garcon/garcon-menu.h
new file mode 100644
index 0000000..b519323
--- /dev/null
+++ b/garcon/garcon-menu.h
@@ -0,0 +1,70 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GARCON_MENU_H__
+#define __GARCON_MENU_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GARCON_TYPE_MENU            (garcon_menu_get_type ())
+#define GARCON_MENU(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GARCON_TYPE_MENU, GarconMenu))
+#define GARCON_MENU_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GARCON_TYPE_MENU, GarconMenuClass))
+#define GARCON_IS_MENU(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GARCON_TYPE_MENU))
+#define GARCON_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GARCON_TYPE_MENU))
+#define GARCON_MENU_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GARCON_TYPE_MENU, GarconMenuClass))
+
+typedef struct _GarconMenuPrivate GarconMenuPrivate;
+typedef struct _GarconMenuClass   GarconMenuClass;
+typedef struct _GarconMenu        GarconMenu;
+
+GType                garcon_menu_get_type           (void) G_GNUC_CONST;
+
+GarconMenu          *garcon_menu_new                (const gchar  *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+GarconMenu          *garcon_menu_new_for_file       (GFile        *file) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+GarconMenu          *garcon_menu_new_applications   (void) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+gboolean             garcon_menu_load               (GarconMenu   *menu, 
+                                                     GCancellable *cancellable,
+                                                     GError      **error);
+GFile               *garcon_menu_get_file           (GarconMenu   *menu);
+GarconMenuDirectory *garcon_menu_get_directory      (GarconMenu   *menu);
+GList               *garcon_menu_get_menus          (GarconMenu   *menu);
+GarconMenu          *garcon_menu_get_menu_with_name (GarconMenu   *menu,
+                                                     const gchar  *name);
+GarconMenu          *garcon_menu_get_parent         (GarconMenu   *menu);
+GList               *garcon_menu_get_elements       (GarconMenu   *menu);
+
+struct _GarconMenuClass
+{
+  GObjectClass __parent__;
+};
+
+struct _GarconMenu
+{
+  GObject              __parent__;
+
+  /* < private > */
+  GarconMenuPrivate *priv;
+};
+
+G_END_DECLS
+
+#endif /* !__GARCON_MENU_H__ */
diff --git a/garcon/garcon.c b/garcon/garcon.c
new file mode 100644
index 0000000..c4ed531
--- /dev/null
+++ b/garcon/garcon.c
@@ -0,0 +1,153 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General 
+ * Public License along with this library; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib-object.h>
+
+#include <garcon/garcon.h>
+#include <garcon/garcon-environment.h>
+#include <garcon/garcon-menu-item-cache.h>
+#include <garcon/garcon-menu-directory.h>
+#include <garcon/garcon-menu-monitor.h>
+#include <garcon/garcon-menu-separator.h>
+
+
+
+/**
+ * SECTION:garcon
+ * @title: Library Initialization and Shutdown
+ *
+ * Library Initialization and Shutdown.
+ **/
+
+
+
+static gint garcon_ref_count = 0;
+
+
+
+/**
+ * garcon_init:
+ * @env : name of the desktop environment (e.g. XFCE, GNOME or KDE) 
+ *        or %NULL.
+ *
+ * Initializes the garcon library. @env optionally defines the 
+ * name of the desktop environment for which menus will be generated. 
+ * This means that items belonging only to other desktop environments 
+ * will be ignored.
+ **/
+void
+garcon_init (const gchar *env)
+{
+  if (g_atomic_int_exchange_and_add (&garcon_ref_count, 1) == 0)
+    {
+      /* Initialize the GThread system */
+      if (!g_thread_supported ())
+        g_thread_init (NULL);
+
+      /* Initialize the GObject type system */
+      g_type_init ();
+
+      /* Set desktop environment */
+      garcon_set_environment (env);
+
+      /* Initialize the menu item cache */
+      _garcon_menu_item_cache_init ();
+
+      /* Initialize the directory module */
+      _garcon_menu_directory_init ();
+
+      /* Initialize monitoring system */
+      _garcon_menu_monitor_init ();
+
+      /* Creates the menu separator */
+      _garcon_menu_separator_init ();
+   }
+}
+
+
+
+/**
+ * garcon_shutdown:
+ *
+ * Shuts the garcon library down.
+ **/
+void
+garcon_shutdown (void)
+{
+  if (g_atomic_int_dec_and_test (&garcon_ref_count))
+    {
+      /* Unset desktop environment */
+      garcon_set_environment (NULL);
+
+      /* Destroys the menu separator */
+      _garcon_menu_separator_shutdown ();
+
+      /* Shutdown monitoring system */
+      _garcon_menu_monitor_shutdown ();
+
+      /* Shutdown the directory module */
+      _garcon_menu_directory_shutdown ();
+
+      /* Shutdown the menu item cache */
+      _garcon_menu_item_cache_shutdown ();
+    }
+}
+
+
+
+gchar *
+garcon_config_lookup (const gchar *filename)
+{
+  const gchar * const *dirs;
+  gchar               *path;
+  gint                 i;
+
+  g_return_val_if_fail (filename != NULL && g_utf8_strlen (filename, -1) > 0, NULL);
+
+  path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_config_dir (), filename, NULL);
+
+  if (!g_file_test (path, G_FILE_TEST_EXISTS))
+    {
+      g_free (path);
+      path = NULL;
+
+      dirs = g_get_system_config_dirs ();
+
+      for (i = 0; path == NULL && dirs[i] != NULL; ++i)
+        {
+          if (g_path_is_absolute (dirs[i]))
+            {
+              path = g_build_path (G_DIR_SEPARATOR_S, dirs[i], filename, NULL);
+
+              if (!g_file_test (path, G_FILE_TEST_IS_REGULAR))
+                {
+                  g_free (path);
+                  path = NULL;
+                }
+            }
+        }
+    }
+  
+  return path;
+}
diff --git a/garcon/garcon.h b/garcon/garcon.h
new file mode 100644
index 0000000..e757fa9
--- /dev/null
+++ b/garcon/garcon.h
@@ -0,0 +1,54 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2006-2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GARCON_H__
+#define __GARCON_H__
+
+#include <gio/gio.h>
+
+#define GARCON_INSIDE_GARCON_H
+
+#include <garcon/garcon-config.h>
+#include <garcon/garcon-menu-directory.h>
+#include <garcon/garcon-menu-element.h>
+#include <garcon/garcon-environment.h>
+#include <garcon/garcon-menu.h>
+#include <garcon/garcon-menu-item.h>
+#include <garcon/garcon-menu-item-cache.h>
+#include <garcon/garcon-menu-item-pool.h>
+#include <garcon/garcon-menu-node.h>
+#include <garcon/garcon-menu-merger.h>
+#include <garcon/garcon-menu-monitor.h>
+#include <garcon/garcon-menu-parser.h>
+#include <garcon/garcon-menu-separator.h>
+#include <garcon/garcon-menu-tree-provider.h>
+
+#undef GARCON_INSIDE_GARCON_H
+
+G_BEGIN_DECLS
+
+void   garcon_init          (const gchar *env);
+void   garcon_shutdown      (void);
+
+gchar *garcon_config_lookup (const gchar *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+G_END_DECLS
+
+#endif /* !__GARCON_H__ */
diff --git a/libxfce4menu/Makefile.am b/libxfce4menu/Makefile.am
deleted file mode 100644
index a2051de..0000000
--- a/libxfce4menu/Makefile.am
+++ /dev/null
@@ -1,87 +0,0 @@
-# $Id$ 
-#
-# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
-
-INCLUDES = 								\
-	-I$(top_srcdir)							\
-	-DLIBXFCE4MENU_COMPILATION					\
-	-DLIBXFCE4MENU_VERSION_API=\"$(LIBXFCE4MENU_VERSION_API)\"	\
-	-DG_LOG_DOMAIN=\"libxfce4menu\"					\
-	$(PLATFORM_CFLAGS)
-
-lib_LTLIBRARIES = 							\
-	libxfce4menu-0.1.la
-
-libxfce4menu_headers =							\
-	xfce-menu.h							\
-	xfce-menu-element.h						\
-	xfce-menu-separator.h						\
-	xfce-menu-layout.h						\
-	xfce-menu-directory.h						\
-	xfce-menu-rules.h						\
-	xfce-menu-standard-rules.h					\
-	xfce-menu-or-rules.h						\
-	xfce-menu-and-rules.h						\
-	xfce-menu-not-rules.h						\
-	xfce-menu-item-pool.h						\
-	xfce-menu-item-cache.h						\
-	xfce-menu-move.h						\
-	xfce-menu-environment.h						\
-	xfce-menu-monitor.h						\
-	xfce-menu-item.h						
-
-libxfce4menu_sources =							\
-	xfce-menu.c							\
-	xfce-menu-element.c						\
-	xfce-menu-separator.c						\
-	xfce-menu-layout.c						\
-	xfce-menu-directory.c						\
-	xfce-menu-rules.c						\
-	xfce-menu-standard-rules.c					\
-	xfce-menu-or-rules.c						\
-	xfce-menu-and-rules.c						\
-	xfce-menu-not-rules.c						\
-	xfce-menu-item-pool.c						\
-	xfce-menu-item-cache.c						\
-	xfce-menu-move.c						\
-	xfce-menu-environment.c						\
-	xfce-menu-monitor.c						\
-	xfce-menu-item.c						
-
-libxfce4menuincludedir = $(includedir)/xfce4/libxfce4menu-0.1/libxfce4menu
-
-libxfce4menuinclude_HEADERS =						\
-	$(libxfce4menu_headers)						\
-	libxfce4menu.h							\
-	libxfce4menu-config.h
-
-libxfce4menu_0_1_la_DEPENDENCIES = 					\
-	$(top_builddir)/tdb/libtdb.la
-
-libxfce4menu_0_1_la_SOURCES =						\
-	$(libxfce4menu_sources)						\
-	$(libxfce4menu_headers)
-
-libxfce4menu_0_1_la_CFLAGS = 						\
-	$(GLIB_CFLAGS)							\
-	$(GTHREAD_CFLAGS)						\
-	$(LIBXFCE4UTIL_CFLAGS)						\
-	$(PLATFORM_CFLAGS)						
-
-libxfce4menu_0_1_la_LDFLAGS =						\
-	-no-undefined							\
-	-export-dynamic							\
-	-version-info $(LIBXFCE4MENU_VERINFO)				\
-	$(PLATFORM_LDFLAGS)
-	
-libxfce4menu_0_1_la_LIBADD = 						\
-	$(GLIB_LIBS)							\
-	$(GTHREAD_LIBS)							\
-	$(LIBXFCE4UTIL_LIBS)						\
-	$(top_builddir)/tdb/libtdb.la
-
-EXTRA_DIST =								\
-	libxfce4menu-config.h.in
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libxfce4menu-0.1.pc
diff --git a/libxfce4menu/libxfce4menu-0.1.pc.in b/libxfce4menu/libxfce4menu-0.1.pc.in
deleted file mode 100644
index 982643e..0000000
--- a/libxfce4menu/libxfce4menu-0.1.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-libxfce4menu_api_version=@LIBXFCE4MENU_VERSION_API@
-
-Name: @PACKAGE_TARNAME@
-Description: Freedesktop.org compliant menu library
-Requires: gtk+-2.0 libxfce4util-1.0
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -lxfce4menu-${libxfce4menu_api_version}
-Cflags: -I${includedir}/xfce4/libxfce4menu-${libxfce4menu_api_version}
diff --git a/libxfce4menu/libxfce4menu-config.h.in b/libxfce4menu/libxfce4menu-config.h.in
deleted file mode 100644
index 79240dc..0000000
--- a/libxfce4menu/libxfce4menu-config.h.in
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2008 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined (LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined (LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly, this file may disappear or change contents."
-#endif
-
-#ifndef __LIBXFCE4MENU_CONFIG_H__
-#define __LIBXFCE4MENU_CONFIG_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-#define LIBXFCE4MENU_MAJOR_VERSION @LIBXFCE4MENU_VERSION_MAJOR@
-#define LIBXFCE4MENU_MINOR_VERSION @LIBXFCE4MENU_VERSION_MINOR@
-#define LIBXFCE4MENU_MICRO_VERSION @LIBXFCE4MENU_VERSION_MICRO@
-
-#define LIBXFCE4MENU_CHECK_VERSION(major,minor,micro) \
-  (LIBXFCE4MENU_MAJOR_VERSION > (major) \
-   || (LIBXFCE4MENU_MAJOR_VERSION == (major) \
-       && LIBXFCE4MENU_MINOR_VERSION > (minor)) \
-   || (LIBXFCE4MENU_MAJOR_VERSION == (major) \
-       && LIBXFCE4MENU_MINOR_VERSION == (minor) \
-       && LIBXFCE4MENU_MICRO_VERSION >= (micro)))
-
-extern const guint libxfce4menu_major_version;
-extern const guint libxfce4menu_minor_version;
-extern const guint libxfce4menu_micro_version;
-
-const gchar *libxfce4menu_check_version (guint required_major,
-                                         guint required_minor,
-                                         guint required_micro);
-
-G_END_DECLS;
-
-#endif /* !__LIBXFCE4MENU_CONFIG_H__ */
diff --git a/libxfce4menu/libxfce4menu.h b/libxfce4menu/libxfce4menu.h
deleted file mode 100644
index 15c18b3..0000000
--- a/libxfce4menu/libxfce4menu.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __LIBXFCE4MENU_LIBXFCE4MENU_H__
-#define __LIBXFCE4MENU_LIBXFCE4MENU_H__
-
-#define LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H
-
-#include <libxfce4menu/libxfce4menu-config.h>
-#include <libxfce4menu/xfce-menu-environment.h>
-#include <libxfce4menu/xfce-menu-element.h>
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-item-pool.h>
-#include <libxfce4menu/xfce-menu-item-cache.h>
-#include <libxfce4menu/xfce-menu-rules.h>
-#include <libxfce4menu/xfce-menu-standard-rules.h>
-#include <libxfce4menu/xfce-menu-or-rules.h>
-#include <libxfce4menu/xfce-menu-and-rules.h>
-#include <libxfce4menu/xfce-menu-not-rules.h>
-#include <libxfce4menu/xfce-menu-directory.h>
-#include <libxfce4menu/xfce-menu-layout.h>
-#include <libxfce4menu/xfce-menu-separator.h>
-#include <libxfce4menu/xfce-menu.h>
-#include <libxfce4menu/xfce-menu-monitor.h>
-
-#define LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H
-
-#endif /* !__LIBXFCE4UTIL_LIBXFCE4UTIL_H__ */
diff --git a/libxfce4menu/xfce-menu-and-rules.c b/libxfce4menu/xfce-menu-and-rules.c
deleted file mode 100644
index 1339635..0000000
--- a/libxfce4menu/xfce-menu-and-rules.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-rules.h>
-#include <libxfce4menu/xfce-menu-standard-rules.h>
-#include <libxfce4menu/xfce-menu-and-rules.h>
-
-
-
-static void     xfce_menu_and_rules_class_init     (XfceMenuAndRulesClass *klass);
-static void     xfce_menu_and_rules_init           (XfceMenuAndRules      *rules);
-static void     xfce_menu_and_rules_finalize       (GObject               *object);
-static gboolean xfce_menu_and_rules_match          (XfceMenuStandardRules *rules,
-                                                    XfceMenuItem          *item);
-
-
-
-struct _XfceMenuAndRulesClass
-{
-  XfceMenuStandardRulesClass __parent__;
-};
-
-struct _XfceMenuAndRules
-{
-  XfceMenuStandardRules __parent__;
-};
-
-
-
-static GObjectClass *xfce_menu_and_rules_parent_class = NULL;
-
-
-
-GType
-xfce_menu_and_rules_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuAndRulesClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_and_rules_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuAndRules),
-        0,
-        (GInstanceInitFunc) xfce_menu_and_rules_init,
-        NULL,
-      };
-
-      type = g_type_register_static (XFCE_TYPE_MENU_STANDARD_RULES, "XfceMenuAndRules", &info, 0);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_and_rules_class_init (XfceMenuAndRulesClass *klass)
-{
-  GObjectClass *gobject_class;
-  XfceMenuStandardRulesClass *rules_class;
-
-  /* Determine the parent type class */
-  xfce_menu_and_rules_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_and_rules_finalize;
-
-  rules_class = XFCE_MENU_STANDARD_RULES_CLASS (klass);
-  rules_class->match_item = xfce_menu_and_rules_match;
-}
-
-
-
-static void
-xfce_menu_and_rules_init (XfceMenuAndRules *rules)
-{
-}
-
-
-
-static void
-xfce_menu_and_rules_finalize (GObject *object)
-{
-  (*G_OBJECT_CLASS (xfce_menu_and_rules_parent_class)->finalize) (object); 
-}
-
-
-
-XfceMenuAndRules*
-xfce_menu_and_rules_new (void)
-{
-  return g_object_new (XFCE_TYPE_MENU_AND_RULES, NULL);
-}
-
-
-
-static gboolean
-xfce_menu_and_rules_match (XfceMenuStandardRules *rules,
-                           XfceMenuItem          *item)
-{
-  GList                 *iter;
-
-  g_return_val_if_fail (XFCE_IS_MENU_STANDARD_RULES (rules), FALSE);
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
-
-  /* Check if all elements should be included */
-  if (rules->all)
-    return TRUE;
-
-  /* Compare desktop id's */
-  for (iter = rules->filenames; iter != NULL; iter = g_list_next (iter))
-    {
-      if (g_utf8_collate (xfce_menu_item_get_desktop_id (item), iter->data) != 0)
-        return FALSE;
-    }
-
-  for (iter = rules->categories; iter != NULL; iter = g_list_next (iter))
-    {
-      if (!g_list_find_custom (xfce_menu_item_get_categories (item), iter->data, (GCompareFunc) g_utf8_collate))
-        return FALSE;
-    }
-
-  /* Match item against nested rules */
-  for (iter = g_list_first (rules->rules); iter != NULL; iter = g_list_next (iter))
-    {
-      if (!xfce_menu_rules_match (XFCE_MENU_RULES (iter->data), item))
-        return FALSE;
-    }
-
-  return TRUE;
-}
diff --git a/libxfce4menu/xfce-menu-and-rules.h b/libxfce4menu/xfce-menu-and-rules.h
deleted file mode 100644
index 8c61beb..0000000
--- a/libxfce4menu/xfce-menu-and-rules.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_AND_RULES_H__
-#define __XFCE_MENU_AND_RULES_H__
-
-#include <glib-object.h>
-
-typedef struct _XfceMenuAndRules        XfceMenuAndRules;
-typedef struct _XfceMenuAndRulesClass   XfceMenuAndRulesClass;
-
-#define XFCE_TYPE_MENU_AND_RULES             (xfce_menu_and_rules_get_type ())
-#define XFCE_MENU_AND_RULES(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_AND_RULES, XfceMenuAndRules))
-#define XFCE_MENU_AND_RULES_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_AND_RULES, XfceMenuAndRulesClass))
-#define XFCE_IS_MENU_AND_RULES(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_AND_RULES))
-#define XFCE_IS_MENU_AND_RULES_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((obj), XFCE_TYPE_MENU_AND_RULES))
-#define XFCE_MENU_AND_RULES_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_AND_RULES, XfceMenuAndRulesClass))
-
-GType             xfce_menu_and_rules_get_type (void) G_GNUC_CONST;
-
-XfceMenuAndRules *xfce_menu_and_rules_new      (void);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_AND_RULES_H__ */
diff --git a/libxfce4menu/xfce-menu-directory.c b/libxfce4menu/xfce-menu-directory.c
deleted file mode 100644
index 0a9c36c..0000000
--- a/libxfce4menu/xfce-menu-directory.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <locale.h>
-#include <glib.h>
-#include <libxfce4util/libxfce4util.h>
-
-#include <libxfce4menu/xfce-menu-environment.h>
-#include <libxfce4menu/xfce-menu-directory.h>
-
-
-
-void
-_xfce_menu_directory_init (void)
-{
-}
-
-
-
-void
-_xfce_menu_directory_shutdown (void)
-{
-}
-
-
-
-#define XFCE_MENU_DIRECTORY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_MENU_DIRECTORY, XfceMenuDirectoryPrivate))
-
-
-
-/* Desktop entry keys */
-#if 0
-static const gchar *desktop_entry_keys[] = 
-{
-  "Name",
-  "Comment",
-  "Icon",
-  "Categories",
-  "OnlyShowIn",
-  "NotShowIn",
-  "NoDisplay",
-  "Hidden",
-  NULL
-};
-#endif
-
-
-
-/* Property identifiers */
-enum
-{
-  PROP_0,
-  PROP_FILENAME,
-  PROP_NAME,
-  PROP_COMMENT,
-  PROP_NO_DISPLAY,
-  PROP_ICON,
-};
-
-
-
-static void       xfce_menu_directory_class_init       (XfceMenuDirectoryClass       *klass);
-static void       xfce_menu_directory_init             (XfceMenuDirectory            *directory);
-static void       xfce_menu_directory_finalize         (GObject                      *object);
-static void       xfce_menu_directory_get_property     (GObject                      *object,
-                                                        guint                         prop_id,
-                                                        GValue                       *value,
-                                                        GParamSpec                   *pspec);
-static void       xfce_menu_directory_set_property     (GObject                      *object,
-                                                        guint                         prop_id,
-                                                        const GValue                 *value,
-                                                        GParamSpec                   *pspec);
-static void       xfce_menu_directory_free_private     (XfceMenuDirectory            *directory);
-static void       xfce_menu_directory_load             (XfceMenuDirectory            *directory);
-
-
-
-struct _XfceMenuDirectoryPrivate
-{
-  /* Directory filename */
-  gchar             *filename;
-
-  /* Directory name */
-  gchar             *name;
-
-  /* Directory description (comment) */
-  gchar             *comment;
-
-  /* Icon */
-  gchar             *icon;
-
-  /* Environments in which the menu should be displayed only */
-  gchar            **only_show_in;
-
-  /* Environments in which the menu should be hidden */
-  gchar            **not_show_in;
-
-  /* Whether the menu should be ignored completely */
-  guint              hidden : 1;
-
-  /* Whether the menu should be hidden */
-  guint              no_display : 1;
-};
-
-struct _XfceMenuDirectoryClass
-{
-  GObjectClass __parent__;
-};
-
-struct _XfceMenuDirectory
-{
-  GObject          __parent__;
-
-  /* < private > */
-  XfceMenuDirectoryPrivate *priv;
-};
-
-
-
-static GObjectClass *xfce_menu_directory_parent_class = NULL;
-
-
-
-GType
-xfce_menu_directory_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuDirectoryClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_directory_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuDirectory),
-        0,
-        (GInstanceInitFunc) xfce_menu_directory_init,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenuDirectory", &info, 0);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_directory_class_init (XfceMenuDirectoryClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  g_type_class_add_private (klass, sizeof(XfceMenuDirectoryPrivate));
-
-  /* Determine the parent type class */
-  xfce_menu_directory_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_directory_finalize; 
-  gobject_class->get_property = xfce_menu_directory_get_property;
-  gobject_class->set_property = xfce_menu_directory_set_property;
-
-  /**
-   * XfceMenuDirectory:filename:
-   *
-   * The filename of an %XfceMenuDirectory object. Whenever this is redefined, the
-   * directory entry is parsed again.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_FILENAME,
-                                   g_param_spec_string ("filename",
-                                                        "Filename",
-                                                        "Directory filename",
-                                                        NULL,
-                                                        G_PARAM_READWRITE));
-
-  /**
-   * XfceMenuDirectory:name:
-   *
-   * Name of the directory.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_FILENAME,
-                                   g_param_spec_string ("name",
-                                                        "Name",
-                                                        "Directory name",
-                                                        NULL,
-                                                        G_PARAM_READWRITE));
-
-  /**
-   * XfceMenuDirectory:comment:
-   *
-   * Directory description (comment).
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_FILENAME,
-                                   g_param_spec_string ("comment",
-                                                        "Description",
-                                                        "Directory description",
-                                                        NULL,
-                                                        G_PARAM_READWRITE));
-
-  /**
-   * XfceMenuDirectory:icon:
-   *
-   * Icon associated with this directory.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_FILENAME,
-                                   g_param_spec_string ("icon",
-                                                        "Icon",
-                                                        "Directory icon",
-                                                        NULL,
-                                                        G_PARAM_READWRITE));
-
-  /**
-   * XfceMenuDirectory:no-display:
-   *
-   * Whether this menu item is hidden in menus.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_NO_DISPLAY,
-                                   g_param_spec_boolean ("no-display",
-                                                         "No Display",
-                                                         "Visibility state of the related menu",
-                                                         FALSE,
-                                                         G_PARAM_READWRITE));
-
-}
-
-
-
-static void
-xfce_menu_directory_init (XfceMenuDirectory *directory)
-{
-  directory->priv = XFCE_MENU_DIRECTORY_GET_PRIVATE (directory);
-  directory->priv->filename = NULL;
-  directory->priv->name = NULL;
-  directory->priv->icon = NULL;
-  directory->priv->only_show_in = NULL;
-  directory->priv->not_show_in = NULL;
-  directory->priv->hidden = FALSE;
-  directory->priv->no_display = FALSE;
-}
-
-
-
-static void
-xfce_menu_directory_finalize (GObject *object)
-{
-  XfceMenuDirectory *directory = XFCE_MENU_DIRECTORY (object);
-
-  /* Free private data */
-  xfce_menu_directory_free_private (directory);
-
-  /* Free filename */
-  if (G_LIKELY (directory->priv->filename != NULL))
-    g_free (directory->priv->filename);
-
-  (*G_OBJECT_CLASS (xfce_menu_directory_parent_class)->finalize) (object);
-}
-
-
-
-static void
-xfce_menu_directory_get_property (GObject    *object,
-                                  guint       prop_id,
-                                  GValue     *value,
-                                  GParamSpec *pspec)
-{
-  XfceMenuDirectory *directory = XFCE_MENU_DIRECTORY (object);
-
-  switch (prop_id)
-    {
-    case PROP_FILENAME:
-      g_value_set_string (value, xfce_menu_directory_get_filename (directory));
-      break;
-
-    case PROP_NAME:
-      g_value_set_string (value, xfce_menu_directory_get_name (directory));
-      break;
-
-    case PROP_COMMENT:
-      g_value_set_string (value, xfce_menu_directory_get_comment (directory));
-      break;
-
-    case PROP_ICON:
-      g_value_set_string (value, xfce_menu_directory_get_icon (directory));
-      break;
-
-    case PROP_NO_DISPLAY:
-      g_value_set_boolean (value, xfce_menu_directory_get_no_display (directory));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-xfce_menu_directory_set_property (GObject      *object,
-                                  guint         prop_id,
-                                  const GValue *value,
-                                  GParamSpec   *pspec)
-{
-  XfceMenuDirectory *directory = XFCE_MENU_DIRECTORY (object);
-
-  switch (prop_id)
-    {
-    case PROP_FILENAME:
-      xfce_menu_directory_set_filename (directory, g_value_get_string (value));
-      break;
-
-    case PROP_NAME:
-      xfce_menu_directory_set_name (directory, g_value_get_string (value));
-      break;
-
-    case PROP_COMMENT:
-      xfce_menu_directory_set_comment (directory, g_value_get_string (value));
-      break;
-
-    case PROP_ICON:
-      xfce_menu_directory_set_icon (directory, g_value_get_string (value));
-      break;
-
-    case PROP_NO_DISPLAY:
-      xfce_menu_directory_set_no_display (directory, g_value_get_boolean (value));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-const gchar*
-xfce_menu_directory_get_filename (XfceMenuDirectory *directory)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), NULL);
-  return directory->priv->filename;
-}
-
-
-
-void
-xfce_menu_directory_set_filename (XfceMenuDirectory *directory, const gchar *filename)
-{
-  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
-  g_return_if_fail (filename != NULL);
-
-  /* Check if there is an old filename */
-  if (G_UNLIKELY (directory->priv->filename != NULL))
-    {
-      if (G_UNLIKELY (filename != NULL && g_utf8_collate (directory->priv->filename, filename) == 0))
-        return;
-
-      /* Free old filename */
-      g_free (directory->priv->filename);
-    }
-
-  /* Set the new filename */
-  directory->priv->filename = g_strdup (filename);
-
-  /* Free private data before reloading the directory */
-  xfce_menu_directory_free_private (directory);
-
-  /* Reload the menu */
-  xfce_menu_directory_load (directory);
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (directory), "filename");
-}
-
-
-
-const gchar*
-xfce_menu_directory_get_name (XfceMenuDirectory *directory)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), NULL);
-  return directory->priv->name;
-}
-
-
-
-void
-xfce_menu_directory_set_name (XfceMenuDirectory *directory, const gchar *name)
-{
-  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
-  g_return_if_fail (name != NULL);
-
-  /* Free old name */
-  if (G_UNLIKELY (directory->priv->name != NULL))
-    g_free (directory->priv->name);
-
-  /* Set the new filename */
-  directory->priv->name = g_strdup (name);
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (directory), "name");
-}
-
-
-
-const gchar*
-xfce_menu_directory_get_comment (XfceMenuDirectory *directory)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), NULL);
-  return directory->priv->comment;
-}
-
-
-
-void
-xfce_menu_directory_set_comment (XfceMenuDirectory *directory, const gchar *comment)
-{
-  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
-
-  /* Free old name */
-  if (G_UNLIKELY (directory->priv->comment != NULL))
-    g_free (directory->priv->comment);
-
-  /* Set the new filename */
-  directory->priv->comment = g_strdup (comment);
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (directory), "comment");
-}
-
-
-const gchar*
-xfce_menu_directory_get_icon (XfceMenuDirectory *directory)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), NULL);
-  return directory->priv->icon;
-}
-
-
-
-void
-xfce_menu_directory_set_icon (XfceMenuDirectory *directory, const gchar *icon)
-{
-  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
-  g_return_if_fail (icon != NULL);
-
-  /* Free old name */
-  if (G_UNLIKELY (directory->priv->icon != NULL))
-    g_free (directory->priv->icon);
-
-  /* Set the new filename */
-  directory->priv->icon = g_strdup (icon);
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (directory), "icon");
-}
-
-
-
-gboolean
-xfce_menu_directory_get_no_display (XfceMenuDirectory *directory)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), FALSE);
-  return directory->priv->no_display;
-}
-
-
-
-void        
-xfce_menu_directory_set_no_display (XfceMenuDirectory *directory,
-                                    gboolean           no_display)
-{
-  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
-  
-  /* Abort if old and new value are equal */
-  if (directory->priv->no_display == no_display)
-    return;
-
-  /* Assign new value */
-  directory->priv->no_display = no_display;
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (directory), "no-display");
-}
-
-
-
-static void
-xfce_menu_directory_free_private (XfceMenuDirectory *directory)
-{
-  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
-
-  /* Free name */
-  g_free (directory->priv->name);
-
-  /* Free comment */
-  g_free (directory->priv->comment);
-
-  /* Free icon */
-  g_free (directory->priv->icon);
-
-  /* Free environment lists */
-  g_strfreev (directory->priv->only_show_in);
-  g_strfreev (directory->priv->not_show_in);
-}
-
-
-
-static void
-xfce_menu_directory_load (XfceMenuDirectory *directory)
-{
-  XfceRc       *entry;
-  const gchar  *name;
-  const gchar  *comment;
-  const gchar  *icon;
-
-  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
-  g_return_if_fail (directory->priv->filename != NULL);
-
-  entry = xfce_rc_simple_open (directory->priv->filename, TRUE);
-
-  if (G_UNLIKELY (entry == NULL))
-    return;
-
-  /* Treat the file as a desktop entry */
-  xfce_rc_set_group (entry, "Desktop Entry");
-
-  /* Read directory information */
-  name = xfce_rc_read_entry (entry, "Name", NULL);
-  comment = xfce_rc_read_entry (entry, "Comment", NULL);
-  icon = xfce_rc_read_entry (entry, "Icon", NULL);
-
-  /* Pass data to the directory */
-  xfce_menu_directory_set_name (directory, name);
-  xfce_menu_directory_set_comment (directory, comment);
-  xfce_menu_directory_set_icon (directory, icon);
-  xfce_menu_directory_set_no_display (directory, xfce_rc_read_bool_entry (entry, "NoDisplay", FALSE));
-
-  /* Set rest of the private data directly */
-  directory->priv->only_show_in = xfce_rc_read_list_entry (entry, "OnlyShowIn", ";");
-  directory->priv->not_show_in = xfce_rc_read_list_entry (entry, "NotShowIn", ";");
-  directory->priv->hidden = xfce_rc_read_bool_entry (entry, "Hidden", FALSE);
-
-  xfce_rc_close (entry);
-}
-
-
-
-gboolean
-xfce_menu_directory_get_hidden (XfceMenuDirectory *directory)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), FALSE);
-  return directory->priv->hidden;
-}
-
-
-
-gboolean
-xfce_menu_directory_show_in_environment (XfceMenuDirectory *directory)
-{
-  const gchar *env;
-  gboolean     show = TRUE;
-  gboolean     included;
-  int          i;
-
-  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), FALSE);
-  
-  /* Determine current environment */
-  env = xfce_menu_get_environment ();
-
-  /* If no environment has been set, the menu is displayed no matter what
-   * OnlyShowIn or NotShowIn contain */
-  if (G_UNLIKELY (env == NULL))
-    return TRUE;
-
-  /* Check if we have a OnlyShowIn OR a NotShowIn list (only one of them will be
-   * there, according to the desktop entry specification) */
-  if (G_UNLIKELY (directory->priv->only_show_in != NULL))
-    {
-      /* Determine whether our environment is included in this list */
-      included = FALSE;
-      for (i = 0; i < g_strv_length (directory->priv->only_show_in); ++i) 
-        {
-          if (G_UNLIKELY (g_utf8_collate (directory->priv->only_show_in[i], env) == 0))
-            included = TRUE;
-        }
-
-      /* If it's not, don't show the menu */
-      if (G_LIKELY (!included))
-        show = FALSE;
-    }
-  else if (G_UNLIKELY (directory->priv->not_show_in != NULL))
-    {
-      /* Determine whether our environment is included in this list */
-      included = FALSE;
-      for (i = 0; i < g_strv_length (directory->priv->not_show_in); ++i)
-        {
-          if (G_UNLIKELY (g_utf8_collate (directory->priv->not_show_in[i], env) == 0))
-            included = TRUE;
-        }
-
-      /* If it is, hide the menu */
-      if (G_UNLIKELY (included))
-        show = FALSE;
-    }
-
-  return show;
-}
diff --git a/libxfce4menu/xfce-menu-directory.h b/libxfce4menu/xfce-menu-directory.h
deleted file mode 100644
index cf7b5e2..0000000
--- a/libxfce4menu/xfce-menu-directory.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_DIRECTORY_H__
-#define __XFCE_MENU_DIRECTORY_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuDirectoryPrivate XfceMenuDirectoryPrivate;
-typedef struct _XfceMenuDirectoryClass   XfceMenuDirectoryClass;
-typedef struct _XfceMenuDirectory        XfceMenuDirectory;
-
-#define XFCE_TYPE_MENU_DIRECTORY            (xfce_menu_directory_get_type ())
-#define XFCE_MENU_DIRECTORY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_DIRECTORY, XfceMenuDirectory))
-#define XFCE_MENU_DIRECTORY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_DIRECTORY, XfceMenuDirectoryClass))
-#define XFCE_IS_MENU_DIRECTORY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_DIRECTORY))
-#define XFCE_IS_MENU_DIRECTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU_DIRECTORY))
-#define XFCE_MENU_DIRECTORY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_DIRECTORY, XfceMenuDirectoryClass))
-
-GType                    xfce_menu_directory_get_type            (void) G_GNUC_CONST;
-
-const gchar             *xfce_menu_directory_get_filename        (XfceMenuDirectory *directory);
-void                     xfce_menu_directory_set_filename        (XfceMenuDirectory *directory,
-                                                                  const gchar       *name);
-const gchar             *xfce_menu_directory_get_name            (XfceMenuDirectory *directory);
-void                     xfce_menu_directory_set_name            (XfceMenuDirectory *directory,
-                                                                  const gchar       *name);
-const gchar             *xfce_menu_directory_get_comment         (XfceMenuDirectory *directory);
-void                     xfce_menu_directory_set_comment         (XfceMenuDirectory *directory,
-                                                                  const gchar       *comment);
-const gchar             *xfce_menu_directory_get_icon            (XfceMenuDirectory *directory);
-void                     xfce_menu_directory_set_icon            (XfceMenuDirectory *directory,
-                                                                  const gchar       *icon);
-gboolean                 xfce_menu_directory_get_no_display      (XfceMenuDirectory *directory);
-void                     xfce_menu_directory_set_no_display      (XfceMenuDirectory *directory,
-                                                                  gboolean           no_display);
-gboolean                 xfce_menu_directory_get_hidden          (XfceMenuDirectory *directory);
-gboolean                 xfce_menu_directory_show_in_environment (XfceMenuDirectory *directory);
-
-#if defined(LIBXFCE4MENU_COMPILATION)
-void _xfce_menu_directory_init     (void) G_GNUC_INTERNAL;
-void _xfce_menu_directory_shutdown (void) G_GNUC_INTERNAL;
-#endif
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_DIRECTORY_H__ */
diff --git a/libxfce4menu/xfce-menu-element.c b/libxfce4menu/xfce-menu-element.c
deleted file mode 100644
index 2a77dfa..0000000
--- a/libxfce4menu/xfce-menu-element.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* $Id$ */
-/*-
- * vi:set sw=2 sts=2 et ai cindent:
- *
- * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-element.h>
-
-
-
-static void xfce_menu_element_class_init (XfceMenuElementIface *klass);
-
-
-
-GType
-xfce_menu_element_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuElementIface),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_element_class_init,
-        NULL,
-        NULL,
-        0,
-        0,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_INTERFACE, "XfceMenuElement", &info, 0);
-      g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_element_class_init (XfceMenuElementIface *klass)
-{
-}
-
-
-
-const gchar*
-xfce_menu_element_get_name (XfceMenuElement *element)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_ELEMENT (element), NULL);
-  return (*XFCE_MENU_ELEMENT_GET_IFACE (element)->get_name) (element);
-}
-
-
-
-const gchar*
-xfce_menu_element_get_icon_name (XfceMenuElement *element)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_ELEMENT (element), NULL);
-  return (*XFCE_MENU_ELEMENT_GET_IFACE (element)->get_icon_name) (element);
-}
diff --git a/libxfce4menu/xfce-menu-element.h b/libxfce4menu/xfce-menu-element.h
deleted file mode 100644
index a1fc746..0000000
--- a/libxfce4menu/xfce-menu-element.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* $Id$ */
-/*-
- * vi:set sw=2 sts=2 et ai cindent:
- *
- * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined (LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined (LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_ELEMENT_H__
-#define __XFCE_MENU_ELEMENT_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuElement      XfceMenuElement;
-typedef struct _XfceMenuElementIface XfceMenuElementIface;
-
-#define XFCE_TYPE_MENU_ELEMENT           (xfce_menu_element_get_type ())
-#define XFCE_MENU_ELEMENT(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_ELEMENT, XfceMenuElement))
-#define XFCE_IS_MENU_ELEMENT(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_ELEMENT))
-#define XFCE_MENU_ELEMENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), XFCE_TYPE_MENU_ELEMENT, XfceMenuElementIface))
-
-struct _XfceMenuElementIface
-{
-  GTypeInterface __parent__;
-
-  /* Virtual methods */
-  const gchar *(*get_name)      (XfceMenuElement *element);
-  const gchar *(*get_icon_name) (XfceMenuElement *element);
-};
-
-GType        xfce_menu_element_get_type      (void) G_GNUC_CONST;
-
-const gchar *xfce_menu_element_get_name      (XfceMenuElement *element);
-const gchar *xfce_menu_element_get_icon_name (XfceMenuElement *element);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_ELEMENT_H__ */
diff --git a/libxfce4menu/xfce-menu-environment.h b/libxfce4menu/xfce-menu-environment.h
deleted file mode 100644
index 2075488..0000000
--- a/libxfce4menu/xfce-menu-environment.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_ENVIRONMENT_H__
-#define __XFCE_MENU_ENVIRONMENT_H__
-
-#include <glib.h>
-
-void                  xfce_menu_set_environment (const gchar *env);
-G_CONST_RETURN gchar *xfce_menu_get_environment (void);
-
-#endif /* !__XFCE_MENU_ENVIRONMENT_H__ */
diff --git a/libxfce4menu/xfce-menu-item-cache.c b/libxfce4menu/xfce-menu-item-cache.c
deleted file mode 100644
index 7dac257..0000000
--- a/libxfce4menu/xfce-menu-item-cache.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/* $Id$ */
-/*-
- * vi:set et ai sts=2 sw=2 cindent:
- *
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include <libxfce4util/libxfce4util.h>
-
-#include <tdb/tdb.h>
-
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-item-cache.h>
-
-
-
-/* TODO Use a proper value here */
-#define XFCE_MENU_ITEM_CACHE_MAX_PATH_LENGTH 4096
-
-
-
-#define XFCE_MENU_ITEM_CACHE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_MENU_ITEM_CACHE, XfceMenuItemCachePrivate))
-
-
-
-static void          xfce_menu_item_cache_class_init (XfceMenuItemCacheClass *klass);
-static void          xfce_menu_item_cache_init       (XfceMenuItemCache      *cache);
-static void          xfce_menu_item_cache_finalize   (GObject                *object);
-#if 1 /* ITEM CACHE DEACTIVATED FOR NOW */
-static XfceMenuItem *xfce_menu_item_cache_fetch_item (XfceMenuItemCache      *cache,
-                                                      const gchar            *filename);
-static void          xfce_menu_item_cache_store_item (XfceMenuItemCache      *cache,
-                                                      const gchar            *filename,
-                                                      XfceMenuItem           *item);
-#endif
-
-
-
-
-static XfceMenuItemCache *_xfce_menu_item_cache = NULL;
-
-
-
-void
-_xfce_menu_item_cache_init (void)
-{
-  if (G_LIKELY (_xfce_menu_item_cache == NULL))
-    {
-      _xfce_menu_item_cache = g_object_new (XFCE_TYPE_MENU_ITEM_CACHE, NULL);
-      g_object_add_weak_pointer (G_OBJECT (_xfce_menu_item_cache), (gpointer) &_xfce_menu_item_cache);
-    }
-}
-
-
-
-void
-_xfce_menu_item_cache_shutdown (void)
-{
-  if (G_LIKELY (_xfce_menu_item_cache != NULL))
-    g_object_unref (G_OBJECT (_xfce_menu_item_cache));
-      
-}
-
-
-
-struct _XfceMenuItemCacheClass
-{
-  GObjectClass __parent__;
-};
-
-struct _XfceMenuItemCachePrivate
-{
-  /* Hash table for mapping absolute filenames to XfceMenuItem's */
-  GHashTable  *items;
-
-  /* TDB context */
-  TDB_CONTEXT *context;
-  TDB_DATA     data;
-
-  /* Mutex lock */
-  GMutex      *lock;
-};
-
-struct _XfceMenuItemCache
-{
-  GObject __parent__;
-
-  /* Private data */
-  XfceMenuItemCachePrivate *priv;
-};
-
-
-
-static GObjectClass *xfce_menu_item_cache_parent_class = NULL;
-
-
-
-GType
-xfce_menu_item_cache_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info = 
-      {
-        sizeof (XfceMenuItemCacheClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_item_cache_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuItemCache),
-        0,
-        (GInstanceInitFunc) xfce_menu_item_cache_init,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenuItemCache", &info, 0);
-    }
-  
-  return type;
-}
-
-
-
-static void
-xfce_menu_item_cache_class_init (XfceMenuItemCacheClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  g_type_class_add_private (klass, sizeof (XfceMenuItemCachePrivate));
-
-  /* Determine the parent type class */
-  xfce_menu_item_cache_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_item_cache_finalize;
-}
-
-
-
-static void
-xfce_menu_item_cache_init (XfceMenuItemCache *cache)
-{
-  gchar *path;
-
-  cache->priv = XFCE_MENU_ITEM_CACHE_GET_PRIVATE (cache);
-
-  /* Initialize the mutex lock */
-  cache->priv->lock = g_mutex_new ();
-
-  /* Create empty hash table */
-  cache->priv->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) xfce_menu_item_unref);
-
-  /* Determine path to the item cache file */
-  path = xfce_resource_save_location (XFCE_RESOURCE_CACHE, "libxfce4menu/items.tdb", TRUE);
-
-  /* Print a warning of the cache file could not be created */
-  if (G_UNLIKELY (path == NULL))
-    {
-      path = xfce_resource_save_location (XFCE_RESOURCE_CACHE, "libxfce4menu/items.tdb", FALSE);
-      g_warning (_("Failed to create the libxfce4menu item cache in %s."), path);
-      g_free (path);
-      return;
-    }
-
-  /* Try to open the item cache file */
-  cache->priv->context = tdb_open (path, 0, TDB_DEFAULT, O_CREAT | O_RDWR, 0600);
-
-  /* Print warning if it could not be opened */
-  if (G_UNLIKELY (cache->priv->context == NULL))
-    g_warning (_("Failed to load the libxfce4menu item cache from %s: %s."), path, g_strerror (errno));
-
-  /* Release the path */
-  g_free (path);
-}
-
-
-
-XfceMenuItemCache*
-xfce_menu_item_cache_get_default (void)
-{
-  return g_object_ref (G_OBJECT (_xfce_menu_item_cache));
-}
-
-
-
-static void
-xfce_menu_item_cache_finalize (GObject *object)
-{
-  XfceMenuItemCache *cache = XFCE_MENU_ITEM_CACHE (object);
-
-  /* Free hash table */
-#if GLIB_CHECK_VERSION(2,10,0)
-  g_hash_table_unref (cache->priv->items);
-#else
-  g_hash_table_destroy (cache->priv->items);
-#endif
-
-  /* Close TDB database */
-  if (G_LIKELY (cache->priv->context != NULL))
-    tdb_close (cache->priv->context);
-
-  /* Release mutex lock */
-  g_mutex_free (cache->priv->lock);
-
-  (*G_OBJECT_CLASS (xfce_menu_item_cache_parent_class)->finalize) (object);
-}
-
-
-
-XfceMenuItem*
-xfce_menu_item_cache_lookup (XfceMenuItemCache *cache,
-                             const gchar       *filename,
-                             const gchar       *desktop_id)
-{
-  XfceMenuItem *item = NULL;
-
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM_CACHE (cache), NULL);
-  g_return_val_if_fail (g_path_is_absolute (filename), NULL);
-  g_return_val_if_fail (desktop_id != NULL, NULL);
-
-  /* Acquire lock on the item cache as it's likely that we need to load 
-   * items from the hard drive and store it in the hash table of the 
-   * item cache */
-  g_mutex_lock (cache->priv->lock);
-
-#if 1
-  /* Search filename in the hash table */
-  item = g_hash_table_lookup (cache->priv->items, filename);
-
-  /* Return the item if we we found one */
-  if (item != NULL)
-    {
-      /* Update desktop id, if necessary */
-      xfce_menu_item_set_desktop_id (item, desktop_id);
-
-      /* TODO Check OnlyShowIn / NotShowIn values */
-
-      /* Store updated item in cache */
-      xfce_menu_item_cache_store_item (cache, filename, item);
-
-      /* Release item cache lock */
-      g_mutex_unlock (cache->priv->lock);
-
-      return item;
-    }
-
-  /* Otherwise, search in the item cache */
-  if (G_LIKELY (cache->priv->context != NULL))
-    {
-      /* Fetch item from cache */
-      item = xfce_menu_item_cache_fetch_item (cache, filename);
-
-      if (G_LIKELY (item != NULL))
-        {
-          /* Update desktop id */
-          xfce_menu_item_set_desktop_id (item, desktop_id);
-
-          /* TODO Check OnlyShowIn / NotShowIn */
-
-          /* Store updated item in the cache */
-          xfce_menu_item_cache_store_item (cache, filename, item);
-
-          /* Add item to the hash table */
-          g_hash_table_replace (cache->priv->items, g_strdup (filename), item);
-
-          /* Grab a reference on the item, but don't increase the allocation
-           * counter */
-#if 1
-          g_object_ref (G_OBJECT (item));
-#endif
-
-          /* Release item cache lock */
-          g_mutex_unlock (cache->priv->lock);
-
-          return item;
-        }
-    }
-#endif
-
-  /* Last chance is to load it directly from the file */
-  item = xfce_menu_item_new (filename);
-
-  if (G_LIKELY (item != NULL))
-    {
-      /* Update desktop id */
-      xfce_menu_item_set_desktop_id (item, desktop_id);
-
-#if 1 /* ITEM CACHE DEACTIVATED FOR NOW */
-      /* Store updated item in cache */
-      xfce_menu_item_cache_store_item (cache, filename, item);
-
-      /* The file has been loaded, add the item to the hash table */
-      g_hash_table_replace (cache->priv->items, g_strdup (filename), item);
-#endif
-
-      /* Grab a reference on it but don't increase the allocation counter */
-#if 1
-      g_object_ref (G_OBJECT (item)); 
-#endif
-    }
-
-  /* Release item cache lock */
-  g_mutex_unlock (cache->priv->lock);
-
-  return item;
-}
-
-
-
-void 
-xfce_menu_item_cache_foreach (XfceMenuItemCache *cache,
-                              GHFunc             func,
-                              gpointer           user_data)
-{
-  g_return_if_fail (XFCE_IS_MENU_ITEM_CACHE (cache));
-
-  /* Acquire lock on the item cache */
-  g_mutex_lock (cache->priv->lock);
-
-  g_hash_table_foreach (cache->priv->items, func, user_data);
-
-  /* Release item cache lock */
-  g_mutex_unlock (cache->priv->lock);
-}
-
-
-
-#if 1 /* ITEM CACHE DEACTIVATED FOR NOW */
-static XfceMenuItem*
-xfce_menu_item_cache_fetch_item (XfceMenuItemCache *cache,
-                                 const gchar       *filename)
-{
-  TDB_DATA      key;
-  gssize        key_length;
-  gchar         key_path[XFCE_MENU_ITEM_CACHE_MAX_PATH_LENGTH];
-  TDB_DATA      data;
-  XfceMenuItem *item = NULL;
-  
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM_CACHE (cache), NULL);
-  g_return_val_if_fail (cache->priv->context != NULL, NULL);
-  g_return_val_if_fail (g_path_is_absolute (filename), NULL);
-
-  /* Generate key path */
-  key_length = g_snprintf (key_path, XFCE_MENU_ITEM_CACHE_MAX_PATH_LENGTH, filename, NULL);
-
-  /* Generate key */
-  key.dsize = key_length;
-  key.dptr = key_path;
-
-  /* Try to fetch the data */
-  data = tdb_fetch (cache->priv->context, key);
-
-  if (G_LIKELY (data.dptr != NULL))
-    {
-      /* TODO Read item information from the data buffer into a newly created 
-       * XfceMenuItem object. */
-    }
-
-  return item;
-}
-
-
-
-static void
-xfce_menu_item_cache_store_item (XfceMenuItemCache *cache,
-                                 const gchar       *filename,
-                                 XfceMenuItem      *item)
-{
-  TDB_DATA key;
-  gssize   key_length;
-  gchar    key_path[XFCE_MENU_ITEM_CACHE_MAX_PATH_LENGTH];
-
-  g_return_if_fail (XFCE_IS_MENU_ITEM_CACHE (cache));
-  g_return_if_fail (cache->priv->context != NULL);
-  g_return_if_fail (g_path_is_absolute (filename));
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
-
-  /* Generate key path */
-  key_length = g_snprintf (key_path, XFCE_MENU_ITEM_CACHE_MAX_PATH_LENGTH, filename, NULL);
-
-  /* Generate key */
-  key.dsize = key_length;
-  key.dptr = key_path;
-
-  /* TODO Allocate a suitable buffer for item information and copy this
-   * information into the data buffer. Afterwards, store it in the database: 
-   *   tdb_store (cache->priv->context, key, data, TDB_REPLACE);
-   */
-}
-#endif
-
-
-
-void
-xfce_menu_item_cache_invalidate (XfceMenuItemCache *cache)
-{
-  g_return_if_fail (XFCE_IS_MENU_ITEM_CACHE (cache));
-
-  /* Destroy the hash table */
-#if GLIB_CHECK_VERSION(2,10,0)
-  g_hash_table_unref (cache->priv->items);
-#else
-  g_hash_table_destroy (cache->priv->items);
-#endif
-  
-  /* Create a new, empty hash table */
-  cache->priv->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) xfce_menu_item_unref);
-}
diff --git a/libxfce4menu/xfce-menu-item-cache.h b/libxfce4menu/xfce-menu-item-cache.h
deleted file mode 100644
index d3547ed..0000000
--- a/libxfce4menu/xfce-menu-item-cache.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_ITEM_CACHE_H__
-#define __XFCE_MENU_ITEM_CACHE_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuItemCachePrivate XfceMenuItemCachePrivate;
-typedef struct _XfceMenuItemCacheClass   XfceMenuItemCacheClass;
-typedef struct _XfceMenuItemCache        XfceMenuItemCache;
-
-#define XFCE_TYPE_MENU_ITEM_CACHE            (xfce_menu_item_cache_get_type ())
-#define XFCE_MENU_ITEM_CACHE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_ITEM_CACHE, XfceMenuItemCache))
-#define XFCE_MENU_ITEM_CACHE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_ITEM_CACHE, XfceMenuItemCacheClass))
-#define XFCE_IS_MENU_ITEM_CACHE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_ITEM_CACHE))
-#define XFCE_IS_MENU_ITEM_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU_ITEM_CACHE))
-#define XFCE_MENU_ITEM_CACHE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_ITEM_CACHE, XfceMenuItemCacheClass))
-
-GType              xfce_menu_item_cache_get_type    (void) G_GNUC_CONST;
-
-XfceMenuItemCache *xfce_menu_item_cache_get_default (void);
-
-XfceMenuItem      *xfce_menu_item_cache_lookup      (XfceMenuItemCache *cache,
-                                                     const gchar       *filename,
-                                                     const gchar       *desktop_id);
-void               xfce_menu_item_cache_foreach     (XfceMenuItemCache *cache,
-                                                     GHFunc             func, 
-                                                     gpointer           user_data);
-void               xfce_menu_item_cache_invalidate  (XfceMenuItemCache *cache);
-
-#if defined(LIBXFCE4MENU_COMPILATION)
-void               _xfce_menu_item_cache_init       (void) G_GNUC_INTERNAL;
-void               _xfce_menu_item_cache_shutdown   (void) G_GNUC_INTERNAL;
-#endif
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_ITEM_CACHE_H__ */
diff --git a/libxfce4menu/xfce-menu-item-pool.c b/libxfce4menu/xfce-menu-item-pool.c
deleted file mode 100644
index 8821ff2..0000000
--- a/libxfce4menu/xfce-menu-item-pool.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-item-pool.h>
-#include <libxfce4menu/xfce-menu-rules.h>
-#include <libxfce4menu/xfce-menu-standard-rules.h>
-
-
-
-#define XFCE_MENU_ITEM_POOL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_MENU_ITEM_POOL, XfceMenuItemPoolPrivate))
-
-
-
-static void     xfce_menu_item_pool_class_init       (XfceMenuItemPoolClass *klass);
-static void     xfce_menu_item_pool_init             (XfceMenuItemPool      *pool);
-static void     xfce_menu_item_pool_finalize         (GObject               *object);
-static gboolean xfce_menu_item_pool_filter_exclude   (const gchar           *desktop_id,
-                                                      XfceMenuItem          *item,
-                                                      XfceMenuStandardRules *rules);
-
-
-
-struct _XfceMenuItemPoolClass
-{
-  GObjectClass __parent__;
-};
-
-struct _XfceMenuItemPoolPrivate
-{
-  /* Hash table for mapping desktop-file id's to XfceMenuItem's */
-  GHashTable *items;
-};
-
-struct _XfceMenuItemPool
-{
-  GObject __parent__;
-
-  /* < private > */
-  XfceMenuItemPoolPrivate *priv;
-};
-
-
-
-static GObjectClass *xfce_menu_item_pool_parent_class = NULL;
-
-
-
-GType
-xfce_menu_item_pool_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info = 
-      {
-        sizeof (XfceMenuItemPoolClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_item_pool_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuItemPool),
-        0,
-        (GInstanceInitFunc) xfce_menu_item_pool_init,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenuItemPool", &info, 0);
-    }
-  
-  return type;
-}
-
-
-
-static void
-xfce_menu_item_pool_class_init (XfceMenuItemPoolClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  g_type_class_add_private (klass, sizeof (XfceMenuItemPoolPrivate));
-
-  /* Determine the parent type class */
-  xfce_menu_item_pool_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_item_pool_finalize;
-}
-
-
-
-static void
-xfce_menu_item_pool_init (XfceMenuItemPool *pool)
-{
-  pool->priv = XFCE_MENU_ITEM_POOL_GET_PRIVATE (pool);
-  pool->priv->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) xfce_menu_item_unref);
-}
-
-
-
-static void
-xfce_menu_item_pool_finalize (GObject *object)
-{
-  XfceMenuItemPool *pool = XFCE_MENU_ITEM_POOL (object);
-
-#if GLIB_CHECK_VERSION(2,10,0)
-  g_hash_table_unref (pool->priv->items);
-#else
-  g_hash_table_destroy (pool->priv->items);
-#endif
-
-  (*G_OBJECT_CLASS (xfce_menu_item_pool_parent_class)->finalize) (object);
-}
-
-
-
-XfceMenuItemPool*
-xfce_menu_item_pool_new (void)
-{
-  return g_object_new (XFCE_TYPE_MENU_ITEM_POOL, NULL);
-}
-
-
-
-void
-xfce_menu_item_pool_insert (XfceMenuItemPool *pool,
-                            XfceMenuItem     *item)
-{
-  g_return_if_fail (XFCE_IS_MENU_ITEM_POOL (pool));
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
-
-  /* Insert into the hash table and remove old item (if any) */
-  g_hash_table_replace (pool->priv->items, g_strdup (xfce_menu_item_get_desktop_id (item)), item);
-
-  /* Grab a reference on the item */
-  xfce_menu_item_ref (item);
-}
-
-
-
-XfceMenuItem*
-xfce_menu_item_pool_lookup (XfceMenuItemPool *pool,
-                            const gchar      *desktop_id)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM_POOL (pool), NULL);
-  g_return_val_if_fail (desktop_id != NULL, NULL);
-
-  return g_hash_table_lookup (pool->priv->items, desktop_id);
-}
-
-
-
-void 
-xfce_menu_item_pool_foreach (XfceMenuItemPool *pool,
-                             GHFunc            func,
-                             gpointer          user_data)
-{
-  g_return_if_fail (XFCE_IS_MENU_ITEM_POOL (pool));
-
-  g_hash_table_foreach (pool->priv->items, func, user_data);
-}
-
-
-
-void
-xfce_menu_item_pool_apply_exclude_rule (XfceMenuItemPool      *pool,
-                                        XfceMenuStandardRules *rule)
-{
-  g_return_if_fail (XFCE_IS_MENU_ITEM_POOL (pool));
-  g_return_if_fail (XFCE_IS_MENU_STANDARD_RULES (rule));
-
-  /* Remove all items which match this exclude rule */
-  g_hash_table_foreach_remove (pool->priv->items, (GHRFunc) xfce_menu_item_pool_filter_exclude, rule);
-}
-
-
-
-static gboolean
-xfce_menu_item_pool_filter_exclude (const gchar           *desktop_id,
-                                    XfceMenuItem          *item,
-                                    XfceMenuStandardRules *rule)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_STANDARD_RULES (rule), FALSE);
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
-
-  return xfce_menu_rules_match (XFCE_MENU_RULES (rule), item);
-}
-
-
-
-gboolean
-xfce_menu_item_pool_get_empty (XfceMenuItemPool *pool)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM_POOL (pool), TRUE);
-  return (g_hash_table_size (pool->priv->items) == 0);
-}
diff --git a/libxfce4menu/xfce-menu-item-pool.h b/libxfce4menu/xfce-menu-item-pool.h
deleted file mode 100644
index 3bece04..0000000
--- a/libxfce4menu/xfce-menu-item-pool.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_ITEM_POOL_H__
-#define __XFCE_MENU_ITEM_POOL_H__
-
-#include <glib-object.h>
-#include <libxfce4menu/xfce-menu-standard-rules.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuItemPoolPrivate XfceMenuItemPoolPrivate;
-typedef struct _XfceMenuItemPoolClass   XfceMenuItemPoolClass;
-typedef struct _XfceMenuItemPool        XfceMenuItemPool;
-
-#define XFCE_TYPE_MENU_ITEM_POOL            (xfce_menu_item_pool_get_type ())
-#define XFCE_MENU_ITEM_POOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_ITEM_POOL, XfceMenuItemPool))
-#define XFCE_MENU_ITEM_POOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_ITEM_POOL, XfceMenuItemPoolClass))
-#define XFCE_IS_MENU_ITEM_POOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_ITEM_POOL))
-#define XFCE_IS_MENU_ITEM_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU_ITEM_POOL))
-#define XFCE_MENU_ITEM_POOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_ITEM_POOL, XfceMenuItemPoolClass))
-
-GType             xfce_menu_item_pool_get_type           (void) G_GNUC_CONST;
-
-XfceMenuItemPool *xfce_menu_item_pool_new                (void);
-
-void              xfce_menu_item_pool_insert             (XfceMenuItemPool      *pool,
-                                                          XfceMenuItem          *item);
-XfceMenuItem     *xfce_menu_item_pool_lookup             (XfceMenuItemPool      *pool,
-                                                          const gchar           *desktop_id);
-void              xfce_menu_item_pool_foreach            (XfceMenuItemPool      *pool,
-                                                          GHFunc                 func, 
-                                                          gpointer               user_data);
-void              xfce_menu_item_pool_apply_exclude_rule (XfceMenuItemPool      *pool,
-                                                          XfceMenuStandardRules *rule);
-gboolean          xfce_menu_item_pool_get_empty          (XfceMenuItemPool      *pool);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_ITEM_POOL_H__ */
diff --git a/libxfce4menu/xfce-menu-item.h b/libxfce4menu/xfce-menu-item.h
deleted file mode 100644
index 41f87fe..0000000
--- a/libxfce4menu/xfce-menu-item.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* $Id$ */
-/*-
- * vi:set et ai sts=2 sw=2 cindent:
- *
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_ITEM_H__
-#define __XFCE_MENU_ITEM_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuItemPrivate XfceMenuItemPrivate;
-typedef struct _XfceMenuItemClass   XfceMenuItemClass;
-typedef struct _XfceMenuItem        XfceMenuItem;
-
-#define XFCE_TYPE_MENU_ITEM            (xfce_menu_item_get_type())
-#define XFCE_MENU_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_ITEM, XfceMenuItem))
-#define XFCE_MENU_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_ITEM, XfceMenuItemClass))
-#define XFCE_IS_MENU_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_ITEM))
-#define XFCE_IS_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU_ITEM))
-#define XFCE_MENU_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_ITEM, XfceMenuItemClass))
-
-GType         xfce_menu_item_get_type                          (void) G_GNUC_CONST;
-
-XfceMenuItem *xfce_menu_item_new                               (const gchar  *filename);
-
-const gchar  *xfce_menu_item_get_desktop_id                    (XfceMenuItem *item);
-void          xfce_menu_item_set_desktop_id                    (XfceMenuItem *item,
-                                                                const gchar  *desktop_id);
-
-const gchar  *xfce_menu_item_get_filename                      (XfceMenuItem *item);
-void          xfce_menu_item_set_filename                      (XfceMenuItem *item,
-                                                                const gchar  *filename);
-const gchar  *xfce_menu_item_get_command                       (XfceMenuItem *item);
-void          xfce_menu_item_set_command                       (XfceMenuItem *item,
-                                                                const gchar  *command);
-const gchar  *xfce_menu_item_get_try_exec                      (XfceMenuItem *item);
-void          xfce_menu_item_set_try_exec                      (XfceMenuItem *item,
-                                                                const gchar  *try_exec);
-const gchar  *xfce_menu_item_get_name                          (XfceMenuItem *item);
-void          xfce_menu_item_set_name                          (XfceMenuItem *item,
-                                                                const gchar  *name);
-const gchar  *xfce_menu_item_get_generic_name                  (XfceMenuItem *item);
-void          xfce_menu_item_set_generic_name                  (XfceMenuItem *item,
-                                                                const gchar  *generic_name);
-const gchar  *xfce_menu_item_get_comment                       (XfceMenuItem *item);
-void          xfce_menu_item_set_comment                       (XfceMenuItem *item,
-                                                                const gchar  *comment);
-const gchar  *xfce_menu_item_get_icon_name                     (XfceMenuItem *item);
-void          xfce_menu_item_set_icon_name                     (XfceMenuItem *item,
-                                                                const gchar  *icon_name);
-const gchar  *xfce_menu_item_get_path                          (XfceMenuItem *item);
-void          xfce_menu_item_set_path                          (XfceMenuItem *item,
-                                                                const gchar  *path);
-gboolean      xfce_menu_item_requires_terminal                 (XfceMenuItem *item);
-void          xfce_menu_item_set_requires_terminal             (XfceMenuItem *item,
-                                                                gboolean      requires_terminal);
-gboolean      xfce_menu_item_get_no_display                    (XfceMenuItem *item);
-void          xfce_menu_item_set_no_display                    (XfceMenuItem *item,
-                                                                gboolean      no_display);
-gboolean      xfce_menu_item_supports_startup_notification     (XfceMenuItem *item);
-void          xfce_menu_item_set_supports_startup_notification (XfceMenuItem *item,
-                                                                gboolean      supports_startup_notification);
-GList        *xfce_menu_item_get_categories                    (XfceMenuItem *item);
-void          xfce_menu_item_set_categories                    (XfceMenuItem *item,
-                                                                GList        *categories);
-gboolean      xfce_menu_item_has_category                      (XfceMenuItem *item,
-                                                                const gchar  *category);
-gboolean      xfce_menu_item_show_in_environment               (XfceMenuItem *item);
-gboolean      xfce_menu_item_only_show_in_environment          (XfceMenuItem *item);
-void          xfce_menu_item_ref                               (XfceMenuItem *item);
-void          xfce_menu_item_unref                             (XfceMenuItem *item);
-gint          xfce_menu_item_get_allocated                     (XfceMenuItem *item);
-void          xfce_menu_item_increment_allocated               (XfceMenuItem *item);
-void          xfce_menu_item_decrement_allocated               (XfceMenuItem *item);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_ITEM_H__ */
diff --git a/libxfce4menu/xfce-menu-layout.c b/libxfce4menu/xfce-menu-layout.c
deleted file mode 100644
index e788cb2..0000000
--- a/libxfce4menu/xfce-menu-layout.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-layout.h>
-
-
-
-#define XFCE_MENU_LAYOUT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_MENU_LAYOUT, XfceMenuLayoutPrivate))
-
-
-
-/* Property identifiers */
-enum
-{
-  PROP_0,
-};
-
-
-
-struct _XfceMenuLayoutNode
-{
-  XfceMenuLayoutNodeType   type;
-  union
-  {
-    gchar                  *filename;
-    gchar                  *menuname;
-    XfceMenuLayoutMergeType merge_type;
-  } data;
-};
-
-
-
-static void xfce_menu_layout_class_init   (XfceMenuLayoutClass *klass);
-static void xfce_menu_layout_init         (XfceMenuLayout      *layout);
-static void xfce_menu_layout_finalize     (GObject             *object);
-static void xfce_menu_layout_get_property (GObject             *object,
-                                           guint                prop_id,
-                                           GValue              *value,
-                                           GParamSpec          *pspec);
-static void xfce_menu_layout_set_property (GObject             *object,
-                                           guint                prop_id,
-                                           const GValue        *value,
-                                           GParamSpec          *pspec);
-static void xfce_menu_layout_free_node    (XfceMenuLayoutNode  *node);
-
-
-
-struct _XfceMenuLayoutClass
-{
-  GObjectClass __parent__;
-};
-
-struct _XfceMenuLayoutPrivate
-{
-  GSList *nodes;
-};
-
-struct _XfceMenuLayout
-{
-  GObject __parent__;
-
-  /* < private > */
-  XfceMenuLayoutPrivate *priv;
-};
-
-
-
-static GObjectClass *xfce_menu_layout_parent_class = NULL;
-
-
-
-GType
-xfce_menu_layout_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuLayoutClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_layout_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuLayout),
-        0,
-        (GInstanceInitFunc) xfce_menu_layout_init,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenuLayout", &info, 0);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_layout_class_init (XfceMenuLayoutClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  g_type_class_add_private (klass, sizeof (XfceMenuLayoutPrivate));
-
-  /* Determine parent type class */
-  xfce_menu_layout_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_layout_finalize;
-  gobject_class->get_property = xfce_menu_layout_get_property;
-  gobject_class->set_property = xfce_menu_layout_set_property;
-}
-
-
-
-static void
-xfce_menu_layout_init (XfceMenuLayout *layout)
-{
-  layout->priv = XFCE_MENU_LAYOUT_GET_PRIVATE (layout);
-  layout->priv->nodes = NULL;
-}
-
-
-
-static void
-xfce_menu_layout_finalize (GObject *object)
-{
-  XfceMenuLayout *layout = XFCE_MENU_LAYOUT (object);
-
-  /* Free nodes */
-  g_slist_foreach (layout->priv->nodes, (GFunc) xfce_menu_layout_free_node, NULL);
-  g_slist_free (layout->priv->nodes);
-
-  (*G_OBJECT_CLASS (xfce_menu_layout_parent_class)->finalize) (object);
-}
-
-
-
-static void
-xfce_menu_layout_get_property (GObject    *object,
-                               guint       prop_id,
-                               GValue     *value,
-                               GParamSpec *pspec)
-{
-#if 0
-  XfceMenuLayout *layout = XFCE_MENU_LAYOUT (object);
-#endif
-
-  switch (prop_id)
-    {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-xfce_menu_layout_set_property (GObject      *object,
-                               guint         prop_id,
-                               const GValue *value,
-                               GParamSpec   *pspec)
-{
-#if 0
-  XfceMenuLayout *layout = XFCE_MENU_LAYOUT (object);
-#endif
-
-  switch (prop_id)
-    {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-XfceMenuLayout*
-xfce_menu_layout_new (void)
-{
-  return g_object_new (XFCE_TYPE_MENU_LAYOUT, NULL);
-}
-
-
-
-static void
-xfce_menu_layout_free_node (XfceMenuLayoutNode *node)
-{
-  if (node->type == XFCE_MENU_LAYOUT_NODE_FILENAME)
-    g_free (node->data.filename);
-  else if (node->type == XFCE_MENU_LAYOUT_NODE_MENUNAME)
-    g_free (node->data.menuname);
-
-  g_free (node);
-}
-
-
-
-void
-xfce_menu_layout_add_filename (XfceMenuLayout *layout,
-                               const gchar    *filename)
-{
-  g_return_if_fail (XFCE_IS_MENU_LAYOUT (layout));
-  g_return_if_fail (filename != NULL);
-
-  /* Build filename node */
-  XfceMenuLayoutNode *node = g_new0 (XfceMenuLayoutNode, 1);
-  node->type = XFCE_MENU_LAYOUT_NODE_FILENAME;
-  node->data.filename = g_strdup (filename);
-
-  /* Append node to the list */
-  layout->priv->nodes = g_slist_append (layout->priv->nodes, node);
-}
-
-
-
-void
-xfce_menu_layout_add_menuname (XfceMenuLayout *layout,
-                               const gchar    *menuname)
-{
-  g_return_if_fail (XFCE_IS_MENU_LAYOUT (layout));
-  g_return_if_fail (menuname != NULL);
-
-  /* Build menuname node */
-  XfceMenuLayoutNode *node = g_new0 (XfceMenuLayoutNode, 1);
-  node->type = XFCE_MENU_LAYOUT_NODE_MENUNAME;
-  node->data.menuname = g_strdup (menuname);
-
-  /* Append node to the list */
-  layout->priv->nodes = g_slist_append (layout->priv->nodes, node);
-}
-
-
-
-void
-xfce_menu_layout_add_separator (XfceMenuLayout *layout)
-{
-  g_return_if_fail (XFCE_IS_MENU_LAYOUT (layout));
-
-  /* Build separator node */
-  XfceMenuLayoutNode *node = g_new0 (XfceMenuLayoutNode, 1);
-  node->type = XFCE_MENU_LAYOUT_NODE_SEPARATOR;
-
-  /* Append node to the list */
-  layout->priv->nodes = g_slist_append (layout->priv->nodes, node);
-}
-
-
-
-void
-xfce_menu_layout_add_merge (XfceMenuLayout         *layout,
-                            XfceMenuLayoutMergeType type)
-{
-  g_return_if_fail (XFCE_IS_MENU_LAYOUT (layout));
-
-  /* Build merge node */
-  XfceMenuLayoutNode *node = g_new0 (XfceMenuLayoutNode, 1);
-  node->type = XFCE_MENU_LAYOUT_NODE_MERGE;
-  node->data.merge_type = type;
-
-  /* Append node to the list */
-  layout->priv->nodes = g_slist_append (layout->priv->nodes, node);
-}
-
-
-
-GSList*
-xfce_menu_layout_get_nodes (XfceMenuLayout *layout)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_LAYOUT (layout), NULL);
-  return layout->priv->nodes;
-}
-
-
-
-gboolean 
-xfce_menu_layout_get_filename_used (XfceMenuLayout *layout,
-                                    const gchar    *filename)
-{
-  XfceMenuLayoutNode *node;
-  GSList             *iter;
-  gboolean            found = FALSE;
-
-  g_return_val_if_fail (XFCE_IS_MENU_LAYOUT (layout), FALSE);
-  g_return_val_if_fail (filename != NULL, FALSE);
-
-  for (iter = layout->priv->nodes; iter != NULL; iter = g_slist_next (iter))
-    {
-      node = (XfceMenuLayoutNode *)iter->data;
-
-      if (G_UNLIKELY (node == NULL))
-        continue;
-
-      if (G_UNLIKELY (node->type == XFCE_MENU_LAYOUT_NODE_FILENAME && g_utf8_collate (node->data.filename, filename) == 0))
-        {
-          found = TRUE;
-          break;
-        }
-    }
-
-  return found;
-}
-
-
-
-gboolean 
-xfce_menu_layout_get_menuname_used (XfceMenuLayout *layout,
-                                    const gchar    *menuname)
-{
-  XfceMenuLayoutNode *node;
-  GSList             *iter;
-  gboolean            found = FALSE;
-
-  g_return_val_if_fail (XFCE_IS_MENU_LAYOUT (layout), FALSE);
-  g_return_val_if_fail (menuname != NULL, FALSE);
-
-  for (iter = layout->priv->nodes; iter != NULL; iter = g_slist_next (iter))
-    {
-      node = (XfceMenuLayoutNode *)iter->data;
-
-      if (G_UNLIKELY (node == NULL))
-        continue;
-
-      if (G_UNLIKELY (node->type == XFCE_MENU_LAYOUT_NODE_MENUNAME && g_utf8_collate (node->data.menuname, menuname) == 0))
-        {
-          found = TRUE;
-          break;
-        }
-    }
-
-  return found;
-}
-
-
-
-XfceMenuLayoutNodeType
-xfce_menu_layout_node_get_type (XfceMenuLayoutNode *node)
-{
-  g_return_val_if_fail (node != NULL, XFCE_MENU_LAYOUT_NODE_INVALID);
-  return node->type;
-}
-
-
-
-const gchar*
-xfce_menu_layout_node_get_filename (XfceMenuLayoutNode *node)
-{
-  g_return_val_if_fail (node != NULL && node->type == XFCE_MENU_LAYOUT_NODE_FILENAME, NULL);
-  return node->data.filename;
-}
-
-
-
-
-const gchar*
-xfce_menu_layout_node_get_menuname (XfceMenuLayoutNode *node)
-{
-  g_return_val_if_fail (node != NULL && node->type == XFCE_MENU_LAYOUT_NODE_MENUNAME, NULL);
-  return node->data.menuname;
-}
-
-
-
-
-XfceMenuLayoutMergeType
-xfce_menu_layout_node_get_merge_type (XfceMenuLayoutNode *node)
-{
-  g_return_val_if_fail (node != NULL && node->type == XFCE_MENU_LAYOUT_NODE_MERGE, XFCE_MENU_LAYOUT_MERGE_ALL);
-  return node->data.merge_type;
-}
diff --git a/libxfce4menu/xfce-menu-layout.h b/libxfce4menu/xfce-menu-layout.h
deleted file mode 100644
index 251c7dd..0000000
--- a/libxfce4menu/xfce-menu-layout.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_LAYOUT_H__
-#define __XFCE_MENU_LAYOUT_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef enum
-{
-  XFCE_MENU_LAYOUT_MERGE_MENUS,
-  XFCE_MENU_LAYOUT_MERGE_FILES,
-  XFCE_MENU_LAYOUT_MERGE_ALL,
-} XfceMenuLayoutMergeType;
-
-typedef enum
-{
-  XFCE_MENU_LAYOUT_NODE_INVALID,
-  XFCE_MENU_LAYOUT_NODE_FILENAME,
-  XFCE_MENU_LAYOUT_NODE_MENUNAME,
-  XFCE_MENU_LAYOUT_NODE_SEPARATOR,
-  XFCE_MENU_LAYOUT_NODE_MERGE,
-} XfceMenuLayoutNodeType;
-
-typedef struct _XfceMenuLayoutNode    XfceMenuLayoutNode;
-
-typedef struct _XfceMenuLayoutPrivate XfceMenuLayoutPrivate;
-typedef struct _XfceMenuLayoutClass   XfceMenuLayoutClass;
-typedef struct _XfceMenuLayout        XfceMenuLayout;
-
-#define XFCE_TYPE_MENU_LAYOUT            (xfce_menu_layout_get_type())
-#define XFCE_MENU_LAYOUT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_LAYOUT, XfceMenuLayout))
-#define XFCE_MENU_LAYOUT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_LAYOUT, XfceMenuLayoutClass))
-#define XFCE_IS_MENU_LAYOUT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_LAYOUT))
-#define XFCE_IS_MENU_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU_LAYOUT))
-#define XFCE_MENU_LAYOUT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_LAYOUT, XfceMenuLayoutClass))
-
-GType                   xfce_menu_layout_get_type            (void) G_GNUC_CONST;
-
-XfceMenuLayout         *xfce_menu_layout_new                 (void) G_GNUC_MALLOC;
-void                    xfce_menu_layout_add_filename        (XfceMenuLayout          *layout,
-                                                              const gchar             *filename);
-void                    xfce_menu_layout_add_menuname        (XfceMenuLayout          *layout,
-                                                              const gchar             *menuname);
-void                    xfce_menu_layout_add_separator       (XfceMenuLayout          *layout);
-void                    xfce_menu_layout_add_merge           (XfceMenuLayout          *layout,
-                                                              XfceMenuLayoutMergeType  type);
-GSList                 *xfce_menu_layout_get_nodes           (XfceMenuLayout          *layout);
-gboolean                xfce_menu_layout_get_filename_used   (XfceMenuLayout          *layout,
-                                                              const gchar             *filename);
-gboolean                xfce_menu_layout_get_menuname_used   (XfceMenuLayout          *layout,
-                                                              const gchar             *menuname);
-
-XfceMenuLayoutNodeType  xfce_menu_layout_node_get_type       (XfceMenuLayoutNode       *node);
-const gchar            *xfce_menu_layout_node_get_filename   (XfceMenuLayoutNode       *node);
-const gchar            *xfce_menu_layout_node_get_menuname   (XfceMenuLayoutNode       *node);
-XfceMenuLayoutMergeType xfce_menu_layout_node_get_merge_type (XfceMenuLayoutNode       *node);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_LAYOUT_H__ */
-
diff --git a/libxfce4menu/xfce-menu-monitor.c b/libxfce4menu/xfce-menu-monitor.c
deleted file mode 100644
index 698f9a4..0000000
--- a/libxfce4menu/xfce-menu-monitor.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/* $Id$ */
-/*-
- * vi:set sw=2 sts=2 et ai cindent:
- *
- * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-monitor.h>
-#include <libxfce4menu/xfce-menu.h>
-#include <libxfce4menu/xfce-menu-item.h>
-
-
-
-/* Initial vtable configuration */
-static XfceMenuMonitorVTable xfce_menu_monitor_vtable = {
-  NULL,
-  NULL,
-  NULL,
-};
-
-/* Monitor flags */
-static XfceMenuMonitorFlags xfce_menu_monitor_flags;
-
-/* User data as provided by the client */
-static gpointer xfce_menu_monitor_user_data = NULL;
-
-/* Hash table with (XfceMenuItem => gpointer) pairs */
-static GHashTable *xfce_menu_monitor_item_handles;
-
-/* Hash table with (Directory => gpointer) pairs */
-static GHashTable *xfce_menu_monitor_shared_handles;
-
-/* Structure for directory handles */
-typedef struct _SharedHandle SharedHandle;
-struct _SharedHandle  
-{
-  gpointer monitor_handle;
-  int      references;
-};
-
-
-
-void 
-_xfce_menu_monitor_init (void)
-{
-  /* Initialize hash tables */
-  xfce_menu_monitor_item_handles = g_hash_table_new (NULL, NULL);
-  xfce_menu_monitor_shared_handles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-  xfce_menu_monitor_flags = XFCE_MENU_MONITOR_DIRECTORIES|XFCE_MENU_MONITOR_MENU_FILES|XFCE_MENU_MONITOR_DIRECTORY_FILES|XFCE_MENU_MONITOR_DESKTOP_FILES;
-}
-
-
-
-void
-_xfce_menu_monitor_shutdown (void)
-{
-#if GLIB_CHECK_VERSION(2,10,0)
-  g_hash_table_unref (xfce_menu_monitor_item_handles);
-  g_hash_table_unref (xfce_menu_monitor_shared_handles);
-#else
-  g_hash_table_destroy (xfce_menu_monitor_item_handles);
-  g_hash_table_destroy (xfce_menu_monitor_shared_handles);
-#endif
-}
-
-
-
-/**
- * xfce_menu_monitor_set_vtable:
- * @vtable    : a #XfceMenuMonitorVTable
- * @user_data : custom pointer to be passed to the vtable functions.
- *
- * Sets the functions to be called when monitoring a file or directory
- * becomes necessary. See #XfceMenuMonitorVTable for more detailled
- * information. Be careful with redefining the #XfceMenuMonitorVTable 
- * (e.g. don't redefine it while there are any #XfceMenu's around).
- *
- * In order to change the user data, just pass the same 
- * #XfceMenuMonitorVTable as you did before. Pass NULL to clear the
- * vtable (e.g. if you want to disable monitoring support).
- */
-void
-xfce_menu_monitor_set_vtable (XfceMenuMonitorVTable *vtable,
-                              gpointer               user_data)
-{
-  if (G_UNLIKELY (vtable == NULL))
-    {
-      xfce_menu_monitor_vtable.monitor_file = NULL;
-      xfce_menu_monitor_vtable.monitor_directory = NULL;
-      xfce_menu_monitor_vtable.remove_monitor = NULL;
-    }
-  else
-    {
-      xfce_menu_monitor_vtable.monitor_file = vtable->monitor_file;
-      xfce_menu_monitor_vtable.monitor_directory = vtable->monitor_directory;
-      xfce_menu_monitor_vtable.remove_monitor = vtable->remove_monitor;
-    }
-
-  xfce_menu_monitor_user_data = user_data;
-}
-
-
-
-gpointer
-xfce_menu_monitor_add_item (XfceMenu     *menu,
-                            XfceMenuItem *item)
-{
-  gpointer monitor_handle;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), NULL);
-  
-  if (G_UNLIKELY (xfce_menu_monitor_vtable.monitor_file == NULL))
-    return NULL;
-
-  /* Request monitor handle from the library client */
-  monitor_handle = xfce_menu_monitor_vtable.monitor_file (menu, xfce_menu_item_get_filename (item), xfce_menu_monitor_user_data);
-
-  if (G_LIKELY (monitor_handle != NULL))
-    {
-      /* Store the item => handle pair in the hash table */
-      g_hash_table_insert (xfce_menu_monitor_item_handles, item, monitor_handle);
-    }
-
-  return monitor_handle;
-}
-
-
-
-void
-xfce_menu_monitor_remove_item (XfceMenu     *menu,
-                               XfceMenuItem *item)
-{
-  gpointer monitor_handle;
-
-  g_return_if_fail (XFCE_IS_MENU_ITEM (item));
-  
-  if (G_UNLIKELY (xfce_menu_monitor_vtable.remove_monitor == NULL))
-    return;
-
-  /* Lookup the monitor handle for this item */
-  monitor_handle = g_hash_table_lookup (xfce_menu_monitor_item_handles, item);
-
-  if (G_LIKELY (monitor_handle != NULL))
-    {
-      /* Remove monitor handle from the library client */
-      xfce_menu_monitor_vtable.remove_monitor (menu, monitor_handle);
-
-      /* ... and remove the item from the hash table */
-      g_hash_table_remove (xfce_menu_monitor_item_handles, item);
-    }
-}
-
-
-
-gpointer
-xfce_menu_monitor_add_directory (XfceMenu    *menu,
-                                 const gchar *directory)
-{
-  SharedHandle *shared_handle;
-  gpointer         monitor_handle;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  g_return_val_if_fail (directory != NULL, NULL);
-  
-  if (G_UNLIKELY (xfce_menu_monitor_vtable.monitor_directory == NULL))
-    return NULL;
-
-  /* Load directory handle from the hash table */
-  shared_handle = (SharedHandle *)g_hash_table_lookup (xfce_menu_monitor_shared_handles, directory);
-
-  /* Check if the directory is already monitored */
-  if (G_LIKELY (shared_handle != NULL))
-    {
-      /* Increment reference counter */
-      shared_handle->references++;
-
-      /* Return the monitor handle */
-      monitor_handle = shared_handle->monitor_handle;
-    }
-  else
-    {
-      /* Request monitor handle from the library client */
-      monitor_handle = xfce_menu_monitor_vtable.monitor_directory (menu, directory, xfce_menu_monitor_user_data);
-
-      if (G_LIKELY (monitor_handle != NULL))
-        {
-          /* Allocate new directory handle */
-          shared_handle = g_new0 (SharedHandle, 1);
-
-          /* Set values (reference counter starts with 1) */
-          shared_handle->references = 1;
-          shared_handle->monitor_handle = monitor_handle;
-
-          /* Store the item => handle pair in the hash table */
-          g_hash_table_insert (xfce_menu_monitor_shared_handles, g_strdup (directory), shared_handle);
-        }
-    }
-
-  return monitor_handle;
-}
-
-
-
-void
-xfce_menu_monitor_remove_directory (XfceMenu    *menu,
-                                    const gchar *directory)
-{
-  SharedHandle *shared_handle;
-
-  g_return_if_fail (directory != NULL);
-  
-  if (G_UNLIKELY (xfce_menu_monitor_vtable.remove_monitor == NULL))
-    return;
-
-  /* Lookup the directory handle for this directory */
-  shared_handle = g_hash_table_lookup (xfce_menu_monitor_shared_handles, directory);
-
-  if (G_LIKELY (shared_handle != NULL))
-    {
-      /* Decrement the reference counter */
-      shared_handle->references--;
-
-      /* Check if there are no references left */
-      if (G_UNLIKELY (shared_handle->references == 0)) 
-        {
-          /* Remove monitor handle from the library client */
-          xfce_menu_monitor_vtable.remove_monitor (menu, shared_handle->monitor_handle);
-
-          /* Remove directory handle from the hash table and destroy it */
-          g_hash_table_remove (xfce_menu_monitor_shared_handles, directory);
-        }
-    }
-}
-
-
-
-gpointer
-xfce_menu_monitor_add_file (XfceMenu    *menu,
-                            const gchar *filename)
-{
-  SharedHandle *shared_handle;
-  gpointer      monitor_handle;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  g_return_val_if_fail (filename != NULL, NULL);
-  
-  if (G_UNLIKELY (xfce_menu_monitor_vtable.monitor_file == NULL))
-    return NULL;
-
-  /* Load filename handle from the hash table */
-  shared_handle = (SharedHandle *)g_hash_table_lookup (xfce_menu_monitor_shared_handles, filename);
-
-  /* Check if the file is already monitored */
-  if (G_LIKELY (shared_handle != NULL))
-    {
-      /* Increment reference counter */
-      shared_handle->references++;
-
-      /* Return the monitor handle */
-      monitor_handle = shared_handle->monitor_handle;
-    }
-  else
-    {
-      /* Request monitor handle from the library client */
-      monitor_handle = xfce_menu_monitor_vtable.monitor_file (menu, filename, xfce_menu_monitor_user_data);
-
-      if (G_LIKELY (monitor_handle != NULL))
-        {
-          /* Allocate new filename handle */
-          shared_handle = g_new0 (SharedHandle, 1);
-
-          /* Set values (reference counter starts with 1) */
-          shared_handle->references = 1;
-          shared_handle->monitor_handle = monitor_handle;
-
-          /* Store the item => handle pair in the hash table */
-          g_hash_table_insert (xfce_menu_monitor_shared_handles, g_strdup (filename), shared_handle);
-        }
-    }
-
-  return monitor_handle;
-}
-
-
-
-void
-xfce_menu_monitor_remove_file (XfceMenu    *menu,
-                               const gchar *filename)
-{
-  SharedHandle *shared_handle;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (filename != NULL);
-  
-  if (G_UNLIKELY (xfce_menu_monitor_vtable.remove_monitor == NULL))
-    return;
-
-  /* Lookup the filename handle for this file */
-  shared_handle = g_hash_table_lookup (xfce_menu_monitor_shared_handles, filename);
-
-  if (G_LIKELY (shared_handle != NULL))
-    {
-      /* Decrement the reference counter */
-      shared_handle->references--;
-
-      /* Check if there are no references left */
-      if (G_UNLIKELY (shared_handle->references == 0)) 
-        {
-          /* Remove monitor handle from the library client */
-          xfce_menu_monitor_vtable.remove_monitor (menu, shared_handle->monitor_handle);
-
-          /* Remove filename handle from the hash table and destroy it */
-          g_hash_table_remove (xfce_menu_monitor_shared_handles, shared_handle);
-        }
-    }
-}
-
-
-
-void 
-xfce_menu_monitor_set_flags (XfceMenuMonitorFlags flags)
-{
-  xfce_menu_monitor_flags = flags;
-}
-
-
-
-XfceMenuMonitorFlags 
-xfce_menu_monitor_get_flags (void)
-{
-  return xfce_menu_monitor_flags;
-}
-
-
-
-gboolean
-xfce_menu_monitor_has_flags (XfceMenuMonitorFlags flags)
-{
-  return (xfce_menu_monitor_flags & flags) != 0;
-}
diff --git a/libxfce4menu/xfce-menu-monitor.h b/libxfce4menu/xfce-menu-monitor.h
deleted file mode 100644
index 80c3ee3..0000000
--- a/libxfce4menu/xfce-menu-monitor.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/* $Id$ */
-/*-
- * vi:set sw=2 sts=2 et ai cindent:
- *
- * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined (LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined (LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_MONITOR_H__
-#define __XFCE_MENU_MONITOR_H__
-
-#include <glib.h>
-#include <libxfce4menu/libxfce4menu.h>
-
-G_BEGIN_DECLS;
-
-typedef enum
-{
-  XFCE_MENU_MONITOR_DIRECTORIES     = 1 << 0,
-  XFCE_MENU_MONITOR_MENU_FILES      = 1 << 1,
-  XFCE_MENU_MONITOR_DIRECTORY_FILES = 1 << 2,
-  XFCE_MENU_MONITOR_DESKTOP_FILES   = 1 << 3
-} XfceMenuMonitorFlags;
-
-typedef struct _XfceMenuMonitorVTable XfceMenuMonitorVTable;
-
-void                 xfce_menu_monitor_set_vtable       (XfceMenuMonitorVTable *vtable, 
-                                                         gpointer               user_data);
-gpointer             xfce_menu_monitor_add_item         (XfceMenu              *menu,
-                                                         XfceMenuItem          *item);
-void                 xfce_menu_monitor_remove_item      (XfceMenu              *menu,
-                                                         XfceMenuItem          *item);
-gpointer             xfce_menu_monitor_add_directory    (XfceMenu              *menu,
-                                                         const gchar           *directory);
-void                 xfce_menu_monitor_remove_directory (XfceMenu              *menu,
-                                                         const gchar           *directory);
-gpointer             xfce_menu_monitor_add_file         (XfceMenu              *menu,
-                                                         const gchar           *filename);
-void                 xfce_menu_monitor_remove_file      (XfceMenu              *menu,
-                                                         const gchar           *filename);
-void                 xfce_menu_monitor_set_flags        (XfceMenuMonitorFlags   flags);
-XfceMenuMonitorFlags xfce_menu_monitor_get_flags        (void);
-gboolean             xfce_menu_monitor_has_flags        (XfceMenuMonitorFlags   flags);
-
-/**
- * XfceMenuMonitorVTable:
- *
- * This structure can be used by clients of the libxfce4menu API to 
- * register functions which will be called whenever monitoring a
- * certain file or directory becomes necessary. This way libxfce4menu
- * only has to manage the monitor handles and leaves the monitoring
- * implementations to the client.
- *
- * This mechanism was invented because the two main API clients, 
- * Thunar and xfdesktop are already linked to ThunarVFS which has
- * monitoring capabilities.
- */
-struct _XfceMenuMonitorVTable
-{
-  gpointer (*monitor_file)      (XfceMenu    *menu,
-                                 const gchar *filename,
-                                 gpointer     user_data);
-
-  gpointer (*monitor_directory) (XfceMenu    *menu,
-                                 const gchar *filename,
-                                 gpointer     user_data);
-
-  void     (*remove_monitor)    (XfceMenu    *menu,
-                                 gpointer     monitor_handle);
-};
-
-#if defined(LIBXFCE4MENU_COMPILATION)
-void _xfce_menu_monitor_init     (void) G_GNUC_INTERNAL;
-void _xfce_menu_monitor_shutdown (void) G_GNUC_INTERNAL;
-#endif
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_MONITOR_H__ */
diff --git a/libxfce4menu/xfce-menu-move.c b/libxfce4menu/xfce-menu-move.c
deleted file mode 100644
index 53b0f54..0000000
--- a/libxfce4menu/xfce-menu-move.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4util/libxfce4util.h>
-
-#include <libxfce4menu/xfce-menu-move.h>
-
-
-
-/* Property identifiers */
-enum
-{
-  PROP_0,
-  PROP_OLD,
-  PROP_NEW,
-};
-
-
-
-static void xfce_menu_move_class_init   (XfceMenuMoveClass *klass);
-static void xfce_menu_move_init         (XfceMenuMove      *move);
-static void xfce_menu_move_finalize     (GObject           *object);
-static void xfce_menu_move_get_property (GObject           *object,
-                                         guint              prop_id,
-                                         GValue            *value,
-                                         GParamSpec        *pspec);
-static void xfce_menu_move_set_property (GObject           *object,
-                                         guint              prop_id,
-                                         const GValue      *value,
-                                         GParamSpec        *pspec);
-
-
-
-struct _XfceMenuMoveClass
-{
-  GObjectClass __parent__;
-};
-
-struct _XfceMenuMove
-{
-  GObject  __parent__;
-
-  /* Name of the submenu to move/rename */
-  gchar   *old;
-
-  /* Name of the target path/name */
-  gchar   *new;
-};
-
-
-
-static GObjectClass *xfce_menu_move_parent_class = NULL;
-
-
-
-GType
-xfce_menu_move_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info = 
-      {
-        sizeof (XfceMenuMoveClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_move_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuMove),
-        0,
-        (GInstanceInitFunc) xfce_menu_move_init,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenuMove", &info, 0);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_move_class_init (XfceMenuMoveClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  /* Determine parent type class */
-  xfce_menu_move_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_move_finalize;
-  gobject_class->get_property = xfce_menu_move_get_property;
-  gobject_class->set_property = xfce_menu_move_set_property;
-
-  /**
-   * XfceMenuMove:old:
-   *
-   * Name of the submenu to be moved/renamed.
-   */
-  g_object_class_install_property (gobject_class,
-                                   PROP_OLD,
-                                   g_param_spec_string ("old",
-                                                        "Old name",
-                                                        "Name of the submenu to be moved",
-                                                        NULL,
-                                                        G_PARAM_READWRITE));
-
-  /**
-   * XfceMenuMove:new:
-   *
-   * Target path/name of the move/rename operation.
-   */
-  g_object_class_install_property (gobject_class,
-                                   PROP_NEW,
-                                   g_param_spec_string ("new",
-                                                        "New name",
-                                                        "Target path/name of the move/rename operation",
-                                                        NULL,
-                                                        G_PARAM_READWRITE));
-}
-
-
-
-static void
-xfce_menu_move_init (XfceMenuMove *move)
-{
-  move->old = NULL;
-  move->new = NULL;
-}
-
-
-
-static void
-xfce_menu_move_finalize (GObject *object)
-{
-  XfceMenuMove *move = XFCE_MENU_MOVE (object);
-
-  /* Free instance variables */
-  xfce_menu_move_set_old (move, NULL);
-  xfce_menu_move_set_new (move, NULL);
-
-  (*G_OBJECT_CLASS (xfce_menu_move_parent_class)->finalize) (object);
-}
-
-
-
-static void
-xfce_menu_move_get_property (GObject    *object,
-                             guint       prop_id,
-                             GValue     *value,
-                             GParamSpec *pspec)
-{
-  XfceMenuMove *move = XFCE_MENU_MOVE (object);
-
-  switch (prop_id)
-    {
-    case PROP_OLD:
-      g_value_set_string (value, xfce_menu_move_get_old (move));
-      break;
-
-    case PROP_NEW:
-      g_value_set_string (value, xfce_menu_move_get_new (move));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-xfce_menu_move_set_property (GObject      *object,
-                             guint         prop_id,
-                             const GValue *value,
-                             GParamSpec   *pspec)
-{
-  XfceMenuMove *move = XFCE_MENU_MOVE (object);
-
-  switch (prop_id)
-    {
-    case PROP_OLD:
-      xfce_menu_move_set_old (move, g_value_get_string (value));
-      break;
-
-    case PROP_NEW:
-      xfce_menu_move_set_new (move, g_value_get_string (value));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-XfceMenuMove*
-xfce_menu_move_new (void)
-{
-  return g_object_new (XFCE_TYPE_MENU_MOVE, NULL);
-}
-
-
-
-const gchar*
-xfce_menu_move_get_old (XfceMenuMove *move)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_MOVE (move), NULL);
-  return move->old;
-}
-
-
-
-void
-xfce_menu_move_set_old (XfceMenuMove *move, 
-                        const gchar  *old)
-{
-  g_return_if_fail (XFCE_IS_MENU_MOVE (move));
-
-  /* Check if old value is set */
-  if (G_UNLIKELY (move->old != NULL))
-    {
-      /* Abort if old and new value is the same */
-      if (G_UNLIKELY (old != NULL && g_utf8_collate (move->old, old) == 0))
-        return;
-
-      /* Otherwise, free the old value */
-      g_free (move->old);
-    }
-
-  /* Assign the new value */
-  move->old = g_strdup (old);
-}
-
-
-
-const gchar*
-xfce_menu_move_get_new (XfceMenuMove *move)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_MOVE (move), NULL);
-  return move->new;
-}
-
-
-
-void
-xfce_menu_move_set_new (XfceMenuMove *move, 
-                        const gchar  *new)
-{
-  g_return_if_fail (XFCE_IS_MENU_MOVE (move));
-
-  /* Check if old value is set */
-  if (G_UNLIKELY (move->new != NULL))
-    {
-      /* Abort if old and new value is the same */
-      if (G_UNLIKELY (new != NULL && g_utf8_collate (move->new, new) == 0))
-        return;
-
-      /* Otherwise, free the old value */
-      g_free (move->new);
-    }
-
-  /* Assign the new value */
-  move->new = g_strdup (new);
-}
diff --git a/libxfce4menu/xfce-menu-move.h b/libxfce4menu/xfce-menu-move.h
deleted file mode 100644
index 98ffe22..0000000
--- a/libxfce4menu/xfce-menu-move.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_MOVE_H__
-#define __XFCE_MENU_MOVE_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuMoveClass XfceMenuMoveClass;
-typedef struct _XfceMenuMove      XfceMenuMove;
-
-#define XFCE_TYPE_MENU_MOVE            (xfce_menu_move_get_type())
-#define XFCE_MENU_MOVE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_MOVE, XfceMenuMove))
-#define XFCE_MENU_MOVE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_MOVE, XfceMenuMoveClass))
-#define XFCE_IS_MENU_MOVE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_MOVE))
-#define XFCE_IS_MENU_MOVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU_MOVE))
-#define XFCE_MENU_MOVE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_MOVE, XfceMenuMoveClass))
-
-GType         xfce_menu_move_get_type    (void) G_GNUC_CONST;
-
-XfceMenuMove *xfce_menu_move_new         (void);
-
-const gchar  *xfce_menu_move_get_old     (XfceMenuMove *move);
-void          xfce_menu_move_set_old     (XfceMenuMove *move,
-                                          const gchar  *old);
-
-const gchar  *xfce_menu_move_get_new     (XfceMenuMove *move);
-void          xfce_menu_move_set_new     (XfceMenuMove *move,
-                                          const gchar  *new);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_MOVE_H__ */
diff --git a/libxfce4menu/xfce-menu-not-rules.c b/libxfce4menu/xfce-menu-not-rules.c
deleted file mode 100644
index 41bd9dc..0000000
--- a/libxfce4menu/xfce-menu-not-rules.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-rules.h>
-#include <libxfce4menu/xfce-menu-standard-rules.h>
-#include <libxfce4menu/xfce-menu-not-rules.h>
-
-
-
-static void     xfce_menu_not_rules_class_init     (XfceMenuNotRulesClass  *klass);
-static void     xfce_menu_not_rules_init           (XfceMenuNotRules       *rules);
-static void     xfce_menu_not_rules_finalize       (GObject               *object);
-static gboolean xfce_menu_not_rules_match          (XfceMenuStandardRules *rules,
-                                                    XfceMenuItem          *item);
-
-
-
-struct _XfceMenuNotRulesClass
-{
-  XfceMenuStandardRulesClass __parent__;
-};
-
-struct _XfceMenuNotRules
-{
-  XfceMenuStandardRules __parent__;
-};
-
-
-
-static GObjectClass *xfce_menu_not_rules_parent_class = NULL;
-
-
-
-GType
-xfce_menu_not_rules_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuNotRulesClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_not_rules_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuNotRules),
-        0,
-        (GInstanceInitFunc) xfce_menu_not_rules_init,
-        NULL,
-      };
-
-      type = g_type_register_static (XFCE_TYPE_MENU_STANDARD_RULES, "XfceMenuNotRules", &info, 0);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_not_rules_class_init (XfceMenuNotRulesClass *klass)
-{
-  GObjectClass *gobject_class;
-  XfceMenuStandardRulesClass *std_rules_class;
-
-  /* Determine the parent type class */
-  xfce_menu_not_rules_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_not_rules_finalize;
-
-  std_rules_class = XFCE_MENU_STANDARD_RULES_CLASS (klass);
-  std_rules_class->match_item = xfce_menu_not_rules_match;
-}
-
-
-
-static void
-xfce_menu_not_rules_init (XfceMenuNotRules *rules)
-{
-}
-
-
-
-static void
-xfce_menu_not_rules_finalize (GObject *object)
-{
-  (*G_OBJECT_CLASS (xfce_menu_not_rules_parent_class)->finalize) (object); 
-}
-
-
-
-XfceMenuNotRules*
-xfce_menu_not_rules_new (void)
-{
-  return g_object_new (XFCE_TYPE_MENU_NOT_RULES, NULL);
-}
-
-
-
-static gboolean
-xfce_menu_not_rules_match (XfceMenuStandardRules *rules,
-                           XfceMenuItem          *item)
-{
-  GList *iter;
-
-  g_return_val_if_fail (XFCE_IS_MENU_STANDARD_RULES (rules), FALSE);
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
-
-  if (rules->all)
-    return FALSE;
-
-  /* Compare desktop id's */
-  for (iter = rules->filenames; iter != NULL; iter = g_list_next (iter))
-    {
-      if (g_utf8_collate (xfce_menu_item_get_desktop_id (item), iter->data) == 0)
-        return FALSE;
-    }
-
-  for (iter = rules->categories; iter != NULL; iter = g_list_next (iter))
-    {
-      if (g_list_find_custom (xfce_menu_item_get_categories (item), iter->data, (GCompareFunc) g_utf8_collate))
-        return FALSE;
-    }
-
-  /* Match item against nested rules */
-  for (iter = g_list_first (rules->rules); iter != NULL; iter = g_list_next (iter))
-    {
-      if (xfce_menu_rules_match (XFCE_MENU_RULES (iter->data), item))
-        return FALSE;
-    }
-
-  return TRUE;
-}
diff --git a/libxfce4menu/xfce-menu-not-rules.h b/libxfce4menu/xfce-menu-not-rules.h
deleted file mode 100644
index a7cd651..0000000
--- a/libxfce4menu/xfce-menu-not-rules.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_NOT_RULES_H__
-#define __XFCE_MENU_NOT_RULES_H__
-
-#include <glib-object.h>
-
-typedef struct _XfceMenuNotRules        XfceMenuNotRules;
-typedef struct _XfceMenuNotRulesClass   XfceMenuNotRulesClass;
-
-#define XFCE_TYPE_MENU_NOT_RULES             (xfce_menu_not_rules_get_type ())
-#define XFCE_MENU_NOT_RULES(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_NOT_RULES, XfceMenuNotRules))
-#define XFCE_MENU_NOT_RULES_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_NOT_RULES, XfceMenuNotRulesClass))
-#define XFCE_IS_MENU_NOT_RULES(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_NOT_RULES))
-#define XFCE_IS_MENU_NOT_RULES_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((obj), XFCE_TYPE_MENU_NOT_RULES))
-#define XFCE_MENU_NOT_RULES_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_NOT_RULES, XfceMenuNotRulesClass))
-
-GType             xfce_menu_not_rules_get_type (void) G_GNUC_CONST;
-
-XfceMenuNotRules *xfce_menu_not_rules_new      (void);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_NOT_RULES_H__ */
diff --git a/libxfce4menu/xfce-menu-or-rules.c b/libxfce4menu/xfce-menu-or-rules.c
deleted file mode 100644
index b33c529..0000000
--- a/libxfce4menu/xfce-menu-or-rules.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-rules.h>
-#include <libxfce4menu/xfce-menu-standard-rules.h>
-#include <libxfce4menu/xfce-menu-or-rules.h>
-
-
-
-static void     xfce_menu_or_rules_class_init     (XfceMenuOrRulesClass  *klass);
-static void     xfce_menu_or_rules_init           (XfceMenuOrRules       *rules);
-static void     xfce_menu_or_rules_finalize       (GObject               *object);
-static gboolean xfce_menu_or_rules_match          (XfceMenuStandardRules *rules,
-                                                   XfceMenuItem          *item);
-
-
-
-struct _XfceMenuOrRulesClass
-{
-  XfceMenuStandardRulesClass __parent__;
-};
-
-struct _XfceMenuOrRules
-{
-  XfceMenuStandardRules __parent__;
-};
-
-
-
-static GObjectClass *xfce_menu_or_rules_parent_class = NULL;
-
-
-
-GType
-xfce_menu_or_rules_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuOrRulesClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_or_rules_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuOrRules),
-        0,
-        (GInstanceInitFunc) xfce_menu_or_rules_init,
-        NULL,
-      };
-
-      type = g_type_register_static (XFCE_TYPE_MENU_STANDARD_RULES, "XfceMenuOrRules", &info, 0);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_or_rules_class_init (XfceMenuOrRulesClass *klass)
-{
-  GObjectClass *gobject_class;
-  XfceMenuStandardRulesClass *rules_class;
-
-  /* Determine the parent type class */
-  xfce_menu_or_rules_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_or_rules_finalize;
-
-  rules_class = XFCE_MENU_STANDARD_RULES_CLASS (klass);
-  rules_class->match_item = xfce_menu_or_rules_match;
-}
-
-
-
-static void
-xfce_menu_or_rules_init (XfceMenuOrRules *rules)
-{
-}
-
-
-
-static void
-xfce_menu_or_rules_finalize (GObject *object)
-{
-  (*G_OBJECT_CLASS (xfce_menu_or_rules_parent_class)->finalize) (object); 
-}
-
-
-
-XfceMenuOrRules*
-xfce_menu_or_rules_new (void)
-{
-  return g_object_new (XFCE_TYPE_MENU_OR_RULES, NULL);
-}
-
-
-
-static gboolean
-xfce_menu_or_rules_match (XfceMenuStandardRules *rules,
-                          XfceMenuItem          *item)
-{
-  GList           *iter;
-
-  g_return_val_if_fail (XFCE_IS_MENU_STANDARD_RULES (rules), FALSE);
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
-
-  if (rules->all)
-    return TRUE;
-
-  /* Compare desktop id's */
-  for (iter = rules->filenames; iter != NULL; iter = g_list_next (iter))
-    {
-      if (g_utf8_collate (xfce_menu_item_get_desktop_id (item), iter->data) == 0)
-        return TRUE;
-    }
-
-  /* Determine categories the item belongs to */
-  for (iter = rules->categories; iter != NULL; iter = g_list_next (iter))
-    {
-      if (g_list_find_custom (xfce_menu_item_get_categories (item), iter->data, (GCompareFunc) g_utf8_collate))
-        return TRUE;
-    }
-
-  /* Match item against nested rules */
-  for (iter = g_list_first (rules->rules); iter != NULL; iter = g_list_next (iter))
-    {
-      if (xfce_menu_rules_match (XFCE_MENU_RULES (iter->data), item))
-        return TRUE;
-    }
-
-  return FALSE;
-}
diff --git a/libxfce4menu/xfce-menu-or-rules.h b/libxfce4menu/xfce-menu-or-rules.h
deleted file mode 100644
index 1b01632..0000000
--- a/libxfce4menu/xfce-menu-or-rules.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_OR_RULES_H__
-#define __XFCE_MENU_OR_RULES_H__
-
-#include <glib-object.h>
-
-typedef struct _XfceMenuOrRules        XfceMenuOrRules;
-typedef struct _XfceMenuOrRulesClass   XfceMenuOrRulesClass;
-
-#define XFCE_TYPE_MENU_OR_RULES             (xfce_menu_or_rules_get_type ())
-#define XFCE_MENU_OR_RULES(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_OR_RULES, XfceMenuOrRules))
-#define XFCE_MENU_OR_RULES_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_OR_RULES, XfceMenuOrRulesClass))
-#define XFCE_IS_MENU_OR_RULES(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_OR_RULES))
-#define XFCE_IS_MENU_OR_RULES_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((obj), XFCE_TYPE_MENU_OR_RULES))
-#define XFCE_MENU_OR_RULES_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_OR_RULES, XfceMenuOrRulesClass))
-
-GType            xfce_menu_or_rules_get_type (void) G_GNUC_CONST;
-
-XfceMenuOrRules *xfce_menu_or_rules_new      (void);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_OR_RULES_H__ */
diff --git a/libxfce4menu/xfce-menu-rules.c b/libxfce4menu/xfce-menu-rules.c
deleted file mode 100644
index 6d003e8..0000000
--- a/libxfce4menu/xfce-menu-rules.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-rules.h>
-
-
-
-static void xfce_menu_rules_class_init (gpointer klass);
-
-
-
-GType
-xfce_menu_rules_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuRulesIface),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_rules_class_init,
-        NULL,
-        NULL,
-        0,
-        0,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_INTERFACE, "XfceMenuRules", &info, 0);
-      g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
-    }
-  
-  return type;
-}
-
-
-
-static void
-xfce_menu_rules_class_init (gpointer klass)
-{
-}
-
-
-
-gboolean
-xfce_menu_rules_match (XfceMenuRules *rules,
-                       XfceMenuItem  *item)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_RULES (rules), FALSE);
-  return (*XFCE_MENU_RULES_GET_IFACE (rules)->match) (rules, item);
-}
-
-
-
-void
-xfce_menu_rules_add_rules (XfceMenuRules *rules,
-                           XfceMenuRules *additional_rules)
-{
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-  g_return_if_fail (XFCE_IS_MENU_RULES (additional_rules));
-  (*XFCE_MENU_RULES_GET_IFACE (rules)->add_rules) (rules, additional_rules);
-}
-
-
-
-void xfce_menu_rules_add_all (XfceMenuRules *rules)
-{
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-  (*XFCE_MENU_RULES_GET_IFACE (rules)->add_all) (rules);
-}
-
-
-
-void
-xfce_menu_rules_add_filename (XfceMenuRules *rules,
-                              const gchar   *filename)
-{
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-  (*XFCE_MENU_RULES_GET_IFACE (rules)->add_filename) (rules, filename);
-}
-
-
-void
-xfce_menu_rules_add_category (XfceMenuRules *rules,
-                              const gchar   *category)
-{
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-  (*XFCE_MENU_RULES_GET_IFACE (rules)->add_category) (rules, category);
-}
diff --git a/libxfce4menu/xfce-menu-rules.h b/libxfce4menu/xfce-menu-rules.h
deleted file mode 100644
index 0bd1df1..0000000
--- a/libxfce4menu/xfce-menu-rules.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* $Id$ */
-/*-
- * vi:set sw=2 sts=2 et ai cindent:
- *
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_RULES_H__
-#define __XFCE_MENU_RULES_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuRules      XfceMenuRules;
-typedef struct _XfceMenuRulesIface XfceMenuRulesIface;
-
-#define XFCE_TYPE_MENU_RULES           (xfce_menu_rules_get_type ())
-#define XFCE_MENU_RULES(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_RULES, XfceMenuRules))
-#define XFCE_IS_MENU_RULES(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_RULES))
-#define XFCE_MENU_RULES_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), XFCE_TYPE_MENU_RULES, XfceMenuRulesIface))
-
-struct _XfceMenuRulesIface
-{
-  GTypeInterface __parent__;
-
-  /* Virtual methods */
-  gboolean  (*match)             (XfceMenuRules *rules, 
-                                  XfceMenuItem  *item);
-  void      (*add_rules)         (XfceMenuRules *rules, 
-                                  XfceMenuRules *additional_rules);
-  void      (*add_all)           (XfceMenuRules *rules);
-  void      (*add_filename)      (XfceMenuRules *rules, 
-                                  const gchar   *filename);
-  void      (*add_category)      (XfceMenuRules *rules, 
-                                  const gchar   *category);
-
-};
-
-GType    xfce_menu_rules_get_type    (void) G_GNUC_CONST;
-
-gboolean xfce_menu_rules_match        (XfceMenuRules *rules,
-                                       XfceMenuItem  *item);
-void     xfce_menu_rules_add_all      (XfceMenuRules *rules);
-void     xfce_menu_rules_add_rules    (XfceMenuRules *rules,
-                                       XfceMenuRules *additional_rules);
-void     xfce_menu_rules_add_filename (XfceMenuRules *rules,
-                                       const gchar   *filename);
-void     xfce_menu_rules_add_category (XfceMenuRules *rules,
-                                       const gchar   *category);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_RULES_H__ */
diff --git a/libxfce4menu/xfce-menu-separator.c b/libxfce4menu/xfce-menu-separator.c
deleted file mode 100644
index 8cdc3d8..0000000
--- a/libxfce4menu/xfce-menu-separator.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* $Id$ */
-/* vim:set et ai sw=2 sts=2: */
-/*-
- * Copyright (c) 2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4menu/xfce-menu-element.h>
-#include <libxfce4menu/xfce-menu-separator.h>
-
-
-
-static void         xfce_menu_separator_class_init            (XfceMenuSeparatorClass *klass);
-static void         xfce_menu_separator_element_init          (XfceMenuElementIface   *iface);
-static void         xfce_menu_separator_init                  (XfceMenuSeparator      *separator);
-static void         xfce_menu_separator_finalize              (GObject                *object);
-static const gchar *xfce_menu_separator_get_element_name      (XfceMenuElement        *element);
-static const gchar *xfce_menu_separator_get_element_icon_name (XfceMenuElement        *element);
-
-
-
-static XfceMenuSeparator *_xfce_menu_separator = NULL;
-
-
-
-void
-_xfce_menu_separator_init (void)
-{
-  if (G_LIKELY (_xfce_menu_separator == NULL))
-    {
-      _xfce_menu_separator = g_object_new (XFCE_TYPE_MENU_SEPARATOR, NULL);
-      g_object_add_weak_pointer (G_OBJECT (_xfce_menu_separator), (gpointer) &_xfce_menu_separator);
-    }
-}
-
-
-
-void
-_xfce_menu_separator_shutdown (void)
-{
-  if (G_LIKELY (_xfce_menu_separator != NULL))
-    g_object_unref (G_OBJECT (_xfce_menu_separator));
-}
-
-
-
-struct _XfceMenuSeparatorClass
-{
-  GObjectClass __parent__;
-};
-
-struct _XfceMenuSeparator
-{
-  GObject __parent__;
-};
-
-
-
-static GObjectClass *xfce_menu_separator_parent_class = NULL;
-
-
-
-GType
-xfce_menu_separator_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuSeparatorClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_separator_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuSeparator),
-        0,
-        (GInstanceInitFunc) xfce_menu_separator_init,
-        NULL,
-      };
-
-      static const GInterfaceInfo element_info =
-      {
-        (GInterfaceInitFunc) xfce_menu_separator_element_init,
-        NULL,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenuSeparator", &info, 0);
-      g_type_add_interface_static (type, XFCE_TYPE_MENU_ELEMENT, &element_info);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_separator_class_init (XfceMenuSeparatorClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  /* Determine parent type class */
-  xfce_menu_separator_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_separator_finalize;
-}
-
-
-
-static void
-xfce_menu_separator_element_init (XfceMenuElementIface *iface)
-{
-  iface->get_name = xfce_menu_separator_get_element_name;
-  iface->get_icon_name = xfce_menu_separator_get_element_icon_name;
-}
-
-
-
-static void
-xfce_menu_separator_init (XfceMenuSeparator *separator)
-{
-}
-
-
-
-static void
-xfce_menu_separator_finalize (GObject *object)
-{
-  (*G_OBJECT_CLASS (xfce_menu_separator_parent_class)->finalize) (object);
-}
-
-
-
-XfceMenuSeparator*
-xfce_menu_separator_get_default (void)
-{
-  return _xfce_menu_separator;
-}
-
-
-
-static const gchar*
-xfce_menu_separator_get_element_name (XfceMenuElement *element)
-{
-  return NULL;
-}
-
-
-
-static const gchar*
-xfce_menu_separator_get_element_icon_name (XfceMenuElement *element)
-{
-  return NULL;
-}
diff --git a/libxfce4menu/xfce-menu-separator.h b/libxfce4menu/xfce-menu-separator.h
deleted file mode 100644
index 4eb07e2..0000000
--- a/libxfce4menu/xfce-menu-separator.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id$ */
-/* vi:set et ai sw=2 sts=2: */
-/*-
- * Copyright (c) 2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_SEPARATOR_H__
-#define __XFCE_MENU_SEPARATOR_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuSeparatorClass XfceMenuSeparatorClass;
-typedef struct _XfceMenuSeparator      XfceMenuSeparator;
-
-#define XFCE_TYPE_MENU_SEPARATOR            (xfce_menu_separator_get_type())
-#define XFCE_MENU_SEPARATOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_SEPARATOR, XfceMenuSeparator))
-#define XFCE_MENU_SEPARATOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_SEPARATOR, XfceMenuSeparatorClass))
-#define XFCE_IS_MENU_SEPARATOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_SEPARATOR))
-#define XFCE_IS_MENU_SEPARATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU_SEPARATOR))
-#define XFCE_MENU_SEPARATOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_SEPARATOR, XfceMenuSeparatorClass))
-
-
-GType              xfce_menu_separator_get_type    (void) G_GNUC_CONST;
-
-XfceMenuSeparator *xfce_menu_separator_get_default (void);
-
-#if defined(LIBXFCE4MENU_COMPILATION)
-void               _xfce_menu_separator_init       (void) G_GNUC_INTERNAL;
-void               _xfce_menu_separator_shutdown   (void) G_GNUC_INTERNAL;
-#endif
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_SEPARATOR_H__ */
diff --git a/libxfce4menu/xfce-menu-standard-rules.c b/libxfce4menu/xfce-menu-standard-rules.c
deleted file mode 100644
index 5a48b17..0000000
--- a/libxfce4menu/xfce-menu-standard-rules.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <libxfce4util/libxfce4util.h>
-
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-rules.h>
-#include <libxfce4menu/xfce-menu-standard-rules.h>
-
-
-
-/* Property identifiers */
-enum
-{
-  PROP_0,
-  PROP_INCLUDE,
-};
-
-
-
-static void     xfce_menu_standard_rules_class_init     (XfceMenuStandardRulesClass *klass);
-static void     xfce_menu_standard_rules_rules_init     (XfceMenuRulesIface         *iface);
-static void     xfce_menu_standard_rules_init           (XfceMenuStandardRules      *rules);
-static void     xfce_menu_standard_rules_finalize       (GObject                    *object);
-static void     xfce_menu_standard_rules_get_property   (GObject                    *object,
-                                                         guint                       prop_id,
-                                                         GValue                     *value,
-                                                         GParamSpec                 *pspec);
-static void     xfce_menu_standard_rules_set_property   (GObject                    *object,
-                                                         guint                       prop_id,
-                                                         const GValue               *value,
-                                                         GParamSpec                 *pspec);
-static gboolean xfce_menu_standard_rules_match          (XfceMenuRules              *rules,
-                                                         XfceMenuItem               *item);
-static gboolean xfce_menu_standard_rules_match_item     (XfceMenuStandardRules      *rules,
-                                                         XfceMenuItem               *item);
-static void     xfce_menu_standard_rules_add_rules      (XfceMenuRules              *rules,
-                                                         XfceMenuRules              *additional_rules);
-static void     xfce_menu_standard_rules_add_all        (XfceMenuRules              *rules);
-static void     xfce_menu_standard_rules_add_filename   (XfceMenuRules              *rules,
-                                                         const gchar                *filename);
-static void     xfce_menu_standard_rules_add_category   (XfceMenuRules              *rules,
-                                                         const gchar                *category);
-
-
-static GObjectClass *xfce_menu_standard_rules_parent_class = NULL;
-
-
-
-GType
-xfce_menu_standard_rules_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuStandardRulesClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_standard_rules_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenuStandardRules),
-        0,
-        (GInstanceInitFunc) xfce_menu_standard_rules_init,
-        NULL,
-      };
-
-      static const GInterfaceInfo rules_info = 
-      {
-        (GInterfaceInitFunc) xfce_menu_standard_rules_rules_init,
-        NULL,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenuStandardRules", &info, G_TYPE_FLAG_ABSTRACT);
-      g_type_add_interface_static (type, XFCE_TYPE_MENU_RULES, &rules_info);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_standard_rules_class_init (XfceMenuStandardRulesClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  xfce_menu_standard_rules_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_standard_rules_finalize;
-  gobject_class->get_property = xfce_menu_standard_rules_get_property;
-  gobject_class->set_property = xfce_menu_standard_rules_set_property;
-
-  klass->match_item = xfce_menu_standard_rules_match_item;
-
-  /**
-   * XfceMenuStandardRules:include:
-   *
-   * Whether this rule set shall be treated as an include or exclude element.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_INCLUDE,
-                                   g_param_spec_boolean ("include",
-                                                         "Include",
-                                                         "Treat element as include or exclude element",
-                                                         TRUE,
-                                                         G_PARAM_READWRITE));
-
-  /* Overwrite XfceMenuRules's properties */
-#if 0
-  g_object_class_override_property (gobject_class, PROP_INCLUDE, "include");
-#endif
-}
-
-
-
-static void
-xfce_menu_standard_rules_rules_init (XfceMenuRulesIface *iface)
-{
-  iface->add_rules = xfce_menu_standard_rules_add_rules;
-  iface->add_all = xfce_menu_standard_rules_add_all;
-  iface->add_filename = xfce_menu_standard_rules_add_filename;
-  iface->add_category = xfce_menu_standard_rules_add_category;
-  iface->match = xfce_menu_standard_rules_match;
-}
-  
-
-
-static void
-xfce_menu_standard_rules_init (XfceMenuStandardRules *rules)
-{
-  rules->all = FALSE;
-  rules->rules = NULL;
-  rules->filenames = NULL;
-  rules->categories = NULL; 
-  rules->include = TRUE;
-}
-
-
-
-static void
-xfce_menu_standard_rules_finalize (GObject *object)
-{
-  XfceMenuStandardRules *rules = XFCE_MENU_STANDARD_RULES (object);
-
-  g_list_foreach (rules->rules, (GFunc) g_object_unref, NULL);
-  g_list_free (rules->rules);
-
-  g_list_foreach (rules->filenames, (GFunc) g_free, NULL);
-  g_list_free (rules->filenames);
-
-  g_list_foreach (rules->categories, (GFunc) g_free, NULL);
-  g_list_free (rules->categories);
-
-  (*G_OBJECT_CLASS (xfce_menu_standard_rules_parent_class)->finalize) (object); 
-}
-
-
-
-static void
-xfce_menu_standard_rules_get_property (GObject    *object,
-                                       guint       prop_id,
-                                       GValue     *value,
-                                       GParamSpec *pspec)
-{
-  XfceMenuStandardRules *rules = XFCE_MENU_STANDARD_RULES (object);
-
-  switch (prop_id)
-    {
-    case PROP_INCLUDE:
-      g_value_set_boolean (value, xfce_menu_standard_rules_get_include (rules));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-xfce_menu_standard_rules_set_property (GObject      *object,
-                                       guint         prop_id,
-                                       const GValue *value,
-                                       GParamSpec   *pspec)
-{
-  XfceMenuStandardRules *rules = XFCE_MENU_STANDARD_RULES (object);
-
-  switch (prop_id)
-    {
-    case PROP_INCLUDE:
-      xfce_menu_standard_rules_set_include (rules, g_value_get_boolean (value));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-xfce_menu_standard_rules_add_rules (XfceMenuRules *rules,
-                                    XfceMenuRules *additional_rules)
-{
-  XfceMenuStandardRules *std_rules = XFCE_MENU_STANDARD_RULES (rules);
-
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-  g_return_if_fail (XFCE_IS_MENU_RULES (additional_rules));
-
-  /* Remove floating reference (if any) and request a normal one */
-#if GLIB_CHECK_VERSION(2,10,0)
-  g_object_ref_sink (G_OBJECT (additional_rules));
-#else
-  g_object_ref (G_OBJECT (additional_rules));
-#endif
-
-  /* Append rules to the list */
-  std_rules->rules = g_list_append (std_rules->rules, additional_rules);
-}
-
-
-
-static void
-xfce_menu_standard_rules_add_all (XfceMenuRules *rules)
-{
-  XfceMenuStandardRules *std_rules = XFCE_MENU_STANDARD_RULES (rules);
-
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-
-  std_rules->all = TRUE;
-}
-
-
-
-static void
-xfce_menu_standard_rules_add_filename (XfceMenuRules *rules,
-                                       const gchar   *filename)
-{
-  XfceMenuStandardRules *std_rules = XFCE_MENU_STANDARD_RULES (rules);
-
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-  g_return_if_fail (filename != NULL);
-
-  /* Append filename to the list */
-  std_rules->filenames = g_list_append (std_rules->filenames, g_strdup (filename));
-}
-
-
-
-static void
-xfce_menu_standard_rules_add_category (XfceMenuRules *rules,
-                                       const gchar   *category)
-{
-  XfceMenuStandardRules *std_rules = XFCE_MENU_STANDARD_RULES (rules);
-
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-  g_return_if_fail (category != NULL);
-
-  /* Append category to the list (if not yet included) */
-  std_rules->categories = g_list_append (std_rules->categories, g_strdup (category));
-}
-
-
-static gboolean
-xfce_menu_standard_rules_match (XfceMenuRules *rules,
-                                XfceMenuItem  *item)
-{
-  XfceMenuStandardRules *std_rules = XFCE_MENU_STANDARD_RULES (rules);
-
-  g_return_val_if_fail (XFCE_IS_MENU_STANDARD_RULES (std_rules), FALSE);
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
-
-  return (*XFCE_MENU_STANDARD_RULES_GET_CLASS (std_rules)->match_item) (std_rules, item);
-}
-
-
-
-static gboolean
-xfce_menu_standard_rules_match_item (XfceMenuStandardRules *rules,
-                                     XfceMenuItem          *item)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_STANDARD_RULES (rules), FALSE);
-  g_return_val_if_fail (XFCE_IS_MENU_ITEM (item), FALSE);
-
-  return FALSE;
-}
-
-
-
-gboolean 
-xfce_menu_standard_rules_get_include (XfceMenuStandardRules *rules)
-{
-  g_return_val_if_fail (XFCE_IS_MENU_STANDARD_RULES (rules), TRUE);
-  return rules->include;
-}
-
-
-
-void xfce_menu_standard_rules_set_include (XfceMenuStandardRules *rules,
-                                           gboolean               include)
-{
-  g_return_if_fail (XFCE_IS_MENU_STANDARD_RULES (rules));
-
-  /* Do nothing if values are equal */
-  if (rules->include == include)
-    return;
-
-  /* Assign new value */
-  rules->include = include;
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (rules), "include");
-}
diff --git a/libxfce4menu/xfce-menu-standard-rules.h b/libxfce4menu/xfce-menu-standard-rules.h
deleted file mode 100644
index f87f5d8..0000000
--- a/libxfce4menu/xfce-menu-standard-rules.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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 FSTANDARD A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_STANDARD_RULES_H__
-#define __XFCE_MENU_STANDARD_RULES_H__
-
-#include <glib-object.h>
-
-typedef struct _XfceMenuStandardRules        XfceMenuStandardRules;
-typedef struct _XfceMenuStandardRulesClass   XfceMenuStandardRulesClass;
-
-#define XFCE_TYPE_MENU_STANDARD_RULES             (xfce_menu_standard_rules_get_type ())
-#define XFCE_MENU_STANDARD_RULES(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_STANDARD_RULES, XfceMenuStandardRules))
-#define XFCE_MENU_STANDARD_RULES_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_STANDARD_RULES, XfceMenuStandardRulesClass))
-#define XFCE_IS_MENU_STANDARD_RULES(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_STANDARD_RULES))
-#define XFCE_IS_MENU_STANDARD_RULES_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((obj), XFCE_TYPE_MENU_STANDARD_RULES))
-#define XFCE_MENU_STANDARD_RULES_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_STANDARD_RULES, XfceMenuStandardRulesClass))
-
-struct _XfceMenuStandardRulesClass
-{
-  GObjectClass __parent__;
-
-  gboolean (*match_item) (XfceMenuStandardRules *rules, 
-                          XfceMenuItem          *item);
-};
-
-struct _XfceMenuStandardRules
-{
-  GObject __parent__;
-
-  /* Nested rules */
-  GList   *rules;
-
-  /* Filename rules */
-  GList   *filenames;
-
-  /* Category rules */
-  GList   *categories;
-
-  /* All rule */
-  guint    all : 1;
-
-  /* Whether this rules object is treated as an include or exclude element */
-  gboolean include;
-};
-
-GType    xfce_menu_standard_rules_get_type      (void) G_GNUC_CONST;
-
-gboolean xfce_menu_standard_rules_get_include   (XfceMenuStandardRules *rules);
-void     xfce_menu_standard_rules_set_include   (XfceMenuStandardRules *rules,
-                                                 gboolean               include);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_STANDARD_RULES_H__ */
diff --git a/libxfce4menu/xfce-menu.c b/libxfce4menu/xfce-menu.c
deleted file mode 100644
index baa537c..0000000
--- a/libxfce4menu/xfce-menu.c
+++ /dev/null
@@ -1,3200 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2 et: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <libxfce4util/libxfce4util.h>
-
-#include <libxfce4menu/xfce-menu-environment.h>
-#include <libxfce4menu/xfce-menu-element.h>
-#include <libxfce4menu/xfce-menu-item.h>
-#include <libxfce4menu/xfce-menu-rules.h>
-#include <libxfce4menu/xfce-menu-standard-rules.h>
-#include <libxfce4menu/xfce-menu-or-rules.h>
-#include <libxfce4menu/xfce-menu-and-rules.h>
-#include <libxfce4menu/xfce-menu-not-rules.h>
-#include <libxfce4menu/xfce-menu-directory.h>
-#include <libxfce4menu/xfce-menu-item-pool.h>
-#include <libxfce4menu/xfce-menu-item-cache.h>
-#include <libxfce4menu/xfce-menu-move.h>
-#include <libxfce4menu/xfce-menu-layout.h>
-#include <libxfce4menu/xfce-menu-separator.h>
-#include <libxfce4menu/xfce-menu-monitor.h>
-#include <libxfce4menu/xfce-menu.h>
-
-
-
-/* Use g_access() on win32 */
-#if defined(G_OS_WIN32)
-#include <glib/gstdio.h>
-#else
-#define g_access(filename, mode) (access ((filename), (mode)))
-#endif
-
-
-
-/* Potential root menu files */
-static const gchar XFCE_MENU_ROOT_SPECS[][30] = 
-{
-  "menus/applications.menu",
-  "menus/xfce-applications.menu",
-  "menus/gnome-applications.menu",
-  "menus/kde-applications.menu",
-};
-
-
-
-static gint xfce_menu_ref_count = 0;
-
-
-
-/**
- * xfce_menu_init:
- * @env : Name of the desktop environment (e.g. XFCE, GNOME, KDE) or %NULL.
- *
- * Initializes the libxfce4menu library and optionally defines the desktop 
- * environment for which menus will be generated. This means items belonging
- * only to other desktop environments will be ignored.
- **/
-void
-xfce_menu_init (const gchar *env)
-{
-  if (g_atomic_int_exchange_and_add (&xfce_menu_ref_count, 1) == 0)
-    {
-      /* Initialize the GThread system */
-      if (!g_thread_supported ())
-        g_thread_init (NULL);
-
-      /* Initialize the GObject type system */
-      g_type_init ();
-
-      /* Set desktop environment */
-      xfce_menu_set_environment (env);
-
-      /* Initialize the menu item cache */
-      _xfce_menu_item_cache_init ();
-
-      /* Initialize the directory module */
-      _xfce_menu_directory_init ();
-
-      /* Initialize monitoring system */
-      _xfce_menu_monitor_init ();
-
-      /* Creates the menu separator */
-      _xfce_menu_separator_init ();
-    }
-}
-
-
-
-/**
- * xfce_menu_shutdown:
- *
- * Shuts down the libxfce4menu library.
- **/
-void
-xfce_menu_shutdown (void)
-{
-  if (g_atomic_int_dec_and_test (&xfce_menu_ref_count))
-    {
-      /* Unset desktop environment */
-      xfce_menu_set_environment (NULL);
-
-      /* Destroys the menu separator */
-      _xfce_menu_separator_shutdown ();
-
-      /* Shutdown monitoring system */
-      _xfce_menu_monitor_shutdown ();
-
-      /* Shutdown the directory module */
-      _xfce_menu_directory_shutdown ();
-
-      /* Shutdown the menu item cache */
-      _xfce_menu_item_cache_shutdown ();
-    }
-}
-
-
-
-#define XFCE_MENU_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_MENU, XfceMenuPrivate))
-
-
-
-/* Menu file parser states */
-typedef enum 
-{
-  XFCE_MENU_PARSE_STATE_START,
-  XFCE_MENU_PARSE_STATE_ROOT,
-  XFCE_MENU_PARSE_STATE_MENU,
-  XFCE_MENU_PARSE_STATE_RULE,
-  XFCE_MENU_PARSE_STATE_END,
-  XFCE_MENU_PARSE_STATE_MOVE,
-  XFCE_MENU_PARSE_STATE_LAYOUT,
-
-} XfceMenuParseState;
-
-/* Menu file node types */
-typedef enum
-{
-  XFCE_MENU_PARSE_NODE_TYPE_NONE,
-  XFCE_MENU_PARSE_NODE_TYPE_NAME,
-  XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY,
-  XFCE_MENU_PARSE_NODE_TYPE_APP_DIR,
-  XFCE_MENU_PARSE_NODE_TYPE_LEGACY_DIR,
-  XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY_DIR,
-  XFCE_MENU_PARSE_NODE_TYPE_FILENAME,
-  XFCE_MENU_PARSE_NODE_TYPE_CATEGORY,
-  XFCE_MENU_PARSE_NODE_TYPE_OLD,
-  XFCE_MENU_PARSE_NODE_TYPE_NEW,
-  XFCE_MENU_PARSE_NODE_TYPE_MENUNAME,
-
-} XfceMenuParseNodeType;
-
-/* Menu file parse context */
-typedef struct _XfceMenuParseContext
-{
-  /* Menu to be parsed */
-  XfceMenu             *root_menu;
-
-  /* Parser state (position in XML tree */
-  XfceMenuParseState    state;
-
-  /* Menu hierarchy "stack" */
-  GList                *menu_stack;
-
-  /* Include/exclude rules stack */
-  GList                *rule_stack;
-
-  /* Current move instruction */
-  XfceMenuMove         *move;
-
-  /* Current node type (for text handler) */
-  XfceMenuParseNodeType node_type;
-
-} XfceMenuParseContext;
-
-typedef struct _XfceMenuPair
-{
-  gpointer first;
-  gpointer second;
-} XfceMenuPair;
-
-typedef struct _XfceMenuParseInfo
-{
-  /* Directory names */
-  GSList     *directory_names;
-
-  /* Desktop entry files items (desktop-file id => absolute filename) used for
-   * resolving the menu items */
-  GHashTable *files;
-
-} XfceMenuParseInfo;
-
-
-
-/* Property identifiers */
-enum
-{
-  PROP_0,
-  PROP_ENVIRONMENT,
-  PROP_FILENAME,
-  PROP_NAME,
-  PROP_DIRECTORY,
-  PROP_DIRECTORY_DIRS, /* TODO */
-  PROP_LEGACY_DIRS, /* TODO */
-  PROP_APP_DIRS, /* TODO Implement methods for this! */
-  PROP_PARENT, /* TODO */
-  PROP_ONLY_UNALLOCATED,
-  PROP_DELETED,
-};
-
-
-
-static void               xfce_menu_class_init                             (XfceMenuClass         *klass);
-static void               xfce_menu_element_init                           (XfceMenuElementIface  *iface);
-static void               xfce_menu_instance_init                          (XfceMenu              *menu);
-static void               xfce_menu_finalize                               (GObject               *object);
-static void               xfce_menu_get_property                           (GObject               *object,
-                                                                            guint                  prop_id,
-                                                                            GValue                *value,
-                                                                            GParamSpec            *pspec);
-static void               xfce_menu_set_property                           (GObject               *object,
-                                                                            guint                  prop_id,
-                                                                            const GValue          *value,
-                                                                            GParamSpec            *pspec);
-
-static gboolean           xfce_menu_load                                   (XfceMenu              *menu,
-                                                                            GError               **error);
-static void               xfce_menu_start_element                          (GMarkupParseContext   *context,
-                                                                            const gchar           *element_name,
-                                                                            const gchar          **attribute_names,
-                                                                            const gchar          **attribute_values,
-                                                                            gpointer               user_data,
-                                                                            GError               **error);
-static void               xfce_menu_end_element                            (GMarkupParseContext   *context,
-                                                                            const gchar           *element_name,
-                                                                            gpointer               user_data,
-                                                                            GError               **error);
-static void               xfce_menu_characters                             (GMarkupParseContext   *context,
-                                                                            const gchar           *text,
-                                                                            gsize                  text_len,
-                                                                            gpointer               user_data,
-                                                                            GError               **error);
-static void               xfce_menu_parse_info_add_directory_name          (XfceMenuParseInfo     *parse_info,
-                                                                            const gchar           *name);
-static void               xfce_menu_parse_info_free                        (XfceMenuParseInfo     *menu);
-static void               xfce_menu_parse_info_consolidate_directory_names (XfceMenuParseInfo *parse_info);
-
-static void               xfce_menu_add_directory_dir                      (XfceMenu              *menu,
-                                                                            const gchar           *dir);
-static void               xfce_menu_add_default_directory_dirs             (XfceMenu              *menu);
-static void               xfce_menu_add_app_dir                            (XfceMenu              *menu,
-                                                                            const gchar           *dir);
-static void               xfce_menu_add_legacy_dir                         (XfceMenu              *menu,
-                                                                            const gchar           *dir);
-static void               xfce_menu_add_kde_legacy_dirs                    (XfceMenu              *menu);
-static void               xfce_menu_add_default_app_dirs                   (XfceMenu              *menu);
-
-#if 0
-static void               xfce_menu_resolve_legacy_menus                   (XfceMenu              *menu);
-static void               xfce_menu_resolve_legacy_menu                    (XfceMenu              *menu,
-                                                                            const gchar           *path);
-#endif
-static void               xfce_menu_remove_duplicates                      (XfceMenu              *menu);
-static void               xfce_menu_consolidate_child_menus                (XfceMenu              *menu);
-#if 0
-static void               xfce_menu_merge_directory_name                   (const gchar           *name,
-                                                                            XfceMenu              *menu);
-static void               xfce_menu_merge_directory_dir                    (const gchar           *dir,
-                                                                            XfceMenu              *menu);
-static void               xfce_menu_merge_app_dir                          (const gchar           *dir,
-                                                                            XfceMenu              *menu);
-static void               xfce_menu_merge_rule                             (XfceMenuRules         *rule,
-                                                                            XfceMenu              *menu);
-#endif
-static void               xfce_menu_consolidate_directory_dirs             (XfceMenu              *menu);
-static void               xfce_menu_consolidate_app_dirs                   (XfceMenu              *menu);
-static void               xfce_menu_resolve_directory                      (XfceMenu              *menu);
-static XfceMenuDirectory *xfce_menu_lookup_directory                       (XfceMenu              *menu,
-                                                                            const gchar           *filename);
-static void               xfce_menu_add_rule                               (XfceMenu              *menu,
-                                                                            XfceMenuRules         *rules);
-static void               xfce_menu_add_move                               (XfceMenu              *menu,
-                                                                            XfceMenuMove          *move);
-static void               xfce_menu_collect_files                          (XfceMenu              *menu);
-static void               xfce_menu_collect_files_from_path                (XfceMenu              *menu,
-                                                                            const gchar           *path,
-                                                                            const gchar           *id_prefix);
-static void               xfce_menu_resolve_items                          (XfceMenu              *menu,
-                                                                            gboolean               only_unallocated);
-static void               xfce_menu_resolve_items_by_rule                  (XfceMenu              *menu,
-                                                                            XfceMenuStandardRules *rule);
-static void               xfce_menu_resolve_item_by_rule                   (const gchar           *desktop_id,
-                                                                            const gchar           *filename,
-                                                                            XfceMenuPair          *data);
-static void               xfce_menu_resolve_deleted                        (XfceMenu              *menu);
-static void               xfce_menu_resolve_moves                          (XfceMenu              *menu);
-static gint               xfce_menu_compare_items                          (gconstpointer         *a,
-                                                                            gconstpointer         *b);
-static const gchar       *xfce_menu_get_element_name                       (XfceMenuElement       *element);
-static const gchar       *xfce_menu_get_element_icon_name                  (XfceMenuElement       *element);
-static void               xfce_menu_monitor_start                          (XfceMenu              *menu);
-static void               xfce_menu_monitor_stop                           (XfceMenu              *menu);
-
-
-
-struct _XfceMenuPrivate
-{
-  /* Menu filename */
-  gchar             *filename;
-
-  /* Menu name */
-  gchar             *name;
-
-  /* Directory */
-  XfceMenuDirectory *directory;
-
-  /* Submenus */
-  GSList            *submenus;
-
-  /* Parent menu */
-  XfceMenu          *parent;
-
-  /* Directory dirs */
-  GSList            *directory_dirs;
-
-  /* Legacy dirs */
-  GSList            *legacy_dirs;
-
-  /* App dirs */
-  GSList            *app_dirs;
-
-  /* Only include desktop entries not used in other menus */
-  guint              only_unallocated : 1;
-
-  /* Whether this menu should be ignored or not */
-  guint              deleted : 1;
-
-  /* Include/exclude rules */
-  GSList            *rules;
-
-  /* Move instructions */
-  GSList            *moves;
-
-  /* Menu item pool */
-  XfceMenuItemPool  *pool;
-
-  /* Shared menu item cache */
-  XfceMenuItemCache *cache;
-
-  /* Menu layout */
-  XfceMenuLayout    *layout;
-
-  /* Parse information (used for resolving) */
-  XfceMenuParseInfo *parse_info;
-};
-
-struct _XfceMenuClass
-{
-  GObjectClass __parent__;
-};
-
-struct _XfceMenu
-{
-  GObject          __parent__;
-
-  /* < private > */
-  XfceMenuPrivate *priv;
-};
-
-
-
-static GObjectClass *xfce_menu_parent_class = NULL;
-
-
-
-GType
-xfce_menu_get_type (void)
-{
-  static GType type = G_TYPE_INVALID;
-
-  if (G_UNLIKELY (type == G_TYPE_INVALID))
-    {
-      static const GTypeInfo info =
-      {
-        sizeof (XfceMenuClass),
-        NULL,
-        NULL,
-        (GClassInitFunc) xfce_menu_class_init,
-        NULL,
-        NULL,
-        sizeof (XfceMenu),
-        0,
-        (GInstanceInitFunc) xfce_menu_instance_init,
-        NULL,
-      };
-
-      static const GInterfaceInfo element_info =
-      {
-        (GInterfaceInitFunc) xfce_menu_element_init,
-        NULL,
-        NULL,
-      };
-
-      type = g_type_register_static (G_TYPE_OBJECT, "XfceMenu", &info, 0);
-      g_type_add_interface_static (type, XFCE_TYPE_MENU_ELEMENT, &element_info);
-    }
-
-  return type;
-}
-
-
-
-static void
-xfce_menu_class_init (XfceMenuClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  g_type_class_add_private (klass, sizeof (XfceMenuPrivate));
-
-  /* Determine the parent type class */
-  xfce_menu_parent_class = g_type_class_peek_parent (klass);
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->finalize = xfce_menu_finalize; 
-  gobject_class->get_property = xfce_menu_get_property;
-  gobject_class->set_property = xfce_menu_set_property;
-
-  /**
-   * XfceMenu:filename:
-   *
-   * The filename of an %XfceMenu object. Whenever this is redefined, the
-   * menu is reloaded.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_FILENAME,
-                                   g_param_spec_string ("filename",
-                                                        "Filename",
-                                                        "XML menu filename",
-                                                        NULL,
-                                                        G_PARAM_READWRITE));
-
-  /**
-   * XfceMenu:name:
-   *
-   * The name of the menu.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_NAME,
-                                   g_param_spec_string ("name",
-                                                        "Name",
-                                                        "Menu name",
-                                                        NULL,
-                                                        G_PARAM_READWRITE));
-
-  /**
-   * XfceMenu:directory:
-   *
-   * The directory entry associated with this menu. 
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_DIRECTORY,
-                                   g_param_spec_object ("directory",
-                                                        "Directory",
-                                                        "Directory entry associated with this menu",
-                                                        XFCE_TYPE_MENU_DIRECTORY,
-                                                        G_PARAM_READWRITE));
-
-  /**
-   * XfceMenu:only-unallocated:
-   *
-   * Whether this menu should only contain desktop entries not used by other
-   * menus.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_ONLY_UNALLOCATED,
-                                   g_param_spec_boolean ("only-unallocated",
-                                                         "Only unallocated",
-                                                         "Whether this menu only contains unallocated entries",
-                                                         FALSE,
-                                                         G_PARAM_READWRITE));
-
-  /**
-   * XfceMenu:deleted:
-   *
-   * Whether this menu should be ignored.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_ONLY_UNALLOCATED,
-                                   g_param_spec_boolean ("deleted",
-                                                         "Deleted",
-                                                         "Whether this menu should be ignored",
-                                                         FALSE,
-                                                         G_PARAM_READWRITE));
-}
-
-
-
-static void
-xfce_menu_element_init (XfceMenuElementIface *iface)
-{
-  iface->get_name = xfce_menu_get_element_name;
-  iface->get_icon_name = xfce_menu_get_element_icon_name;
-}
-
-
-
-static void
-xfce_menu_instance_init (XfceMenu *menu)
-{
-  menu->priv = XFCE_MENU_GET_PRIVATE (menu);
-  menu->priv->filename = NULL;
-  menu->priv->name = NULL;
-  menu->priv->directory = NULL;
-  menu->priv->submenus = NULL;
-  menu->priv->parent = NULL;
-  menu->priv->directory_dirs = NULL;
-  menu->priv->legacy_dirs = NULL;
-  menu->priv->app_dirs = NULL;
-  menu->priv->only_unallocated = FALSE;
-  menu->priv->rules = NULL;
-  menu->priv->moves = NULL;
-  menu->priv->pool = xfce_menu_item_pool_new ();
-  menu->priv->layout = xfce_menu_layout_new ();
-
-  /* Take reference on the menu item cache */
-  menu->priv->cache = xfce_menu_item_cache_get_default ();
-
-  menu->priv->parse_info = g_new (XfceMenuParseInfo, 1);
-  menu->priv->parse_info->directory_names = NULL;
-  menu->priv->parse_info->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-}
-
-
-
-static void
-xfce_menu_finalize (GObject *object)
-{
-  XfceMenu *menu = XFCE_MENU (object);
-
-  /* Stop monitoring */
-  xfce_menu_monitor_stop (menu);
-
-  /* Free filename */
-  g_free (menu->priv->filename);
-
-  /* Free name */
-  g_free (menu->priv->name);
-
-  /* Free directory */
-  if (G_LIKELY (menu->priv->directory != NULL))
-    g_object_unref (menu->priv->directory);
-
-  /* Free directory dirs */
-  g_slist_foreach (menu->priv->directory_dirs, (GFunc) g_free, NULL);
-  g_slist_free (menu->priv->directory_dirs);
-
-  /* Free legacy dirs (check if this is the best way to free the list) */
-  g_slist_foreach (menu->priv->legacy_dirs, (GFunc) g_free, NULL);
-  g_slist_free (menu->priv->legacy_dirs);
-
-  /* Free app dirs */
-  g_slist_foreach (menu->priv->app_dirs, (GFunc) g_free, NULL);
-  g_slist_free (menu->priv->app_dirs);
-
-  /* TODO Free submenus etc. */
-  g_slist_foreach (menu->priv->submenus, (GFunc) g_object_unref, NULL);
-  g_slist_free (menu->priv->submenus);
-
-  /* Free rules */
-  g_slist_foreach (menu->priv->rules, (GFunc) g_object_unref, NULL);
-  g_slist_free (menu->priv->rules);
-
-  /* Free move instructions */
-  g_slist_foreach (menu->priv->moves, (GFunc) g_object_unref, NULL);
-  g_slist_free (menu->priv->moves);
-
-  /* Free item pool */
-  g_object_unref (G_OBJECT (menu->priv->pool));
-
-  /* Free menu layout */
-  g_object_unref (G_OBJECT (menu->priv->layout));
-
-  /* Release item cache reference */
-  g_object_unref (G_OBJECT (menu->priv->cache));
-
-  /* Free parse information */
-  xfce_menu_parse_info_free (menu->priv->parse_info);
-
-  (*G_OBJECT_CLASS (xfce_menu_parent_class)->finalize) (object);
-}
-
-
-
-static void
-xfce_menu_get_property (GObject    *object,
-                        guint       prop_id,
-                        GValue     *value,
-                        GParamSpec *pspec)
-{
-  XfceMenu *menu = XFCE_MENU (object);
-
-  switch (prop_id)
-    {
-    case PROP_FILENAME:
-      g_value_set_string (value, xfce_menu_get_filename (menu));
-      break;
-
-    case PROP_NAME:
-      g_value_set_string (value, xfce_menu_get_name (menu));
-      break;
-
-    case PROP_DIRECTORY:
-      g_value_set_object (value, xfce_menu_get_directory (menu));
-      break;
-
-    case PROP_ONLY_UNALLOCATED:
-      g_value_set_boolean (value, xfce_menu_get_only_unallocated (menu));
-      break;
-
-    case PROP_DELETED:
-      g_value_set_boolean (value, xfce_menu_get_deleted (menu));
-      break;
-    
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-xfce_menu_set_property (GObject      *object,
-                        guint         prop_id,
-                        const GValue *value,
-                        GParamSpec   *pspec)
-{
-  XfceMenu *menu = XFCE_MENU (object);
-
-  switch (prop_id)
-    {
-    case PROP_FILENAME:
-      xfce_menu_set_filename (menu, g_value_get_string (value));
-      break;
-
-    case PROP_NAME:
-      xfce_menu_set_name (menu, g_value_get_string (value));
-      break;
-
-    case PROP_DIRECTORY:
-      xfce_menu_set_directory (menu, g_value_get_object (value));
-      break;
-
-    case PROP_ONLY_UNALLOCATED:
-      xfce_menu_set_only_unallocated (menu, g_value_get_boolean (value));
-      break;
-
-    case PROP_DELETED:
-      xfce_menu_set_deleted (menu, g_value_get_boolean (value));
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-/**
- * xfce_menu_get_root:
- * @error : Return location for errors or %NULL.
- *
- * Loads the system's root menu. This may take some time as it involves
- * parsing and merging a lot of files. So if you call this function from a GUI
- * program it should be done in a way that won't block the user interface (e.g.
- * by using a worker thread).
- * The returned pointer needs to be released using
- * <informalexample><programlisting>
- * g_object_unref (menu);
- * </programlisting></informalexample>
- * when no longer needed.
- *
- * Return value: The system root menu. The menu has to be released when no 
- *               longer needed.
- **/
-XfceMenu*
-xfce_menu_get_root (GError **error)
-{
-  static XfceMenu *root_menu = NULL;
-  gchar           *filename;
-  guint            n;
-
-  if (G_UNLIKELY (root_menu == NULL))
-    {
-      /* Search for a usable root menu file */
-      for (n = 0; n < G_N_ELEMENTS (XFCE_MENU_ROOT_SPECS) && root_menu == NULL; ++n)
-        {
-          /* Search for the root menu file */
-          filename = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, XFCE_MENU_ROOT_SPECS[n]);
-          if (G_UNLIKELY (filename == NULL))
-            continue;
-
-          /* Try to load the root menu from this file */
-          root_menu = xfce_menu_new (filename, NULL);
-          if (G_LIKELY (root_menu != NULL))
-            {
-              /* Add weak pointer on the menu */
-              g_object_add_weak_pointer (G_OBJECT (root_menu), (gpointer) &root_menu);
-            }
-
-          /* Free filename string */
-          g_free (filename);
-        }
-
-      /* Check if we failed to load the root menu */
-      if (G_UNLIKELY (root_menu == NULL))
-        {
-          /* Let the caller know there was no suitable file */
-          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to locate the system menu"));
-        }
-    }
-  else
-    g_object_ref (G_OBJECT (root_menu));
-  
-  return root_menu;
-}
-
-
-
-/**
- * xfce_menu_new:
- * @filename : filename containing the menu structure you want to load.
- * @error    : return location for errors or %NULL.
- *
- * Parses a file and returns the menu structure found in this file. This
- * may involve parsing and merging of a lot of other files. So if you call this
- * function from a GUI program it should be done in a way that won't block the
- * user interface (e.g. by using a worker thread).
- * The returned pointer needs to be released using
- * <informalexample><programlisting>
- * g_object_unref (menu);
- * </programlisting></informalexample>
- * when it is not used anymore.
- *
- * Return value: Menu structure found in @filename.
- **/
-XfceMenu*
-xfce_menu_new (const gchar *filename, 
-               GError     **error)
-{
-  XfceMenu *menu;
-
-  g_return_val_if_fail (filename != NULL && g_path_is_absolute (filename), NULL);
-
-  /* Create new menu */
-  menu = g_object_new (XFCE_TYPE_MENU, "filename", filename, NULL);
-
-  /* Try to load the menu structure */
-  if (!xfce_menu_load (menu, error))
-    {
-      g_object_unref (G_OBJECT (menu));
-      return NULL;
-    }
-
-  return menu;
-}
-
-
-
-/**
- * xfce_menu_get_filename:
- * @menu : a #XfceMenu.
- *
- * Returns the filename from which @menu was loaded.
- * 
- * Return value: filename from which @menu was loaded.
- */
-const gchar*
-xfce_menu_get_filename (XfceMenu *menu)
-{
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  return menu->priv->filename;
-}
-
-
-
-/**
- * xfce_menu_set_filename:
- * @menu     : a #XfceMenu.
- * @filename : new filename of the menu.
- *
- * Sets the menu filename. It should not be necessary to call this
- * function anywhere - it's only of internal use.
- */
-void
-xfce_menu_set_filename (XfceMenu *menu, const gchar *filename)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Abort if filenames are equal */
-  if (G_UNLIKELY (menu->priv->filename != NULL))
-    {
-      if (G_UNLIKELY (filename != NULL && g_utf8_collate (filename, menu->priv->filename) == 0))
-        return;
-
-      /* Free old filename */
-      g_free (menu->priv->filename);
-    }
-
-  /* Set the new filename */
-  menu->priv->filename = g_strdup (filename);
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (menu), "filename");
-}
-
-
-
-/**
- * xfce_menu_get_name:
- * @menu : a #XfceMenu.
- *
- * Returns the name of @menu. In most cases this will be the 
- * contents of the <Menu> element. It may be useful for providing
- * a display name for the menu if it does not have a menu
- * directory.
- *
- * Return value: name of @menu.
- */
-const gchar*
-xfce_menu_get_name (XfceMenu *menu)
-{
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  return menu->priv->name;
-}
-
-
-
-/**
- * xfce_menu_set_name:
- * @menu : a #XfceMenu
- * @name : new name of the menu.
- *
- * Sets the name of @menu. This might come in handy if you want
- * to replace certain menu names with your own names. However, in
- * most cases this function won't be useful.
- */
-void
-xfce_menu_set_name (XfceMenu    *menu, 
-                    const gchar *name)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (name != NULL);
-
-  /* Abort if names are equal */
-  if (G_UNLIKELY (menu->priv->name != NULL))
-    {
-      if (G_UNLIKELY (g_utf8_collate (name, menu->priv->name) == 0))
-        return;
-
-      /* Free old name */
-      g_free (menu->priv->name);
-    }
-
-  /* Set the new filename */
-  menu->priv->name = g_strdup (name);
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (menu), "name");
-}
-
-
-
-/**
- * xfce_menu_get_directory:
- * @menu : a #XfceMenu.
- *
- * Returns the #XfceMenuDirectory of @menu or %NULL. The menu
- * directory may contain a lot of useful information about 
- * the menu, like display name, desktop environments it should
- * show up in etc.
- *
- * Return value: #XfceMenuDirectory of @menu or %NULL.
- */
-XfceMenuDirectory*
-xfce_menu_get_directory (XfceMenu *menu)
-{
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  return menu->priv->directory;
-}
-
-
-
-/**
- * xfce_menu_set_directory:
- * @menu      : a #XfceMenu.
- * @directory : a #XfceMenuDirectory.
- *
- * Replaces the #XfceMenuDirectory of @menu with @directory. This
- * may be useful if @menu has no directory or if you want to 
- * define your own directory for menus. Usually, there's no need
- * to call this function.
- */
-void
-xfce_menu_set_directory (XfceMenu          *menu,
-                         XfceMenuDirectory *directory)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
-
-  /* Abort if directories (TODO: and their locations) are equal */
-  if (G_UNLIKELY (directory == menu->priv->directory))
-    return;
-  
-  /* Destroy old directory */
-  if (G_UNLIKELY (menu->priv->directory != NULL))
-    g_object_unref (menu->priv->directory);
-
-  /* Remove the floating reference and acquire a normal one */
-#if GLIB_CHECK_VERSION(2,10,0)
-  g_object_ref_sink (G_OBJECT (directory));
-#else
-  g_object_ref (G_OBJECT (directory));
-#endif
-
-  /* Set the new directory */
-  menu->priv->directory = directory;
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (menu), "directory");
-}
-
-
-
-/**
- * xfce_menu_get_only_unallocated:
- * @menu : a #XfceMenu.
- *
- * Returns whether @menu only contains #XfceMenuItem<!---->s which
- * are not already included in other menus.
- *
- * Return value: Whether the menu contains only items not used already
- *               included in other menus.
- */
-gboolean
-xfce_menu_get_only_unallocated (XfceMenu *menu)
-{
-  g_return_val_if_fail (XFCE_IS_MENU (menu), FALSE);
-  return menu->priv->only_unallocated;
-}
-
-
-
-/**
- * xfce_menu_set_only_unallocated:
- * @menu             : a #XfceMenu.
- * @only_unallocated : Whether to include only unused 
- *                     #XfceMenuItem<!---->s
- *
- * Since all items are resolved directly after parsing the
- * menu file, this won't be useful other than internally.
- */
-void
-xfce_menu_set_only_unallocated (XfceMenu *menu,
-                                gboolean  only_unallocated)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Abort if values are equal */
-  if (menu->priv->only_unallocated == only_unallocated)
-    return;
-
-  /* Set new value */
-  menu->priv->only_unallocated = only_unallocated;
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (menu), "only-unallocated");
-}
-
-
-
-gboolean
-xfce_menu_get_deleted (XfceMenu *menu)
-{
-  g_return_val_if_fail (XFCE_IS_MENU (menu), FALSE);
-  return menu->priv->deleted;
-}
-
-
-
-void
-xfce_menu_set_deleted (XfceMenu *menu,
-                       gboolean  deleted)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Abort if values are equal */
-  if (menu->priv->deleted == deleted)
-    return;
-
-  /* Set new value */
-  menu->priv->deleted = deleted;
-
-  /* Notify listeners */
-  g_object_notify (G_OBJECT (menu), "deleted");
-}
-
-
-
-/**
- * xfce_menu_get_directory_dirs:
- * @menu : a #XfceMenu
- *
- * Returns a list with all directory dirs of @menu. Collects directory 
- * dirs from @menu up to the root menu so that the root menu directory 
- * dirs come first.
- *
- * Return value: List with all relevant directory dirs of @menu.
- */
-GSList*
-xfce_menu_get_directory_dirs (XfceMenu *menu)
-{
-  XfceMenu *current_menu;
-  GSList   *directories = NULL;
-  GList    *menus = NULL;
-  GList    *iter;
-  GSList    *iter2;
-  
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-
-  /* Collect all menus from menu -> parent -> ... -> root */
-  for (current_menu = menu; current_menu != NULL; current_menu = current_menu->priv->parent)
-    menus = g_list_prepend (menus, current_menu);
-
-  /* Iterate over all menus from root -> parent -> ... -> menu */
-  for (iter = menus; iter != NULL; iter = g_list_next (iter))
-    {
-      /* Fetch current menu */
-      current_menu = XFCE_MENU (iter->data);
-
-      /* Iterate over all directory dirs */
-      for (iter2 = current_menu->priv->directory_dirs; iter2 != NULL; iter2 = g_slist_next (iter2))
-        {
-          /* Append directory dir to the list */
-          directories = g_slist_append (directories, iter2->data);
-        }
-
-      /* Free the directory dir list */
-      g_slist_free (iter2);
-    }
-
-  /* Free menu list */
-  g_list_free (menus);
-
-  return directories;
-}
-
-
-
-GSList*
-xfce_menu_get_legacy_dirs (XfceMenu *menu)
-{
-  /* FIXME: Collecting legacy dirs from the bottom up might be wrong. Perhaps
-   *        only <Menu> items with <LegacyDir> elements are allowed to parse
-   *        legacy menu hierarchies - verify this!
-   */
-
-  XfceMenu *current_menu;
-  GSList   *directories = NULL;
-  GList    *menus = NULL;
-  GList    *iter;
-  GSList    *iter2;
-  
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-
-  /* Collect all menus from menu -> parent -> ... -> root */
-  for (current_menu = menu; current_menu != NULL; current_menu = current_menu->priv->parent)
-    menus = g_list_prepend (menus, current_menu);
-
-  /* Iterate over all menus from root -> parent -> ... -> menu */
-  for (iter = menus; iter != NULL; iter = g_list_next (iter))
-    {
-      /* Fetch current menu */
-      current_menu = XFCE_MENU (iter->data);
-
-      /* Iterate over all legacy directories */
-      for (iter2 = current_menu->priv->legacy_dirs; iter2 != NULL; iter2 = g_slist_next (iter2))
-        {
-          /* Append legacy dir to the list */
-          directories = g_slist_append (directories, iter2->data);
-        }
-
-      /* Free the legacy dir list */
-      g_slist_free (iter2);
-    }
-
-  /* Free menu list */
-  g_list_free (menus);
-
-  return directories;
-}
-
-
-
-GSList*
-xfce_menu_get_app_dirs (XfceMenu *menu)
-{
-  XfceMenu *current_menu;
-  GSList   *directories = NULL;
-  GList    *menus = NULL;
-  GList    *iter;
-  GSList    *iter2;
-  
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-
-  /* Collect all menus from menu -> parent -> ... -> root */
-  for (current_menu = menu; current_menu != NULL; current_menu = current_menu->priv->parent)
-    menus = g_list_prepend (menus, current_menu);
-
-  /* Iterate over all menus from root -> parent -> ... -> menu */
-  for (iter = menus; iter != NULL; iter = g_list_next (iter))
-    {
-      /* Fetch current menu */
-      current_menu = XFCE_MENU (iter->data);
-
-      /* Iterate over all application directories */
-      for (iter2 = current_menu->priv->app_dirs; iter2 != NULL; iter2 = g_slist_next (iter2))
-        {
-          /* Append app dir to the list */
-          directories = g_slist_append (directories, iter2->data);
-        }
-
-      /* Free the app dir list */
-      g_slist_free (iter2);
-    }
-
-  /* Free menu list */
-  g_list_free (menus);
-
-  return directories;
-}
-
-
-
-static gboolean
-xfce_menu_load (XfceMenu *menu, 
-                GError  **error)
-{
-  /* Parser structure (connect handlers etc.) */
-  GMarkupParseContext *context;
-  GMarkupParser parser = {
-      xfce_menu_start_element,
-      xfce_menu_end_element,
-      xfce_menu_characters,
-      NULL,
-      NULL
-  };
-  XfceMenuParseContext menu_context;
-
-  /* File content information */
-  gchar *contents;
-  gsize contents_length;
-  GIOStatus status;
-  GIOChannel *stream;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), FALSE);
-  g_return_val_if_fail (menu->priv->filename != NULL, FALSE);
-
-  /* Try to open the menu file */
-  stream = g_io_channel_new_file (menu->priv->filename, "r", error);
-
-  if (G_UNLIKELY (stream == NULL))
-    return FALSE;
-
-  /* Try to read the menu file */
-  status = g_io_channel_read_to_end (stream, &contents, &contents_length, error);
-  
-  /* Free IO handle */
-  g_io_channel_unref (stream);
-
-  if (G_UNLIKELY (status != G_IO_STATUS_NORMAL))
-    return FALSE;
-
-  /* Define menu parse context */
-  menu_context.root_menu = menu;
-  menu_context.state = XFCE_MENU_PARSE_STATE_START;
-  menu_context.node_type = XFCE_MENU_PARSE_NODE_TYPE_NONE;
-  menu_context.menu_stack = NULL;
-  menu_context.rule_stack = NULL;
-  menu_context.move = NULL;
-
-  /* Allocate parse context */
-  context = g_markup_parse_context_new (&parser, 0, &menu_context, NULL);
-
-  /* Try to parse the menu file */
-  if (!g_markup_parse_context_parse (context, contents, contents_length, error) || 
-      !g_markup_parse_context_end_parse (context, error))
-    {
-      g_markup_parse_context_free (context);
-      return FALSE;
-    }
-  
-  /* Free file contents */
-  g_free (contents);
-
-  /* Free parse context */
-  g_markup_parse_context_free (context);
-
-  /* Free menu parse context */
-  g_list_free (menu_context.menu_stack);
-  g_list_free (menu_context.rule_stack);
-
-#if 0
-  xfce_menu_resolve_legacy_menus (menu);
-#endif
-  xfce_menu_remove_duplicates (menu);
-  xfce_menu_resolve_directory (menu);
-  xfce_menu_resolve_moves (menu);
-
-  /* Collect all potential menu item filenames */
-  xfce_menu_collect_files (menu);
-
-  /* Resolve menu items in two steps to handle <OnlyUnallocated/> properly */
-  xfce_menu_resolve_items (menu, FALSE);
-  xfce_menu_resolve_items (menu, TRUE);
-  
-  /* Remove deleted menus */
-  xfce_menu_resolve_deleted (menu);
-
-  /* Start monitoring */
-  xfce_menu_monitor_start (menu);
-
-  return TRUE;
-}
-
-
-
-static void
-xfce_menu_start_element (GMarkupParseContext *context,
-                         const gchar         *element_name,
-                         const gchar        **attribute_names,
-                         const gchar        **attribute_values,
-                         gpointer             user_data,
-                         GError             **error)
-{
-  XfceMenuParseContext *menu_context = (XfceMenuParseContext *)user_data;
-  XfceMenu             *current_menu;
-  XfceMenuRules        *current_rule;
-
-  switch (menu_context->state) 
-    {
-    case XFCE_MENU_PARSE_STATE_START:
-      if (g_utf8_collate (element_name, "Menu") == 0)
-        {
-          menu_context->state = XFCE_MENU_PARSE_STATE_ROOT;
-          menu_context->menu_stack = g_list_prepend (menu_context->menu_stack, menu_context->root_menu);
-        }
-      break;
-
-    case XFCE_MENU_PARSE_STATE_ROOT:
-    case XFCE_MENU_PARSE_STATE_MENU:
-      /* Fetch current menu from stack */
-      current_menu = g_list_first (menu_context->menu_stack)->data;
-
-      if (g_utf8_collate (element_name, "Name") == 0)
-        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_NAME;
-
-      else if (g_utf8_collate (element_name, "Directory") == 0)
-        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY;
-      else if (g_utf8_collate (element_name, "DirectoryDir") == 0)
-        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY_DIR;
-      else if (g_utf8_collate (element_name, "DefaultDirectoryDirs") == 0)
-        xfce_menu_add_default_directory_dirs (current_menu);
-
-      else if (g_utf8_collate (element_name, "DefaultAppDirs") == 0)
-        xfce_menu_add_default_app_dirs (current_menu);
-      else if (g_utf8_collate (element_name, "AppDir") == 0)
-        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_APP_DIR;
-
-      else if (g_utf8_collate (element_name, "KDELegacyDirs") == 0)
-        xfce_menu_add_kde_legacy_dirs (current_menu);
-      else if (g_utf8_collate (element_name, "LegacyDir") == 0)
-        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_LEGACY_DIR;
-
-      else if (g_utf8_collate (element_name, "OnlyUnallocated") == 0)
-        xfce_menu_set_only_unallocated (current_menu, TRUE);
-      else if (g_utf8_collate (element_name, "NotOnlyUnallocated") == 0)
-        xfce_menu_set_only_unallocated (current_menu, FALSE);
-
-      else if (g_utf8_collate (element_name, "Deleted") == 0)
-        xfce_menu_set_deleted (current_menu, TRUE);
-      else if (g_utf8_collate (element_name, "NotDeleted") == 0)
-        xfce_menu_set_deleted (current_menu, FALSE);
-
-      else if (g_utf8_collate (element_name, "Include") == 0)
-        {
-          /* Create include rule */
-          XfceMenuOrRules *rule = xfce_menu_or_rules_new ();
-
-          /* Set include property */
-          xfce_menu_standard_rules_set_include (XFCE_MENU_STANDARD_RULES (rule), TRUE);
-
-          /* Add rule to the menu */
-          xfce_menu_add_rule (current_menu, XFCE_MENU_RULES (rule));
-
-          /* Put rule to the stack */
-          menu_context->rule_stack = g_list_prepend (menu_context->rule_stack, rule);
-
-          /* Set parse state */
-          menu_context->state = XFCE_MENU_PARSE_STATE_RULE;
-        }
-      else if (g_utf8_collate (element_name, "Exclude") == 0)
-        {
-          /* Create exclude rule */
-          XfceMenuOrRules *rule = xfce_menu_or_rules_new ();
-
-          /* Set include property */
-          xfce_menu_standard_rules_set_include (XFCE_MENU_STANDARD_RULES (rule), FALSE);
-
-          /* Add rule to the menu */
-          xfce_menu_add_rule (current_menu, XFCE_MENU_RULES (rule));
-
-          /* Put rule to the stack */
-          menu_context->rule_stack = g_list_prepend (menu_context->rule_stack, rule);
-
-          /* Set parse state */
-          menu_context->state = XFCE_MENU_PARSE_STATE_RULE;
-        }
-
-      else if (g_utf8_collate (element_name, "Menu") == 0)
-        {
-          /* Create new menu */
-          XfceMenu *menu = g_object_new (XFCE_TYPE_MENU, "filename", current_menu->priv->filename, NULL);
-
-          /* Add menu as submenu to the current menu */
-          xfce_menu_add_menu (current_menu, menu); 
-
-          /* Menu is now owned by the current menu, so we can release it */
-          g_object_unref (menu);
-
-          /* Set parse state */
-          menu_context->state = XFCE_MENU_PARSE_STATE_MENU;
-
-          /* Push new menu to the stack */
-          menu_context->menu_stack = g_list_prepend (menu_context->menu_stack, menu);
-        }
-
-      else if (g_utf8_collate (element_name, "Move") == 0)
-        {
-          /* Set parse state */
-          menu_context->state = XFCE_MENU_PARSE_STATE_MOVE;
-        }
-      else if (g_utf8_collate (element_name, "Layout") == 0)
-        {
-          /* Set parse state */
-          menu_context->state = XFCE_MENU_PARSE_STATE_LAYOUT;
-        }
-      
-      break;
-
-    case XFCE_MENU_PARSE_STATE_RULE:
-      /* Fetch current rule from stack */
-      current_rule = XFCE_MENU_RULES (g_list_first (menu_context->rule_stack)->data);
-
-      if (g_utf8_collate (element_name, "All") == 0)
-        {
-          xfce_menu_rules_add_all (current_rule);
-        }
-      else if (g_utf8_collate (element_name, "Filename") == 0)
-        {
-          menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_FILENAME;
-        }
-      else if (g_utf8_collate (element_name, "Category") == 0)
-        {
-          menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_CATEGORY;
-        }
-      else if (g_utf8_collate (element_name, "And") == 0)
-        {
-          /* Create include rule */
-          XfceMenuAndRules *rule = xfce_menu_and_rules_new ();
-
-          /* Add rule to the current rule */
-          xfce_menu_rules_add_rules (current_rule, XFCE_MENU_RULES (rule));
-
-          /* Rule is now owned by current rule, so we can release it */
-          g_object_unref (rule);
-
-          /* Put rule to the stack */
-          menu_context->rule_stack = g_list_prepend (menu_context->rule_stack, rule);
-        }
-      else if (g_utf8_collate (element_name, "Or") == 0)
-        {
-          /* Create include rule */
-          XfceMenuOrRules *rule = xfce_menu_or_rules_new ();
-
-          /* Add rule to the current rule */
-          xfce_menu_rules_add_rules (current_rule, XFCE_MENU_RULES (rule));
-
-          /* Rule is now owned by current rule, so we can release it */
-          g_object_unref (rule);
-
-          /* Put rule to the stack */
-          menu_context->rule_stack = g_list_prepend (menu_context->rule_stack, rule);
-        }
-      else if (g_utf8_collate (element_name, "Not") == 0)
-        {
-          /* Create include rule */
-          XfceMenuNotRules *rule = xfce_menu_not_rules_new ();
-
-          /* Add rule to the current rule */
-          xfce_menu_rules_add_rules (current_rule, XFCE_MENU_RULES (rule));
-
-          /* Rule is now owned by current rule, so we can release it */
-          g_object_unref (rule);
-
-          /* Put rule to the stack */
-          menu_context->rule_stack = g_list_prepend (menu_context->rule_stack, rule);
-        }
-
-      break;
-
-    case XFCE_MENU_PARSE_STATE_MOVE:
-      /* Fetch current menu from stack */
-      current_menu = g_list_first (menu_context->menu_stack)->data;
-
-      if (g_utf8_collate (element_name, "Old") == 0)
-        {
-          /* Create a new move instruction in the parse context */
-          menu_context->move = xfce_menu_move_new ();
-
-          /* Add move instruction to the menu */
-          xfce_menu_add_move (current_menu, menu_context->move);
-
-          menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_OLD;
-        }
-      else if (g_utf8_collate (element_name, "New") == 0)
-        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_NEW;
-
-      break;
-
-    case XFCE_MENU_PARSE_STATE_LAYOUT:
-      /* Fetch current menu from stack */
-      current_menu = g_list_first (menu_context->menu_stack)->data;
-
-      if (g_utf8_collate (element_name, "Filename") == 0)
-        {
-          /* Set node type */
-          menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_FILENAME;
-        }
-      else if (g_utf8_collate (element_name, "Menuname") == 0)
-        {
-          /* TODO Parse attributes */
-          
-          /* Set node type */
-          menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_MENUNAME;
-        }
-      else if (g_utf8_collate (element_name, "Separator") == 0)
-        {
-          /* Add separator to the menu layout */
-          xfce_menu_layout_add_separator (current_menu->priv->layout);
-        }
-      else if (g_utf8_collate (element_name, "Merge") == 0)
-        {
-          XfceMenuLayoutMergeType type = XFCE_MENU_LAYOUT_MERGE_ALL;
-
-          gboolean type_found = FALSE;
-          gint     i;
-
-          /* Find 'type' attribute */
-          for (i = 0; i < g_strv_length ((gchar **)attribute_names); ++i) 
-            {
-              if (g_utf8_collate (attribute_names[i], "type") == 0)
-                {
-                  /* Determine merge type */
-                  if (g_utf8_collate (attribute_values[i], "menus") == 0)
-                    type = XFCE_MENU_LAYOUT_MERGE_MENUS;
-                  else if (g_utf8_collate (attribute_values[i], "files") == 0)
-                    type = XFCE_MENU_LAYOUT_MERGE_FILES;
-                  else if (g_utf8_collate (attribute_values[i], "all") == 0)
-                    type = XFCE_MENU_LAYOUT_MERGE_ALL;
-
-                  type_found = TRUE;
-                }
-            }
-
-          /* Add merge to the menu layout */
-          xfce_menu_layout_add_merge (current_menu->priv->layout, type);
-        }
-    default:
-      break;
-    }
-}
-
-
-
-static void 
-xfce_menu_end_element (GMarkupParseContext *context,
-                       const gchar         *element_name,
-                       gpointer             user_data,
-                       GError             **error)
-{
-  XfceMenuParseContext *menu_context = (XfceMenuParseContext *)user_data;
-
-  switch (menu_context->state)
-    {
-    case XFCE_MENU_PARSE_STATE_ROOT:
-      if (g_utf8_collate (element_name, "Menu") == 0)
-        {
-          /* Remove root menu from stack */
-          menu_context->menu_stack = g_list_delete_link (menu_context->menu_stack, g_list_first (menu_context->menu_stack));
-
-          /* Set parser state */
-          menu_context->state = XFCE_MENU_PARSE_STATE_END;
-        }
-      break;
-
-    case XFCE_MENU_PARSE_STATE_MENU:
-      if (g_utf8_collate (element_name, "Menu") == 0)
-        {
-          /* Remove current menu from stack */
-          menu_context->menu_stack = g_list_delete_link (menu_context->menu_stack, g_list_first (menu_context->menu_stack));
-
-          /* Set parse state to _STATE_ROOT only if there are no other menus
-           * left on the stack. Otherwise, we're still inside a <Menu> element. */
-          if (G_LIKELY (g_list_length (menu_context->menu_stack) == 1))
-            menu_context->state = XFCE_MENU_PARSE_STATE_ROOT;
-        }
-      break;
-
-    case XFCE_MENU_PARSE_STATE_RULE:
-      if (g_utf8_collate (element_name, "Include") == 0 || g_utf8_collate (element_name, "Exclude") == 0 || g_utf8_collate (element_name, "Or") == 0 || g_utf8_collate (element_name, "And") == 0 || g_utf8_collate (element_name, "Not") == 0)
-        {
-          /* Remove current rule from stack */
-          menu_context->rule_stack = g_list_delete_link (menu_context->rule_stack, g_list_first (menu_context->rule_stack));
-
-          /* Set parse state */
-          if (g_list_length (menu_context->rule_stack) == 0)
-            {
-              if (g_list_length (menu_context->menu_stack) > 1) 
-                menu_context->state = XFCE_MENU_PARSE_STATE_MENU;
-              else
-                menu_context->state = XFCE_MENU_PARSE_STATE_ROOT;
-            }
-        }
-      break;
-
-    case XFCE_MENU_PARSE_STATE_MOVE:
-      if (g_utf8_collate (element_name, "Move") == 0)
-        {
-          /* Set menu parse state */
-          menu_context->state = XFCE_MENU_PARSE_STATE_MENU;
-
-          /* Handle incomplete move commands (those missing a <New> element) */
-          if (G_UNLIKELY (menu_context->move != NULL && xfce_menu_move_get_new (menu_context->move) == NULL))
-            {
-              /* Determine current menu */
-              XfceMenu *current_menu = XFCE_MENU (g_list_first (menu_context->menu_stack)->data);
-
-              /* Remove move command from the menu */
-              current_menu->priv->moves = g_slist_remove (current_menu->priv->moves, menu_context->move);
-
-              /* Free the move command */
-              g_object_unref (menu_context->move);
-            }
-        }
-      else if (g_utf8_collate (element_name, "New") == 0)
-        menu_context->move = NULL;
-      break;
-
-    case XFCE_MENU_PARSE_STATE_LAYOUT:
-      if (g_utf8_collate (element_name, "Layout") == 0)
-        {
-          if (g_list_length (menu_context->menu_stack) > 1)
-            menu_context->state = XFCE_MENU_PARSE_STATE_MENU;
-          else
-            menu_context->state = XFCE_MENU_PARSE_STATE_ROOT;
-        }
-      break;
-
-    default:
-      break;
-    }
-}
-
-
-
-static void
-xfce_menu_characters (GMarkupParseContext *context,
-                      const gchar         *text,
-                      gsize                text_len,
-                      gpointer             user_data,
-                      GError             **error)
-{
-  XfceMenuParseContext *menu_context = (XfceMenuParseContext *)user_data;
-  XfceMenu             *current_menu = NULL;
-  XfceMenuRules        *current_rule = NULL;
-  gchar                *content;
-
-  /* Ignore characters outside of the root <Menu> element */
-  if (G_UNLIKELY (g_list_length (menu_context->menu_stack) == 0))
-    return;
-
-  /* Get the current menu */
-  current_menu = g_list_first (menu_context->menu_stack)->data;
-
-  /* Generate NUL-terminated string */
-  content = g_strndup (text, text_len);
-
-  /* Fetch current rule from stack (if possible) */
-  if (g_list_length (menu_context->rule_stack) > 0)
-    current_rule = g_list_first (menu_context->rule_stack)->data;
-
-  switch (menu_context->node_type)
-    {
-    case XFCE_MENU_PARSE_NODE_TYPE_NAME:
-      xfce_menu_set_name (current_menu, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY:
-      xfce_menu_parse_info_add_directory_name (current_menu->priv->parse_info, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY_DIR:
-      xfce_menu_add_directory_dir (current_menu, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_APP_DIR:
-      xfce_menu_add_app_dir (current_menu, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_LEGACY_DIR:
-      xfce_menu_add_legacy_dir (current_menu, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_FILENAME:
-      if (menu_context->state == XFCE_MENU_PARSE_STATE_RULE) 
-        {
-          if (G_LIKELY (current_rule != NULL))
-            xfce_menu_rules_add_filename (current_rule, content);
-        }
-      else if (menu_context->state == XFCE_MENU_PARSE_STATE_LAYOUT)
-        xfce_menu_layout_add_filename (current_menu->priv->layout, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_CATEGORY:
-      if (G_LIKELY (current_rule != NULL))
-        xfce_menu_rules_add_category (current_rule, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_OLD:
-      xfce_menu_move_set_old (menu_context->move, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_NEW:
-      if (G_LIKELY (menu_context->move != NULL))
-        xfce_menu_move_set_new (menu_context->move, content);
-      break;
-
-    case XFCE_MENU_PARSE_NODE_TYPE_MENUNAME:
-      xfce_menu_layout_add_menuname (current_menu->priv->layout, content);
-      break;
-
-    default:
-      break;
-    }
-
-  /* Free string */
-  g_free (content);
-
-  /* Invalidate node type information */
-  menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_NONE;
-}
-
-
-
-static void
-xfce_menu_parse_info_add_directory_name (XfceMenuParseInfo *parse_info,
-                                         const gchar       *name)
-{
-  g_return_if_fail (name != NULL);
-  parse_info->directory_names = g_slist_append (parse_info->directory_names, g_strdup (name));
-}
-
-
-
-static void
-xfce_menu_parse_info_consolidate_directory_names (XfceMenuParseInfo *parse_info)
-{
-  GSList *names = NULL;
-  GSList *iter;
-
-  g_return_if_fail (parse_info != NULL);
-
-  /* Iterate over directory names in reverse order */
-  for (iter = g_slist_reverse (parse_info->directory_names); iter != NULL; iter = g_slist_next (iter))
-    {
-      /* Prepend name to the new list unless it already exists */
-      if (G_LIKELY (g_slist_find_custom (names, iter->data, (GCompareFunc) g_utf8_collate) == NULL))
-        names = g_slist_prepend (names, g_strdup (iter->data));
-    }
-
-  /* Free old list */
-  g_slist_foreach (parse_info->directory_names, (GFunc) g_free, NULL);
-  g_slist_free (parse_info->directory_names);
-
-  parse_info->directory_names = names;
-}
-
-
-
-static void
-xfce_menu_parse_info_free (XfceMenuParseInfo *parse_info)
-{
-  g_return_if_fail (parse_info != NULL);
-
-  /* Free directory names */
-  g_slist_foreach (parse_info->directory_names, (GFunc) g_free, NULL);
-  g_slist_free (parse_info->directory_names);
-
-#if GLIB_CHECK_VERSION(2,12,0)
-  g_hash_table_unref (parse_info->files);
-#else
-  g_hash_table_destroy (parse_info->files);
-#endif
-
-  /* Free parse info */
-  g_free (parse_info);
-}
-
-
-
-static void
-xfce_menu_add_directory_dir (XfceMenu    *menu,
-                             const gchar *dir)
-{
-  /* Absolute path of the directory (free'd by the menu instance later) */
-  gchar *path;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (dir != NULL);
-
-  if (!g_path_is_absolute (dir))
-    {
-      /* Determine the absolute path (directory) of the menu file */
-      gchar *dirname = g_path_get_dirname (menu->priv->filename);
-
-      /* Construct absolute path */
-      path = g_build_path (G_DIR_SEPARATOR_S, dirname, dir, NULL);
-
-      /* Free absolute menu file directory path */
-      g_free (dirname);
-    }
-  else
-    path = g_strdup (dir);
-
-  /* Append path */
-  menu->priv->directory_dirs = g_slist_append (menu->priv->directory_dirs, path);
-}
-
-
-
-static void
-xfce_menu_add_default_directory_dirs (XfceMenu *menu)
-{
-  int          i;
-  gchar       *path;
-  gchar       *kde_data_dir;
-  const gchar *kde_dir;
-
-  const gchar * const *dirs;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Append $KDEDIR/share/desktop-directories as a workaround for distributions 
-   * not installing KDE menu files properly into $XDG_DATA_DIR */
-
-  /* Get KDEDIR environment variable */
-  kde_dir = g_getenv ("KDEDIR");
-
-  /* Check if this variable is set */
-  if (G_UNLIKELY (kde_dir != NULL))
-    {
-      /* Build KDE data dir */
-      kde_data_dir = g_build_filename (kde_dir, "share", "desktop-directories", NULL);
-
-      /* Add it as a directory dir if it exists */
-      if (G_LIKELY (g_file_test (kde_data_dir, G_FILE_TEST_IS_DIR)))
-        xfce_menu_add_directory_dir (menu, kde_data_dir);
-
-      /* Free the KDE data dir */
-      g_free (kde_data_dir);
-    }
-
-  /* The $KDEDIR workaround ends here */
-
-  /* Append system-wide data dirs */
-  dirs = g_get_system_data_dirs ();
-  for (i = 0; dirs[i] != NULL; i++)
-    {
-      path = g_build_path (G_DIR_SEPARATOR_S, dirs[i], "desktop-directories", NULL);
-      xfce_menu_add_directory_dir (menu, path);
-      g_free (path);
-    }
-
-  /* Append user data dir */
-  path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), "desktop-directories", NULL);
-  xfce_menu_add_directory_dir (menu, path);
-  g_free (path);
-}
-
-
-
-static void
-xfce_menu_add_legacy_dir (XfceMenu    *menu,
-                          const gchar *dir)
-{
-  /* Absolute path of the directory (free'd by the menu instance later) */
-  gchar *path;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (menu->priv->filename != NULL);
-  g_return_if_fail (dir != NULL);
-
-  if (!g_path_is_absolute (dir))
-    {
-      /* Determine the absolute path (directory) of the menu file */
-      gchar *dirname = g_path_get_dirname (menu->priv->filename);
-
-      /* Construct absolute path */
-      path = g_build_path (G_DIR_SEPARATOR_S, dirname, dir, NULL);
-
-      /* Free absolute menu file directory path */
-      g_free (dirname);
-    }
-  else
-    path = g_strdup (dir);
-
-  /* Check if there already are legacy dirs */
-  if (G_LIKELY (menu->priv->legacy_dirs != NULL))
-    {
-      /* Remove all previous occurences of the directory from the list */
-      /* TODO: This probably is rather dirty and should be replaced with a more
-       * clean algorithm. */
-      GSList *iter = menu->priv->legacy_dirs;
-      while (iter != NULL) 
-        {
-          gchar *data = (gchar *)iter->data;
-          if (g_utf8_collate (data, dir) == 0)
-            {
-              GSList *tmp = g_slist_next (iter);
-              menu->priv->app_dirs = g_slist_remove_link (menu->priv->legacy_dirs, iter);
-              iter = tmp;
-            }
-          else
-            iter = iter->next;
-        }
-      
-      /* Append directory */
-      menu->priv->legacy_dirs = g_slist_append (menu->priv->legacy_dirs, path);
-    }
-  else
-    {
-      /* Create new GSList and append the absolute path of the directory */
-      menu->priv->legacy_dirs = g_slist_append (menu->priv->legacy_dirs, path);
-    }
-}
-
-
-
-static void
-xfce_menu_add_kde_legacy_dirs (XfceMenu *menu)
-{
-  static gchar **kde_legacy_dirs = NULL;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  if (G_UNLIKELY (kde_legacy_dirs == NULL))
-    {
-      gchar       *std_out;
-      gchar       *std_err;
-
-      gint         status;
-      GError      *error = NULL;
-      const gchar *kde_dir = g_getenv ("KDEDIR");
-      const gchar *path = g_getenv ("PATH");
-      gchar       *kde_path;
-
-      /* Determine value of KDEDIR */
-      if (G_UNLIKELY (kde_dir != NULL))
-        {
-          /* Build KDEDIR/bin path */
-          gchar *kde_bin_dir = g_build_path (G_DIR_SEPARATOR_S, kde_dir, "bin", NULL);
-          
-          /* Expand PATH to include KDEDIR/bin - if necessary */
-          const gchar *occurence = g_strrstr (path, kde_bin_dir);
-          if (G_LIKELY (occurence == NULL))
-            {
-              /* PATH = $PATH:$KDEDIR/bin */
-              kde_path = g_strjoin (G_SEARCHPATH_SEPARATOR_S, path, kde_bin_dir, NULL);
-
-              /* Set new $PATH value */
-              g_setenv ("PATH", kde_path, TRUE);
-
-              /* Free expanded PATH value */
-              g_free (kde_path);
-            }
-              
-          /* Free KDEDIR/bin */
-          g_free (kde_bin_dir);
-        }
-
-      /* Parse output of kde-config */
-      if (g_spawn_command_line_sync ("kde-config --path apps", &std_out, &std_err, &status, &error))
-        kde_legacy_dirs = g_strsplit (g_strchomp (std_out), G_SEARCHPATH_SEPARATOR_S, 0);
-      else
-        g_error_free (error);
-
-      /* Free output buffers */
-      g_free (std_err);
-      g_free (std_out);
-    }
-
-  if (kde_legacy_dirs != NULL) /* This is neither likely nor unlikely */
-    {
-      int i;
-
-      /* Add all KDE legacy dirs to the list */
-      for (i = 0; i < g_strv_length (kde_legacy_dirs); i++) 
-        xfce_menu_add_legacy_dir (menu, kde_legacy_dirs[i]);
-    }
-}
-
-
-
-static void
-xfce_menu_add_app_dir (XfceMenu    *menu,
-                       const gchar *dir)
-{
-  /* Absolute path of the directory (free'd by the menu instance later) */
-  gchar *path;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (menu->priv->filename != NULL);
-  g_return_if_fail (dir != NULL);
-
-  if (!g_path_is_absolute (dir))
-    {
-      /* Determine the absolute path (directory) of the menu file */
-      gchar *dirname = g_path_get_dirname (menu->priv->filename);
-
-      /* Construct absolute path */
-      path = g_build_path (G_DIR_SEPARATOR_S, dirname, dir, NULL);
-
-      /* Free absolute menu file directory path */
-      g_free (dirname);
-    }
-  else
-    path = g_strdup (dir);
-
-  /* Append path */
-  menu->priv->app_dirs = g_slist_append (menu->priv->app_dirs, path);
-}
-
-
-
-static void 
-xfce_menu_add_default_app_dirs (XfceMenu *menu)
-{
-  int    i;
-  gchar *path;
-  gchar *kde_data_dir;
-  const gchar *kde_dir;
-
-  const gchar * const *dirs;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Append $KDEDIR/share/applications as a workaround for distributions 
-   * not installing KDE menu files properly into $XDG_DATA_DIR */
-
-  /* Get KDEDIR environment variable */
-  kde_dir = g_getenv ("KDEDIR");
-
-  /* Check if this variable is set */
-  if (G_UNLIKELY (kde_dir != NULL))
-    {
-      /* Build KDE data dir */
-      kde_data_dir = g_build_filename (kde_dir, "share", "applications", NULL);
-
-      /* Add it as an app dir if it exists */
-      if (G_LIKELY (g_file_test (kde_data_dir, G_FILE_TEST_IS_DIR)))
-        xfce_menu_add_app_dir (menu, kde_data_dir);
-
-      /* Free the KDE data dir */
-      g_free (kde_data_dir);
-    }
-
-  /* The $KDEDIR workaround ends here */
-
-  /* Append system-wide data dirs */
-  dirs = g_get_system_data_dirs ();
-  for (i = 0; dirs[i] != NULL; i++)
-    {
-      path = g_build_path (G_DIR_SEPARATOR_S, dirs[i], "applications", NULL);
-      xfce_menu_add_app_dir (menu, path);
-      g_free (path);
-    }
-
-  /* Append user data dir */
-  path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), "applications", NULL);
-  xfce_menu_add_app_dir (menu, path);
-  g_free (path);
-}
-
-
-
-GSList*
-xfce_menu_get_menus (XfceMenu *menu)
-{
-  GSList *menus = NULL;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  
-  /* Copy submenu list */
-  menus = g_slist_copy (menu->priv->submenus);
-
-  /* Sort submenus */
-  menus = g_slist_sort (menus, (GCompareFunc) xfce_menu_compare_items);
-
-  return menus;
-}
-
-
-
-void
-xfce_menu_add_menu (XfceMenu *menu,
-                    XfceMenu *submenu)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (XFCE_IS_MENU (submenu));
-
-  /* Remove floating reference and acquire a 'real' one */
-#if GLIB_CHECK_VERSION (2,10,0)
-  g_object_ref_sink (G_OBJECT (submenu));
-#else
-  g_object_ref (G_OBJECT (submenu));
-#endif
-
-  /* Append menu to the list */
-  menu->priv->submenus = g_slist_append (menu->priv->submenus, submenu);
-
-  /* TODO: Use property method here */
-  submenu->priv->parent = menu;
-}
-
-
-
-XfceMenu*
-xfce_menu_get_menu_with_name (XfceMenu    *menu,
-                              const gchar *name)
-{
-  XfceMenu *result = NULL;
-  XfceMenu *submenu;
-  GSList   *iter;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  g_return_val_if_fail (name != NULL, NULL);
-
-  /* Iterate over the submenu list */
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    {
-      submenu = XFCE_MENU (iter->data);
-
-      /* End loop when a matching submenu is found */
-      if (G_UNLIKELY (g_utf8_collate (xfce_menu_get_name (submenu), name) == 0))
-        {
-          result = submenu;
-          break;
-        }
-    }
-
-  return result;
-}
-
-
-
-XfceMenu *
-xfce_menu_get_parent (XfceMenu *menu)
-{
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  return menu->priv->parent;
-}
-
-
-
-#if 0
-static void
-xfce_menu_resolve_legacy_menus (XfceMenu *menu)
-{
-  GSList      *iter;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Iterate over list of legacy directories */
-  for (iter = menu->priv->legacy_dirs; iter != NULL; iter = g_slist_next (iter))
-    {
-      /* Check if the directory exists */
-      if (g_file_test (iter->data, G_FILE_TEST_IS_DIR))
-        {
-          /* Resolve legacy menu hierarchy found in this directory */
-          xfce_menu_resolve_legacy_menu (menu, iter->data);
-        }
-    }
-
-  /* Resolve legacy menus of all child menus */
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    {
-      xfce_menu_resolve_legacy_menus (XFCE_MENU (iter->data));
-    }
-}
-
-
-
-static void
-xfce_menu_resolve_legacy_menu (XfceMenu    *menu,
-                               const gchar *path)
-{
-  XfceMenu          *legacy_menu;
-  XfceMenuDirectory *directory = NULL;
-  GDir              *dir;
-  const gchar       *filename;
-  gchar             *absolute_filename;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (path != NULL && g_file_test (path, G_FILE_TEST_IS_DIR));
-
-  /* Open directory for reading */
-  dir = g_dir_open (path, 0, NULL);
-
-  /* Abort if directory could not be opened */
-  if (G_UNLIKELY (dir == NULL))
-    return;
-
-  /* Create the legacy menu */
-  legacy_menu = g_object_new (XFCE_TYPE_MENU, "filename", menu->priv->filename, NULL);
-
-  /* Set legacy menu name to the directory path */
-  xfce_menu_set_name (legacy_menu, path);
-
-  /* Iterate over directory entries */
-  while ((filename = g_dir_read_name (dir)) != NULL)
-    {
-      /* Build absolute filename for this entry */
-      absolute_filename = g_build_filename (path, filename, NULL);
-
-      if (g_file_test (absolute_filename, G_FILE_TEST_IS_DIR))
-        {
-          /* We have a subdir -> create another legacy menu for this subdirectory */
-          xfce_menu_resolve_legacy_menu (legacy_menu, absolute_filename);
-        }
-      else if (g_utf8_collate (".directory", filename) == 0) 
-        {
-          /* We have a .directory file -> create the directory object for the legacy menu */
-          directory = g_object_new (XFCE_TYPE_MENU_DIRECTORY, "filename", absolute_filename, NULL);
-        }
-    }
-
-  /* Check if there was a .directory file in the directory. Otherwise, don't add
-   * this legacy menu to its parent (-> it is ignored). */
-  if (G_LIKELY (directory != NULL))
-    {
-      /* Set the legacy menu directory */
-      xfce_menu_set_directory (legacy_menu, directory);
-
-      /* Add legacy menu to its new parent */
-      xfce_menu_add_menu (menu, legacy_menu);
-    }
-  else
-    {
-      /* Destroy the legacy menu again - no .directory file found */
-      g_object_unref (legacy_menu);
-    }
-
-  /* Close directory handle */
-  g_dir_close (dir);
-}
-#endif
-
-
-
-static void
-xfce_menu_remove_duplicates (XfceMenu *menu)
-{
-  GSList *iter;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  xfce_menu_consolidate_child_menus (menu);
-  xfce_menu_consolidate_app_dirs (menu);
-  xfce_menu_consolidate_directory_dirs (menu);
-  xfce_menu_parse_info_consolidate_directory_names (menu->priv->parse_info);
-
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    {
-      XfceMenu *submenu = XFCE_MENU (iter->data);
-      xfce_menu_remove_duplicates (submenu);
-    }
-}
-
-
-
-static void
-xfce_menu_consolidate_child_menus (XfceMenu *menu)
-{
-#if 0
-  GSList      *iter;
-  GSList      *merged_submenus = NULL;
-  GHashTable  *groups;
-  const gchar *name;
-  XfceMenu    *submenu;
-  XfceMenu    *merged_menu;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Setup the hash table */
-  groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
-  /* Iterate over all submenus */
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    {
-      submenu = XFCE_MENU (iter->data);
-
-      /* Get menu this submenu should be appended to */
-      merged_menu = XFCE_MENU (g_hash_table_lookup (groups, xfce_menu_get_name (submenu)));
-
-      if (G_LIKELY (merged_menu == NULL))
-        {
-          /* Create empty menu */
-          merged_menu = g_object_new (XFCE_TYPE_MENU, NULL);
-
-          /* Add new menu to the hash table */
-          g_hash_table_insert (groups, (gpointer) xfce_menu_get_name (submenu), merged_menu);
-        }
-
-      /* Copy menu information */
-      /* FIXME This introduces possible bugs. E.g. if merged_menu has one <Deleted> 
-       * element and submenu has none, the lines below would set it to <NotDeleted> 
-       * (which is the default value). This does not follow the spec! Same goes
-       * for <OnlyUnallocated>. */
-      xfce_menu_set_name (merged_menu, xfce_menu_get_name (submenu));
-      xfce_menu_set_only_unallocated (merged_menu, xfce_menu_get_only_unallocated (submenu));
-      xfce_menu_set_deleted (merged_menu, xfce_menu_get_deleted (submenu));
-      xfce_menu_set_filename (merged_menu, xfce_menu_get_filename (submenu));
-
-      /* Set parent menu */
-      merged_menu->priv->parent = menu;
-
-      /* Append directory names, directory and app dirs as well as rules to the merged menu */      
-      g_slist_foreach (submenu->priv->parse_info->directory_names, (GFunc) xfce_menu_merge_directory_name, merged_menu);
-      g_slist_foreach (submenu->priv->directory_dirs, (GFunc) xfce_menu_merge_directory_dir, merged_menu);
-      g_slist_foreach (submenu->priv->app_dirs, (GFunc) xfce_menu_merge_app_dir, merged_menu);
-      g_slist_foreach (submenu->priv->rules, (GFunc) xfce_menu_merge_rule, merged_menu);
-
-      /* TODO Merge submenus of submenu and merged_menu! */
-
-      /* Add merged menu to the new list of submenus if not included already */
-      if (g_slist_find (merged_submenus, merged_menu) == NULL)
-        merged_submenus = g_slist_append (merged_submenus, merged_menu);
-    }
-
-  /* Free old submenu list (and the submenus) */
-  g_slist_foreach (menu->priv->submenus, (GFunc) g_object_unref, NULL);
-  g_slist_free (menu->priv->submenus);
-
-  /* Use list of merged submenus as new submenu list */
-  menu->priv->submenus = merged_submenus;
-
-  /* Free hash table */
-#if GLIB_CHECK_VERSION(2,10,0)  
-  g_hash_table_unref (groups);
-#else
-  g_hash_table_destroy (groups);
-#endif
-
-#endif
-}
-
-
-
-#if 0
-static void
-xfce_menu_merge_directory_name (const gchar *name,
-                                XfceMenu    *menu)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  menu->priv->parse_info->directory_names = g_slist_append (menu->priv->parse_info->directory_names, (gpointer) name);
-}
-
-
-
-static void
-xfce_menu_merge_directory_dir (const gchar *dir, 
-                               XfceMenu    *menu)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  xfce_menu_add_directory_dir (menu, dir);
-}
-
-
-
-static void
-xfce_menu_merge_app_dir (const gchar *dir,
-                         XfceMenu    *menu)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  xfce_menu_add_app_dir (menu, dir);
-}
-
-
-
-static void
-xfce_menu_merge_rule (XfceMenuRules *rules,
-                      XfceMenu      *menu)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-  xfce_menu_add_rule (menu, rules);
-}
-#endif
-
-
-
-static void
-xfce_menu_consolidate_directory_dirs (XfceMenu *menu)
-{
-  GSList *iter;
-  GSList *dirs = NULL;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Iterate over directory dirs in reverse order */
-  for (iter = g_slist_reverse (menu->priv->directory_dirs); iter != NULL; iter = g_slist_next (iter))
-    {
-      /* Prepend directory dir to the new list unless it already exists */
-      if (G_LIKELY (g_slist_find_custom (dirs, iter->data, (GCompareFunc) g_utf8_collate) == NULL))
-        dirs = g_slist_prepend (dirs, g_strdup (iter->data));
-    }
-
-  /* Free old list */
-  g_slist_foreach (menu->priv->directory_dirs, (GFunc) g_free, NULL);
-  g_slist_free (menu->priv->directory_dirs);
-
-  menu->priv->directory_dirs = dirs;
-}
-
-
-
-static void
-xfce_menu_consolidate_app_dirs (XfceMenu *menu)
-{
-  GSList *iter;
-  GSList *dirs = NULL;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Iterate over app dirs in reverse order */
-  for (iter = menu->priv->app_dirs; iter != NULL; iter = g_slist_next (iter))
-    {
-      /* Append app dir to the new list unless it already exists */
-      if (G_LIKELY (g_slist_find_custom (dirs, iter->data, (GCompareFunc) g_utf8_collate) == NULL))
-        dirs = g_slist_append (dirs, g_strdup (iter->data));
-    }
-
-  /* Free old list */
-  g_slist_foreach (menu->priv->app_dirs, (GFunc) g_free, NULL);
-  g_slist_free (menu->priv->app_dirs);
-
-  menu->priv->app_dirs = dirs;
-}
-
-
-
-static void
-xfce_menu_resolve_directory (XfceMenu *menu)
-{
-  GSList            *directory_names;
-  GSList            *iter;
-  XfceMenuDirectory *directory = NULL;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Get reverse copy of all directory names */
-  directory_names = g_slist_reverse (g_slist_copy (menu->priv->parse_info->directory_names));
-
-  /* Try to load one directory name after another */
-  for (iter = directory_names; iter != NULL; iter = g_slist_next (iter))
-    {
-      /* Try to load the directory with this name */
-      directory = xfce_menu_lookup_directory (menu, iter->data);
-
-      /* Abort search if the directory was loaded successfully */
-      if (G_LIKELY (directory != NULL))
-        break;
-    }
-
-  if (G_LIKELY (directory != NULL)) 
-    {
-      /* Set the directory (assuming that we found at least one valid name) */
-      menu->priv->directory = directory;
-    }
-
-  /* Free reverse list copy */
-  g_slist_free (directory_names);
-
-  /* ... and all submenus (recursively) */
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    xfce_menu_resolve_directory (iter->data);
-}
-
-
-
-static XfceMenuDirectory*
-xfce_menu_lookup_directory (XfceMenu    *menu,
-                            const gchar *filename)
-{
-  XfceMenuDirectory *directory = NULL;
-  XfceMenu          *current;
-  GSList            *dirs;
-  gchar             *dirname;
-  gchar             *absolute_path;
-  GSList            *iter;
-  gboolean           found = FALSE;
-  
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-  g_return_val_if_fail (filename != NULL, NULL);
-
-  /* Iterate through all (including parent) menus from the bottom up */
-  for (current = menu; current != NULL; current = xfce_menu_get_parent (current))
-    {
-      /* Allocate a reverse copy of the menu's directory dirs */
-      dirs = g_slist_reverse (xfce_menu_get_directory_dirs (current));
-
-      /* Iterate through all directories */
-      for (iter = dirs; iter != NULL; iter = g_slist_next (iter))
-        {
-          /* Check if the path is absolute */
-          if (G_UNLIKELY (!g_path_is_absolute (iter->data)))
-            {
-              /* Determine directory of the menu file */
-              dirname = g_path_get_dirname (xfce_menu_get_filename (menu));
-              
-              /* Build absolute path */
-              absolute_path = g_build_filename (dirname, iter->data, filename, NULL);
-
-              /* Free directory name */
-              g_free (dirname); 
-            }
-          else
-            absolute_path = g_build_filename (iter->data, filename, NULL);
-
-          /* Check if the file exists and is readable */
-          if (G_UNLIKELY (g_file_test (absolute_path, G_FILE_TEST_EXISTS)))
-            {
-              if (G_LIKELY (g_access (absolute_path, R_OK) == 0))
-                {
-                  /* Load menu directory */
-                  directory = g_object_new (XFCE_TYPE_MENU_DIRECTORY, "filename", absolute_path, NULL);
-
-                  /* Update search status */
-                  found = TRUE;
-                }
-            }
-          
-          /* Free the absolute path */
-         g_free (absolute_path);
-
-          /* Cancel search if we found the menu directory file */
-          if (G_UNLIKELY (found))
-            break;
-        }
-
-      /* Free reverse copy */
-      g_slist_free (dirs);
-    }
-
-  return directory;
-}
-
-
-
-static void
-xfce_menu_collect_files (XfceMenu *menu)
-{
-  GSList *app_dirs;
-  GSList *iter;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Fetch all application directories */
-  app_dirs = g_slist_reverse (xfce_menu_get_app_dirs (menu));
-
-  /* Collect desktop entry filenames */
-  for (iter = app_dirs; iter != NULL; iter = g_slist_next (iter))
-    xfce_menu_collect_files_from_path (menu, iter->data, NULL);
-
-  /* Free directory list */
-  g_slist_free (app_dirs);
-
-  /* Collect filenames for submenus */
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    xfce_menu_collect_files (XFCE_MENU (iter->data));
-}
-
-
-
-static void
-xfce_menu_collect_files_from_path (XfceMenu    *menu,
-                                   const gchar *path,
-                                   const gchar *id_prefix)
-{
-  GDir        *dir;
-  const gchar *filename;
-  gchar       *absolute_path;
-  gchar       *new_id_prefix;
-  gchar       *desktop_id;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (path != NULL && g_path_is_absolute (path));
-
-  /* Skip directory if it doesn't exist */
-  if (G_UNLIKELY (!g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
-    return;
-
-  /* Open directory for reading */
-  dir = g_dir_open (path, 0, NULL);
-
-  /* Abort if directory cannot be opened */
-  if (G_UNLIKELY (dir == NULL))
-    return;
-
-  /* Read file by file */
-  while ((filename = g_dir_read_name (dir)) != NULL)
-    {
-      /* Build absolute path */
-      absolute_path = g_build_filename (path, filename, NULL);
-
-      /* Treat files and directories differently */
-      if (g_file_test (absolute_path, G_FILE_TEST_IS_DIR))
-        {
-          /* Create new desktop-file id prefix */
-          if (G_LIKELY (id_prefix == NULL))
-            new_id_prefix = g_strdup (filename);
-          else
-            new_id_prefix = g_strjoin ("-", id_prefix, filename, NULL);
-
-          /* Collect files in the directory */
-          xfce_menu_collect_files_from_path (menu, absolute_path, new_id_prefix);
-
-          /* Free id prefix */
-          g_free (new_id_prefix);
-        }
-      else
-        {
-          /* Skip all filenames which do not end with .desktop */
-          if (G_LIKELY (g_str_has_suffix (filename, ".desktop")))
-            {
-              /* Create desktop-file id */
-              if (G_LIKELY (id_prefix == NULL))
-                desktop_id = g_strdup (filename);
-              else
-                desktop_id = g_strjoin ("-", id_prefix, filename, NULL);
-
-              /* Insert into the files hash table if the desktop-file id does not exist in there yet */
-              if (G_LIKELY (g_hash_table_lookup (menu->priv->parse_info->files, desktop_id) == NULL))
-                g_hash_table_insert (menu->priv->parse_info->files, g_strdup (desktop_id), g_strdup (absolute_path));
-
-              /* Free desktop-file id */
-              g_free (desktop_id);
-            }
-        }
-
-      /* Free absolute path */
-      g_free (absolute_path);
-    }
-
-  /* Close directory handle */
-  g_dir_close (dir);
-}
-
-
-
-static void
-xfce_menu_resolve_items (XfceMenu *menu,
-                         gboolean  only_unallocated)
-{
-  XfceMenuStandardRules *rule;
-  GSList                *iter;
-
-  g_return_if_fail (menu != NULL && XFCE_IS_MENU (menu));
-
-  /* Resolve items in this menu (if it matches the only_unallocated argument.
-   * This means that in the first pass, all items of menus without 
-   * <OnlyUnallocated /> are resolved and in the second pass, only items of 
-   * menus with <OnlyUnallocated /> are resolved */
-  if (menu->priv->only_unallocated == only_unallocated)
-    {
-      /* Iterate over all rules */
-      for (iter = menu->priv->rules; iter != NULL; iter = g_slist_next (iter))
-        {
-          rule = XFCE_MENU_STANDARD_RULES (iter->data);
-
-          if (G_LIKELY (xfce_menu_standard_rules_get_include (rule)))
-            {
-              /* Resolve available items and match them against this rule */
-              xfce_menu_resolve_items_by_rule (menu, rule);
-            }
-          else
-            {
-              /* Remove all items matching this exclude rule from the item pool */
-              xfce_menu_item_pool_apply_exclude_rule (menu->priv->pool, rule);
-            }
-        }
-    }
-
-  /* Iterate over all submenus */
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    {
-      /* Resolve items of the submenu */
-      xfce_menu_resolve_items (XFCE_MENU (iter->data), only_unallocated);
-    }
-}
-
-
-
-static void
-xfce_menu_resolve_items_by_rule (XfceMenu              *menu,
-                                 XfceMenuStandardRules *rule)
-{
-  XfceMenuPair pair;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (XFCE_IS_MENU_STANDARD_RULES (rule));
-
-  /* Store menu and rule pointer in the pair */
-  pair.first = menu;
-  pair.second = rule;
-
-  /* Try to insert each of the collected desktop entry filenames into the menu */
-  g_hash_table_foreach (menu->priv->parse_info->files, (GHFunc) xfce_menu_resolve_item_by_rule, &pair);
-}
-
-
-
-static void
-xfce_menu_resolve_item_by_rule (const gchar  *desktop_id,
-                                const gchar  *filename,
-                                XfceMenuPair *data)
-{
-  XfceMenu              *menu = NULL;
-  XfceMenuStandardRules *rule = NULL;
-  XfceMenuItem          *item = NULL;
-
-  g_return_if_fail (XFCE_IS_MENU (data->first));
-  g_return_if_fail (XFCE_IS_MENU_STANDARD_RULES (data->second));
-
-  /* Restore menu and rule from the data pair */
-  menu = XFCE_MENU (data->first);
-  rule = XFCE_MENU_STANDARD_RULES (data->second);
-
-  /* Try to load the menu item from the cache */
-  item = xfce_menu_item_cache_lookup (menu->priv->cache, filename, desktop_id);
-
-  if (G_LIKELY (item != NULL))
-    {
-      /* Only include item if menu not only includes unallocated items
-       * or if the item is not allocated yet */
-      if (!menu->priv->only_unallocated || xfce_menu_item_get_allocated (item) == 0)
-        {
-          /* Add item to the pool if it matches the include rule */
-          if (G_LIKELY (xfce_menu_standard_rules_get_include (rule) && xfce_menu_rules_match (XFCE_MENU_RULES (rule), item)))
-            {
-#if 0
-              if (menu->priv->directory != NULL && g_str_equal (xfce_menu_directory_get_name (menu->priv->directory), "Other"))
-                g_debug ("Adding item %s to Other (allocated: %d)", xfce_menu_item_get_name (item), xfce_menu_item_get_allocated (item));
-#endif
-              xfce_menu_item_pool_insert (menu->priv->pool, item);
-            }
-        }
-    }
-}
-
-
-
-static void
-xfce_menu_resolve_deleted (XfceMenu *menu)
-{
-  GSList  *iter;
-  gboolean deleted;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Note: There's a limitation: if the root menu has a <Deleted /> we
-   * can't just free the pointer here. Therefor we only check child menus. */
-
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    {
-      XfceMenu *submenu = iter->data;
-
-      /* Determine whether this submenu was deleted */
-      deleted = submenu->priv->deleted;
-      if (G_LIKELY (submenu->priv->directory != NULL))
-        deleted = deleted || xfce_menu_directory_get_hidden (submenu->priv->directory);
-
-      /* Remove submenu if it is deleted, otherwise check submenus of the submenu */
-      if (G_UNLIKELY (deleted))
-        {
-          /* Remove submenu from the list ... */
-          menu->priv->submenus = g_slist_remove_link (menu->priv->submenus, iter);
-
-          /* ... and destroy it */
-          g_object_unref (G_OBJECT (submenu));
-        }
-      else
-        xfce_menu_resolve_deleted (submenu);
-    }
-}
-
-
-
-static void
-xfce_menu_resolve_moves (XfceMenu *menu)
-{
-  XfceMenuMove *move;
-  XfceMenu     *source;
-  XfceMenu     *destination;
-  GSList       *iter;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Recurse into the submenus which need to perform move actions first */
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    {
-      source = XFCE_MENU (iter->data);
-
-      /* Resolve moves of the child menu */
-      xfce_menu_resolve_moves (source);
-    }
-
-  /* Iterate over move instructions */
-  for (iter = menu->priv->moves; iter != NULL; iter = g_slist_next (iter))
-    {
-      move = XFCE_MENU_MOVE (iter->data);
-      
-      /* Determine submenu with the old name */
-      source = xfce_menu_get_menu_with_name (menu, xfce_menu_move_get_old (move));
-
-      /* Skip if there is no such submenu */
-      if (G_LIKELY (source == NULL))
-        continue;
-
-      /* Determine destination submenu */
-      destination = xfce_menu_get_menu_with_name (menu, xfce_menu_move_get_new (move));
-
-      /* If destination does not exist, simply reset the name of the source menu */
-      if (G_LIKELY (destination == NULL))
-        xfce_menu_set_name (source, xfce_menu_move_get_new (move));
-      else
-        {
-          /* TODO: See section "Merging" in the menu specification. */
-        }
-    }
-
-#if 0 
-  XfceMenu     *submenu;
-  XfceMenu     *target_submenu;
-  XfceMenuMove *move;
-  GSList       *iter;
-  GSList       *submenu_iter;
-  GSList       *removed_menus;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Recurse into the submenus which need to perform move actions first */
-  for (submenu_iter = menu->priv->submenus; submenu_iter != NULL; submenu_iter = g_slist_next (submenu_iter))
-    {
-      submenu = XFCE_MENU (submenu_iter->data);
-
-      /* Resolve moves of the child menu */
-      xfce_menu_resolve_moves (submenu);
-    }
-
-  /* Iterate over the move instructions */
-  for (iter = menu->priv->moves; iter != NULL; iter = g_slist_next (iter))
-    {
-      move = XFCE_MENU_MOVE (iter->data);
-
-      /* Fetch submenu with the old name */
-      submenu = xfce_menu_get_menu_with_name (menu, xfce_menu_move_get_old (move));
-
-      /* Only go into details if there actually is a submenu with this name */
-      if (submenu != NULL)
-        {
-          /* Fetch the target submenu */
-          target_submenu = xfce_menu_get_menu_with_name (menu, xfce_menu_move_get_new (move));
-
-          /* If there is no target, just rename the submenu */
-          if (target_submenu == NULL)
-            xfce_menu_set_name (submenu, xfce_menu_move_get_new (move));
-          else
-            {
-              /* TODO Set <Deleted>, <OnlyUnallocated>, etc. See FIXME in this file for what kind 
-               * of bugs this may introduce. */
-
-              /* Append directory names, directory and app dirs as well as rules to the merged menu */      
-              g_slist_foreach (submenu->priv->parse_info->directory_names, (GFunc) xfce_menu_merge_directory_name, target_submenu);
-              g_slist_foreach (submenu->priv->directory_dirs, (GFunc) xfce_menu_merge_directory_dir, target_submenu);
-              g_slist_foreach (submenu->priv->app_dirs, (GFunc) xfce_menu_merge_app_dir, target_submenu);
-              g_slist_foreach (submenu->priv->rules, (GFunc) xfce_menu_merge_rule, target_submenu);
-              
-              /* Remove submenu from the submenu list */
-              menu->priv->submenus = g_slist_remove (menu->priv->submenus, submenu);
-
-              /* TODO Merge submenus of submenu and target_submenu. Perhaps even
-               * find a better way for merging menus as the current way is a)
-               * duplicated (see consolidate_child_menus) and b) buggy */
-
-              /* TODO Free the submenu - this introduces a strange item pool
-               * error ... */
-              /* g_object_unref (submenu); */
-            }
-        }
-    }
-#endif
-}
-
-
-
-static void
-xfce_menu_add_rule (XfceMenu      *menu,
-                    XfceMenuRules *rules)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (XFCE_IS_MENU_RULES (rules));
-
-  menu->priv->rules = g_slist_append (menu->priv->rules, rules);
-}
-
-
-
-static void
-xfce_menu_add_move (XfceMenu     *menu,
-                    XfceMenuMove *move)
-{
-  g_return_if_fail (XFCE_IS_MENU (menu));
-  g_return_if_fail (XFCE_IS_MENU_MOVE (move));
-
-  menu->priv->moves = g_slist_append (menu->priv->moves, move);
-}
-
-
-
-XfceMenuItemPool*
-xfce_menu_get_item_pool (XfceMenu *menu)
-{
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-
-  return menu->priv->pool;
-}
-
-
-
-static void
-items_collect (const gchar  *desktop_id,
-               XfceMenuItem *item,
-               GSList      **listp)
-{
-  *listp = g_slist_prepend (*listp, item);
-}
-
-
-
-/**
- * xfce_menu_get_items:
- * @menu : a #XfceMenu.
- *
- * Convenience wrapper around xfce_menu_get_item_pool(), which simply returns the
- * #XfceMenuItem<!---->s contained within the associated item pool as singly linked
- * list.
- *
- * The caller is responsible to free the returned list using
- * <informalexample><programlisting>
- * g_slist_free (list);
- * </programlisting></informalexample>
- * when no longer needed.
- * 
- * Return value: the list of #XfceMenuItem<!---->s within this menu.
- **/
-GSList*
-xfce_menu_get_items (XfceMenu *menu)
-{
-  GSList *items = NULL;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-
-  /* Collect the items in the pool */
-  xfce_menu_item_pool_foreach (menu->priv->pool, (GHFunc) items_collect, &items);
-
-  /* Sort items */
-  items = g_slist_sort (items, (GCompareFunc) xfce_menu_compare_items);
-
-  return items;
-}
-
-
-
-gboolean
-xfce_menu_has_layout (XfceMenu *menu)
-{
-  GSList *nodes;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), FALSE);
-  g_return_val_if_fail (XFCE_IS_MENU_LAYOUT (menu->priv->layout), FALSE);
-
-  /* Fetch layout nodes */
-  nodes = xfce_menu_layout_get_nodes (menu->priv->layout);
-
-  /* Menu is supposed to have no layout when the nodes list is empty */
-  return g_slist_length (nodes) > 0;
-}
-
-
-
-static void
-layout_elements_collect (GSList        **dest_list,
-                         GSList         *src_list,
-                         XfceMenuLayout *layout)
-{
-  XfceMenuItem *item;
-  XfceMenu     *menu;
-  GSList       *iter;
-
-  for (iter = src_list; iter != NULL; iter = g_slist_next (iter))
-    {
-      if (XFCE_IS_MENU (iter->data))
-        {
-          menu = XFCE_MENU (iter->data);
-
-          if (G_LIKELY (!xfce_menu_layout_get_menuname_used (layout, xfce_menu_get_name (menu))))
-            *dest_list = g_slist_append (*dest_list, iter->data);
-        }
-      else if (XFCE_IS_MENU_ITEM (iter->data))
-        {
-          item = XFCE_MENU_ITEM (iter->data);
-
-          if (G_LIKELY (!xfce_menu_layout_get_filename_used (layout, xfce_menu_item_get_desktop_id (item))))
-            *dest_list = g_slist_append (*dest_list, iter->data);
-        }
-    }
-}
-
-
-
-GSList*
-xfce_menu_get_layout_elements (XfceMenu *menu)
-{
-  GSList *items = NULL;
-  GSList *menu_items;
-  GSList *nodes;
-  GSList *iter;
-
-  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
-
-  /* Return NULL if there is no layout */
-  if (G_UNLIKELY (!xfce_menu_has_layout (menu)))
-    return NULL;
-
-  /* Fetch layout nodes */
-  nodes = xfce_menu_layout_get_nodes (menu->priv->layout);
-
-  /* Process layout nodes in order */
-  for (iter = nodes; iter != NULL; iter = g_slist_next (iter))
-    {
-      XfceMenuLayoutNode     *node = (XfceMenuLayoutNode *)iter->data;
-      XfceMenuLayoutNodeType  type;
-      XfceMenuLayoutMergeType merge_type;
-      XfceMenuItem           *item;
-      XfceMenu               *submenu;
-
-      /* Determine layout node type */
-      type = xfce_menu_layout_node_get_type (node);
-
-      if (type == XFCE_MENU_LAYOUT_NODE_FILENAME)
-        {
-          /* Search for desktop ID in the item pool */
-          item = xfce_menu_item_pool_lookup (menu->priv->pool, xfce_menu_layout_node_get_filename (node));
-
-          /* If the item with this desktop ID is included in the menu, append it to the list */
-          if (G_LIKELY (item != NULL))
-            items = g_slist_append (items, item);
-        }
-      if (type == XFCE_MENU_LAYOUT_NODE_MENUNAME)
-        {
-          /* Search submenu with this name */
-          submenu = xfce_menu_get_menu_with_name (menu, xfce_menu_layout_node_get_menuname (node));
-
-          /* If there is such a menu, append it to the list */
-          if (G_LIKELY (submenu != NULL))
-            items = g_slist_append (items, submenu);
-        }
-      else if (type == XFCE_MENU_LAYOUT_NODE_SEPARATOR)
-        {
-          /* Append separator to the list */
-          items = g_slist_append (items, xfce_menu_separator_get_default ());
-        }
-      else if (type == XFCE_MENU_LAYOUT_NODE_MERGE)
-        {
-          /* Determine merge type */
-          merge_type = xfce_menu_layout_node_get_merge_type (node);
-
-          if (merge_type == XFCE_MENU_LAYOUT_MERGE_ALL)
-            {
-              /* Get all menu items of this menu */
-              menu_items = xfce_menu_get_items (menu);
-              
-              /* Append submenus */
-              menu_items = g_slist_concat (menu_items, xfce_menu_get_menus (menu));
-
-              /* Sort menu items */
-              menu_items = g_slist_sort (menu_items, (GCompareFunc) xfce_menu_compare_items);
-
-              /* Append menu items to the returned item list */
-              layout_elements_collect (&items, menu_items, menu->priv->layout);
-            }
-          else if (merge_type == XFCE_MENU_LAYOUT_MERGE_FILES)
-            {
-              /* Get all menu items of this menu */
-              menu_items = xfce_menu_get_items (menu);
-
-              /* Append menu items to the returned item list */
-              layout_elements_collect (&items, menu_items, menu->priv->layout);
-            }
-          else if (merge_type == XFCE_MENU_LAYOUT_MERGE_MENUS)
-            {
-              /* Get all submenus */
-              menu_items = xfce_menu_get_menus (menu);
-
-              /* Append submenus to the returned item list */
-              layout_elements_collect (&items, menu_items, menu->priv->layout);
-            }
-        }
-    }
-  
-  return items;
-}
-
-
-
-static gint
-xfce_menu_compare_items (gconstpointer *a,
-                         gconstpointer *b)
-{
-  return g_utf8_collate (xfce_menu_element_get_name (XFCE_MENU_ELEMENT (a)), 
-                         xfce_menu_element_get_name (XFCE_MENU_ELEMENT (b)));
-}
-
-
-
-static const gchar*
-xfce_menu_get_element_name (XfceMenuElement *element)
-{
-  XfceMenu    *menu;
-  const gchar *name = NULL;
-
-  g_return_val_if_fail (XFCE_IS_MENU (element), NULL);
-
-  menu = XFCE_MENU (element);
-
-  /* Try directory name first */
-  if (menu->priv->directory != NULL)
-    name = xfce_menu_directory_get_name (menu->priv->directory);
-
-  /* Otherwise use the menu name as a fallback */
-  if (name == NULL)
-    name = menu->priv->name;
-
-  return name;
-}
-
-
-
-static const gchar*
-xfce_menu_get_element_icon_name (XfceMenuElement *element)
-{
-  XfceMenu *menu;
-  
-  g_return_val_if_fail (XFCE_IS_MENU (element), NULL);
-
-  menu = XFCE_MENU (element);
-
-  return menu->priv->directory != NULL ? xfce_menu_directory_get_icon (menu->priv->directory) : NULL;
-}
-
-
-
-static void
-item_monitor_start (const gchar  *desktop_id,
-                    XfceMenuItem *item,
-                    XfceMenu     *menu)
-{
-  xfce_menu_monitor_add_item (menu, item);
-}
-
-
-
-static void
-xfce_menu_monitor_start (XfceMenu *menu)
-{
-  GSList *iter;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Monitor the menu file */
-  if (G_LIKELY (xfce_menu_monitor_has_flags (XFCE_MENU_MONITOR_MENU_FILES)))
-    xfce_menu_monitor_add_file (menu, menu->priv->filename);
-
-  /* Monitor the menu directory file */
-  if (G_LIKELY (XFCE_IS_MENU_DIRECTORY (menu->priv->directory) && xfce_menu_monitor_has_flags (XFCE_MENU_MONITOR_DIRECTORY_FILES)))
-    xfce_menu_monitor_add_file (menu, xfce_menu_directory_get_filename (menu->priv->directory));
-
-  /* Monitor the application directories */
-  if (G_LIKELY (xfce_menu_monitor_has_flags (XFCE_MENU_MONITOR_DIRECTORIES)))
-    for (iter = menu->priv->app_dirs; iter != NULL; iter = g_slist_next (iter))
-      xfce_menu_monitor_add_directory (menu, (const gchar *)iter->data);
-
-  /* Monitor items in the menu pool */
-  if (G_LIKELY (xfce_menu_monitor_has_flags (XFCE_MENU_MONITOR_DESKTOP_FILES)))
-    xfce_menu_item_pool_foreach (menu->priv->pool, (GHFunc) item_monitor_start, menu);
-
-  /* Monitor items in submenus */
-  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
-    xfce_menu_monitor_start (XFCE_MENU (iter->data));
-}
-
-
-
-static void
-item_monitor_stop (const gchar  *desktop_id,
-                   XfceMenuItem *item,
-                   XfceMenu     *menu)
-{
-  xfce_menu_monitor_remove_item (menu, item);
-}
-
-
-
-static void
-xfce_menu_monitor_stop (XfceMenu *menu)
-{
-  GSList *iter;
-
-  g_return_if_fail (XFCE_IS_MENU (menu));
-
-  /* Stop monitoring the items */
-  xfce_menu_item_pool_foreach (menu->priv->pool, (GHFunc) item_monitor_stop, menu);
-
-  /* Stop monitoring the application directories */
-  for (iter = menu->priv->app_dirs; iter != NULL; iter = g_slist_next (iter))
-    xfce_menu_monitor_remove_directory (menu, (const gchar *)iter->data);
-
-  /* Stop monitoring the menu directory file */
-  if (XFCE_IS_MENU_DIRECTORY (menu->priv->directory))
-    xfce_menu_monitor_remove_file (menu, xfce_menu_directory_get_filename (menu->priv->directory));
-
-  /* Stop monitoring the menu file */
-  xfce_menu_monitor_remove_file (menu, menu->priv->filename);
-}
diff --git a/libxfce4menu/xfce-menu.h b/libxfce4menu/xfce-menu.h
deleted file mode 100644
index a212886..0000000
--- a/libxfce4menu/xfce-menu.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* $Id$ */
-/* vi:set expandtab sw=2 sts=2: */
-/*-
- * Copyright (c) 2006-2007 Jannis Pohlmann <jannis at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
-#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
-#endif
-
-#ifndef __XFCE_MENU_H__
-#define __XFCE_MENU_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _XfceMenuPrivate XfceMenuPrivate;
-typedef struct _XfceMenuClass   XfceMenuClass;
-typedef struct _XfceMenu        XfceMenu;
-
-#define XFCE_TYPE_MENU            (xfce_menu_get_type ())
-#define XFCE_MENU(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU, XfceMenu))
-#define XFCE_MENU_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU, XfceMenuClass))
-#define XFCE_IS_MENU(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU))
-#define XFCE_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU))
-#define XFCE_MENU_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU, XfceMenuClass))
-
-void               xfce_menu_init                  (const gchar *env);
-void               xfce_menu_shutdown              (void);
-
-GType              xfce_menu_get_type              (void) G_GNUC_CONST;
-
-XfceMenu          *xfce_menu_get_root              (GError           **error) G_GNUC_CONST;
-
-XfceMenu          *xfce_menu_new                   (const gchar       *filename,
-                                                    GError           **error) G_GNUC_MALLOC;
-
-const gchar       *xfce_menu_get_filename          (XfceMenu          *menu);
-void               xfce_menu_set_filename          (XfceMenu          *menu,
-                                                    const gchar       *filename);
-const gchar       *xfce_menu_get_name              (XfceMenu          *menu);
-void               xfce_menu_set_name              (XfceMenu          *menu,
-                                                    const gchar       *name);
-XfceMenuDirectory *xfce_menu_get_directory         (XfceMenu          *menu);
-void               xfce_menu_set_directory         (XfceMenu          *menu,
-                                                    XfceMenuDirectory *directory);
-GSList            *xfce_menu_get_directory_dirs    (XfceMenu          *menu);
-GSList            *xfce_menu_get_legacy_dirs       (XfceMenu          *menu);
-GSList            *xfce_menu_get_app_dirs          (XfceMenu          *menu);
-gboolean           xfce_menu_get_only_unallocated  (XfceMenu          *menu);
-void               xfce_menu_set_only_unallocated  (XfceMenu          *menu,
-                                                    gboolean           only_unallocated);
-gboolean           xfce_menu_get_deleted           (XfceMenu          *menu);
-void               xfce_menu_set_deleted           (XfceMenu          *menu,
-                                                    gboolean           deleted);
-GSList            *xfce_menu_get_menus             (XfceMenu          *menu);
-void               xfce_menu_add_menu              (XfceMenu          *menu,
-                                                    XfceMenu          *submenu);
-XfceMenu          *xfce_menu_get_menu_with_name    (XfceMenu          *menu,
-                                                    const gchar       *name);
-XfceMenu          *xfce_menu_get_parent            (XfceMenu          *menu);
-XfceMenuItemPool  *xfce_menu_get_item_pool         (XfceMenu          *menu);
-GSList            *xfce_menu_get_items             (XfceMenu          *menu);
-gboolean           xfce_menu_has_layout            (XfceMenu          *menu);
-GSList            *xfce_menu_get_layout_elements   (XfceMenu          *menu);
-
-G_END_DECLS;
-
-#endif /* !__XFCE_MENU_H__ */
diff --git a/po/ChangeLog b/po/ChangeLog
index 12c86c0..313bf13 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,12 @@
+2009-03-15  Jannis Pohlmann <jannis at xfce.org>
+
+	* POTFILES.in: Remove deleted file xfce-menu-layout.c.
+
+2009-03-14  Jannis Pohlmann <jannis at xfce.org>
+
+	* POTFILES.in: Update translatable source file list.
+	* libxfce4menu-0.1.pot: Update pot file.
+
 2009-02-07  Maximilian Schleiss <maximilian at xfce.org>
 
 	* de.po: German translation update (Enrico Tröger)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 913cdef..844b306 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,16 +1,18 @@
-libxfce4menu/xfce-menu.c
-libxfce4menu/xfce-menu-item.c
-libxfce4menu/xfce-menu-directory.c
-libxfce4menu/xfce-menu-element.c
-libxfce4menu/xfce-menu-environment.c
-libxfce4menu/xfce-menu-rules.c
-libxfce4menu/xfce-menu-standard-rules.c
-libxfce4menu/xfce-menu-and-rules.c
-libxfce4menu/xfce-menu-or-rules.c
-libxfce4menu/xfce-menu-not-rules.c
-libxfce4menu/xfce-menu-item-cache.c
-libxfce4menu/xfce-menu-item-pool.c
-libxfce4menu/xfce-menu-layout.c
-libxfce4menu/xfce-menu-move.c
-libxfce4menu/xfce-menu-separator.c
-tests/test-display-menu.c
+./garcon/garconmenutreeprovider.c
+./garcon/garconmenumerger.c
+./garcon/garconmenuitem-pool.c
+./garcon/garcon.c
+./garcon/garconmnenu.c
+./garcon/garconmenuparser.c
+./garcon/garconmenuseparator.c
+./garcon/garconmenunode.c
+./garcon/garconmenuitem-cache.c
+./garcon/garconenvironment.c
+./garcon/garconmenuitem.c
+./garcon/garcongio.c
+./garcon/garconmenumonitor.c
+./garcon/garconmenudirectory.c
+./garcon/garconmenuelement.c
+./tests/test-display-menu.c
+./tests/test-menu-parser.c
+./tests/test-menu-spec.c
diff --git a/po/libxfce4menu-0.1.pot b/po/garcon.pot
similarity index 57%
rename from po/libxfce4menu-0.1.pot
rename to po/garcon.pot
index 4be5ac9..ef7825d 100644
--- a/po/libxfce4menu-0.1.pot
+++ b/po/garcon.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-06 01:23+0100\n"
+"POT-Creation-Date: 2009-04-04 23:40+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -16,27 +16,21 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#. Let the caller know there was no suitable file
-#: ../libxfce4menu/xfce-menu.c:743
+#: .././libxfce4menu/xfce-menu-parser.c:307
 #, c-format
-msgid "Failed to locate the system menu"
+msgid "Could not load menu file data from %s: %s"
 msgstr ""
 
-#: ../libxfce4menu/xfce-menu-item-cache.c:198
+#: .././libxfce4menu/xfce-menu-parser.c:311
 #, c-format
-msgid "Failed to create the libxfce4menu item cache in %s."
+msgid "Could not load menu file data from %s"
 msgstr ""
 
-#: ../libxfce4menu/xfce-menu-item-cache.c:208
-#, c-format
-msgid "Failed to load the libxfce4menu item cache from %s: %s."
-msgstr ""
-
-#: ../tests/test-display-menu.c:353
+#: .././tests/test-display-menu.c:357
 msgid "XfceMenu: Display Menu Test"
 msgstr ""
 
 #. Create button
-#: ../tests/test-display-menu.c:362
+#: .././tests/test-display-menu.c:366
 msgid "_Show menu"
 msgstr ""
diff --git a/tdb/Makefile.am b/tdb/Makefile.am
deleted file mode 100644
index 0609898..0000000
--- a/tdb/Makefile.am
+++ /dev/null
@@ -1,67 +0,0 @@
-# $Id$
-
-INCLUDES =								\
-	-I$(top_srcdir)							\
-	-I$(top_builddir)						\
-	$(PLATFORM_CFLAGS)
-
-noinst_LTLIBRARIES =							\
-	libtdb.la
-
-libtdb_la_SOURCES =							\
-	spinlock.c							\
-	spinlock.h							\
-	tdb.c								\
-	tdb.h								\
-	tdbconfig.h
-
-noinst_PROGRAMS =							\
-	tdbtool
-
-tdbtool_SOURCES =							\
-	tdbtool.c
-
-tdbtool_DEPENDENCIES =							\
-	libtdb.la
-
-tdbtool_LDADD =								\
-	libtdb.la
-
-TESTS =									\
-	tdbspeed							\
-	tdbtorture
-
-check_PROGRAMS =							\
-	tdbspeed							\
-	tdbtorture
-
-tdbspeed_SOURCES =							\
-	tdbspeed.c
-
-tdbspeed_DEPENDENCIES =							\
-	libtdb.la
-
-tdbspeed_LDADD =							\
-	libtdb.la
-
-tdbtorture_CFLAGS =							\
-	-DNLOOPS=1000							\
-	-DNPROCS=10
-
-tdbtorture_SOURCES =							\
-	tdbtorture.c
-
-tdbtorture_DEPENDENCIES =						\
-	libtdb.la
-
-tdbtorture_LDADD =							\
-	libtdb.la
-
-CLEANFILES =								\
-	test.tdb							\
-	torture.tdb
-
-EXTRA_DIST =								\
-	README
-
-# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/tdb/README b/tdb/README
deleted file mode 100644
index fac3eac..0000000
--- a/tdb/README
+++ /dev/null
@@ -1,167 +0,0 @@
-tdb - a trivial database system
-tridge at linuxcare.com December 1999
-==================================
-
-This is a simple database API. It was inspired by the realisation that
-in Samba we have several ad-hoc bits of code that essentially
-implement small databases for sharing structures between parts of
-Samba. As I was about to add another I realised that a generic
-database module was called for to replace all the ad-hoc bits.
-
-I based the interface on gdbm. I couldn't use gdbm as we need to be
-able to have multiple writers to the databases at one time.
-
-Compilation
------------
-
-add HAVE_MMAP=1 to use mmap instead of read/write
-add TDB_DEBUG=1 for verbose debug info
-add NOLOCK=1 to disable locking code
-
-Testing
--------
-
-Compile tdbtest.c and link with gdbm for testing. tdbtest will perform
-identical operations via tdb and gdbm then make sure the result is the
-same
-
-Also included is tdbtool, which allows simple database manipulation
-on the commandline.
-
-tdbtest and tdbtool are not built as part of Samba, but are included
-for completeness.
-
-Interface
----------
-
-The interface is very similar to gdbm except for the following:
-
-- different open interface. The tdb_open call is more similar to a
-  traditional open()
-- no tdbm_reorganise() function
-- no tdbm_sync() function. No operations are cached in the library anyway
-- added a tdb_traverse() function for traversing the whole database
-
-A general rule for using tdb is that the caller frees any returned
-TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA
-return value called p. This is the same as gdbm.
-
-here is a full list of tdb functions with brief descriptions.
-
-
-----------------------------------------------------------------------
-TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
-		      int open_flags, mode_t mode)
-
-   open the database, creating it if necessary 
-
-   The open_flags and mode are passed straight to the open call on the database
-   file. A flags value of O_WRONLY is invalid
-
-   The hash size is advisory, use zero for a default value. 
-
-   return is NULL on error
-
-   possible tdb_flags are:
-    TDB_CLEAR_IF_FIRST - clear database if we are the only one with it open
-    TDB_INTERNAL - don't use a file, instaed store the data in
-                   memory. The filename is ignored in this case.
-    TDB_NOLOCK - don't do any locking
-    TDB_NOMMAP - don't use mmap
-
-----------------------------------------------------------------------
-char *tdb_error(TDB_CONTEXT *tdb);
-
-     return a error string for the last tdb error
-
-----------------------------------------------------------------------
-int tdb_close(TDB_CONTEXT *tdb);
-
-   close a database
-
-----------------------------------------------------------------------
-int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf);
-
-   update an entry in place - this only works if the new data size
-   is <= the old data size and the key exists.
-   on failure return -1
-
-----------------------------------------------------------------------
-TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
-
-   fetch an entry in the database given a key 
-   if the return value has a null dptr then a error occurred
-
-   caller must free the resulting data
-
-----------------------------------------------------------------------
-int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
-
-   check if an entry in the database exists 
-
-   note that 1 is returned if the key is found and 0 is returned if not found
-   this doesn't match the conventions in the rest of this module, but is
-   compatible with gdbm
-
-----------------------------------------------------------------------
-int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb,
-                 TDB_DATA key, TDB_DATA dbuf, void *state), void *state);
-
-   traverse the entire database - calling fn(tdb, key, data, state) on each 
-   element.
-
-   return -1 on error or the record count traversed
-
-   if fn is NULL then it is not called
-
-   a non-zero return value from fn() indicates that the traversal should stop
-
-----------------------------------------------------------------------
-TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
-
-   find the first entry in the database and return its key
-
-   the caller must free the returned data
-
-----------------------------------------------------------------------
-TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
-
-   find the next entry in the database, returning its key
-
-   the caller must free the returned data
-
-----------------------------------------------------------------------
-int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
-
-   delete an entry in the database given a key
-
-----------------------------------------------------------------------
-int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
-
-   store an element in the database, replacing any existing element
-   with the same key 
-
-   If flag==TDB_INSERT then don't overwrite an existing entry
-   If flag==TDB_MODIFY then don't create a new entry
-
-   return 0 on success, -1 on failure
-
-----------------------------------------------------------------------
-int tdb_writelock(TDB_CONTEXT *tdb);
-
-   lock the database. If we already have it locked then don't do anything
-
-----------------------------------------------------------------------
-int tdb_writeunlock(TDB_CONTEXT *tdb);
-   unlock the database
-
-----------------------------------------------------------------------
-int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
-
-   lock one hash chain. This is meant to be used to reduce locking
-   contention - it cannot guarantee how many records will be locked
-
-----------------------------------------------------------------------
-int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
-
-   unlock one hash chain
diff --git a/tdb/spinlock.c b/tdb/spinlock.c
deleted file mode 100644
index 9b726e7..0000000
--- a/tdb/spinlock.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 2001 Anton Blanchard <anton at samba.org>
- * Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * This file was originally part of the tdb library, which in turn is
- * part of the Samba suite, a Unix SMB/CIFS implementation.
- */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SCHED_H
-#include <sched.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <tdb/spinlock.h>
-
-#ifdef USE_SPINLOCKS
-
-/*
- * ARCH SPECIFIC
- */
-
-#if defined(SPARC_SPINLOCKS)
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
-	unsigned int result;
-
-	asm volatile("ldstub    [%1], %0"
-		: "=r" (result)
-		: "r" (lock)
-		: "memory");
-
-	return (result == 0) ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-	asm volatile("":::"memory");
-	*lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-	*lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-	return (*lock != 0);
-}
-
-#elif defined(POWERPC_SPINLOCKS) 
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
-	unsigned int result;
-
-	__asm__ __volatile__(
-"1:	lwarx		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	li		%0,0\n\
-	bne-		2f\n\
-	li		%0,1\n\
-	stwcx.		%0,0,%1\n\
-	bne-		1b\n\
-	isync\n\
-2:"	: "=&r"(result)
-	: "r"(lock)
-	: "cr0", "memory");
-
-	return (result == 1) ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-	asm volatile("eieio":::"memory");
-	*lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-	*lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-	return (*lock != 0);
-}
-
-#elif defined(INTEL_SPINLOCKS) 
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
-	int oldval;
-
-	asm volatile("xchgl %0,%1"
-		: "=r" (oldval), "=m" (*lock)
-		: "0" (0)
-		: "memory");
-
-	return oldval > 0 ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-	asm volatile("":::"memory");
-	*lock = 1;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-	*lock = 1;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-	return (*lock != 1);
-}
-
-#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730)
-
-/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See
- * sync(3) for the details of the intrinsic operations.
- *
- * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro.
- */
-
-#ifdef STANDALONE
-
-/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */
-#define inline __inline
-
-#endif /* STANDALONE */
-
-/* Returns 0 if the lock is acquired, EBUSY otherwise. */
-static inline int __spin_trylock(spinlock_t *lock)
-{
-        unsigned int val;
-        val = __lock_test_and_set(lock, 1);
-        return val == 0 ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-        __lock_release(lock);
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-        __lock_release(lock);
-}
-
-/* Returns 1 if the lock is held, 0 otherwise. */
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-        unsigned int val;
-        val = __add_and_fetch(lock, 0);
-	return val;
-}
-
-#elif defined(MIPS_SPINLOCKS) 
-
-static inline unsigned int load_linked(unsigned long addr)
-{
-	unsigned int res;
-
-	__asm__ __volatile__("ll\t%0,(%1)"
-		: "=r" (res)
-		: "r" (addr));
-
-	return res;
-}
-
-static inline unsigned int store_conditional(unsigned long addr, unsigned int value)
-{
-	unsigned int res;
-
-	__asm__ __volatile__("sc\t%0,(%2)"
-		: "=r" (res)
-		: "0" (value), "r" (addr));
-	return res;
-}
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
-	unsigned int mw;
-
-	do {
-		mw = load_linked(lock);
-		if (mw) 
-			return EBUSY;
-	} while (!store_conditional(lock, 1));
-
-	asm volatile("":::"memory");
-
-	return 0;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
-	asm volatile("":::"memory");
-	*lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
-	*lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
-	return (*lock != 0);
-}
-
-#else
-#error Need to implement spinlock code in spinlock.c
-#endif
-
-/*
- * OS SPECIFIC
- */
-
-static void yield_cpu(void)
-{
-	struct timespec tm;
-
-#ifdef HAVE_SCHED_YIELD
-	sched_yield();
-#else
-	/* Linux will busy loop for delays < 2ms on real time tasks */
-	tm.tv_sec = 0;
-	tm.tv_nsec = 2000000L + 1;
-	nanosleep(&tm, NULL);
-#endif
-}
-
-static int this_is_smp(void)
-{
-#if defined(HAVE_SYSCONF) && defined(SYSCONF_SC_NPROC_ONLN)
-        return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
-#else
-	return 0;
-#endif
-}
-
-/*
- * GENERIC
- */
-
-static int smp_machine = 0;
-
-static inline void __spin_lock(spinlock_t *lock)
-{
-	int ntries = 0;
-
-	while(__spin_trylock(lock)) {
-		while(__spin_is_locked(lock)) {
-			if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
-				continue;
-			yield_cpu();
-		}
-	}
-}
-
-static void __read_lock(tdb_rwlock_t *rwlock)
-{
-	int ntries = 0;
-
-	while(1) {
-		__spin_lock(&rwlock->lock);
-
-		if (!(rwlock->count & RWLOCK_BIAS)) {
-			rwlock->count++;
-			__spin_unlock(&rwlock->lock);
-			return;
-		}
-	
-		__spin_unlock(&rwlock->lock);
-
-		while(rwlock->count & RWLOCK_BIAS) {
-			if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
-				continue;
-			yield_cpu();
-		}
-	}
-}
-
-static void __write_lock(tdb_rwlock_t *rwlock)
-{
-	int ntries = 0;
-
-	while(1) {
-		__spin_lock(&rwlock->lock);
-
-		if (rwlock->count == 0) {
-			rwlock->count |= RWLOCK_BIAS;
-			__spin_unlock(&rwlock->lock);
-			return;
-		}
-
-		__spin_unlock(&rwlock->lock);
-
-		while(rwlock->count != 0) {
-			if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
-				continue;
-			yield_cpu();
-		}
-	}
-}
-
-static void __write_unlock(tdb_rwlock_t *rwlock)
-{
-	__spin_lock(&rwlock->lock);
-
-#ifdef DEBUG
-	if (!(rwlock->count & RWLOCK_BIAS))
-		fprintf(stderr, "bug: write_unlock\n");
-#endif
-
-	rwlock->count &= ~RWLOCK_BIAS;
-	__spin_unlock(&rwlock->lock);
-}
-
-static void __read_unlock(tdb_rwlock_t *rwlock)
-{
-	__spin_lock(&rwlock->lock);
-
-#ifdef DEBUG
-	if (!rwlock->count)
-		fprintf(stderr, "bug: read_unlock\n");
-
-	if (rwlock->count & RWLOCK_BIAS)
-		fprintf(stderr, "bug: read_unlock\n");
-#endif
-
-	rwlock->count--;
-	__spin_unlock(&rwlock->lock);
-}
-
-/* TDB SPECIFIC */
-
-/* lock a list in the database. list -1 is the alloc list */
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type)
-{
-	tdb_rwlock_t *rwlocks;
-
-	if (!tdb->map_ptr) return -1;
-	rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-
-	switch(rw_type) {
-	case F_RDLCK:
-		__read_lock(&rwlocks[list+1]);
-		break;
-
-	case F_WRLCK:
-		__write_lock(&rwlocks[list+1]);
-		break;
-
-	default:
-		return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-	}
-	return 0;
-}
-
-/* unlock the database. */
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type)
-{
-	tdb_rwlock_t *rwlocks;
-
-	if (!tdb->map_ptr) return -1;
-	rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-
-	switch(rw_type) {
-	case F_RDLCK:
-		__read_unlock(&rwlocks[list+1]);
-		break;
-
-	case F_WRLCK:
-		__write_unlock(&rwlocks[list+1]);
-		break;
-
-	default:
-		return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-	}
-
-	return 0;
-}
-
-int tdb_create_rwlocks(int fd, unsigned int hash_size)
-{
-	unsigned size, i;
-	tdb_rwlock_t *rwlocks;
-
-	size = TDB_SPINLOCK_SIZE(hash_size);
-	rwlocks = malloc(size);
-	if (!rwlocks)
-		return -1;
-
-	for(i = 0; i < hash_size+1; i++) {
-		__spin_lock_init(&rwlocks[i].lock);
-		rwlocks[i].count = 0;
-	}
-
-	/* Write it out (appending to end) */
-	if (write(fd, rwlocks, size) != size) {
-		free(rwlocks);
-		return -1;
-	}
-	smp_machine = this_is_smp();
-	free(rwlocks);
-	return 0;
-}
-
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
-{
-	tdb_rwlock_t *rwlocks;
-	unsigned i;
-
-	if (tdb->header.rwlocks == 0) return 0;
-	if (!tdb->map_ptr) return -1;
-
-	/* We're mmapped here */
-	rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-	for(i = 0; i < tdb->header.hash_size+1; i++) {
-		__spin_lock_init(&rwlocks[i].lock);
-		rwlocks[i].count = 0;
-	}
-	return 0;
-}
-#else
-int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; }
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
-
-/* Non-spinlock version: remove spinlock pointer */
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
-{
-	tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks
-				- (char *)&tdb->header);
-
-	tdb->header.rwlocks = 0;
-	if (lseek(tdb->fd, off, SEEK_SET) != off
-	    || write(tdb->fd, (void *)&tdb->header.rwlocks,
-		     sizeof(tdb->header.rwlocks)) 
-	    != sizeof(tdb->header.rwlocks))
-		return -1;
-	return 0;
-}
-#endif
diff --git a/tdb/spinlock.h b/tdb/spinlock.h
deleted file mode 100644
index f492df1..0000000
--- a/tdb/spinlock.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 2001 Anton Blanchard <anton at samba.org>
- * Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * This file was originally part of the tdb library, which in turn is
- * part of the Samba suite, a Unix SMB/CIFS implementation.
- */
-
-#ifndef __SPINLOCK_H__
-#define __SPINLOCK_H__
-
-#include <tdb/tdb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef USE_SPINLOCKS
-
-#define RWLOCK_BIAS 0x1000UL
-
-/* OS SPECIFIC */
-#define MAX_BUSY_LOOPS 1000
-
-/* ARCH SPECIFIC */
-/* We should make sure these are padded to a cache line */
-#if defined(SPARC_SPINLOCKS)
-typedef volatile char spinlock_t;
-#elif defined(POWERPC_SPINLOCKS)
-typedef volatile unsigned long spinlock_t;
-#elif defined(INTEL_SPINLOCKS)
-typedef volatile int spinlock_t;
-#elif defined(MIPS_SPINLOCKS)
-typedef volatile unsigned long spinlock_t;
-#else
-#error Need to implement spinlock code in spinlock.h
-#endif
-
-typedef struct {
-	spinlock_t lock;
-	volatile int count;
-} tdb_rwlock_t;
-
-#define TDB_SPINLOCK_SIZE(hash_size) (((hash_size) + 1) * sizeof(tdb_rwlock_t))
-
-#else /* !USE_SPINLOCKS */
-
-#define TDB_SPINLOCK_SIZE(hash_size) 0
-
-#endif /* !USE_SPINLOCKS */
-
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
-int tdb_create_rwlocks(int fd, unsigned int hash_size);
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__SPINLOCK_H__ */
diff --git a/tdb/tdb.c b/tdb/tdb.c
deleted file mode 100644
index 3b9f988..0000000
--- a/tdb/tdb.c
+++ /dev/null
@@ -1,2099 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 1999-2004 Andrew Tridgell <tridge at linuxcare.com>
- * Copyright (c) 2000      Paul `Rusty' Russel <rusty at linuxcare.com>
- * Copyright (c) 2000-2003 Jeremy Allison <jeremy at valinux.com>
- * Copyright (c) 2005      Benedikt Meurer <benny at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * This file was originally part of the tdb library, which in turn is
- * part of the Samba suite, a Unix SMB/CIFS implementation.
- */
-
-/* NOTE: If you use tdbs under valgrind, and in particular if you run
- * tdbtorture, you may get spurious "uninitialized value" warnings.  I
- * think this is because valgrind doesn't understand that the mmap'd
- * area may be written to by other processes.  Memory can, from the
- * point of view of the grinded process, spontaneously become
- * initialized.
- *
- * I can think of a few solutions.  [mbp 20030311]
- *
- * 1 - Write suppressions for Valgrind so that it doesn't complain
- * about this.  Probably the most reasonable but people need to
- * remember to use them.
- *
- * 2 - Use IO not mmap when running under valgrind.  Not so nice.
- *
- * 3 - Use the special valgrind macros to mark memory as valid at the
- * right time.  Probably too hard -- the process just doesn't know.
- */ 
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_UI_H
-#include <sys/uio.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <tdb/spinlock.h>
-#include <tdb/tdb.h>
-
-#define TDB_MAGIC_FOOD "TDB file\n"
-#define TDB_VERSION (0x26011967 + 6)
-#define TDB_MAGIC (0x26011999U)
-#define TDB_FREE_MAGIC (~TDB_MAGIC)
-#define TDB_DEAD_MAGIC (0xFEE1DEAD)
-#define TDB_ALIGNMENT 4
-#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT)
-#define DEFAULT_HASH_SIZE 131
-#define TDB_PAGE_SIZE 0x2000
-#define FREELIST_TOP (sizeof(struct tdb_header))
-#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1))
-#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24))
-#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC)
-#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r))
-#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off))
-#define TDB_DATA_START(hash_size) (TDB_HASH_TOP(hash_size-1) + TDB_SPINLOCK_SIZE(hash_size))
-
-
-/* NB assumes there is a local variable called "tdb" that is the
- * current context, also takes doubly-parenthesized print-style
- * argument. */
-#define TDB_LOG(x) (tdb->log_fn?((tdb->log_fn x),0) : 0)
-
-/* lock offsets */
-#define GLOBAL_LOCK 0
-#define ACTIVE_LOCK 4
-
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-
-/* free memory if the pointer is valid and zero the pointer */
-#ifndef SAFE_FREE
-#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0)
-#endif
-
-#define BUCKET(hash) ((hash) % tdb->header.hash_size)
-TDB_DATA tdb_null;
-
-/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
-static TDB_CONTEXT *tdbs = NULL;
-
-static int tdb_munmap(TDB_CONTEXT *tdb)
-{
-	if (tdb->flags & TDB_INTERNAL)
-		return 0;
-
-#ifdef HAVE_MMAP
-	if (tdb->map_ptr) {
-		int ret = munmap(tdb->map_ptr, tdb->map_size);
-		if (ret != 0)
-			return ret;
-	}
-#endif
-	tdb->map_ptr = NULL;
-	return 0;
-}
-
-static void tdb_mmap(TDB_CONTEXT *tdb)
-{
-	if (tdb->flags & TDB_INTERNAL)
-		return;
-
-#ifdef HAVE_MMAP
-	if (!(tdb->flags & TDB_NOMMAP)) {
-		tdb->map_ptr = mmap(NULL, tdb->map_size, 
-				    PROT_READ|(tdb->read_only? 0:PROT_WRITE), 
-				    MAP_SHARED|MAP_FILE, tdb->fd, 0);
-
-		/*
-		 * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
-		 */
-
-		if (tdb->map_ptr == MAP_FAILED) {
-			tdb->map_ptr = NULL;
-			TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", 
-				 tdb->map_size, strerror(errno)));
-		}
-	} else {
-		tdb->map_ptr = NULL;
-	}
-#else
-	tdb->map_ptr = NULL;
-#endif
-}
-
-/* Endian conversion: we only ever deal with 4 byte quantities */
-static void *convert(void *buf, u32 size)
-{
-	u32 i, *p = buf;
-	for (i = 0; i < size / 4; i++)
-		p[i] = TDB_BYTEREV(p[i]);
-	return buf;
-}
-#define DOCONV() (tdb->flags & TDB_CONVERT)
-#define CONVERT(x) (DOCONV() ? convert(&x, sizeof(x)) : &x)
-
-/* the body of the database is made of one list_struct for the free space
-   plus a separate data list for each hash value */
-struct list_struct {
-	tdb_off next; /* offset of the next record in the list */
-	tdb_len rec_len; /* total byte length of record */
-	tdb_len key_len; /* byte length of key */
-	tdb_len data_len; /* byte length of data */
-	u32 full_hash; /* the full 32 bit hash of the key */
-	u32 magic;   /* try to catch errors */
-	/* the following union is implied:
-		union {
-			char record[rec_len];
-			struct {
-				char key[key_len];
-				char data[data_len];
-			}
-			u32 totalsize; (tailer)
-		}
-	*/
-};
-
-/***************************************************************
- Allow a caller to set a "alarm" flag that tdb can check to abort
- a blocking lock on SIGALRM.
-***************************************************************/
-
-static sig_atomic_t *palarm_fired;
-
-void tdb_set_lock_alarm(sig_atomic_t *palarm)
-{
-	palarm_fired = palarm;
-}
-
-/* a byte range locking function - return 0 on success
-   this functions locks/unlocks 1 byte at the specified offset.
-
-   On error, errno is also set so that errors are passed back properly
-   through tdb_open(). */
-static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, 
-		      int rw_type, int lck_type, int probe)
-{
-	struct flock fl;
-	int ret;
-
-	if (tdb->flags & TDB_NOLOCK)
-		return 0;
-	if ((rw_type == F_WRLCK) && (tdb->read_only)) {
-		errno = EACCES;
-		return -1;
-	}
-
-	fl.l_type = rw_type;
-	fl.l_whence = SEEK_SET;
-	fl.l_start = offset;
-	fl.l_len = 1;
-	fl.l_pid = 0;
-
-	do {
-		ret = fcntl(tdb->fd,lck_type,&fl);
-		if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired)
-			break;
-	} while (ret == -1 && errno == EINTR);
-
-	if (ret == -1) {
-		if (!probe && lck_type != F_SETLK) {
-			/* Ensure error code is set for log fun to examine. */
-			if (errno == EINTR && palarm_fired && *palarm_fired)
-				tdb->ecode = TDB_ERR_LOCK_TIMEOUT;
-			else
-				tdb->ecode = TDB_ERR_LOCK;
-			TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d\n", 
-				 tdb->fd, offset, rw_type, lck_type));
-		}
-		/* Was it an alarm timeout ? */
-		if (errno == EINTR && palarm_fired && *palarm_fired) {
-			TDB_LOG((tdb, 5, "tdb_brlock timed out (fd=%d) at offset %d rw_type=%d lck_type=%d\n", 
-				 tdb->fd, offset, rw_type, lck_type));
-			return TDB_ERRCODE(TDB_ERR_LOCK_TIMEOUT, -1);
-		}
-		/* Otherwise - generic lock error. errno set by fcntl.
-		 * EAGAIN is an expected return from non-blocking
-		 * locks. */
-		if (errno != EAGAIN) {
-			TDB_LOG((tdb, 5, "tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d: %s\n", 
-				 tdb->fd, offset, rw_type, lck_type, 
-				 strerror(errno)));
-		}
-		return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-	}
-	return 0;
-}
-
-/* lock a list in the database. list -1 is the alloc list */
-static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype)
-{
-	if (list < -1 || list >= (int)tdb->header.hash_size) {
-		TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", 
-			   list, ltype));
-		return -1;
-	}
-	if (tdb->flags & TDB_NOLOCK)
-		return 0;
-
-	/* Since fcntl locks don't nest, we do a lock for the first one,
-	   and simply bump the count for future ones */
-	if (tdb->locked[list+1].count == 0) {
-		if (!tdb->read_only && tdb->header.rwlocks) {
-			if (tdb_spinlock(tdb, list, ltype)) {
-				TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n", 
-					   list, ltype));
-				return -1;
-			}
-		} else if (tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) {
-			TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", 
-					   list, ltype, strerror(errno)));
-			return -1;
-		}
-		tdb->locked[list+1].ltype = ltype;
-	}
-	tdb->locked[list+1].count++;
-	return 0;
-}
-
-/* unlock the database: returns void because it's too late for errors. */
-	/* changed to return int it may be interesting to know there
-	   has been an error  --simo */
-static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype)
-{
-	int ret = -1;
-
-	if (tdb->flags & TDB_NOLOCK)
-		return 0;
-
-	/* Sanity checks */
-	if (list < -1 || list >= (int)tdb->header.hash_size) {
-		TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
-		return ret;
-	}
-
-	if (tdb->locked[list+1].count==0) {
-		TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n"));
-		return ret;
-	}
-
-	if (tdb->locked[list+1].count == 1) {
-		/* Down to last nested lock: unlock underneath */
-		if (!tdb->read_only && tdb->header.rwlocks) {
-			ret = tdb_spinunlock(tdb, list, ltype);
-		} else {
-			ret = tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, F_SETLKW, 0);
-		}
-	} else {
-		ret = 0;
-	}
-	tdb->locked[list+1].count--;
-
-	if (ret)
-		TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); 
-	return ret;
-}
-
-/* check for an out of bounds access - if it is out of bounds then
-   see if the database has been expanded by someone else and expand
-   if necessary 
-   note that "len" is the minimum length needed for the db
-*/
-static int tdb_oob(TDB_CONTEXT *tdb, tdb_off len, int probe)
-{
-	struct stat st;
-	if (len <= tdb->map_size)
-		return 0;
-	if (tdb->flags & TDB_INTERNAL) {
-		if (!probe) {
-			/* Ensure ecode is set for log fn. */
-			tdb->ecode = TDB_ERR_IO;
-			TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n",
-				 (int)len, (int)tdb->map_size));
-		}
-		return TDB_ERRCODE(TDB_ERR_IO, -1);
-	}
-
-	if (fstat(tdb->fd, &st) == -1)
-		return TDB_ERRCODE(TDB_ERR_IO, -1);
-
-	if (st.st_size < (size_t)len) {
-		if (!probe) {
-			/* Ensure ecode is set for log fn. */
-			tdb->ecode = TDB_ERR_IO;
-			TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n",
-				 (int)len, (int)st.st_size));
-		}
-		return TDB_ERRCODE(TDB_ERR_IO, -1);
-	}
-
-	/* Unmap, update size, remap */
-	if (tdb_munmap(tdb) == -1)
-		return TDB_ERRCODE(TDB_ERR_IO, -1);
-	tdb->map_size = st.st_size;
-	tdb_mmap(tdb);
-	return 0;
-}
-
-/* write a lump of data at a specified offset */
-static int tdb_write(TDB_CONTEXT *tdb, tdb_off off, void *buf, tdb_len len)
-{
-	if (tdb_oob(tdb, off + len, 0) != 0)
-		return -1;
-
-	if (tdb->map_ptr)
-		memcpy(off + (char *)tdb->map_ptr, buf, len);
-#ifdef HAVE_PWRITE
-	else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) {
-#else
-	else if (lseek(tdb->fd, off, SEEK_SET) != off
-		 || write(tdb->fd, buf, len) != (ssize_t)len) {
-#endif
-		/* Ensure ecode is set for log fn. */
-		tdb->ecode = TDB_ERR_IO;
-		TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n",
-			   off, len, strerror(errno)));
-		return TDB_ERRCODE(TDB_ERR_IO, -1);
-	}
-	return 0;
-}
-
-/* read a lump of data at a specified offset, maybe convert */
-static int tdb_read(TDB_CONTEXT *tdb,tdb_off off,void *buf,tdb_len len,int cv)
-{
-	if (tdb_oob(tdb, off + len, 0) != 0)
-		return -1;
-
-	if (tdb->map_ptr)
-		memcpy(buf, off + (char *)tdb->map_ptr, len);
-#ifdef HAVE_PREAD
-	else if (pread(tdb->fd, buf, len, off) != (ssize_t)len) {
-#else
-	else if (lseek(tdb->fd, off, SEEK_SET) != off
-		 || read(tdb->fd, buf, len) != (ssize_t)len) {
-#endif
-		/* Ensure ecode is set for log fn. */
-		tdb->ecode = TDB_ERR_IO;
-		TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d (%s)\n",
-			   off, len, strerror(errno)));
-		return TDB_ERRCODE(TDB_ERR_IO, -1);
-	}
-	if (cv)
-		convert(buf, len);
-	return 0;
-}
-
-/* read a lump of data, allocating the space for it */
-static char *tdb_alloc_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_len len)
-{
-	char *buf;
-
-	if (!(buf = malloc(len))) {
-		/* Ensure ecode is set for log fn. */
-		tdb->ecode = TDB_ERR_OOM;
-		TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n",
-			   len, strerror(errno)));
-		return TDB_ERRCODE(TDB_ERR_OOM, buf);
-	}
-	if (tdb_read(tdb, offset, buf, len, 0) == -1) {
-		SAFE_FREE(buf);
-		return NULL;
-	}
-	return buf;
-}
-
-/* read/write a tdb_off */
-static int ofs_read(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d)
-{
-	return tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV());
-}
-static int ofs_write(TDB_CONTEXT *tdb, tdb_off offset, tdb_off *d)
-{
-	tdb_off off = *d;
-	return tdb_write(tdb, offset, CONVERT(off), sizeof(*d));
-}
-
-/* read/write a record */
-static int rec_read(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
-	if (tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1)
-		return -1;
-	if (TDB_BAD_MAGIC(rec)) {
-		/* Ensure ecode is set for log fn. */
-		tdb->ecode = TDB_ERR_CORRUPT;
-		TDB_LOG((tdb, 0,"rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
-		return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
-	}
-	return tdb_oob(tdb, rec->next+sizeof(*rec), 0);
-}
-static int rec_write(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
-	struct list_struct r = *rec;
-	return tdb_write(tdb, offset, CONVERT(r), sizeof(r));
-}
-
-/* read a freelist record and check for simple errors */
-static int rec_free_read(TDB_CONTEXT *tdb, tdb_off off, struct list_struct *rec)
-{
-	if (tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
-		return -1;
-
-	if (rec->magic == TDB_MAGIC) {
-		/* this happens when a app is showdown while deleting a record - we should
-		   not completely fail when this happens */
-		TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", 
-			 rec->magic, off));
-		rec->magic = TDB_FREE_MAGIC;
-		if (tdb_write(tdb, off, rec, sizeof(*rec)) == -1)
-			return -1;
-	}
-
-	if (rec->magic != TDB_FREE_MAGIC) {
-		/* Ensure ecode is set for log fn. */
-		tdb->ecode = TDB_ERR_CORRUPT;
-		TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", 
-			   rec->magic, off));
-		return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
-	}
-	if (tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
-		return -1;
-	return 0;
-}
-
-/* update a record tailer (must hold allocation lock) */
-static int update_tailer(TDB_CONTEXT *tdb, tdb_off offset,
-			 const struct list_struct *rec)
-{
-	tdb_off totalsize;
-
-	/* Offset of tailer from record header */
-	totalsize = sizeof(*rec) + rec->rec_len;
-	return ofs_write(tdb, offset + totalsize - sizeof(tdb_off),
-			 &totalsize);
-}
-
-static tdb_off tdb_dump_record(TDB_CONTEXT *tdb, tdb_off offset)
-{
-	struct list_struct rec;
-	tdb_off tailer_ofs, tailer;
-
-	if (tdb_read(tdb, offset, (char *)&rec, sizeof(rec), DOCONV()) == -1) {
-		printf("ERROR: failed to read record at %u\n", offset);
-		return 0;
-	}
-
-	printf(" rec: offset=%u next=%d rec_len=%d key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n",
-	       offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, rec.full_hash, rec.magic);
-
-	tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off);
-	if (ofs_read(tdb, tailer_ofs, &tailer) == -1) {
-		printf("ERROR: failed to read tailer at %u\n", tailer_ofs);
-		return rec.next;
-	}
-
-	if (tailer != rec.rec_len + sizeof(rec)) {
-		printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n",
-				(unsigned)tailer, (unsigned)(rec.rec_len + sizeof(rec)));
-	}
-	return rec.next;
-}
-
-static int tdb_dump_chain(TDB_CONTEXT *tdb, int i)
-{
-	tdb_off rec_ptr, top;
-	int hash_length = 0;
-
-	top = TDB_HASH_TOP(i);
-
-	if (tdb_lock(tdb, i, F_WRLCK) != 0)
-		return -1;
-
-	if (ofs_read(tdb, top, &rec_ptr) == -1)
-		return tdb_unlock(tdb, i, F_WRLCK);
-
-	if (rec_ptr)
-		printf("hash=%d\n", i);
-
-	while (rec_ptr) {
-		rec_ptr = tdb_dump_record(tdb, rec_ptr);
-		hash_length += 1;
-	}
-
-	printf("chain %d length %d\n", i, hash_length);
-
-	return tdb_unlock(tdb, i, F_WRLCK);
-}
-
-void tdb_dump_all(TDB_CONTEXT *tdb)
-{
-	int i;
-	for (i=0;i<tdb->header.hash_size;i++) {
-		tdb_dump_chain(tdb, i);
-	}
-	tdb_printfreelist(tdb);
-}
-
-int tdb_printfreelist(TDB_CONTEXT *tdb)
-{
-	int ret;
-	long total_free = 0;
-	tdb_off offset, rec_ptr;
-	struct list_struct rec;
-
-	if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0)
-		return ret;
-
-	offset = FREELIST_TOP;
-
-	/* read in the freelist top */
-	if (ofs_read(tdb, offset, &rec_ptr) == -1) {
-		tdb_unlock(tdb, -1, F_WRLCK);
-		return 0;
-	}
-
-	printf("freelist top=[0x%08x]\n", rec_ptr );
-	while (rec_ptr) {
-		if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) {
-			tdb_unlock(tdb, -1, F_WRLCK);
-			return -1;
-		}
-
-		if (rec.magic != TDB_FREE_MAGIC) {
-			printf("bad magic 0x%08x in free list\n", rec.magic);
-			tdb_unlock(tdb, -1, F_WRLCK);
-			return -1;
-		}
-
-		printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)]\n", rec.next, rec.rec_len, rec.rec_len );
-		total_free += rec.rec_len;
-
-		/* move to the next record */
-		rec_ptr = rec.next;
-	}
-	printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, 
-               (int)total_free);
-
-	return tdb_unlock(tdb, -1, F_WRLCK);
-}
-
-/* Remove an element from the freelist.  Must have alloc lock. */
-static int remove_from_freelist(TDB_CONTEXT *tdb, tdb_off off, tdb_off next)
-{
-	tdb_off last_ptr, i;
-
-	/* read in the freelist top */
-	last_ptr = FREELIST_TOP;
-	while (ofs_read(tdb, last_ptr, &i) != -1 && i != 0) {
-		if (i == off) {
-			/* We've found it! */
-			return ofs_write(tdb, last_ptr, &next);
-		}
-		/* Follow chain (next offset is at start of record) */
-		last_ptr = i;
-	}
-	TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off));
-	return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
-}
-
-/* Add an element into the freelist. Merge adjacent records if
-   neccessary. */
-static int tdb_free(TDB_CONTEXT *tdb, tdb_off offset, struct list_struct *rec)
-{
-	tdb_off right, left;
-
-	/* Allocation and tailer lock */
-	if (tdb_lock(tdb, -1, F_WRLCK) != 0)
-		return -1;
-
-	/* set an initial tailer, so if we fail we don't leave a bogus record */
-	if (update_tailer(tdb, offset, rec) != 0) {
-		TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n"));
-		goto fail;
-	}
-
-	/* Look right first (I'm an Australian, dammit) */
-	right = offset + sizeof(*rec) + rec->rec_len;
-	if (right + sizeof(*rec) <= tdb->map_size) {
-		struct list_struct r;
-
-		if (tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
-			TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right));
-			goto left;
-		}
-
-		/* If it's free, expand to include it. */
-		if (r.magic == TDB_FREE_MAGIC) {
-			if (remove_from_freelist(tdb, right, r.next) == -1) {
-				TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right));
-				goto left;
-			}
-			rec->rec_len += sizeof(r) + r.rec_len;
-		}
-	}
-
-left:
-	/* Look left */
-	left = offset - sizeof(tdb_off);
-	if (left > TDB_DATA_START(tdb->header.hash_size)) {
-		struct list_struct l;
-		tdb_off leftsize;
-		
-		/* Read in tailer and jump back to header */
-		if (ofs_read(tdb, left, &leftsize) == -1) {
-			TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left));
-			goto update;
-		}
-		left = offset - leftsize;
-
-		/* Now read in record */
-		if (tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) {
-			TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize));
-			goto update;
-		}
-
-		/* If it's free, expand to include it. */
-		if (l.magic == TDB_FREE_MAGIC) {
-			if (remove_from_freelist(tdb, left, l.next) == -1) {
-				TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left));
-				goto update;
-			} else {
-				offset = left;
-				rec->rec_len += leftsize;
-			}
-		}
-	}
-
-update:
-	if (update_tailer(tdb, offset, rec) == -1) {
-		TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset));
-		goto fail;
-	}
-
-	/* Now, prepend to free list */
-	rec->magic = TDB_FREE_MAGIC;
-
-	if (ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 ||
-	    rec_write(tdb, offset, rec) == -1 ||
-	    ofs_write(tdb, FREELIST_TOP, &offset) == -1) {
-		TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset));
-		goto fail;
-	}
-
-	/* And we're done. */
-	tdb_unlock(tdb, -1, F_WRLCK);
-	return 0;
-
- fail:
-	tdb_unlock(tdb, -1, F_WRLCK);
-	return -1;
-}
-
-
-/* expand a file.  we prefer to use ftruncate, as that is what posix
-  says to use for mmap expansion */
-static int expand_file(TDB_CONTEXT *tdb, tdb_off size, tdb_off addition)
-{
-	char buf[1024];
-#if HAVE_FTRUNCATE_EXTEND
-	if (ftruncate(tdb->fd, size+addition) != 0) {
-		TDB_LOG((tdb, 0, "expand_file ftruncate to %d failed (%s)\n", 
-			   size+addition, strerror(errno)));
-		return -1;
-	}
-#else
-	char b = 0;
-
-#ifdef HAVE_PWRITE
-	if (pwrite(tdb->fd,  &b, 1, (size+addition) - 1) != 1) {
-#else
-	if (lseek(tdb->fd, (size+addition) - 1, SEEK_SET) != (size+addition) - 1 || 
-	    write(tdb->fd, &b, 1) != 1) {
-#endif
-		TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", 
-			   size+addition, strerror(errno)));
-		return -1;
-	}
-#endif
-
-	/* now fill the file with something. This ensures that the file isn't sparse, which would be
-	   very bad if we ran out of disk. This must be done with write, not via mmap */
-	memset(buf, 0x42, sizeof(buf));
-	while (addition) {
-		int n = addition>sizeof(buf)?sizeof(buf):addition;
-#ifdef HAVE_PWRITE
-		int ret = pwrite(tdb->fd, buf, n, size);
-#else
-		int ret;
-		if (lseek(tdb->fd, size, SEEK_SET) != size)
-			return -1;
-		ret = write(tdb->fd, buf, n);
-#endif
-		if (ret != n) {
-			TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", 
-				   n, strerror(errno)));
-			return -1;
-		}
-		addition -= n;
-		size += n;
-	}
-	return 0;
-}
-
-
-/* expand the database at least size bytes by expanding the underlying
-   file and doing the mmap again if necessary */
-static int tdb_expand(TDB_CONTEXT *tdb, tdb_off size)
-{
-	struct list_struct rec;
-	tdb_off offset;
-
-	if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
-		TDB_LOG((tdb, 0, "lock failed in tdb_expand\n"));
-		return -1;
-	}
-
-	/* must know about any previous expansions by another process */
-	tdb_oob(tdb, tdb->map_size + 1, 1);
-
-	/* always make room for at least 10 more records, and round
-           the database up to a multiple of TDB_PAGE_SIZE */
-	size = TDB_ALIGN(tdb->map_size + size*10, TDB_PAGE_SIZE) - tdb->map_size;
-
-	if (!(tdb->flags & TDB_INTERNAL))
-		tdb_munmap(tdb);
-
-	/*
-	 * We must ensure the file is unmapped before doing this
-	 * to ensure consistency with systems like OpenBSD where
-	 * writes and mmaps are not consistent.
-	 */
-
-	/* expand the file itself */
-	if (!(tdb->flags & TDB_INTERNAL)) {
-		if (expand_file(tdb, tdb->map_size, size) != 0)
-			goto fail;
-	}
-
-	tdb->map_size += size;
-
-	if (tdb->flags & TDB_INTERNAL) {
-		char *new_map_ptr = realloc(tdb->map_ptr, tdb->map_size);
-		if (!new_map_ptr) {
-			tdb->map_size -= size;
-			goto fail;
-		}
-		tdb->map_ptr = new_map_ptr;
-	} else {
-		/*
-		 * We must ensure the file is remapped before adding the space
-		 * to ensure consistency with systems like OpenBSD where
-		 * writes and mmaps are not consistent.
-		 */
-
-		/* We're ok if the mmap fails as we'll fallback to read/write */
-		tdb_mmap(tdb);
-	}
-
-	/* form a new freelist record */
-	memset(&rec,'\0',sizeof(rec));
-	rec.rec_len = size - sizeof(rec);
-
-	/* link it into the free list */
-	offset = tdb->map_size - size;
-	if (tdb_free(tdb, offset, &rec) == -1)
-		goto fail;
-
-	tdb_unlock(tdb, -1, F_WRLCK);
-	return 0;
- fail:
-	tdb_unlock(tdb, -1, F_WRLCK);
-	return -1;
-}
-
-/* allocate some space from the free list. The offset returned points
-   to a unconnected list_struct within the database with room for at
-   least length bytes of total data
-
-   0 is returned if the space could not be allocated
- */
-static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length,
-			    struct list_struct *rec)
-{
-	tdb_off rec_ptr, last_ptr, newrec_ptr;
-	struct list_struct newrec;
-
-	memset(&newrec, '\0', sizeof(newrec));
-
-	if (tdb_lock(tdb, -1, F_WRLCK) == -1)
-		return 0;
-
-	/* Extra bytes required for tailer */
-	length += sizeof(tdb_off);
-
- again:
-	last_ptr = FREELIST_TOP;
-
-	/* read in the freelist top */
-	if (ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
-		goto fail;
-
-	/* keep looking until we find a freelist record big enough */
-	while (rec_ptr) {
-		if (rec_free_read(tdb, rec_ptr, rec) == -1)
-			goto fail;
-
-		if (rec->rec_len >= length) {
-			/* found it - now possibly split it up  */
-			if (rec->rec_len > length + MIN_REC_SIZE) {
-				/* Length of left piece */
-				length = TDB_ALIGN(length, TDB_ALIGNMENT);
-
-				/* Right piece to go on free list */
-				newrec.rec_len = rec->rec_len
-					- (sizeof(*rec) + length);
-				newrec_ptr = rec_ptr + sizeof(*rec) + length;
-
-				/* And left record is shortened */
-				rec->rec_len = length;
-			} else
-				newrec_ptr = 0;
-
-			/* Remove allocated record from the free list */
-			if (ofs_write(tdb, last_ptr, &rec->next) == -1)
-				goto fail;
-
-			/* Update header: do this before we drop alloc
-                           lock, otherwise tdb_free() might try to
-                           merge with us, thinking we're free.
-                           (Thanks Jeremy Allison). */
-			rec->magic = TDB_MAGIC;
-			if (rec_write(tdb, rec_ptr, rec) == -1)
-				goto fail;
-
-			/* Did we create new block? */
-			if (newrec_ptr) {
-				/* Update allocated record tailer (we
-                                   shortened it). */
-				if (update_tailer(tdb, rec_ptr, rec) == -1)
-					goto fail;
-
-				/* Free new record */
-				if (tdb_free(tdb, newrec_ptr, &newrec) == -1)
-					goto fail;
-			}
-
-			/* all done - return the new record offset */
-			tdb_unlock(tdb, -1, F_WRLCK);
-			return rec_ptr;
-		}
-		/* move to the next record */
-		last_ptr = rec_ptr;
-		rec_ptr = rec->next;
-	}
-	/* we didn't find enough space. See if we can expand the
-	   database and if we can then try again */
-	if (tdb_expand(tdb, length + sizeof(*rec)) == 0)
-		goto again;
- fail:
-	tdb_unlock(tdb, -1, F_WRLCK);
-	return 0;
-}
-
-/* initialise a new database with a specified hash size */
-static int tdb_new_database(TDB_CONTEXT *tdb, int hash_size)
-{
-	struct tdb_header *newdb;
-	int size, ret = -1;
-
-	/* We make it up in memory, then write it out if not internal */
-	size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off);
-	if (!(newdb = calloc(size, 1)))
-		return TDB_ERRCODE(TDB_ERR_OOM, -1);
-
-	/* Fill in the header */
-	newdb->version = TDB_VERSION;
-	newdb->hash_size = hash_size;
-#ifdef USE_SPINLOCKS
-	newdb->rwlocks = size;
-#endif
-	if (tdb->flags & TDB_INTERNAL) {
-		tdb->map_size = size;
-		tdb->map_ptr = (char *)newdb;
-		memcpy(&tdb->header, newdb, sizeof(tdb->header));
-		/* Convert the `ondisk' version if asked. */
-		CONVERT(*newdb);
-		return 0;
-	}
-	if (lseek(tdb->fd, 0, SEEK_SET) == -1)
-		goto fail;
-
-	if (ftruncate(tdb->fd, 0) == -1)
-		goto fail;
-
-	/* This creates an endian-converted header, as if read from disk */
-	CONVERT(*newdb);
-	memcpy(&tdb->header, newdb, sizeof(tdb->header));
-	/* Don't endian-convert the magic food! */
-	memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
-	if (write(tdb->fd, newdb, size) != size)
-		ret = -1;
-	else
-		ret = tdb_create_rwlocks(tdb->fd, hash_size);
-
-  fail:
-	SAFE_FREE(newdb);
-	return ret;
-}
-
-/* Returns 0 on fail.  On success, return offset of record, and fills
-   in rec */
-static tdb_off tdb_find(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash,
-			struct list_struct *r)
-{
-	tdb_off rec_ptr;
-	
-	/* read in the hash top */
-	if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
-		return 0;
-
-	/* keep looking until we find the right record */
-	while (rec_ptr) {
-		if (rec_read(tdb, rec_ptr, r) == -1)
-			return 0;
-
-		if (!TDB_DEAD(r) && hash==r->full_hash && key.dsize==r->key_len) {
-			char *k;
-			/* a very likely hit - read the key */
-			k = tdb_alloc_read(tdb, rec_ptr + sizeof(*r), 
-					   r->key_len);
-			if (!k)
-				return 0;
-
-			if (memcmp(key.dptr, k, key.dsize) == 0) {
-				SAFE_FREE(k);
-				return rec_ptr;
-			}
-			SAFE_FREE(k);
-		}
-		rec_ptr = r->next;
-	}
-	return TDB_ERRCODE(TDB_ERR_NOEXIST, 0);
-}
-
-/* As tdb_find, but if you succeed, keep the lock */
-static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype,
-			     struct list_struct *rec)
-{
-	u32 rec_ptr;
-
-	if (tdb_lock(tdb, BUCKET(hash), locktype) == -1)
-		return 0;
-	if (!(rec_ptr = tdb_find(tdb, key, hash, rec)))
-		tdb_unlock(tdb, BUCKET(hash), locktype);
-	return rec_ptr;
-}
-
-enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb)
-{
-	return tdb->ecode;
-}
-
-static struct tdb_errname {
-	enum TDB_ERROR ecode; const char *estring;
-} emap[] = { {TDB_SUCCESS, "Success"},
-	     {TDB_ERR_CORRUPT, "Corrupt database"},
-	     {TDB_ERR_IO, "IO Error"},
-	     {TDB_ERR_LOCK, "Locking error"},
-	     {TDB_ERR_OOM, "Out of memory"},
-	     {TDB_ERR_EXISTS, "Record exists"},
-	     {TDB_ERR_NOLOCK, "Lock exists on other keys"},
-	     {TDB_ERR_NOEXIST, "Record does not exist"} };
-
-/* Error string for the last tdb error */
-const char *tdb_errorstr(TDB_CONTEXT *tdb)
-{
-	u32 i;
-	for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++)
-		if (tdb->ecode == emap[i].ecode)
-			return emap[i].estring;
-	return "Invalid error code";
-}
-
-/* update an entry in place - this only works if the new data size
-   is <= the old data size and the key exists.
-   on failure return -1.
-*/
-
-static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf)
-{
-	struct list_struct rec;
-	tdb_off rec_ptr;
-
-	/* find entry */
-	if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
-		return -1;
-
-	/* must be long enough key, data and tailer */
-	if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off)) {
-		tdb->ecode = TDB_SUCCESS; /* Not really an error */
-		return -1;
-	}
-
-	if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
-		      dbuf.dptr, dbuf.dsize) == -1)
-		return -1;
-
-	if (dbuf.dsize != rec.data_len) {
-		/* update size */
-		rec.data_len = dbuf.dsize;
-		return rec_write(tdb, rec_ptr, &rec);
-	}
- 
-	return 0;
-}
-
-/* find an entry in the database given a key */
-/* If an entry doesn't exist tdb_err will be set to
- * TDB_ERR_NOEXIST. If a key has no data attached
- * tdb_err will not be set. Both will return a
- * zero pptr and zero dsize.
- */
-
-TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-	tdb_off rec_ptr;
-	struct list_struct rec;
-	TDB_DATA ret;
-	u32 hash;
-
-	/* find which hash bucket it is in */
-	hash = tdb->hash_fn(&key);
-	if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
-		return tdb_null;
-
-	if (rec.data_len)
-		ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
-					  rec.data_len);
-	else
-		ret.dptr = NULL;
-	ret.dsize = rec.data_len;
-	tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
-	return ret;
-}
-
-/* check if an entry in the database exists 
-
-   note that 1 is returned if the key is found and 0 is returned if not found
-   this doesn't match the conventions in the rest of this module, but is
-   compatible with gdbm
-*/
-static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
-{
-	struct list_struct rec;
-	
-	if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
-		return 0;
-	tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);
-	return 1;
-}
-
-int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-	u32 hash = tdb->hash_fn(&key);
-	return tdb_exists_hash(tdb, key, hash);
-}
-
-/* record lock stops delete underneath */
-static int lock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
-	return off ? tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0) : 0;
-}
-/*
-  Write locks override our own fcntl readlocks, so check it here.
-  Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
-  an error to fail to get the lock here.
-*/
- 
-static int write_lock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
-	struct tdb_traverse_lock *i;
-	for (i = &tdb->travlocks; i; i = i->next)
-		if (i->off == off)
-			return -1;
-	return tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1);
-}
-
-/*
-  Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
-  an error to fail to get the lock here.
-*/
-
-static int write_unlock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
-	return tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0);
-}
-/* fcntl locks don't stack: avoid unlocking someone else's */
-static int unlock_record(TDB_CONTEXT *tdb, tdb_off off)
-{
-	struct tdb_traverse_lock *i;
-	u32 count = 0;
-
-	if (off == 0)
-		return 0;
-	for (i = &tdb->travlocks; i; i = i->next)
-		if (i->off == off)
-			count++;
-	return (count == 1 ? tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0) : 0);
-}
-
-/* actually delete an entry in the database given the offset */
-static int do_delete(TDB_CONTEXT *tdb, tdb_off rec_ptr, struct list_struct*rec)
-{
-	tdb_off last_ptr, i;
-	struct list_struct lastrec;
-
-	if (tdb->read_only) return -1;
-
-	if (write_lock_record(tdb, rec_ptr) == -1) {
-		/* Someone traversing here: mark it as dead */
-		rec->magic = TDB_DEAD_MAGIC;
-		return rec_write(tdb, rec_ptr, rec);
-	}
-	if (write_unlock_record(tdb, rec_ptr) != 0)
-		return -1;
-
-	/* find previous record in hash chain */
-	if (ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1)
-		return -1;
-	for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next)
-		if (rec_read(tdb, i, &lastrec) == -1)
-			return -1;
-
-	/* unlink it: next ptr is at start of record. */
-	if (last_ptr == 0)
-		last_ptr = TDB_HASH_TOP(rec->full_hash);
-	if (ofs_write(tdb, last_ptr, &rec->next) == -1)
-		return -1;
-
-	/* recover the space */
-	if (tdb_free(tdb, rec_ptr, rec) == -1)
-		return -1;
-	return 0;
-}
-
-/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */
-static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock,
-			 struct list_struct *rec)
-{
-	int want_next = (tlock->off != 0);
-
-	/* Lock each chain from the start one. */
-	for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
-
-		/* this is an optimisation for the common case where
-		   the hash chain is empty, which is particularly
-		   common for the use of tdb with ldb, where large
-		   hashes are used. In that case we spend most of our
-		   time in tdb_brlock(), locking empty hash chains.
-
-		   To avoid this, we do an unlocked pre-check to see
-		   if the hash chain is empty before starting to look
-		   inside it. If it is empty then we can avoid that
-		   hash chain. If it isn't empty then we can't believe
-		   the value we get back, as we read it without a
-		   lock, so instead we get the lock and re-fetch the
-		   value below.
-
-		   Notice that not doing this optimisation on the
-		   first hash chain is critical. We must guarantee
-		   that we have done at least one fcntl lock at the
-		   start of a search to guarantee that memory is
-		   coherent on SMP systems. If records are added by
-		   others during the search then thats OK, and we
-		   could possibly miss those with this trick, but we
-		   could miss them anyway without this trick, so the
-		   semantics don't change.
-
-		   With a non-indexed ldb search this trick gains us a
-		   factor of around 80 in speed on a linux 2.6.x
-		   system (testing using ldbtest).
-		 */
-		if (!tlock->off && tlock->hash != 0) {
-			u32 off;
-			if (tdb->map_ptr) {
-				for (;tlock->hash < tdb->header.hash_size;tlock->hash++) {
-					if (0 != *(u32 *)(TDB_HASH_TOP(tlock->hash) + (unsigned char *)tdb->map_ptr)) {
-						break;
-					}
-				}
-				if (tlock->hash == tdb->header.hash_size) {
-					continue;
-				}
-			} else {
-				if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash), &off) == 0 &&
-				    off == 0) {
-					continue;
-				}
-			}
-		}
-
-		if (tdb_lock(tdb, tlock->hash, F_WRLCK) == -1)
-			return -1;
-
-		/* No previous record?  Start at top of chain. */
-		if (!tlock->off) {
-			if (ofs_read(tdb, TDB_HASH_TOP(tlock->hash),
-				     &tlock->off) == -1)
-				goto fail;
-		} else {
-			/* Otherwise unlock the previous record. */
-			if (unlock_record(tdb, tlock->off) != 0)
-				goto fail;
-		}
-
-		if (want_next) {
-			/* We have offset of old record: grab next */
-			if (rec_read(tdb, tlock->off, rec) == -1)
-				goto fail;
-			tlock->off = rec->next;
-		}
-
-		/* Iterate through chain */
-		while( tlock->off) {
-			tdb_off current;
-			if (rec_read(tdb, tlock->off, rec) == -1)
-				goto fail;
-
-			/* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi at exanet.com>. */
-			if (tlock->off == rec->next) {
-				TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n"));
-				goto fail;
-			}
-
-			if (!TDB_DEAD(rec)) {
-				/* Woohoo: we found one! */
-				if (lock_record(tdb, tlock->off) != 0)
-					goto fail;
-				return tlock->off;
-			}
-
-			/* Try to clean dead ones from old traverses */
-			current = tlock->off;
-			tlock->off = rec->next;
-			if (!tdb->read_only && 
-			    do_delete(tdb, current, rec) != 0)
-				goto fail;
-		}
-		tdb_unlock(tdb, tlock->hash, F_WRLCK);
-		want_next = 0;
-	}
-	/* We finished iteration without finding anything */
-	return TDB_ERRCODE(TDB_SUCCESS, 0);
-
- fail:
-	tlock->off = 0;
-	if (tdb_unlock(tdb, tlock->hash, F_WRLCK) != 0)
-		TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n"));
-	return -1;
-}
-
-/* traverse the entire database - calling fn(tdb, key, data) on each element.
-   return -1 on error or the record count traversed
-   if fn is NULL then it is not called
-   a non-zero return value from fn() indicates that the traversal should stop
-  */
-int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private_val)
-{
-	TDB_DATA key, dbuf;
-	struct list_struct rec;
-	struct tdb_traverse_lock tl = { NULL, 0, 0 };
-	int ret, count = 0;
-
-	/* This was in the initializaton, above, but the IRIX compiler
-	 * did not like it.  crh
-	 */
-	tl.next = tdb->travlocks.next;
-
-	/* fcntl locks don't stack: beware traverse inside traverse */
-	tdb->travlocks.next = &tl;
-
-	/* tdb_next_lock places locks on the record returned, and its chain */
-	while ((ret = tdb_next_lock(tdb, &tl, &rec)) > 0) {
-		count++;
-		/* now read the full record */
-		key.dptr = tdb_alloc_read(tdb, tl.off + sizeof(rec), 
-					  rec.key_len + rec.data_len);
-		if (!key.dptr) {
-			ret = -1;
-			if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0)
-				goto out;
-			if (unlock_record(tdb, tl.off) != 0)
-				TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n"));
-			goto out;
-		}
-		key.dsize = rec.key_len;
-		dbuf.dptr = key.dptr + rec.key_len;
-		dbuf.dsize = rec.data_len;
-
-		/* Drop chain lock, call out */
-		if (tdb_unlock(tdb, tl.hash, F_WRLCK) != 0) {
-			ret = -1;
-			goto out;
-		}
-		if (fn && fn(tdb, key, dbuf, private_val)) {
-			/* They want us to terminate traversal */
-			ret = count;
-			if (unlock_record(tdb, tl.off) != 0) {
-				TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));;
-				ret = -1;
-			}
-			tdb->travlocks.next = tl.next;
-			SAFE_FREE(key.dptr);
-			return count;
-		}
-		SAFE_FREE(key.dptr);
-	}
-out:
-	tdb->travlocks.next = tl.next;
-	if (ret < 0)
-		return -1;
-	else
-		return count;
-}
-
-/* find the first entry in the database and return its key */
-TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb)
-{
-	TDB_DATA key;
-	struct list_struct rec;
-
-	/* release any old lock */
-	if (unlock_record(tdb, tdb->travlocks.off) != 0)
-		return tdb_null;
-	tdb->travlocks.off = tdb->travlocks.hash = 0;
-
-	if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0)
-		return tdb_null;
-	/* now read the key */
-	key.dsize = rec.key_len;
-	key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
-	if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0)
-		TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n"));
-	return key;
-}
-
-/* find the next entry in the database, returning its key */
-TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
-{
-	u32 oldhash;
-	TDB_DATA key = tdb_null;
-	struct list_struct rec;
-	char *k = NULL;
-
-	/* Is locked key the old key?  If so, traverse will be reliable. */
-	if (tdb->travlocks.off) {
-		if (tdb_lock(tdb,tdb->travlocks.hash,F_WRLCK))
-			return tdb_null;
-		if (rec_read(tdb, tdb->travlocks.off, &rec) == -1
-		    || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
-					    rec.key_len))
-		    || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) {
-			/* No, it wasn't: unlock it and start from scratch */
-			if (unlock_record(tdb, tdb->travlocks.off) != 0)
-				return tdb_null;
-			if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0)
-				return tdb_null;
-			tdb->travlocks.off = 0;
-		}
-
-		SAFE_FREE(k);
-	}
-
-	if (!tdb->travlocks.off) {
-		/* No previous element: do normal find, and lock record */
-		tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec);
-		if (!tdb->travlocks.off)
-			return tdb_null;
-		tdb->travlocks.hash = BUCKET(rec.full_hash);
-		if (lock_record(tdb, tdb->travlocks.off) != 0) {
-			TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno)));
-			return tdb_null;
-		}
-	}
-	oldhash = tdb->travlocks.hash;
-
-	/* Grab next record: locks chain and returned record,
-	   unlocks old record */
-	if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) {
-		key.dsize = rec.key_len;
-		key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
-					  key.dsize);
-		/* Unlock the chain of this new record */
-		if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0)
-			TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
-	}
-	/* Unlock the chain of old record */
-	if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0)
-		TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n"));
-	return key;
-}
-
-/* delete an entry in the database given a key */
-static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
-{
-	tdb_off rec_ptr;
-	struct list_struct rec;
-	int ret;
-
-	if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
-		return -1;
-	ret = do_delete(tdb, rec_ptr, &rec);
-	if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
-		TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n"));
-	return ret;
-}
-
-int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-	u32 hash = tdb->hash_fn(&key);
-	return tdb_delete_hash(tdb, key, hash);
-}
-
-/* store an element in the database, replacing any existing element
-   with the same key 
-
-   return 0 on success, -1 on failure
-*/
-int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
-{
-	struct list_struct rec;
-	u32 hash;
-	tdb_off rec_ptr;
-	char *p = NULL;
-	int ret = 0;
-
-	/* find which hash bucket it is in */
-	hash = tdb->hash_fn(&key);
-	if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
-		return -1;
-
-	/* check for it existing, on insert. */
-	if (flag == TDB_INSERT) {
-		if (tdb_exists_hash(tdb, key, hash)) {
-			tdb->ecode = TDB_ERR_EXISTS;
-			goto fail;
-		}
-	} else {
-		/* first try in-place update, on modify or replace. */
-		if (tdb_update_hash(tdb, key, hash, dbuf) == 0)
-			goto out;
-		if (tdb->ecode == TDB_ERR_NOEXIST &&
-		    flag == TDB_MODIFY) {
-			/* if the record doesn't exist and we are in TDB_MODIFY mode then
-			 we should fail the store */
-			goto fail;
-	}
-	}
-	/* reset the error code potentially set by the tdb_update() */
-	tdb->ecode = TDB_SUCCESS;
-
-	/* delete any existing record - if it doesn't exist we don't
-           care.  Doing this first reduces fragmentation, and avoids
-           coalescing with `allocated' block before it's updated. */
-	if (flag != TDB_INSERT)
-		tdb_delete_hash(tdb, key, hash);
-
-	/* Copy key+value *before* allocating free space in case malloc
-	   fails and we are left with a dead spot in the tdb. */
-
-	if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) {
-		tdb->ecode = TDB_ERR_OOM;
-		goto fail;
-	}
-
-	memcpy(p, key.dptr, key.dsize);
-	if (dbuf.dsize)
-		memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize);
-
-	/* we have to allocate some space */
-	if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec)))
-		goto fail;
-
-	/* Read hash top into next ptr */
-	if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
-		goto fail;
-
-	rec.key_len = key.dsize;
-	rec.data_len = dbuf.dsize;
-	rec.full_hash = hash;
-	rec.magic = TDB_MAGIC;
-
-	/* write out and point the top of the hash chain at it */
-	if (rec_write(tdb, rec_ptr, &rec) == -1
-	    || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
-	    || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
-		/* Need to tdb_unallocate() here */
-		goto fail;
-	}
- out:
-	SAFE_FREE(p); 
-	tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
-	return ret;
-fail:
-	ret = -1;
-	goto out;
-}
-
-/* Attempt to append data to an entry in place - this only works if the new data size
-   is <= the old data size and the key exists.
-   on failure return -1. Record must be locked before calling.
-*/
-static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf)
-{
-	struct list_struct rec;
-	tdb_off rec_ptr;
-
-	/* find entry */
-	if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
-		return -1;
-
-	/* Append of 0 is always ok. */
-	if (new_dbuf.dsize == 0)
-		return 0;
-
-	/* must be long enough for key, old data + new data and tailer */
-	if (rec.rec_len < key.dsize + rec.data_len + new_dbuf.dsize + sizeof(tdb_off)) {
-		/* No room. */
-		tdb->ecode = TDB_SUCCESS; /* Not really an error */
-		return -1;
-	}
-
-	if (tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len + rec.data_len,
-		      new_dbuf.dptr, new_dbuf.dsize) == -1)
-		return -1;
-
-	/* update size */
-	rec.data_len += new_dbuf.dsize;
-	return rec_write(tdb, rec_ptr, &rec);
-}
-
-/* Append to an entry. Create if not exist. */
-
-int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
-{
-	struct list_struct rec;
-	u32 hash;
-	tdb_off rec_ptr;
-	char *p = NULL;
-	int ret = 0;
-	size_t new_data_size = 0;
-
-	/* find which hash bucket it is in */
-	hash = tdb->hash_fn(&key);
-	if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
-		return -1;
-
-	/* first try in-place. */
-	if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0)
-		goto out;
-
-	/* reset the error code potentially set by the tdb_append_inplace() */
-	tdb->ecode = TDB_SUCCESS;
-
-	/* find entry */
-	if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) {
-		if (tdb->ecode != TDB_ERR_NOEXIST)
-			goto fail;
-
-		/* Not found - create. */
-
-		ret = tdb_store(tdb, key, new_dbuf, TDB_INSERT);
-		goto out;
-	}
-
-	new_data_size = rec.data_len + new_dbuf.dsize;
-
-	/* Copy key+old_value+value *before* allocating free space in case malloc
-	   fails and we are left with a dead spot in the tdb. */
-
-	if (!(p = (char *)malloc(key.dsize + new_data_size))) {
-		tdb->ecode = TDB_ERR_OOM;
-		goto fail;
-	}
-
-	/* Copy the key in place. */
-	memcpy(p, key.dptr, key.dsize);
-
-	/* Now read the old data into place. */
-	if (rec.data_len &&
-		tdb_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, p + key.dsize, rec.data_len, 0) == -1)
-			goto fail;
-
-	/* Finally append the new data. */
-	if (new_dbuf.dsize)
-		memcpy(p+key.dsize+rec.data_len, new_dbuf.dptr, new_dbuf.dsize);
-
-	/* delete any existing record - if it doesn't exist we don't
-           care.  Doing this first reduces fragmentation, and avoids
-           coalescing with `allocated' block before it's updated. */
-
-	tdb_delete_hash(tdb, key, hash);
-
-	if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec)))
-		goto fail;
-
-	/* Read hash top into next ptr */
-	if (ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
-		goto fail;
-
-	rec.key_len = key.dsize;
-	rec.data_len = new_data_size;
-	rec.full_hash = hash;
-	rec.magic = TDB_MAGIC;
-
-	/* write out and point the top of the hash chain at it */
-	if (rec_write(tdb, rec_ptr, &rec) == -1
-	    || tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+new_data_size)==-1
-	    || ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
-		/* Need to tdb_unallocate() here */
-		goto fail;
-	}
-
- out:
-	SAFE_FREE(p); 
-	tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
-	return ret;
-
-fail:
-	ret = -1;
-	goto out;
-}
-
-static int tdb_already_open(dev_t device,
-			    ino_t ino)
-{
-	TDB_CONTEXT *i;
-	
-	for (i = tdbs; i; i = i->next) {
-		if (i->device == device && i->inode == ino) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-/* This is based on the hash algorithm from gdbm */
-static u32 default_tdb_hash(TDB_DATA *key)
-{
-	u32 value;	/* Used to compute the hash value.  */
-	u32   i;	/* Used to cycle through random values. */
-
-	/* Set the initial value from the key size. */
-	for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
-		value = (value + (key->dptr[i] << (i*5 % 24)));
-
-	return (1103515243 * value + 12345);  
-}
-
-/* open the database, creating it if necessary 
-
-   The open_flags and mode are passed straight to the open call on the
-   database file. A flags value of O_WRONLY is invalid. The hash size
-   is advisory, use zero for a default value.
-
-   Return is NULL on error, in which case errno is also set.  Don't 
-   try to call tdb_error or tdb_errname, just do strerror(errno).
-
-   @param name may be NULL for internal databases. */
-TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
-		      int open_flags, mode_t mode)
-{
-	return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
-}
-
-
-TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
-			 int open_flags, mode_t mode,
-			 tdb_log_func log_fn,
-			 tdb_hash_func hash_fn)
-{
-	TDB_CONTEXT *tdb;
-	struct stat st;
-	int rev = 0, locked = 0;
-	unsigned char *vp;
-	u32 vertest;
-
-	if (!(tdb = calloc(1, sizeof *tdb))) {
-		/* Can't log this */
-		errno = ENOMEM;
-		goto fail;
-	}
-	tdb->fd = -1;
-	tdb->name = NULL;
-	tdb->map_ptr = NULL;
-	tdb->flags = tdb_flags;
-	tdb->open_flags = open_flags;
-	tdb->log_fn = log_fn;
-	tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
-
-	if ((open_flags & O_ACCMODE) == O_WRONLY) {
-		TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n",
-			 name));
-		errno = EINVAL;
-		goto fail;
-	}
-	
-	if (hash_size == 0)
-		hash_size = DEFAULT_HASH_SIZE;
-	if ((open_flags & O_ACCMODE) == O_RDONLY) {
-		tdb->read_only = 1;
-		/* read only databases don't do locking or clear if first */
-		tdb->flags |= TDB_NOLOCK;
-		tdb->flags &= ~TDB_CLEAR_IF_FIRST;
-	}
-
-	/* internal databases don't mmap or lock, and start off cleared */
-	if (tdb->flags & TDB_INTERNAL) {
-		tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP);
-		tdb->flags &= ~TDB_CLEAR_IF_FIRST;
-		if (tdb_new_database(tdb, hash_size) != 0) {
-			TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!"));
-			goto fail;
-		}
-		goto internal;
-	}
-
-	if ((tdb->fd = open(name, open_flags, mode)) == -1) {
-		TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n",
-			 name, strerror(errno)));
-		goto fail;	/* errno set by open(2) */
-	}
-
-	/* ensure there is only one process initialising at once */
-	if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) {
-		TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n",
-			 name, strerror(errno)));
-		goto fail;	/* errno set by tdb_brlock */
-	}
-
-	/* we need to zero database if we are the only one with it open */
-	if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
-		(locked = (tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) {
-		open_flags |= O_CREAT;
-		if (ftruncate(tdb->fd, 0) == -1) {
-			TDB_LOG((tdb, 0, "tdb_open_ex: "
-				 "failed to truncate %s: %s\n",
-				 name, strerror(errno)));
-			goto fail; /* errno set by ftruncate */
-		}
-	}
-
-	if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
-	    || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0
-	    || (tdb->header.version != TDB_VERSION
-		&& !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) {
-		/* its not a valid database - possibly initialise it */
-		if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) {
-			errno = EIO; /* ie bad format or something */
-			goto fail;
-		}
-		rev = (tdb->flags & TDB_CONVERT);
-	}
-	vp = (unsigned char *)&tdb->header.version;
-	vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) |
-		  (((u32)vp[2]) << 8) | (u32)vp[3];
-	tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0;
-	if (!rev)
-		tdb->flags &= ~TDB_CONVERT;
-	else {
-		tdb->flags |= TDB_CONVERT;
-		convert(&tdb->header, sizeof(tdb->header));
-	}
-	if (fstat(tdb->fd, &st) == -1)
-		goto fail;
-
-	/* Is it already in the open list?  If so, fail. */
-	if (tdb_already_open(st.st_dev, st.st_ino)) {
-		TDB_LOG((tdb, 2, "tdb_open_ex: "
-			 "%s (%d,%d) is already open in this process\n",
-			 name, (int)st.st_dev, (int)st.st_ino));
-		errno = EBUSY;
-		goto fail;
-	}
-
-	if (!(tdb->name = (char *)strdup(name))) {
-		errno = ENOMEM;
-		goto fail;
-	}
-
-	tdb->map_size = st.st_size;
-	tdb->device = st.st_dev;
-	tdb->inode = st.st_ino;
-	tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0]));
-	if (!tdb->locked) {
-		TDB_LOG((tdb, 2, "tdb_open_ex: "
-			 "failed to allocate lock structure for %s\n",
-			 name));
-		errno = ENOMEM;
-		goto fail;
-	}
-	tdb_mmap(tdb);
-	if (locked) {
-		if (!tdb->read_only)
-			if (tdb_clear_spinlocks(tdb) != 0) {
-				TDB_LOG((tdb, 0, "tdb_open_ex: "
-				"failed to clear spinlock\n"));
-				goto fail;
-			}
-		if (tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) {
-			TDB_LOG((tdb, 0, "tdb_open_ex: "
-				 "failed to take ACTIVE_LOCK on %s: %s\n",
-				 name, strerror(errno)));
-			goto fail;
-		}
-
-	}
-
-	/* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
-	   we didn't get the initial exclusive lock as we need to let all other
-	   users know we're using it. */
-
-	if (tdb_flags & TDB_CLEAR_IF_FIRST) {
-		/* leave this lock in place to indicate it's in use */
-		if (tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)
-			goto fail;
-	}
-
-
- internal:
-	/* Internal (memory-only) databases skip all the code above to
-	 * do with disk files, and resume here by releasing their
-	 * global lock and hooking into the active list. */
-	if (tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0) == -1)
-		goto fail;
-	tdb->next = tdbs;
-	tdbs = tdb;
-	return tdb;
-
- fail:
-	{ int save_errno = errno;
-
-	if (!tdb)
-		return NULL;
-	
-	if (tdb->map_ptr) {
-		if (tdb->flags & TDB_INTERNAL)
-			SAFE_FREE(tdb->map_ptr);
-		else
-			tdb_munmap(tdb);
-	}
-	SAFE_FREE(tdb->name);
-	if (tdb->fd != -1)
-		if (close(tdb->fd) != 0)
-			TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n"));
-	SAFE_FREE(tdb->locked);
-	SAFE_FREE(tdb);
-	errno = save_errno;
-	return NULL;
-	}
-}
-
-/**
- * Close a database.
- *
- * @returns -1 for error; 0 for success.
- **/
-int tdb_close(TDB_CONTEXT *tdb)
-{
-	TDB_CONTEXT **i;
-	int ret = 0;
-
-	if (tdb->map_ptr) {
-		if (tdb->flags & TDB_INTERNAL)
-			SAFE_FREE(tdb->map_ptr);
-		else
-			tdb_munmap(tdb);
-	}
-	SAFE_FREE(tdb->name);
-	if (tdb->fd != -1)
-		ret = close(tdb->fd);
-	SAFE_FREE(tdb->locked);
-
-	/* Remove from contexts list */
-	for (i = &tdbs; *i; i = &(*i)->next) {
-		if (*i == tdb) {
-			*i = tdb->next;
-			break;
-		}
-	}
-
-	memset(tdb, 0, sizeof(*tdb));
-	SAFE_FREE(tdb);
-
-	return ret;
-}
-
-/* lock/unlock entire database */
-int tdb_lockall(TDB_CONTEXT *tdb)
-{
-	u32 i;
-
-	/* There are no locks on read-only dbs */
-	if (tdb->read_only)
-		return TDB_ERRCODE(TDB_ERR_LOCK, -1);
-	for (i = 0; i < tdb->header.hash_size; i++) 
-		if (tdb_lock(tdb, i, F_WRLCK))
-			break;
-
-	/* If error, release locks we have... */
-	if (i < tdb->header.hash_size) {
-		u32 j;
-
-		for ( j = 0; j < i; j++)
-			tdb_unlock(tdb, j, F_WRLCK);
-		return TDB_ERRCODE(TDB_ERR_NOLOCK, -1);
-	}
-
-	return 0;
-}
-void tdb_unlockall(TDB_CONTEXT *tdb)
-{
-	u32 i;
-	for (i=0; i < tdb->header.hash_size; i++)
-		tdb_unlock(tdb, i, F_WRLCK);
-}
-
-/* lock/unlock one hash chain. This is meant to be used to reduce
-   contention - it cannot guarantee how many records will be locked */
-int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-	return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
-}
-
-int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-	return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
-}
-
-int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-	return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
-}
-
-int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
-{
-	return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
-}
-
-
-/* register a loging function */
-void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , const char *, ...))
-{
-	tdb->log_fn = fn;
-}
-
-/* reopen a tdb - this can be used after a fork to ensure that we have an independent
-   seek pointer from our parent and to re-establish locks */
-int tdb_reopen(TDB_CONTEXT *tdb)
-{
-	struct stat st;
-
-	if (tdb->flags & TDB_INTERNAL)
-		return 0; /* Nothing to do. */
-	if (tdb_munmap(tdb) != 0) {
-		TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno)));
-		goto fail;
-	}
-	if (close(tdb->fd) != 0)
-		TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n"));
-	tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
-	if (tdb->fd == -1) {
-		TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno)));
-		goto fail;
-	}
-	if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
-			(tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) {
-		TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n"));
-		goto fail;
-	}
-	if (fstat(tdb->fd, &st) != 0) {
-		TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
-		goto fail;
-	}
-	if (st.st_ino != tdb->inode || st.st_dev != tdb->device) {
-		TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n"));
-		goto fail;
-	}
-	tdb_mmap(tdb);
-
-	return 0;
-
-fail:
-	tdb_close(tdb);
-	return -1;
-}
-
-/* reopen all tdb's */
-int tdb_reopen_all(void)
-{
-	TDB_CONTEXT *tdb;
-
-	for (tdb=tdbs; tdb; tdb = tdb->next) {
-		if (tdb_reopen(tdb) != 0)
-			return -1;
-	}
-
-	return 0;
-}
diff --git a/tdb/tdb.h b/tdb/tdb.h
deleted file mode 100644
index 84b83dc..0000000
--- a/tdb/tdb.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 1999-2004 Andrew Tridgell <tridge at linuxcare.com>
- * Copyright (c) 2005      Benedikt Meurer <benny at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * This file was originally part of the tdb library, which in turn is
- * part of the Samba suite, a Unix SMB/CIFS implementation.
- */
-
-#ifndef __TDB_H__
-#define __TDB_H__
-
-#include <tdb/tdbconfig.h>
-
-#include <signal.h>
-#include <unistd.h>
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-#ifndef PRINTF_ATTRIBUTE
-/** Use gcc attribute to check printf fns.  a1 is the 1-based index of
- * the parameter containing the format, and a2 the index of the first
- * argument. Note that some gcc 2.x versions don't handle this
- * properly **/
-#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 )
-#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
-#else
-#define PRINTF_ATTRIBUTE(a1, a2)
-#endif
-#endif
-
-/* flags to tdb_store() */
-#define TDB_REPLACE 1
-#define TDB_INSERT 2
-#define TDB_MODIFY 3
-
-/* flags for tdb_open() */
-#define TDB_DEFAULT 0 /* just a readability place holder */
-#define TDB_CLEAR_IF_FIRST 1
-#define TDB_INTERNAL 2 /* don't store on disk */
-#define TDB_NOLOCK   4 /* don't do any locking */
-#define TDB_NOMMAP   8 /* don't use mmap */
-#define TDB_CONVERT 16 /* convert endian (internal use) */
-#define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */
-
-#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)
-
-/* error codes */
-enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, 
-		TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
-		TDB_ERR_NOEXIST};
-
-typedef struct {
-	char *dptr;
-	size_t dsize;
-} TDB_DATA;
-
-typedef u32 tdb_len;
-typedef u32 tdb_off;
-
-/* this is stored at the front of every database */
-struct tdb_header {
-	char magic_food[32]; /* for /etc/magic */
-	u32 version; /* version of the code */
-	u32 hash_size; /* number of hash entries */
-	tdb_off rwlocks;
-	tdb_off reserved[31];
-};
-
-struct tdb_lock_type {
-	u32 count;
-	u32 ltype;
-};
-
-struct tdb_traverse_lock {
-	struct tdb_traverse_lock *next;
-	u32 off;
-	u32 hash;
-};
-
-/* this is the context structure that is returned from a db open */
-typedef struct tdb_context {
-	char *name; /* the name of the database */
-	void *map_ptr; /* where it is currently mapped */
-	int fd; /* open file descriptor for the database */
-	tdb_len map_size; /* how much space has been mapped */
-	int read_only; /* opened read-only */
-	struct tdb_lock_type *locked; /* array of chain locks */
-	enum TDB_ERROR ecode; /* error code for last tdb error */
-	struct tdb_header header; /* a cached copy of the header */
-	u32 flags; /* the flags passed to tdb_open */
-	struct tdb_traverse_lock travlocks; /* current traversal locks */
-	struct tdb_context *next; /* all tdbs to avoid multiple opens */
-	dev_t device;	/* uniquely identifies this tdb */
-	ino_t inode;	/* uniquely identifies this tdb */
-	void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */
-	u32 (*hash_fn)(TDB_DATA *key);
-	int open_flags; /* flags used in the open - needed by reopen */
-} TDB_CONTEXT;
-
-typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
-typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...);
-typedef u32 (*tdb_hash_func)(TDB_DATA *key);
-
-TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
-		      int open_flags, mode_t mode);
-TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
-			 int open_flags, mode_t mode,
-			 tdb_log_func log_fn,
-			 tdb_hash_func hash_fn);
-
-int tdb_reopen(TDB_CONTEXT *tdb);
-int tdb_reopen_all(void);
-void tdb_logging_function(TDB_CONTEXT *tdb, tdb_log_func);
-enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb);
-const char *tdb_errorstr(TDB_CONTEXT *tdb);
-TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
-int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf);
-int tdb_close(TDB_CONTEXT *tdb);
-TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
-TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *);
-int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_lockall(TDB_CONTEXT *tdb);
-void tdb_unlockall(TDB_CONTEXT *tdb);
-
-/* Low level locking functions: use with care */
-void tdb_set_lock_alarm(sig_atomic_t *palarm);
-int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key);
-
-/* Debug functions. Not used in production. */
-void tdb_dump_all(TDB_CONTEXT *tdb);
-int tdb_printfreelist(TDB_CONTEXT *tdb);
-
-extern TDB_DATA tdb_null;
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif /* !__TDB_H__ */
diff --git a/tdb/tdbconfig.h.in b/tdb/tdbconfig.h.in
deleted file mode 100644
index 8150346..0000000
--- a/tdb/tdbconfig.h.in
+++ /dev/null
@@ -1,34 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 2005 Benedikt Meurer <benny at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __TDBCONFIG_H__
-#define __TDBCONFIG_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef @TDB_U32_TYPE@ u32;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__TDBCONFIG_H__ */
diff --git a/tdb/tdbspeed.c b/tdb/tdbspeed.c
deleted file mode 100644
index 74b091d..0000000
--- a/tdb/tdbspeed.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 1999-2004 Andrew Tridgell <tridge at linuxcare.com>
- * Copyright (c) 2005      Benedikt Meurer <benny at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * This file was originally part of the tdb library, which in turn is
- * part of the Samba suite, a Unix SMB/CIFS implementation.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-
-#include <tdb/tdb.h>
-
-/* Turn off if error returns from TDB are sane (before v1.0.2) */
-#if 1
-#define TDB_ERROR(tdb, code) ((tdb)->ecode == code)
-#else
-#define TDB_ERROR(tdb, code) 1
-#endif
-/* a test program for tdb - the trivial database */
-
-static TDB_DATA *randdata, *randkeys;
-
-#define DELETE_PROB 7
-#define STORE_PROB 5
-
-static TDB_CONTEXT *db;
-
-struct timeval tp1,tp2;
-
-static void start_timer()
-{
-	gettimeofday(&tp1,NULL);
-}
-
-static double end_timer()
-{
-	gettimeofday(&tp2,NULL);
-	return((tp2.tv_sec - tp1.tv_sec) + 
-	       (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
-}
-
-static void fatal(TDB_CONTEXT *tdb, const char *why)
-{
-	perror(why);
-	if (tdb) fprintf(stderr, "TDB: (%u)\n", tdb->ecode);
-	exit(1);
-}
-
-static char *randbuf(int len)
-{
-	char *buf;
-	int i;
-	buf = (char *)malloc(len+1);
-
-	for (i=0;i<len;i++) {
-		buf[i] = 'a' + (rand() % 26);
-	}
-	buf[i] = 0;
-	return buf;
-}
-
-static void addrec_db(int i)
-{
-	TDB_DATA key, data;
-
-	key.dptr = randkeys[i].dptr;
-	key.dsize = randkeys[i].dsize+1;
-
-	data.dptr = randdata[i].dptr;
-	data.dsize = randdata[i].dsize+1;
-
-	if (rand() % DELETE_PROB == 0) {
-		if (tdb_delete(db, key) == -1
-		    && !TDB_ERROR(db, TDB_ERR_NOEXIST))
-			fatal(db, "tdb_delete failed");
-	} else if (rand() % STORE_PROB == 0) {
-		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
-			fatal(db, "tdb_store failed");
-		}
-	} else {
-		data = tdb_fetch(db, key);
-		if (data.dptr) free(data.dptr);
-		else {
-			if (db->ecode && !TDB_ERROR(db,TDB_ERR_NOEXIST))
-				fatal(db, "tdb_fetch failed");
-		}
-	}
-}
-
-struct db_size {
-	const char *name;
-	int size;
-} db_sizes[]
-= { { "default", 0 },
-    { "307", 307 },
-    { "512", 512 },
-    { "1024", 1024 },
-    { "4096", 4096 },
-    { "16384", 16384 },
-    { "65536", 65536 } };
-
-unsigned int num_loops[]  /* 10,000 each */
-= { 1, 5, 25 };
-
-struct tdb_flag {
-	const char *name;
-	int flags;
-} tdb_flags[]
-= { { "normal", TDB_CLEAR_IF_FIRST },
-#ifdef TDB_CONVERT
-    { "byte-reversed", TDB_CLEAR_IF_FIRST|TDB_CONVERT }
-#endif
-};
-
-int main(int argc, char *argv[])
-{
-	int i, j, seed=0;
-	int k;
-
-	/* Precook random buffers */
-	randdata = malloc(10000 * sizeof(randdata[0]));
-	randkeys = malloc(10000 * sizeof(randkeys[0]));
-
-	srand(seed);
-	for (i=0;i<10000;i++) {
-		randkeys[i].dsize = 1 + (rand() % 4);
-		randdata[i].dsize = 1 + (rand() % 100);
-		randkeys[i].dptr = randbuf(randkeys[i].dsize);
-		randdata[i].dptr = randbuf(randdata[i].dsize);
-	}
-
-	for (k = 0; k < sizeof(tdb_flags)/sizeof(struct tdb_flag); k++) {
-		printf("Operations per second for %s database:\n",
-		       tdb_flags[k].name);
-
-		printf("Hashsize:   ");
-		for (i = 0; i < sizeof(db_sizes)/sizeof(struct db_size); i++)
-			printf("%-8s ", db_sizes[i].name);
-		printf("\n");
-		
-		for (i = 0; i < sizeof(num_loops)/sizeof(int); i++) {
-			printf("%7u:    ", num_loops[i]*10000);
-			for (j = 0; j < sizeof(db_sizes)/sizeof(struct db_size); j++) {
-				unsigned int l = 0, l2;
-				db = tdb_open("test.tdb", db_sizes[j].size,
-					      tdb_flags[k].flags,
-					      O_RDWR | O_CREAT | O_TRUNC, 0600);
-				srand(seed);
-				start_timer();
-				for (l2=0; l2 < num_loops[i]; l2++)
-					for (l=0;l<10000;l++) addrec_db(l);
-				printf("%-7u  ", (int)(l*l2/end_timer()));
-				tdb_close(db);
-			}
-			printf("\n");
-		}
-		printf("\n");
-	}
-	return 0;
-}
diff --git a/tdb/tdbtool.c b/tdb/tdbtool.c
deleted file mode 100644
index d537dee..0000000
--- a/tdb/tdbtool.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 1999-2000 Andrew Tridgell
- * Copyright (c) 2000      Paul `Rusty' Russell
- * Copyright (c) 2000      Jeremy Allison
- * Copyright (c) 2001      Andrew Esh
- * Copyright (c) 2005      Benedikt Meurer <benny at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * This file was originally part of the tdb library, which in turn is
- * part of the Samba suite, a Unix SMB/CIFS implementation.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <tdb/tdb.h>
-
-/* a tdb tool for manipulating a tdb database */
-
-#define FSTRING_LEN 256
-typedef char fstring[FSTRING_LEN];
-
-typedef struct connections_key {
-  pid_t pid;
-  int cnum;
-  fstring name;
-} connections_key;
-
-typedef struct connections_data {
-  int magic;
-  pid_t pid;
-  int cnum;
-  uid_t uid;
-  gid_t gid;
-  char name[24];
-  char addr[24];
-  char machine[128];
-  time_t start;
-} connections_data;
-
-static TDB_CONTEXT *tdb;
-FILE *pDumpFile;
-
-static int print_rec(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state);
-
-static char *get_token(int startover)
-{
-        static char tmp[1024];
-  static char *cont = NULL;
-  char *insert, *start;
-  char *k = strtok(NULL, " ");
-
-  if (!k)
-    return NULL;
-
-  if (startover)
-    start = tmp;
-  else
-    start = cont;
-
-  strcpy(start, k);
-  insert = start + strlen(start) - 1;
-  while (*insert == '\\') {
-    *insert++ = ' ';
-    k = strtok(NULL, " ");
-    if (!k)
-      break;
-    strcpy(insert, k);
-    insert = start + strlen(start) - 1;
-  }
-
-  /* Get ready for next call */
-  cont = start + strlen(start) + 1;
-  return start;
-}
-
-static int open_dump_file()
-{
-  int retval = 0;
-  char *tok = get_token(0);
-  if (!tok) {
-    pDumpFile = stdout;
-  } else {
-    pDumpFile = fopen(tok, "w");
-    
-    if (pDumpFile == NULL) {
-      printf("File Open Failed! --  %s", tok);
-      retval = 1;
-    } else {
-      printf("Writing to file: %s\n", tok);
-    }
-  }
-    return(retval);
-}
-
-static void close_dump_file()
-{
-  if(pDumpFile != NULL && pDumpFile != stdout) {
-    fclose(pDumpFile);
-  }
-}
-
- static void print_asc(unsigned char *buf,int len)
-{
-  int i;
-
-  /* We're probably printing ASCII strings so don't try to display
-     the trailing NULL character. */
-
-  if (buf[len - 1] == 0)
-          len--;
-
-  for (i=0;i<len;i++)
-    fprintf(pDumpFile,"%c",isprint(buf[i])?buf[i]:'.');
-}
-
-static void print_data(unsigned char *buf,int len)
-{
-  int i=0;
-  if (len<=0) return;
-  fprintf(pDumpFile,"[%03X] ",i);
-  for (i=0;i<len;) {
-    fprintf(pDumpFile,"%02X ",(int)buf[i]);
-    i++;
-    if (i%8 == 0) fprintf(pDumpFile," ");
-    if (i%16 == 0) {      
-      print_asc(&buf[i-16],8); fprintf(pDumpFile," ");
-      print_asc(&buf[i-8],8); fprintf(pDumpFile,"\n");
-      if (i<len) fprintf(pDumpFile,"[%03X] ",i);
-    }
-  }
-  if (i%16) {
-    int n;
-    
-    n = 16 - (i%16);
-    fprintf(pDumpFile," ");
-    if (n>8) fprintf(pDumpFile," ");
-    while (n--) fprintf(pDumpFile,"   ");
-    
-    n = i%16;
-    if (n > 8) n = 8;
-    print_asc(&buf[i-(i%16)],n); fprintf(pDumpFile," ");
-    n = (i%16) - n;
-    if (n>0) print_asc(&buf[i-n],n); 
-    fprintf(pDumpFile,"\n");    
-  }
-}
-
-static void help(void)
-{
-  printf(
-"tdbtool:\n"
-"  create    dbname     : create a database\n"
-"  open      dbname     : open an existing database\n"
-"  erase                : erase the database\n"
-"  dump      dumpname   : dump the database as strings\n"
-"  insert    key  data  : insert a record\n"
-"  store     key  data  : store a record (replace)\n"
-"  show      key        : show a record by key\n"
-"  delete    key        : delete a record by key\n"
-"  list                 : print the database hash table and freelist\n"
-"  free                 : print the database freelist\n"
-"  1 | first            : print the first record\n"
-"  n | next             : print the next record\n"
-"  q | quit             : terminate\n"
-"  \\n                   : repeat 'next' command\n");
-}
-
-static void terror(char *why)
-{
-  printf("%s\n", why);
-}
-
-static void create_tdb(void)
-{
-  char *tok = get_token(1);
-  if (!tok) {
-    help();
-    return;
-  }
-  if (tdb) tdb_close(tdb);
-  tdb = tdb_open(tok, 0, TDB_CLEAR_IF_FIRST,
-           O_RDWR | O_CREAT | O_TRUNC, 0600);
-  if (!tdb) {
-    printf("Could not create %s: %s\n", tok, strerror(errno));
-  }
-}
-
-static void open_tdb(void)
-{
-  char *tok = get_token(1);
-  if (!tok) {
-    help();
-    return;
-  }
-  if (tdb) tdb_close(tdb);
-  tdb = tdb_open(tok, 0, 0, O_RDWR, 0600);
-  if (!tdb) {
-    printf("Could not open %s: %s\n", tok, strerror(errno));
-  }
-}
-
-static void insert_tdb(void)
-{
-  char *k = get_token(1);
-  char *d = get_token(0);
-  TDB_DATA key, dbuf;
-
-  if (!k || !d) {
-    help();
-    return;
-  }
-
-  key.dptr = k;
-  key.dsize = strlen(k)+1;
-  dbuf.dptr = d;
-  dbuf.dsize = strlen(d)+1;
-
-  if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) {
-    terror("insert failed");
-  }
-}
-
-static void store_tdb(void)
-{
-  char *k = get_token(1);
-  char *d = get_token(0);
-  TDB_DATA key, dbuf;
-
-  if (!k || !d) {
-    help();
-    return;
-  }
-
-  key.dptr = k;
-  key.dsize = strlen(k)+1;
-  dbuf.dptr = d;
-  dbuf.dsize = strlen(d)+1;
-
-  printf("Storing key:\n");
-  print_rec(tdb, key, dbuf, NULL);
-
-  if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
-    terror("store failed");
-  }
-}
-
-static void show_tdb(void)
-{
-  char *k = get_token(1);
-  TDB_DATA key, dbuf;
-
-  if (!k) {
-    help();
-    return;
-  }
-
-  key.dptr = k;
-  key.dsize = strlen(k)+1;
-
-  dbuf = tdb_fetch(tdb, key);
-  if (!dbuf.dptr) {
-    terror("fetch failed");
-    return;
-  }
-  /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
-  print_rec(tdb, key, dbuf, NULL);
-}
-
-static void delete_tdb(void)
-{
-  char *k = get_token(1);
-  TDB_DATA key;
-
-  if (!k) {
-    help();
-    return;
-  }
-
-  key.dptr = k;
-  key.dsize = strlen(k)+1;
-
-  if (tdb_delete(tdb, key) != 0) {
-    terror("delete failed");
-  }
-}
-
-static int print_rec(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
-{
-  fprintf(pDumpFile,"\nkey %u bytes\n", (unsigned) key.dsize);
-  print_asc((unsigned char*)key.dptr, key.dsize);
-  fprintf(pDumpFile,"\ndata %u bytes\n", (unsigned) dbuf.dsize);
-  print_data((unsigned char*)dbuf.dptr, dbuf.dsize);
-  return 0;
-}
-
-static int print_key(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
-{
-  print_asc((unsigned char*)key.dptr, key.dsize);
-  printf("\n");
-  return 0;
-}
-
-static int total_bytes;
-
-static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
-{
-  total_bytes += dbuf.dsize;
-  return 0;
-}
-
-static void info_tdb(void)
-{
-  int count;
-  total_bytes = 0;
-  if ((count = tdb_traverse(tdb, traverse_fn, NULL) == -1))
-    printf("Error = %s\n", tdb_errorstr(tdb));
-  else
-    printf("%d records totalling %d bytes\n", count, total_bytes);
-}
-
-static char *tdb_getline(char *prompt)
-{
-  static char line[1024];
-  char *p;
-  fputs(prompt, stdout);
-  line[0] = 0;
-  p = fgets(line, sizeof(line)-1, stdin);
-  if (p) p = strchr(p, '\n');
-  if (p) *p = 0;
-  pDumpFile = stdout;
-  return p?line:NULL;
-}
-
-static int do_delete_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf,
-                     void *state)
-{
-    return tdb_delete(tdb, key);
-}
-
-static void first_record(TDB_CONTEXT *tdb, TDB_DATA *pkey)
-{
-  TDB_DATA dbuf;
-  *pkey = tdb_firstkey(tdb);
-  
-  dbuf = tdb_fetch(tdb, *pkey);
-  if (!dbuf.dptr) terror("fetch failed");
-  /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
-  print_rec(tdb, *pkey, dbuf, NULL);
-}
-
-static void next_record(TDB_CONTEXT *tdb, TDB_DATA *pkey)
-{
-  TDB_DATA dbuf;
-  *pkey = tdb_nextkey(tdb, *pkey);
-  
-  dbuf = tdb_fetch(tdb, *pkey);
-  if (!dbuf.dptr) 
-    terror("fetch failed");
-  else
-    /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */
-    print_rec(tdb, *pkey, dbuf, NULL);
-}
-
-int main(int argc, char *argv[])
-{
-    int bIterate = 0;
-    char *line;
-    char *tok;
-  TDB_DATA iterate_kbuf;
-
-    if (argv[1]) {
-  static char tmp[1024];
-        sprintf(tmp, "open %s", argv[1]);
-        tok=strtok(tmp," ");
-        open_tdb();
-    }
-
-    while ((line = tdb_getline("tdb> "))) {
-
-        /* Shell command */
-        
-        if (line[0] == '!') {
-            system(line + 1);
-            continue;
-        }
-        
-        if ((tok = strtok(line," "))==NULL) {
-           if (bIterate)
-              next_record(tdb, &iterate_kbuf);
-           continue;
-        }
-        if (strcmp(tok,"create") == 0) {
-            bIterate = 0;
-            create_tdb();
-            continue;
-        } else if (strcmp(tok,"open") == 0) {
-            open_tdb();
-            continue;
-        } else if ((strcmp(tok, "q") == 0) ||
-                   (strcmp(tok, "quit") == 0)) {
-            break;
-  }
-            
-        /* all the rest require a open database */
-        if (!tdb) {
-            bIterate = 0;
-            terror("database not open");
-            help();
-            continue;
-        }
-            
-        if (strcmp(tok,"insert") == 0) {
-            bIterate = 0;
-            insert_tdb();
-        } else if (strcmp(tok,"store") == 0) {
-            bIterate = 0;
-            store_tdb();
-        } else if (strcmp(tok,"show") == 0) {
-            bIterate = 0;
-            show_tdb();
-        } else if (strcmp(tok,"erase") == 0) {
-            bIterate = 0;
-            tdb_traverse(tdb, do_delete_fn, NULL);
-        } else if (strcmp(tok,"delete") == 0) {
-            bIterate = 0;
-            delete_tdb();
-        } else if (strcmp(tok,"dump") == 0) {
-            bIterate = 0;
-      if(open_dump_file() == 0) { //open file
-        tdb_traverse(tdb, print_rec, NULL);
-        close_dump_file(); //close file
-      }
-      pDumpFile = stdout;
-        } else if (strcmp(tok,"list") == 0) {
-            tdb_dump_all(tdb);
-        } else if (strcmp(tok, "free") == 0) {
-            tdb_printfreelist(tdb);
-        } else if (strcmp(tok,"info") == 0) {
-            info_tdb();
-        } else if ( (strcmp(tok, "1") == 0) ||
-                    (strcmp(tok, "first") == 0)) {
-            bIterate = 1;
-            first_record(tdb, &iterate_kbuf);
-        } else if ((strcmp(tok, "n") == 0) ||
-                   (strcmp(tok, "next") == 0)) {
-            next_record(tdb, &iterate_kbuf);
-        } else if ((strcmp(tok, "keys") == 0)) {
-                bIterate = 0;
-                tdb_traverse(tdb, print_key, NULL);
-        } else {
-            help();
-        }
-    }
-
-    if (tdb) tdb_close(tdb);
-
-    return 0;
-}
diff --git a/tdb/tdbtorture.c b/tdb/tdbtorture.c
deleted file mode 100644
index c2fe916..0000000
--- a/tdb/tdbtorture.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 1999-2004 Andrew Tridgell <tridge at linuxcare.com>
- * Copyright (c) 2005      Benedikt Meurer <benny at xfce.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * This file was originally part of the tdb library, which in turn is
- * part of the Samba suite, a Unix SMB/CIFS implementation.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_MMAN_h
-#include <sys/mman.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <tdb/tdb.h>
-
-/* this tests tdb by doing lots of ops from several simultaneous
-   writers - that stresses the locking code. Build with TDB_DEBUG=1
-   for best effect */
-
-
-
-#define REOPEN_PROB 30
-#define DELETE_PROB 8
-#define STORE_PROB 4
-#define APPEND_PROB 6
-#define LOCKSTORE_PROB 0
-#define TRAVERSE_PROB 20
-#define CULL_PROB 100
-#define KEYLEN 3
-#define DATALEN 100
-#define LOCKLEN 20
-
-static TDB_CONTEXT *db;
-
-static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
-{
-	va_list ap;
-    
-	va_start(ap, format);
-	vfprintf(stdout, format, ap);
-	va_end(ap);
-	fflush(stdout);
-#if 0
-	{
-		char *ptr;
-		asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid());
-		system(ptr);
-		free(ptr);
-	}
-#endif	
-}
-
-static void fatal(char *why)
-{
-	perror(why);
-	exit(1);
-}
-
-static char *randbuf(int len)
-{
-	char *buf;
-	int i;
-	buf = (char *)malloc(len+1);
-
-	for (i=0;i<len;i++) {
-		buf[i] = 'a' + (rand() % 26);
-	}
-	buf[i] = 0;
-	return buf;
-}
-
-static int cull_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf,
-			 void *state)
-{
-	if (random() % CULL_PROB == 0) {
-		tdb_delete(tdb, key);
-	}
-	return 0;
-}
-
-static void addrec_db(void)
-{
-	int klen, dlen, slen;
-	char *k, *d, *s;
-	TDB_DATA key, data, lockkey;
-
-	klen = 1 + (rand() % KEYLEN);
-	dlen = 1 + (rand() % DATALEN);
-	slen = 1 + (rand() % LOCKLEN);
-
-	k = randbuf(klen);
-	d = randbuf(dlen);
-	s = randbuf(slen);
-
-	key.dptr = k;
-	key.dsize = klen+1;
-
-	data.dptr = d;
-	data.dsize = dlen+1;
-
-	lockkey.dptr = s;
-	lockkey.dsize = slen+1;
-
-#if REOPEN_PROB
-	if (random() % REOPEN_PROB == 0) {
-		tdb_reopen_all();
-		goto next;
-	} 
-#endif
-
-#if DELETE_PROB
-	if (random() % DELETE_PROB == 0) {
-		tdb_delete(db, key);
-		goto next;
-	}
-#endif
-
-#if STORE_PROB
-	if (random() % STORE_PROB == 0) {
-		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
-			fatal("tdb_store failed");
-		}
-		goto next;
-	}
-#endif
-
-#if APPEND_PROB
-	if (random() % APPEND_PROB == 0) {
-		if (tdb_append(db, key, data) != 0) {
-			fatal("tdb_append failed");
-		}
-		goto next;
-	}
-#endif
-
-#if LOCKSTORE_PROB
-	if (random() % LOCKSTORE_PROB == 0) {
-		tdb_chainlock(db, lockkey);
-		data = tdb_fetch(db, key);
-		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
-			fatal("tdb_store failed");
-		}
-		if (data.dptr) free(data.dptr);
-		tdb_chainunlock(db, lockkey);
-		goto next;
-	} 
-#endif
-
-#if TRAVERSE_PROB
-	if (random() % TRAVERSE_PROB == 0) {
-		tdb_traverse(db, cull_traverse, NULL);
-		goto next;
-	}
-#endif
-
-	data = tdb_fetch(db, key);
-	if (data.dptr) free(data.dptr);
-
-next:
-	free(k);
-	free(d);
-	free(s);
-}
-
-static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf,
-                       void *state)
-{
-	tdb_delete(tdb, key);
-	return 0;
-}
-
-#ifndef NPROC
-#define NPROC 6
-#endif
-
-#ifndef NLOOPS
-#define NLOOPS 200000
-#endif
-
-int main(int argc, char *argv[])
-{
-	int i, seed=0;
-	int loops = NLOOPS;
-	pid_t pids[NPROC];
-
-	pids[0] = getpid();
-
-	for (i=0;i<NPROC-1;i++) {
-		if ((pids[i+1]=fork()) == 0) break;
-	}
-
-	db = tdb_open("torture.tdb", 2, TDB_CLEAR_IF_FIRST, 
-		      O_RDWR | O_CREAT, 0600);
-	if (!db) {
-		fatal("db open failed");
-	}
-	tdb_logging_function(db, tdb_log);
-
-	srand(seed + getpid());
-	srandom(seed + getpid() + time(NULL));
-	for (i=0;i<loops;i++) addrec_db();
-
-	tdb_traverse(db, NULL, NULL);
-	tdb_traverse(db, traverse_fn, NULL);
-	tdb_traverse(db, traverse_fn, NULL);
-
-	tdb_close(db);
-
-	if (getpid() == pids[0]) {
-		for (i=0;i<NPROC-1;i++) {
-			int status;
-			if (waitpid(pids[i+1], &status, 0) != pids[i+1]) {
-				printf("failed to wait for %d\n",
-				       (int)pids[i+1]);
-				exit(1);
-			}
-			if (WEXITSTATUS(status) != 0) {
-				printf("child %d exited with status %d\n",
-				       (int)pids[i+1], WEXITSTATUS(status));
-				exit(1);
-			}
-		}
-		printf("OK\n");
-	}
-
-	return 0;
-}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ebc3613..d274410 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,19 +1,51 @@
-# $Id$
-#
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
+# 
+# Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library 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 Library General Public License for more details.
+# 
+# You should have received a copy of the GNU Library General 
+# Public License along with this library; if not, write to the 
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
 
 INCLUDES =								\
 	-I$(top_srcdir)							\
-	-DG_LOG_DOMAIN=\"libxfce4menu-tests\"
+	-DG_LOG_DOMAIN=\"gdesktopmenu-tests\"
 
 TESTS =									\
+	test-menu-parser						\
 	test-menu-spec							\
 	test-display-menu
 
 check_PROGRAMS =							\
+	test-menu-parser						\
 	test-menu-spec							\
 	test-display-menu
 
+test_menu_parser_SOURCES =						\
+	test-menu-parser.c
+
+test_menu_parser_CFLAGS =						\
+	$(LIBXFCE4UTIL_CFLAGS)						\
+	$(GLIB_CFLAGS)
+
+test_menu_parser_DEPENDENCIES =						\
+	$(top_builddir)/gdesktopmenu/libgdesktopmenu-$(GDESKTOPMENU_VERSION_API).la
+
+test_menu_parser_LDADD =						\
+	$(LIBXFCE4UTIL_LIBS)						\
+	$(GLIB_LIBS)							\
+	$(top_builddir)/gdesktopmenu/libgdesktopmenu-$(GDESKTOPMENU_VERSION_API).la
+
 test_menu_spec_SOURCES =						\
 	test-menu-spec.c
 
@@ -22,12 +54,12 @@ test_menu_spec_CFLAGS =							\
 	$(GLIB_CFLAGS)
 
 test_menu_spec_DEPENDENCIES =						\
-	$(top_builddir)/libxfce4menu/libxfce4menu-$(LIBXFCE4MENU_VERSION_API).la
+	$(top_builddir)/gdesktopmenu/libgdesktopmenu-$(GDESKTOPMENU_VERSION_API).la
 
 test_menu_spec_LDADD =							\
 	$(LIBXFCE4UTIL_LIBS)						\
 	$(GLIB_LIBS)							\
-	$(top_builddir)/libxfce4menu/libxfce4menu-$(LIBXFCE4MENU_VERSION_API).la
+	$(top_builddir)/gdesktopmenu/libgdesktopmenu-$(GDESKTOPMENU_VERSION_API).la
 
 test_display_menu_SOURCES =						\
 	test-display-menu.c
@@ -38,11 +70,11 @@ test_display_menu_CFLAGS =						\
 	$(GLIB_CFLAGS)
 
 test_display_menu_DEPENDENCIES =					\
-	$(top_builddir)/libxfce4menu/libxfce4menu-$(LIBXFCE4MENU_VERSION_API).la
+	$(top_builddir)/gdesktopmenu/libgdesktopmenu-$(GDESKTOPMENU_VERSION_API).la
 
 test_display_menu_LDADD =						\
 	$(LIBXFCE4UTIL_LIBS)						\
 	$(GTK_LIBS)							\
 	$(GLIB_LIBS)							\
-	$(top_builddir)/libxfce4menu/libxfce4menu-$(LIBXFCE4MENU_VERSION_API).la
+	$(top_builddir)/gdesktopmenu/libgdesktopmenu-$(GDESKTOPMENU_VERSION_API).la
 
diff --git a/tests/test-display-menu.c b/tests/test-display-menu.c
index f361d37..230274f 100644
--- a/tests/test-display-menu.c
+++ b/tests/test-display-menu.c
@@ -33,9 +33,10 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <glib/gprintf.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
 
-#include <libxfce4util/libxfce4util.h>
-#include <libxfce4menu/libxfce4menu.h>
+#include <gdesktopmenu/gdesktopmenu.h>
 
 
 
@@ -45,7 +46,7 @@
 
 
 /* Root menu */
-static XfceMenu *root = NULL;
+static GDesktopMenu *root = NULL;
 
 
 
@@ -55,32 +56,44 @@ static guint pseudo_monitor_handler = 0;
 
 
 static gpointer
-monitor_file (XfceMenu    *menu,
-              const gchar *filename,
-              gpointer     user_data)
+monitor_file (GDesktopMenu *menu,
+              const gchar  *filename,
+              gpointer      user_data)
 {
-  g_debug ("%s: monitoring file %s => %d", xfce_menu_element_get_name (XFCE_MENU_ELEMENT (menu)), filename, ++pseudo_monitor_handler);
+#if 0
+  g_debug ("%s: monitoring file %s => %d", 
+           g_desktop_menu_element_get_name (G_DESKTOP_MENU_ELEMENT (menu)), 
+           filename, ++pseudo_monitor_handler);
+#endif
   return GUINT_TO_POINTER (pseudo_monitor_handler);
 }
 
 
 
 static gpointer
-monitor_directory (XfceMenu    *menu,
-                   const gchar *filename,
-                   gpointer     user_data)
+monitor_directory (GDesktopMenu *menu,
+                   const gchar  *filename,
+                   gpointer      user_data)
 {
-  g_debug ("%s: monitoring directory %s => %d", xfce_menu_element_get_name (XFCE_MENU_ELEMENT (menu)), filename, ++pseudo_monitor_handler);
+#if 0
+  g_debug ("%s: monitoring directory %s => %d", 
+           g_desktop_menu_element_get_name (G_DESKTOP_MENU_ELEMENT (menu)), 
+           filename, ++pseudo_monitor_handler);
+#endif
   return GUINT_TO_POINTER (pseudo_monitor_handler);
 }
 
 
 
 static void
-remove_monitor (XfceMenu *menu,
-                gpointer  monitor_handle)
+remove_monitor (GDesktopMenu *menu,
+                gpointer      monitor_handle)
 {
-  g_debug ("%s: removing monitor %d", xfce_menu_element_get_name (XFCE_MENU_ELEMENT (menu)), GPOINTER_TO_UINT (monitor_handle));
+#if 0
+  g_debug ("%s: removing monitor %d", 
+           g_desktop_menu_element_get_name (G_DESKTOP_MENU_ELEMENT (menu)), 
+           GPOINTER_TO_UINT (monitor_handle));
+#endif
 }
 
 
@@ -88,21 +101,21 @@ remove_monitor (XfceMenu *menu,
 static void
 initialize_monitoring (void)
 {
-  XfceMenuMonitorVTable vtable = { 
-      monitor_file,
-      monitor_directory,
-      remove_monitor,
+  GDesktopMenuMonitorVTable vtable = { 
+    monitor_file,
+    monitor_directory,
+    remove_monitor,
   };
 
   /* Pass VTable to the menu library */
-  xfce_menu_monitor_set_vtable (&vtable, NULL);
+  g_desktop_menu_monitor_set_vtable (&vtable, NULL);
 }
 
 
 
 static void
-execute_item_command (GtkWidget    *widget,
-                      XfceMenuItem *item)
+execute_item_command (GtkWidget        *widget,
+                      GDesktopMenuItem *item)
 {
 #if 0
   GError      *error = NULL;
@@ -111,15 +124,16 @@ execute_item_command (GtkWidget    *widget,
   gboolean     terminal;
   gboolean     startup_notification;
 
-  command = xfce_menu_item_get_command (item);
-  terminal = xfce_menu_item_requires_terminal (item);
-  startup_notification = xfce_menu_item_supports_startup_notification (item);
+  command = g_desktop_menu_item_get_command (item);
+  terminal = g_desktop_menu_item_requires_terminal (item);
+  startup_notification = g_desktop_menu_item_supports_startup_notification (item);
 
   if (G_UNLIKELY (command == NULL))
     return;
 
 #if 0
-  if (!xfce_exec_on_screen (gdk_screen_get_default (), command, terminal, startup_notification, &error))
+  if (!xfce_exec_on_screen (gdk_screen_get_default (), command, terminal, 
+                            startup_notification, &error))
     {
       xfce_err (error->message);
       g_error_free (error);
@@ -130,7 +144,7 @@ execute_item_command (GtkWidget    *widget,
 
 
 static GdkPixbuf*
-create_item_icon (XfceMenuItem *item)
+create_item_icon (GDesktopMenuItem *item)
 {
   GdkPixbuf    *icon = NULL;
   GtkIconTheme *icon_theme;
@@ -144,8 +158,8 @@ create_item_icon (XfceMenuItem *item)
   /* Get current icon theme */
   icon_theme = gtk_icon_theme_get_default ();
 
-  item_name = xfce_menu_element_get_name (XFCE_MENU_ELEMENT (item));
-  icon_name = xfce_menu_element_get_icon_name (XFCE_MENU_ELEMENT (item));
+  item_name = g_desktop_menu_element_get_name (G_DESKTOP_MENU_ELEMENT (item));
+  icon_name = g_desktop_menu_element_get_icon_name (G_DESKTOP_MENU_ELEMENT (item));
 
   if (icon_name == NULL)
     return NULL;
@@ -204,8 +218,8 @@ create_item_icon (XfceMenuItem *item)
 
 
 static void
-create_item_widgets (XfceMenuItem *item, 
-                     GtkWidget    *parent_menu)
+create_item_widgets (GDesktopMenuItem *item, 
+                     GtkWidget        *parent_menu)
 {
   GtkWidget *gtk_item;
   GtkWidget *image;
@@ -219,7 +233,7 @@ create_item_widgets (XfceMenuItem *item,
   else
     image = gtk_image_new_from_icon_name ("applications-other", ICON_SIZE);
 
-  gtk_item = gtk_image_menu_item_new_with_label (xfce_menu_element_get_name (XFCE_MENU_ELEMENT (item)));
+  gtk_item = gtk_image_menu_item_new_with_label (g_desktop_menu_element_get_name (G_DESKTOP_MENU_ELEMENT (item)));
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (gtk_item), image);
   gtk_menu_shell_append (GTK_MENU_SHELL (parent_menu), gtk_item);
   gtk_widget_show (gtk_item);
@@ -231,58 +245,55 @@ create_item_widgets (XfceMenuItem *item,
 
 
 static void
-create_menu_widgets (GtkWidget *gtk_menu, 
-                     XfceMenu  *menu)
+create_menu_widgets (GtkWidget    *gtk_menu, 
+                     GDesktopMenu *menu)
 {
-  XfceMenuDirectory *directory;
-  XfceMenu          *submenu;
-  GtkIconTheme      *icon_theme;
-  GtkWidget         *gtk_item;
-  GtkWidget         *gtk_submenu;
-  GtkWidget         *image;
-  GdkPixbuf         *icon;
-  GSList            *iter;
-  GSList            *items;
-  const gchar       *display_name;
-  const gchar       *icon_name;
+  GDesktopMenuDirectory *directory;
+  GDesktopMenu          *submenu;
+  GtkIconTheme          *icon_theme;
+  GtkWidget             *gtk_item;
+  GtkWidget             *gtk_submenu;
+  GtkWidget             *image;
+  GdkPixbuf             *icon;
+  GList                 *iter;
+  GList                 *items;
+  const gchar           *display_name;
+  const gchar           *icon_name;
 
   /* Get current icon theme */
   icon_theme = gtk_icon_theme_get_default ();
 
   /* Get submenus and items based on the menu layout */
-  if (G_UNLIKELY (xfce_menu_has_layout (menu)))
-    items = xfce_menu_get_layout_elements (menu);
-  else
-    {
-      items = xfce_menu_get_menus (menu);
-      items = g_slist_concat (items, xfce_menu_get_items (menu));
-    }
+  items = g_desktop_menu_get_elements (menu);
 
   /* Iterate over menu items */
-  for (iter = items; iter != NULL; iter = g_slist_next (iter))
+  for (iter = items; iter != NULL; iter = g_list_next (iter))
     {
-      if (XFCE_IS_MENU_ITEM (iter->data))
+      if (!g_desktop_menu_element_get_visible (iter->data))
+        continue;
+
+      if (G_IS_DESKTOP_MENU_ITEM (iter->data))
         {
           /* Add menu item to the menu */
-          create_item_widgets (XFCE_MENU_ITEM (iter->data), gtk_menu);
+          create_item_widgets (G_DESKTOP_MENU_ITEM (iter->data), gtk_menu);
         }
-      else if (XFCE_IS_MENU_SEPARATOR (iter->data))
+      else if (G_IS_DESKTOP_MENU_SEPARATOR (iter->data))
         {
           /* Add separator to the menu */
           gtk_item = gtk_separator_menu_item_new ();
           gtk_menu_shell_append (GTK_MENU_SHELL (gtk_menu), gtk_item);
           gtk_widget_show (gtk_item);
         }
-      else if (XFCE_IS_MENU (iter->data))
+      else if (G_IS_DESKTOP_MENU (iter->data))
         {
-          submenu = XFCE_MENU (iter->data);
-          directory = xfce_menu_get_directory (submenu);
+          submenu = G_DESKTOP_MENU (iter->data);
+          directory = g_desktop_menu_get_directory (submenu);
 
           /* Determine display name */
-          display_name = xfce_menu_element_get_name (XFCE_MENU_ELEMENT (submenu));
+          display_name = g_desktop_menu_element_get_name (G_DESKTOP_MENU_ELEMENT (submenu));
 
           /* Determine icon name */
-          icon_name = xfce_menu_element_get_icon_name (XFCE_MENU_ELEMENT (submenu));
+          icon_name = g_desktop_menu_element_get_icon_name (G_DESKTOP_MENU_ELEMENT (submenu));
           if (icon_name == NULL)
             icon_name = "applications-other";
 
@@ -314,7 +325,7 @@ create_menu_widgets (GtkWidget *gtk_menu,
     }
 
   /* Free menu item list */
-  g_slist_free (items);
+  g_list_free (items);
 }
 
 
@@ -350,7 +361,7 @@ create_main_window (void)
 
   /* Create main window */
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  gtk_window_set_title (GTK_WINDOW (window), _("XfceMenu: Display Menu Test"));
+  gtk_window_set_title (GTK_WINDOW (window), _("GDesktopMenu: Display Menu Test"));
   gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
   gtk_container_set_border_width (GTK_CONTAINER (window), 12);
   gtk_widget_show (window);
@@ -376,11 +387,11 @@ int
 main (int    argc,
       char **argv)
 {
-  GError *error     = NULL;
+  GError *error = NULL;
   gint    exit_code = EXIT_SUCCESS;
 
   /* Initialize the menu library */
-  xfce_menu_init ("XFCE");
+  g_desktop_menu_init ("XFCE");
 
   /* Set up menu monitoring */
   initialize_monitoring ();
@@ -390,12 +401,12 @@ main (int    argc,
 
   /* Try to load the menu */
   if (G_UNLIKELY (g_strv_length (argv) > 1))
-    root = xfce_menu_new (argv[1], &error);
+    root = g_desktop_menu_new (argv[1]);
   else
-    root = xfce_menu_get_root (&error);
+    root = g_desktop_menu_new_applications ();
 
   /* Check if the menu was loaded */
-  if (G_LIKELY (root != NULL))
+  if (G_LIKELY (g_desktop_menu_load (root, NULL, &error)))
     {
       /* Create main window */
       create_main_window ();
@@ -408,12 +419,17 @@ main (int    argc,
     }
   else
     {
-      g_error (error->message);
+      gchar *uri;
+
+      uri = g_file_get_uri (g_desktop_menu_get_file (root));
+      g_error ("Could not load menu from %s: %s", uri, error->message);
+      g_free (uri);
+
       exit_code = EXIT_FAILURE;
     }
 
   /* Shut down the menu library */
-  xfce_menu_shutdown ();
+  g_desktop_menu_shutdown ();
 
   return exit_code;
 }
diff --git a/tests/test-menu-parser.c b/tests/test-menu-parser.c
new file mode 100644
index 0000000..0492370
--- /dev/null
+++ b/tests/test-menu-parser.c
@@ -0,0 +1,306 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <glib.h>
+
+#include <gdesktopmenu/gdesktopmenu.h>
+
+
+
+#define FILENAME "/etc/xdg/menus/applications.menu"
+
+
+
+static gboolean print_node (GNode *node, 
+                            gint   depth);
+
+
+
+const gchar *
+node_name (GNode *node)
+{
+  switch (g_desktop_menu_node_tree_get_node_type (node))
+    {
+      case G_DESKTOP_MENU_NODE_TYPE_MENU: return "Menu"; break;
+      case G_DESKTOP_MENU_NODE_TYPE_INCLUDE: return "Include"; break;
+      case G_DESKTOP_MENU_NODE_TYPE_EXCLUDE: return "Exclude"; break;
+      case G_DESKTOP_MENU_NODE_TYPE_OR: return "Or"; break;
+      case G_DESKTOP_MENU_NODE_TYPE_AND: return "And"; break;
+      case G_DESKTOP_MENU_NODE_TYPE_NOT: return "Not"; break;
+      case G_DESKTOP_MENU_NODE_TYPE_MOVE: return "Move"; break;
+      case G_DESKTOP_MENU_NODE_TYPE_LAYOUT: return "Layout"; break;
+      default: return NULL; break;
+    }
+}
+
+
+
+static void
+print_child_nodes (GNode *node,
+                   gint   depth)
+{
+  GNode *child;
+
+  for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
+    {
+      g_node_traverse (child, G_PRE_ORDER, G_TRAVERSE_ALL, 1, 
+                       (GNodeTraverseFunc) print_node, GINT_TO_POINTER (depth+2));
+    }
+}
+
+
+
+static gboolean
+print_node (GNode *node,
+            gint   depth)
+{
+  gint i;
+
+#define INDENT {for (i = 0; i < depth; ++i) g_print (" ");}
+
+  if (G_UNLIKELY (g_desktop_menu_node_tree_get_node_type (node) == G_DESKTOP_MENU_NODE_TYPE_MENU ||
+                  g_desktop_menu_node_tree_get_node_type (node) == G_DESKTOP_MENU_NODE_TYPE_INCLUDE ||
+                  g_desktop_menu_node_tree_get_node_type (node) == G_DESKTOP_MENU_NODE_TYPE_EXCLUDE ||
+                  g_desktop_menu_node_tree_get_node_type (node) == G_DESKTOP_MENU_NODE_TYPE_OR ||
+                  g_desktop_menu_node_tree_get_node_type (node) == G_DESKTOP_MENU_NODE_TYPE_AND ||
+                  g_desktop_menu_node_tree_get_node_type (node) == G_DESKTOP_MENU_NODE_TYPE_NOT ||
+                  g_desktop_menu_node_tree_get_node_type (node) == G_DESKTOP_MENU_NODE_TYPE_MOVE ||
+                  g_desktop_menu_node_tree_get_node_type (node) == G_DESKTOP_MENU_NODE_TYPE_LAYOUT))
+    {
+      INDENT; g_print ("<%s>\n", node_name (node));
+      print_child_nodes (node, depth);
+      INDENT; g_print ("</%s>\n", node_name (node));
+    }
+  else
+    {
+      switch (g_desktop_menu_node_tree_get_node_type (node))
+        {
+        case G_DESKTOP_MENU_NODE_TYPE_NAME:
+          INDENT; g_print ("<Name>%s</Name>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_DIRECTORY:
+          INDENT; g_print ("<Directory>%s</Directory>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_DIRECTORY_DIR:
+          INDENT; g_print ("<DirectoryDir>%s</DirectoryDir>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS:
+          INDENT; g_print ("<DefaultDirectoryDirs/>\n");
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_APP_DIR:
+          INDENT; g_print ("<AppDir>%s</AppDir>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_DEFAULT_APP_DIRS:
+          INDENT; g_print ("<DefaultAppDirs/>\n");
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_ONLY_UNALLOCATED:
+          INDENT; g_print ("<OnlyUnallocated/>\n");
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED:
+          INDENT; g_print ("<NotOnlyUnallocated/>\n");
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_DELETED:
+          INDENT; g_print ("<Deleted/>\n");
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_NOT_DELETED:
+          INDENT; g_print ("<NotDeleted/>\n");
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_FILENAME:
+          INDENT; g_print ("<Filename>%s</Filename>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_CATEGORY:
+          INDENT; g_print ("<Category>%s</Category>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_OLD:
+          INDENT; g_print ("<Old>%s</Old>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_NEW:
+          INDENT; g_print ("<New>%s</New>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_MENUNAME:
+          INDENT; g_print ("<Menuname>%s</Menuname>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_SEPARATOR:
+          INDENT; g_print ("<Separator/>\n");
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_MERGE:
+          INDENT; 
+          switch (g_desktop_menu_node_tree_get_layout_merge_type (node))
+            {
+            case G_DESKTOP_MENU_LAYOUT_MERGE_ALL:
+              g_print ("<Merge type=\"all\"/>\n");
+              break;
+            case G_DESKTOP_MENU_LAYOUT_MERGE_MENUS:
+              g_print ("<Merge type=\"menus\"/>\n");
+              break;
+            case G_DESKTOP_MENU_LAYOUT_MERGE_FILES:
+              g_print ("<Merge type=\"files\"/>\n");
+              break;
+            }
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_MERGE_FILE:
+          INDENT;
+          switch (g_desktop_menu_node_tree_get_merge_file_type (node))
+            {
+            case G_DESKTOP_MENU_MERGE_FILE_PATH:
+              g_print ("<MergeFile type=\"path\">%s</MergeFile>\n", 
+                       g_desktop_menu_node_tree_get_merge_file_filename (node));
+              break;
+            case G_DESKTOP_MENU_MERGE_FILE_PARENT:
+              g_print ("<MergeFile type=\"parent\"/>\n");
+              break;
+            }
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_MERGE_DIR:
+          INDENT; g_print ("<MergeDir>%s</MergeDir>\n", g_desktop_menu_node_tree_get_string (node));
+          break;
+        case G_DESKTOP_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS:
+          INDENT; g_print ("<DefaultMergeDirs/>\n");
+          break;
+        default:
+          break;
+        }
+    }
+
+  return FALSE;
+}
+
+
+
+void
+print_tree (GDesktopMenuTreeProvider *provider)
+{
+  GNode *tree;
+
+  g_return_if_fail (G_IS_DESKTOP_MENU_TREE_PROVIDER (provider));
+
+  tree = g_desktop_menu_tree_provider_get_tree (provider);
+  print_node (tree, 0);
+  g_desktop_menu_node_tree_free (tree);
+}
+
+
+
+static const gchar ROOT_SPECS[][30] = 
+{
+  "menus/applications.menu",
+  "menus/xfce-applications.menu",
+  "menus/gnome-applications.menu",
+  "menus/kde-applications.menu",
+};
+
+
+
+int
+main (int    argc,
+      char **argv)
+{
+  GDesktopMenuParser *parser;
+  GDesktopMenuMerger *merger;
+  GError             *error = NULL;
+  GFile              *file = NULL;
+  gchar              *filename;
+  gint                result = EXIT_SUCCESS;
+  gint                n;
+
+  if (!g_thread_supported ())
+    g_thread_init (NULL);
+
+  g_desktop_menu_init ("XFCE");
+
+  if (argc > 1)
+    file = g_file_new_for_path (argv[1]);
+  else
+    {
+      /* Search for a usable root menu file */
+      for (n = 0; n < G_N_ELEMENTS (ROOT_SPECS) && file == NULL; ++n)
+        {
+          /* Search for the root menu file */
+          filename = g_desktop_menu_config_lookup (ROOT_SPECS[n]);
+          if (G_UNLIKELY (filename == NULL))
+            continue;
+
+          /* Try to load the root menu from this file */
+          file = g_file_new_for_path (filename);
+          g_free (filename);
+
+          if (!g_file_query_exists (file, NULL))
+            {
+              g_object_unref (file);
+              file = NULL;
+            }
+        }
+    }
+
+  parser = g_desktop_menu_parser_new (file);
+  g_object_unref (file);
+  
+  if (G_LIKELY (g_desktop_menu_parser_run (parser, NULL, &error)))
+    {
+      print_tree (G_DESKTOP_MENU_TREE_PROVIDER (parser));
+
+      merger = g_desktop_menu_merger_new (G_DESKTOP_MENU_TREE_PROVIDER (parser));
+
+      if (G_LIKELY (g_desktop_menu_merger_run (merger, NULL, &error)))
+        {
+          g_print ("\n\n");
+          print_tree (G_DESKTOP_MENU_TREE_PROVIDER (merger));
+        }
+      else
+        {
+          if (error != NULL)
+            {
+              g_error ("Could not merge menus in %s: %s", 
+                       argc > 1 ? argv[1] : FILENAME, 
+                       error->message);
+
+              g_error_free (error);
+            }
+
+          result = EXIT_FAILURE;
+        }
+
+      g_object_unref (merger);
+    }
+  else
+    {
+      if (error != NULL)
+        {
+          g_error ("Could not parse %s: %s", argc > 1 ? argv[1] : FILENAME, error->message);
+          g_error_free (error);
+        }
+
+      result = EXIT_FAILURE;
+    }
+
+  g_object_unref (parser);
+
+  g_desktop_menu_shutdown ();
+
+  return result;
+}
diff --git a/tests/test-menu-spec.c b/tests/test-menu-spec.c
index f5514bd..911d2e6 100644
--- a/tests/test-menu-spec.c
+++ b/tests/test-menu-spec.c
@@ -30,54 +30,69 @@
 
 #include <glib/gprintf.h>
 
-#include <libxfce4util/libxfce4util.h>
-#include <libxfce4menu/libxfce4menu.h>
+#include <gdesktopmenu/gdesktopmenu.h>
 
 
 
 void
-print_menu (XfceMenu *menu, gboolean is_root)
+print_menu (GDesktopMenu *menu, 
+            const gchar  *path)
 {
-  XfceMenuDirectory *directory;
-  GSList            *menus;
-  GSList            *items;
-  GSList            *iter;
-  const gchar       *name;
+  GDesktopMenuDirectory *directory;
+  GList                 *menus;
+  GList                 *items;
+  GList                 *iter;
+  gchar                 *name;
+
+  if (!g_desktop_menu_element_get_visible (G_DESKTOP_MENU_ELEMENT (menu)))
+    return;
 
   /* Determine menu name */
-  directory = xfce_menu_get_directory (menu);
-  name = is_root ? "" : (directory == NULL ? xfce_menu_get_name (menu) : xfce_menu_directory_get_name (directory));
+  directory = g_desktop_menu_get_directory (menu);
+
+  if (G_UNLIKELY (path == NULL))
+    name = g_strdup ("");
+  else
+    {
+      name = g_strdup_printf ("%s%s/", path, 
+                              (directory == NULL 
+                               ? g_desktop_menu_element_get_name (G_DESKTOP_MENU_ELEMENT (menu)) 
+                               : g_desktop_menu_directory_get_name (directory)));
+    }
 
   /* Fetch submenus */
-  menus = xfce_menu_get_menus (menu);
+  menus = g_desktop_menu_get_menus (menu);
 
   /* Print child menus */
-  for (iter = menus; iter != NULL; iter = g_slist_next (iter)) 
+  for (iter = menus; iter != NULL; iter = g_list_next (iter)) 
     {
-      XfceMenuDirectory *submenu_directory = xfce_menu_get_directory (XFCE_MENU (iter->data));
-
-      /* Don't display hidden menus */
-      if (G_LIKELY (submenu_directory == NULL || !xfce_menu_directory_get_no_display (submenu_directory)))
-        print_menu (XFCE_MENU (iter->data), FALSE);
+      /* Only display menus which are not hidden or excluded from this environment */
+      if (G_LIKELY (g_desktop_menu_element_get_visible (iter->data)))
+        print_menu (G_DESKTOP_MENU (iter->data), name);
     }
 
   /* Free submenu list */
-  g_slist_free (menus);
+  g_list_free (menus);
 
   /* Fetch menu items */
-  items = xfce_menu_get_items (menu);
+  items = g_desktop_menu_get_elements (menu);
 
   /* Print menu items */
-  for (iter = items; iter != NULL; iter = g_slist_next (iter)) 
+  for (iter = items; iter != NULL; iter = g_list_next (iter)) 
     {
-      XfceMenuItem      *item = iter->data;
-
-      if (G_UNLIKELY (!xfce_menu_item_get_no_display (item)))
-        g_printf ("%s/\t%s\t%s\n", name, xfce_menu_item_get_desktop_id (item), xfce_menu_item_get_filename (item));
+      if (G_IS_DESKTOP_MENU_ITEM (iter->data) 
+          && g_desktop_menu_element_get_visible (iter->data))
+        {
+          g_printf ("%s\t%s\t%s\n", name, g_desktop_menu_item_get_desktop_id (iter->data), 
+                    g_desktop_menu_item_get_filename (iter->data));
+        }
     }
 
   /* Free menu item list */
-  g_slist_free (items);
+  g_list_free (items);
+
+  /* Free name */
+  g_free (name);
 }
 
 
@@ -86,28 +101,35 @@ int
 main (int    argc,
       char **argv)
 {
-  XfceMenu *menu;
-  GError   *error = NULL;
+  GDesktopMenu *menu;
+  GError       *error = NULL;
 #ifdef HAVE_STDLIB_H
-  int       exit_code = EXIT_SUCCESS;
+  int           exit_code = EXIT_SUCCESS;
 #else
-  int       exit_code = 0;
+  int           exit_code = 0;
 #endif
 
+  g_set_prgname ("test-menu-spec");
+
   /* Initialize menu library */
-  xfce_menu_init (NULL);
+  g_desktop_menu_init (NULL);
 
   /* Try to get the root menu */
-  menu = xfce_menu_get_root (&error);
+  menu = g_desktop_menu_new_applications ();
 
-  if (G_LIKELY (menu != NULL)) 
+  if (G_LIKELY (g_desktop_menu_load (menu, NULL, &error)))
     {
       /* Print menu contents according to the test suite criteria */
-      print_menu (menu, TRUE);
+      print_menu (menu, NULL);
     }
   else
     {
-      g_error (error->message);
+      gchar *uri;
+
+      uri = g_file_get_uri (g_desktop_menu_get_file (menu));
+      g_error ("Could not load menu from %s: %s", uri, error->message);
+      g_free (uri);
+
       g_error_free (error);
 #ifdef HAVE_STDLIB_H
       exit_code = EXIT_FAILURE;
@@ -117,7 +139,7 @@ main (int    argc,
     }
 
   /* Shut down the menu library */
-  xfce_menu_shutdown ();
+  g_desktop_menu_shutdown ();
 
   return exit_code;
 }



More information about the Xfce4-commits mailing list