1 /* vi:set sw=2 sts=2 ts=2 et ai: */
2 /*-
3  * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include <glib.h>
26 #include <glib-object.h>
27 
28 #include <garcon/garcon-menu-item.h>
29 #include <garcon/garcon-menu-node.h>
30 
31 
32 
33 /* Property identifiers */
34 enum
35 {
36   PROP_0,
37   PROP_NODE_TYPE,
38 };
39 
40 
41 
42 static void garcon_menu_node_finalize     (GObject             *object);
43 static void garcon_menu_node_get_property (GObject             *object,
44                                            guint                prop_id,
45                                            GValue              *value,
46                                            GParamSpec          *pspec);
47 static void garcon_menu_node_set_property (GObject             *object,
48                                            guint                prop_id,
49                                            const GValue        *value,
50                                            GParamSpec          *pspec);
51 static void garcon_menu_node_free_data    (GarconMenuNode      *node);
52 
53 
54 
55 struct _GarconMenuNodeClass
56 {
57   GObjectClass __parent__;
58 };
59 
60 union _GarconMenuNodeData
61 {
62   GarconMenuLayoutMergeType layout_merge_type;
63   struct
64   {
65     GarconMenuMergeFileType type;
66     gchar                  *filename;
67   } merge_file;
68   gchar                    *string;
69 };
70 
71 struct _GarconMenuNode
72 {
73   GObject            __parent__;
74 
75   GarconMenuNodeType node_type;
76   GarconMenuNodeData data;
77 };
78 
79 
80 
81 GType
82 garcon_menu_node_type_get_type (void)
83 {
84   static GType      type = G_TYPE_INVALID;
85   static GEnumValue values[] =
86   {
87     { GARCON_MENU_NODE_TYPE_INVALID, "GARCON_MENU_NODE_TYPE_INVALID", "Invalid" },
88     { GARCON_MENU_NODE_TYPE_MENU, "GARCON_MENU_NODE_TYPE_MENU", "Menu" },
89     { GARCON_MENU_NODE_TYPE_NAME, "GARCON_MENU_NODE_TYPE_NAME", "Name" },
90     { GARCON_MENU_NODE_TYPE_DIRECTORY, "GARCON_MENU_NODE_TYPE_DIRECTORY", "Directory" },
91     { GARCON_MENU_NODE_TYPE_DIRECTORY_DIR, "GARCON_MENU_NODE_TYPE_DIRECTORY_DIR", "DirectoryDir" },
92     { GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS", "DefaultDirectoryDirs" },
93     { GARCON_MENU_NODE_TYPE_APP_DIR, "GARCON_MENU_NODE_TYPE_APP_DIR", "AppDir" },
94     { GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS", "DefaultAppDirs" },
95     { GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED, "GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED", "OnlyUnallocated" },
96     { GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED, "GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED", "NotOnlyUnallocated" },
97     { GARCON_MENU_NODE_TYPE_DELETED, "GARCON_MENU_NODE_TYPE_DELETED", "Deleted" },
98     { GARCON_MENU_NODE_TYPE_NOT_DELETED, "GARCON_MENU_NODE_TYPE_NOT_DELETED", "NotDeleted" },
99     { GARCON_MENU_NODE_TYPE_INCLUDE, "GARCON_MENU_NODE_TYPE_INCLUDE", "Include" },
100     { GARCON_MENU_NODE_TYPE_EXCLUDE, "GARCON_MENU_NODE_TYPE_EXCLUDE", "Exclude" },
101     { GARCON_MENU_NODE_TYPE_ALL, "GARCON_MENU_NODE_TYPE_ALL", "All" },
102     { GARCON_MENU_NODE_TYPE_FILENAME, "GARCON_MENU_NODE_TYPE_FILENAME", "Filename" },
103     { GARCON_MENU_NODE_TYPE_CATEGORY, "GARCON_MENU_NODE_TYPE_CATEGORY", "Category" },
104     { GARCON_MENU_NODE_TYPE_OR, "GARCON_MENU_NODE_TYPE_OR", "Or" },
105     { GARCON_MENU_NODE_TYPE_AND, "GARCON_MENU_NODE_TYPE_AND", "And" },
106     { GARCON_MENU_NODE_TYPE_NOT, "GARCON_MENU_NODE_TYPE_NOT", "Not" },
107     { GARCON_MENU_NODE_TYPE_MOVE, "GARCON_MENU_NODE_TYPE_MOVE", "Move" },
108     { GARCON_MENU_NODE_TYPE_OLD, "GARCON_MENU_NODE_TYPE_OLD", "Old" },
109     { GARCON_MENU_NODE_TYPE_NEW, "GARCON_MENU_NODE_TYPE_NEW", "New" },
110     { GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT, "GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT", "DefaultLayout" },
111     { GARCON_MENU_NODE_TYPE_LAYOUT, "GARCON_MENU_NODE_TYPE_LAYOUT", "Layout" },
112     { GARCON_MENU_NODE_TYPE_MENUNAME, "GARCON_MENU_NODE_TYPE_MENUNAME", "Menuname" },
113     { GARCON_MENU_NODE_TYPE_SEPARATOR, "GARCON_MENU_NODE_TYPE_SEPARATOR", "Separator" },
114     { GARCON_MENU_NODE_TYPE_MERGE, "GARCON_MENU_NODE_TYPE_MERGE", "Merge" },
115     { GARCON_MENU_NODE_TYPE_MERGE_FILE, "GARCON_MENU_NODE_TYPE_MERGE_FILE", "MergeFile" },
116     { GARCON_MENU_NODE_TYPE_MERGE_DIR, "GARCON_MENU_NODE_TYPE_MERGE_DIR", "MergeDir" },
117     { GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS", "MergeDirs" },
118     { 0, NULL, NULL },
119   };
120 
121   if (G_UNLIKELY (type == G_TYPE_INVALID))
122     type = g_enum_register_static ("GarconMenuNodeType", values);
123 
124   return type;
125 }
126 
127 
128 
129 G_DEFINE_TYPE (GarconMenuNode, garcon_menu_node, G_TYPE_OBJECT)
130 
131 
132 
133 static void
134 garcon_menu_node_class_init (GarconMenuNodeClass *klass)
135 {
136   GObjectClass *gobject_class;
137 
138   gobject_class = G_OBJECT_CLASS (klass);
139   gobject_class->finalize = garcon_menu_node_finalize;
140   gobject_class->get_property = garcon_menu_node_get_property;
141   gobject_class->set_property = garcon_menu_node_set_property;
142 
143   g_object_class_install_property (gobject_class,
144                                    PROP_NODE_TYPE,
145                                    g_param_spec_enum ("node-type",
146                                                       "node-type",
147                                                       "node-type",
148                                                       garcon_menu_node_type_get_type (),
149                                                       GARCON_MENU_NODE_TYPE_MENU,
150                                                       G_PARAM_READWRITE |
151                                                       G_PARAM_STATIC_STRINGS));
152 }
153 
154 
155 
156 static void
157 garcon_menu_node_init (GarconMenuNode *node)
158 {
159 }
160 
161 
162 
163 static void
164 garcon_menu_node_finalize (GObject *object)
165 {
166   GarconMenuNode *node = GARCON_MENU_NODE (object);
167 
168   garcon_menu_node_free_data (node);
169 
170   (*G_OBJECT_CLASS (garcon_menu_node_parent_class)->finalize) (object);
171 }
172 
173 
174 
175 static void
176 garcon_menu_node_get_property (GObject    *object,
177                                guint       prop_id,
178                                GValue     *value,
179                                GParamSpec *pspec)
180 {
181   GarconMenuNode *node = GARCON_MENU_NODE (object);
182 
183   switch (prop_id)
184     {
185     case PROP_NODE_TYPE:
186       g_value_set_enum (value, node->node_type);
187       break;
name_of_col_is(const dict_table_t * table,const dict_index_t * index,ulint i,const char * name)188 
189     default:
190       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
191       break;
192     }
193 }
194 
195 
196 
197 static void
198 garcon_menu_node_set_property (GObject      *object,
199                                guint         prop_id,
200                                const GValue *value,
201                                GParamSpec   *pspec)
202 {
203   GarconMenuNode *node = GARCON_MENU_NODE (object);
204 
205   switch (prop_id)
206     {
207     case PROP_NODE_TYPE:
dict_get_first_table_name_in_db(const char * name)208       node->node_type = g_value_get_enum (value);
209       g_object_notify (G_OBJECT (node), "node-type");
210       break;
211 
212     default:
213       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
214       break;
215     }
216 }
217 
218 
219 
220 GarconMenuNode *
221 garcon_menu_node_new (GarconMenuNodeType node_type)
222 {
223   return g_object_new (GARCON_TYPE_MENU_NODE, "node-type", node_type, NULL);
224 }
225 
226 
227 
228 GarconMenuNodeType garcon_menu_node_get_node_type (GarconMenuNode *node)
229 {
230   g_return_val_if_fail (GARCON_IS_MENU_NODE (node), 0);
231   return node->node_type;
232 }
233 
234 
235 /**
236  * garcon_menu_node_create:
237  * @node_type: a #GarconMenuNodeType
238  * @first_value:
239  * @...:
240  *
241  * Returns: (transfer full): a #GarconMenuNode
242  */
243 GarconMenuNode *
244 garcon_menu_node_create (GarconMenuNodeType node_type,
245                          gpointer           first_value,
246                          ...)
247 {
248   GarconMenuNode *node;
249 
250   node = garcon_menu_node_new (node_type);
251 
252   switch (node_type)
253     {
254     case GARCON_MENU_NODE_TYPE_NAME:
255     case GARCON_MENU_NODE_TYPE_DIRECTORY:
256     case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
257     case GARCON_MENU_NODE_TYPE_APP_DIR:
258     case GARCON_MENU_NODE_TYPE_FILENAME:
259     case GARCON_MENU_NODE_TYPE_CATEGORY:
260     case GARCON_MENU_NODE_TYPE_OLD:
261     case GARCON_MENU_NODE_TYPE_NEW:
262     case GARCON_MENU_NODE_TYPE_MENUNAME:
263     case GARCON_MENU_NODE_TYPE_MERGE_DIR:
264       node->data.string = g_strdup (first_value);
265       break;
266 
267     case GARCON_MENU_NODE_TYPE_MERGE:
268       node->data.layout_merge_type = GPOINTER_TO_UINT (first_value);
269       break;
270 
271     case GARCON_MENU_NODE_TYPE_MERGE_FILE:
272       node->data.merge_file.type = GPOINTER_TO_UINT (first_value);
273       node->data.merge_file.filename = NULL;
274       break;
275 
276     default:
277       break;
278     }
279 
280   return node;
281 }
282 
283 
284 /**
285  * garcon_menu_node_copy:
286  * @node: a #GarconMenuNode
287  * @data:
288  *
289  * Returns: (transfer full): a #GarconMenuNode
290  */
dict_getnext_system_low(btr_pcur_t * pcur,mtr_t * mtr)291 GarconMenuNode *
292 garcon_menu_node_copy (GarconMenuNode *node,
293                        gpointer        data)
294 {
295   GarconMenuNode *copy;
296 
297   if (node == NULL || !GARCON_IS_MENU_NODE (node))
298     return NULL;
299 
300   copy = garcon_menu_node_new (node->node_type);
301 
302   switch (copy->node_type)
303     {
304     case GARCON_MENU_NODE_TYPE_NAME:
305     case GARCON_MENU_NODE_TYPE_DIRECTORY:
306     case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
307     case GARCON_MENU_NODE_TYPE_APP_DIR:
308     case GARCON_MENU_NODE_TYPE_FILENAME:
309     case GARCON_MENU_NODE_TYPE_CATEGORY:
310     case GARCON_MENU_NODE_TYPE_OLD:
311     case GARCON_MENU_NODE_TYPE_NEW:
312     case GARCON_MENU_NODE_TYPE_MENUNAME:
313     case GARCON_MENU_NODE_TYPE_MERGE_DIR:
314       copy->data.string = g_strdup (node->data.string);
315       break;
316 
317     case GARCON_MENU_NODE_TYPE_MERGE:
318       copy->data.layout_merge_type = node->data.layout_merge_type;
319       break;
320 
321     case GARCON_MENU_NODE_TYPE_MERGE_FILE:
322       copy->data.merge_file.type = node->data.merge_file.type;
323       copy->data.merge_file.filename = g_strdup (node->data.merge_file.filename);
324       break;
325 
326     default:
327       break;
328     }
329 
330   return copy;
331 }
332 
333 
334 
335 static void
336 garcon_menu_node_free_data (GarconMenuNode *node)
337 {
338   g_return_if_fail (GARCON_IS_MENU_NODE (node));
339 
340   switch (node->node_type)
341     {
342     case GARCON_MENU_NODE_TYPE_NAME:
343     case GARCON_MENU_NODE_TYPE_DIRECTORY:
344     case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
345     case GARCON_MENU_NODE_TYPE_APP_DIR:
346     case GARCON_MENU_NODE_TYPE_FILENAME:
347     case GARCON_MENU_NODE_TYPE_CATEGORY:
348     case GARCON_MENU_NODE_TYPE_OLD:
349     case GARCON_MENU_NODE_TYPE_NEW:
350     case GARCON_MENU_NODE_TYPE_MENUNAME:
dict_getnext_system(btr_pcur_t * pcur,mtr_t * mtr)351     case GARCON_MENU_NODE_TYPE_MERGE_DIR:
352       g_free (node->data.string);
353       break;
354 
355     case GARCON_MENU_NODE_TYPE_MERGE_FILE:
356       g_free (node->data.merge_file.filename);
357       break;
358 
359     default:
360       break;
361     }
362 }
363 
364 
365 
366 const gchar *
367 garcon_menu_node_get_string (GarconMenuNode *node)
368 {
369   g_return_val_if_fail (GARCON_IS_MENU_NODE (node), NULL);
370   return node->data.string;
371 }
372 
dict_process_sys_tables_rec_and_mtr_commit(mem_heap_t * heap,const rec_t * rec,dict_table_t ** table,bool cached,mtr_t * mtr)373 
374 
375 void
376 garcon_menu_node_set_string (GarconMenuNode *node,
377                              const gchar    *value)
378 {
379   g_return_if_fail (GARCON_IS_MENU_NODE (node));
380   g_return_if_fail (value != NULL);
381 
382   g_free (node->data.string);
383   node->data.string = g_strdup (value);
384 }
385 
386 
387 
388 GarconMenuMergeFileType
389 garcon_menu_node_get_merge_file_type (GarconMenuNode *node)
390 {
391   g_return_val_if_fail (GARCON_IS_MENU_NODE (node), 0);
392   g_return_val_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE, 0);
393   return node->data.merge_file.type;
394 }
395 
396 
397 
398 void
399 garcon_menu_node_set_merge_file_type (GarconMenuNode         *node,
400                                       GarconMenuMergeFileType type)
401 {
402   g_return_if_fail (GARCON_IS_MENU_NODE (node));
403   g_return_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE);
404   node->data.merge_file.type = type;
405 }
406 
407 
408 
409 const gchar *
410 garcon_menu_node_get_merge_file_filename (GarconMenuNode *node)
411 {
412   g_return_val_if_fail (GARCON_IS_MENU_NODE (node), NULL);
413   g_return_val_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE, NULL);
dict_process_sys_indexes_rec(mem_heap_t * heap,const rec_t * rec,dict_index_t * index,table_id_t * table_id)414   return node->data.merge_file.filename;
415 }
416 
417 
418 
419 void
420 garcon_menu_node_set_merge_file_filename (GarconMenuNode *node,
421                                           const gchar    *filename)
422 {
423   g_return_if_fail (GARCON_IS_MENU_NODE (node));
424   g_return_if_fail (filename != NULL);
425   g_return_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE);
426 
427   g_free (node->data.merge_file.filename);
428   node->data.merge_file.filename = g_strdup (filename);
429 }
430 
431 
432 
433 typedef struct
434 {
435   GarconMenuNodeType type;
436   GNode             *self;
437   gpointer           value;
438 } Pair;
dict_process_sys_columns_rec(mem_heap_t * heap,const rec_t * rec,dict_col_t * column,table_id_t * table_id,const char ** col_name,ulint * nth_v_col)439 
440 
441 
442 static gboolean
443 collect_children (GNode *node,
444                   Pair  *pair)
445 {
446   if (node == pair->self)
447     return FALSE;
448 
449   if (garcon_menu_node_tree_get_node_type (node) == pair->type)
450     pair->value = g_list_prepend (pair->value, node);
451 
452   return FALSE;
453 }
454 
455 
456 /**
457  * garcon_menu_node_tree_get_child_node: (skip)
458  * @tree: #GNode instance
459  * @type: type for the menu nodes
460  * @reverse:
461  *
462  * Returns: a #GNode if @type is valid menu nodes type.
463  */
464 GNode *
465 garcon_menu_node_tree_get_child_node (GNode             *tree,
dict_process_sys_virtual_rec(const rec_t * rec,table_id_t * table_id,ulint * pos,ulint * base_pos)466                                       GarconMenuNodeType type,
467                                       gboolean           reverse)
468 {
469   GNode *child = NULL;
470 
471   if (reverse)
472     {
473       for (child = g_node_last_child (tree);
474            child != NULL;
475            child = g_node_prev_sibling (child))
476         {
477           if (garcon_menu_node_tree_get_node_type (child) == type)
478             return child;
479         }
480     }
481   else
482     {
483       for (child = g_node_first_child (tree);
484            child != NULL;
485            child = g_node_next_sibling (child))
486         {
487           if (garcon_menu_node_tree_get_node_type (child) == type)
488             return child;
489         }
490     }
491 
492   return child;
493 }
494 
495 
496 /**
497  * garcon_menu_node_tree_get_child_nodes:
498  * @tree: a GNode
499  * @type: type for the menu nodes
500  * @reverse:
501  *
502  * Returns: (element-type GNode) (transfer full): list of #GNode
503  */
504 GList *
505 garcon_menu_node_tree_get_child_nodes (GNode             *tree,
506                                        GarconMenuNodeType type,
507                                        gboolean           reverse)
508 {
509   Pair pair;
510 
511   pair.type = type;
512   pair.value = NULL;
513   pair.self = tree;
514 
515   g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
516                    (GNodeTraverseFunc) collect_children, &pair);
517 
518   /* Return the list as if we appended */
519   if (!reverse && pair.value != NULL)
dict_process_sys_foreign_rec(mem_heap_t * heap,const rec_t * rec,dict_foreign_t * foreign)520     pair.value = g_list_reverse (pair.value);
521 
522   return (GList *) pair.value;
523 }
524 
525 
526 
527 static gboolean
528 collect_strings (GNode *node,
529                  Pair  *pair)
530 {
531   gpointer string;
532 
533   if (node == pair->self)
534     return FALSE;
535 
536   if (garcon_menu_node_tree_get_node_type (node) == pair->type)
537     {
538       string = (gpointer) garcon_menu_node_tree_get_string (node);
539       pair->value = g_list_prepend (pair->value, string);
540     }
541 
542   return FALSE;
543 }
544 
545 
546 /**
547  * garcon_menu_node_tree_get_string_children:
548  * @tree: a #GNode instance
549  * @type: type for the menu nodes
550  * @reverse:
551  *
552  * Returns: (element-type GNode) (transfer full): list of #GNode
553  */
554 GList *
555 garcon_menu_node_tree_get_string_children (GNode             *tree,
556                                            GarconMenuNodeType type,
557                                            gboolean           reverse)
558 {
559   Pair pair;
560 
561   pair.type = type;
562   pair.value = NULL;
563   pair.self = tree;
564 
565   g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
566                    (GNodeTraverseFunc) collect_strings, &pair);
567 
568   /* Return the list as if we appended */
569   if (!reverse && pair.value != NULL)
570     pair.value = g_list_reverse (pair.value);
571 
572   return (GList *) pair.value;
573 }
574 
575 
576 
577 static gboolean
578 collect_boolean (GNode *node,
579                  Pair  *pair)
580 {
581   if (node == pair->self)
582     return FALSE;
583 
584   if (garcon_menu_node_tree_get_node_type (node) == pair->type)
585     {
586       pair->value = GUINT_TO_POINTER (1);
587       return TRUE;
588     }
589 
590   return FALSE;
591 }
592 
593 
594 
595 gboolean
596 garcon_menu_node_tree_get_boolean_child (GNode             *tree,
597                                          GarconMenuNodeType type)
598 {
599   Pair pair;
dict_process_sys_foreign_col_rec(mem_heap_t * heap,const rec_t * rec,const char ** name,const char ** for_col_name,const char ** ref_col_name,ulint * pos)600 
601   pair.value = GUINT_TO_POINTER (0);
602   pair.self = tree;
603   pair.type = type;
604 
605   g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
606                    (GNodeTraverseFunc) collect_boolean, &pair);
607 
608   return !!GPOINTER_TO_UINT (pair.value);
609 }
610 
611 
612 
613 static gboolean
614 collect_string (GNode *node,
615                 Pair  *pair)
616 {
617   const gchar **string = pair->value;
618 
619   if (node == pair->self)
620     return FALSE;
621 
622   if (garcon_menu_node_tree_get_node_type (node) == pair->type)
623     {
624       *string = garcon_menu_node_tree_get_string (node);
625       return TRUE;
626     }
627 
628   return FALSE;
629 }
630 
631 
632 
633 const gchar *
634 garcon_menu_node_tree_get_string_child (GNode             *tree,
635                                         GarconMenuNodeType type)
636 {
637   Pair         pair;
638   const gchar *string = NULL;
639 
640   pair.type = type;
641   pair.value = &string;
642   pair.self = tree;
643 
644   g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
645                    (GNodeTraverseFunc) collect_string, &pair);
646 
647   return string;
648 }
649 
650 
651 
652 gboolean
653 garcon_menu_node_tree_rule_matches (GNode          *node,
654                                     GarconMenuItem *item)
655 {
656   GNode   *child;
657   gboolean matches = FALSE;
658   gboolean child_matches = FALSE;
659 
660   switch (garcon_menu_node_tree_get_node_type (node))
661     {
662     case GARCON_MENU_NODE_TYPE_CATEGORY:
663       matches = garcon_menu_item_has_category (item, garcon_menu_node_tree_get_string (node));
664       break;
665 
666     case GARCON_MENU_NODE_TYPE_INCLUDE:
667     case GARCON_MENU_NODE_TYPE_EXCLUDE:
668     case GARCON_MENU_NODE_TYPE_OR:
dict_process_sys_tablespaces(mem_heap_t * heap,const rec_t * rec,ulint * space,const char ** name,ulint * flags)669       for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
670         matches = matches || garcon_menu_node_tree_rule_matches (child, item);
671       break;
672 
673     case GARCON_MENU_NODE_TYPE_FILENAME:
674       matches = g_str_equal (garcon_menu_node_tree_get_string (node),
675                              garcon_menu_item_get_desktop_id (item));
676       break;
677 
678     case GARCON_MENU_NODE_TYPE_AND:
679       matches = TRUE;
680       for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
681         matches = matches && garcon_menu_node_tree_rule_matches (child, item);
682       break;
683 
684     case GARCON_MENU_NODE_TYPE_NOT:
685       for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
686         child_matches = child_matches || garcon_menu_node_tree_rule_matches (child, item);
687       matches = !child_matches;
688       break;
689 
690     case GARCON_MENU_NODE_TYPE_ALL:
691       matches = TRUE;
692       break;
693 
694     default:
695       break;
696     }
697 
698   return matches;
699 }
700 
701 
702 
703 
704 
705 
706 GarconMenuNodeType
707 garcon_menu_node_tree_get_node_type (GNode *tree)
708 {
709   if (tree == NULL)
710     return GARCON_MENU_NODE_TYPE_INVALID;
711 
712   if (tree->data == NULL)
713     return GARCON_MENU_NODE_TYPE_MENU;
714 
715   return garcon_menu_node_get_node_type (tree->data);
716 }
717 
718 
719 
720 const gchar *
721 garcon_menu_node_tree_get_string (GNode *tree)
722 {
723   if (tree == NULL || tree->data == NULL)
724     return NULL;
725   else
726     return garcon_menu_node_get_string (tree->data);
727 }
728 
729 
730 
731 void
732 garcon_menu_node_tree_set_string (GNode       *tree,
733                                   const gchar *value)
734 {
dict_process_sys_datafiles(mem_heap_t * heap,const rec_t * rec,ulint * space,const char ** path)735   GarconMenuNodeType type;
736 
737   type = garcon_menu_node_tree_get_node_type (tree);
738 
739   g_return_if_fail (type == GARCON_MENU_NODE_TYPE_NAME ||
740                     type == GARCON_MENU_NODE_TYPE_DIRECTORY ||
741                     type == GARCON_MENU_NODE_TYPE_DIRECTORY_DIR ||
742                     type == GARCON_MENU_NODE_TYPE_APP_DIR ||
743                     type == GARCON_MENU_NODE_TYPE_FILENAME ||
744                     type == GARCON_MENU_NODE_TYPE_CATEGORY ||
745                     type == GARCON_MENU_NODE_TYPE_OLD ||
746                     type == GARCON_MENU_NODE_TYPE_NEW ||
747                     type == GARCON_MENU_NODE_TYPE_MENUNAME ||
748                     type == GARCON_MENU_NODE_TYPE_MERGE_DIR);
749 
750   garcon_menu_node_set_string (tree->data, value);
751 }
752 
753 
754 GarconMenuLayoutMergeType
755 garcon_menu_node_tree_get_layout_merge_type (GNode *tree)
756 {
757   g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE, 0);
758   return ((GarconMenuNode *)tree->data)->data.layout_merge_type;
759 }
760 
761 
762 
763 GarconMenuMergeFileType
764 garcon_menu_node_tree_get_merge_file_type (GNode *tree)
765 {
766   g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE, 0);
767   return garcon_menu_node_get_merge_file_type (tree->data);
768 }
769 
770 
771 
772 const gchar *
773 garcon_menu_node_tree_get_merge_file_filename (GNode *tree)
774 {
775   g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE, NULL);
776   return garcon_menu_node_get_merge_file_filename (tree->data);
777 }
778 
779 
780 
781 void
782 garcon_menu_node_tree_set_merge_file_filename (GNode       *tree,
783                                                   const gchar *filename)
784 {
785   g_return_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE);
786   garcon_menu_node_set_merge_file_filename (tree->data, filename);
787 }
dict_get_first_path(ulint space_id)788 
789 
790 
791 gint
792 garcon_menu_node_tree_compare (GNode *tree,
793                                GNode *other_tree)
794 {
795   GarconMenuNode *node;
796   GarconMenuNode *other_node;
797 
798   if (tree == NULL || other_tree == NULL)
799     return 0;
800 
801   node = tree->data;
802   other_node = other_tree->data;
803 
804   if (node->node_type != other_node->node_type)
805     return 0;
806 
807   switch (node->node_type)
808     {
809     case GARCON_MENU_NODE_TYPE_NAME:
810     case GARCON_MENU_NODE_TYPE_DIRECTORY:
811     case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
812     case GARCON_MENU_NODE_TYPE_APP_DIR:
813     case GARCON_MENU_NODE_TYPE_FILENAME:
814     case GARCON_MENU_NODE_TYPE_CATEGORY:
815     case GARCON_MENU_NODE_TYPE_OLD:
816     case GARCON_MENU_NODE_TYPE_NEW:
817     case GARCON_MENU_NODE_TYPE_MENUNAME:
818     case GARCON_MENU_NODE_TYPE_MERGE_DIR:
819       return g_strcmp0 (node->data.string, other_node->data.string);
820       break;
821 
822     case GARCON_MENU_NODE_TYPE_MERGE_FILE:
823       return g_strcmp0 (node->data.merge_file.filename,
824                         other_node->data.merge_file.filename);
825       break;
826 
827     default:
828       return 0;
829       break;
830     }
831 
832   return 0;
833 }
834 
835 
836 /**
837  * garcon_menu_node_tree_copy: (skip)
838  * @tree: a #GNode
839  *
840  * Recursively copies a #GNode.
841  */
842 GNode *
843 garcon_menu_node_tree_copy (GNode *tree)
844 {
845   return g_node_copy_deep (tree, (GCopyFunc) garcon_menu_node_copy, NULL);
846 }
847 
848 
849 
850 static gboolean
851 free_children (GNode   *tree,
852                gpointer data)
853 {
854   garcon_menu_node_tree_free_data (tree);
855   return FALSE;
856 }
857 
858 
859 
860 void
861 garcon_menu_node_tree_free (GNode *tree)
862 {
863   if (tree != NULL)
864     {
865       g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
866                        (GNodeTraverseFunc) free_children, NULL);
867 
868       g_node_destroy (tree);
869     }
dict_update_filepath(ulint space_id,const char * filepath)870 }
871 
872 
873 
874 void
875 garcon_menu_node_tree_free_data (GNode *tree)
876 {
877   if (tree != NULL && tree->data != NULL)
878     g_object_unref (tree->data);
879 }
880 
881