/*! \fn gboolean CDesktopAppChooser::m_LoadAndBuildAppsMenuTree(void)
    \brief To load the main application menu(.menu) file. 

    \param[in] NONE
    \return TRUE or FALSE
*/
gboolean CDesktopAppChooser::m_LoadAndBuildAppsMenuTree(void)
{
  GSList *directoryList = NULL;

  /*------------ THE ENTRY POINT !!! -------------*/
  /* To open the applications .menu file. */
  m_MenuTree = gmenu_tree_lookup( APPLICATIONS_MENU, GMENU_TREE_FLAGS_NONE );

  /* To store the parsed direcotry contents. */
  m_RootDir = gmenu_tree_get_root_directory( m_MenuTree );

  /* To build the top-level tree node. */
  for(directoryList = gmenu_tree_directory_get_contents( m_RootDir ); 
      directoryList; 
      directoryList = directoryList->next )
  {
     GMenuTreeDirectory *tmpDir = (GMenuTreeDirectory*)directoryList->data;

     /* To check its type. */
     if( G_UNLIKELY(gmenu_tree_item_get_type((GMenuTreeItem*)tmpDir) != GMENU_TREE_ITEM_DIRECTORY) )
       continue;

     /* To build top-level(Directory) nodes. */          
     m_AddAppsMenuTopLevelNode(tmpDir);

     /* To build child nodes(applications). */
     m_AddAppsMenuLeafNode(tmpDir);		
  }

  return true;
}
Example #2
0
static GList *
xde_appmenu(MenuContext *ctx, GList *entries, const char *name)
{
	GMenuTreeDirectory *dir;
	GList *text = NULL;
	char *s, *esc, *qname;

	if (!(dir = gmenu_tree_get_root_directory(ctx->tree))) {
		EPRINTF("could not get root directory\n");
		return (text);
	}
	if (!name)
		name = gmenu_tree_directory_get_name(dir);
	esc = xde_character_escape(name, '"');
	s = g_strdup_printf("\nMenu \"%s\" twm_MenuColor\n", esc);
	text = g_list_append(text, s);
	s = strdup("{\n");
	text = g_list_append(text, s);
	qname = g_strdup_printf("\"%s\"", esc);
	s = g_strdup_printf("    %-32s  %s\n", qname, "f.title");
	text = g_list_append(text, s);
	text = g_list_concat(text, entries);
	s = strdup("}\n");
	text = g_list_append(text, s);
	g_free(qname);
	free(esc);
	return (text);
}
/**
 * shell_app_system_get_sections:
 *
 * return names of sections in applications menu.
 *
 * Returns: (element-type utf8) (transfer full): List of Names
 */
GList *
shell_app_system_get_sections (ShellAppSystem *system)
{
  GList *res = NULL;
  GSList *i, *contents;
  GMenuTreeDirectory *root;

  root = gmenu_tree_get_root_directory (system->priv->apps_tree);

  if (G_UNLIKELY (!root))
    g_error ("applications.menu not found.");

  contents = gmenu_tree_directory_get_contents (root);

  for (i = contents; i; i = i->next)
    {
      GMenuTreeItem *item = i->data;
      if (gmenu_tree_item_get_type (item) == GMENU_TREE_ITEM_DIRECTORY)
        {
          char *name = g_strdup (gmenu_tree_directory_get_name ((GMenuTreeDirectory*)item));

          g_assert (name);

          res = g_list_append (res, name);
        }
      gmenu_tree_item_unref (item);
    }

  g_slist_free (contents);

  return res;
}
Example #4
0
static GList *
xde_create(MenuContext *ctx, Style style, const char *name)
{
	GMenuTreeDirectory *dir;
	GList *text = NULL;
	GList *entries = NULL;
	char *qname = NULL;
	char *s;

	ctx->wmm.output = NULL;

	s = g_strdup_printf("%s\n", "changequote(`[[[',`]]]')dnl");
	ctx->wmm.output = g_list_append(ctx->wmm.output, s);

	if (!(dir = gmenu_tree_get_root_directory(ctx->tree))) {
		EPRINTF("could not get root directory\n");
		return (text);
	}
	xde_reset_indent(ctx, 0);
	xde_increase_indent(ctx);
	entries = ctx->wmm.ops.menu(ctx, dir);
	xde_decrease_indent(ctx);

	if (!name)
		name = gmenu_tree_directory_get_name(dir);

	if (style == StyleFullmenu) {
		text = ctx->wmm.wmmenu(ctx);
		ctx->wmm.output = g_list_concat(ctx->wmm.output, text);
		text = ctx->wmm.wmspec(ctx);
		ctx->wmm.output = g_list_concat(ctx->wmm.output, text);
	}
	if (style == StyleAppmenu || style == StyleSubmenu) {
		text = ctx->wmm.appmenu(ctx, entries, name);
	}
	if (style == StyleEntries) {
		return (entries);
	}
	if (style == StyleSubmenu) {
		qname = g_strdup_printf("\"%s\"", name);
		s = g_strdup_printf("    %-32s  f.menu \"%s\"\n", qname, name);
		g_free(qname);
		/* FIXME: free other entries */
		entries = g_list_append(NULL, s);
	}
	if (style != StyleAppmenu) {
		text = ctx->wmm.rootmenu(ctx, entries);
		ctx->wmm.output = g_list_concat(ctx->wmm.output, text);
	}

	s = g_strdup_printf("\n%s\n", "changequote(`,)dnl");
	text = g_list_append(ctx->wmm.output, s);
	ctx->wmm.output = NULL;
	return (text);
}
static void
reload_menu (GnomeControlCenter *shell)
{
  GError *error;
  GMenuTreeDirectory *d;
  GMenuTreeIter *iter;
  GMenuTreeItemType next_type;

  error = NULL;
  if (!gmenu_tree_load_sync (shell->priv->menu_tree, &error))
    {
      g_warning ("Could not load control center menu: %s", error->message);
      g_clear_error (&error);
      return;
    }


  d = gmenu_tree_get_root_directory (shell->priv->menu_tree);
  iter = gmenu_tree_directory_iter (d);

  while ((next_type = gmenu_tree_iter_next (iter)) != GMENU_TREE_ITEM_INVALID)
    {
      if (next_type == GMENU_TREE_ITEM_DIRECTORY)
        {
          GMenuTreeDirectory *subdir;
          const gchar *dir_name;
          GMenuTreeIter *sub_iter;
          GMenuTreeItemType sub_next_type;

          subdir = gmenu_tree_iter_get_directory (iter);
          dir_name = gmenu_tree_directory_get_name (subdir);

          maybe_add_category_view (shell, dir_name);

          /* add the items from this category to the model */
          sub_iter = gmenu_tree_directory_iter (subdir);
          while ((sub_next_type = gmenu_tree_iter_next (sub_iter)) != GMENU_TREE_ITEM_INVALID)
            {
              if (sub_next_type == GMENU_TREE_ITEM_ENTRY)
                {
                  GMenuTreeEntry *item = gmenu_tree_iter_get_entry (sub_iter);
                  cc_shell_model_add_item (CC_SHELL_MODEL (shell->priv->store),
                                           dir_name,
                                           item);
                  gmenu_tree_item_unref (item);
                }
            }

          gmenu_tree_iter_unref (sub_iter);
          gmenu_tree_item_unref (subdir);
        }
    }

  gmenu_tree_iter_unref (iter);
}
Example #6
0
GeeArrayList* slingshot_backend_gmenu_entries_get_categories (void) {
    GeeArrayList* result = NULL;
    GMenuTree* _tmp0_ = NULL;
    GMenuTree* _tmp1_;
    GMenuTree* tree;
    GMenuTree* _tmp2_;
    GMenuTreeDirectory* _tmp3_ = NULL;
    GMenuTreeDirectory* _tmp4_;
    GMenuTreeDirectory* root;
    GeeArrayList* _tmp5_;
    GeeArrayList* main_directory_entries;
    GMenuTreeDirectory* _tmp6_;
    GSList* _tmp7_ = NULL;
    _tmp0_ = gmenu_tree_lookup ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_EXCLUDED);
    _tmp1_ = _gmenu_tree_ref0 (_tmp0_);
    tree = _tmp1_;
    _tmp2_ = tree;
    _tmp3_ = gmenu_tree_get_root_directory (_tmp2_);
    _tmp4_ = _gmenu_tree_item_ref0 (_tmp3_);
    root = _tmp4_;
    _tmp5_ = gee_array_list_new (G_TYPE_POINTER, (GBoxedCopyFunc) gmenu_tree_item_ref, gmenu_tree_item_unref, NULL);
    main_directory_entries = _tmp5_;
    _tmp6_ = root;
    _tmp7_ = gmenu_tree_directory_get_contents (_tmp6_);
    {
        GSList* item_collection = NULL;
        GSList* item_it = NULL;
        item_collection = _tmp7_;
        for (item_it = item_collection; item_it != NULL; item_it = item_it->next) {
            GMenuTreeItem* _tmp8_;
            GMenuTreeItem* item = NULL;
            _tmp8_ = _gmenu_tree_item_ref0 ((GMenuTreeItem*) item_it->data);
            item = _tmp8_;
            {
                GMenuTreeItem* _tmp9_;
                GMenuTreeItemType _tmp10_ = 0;
                _tmp9_ = item;
                _tmp10_ = gmenu_tree_item_get_type (_tmp9_);
                if (_tmp10_ == GMENU_TREE_ITEM_DIRECTORY) {
                    GeeArrayList* _tmp11_;
                    GMenuTreeItem* _tmp12_;
                    _tmp11_ = main_directory_entries;
                    _tmp12_ = item;
                    gee_abstract_collection_add ((GeeAbstractCollection*) _tmp11_, (GMenuTreeDirectory*) _tmp12_);
                }
                _gmenu_tree_item_unref0 (item);
            }
        }
    }
    result = main_directory_entries;
    _gmenu_tree_item_unref0 (root);
    _gmenu_tree_unref0 (tree);
    return result;
}
Example #7
0
void main(int argc, char *argv[])
{
  GMenuTree *tree = NULL;
  GMenuTreeDirectory *directory = NULL;
  GMenuTreeEntry *entry = NULL;
  const char *name = NULL;

  gtk_set_locale ();

  tree = gmenu_tree_lookup ("lxde-applications.menu", GMENU_TREE_FLAGS_NONE);
  directory = gmenu_tree_get_root_directory(tree);

  walk_tree(directory);
}
static void
reread_entries (ShellAppSystem     *self,
                GSList            **cache,
                GHashTable         *unique,
                GMenuTree          *tree)
{
  GMenuTreeDirectory *trunk;

  trunk = gmenu_tree_get_root_directory (tree);

  g_slist_foreach (*cache, (GFunc)shell_app_info_unref, NULL);
  g_slist_free (*cache);
  *cache = NULL;

  *cache = gather_entries_recurse (self, *cache, unique, trunk);

  gmenu_tree_item_unref (trunk);
}
Example #9
0
static GList *
xde_create(MenuContext *ctx, Style style, const char *name)
{
	GMenuTreeDirectory *dir;
	GList *text = NULL;
	GList *entries = NULL;
	char *s;

	ctx->wmm.output = NULL;

	s = g_strdup_printf("%s\n\n", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
	ctx->wmm.output = g_list_append(ctx->wmm.output, s);
	s = g_strdup_printf("%s\n\n", "<openbox_menu xmlns=\"http://openbox.org/3.4/menu\">");
	ctx->wmm.output = g_list_append(ctx->wmm.output, s);

	if (!(dir = gmenu_tree_get_root_directory(ctx->tree))) {
		EPRINTF("could not get root directory\n");
		return (text);
	}
	xde_reset_indent(ctx, 0);
	xde_increase_indent(ctx);
	entries = ctx->wmm.ops.menu(ctx, dir);
	xde_decrease_indent(ctx);

	switch(style) {
	case StyleFullmenu:
	default:
		text = ctx->wmm.rootmenu(ctx, entries);
		break;
	case StyleAppmenu:
		if (!name)
			name = gmenu_tree_directory_get_name(dir);
		text = ctx->wmm.appmenu(ctx, entries, name);
		break;
	case StyleEntries:
		break;
	}
	text = g_list_concat(ctx->wmm.output, text);
	ctx->wmm.output = NULL;

	s = g_strdup_printf("\n%s\n", "</openbox_menu>");
	text = g_list_append(text, s);
	return (text);
}
Example #10
0
static GHashTable *
get_flattened_entries_from_tree (GMenuTree *tree)
{
  GHashTable *table;
  GMenuTreeDirectory *root;

  table = g_hash_table_new_full (g_str_hash, g_str_equal,
                                 (GDestroyNotify) NULL,
                                 (GDestroyNotify) gmenu_tree_item_unref);

  root = gmenu_tree_get_root_directory (tree);
  
  if (root != NULL)
    get_flattened_entries_recurse (root, table);

  gmenu_tree_item_unref (root);
  
  return table;
}
Example #11
0
static void menu_tree_changed(GMenuTree *tree, gpointer user_data) 
{
    GMenuTreeDirectory *root = NULL;
    GtkWidget *menuitem = NULL;

    popup = gtk_menu_new();

    gmenu_tree_load_sync(tree, NULL);

    root = gmenu_tree_get_root_directory(tree);
    if (root) {
        traverse_directory(root, NULL);
        gmenu_tree_item_unref(root);
        root = NULL;
    }

    gtk_menu_shell_append(GTK_MENU_SHELL(popup), gtk_separator_menu_item_new());

    menuitem = menu_item_new_with_icon_name_text("logout", _("Logout"));
    gtk_menu_shell_append(GTK_MENU_SHELL(popup), menuitem);
    g_object_connect(G_OBJECT(menuitem), 
        "signal::activate", G_CALLBACK(logout), NULL, 
        NULL);
}
Example #12
0
GSList* get_menu_data(gboolean show_search, gboolean show_run, gboolean show_places, gboolean show_logout, char* file_manager, char*logout)
{
  /*FIXME... I'm leaking a bit of memory here */

  Menu_list_item * dir_item;
  GSList*  data = NULL;
  GMenuTree *  menu_tree;
  const char * menu_file[] = {"gnomecc.menu", "preferences.menu", "settings.menu", NULL};//
  GMenuTreeDirectory *root;
  int i;

  if (!gnome_vfs_initialized())
    gnome_vfs_init();

  G_file_manager = file_manager;

  menu_tree = gmenu_tree_lookup("applications.menu", GMENU_TREE_FLAGS_NONE);

  if (menu_tree)
  {
    root = gmenu_tree_get_root_directory(menu_tree);

    if (root)
    {
      fill_er_up(root, &data);
      gmenu_tree_item_unref(root);
    }
  }


  data = g_slist_prepend(data, get_blank());

  data = g_slist_append(data, get_separator());

  menu_tree = gmenu_tree_lookup("gnomecc.menu", GMENU_TREE_FLAGS_NONE);

  if (menu_tree)
  {
    root = gmenu_tree_get_root_directory(menu_tree);

    if (root)
    {
      dir_item = g_malloc(sizeof(Menu_list_item));
      dir_item->item_type = MENU_ITEM_DIRECTORY;
      dir_item->name = g_strdup("Control Centre");
      dir_item->comment = g_strdup("Gnome Control Centre");
      dir_item->null = NULL;
      dir_item->sublist = NULL;
      dir_item->icon = g_strdup("gnome-control-center");
      data = g_slist_append(data, dir_item);

      fill_er_up(root, &dir_item->sublist);
      dir_item->sublist = g_slist_prepend(dir_item->sublist, get_blank());
      dir_item->sublist = g_slist_append(dir_item->sublist, get_blank());
      gmenu_tree_item_unref(root);
    }
  }

  menu_tree = gmenu_tree_lookup("settings.menu", GMENU_TREE_FLAGS_NONE);

  if (menu_tree)
  {
    root = gmenu_tree_get_root_directory(menu_tree);

    if (root)
    {
      dir_item = g_malloc(sizeof(Menu_list_item));
      dir_item->item_type = MENU_ITEM_DIRECTORY;
      dir_item->name = g_strdup("Settings");
      dir_item->comment = g_strdup("System Settings");
      dir_item->sublist = NULL;
      dir_item->null = NULL;
      dir_item->icon = g_strdup("gnome-settings");
      data = g_slist_append(data, dir_item);

      fill_er_up(root, &dir_item->sublist);
      dir_item->sublist = g_slist_prepend(dir_item->sublist, get_blank());
      dir_item->sublist = g_slist_append(dir_item->sublist, get_blank());
      gmenu_tree_item_unref(root);
    }
  }

  data = g_slist_append(data, get_separator());


  if (show_places)
  {
    dir_item = g_malloc(sizeof(Menu_list_item));
    dir_item->item_type = MENU_ITEM_DIRECTORY;
    dir_item->name = g_strdup("Places");
    dir_item->icon = g_strdup("bookmark");
    dir_item->comment = g_strdup("Your special places :-)");
    dir_item->sublist = NULL;
    dir_item->monitor = monitor_places;
    data = g_slist_append(data, dir_item);
    update_places(&dir_item->sublist, file_manager);
  }

  if (show_search)
  {
    dir_item = g_malloc(sizeof(Menu_list_item));
    dir_item->item_type = MENU_ITEM_SEARCH;
    dir_item->name = g_strdup("Find:");
    dir_item->icon = g_strdup("stock_search");
    dir_item->comment = g_strdup("Search");
    dir_item->sublist = NULL;
    dir_item->search_entry = NULL;
    data = g_slist_append(data, dir_item);
  }

  if (show_run)
  {
    dir_item = g_malloc(sizeof(Menu_list_item));
    dir_item->item_type = MENU_ITEM_RUN;
    dir_item->name = g_strdup("Run:");
    dir_item->icon = g_strdup("exec");
    dir_item->comment = g_strdup("Run a program");
    dir_item->sublist = NULL;
    dir_item->search_entry = NULL;
    data = g_slist_append(data, dir_item);

  }



  if (show_logout)
  {
    dir_item = g_malloc(sizeof(Menu_list_item));
    dir_item->item_type = MENU_ITEM_ENTRY;
    dir_item->name = g_strdup("Logout...");
    dir_item->icon = g_strdup("gnome-logout");
    dir_item->exec = g_strdup(logout);
    dir_item->desktop = g_strdup("");
    dir_item->comment = g_strdup("Logout and related activities.");
    dir_item->sublist = NULL;
    data = g_slist_append(data, dir_item);

  }

  data = g_slist_append(data, get_blank());

  return data;
}
Example #13
0
int main() {
	auto tree=gmenu_tree_new(menu_name, GMENU_TREE_FLAGS_NONE); //no need flags, defaults is good enough
	
	{
		char lang[locale_size]; //here we get system locale string
		strcpy(lang,getenv("LANG"));
		char* country=0; //and parse it to 3 strings - lang, country, modifier
		char* modifier=0;
		//char* enc=0; //it could be useful somewhere else. let it be commented
		for(int i=0;lang[i];++i){
			switch(lang[i]){
				case '_':
					lang[i]=0;
					country=lang+i+1;
					break;
				case '@':
					lang[i]=0;
					modifier=lang+i+1;
					break;
				case '.':
					lang[i]=0;
					//enc=lang+i+1;
					break;
			}
		}

		{
			int loc_i=0; //current locale index
			if(*lang&&country&&modifier){
				strcpy(locales[loc_i++]+4,(std::string("[")+lang+"_"+country+"@"+modifier+"]").c_str());
			}
			if(*lang&&country){
				strcpy(locales[loc_i++]+4,(std::string("[")+lang+"_"+country+"]").c_str());
			}
			if(*lang&&modifier){
				strcpy(locales[loc_i++]+4,(std::string("[")+lang+"@"+modifier+"]").c_str());
			}
			if(*lang){
				strcpy(locales[loc_i++]+4,(std::string("[")+lang+"]").c_str());
			}
			locales[loc_i+1][0]=0; //barier to stop in case of buggy .desktop entry
		}
	}
	
	while(!gmenu_tree_load_sync(tree,NULL)){ //wait for load
		usleep(sync_wait_time);
	}
	
	qu.push(gmenu_tree_get_root_directory(tree)); //push root menu dir in queue
	while(!qu.empty()){ //while queue not empty, create menu for first dir
		auto& dir=qu.front();
		
		{
			const char* name=gmenu_tree_directory_get_menu_id(dir); //menu id used as unique fvwm menu suffix
			printf("DestroyMenu \"FvwmMenu%s\"\n",name);
			printf("AddToMenu \"FvwmMenu%s\"\n",name);
		}
		
		auto it=gmenu_tree_directory_iter(dir); //iterator
		decltype(gmenu_tree_iter_next(it)) next_type; //iterator type
		while ((next_type=gmenu_tree_iter_next(it))!=GMENU_TREE_ITEM_INVALID){
			switch (next_type){ 
				case GMENU_TREE_ITEM_DIRECTORY:{ //add directory function popup and queue it
					auto cur=gmenu_tree_iter_get_directory(it);
					printf("+ \"%s\" Popup \"FvwmMenu%s\"\n",
						gmenu_tree_directory_get_name(cur),
						gmenu_tree_directory_get_menu_id(cur));
					qu.push(cur);
					break;
				}
				case GMENU_TREE_ITEM_ENTRY:{
					auto cur=gmenu_tree_iter_get_entry(it);
					auto inf=gmenu_tree_entry_get_app_info(cur);
					std::string exec=g_desktop_app_info_get_string(inf,"Exec"); //get exec command
					int index;
					while((index=exec.find('%'))!=-1){ //delete all % params
						exec.erase(index,2);
					}
					int loc_i=0;
					char* name=0;
					do{ //find localised name in standard specified order
						name=g_desktop_app_info_get_string(inf,locales[loc_i]);
						++loc_i;
					}while(!name&&locales[loc_i][0]);
					if(name){ //if name not empty
						printf("+ \"%s\" Exec exec %s\n",name,exec.c_str()); //add menu entry
					}
					break;
				}
				case GMENU_TREE_ITEM_SEPARATOR:{ //add empty menu entry
					printf("+ \"\" Nop");
				}
				default:{ //TODO: add other types if needed
					
				}
			}
		}
		gmenu_tree_iter_unref(it); //unref iterator (dunno why, but why not?)
		printf("\n"); //just for better readability
		
		qu.pop();
	}
	return 0;
}
Example #14
0
/*=============================================================================
 * Main Function
 */
int main (int argc, char **argv)
{
    int i;
    char *xdgfile = NULL;
    
    for (i = 1; i < argc; i++)
    {
        if ((strcmp (argv[i], "-h") == 0) || (strcmp (argv[i], "--help") == 0))
        {
          show_help ();
          g_free (xdgfile);
          return 0;
        }
        else if ((strcmp (argv[i], "--show-amount") == 0) ||
        (strcmp (argv[i], "-a") == 0))
        {
            option_show_amount_of_entries = 1;
        }
        else if ((strcmp (argv[i], "--plain") == 0) ||
        (strcmp (argv[i], "-p") == 0))
        {
            option_do_not_use_categories = 1;
        }
        else if (argv[i][0] != '-')
        {
            if (xdgfile != NULL) {
                g_printf ("Unexpected amount of arguments.\n");
                g_free (xdgfile);
                return 1;
            }
            xdgfile = g_strdup (argv[i]);
        }
        else
        {
            g_printf ("Unknown argument: %s\n", argv[i]);
            return 1;
        }
    }
    
    if (xdgfile == NULL) {
        show_help ();
        g_free (xdgfile);
        return 1;
    }
    
    FILE * file;
    if (!(file = fopen(xdgfile, "r")))
    {
        g_printf ("Could not read file \"%s\".\n", xdgfile);
        g_free (xdgfile);
        return 2;
    }
    fclose(file);
    
    GMenuTree *menuTree = gmenu_tree_lookup (xdgfile,  GMENU_TREE_FLAGS_NONE );
    
    GMenuTreeDirectory *rootDirectory = gmenu_tree_get_root_directory(menuTree);
    
    g_printf ("<openbox_pipe_menu>\n");
    g_printf ("<separator label=\"Menu XDG\" />\n");

    process_directory(rootDirectory, 1);
    
    gmenu_tree_item_unref (rootDirectory);
    
    g_printf ("</openbox_pipe_menu>\n");
    
    g_free (xdgfile);
    return 0;
}
Example #15
0
int main(int argc, char** argv)
{
    GOptionContext* opt_ctx;
    GError* err = NULL;
    GMenuTree* menu_tree = NULL;
    GMenuTreeDirectory* root_dir;
    GSList* l;
    FILE *of;
    int ofd;
    char *tmp;
    char *dir;
    const gchar* const * xdg_cfg_dirs;
    const gchar* const * pdir;
    const char* menu_prefix;
    char* menu_file;
    char* plus_ptr = NULL;

    setlocale (LC_ALL, "");

    opt_ctx = g_option_context_new("Generate cache for freedesktop.org compliant menus.");
    g_option_context_add_main_entries( opt_ctx, opt_entries, NULL );
    if( ! g_option_context_parse( opt_ctx, &argc, &argv, &err ) )
    {
        g_print( "%s", err->message );
        g_error_free( err );
        return 1;
    }

    if( lang )
        g_setenv( "LANGUAGE", lang, TRUE );
#if 0
    /* if the cache is already up-to-date, just leave it. */
    if( !force && is_menu_uptodate() )
    {
        g_print("upda-to-date, re-generation is not needed.");
        return 0;
    }
#endif

    /* some memory leaks happen here if g_free is not used to free the keys. */
    de_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
    g_hash_table_insert( de_hash, (gpointer)"LXDE", (gpointer)SHOW_IN_LXDE );
    g_hash_table_insert( de_hash, (gpointer)"GNOME", (gpointer)SHOW_IN_GNOME );
    g_hash_table_insert( de_hash, (gpointer)"KDE", (gpointer)SHOW_IN_KDE );
    g_hash_table_insert( de_hash, (gpointer)"XFCE", (gpointer)SHOW_IN_XFCE );
    g_hash_table_insert( de_hash, (gpointer)"ROX", (gpointer)SHOW_IN_ROX );

    if(ifile)
        plus_ptr = strrchr(ifile, '+');

    if(plus_ptr != NULL && strcmp(plus_ptr, "+hidden") != 0)
        plus_ptr = NULL;

    if(plus_ptr)
    {
        *plus_ptr = '\0';
        menu_tree = gmenu_tree_lookup( ifile, GMENU_TREE_FLAGS_INCLUDE_NODISPLAY | GMENU_TREE_FLAGS_INCLUDE_EXCLUDED | GMENU_TREE_FLAGS_SHOW_EMPTY );
        *plus_ptr = '+';
    }
    else
        menu_tree = gmenu_tree_lookup( ifile, GMENU_TREE_FLAGS_INCLUDE_EXCLUDED );
    if( ! menu_tree )
    {
        g_print("Error loading source menu file: %s\n", ifile);
        return 1;
    }

    dir = g_path_get_dirname( ofile );
    if( !g_file_test( dir, G_FILE_TEST_EXISTS ) )
        g_mkdir_with_parents( dir, 0700 );
    g_free( dir );

    /* write the tree to cache. */
    tmp = g_malloc( strlen( ofile ) + 7 );
    strcpy( tmp, ofile );
    strcat( tmp, "XXXXXX" );
    ofd = g_mkstemp( tmp );
    if( ofd == -1 )
    {
        g_print( "Error writing output file: %s\n", g_strerror(errno) );
        return 1;
    }

    of = fdopen( ofd, "w" );
    if( ! of )
    {
        g_print( "Error writing output file: %s\n", ofile );
        return 1;
    }

    /* Version number should be added to the head of this cache file. */
    fprintf( of, "%d.%d\n", VER_MAJOR, VER_MINOR );

    /* the first line is menu name */
    fprintf( of, "%s\n", ifile );

    root_dir = gmenu_tree_get_root_directory( menu_tree );

    /* add the source menu file itself to the list of files requiring monitor */
    if(plus_ptr)
        *plus_ptr = '\0';
    if( g_path_is_absolute(ifile) )
    {
        if( ! g_slist_find_custom(all_used_files, ifile, (GCompareFunc)strcmp ) )
            all_used_files = g_slist_prepend(all_used_files, g_strdup(ifile));
    }
    else
    {
        char* file_name;
        xdg_cfg_dirs = g_get_system_config_dirs();
        menu_prefix = g_getenv("XDG_MENU_PREFIX");
        file_name = menu_prefix ? g_strconcat(menu_prefix, ifile, NULL) : ifile;
        for( pdir = xdg_cfg_dirs; *pdir; ++pdir )
        {
            menu_file = g_build_filename( *pdir, "menus", file_name, NULL );
            if( ! g_slist_find_custom(all_used_dirs, menu_file, (GCompareFunc)strcmp ) )
                all_used_files = g_slist_prepend(all_used_files, menu_file);
            else
                g_free( menu_file );
        }
        menu_file = g_build_filename( g_get_user_config_dir(), "menus", file_name, NULL );
        if( file_name != ifile )
            g_free(file_name);

        if( ! g_slist_find_custom(all_used_dirs, menu_file, (GCompareFunc)strcmp ) )
            all_used_files = g_slist_prepend(all_used_files, menu_file);
        else
            g_free(menu_file);
    }

    /* write a list of all files which need to be monitored for changes. */
    /* write number of files first */
    fprintf( of, "%d\n", g_slist_length(all_used_dirs) + g_slist_length(all_used_files) );

    /* list all files.
     * add D or F at the begin of each line to indicate whether it's a
     * file or directory. */
    for( l = all_used_dirs; l; l = l->next )
    {
        fprintf( of, "D%s\n", (char*)l->data );
    }
    for( l = all_used_files; l; l = l->next )
    {
        fprintf( of, "F%s\n", (char*)l->data );
    }

    /* write all DE names in this menu. Known DEs such as LXDE, GNOME, and KDE don't need to be listed here */
    if( g_hash_table_size(de_hash) > N_KNOWN_DESKTOPS ) /* if there are some unknown DEs added to the hash */
        g_hash_table_foreach(de_hash, (GHFunc)write_de_name, of );
    fputc('\n', of);

    /* write the whole menu tree */
    write_dir( of, root_dir );

    fclose( of );

    gmenu_tree_unref( menu_tree );

    g_hash_table_destroy(de_hash);

    if( g_rename( tmp, ofile ) == -1 )
    {
        g_print( "Error writing output file: %s\n", g_strerror( errno ) );
    }
    g_free( tmp );
    /* g_print("success!\n"); */
    return 0;
}