From 8d46b0347ce6cfff71a769b7aec8d402b572bb0b Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Thu, 15 Feb 2024 16:29:48 +0000 Subject: Deploy mate-desktop/mate-menus to github.com/mate-desktop/mate-menus.git:gh-pages --- .../0.html | 2005 ++++ .../1.html | 403 + .../10.html | 1103 ++ .../11.html | 1109 ++ .../12.html | 765 ++ .../2.html | 345 + .../3.html | 553 + .../4.html | 365 + .../5.html | 2695 +++++ .../6.html | 371 + .../7.html | 10425 +++++++++++++++++++ .../8.html | 563 + .../9.html | 5217 ++++++++++ .../index.html | 313 + .../stats.html | 186 + .../style.css | 177 + 16 files changed, 26595 insertions(+) create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/0.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/1.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/10.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/11.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/12.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/2.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/3.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/4.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/5.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/6.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/7.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/8.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/9.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/index.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/stats.html create mode 100644 2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/style.css (limited to '2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master') diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/0.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/0.html new file mode 100644 index 0000000..838ce20 --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/0.html @@ -0,0 +1,2005 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
/*
+ * Copyright (C) 2002 - 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "desktop-entries.h"
+#include <gio/gdesktopappinfo.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include <string.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "menu-util.h"
+
+#define DESKTOP_ENTRY_GROUP     "Desktop Entry"
+
+struct DesktopEntry
+{
+  guint       refcount;
+
+  char       *path;
+  const char *basename;
+
+  guint       type      : 2;
+  guint       reserved  : 30;
+};
+
+typedef struct
+{
+  DesktopEntry     base;
+
+  GDesktopAppInfo *appinfo;
+  GQuark          *categories;
+} DesktopEntryDesktop;
+
+typedef struct
+{
+  DesktopEntry base;
+
+  char     *name;
+  char     *generic_name;
+  char     *comment;
+  GIcon    *icon;
+  char     *full_name;
+  char     *exec;
+
+  guint     nodisplay : 1;
+  guint     hidden    : 1;
+  guint     showin    : 1;
+  guint     terminal  : 1;
+} DesktopEntryDirectory;
+
+struct DesktopEntrySet {
+	int refcount;
+	GHashTable* hash;
+};
+
+/*
+ * Desktop entries
+ */
+
+/**
+ * unix_basename_from_path:
+ * @path: Path string
+ *
+ * Returns: A constant pointer into the basename of @path
+ */
+static const char *
+unix_basename_from_path (const char *path)
+{
+  const char *basename = g_strrstr (path, "/");
+  if (basename)
+    return basename + 1;
+  else
+    return path;
+}
+
+static const char *
+get_current_desktop (void)
+{
+  static char *current_desktop = NULL;
+
+  /* Support XDG_CURRENT_DESKTOP environment variable; this can be used
+   * to abuse mate-menus in non-MATE desktops. */
+  if (!current_desktop)
+    {
+      const char *desktop;
+
+      desktop = g_getenv ("XDG_CURRENT_DESKTOP");
+
+      /* Note: if XDG_CURRENT_DESKTOP is set but empty, do as if it
+       * was not set */
+      if (!desktop || desktop[0] == '\0')
+        current_desktop = g_strdup ("MATE");
+      else
+        current_desktop = g_strdup (desktop);
+    }
+
+  /* Using "*" means skipping desktop-related checks */
+  if (g_strcmp0 (current_desktop, "*") == 0)
+    return NULL;
+
+  return current_desktop;
+}
+
+static GIcon *
+key_file_get_icon (GKeyFile *key_file)
+{
+  GIcon *icon = NULL;
+  gchar *icon_name;
+
+  icon_name = g_key_file_get_locale_string (key_file, DESKTOP_ENTRY_GROUP,
+                                            "Icon", NULL, NULL);
+  if (!icon_name)
+    return NULL;
+
+  if (g_path_is_absolute (icon_name)) {
+    GFile *file;
+
+    file = g_file_new_for_path (icon_name);
+    icon = g_file_icon_new (file);
+    g_object_unref (file);
+  } else {
+    char *p;
+
+    /* Work around a common mistake in desktop files */
+    if ((p = strrchr (icon_name, '.')) != NULL &&
+        (strcmp (p, ".png") == 0 ||
+         strcmp (p, ".xpm") == 0 ||
+         strcmp (p, ".svg") == 0))
+      *p = 0;
+
+    icon = g_themed_icon_new (icon_name);
+  }
+
+  g_free (icon_name);
+
+  return icon;
+}
+
+static gboolean
+key_file_get_show_in (GKeyFile *key_file)
+{
+  const gchar *current_desktop;
+  gchar **strv;
+  gboolean show_in = TRUE;
+  int i;
+
+  current_desktop = get_current_desktop ();
+  if (!current_desktop)
+    return TRUE;
+
+  strv = g_key_file_get_string_list (key_file,
+                                     DESKTOP_ENTRY_GROUP,
+                                     "OnlyShowIn",
+                                     NULL,
+                                     NULL);
+  if (strv)
+    {
+      show_in = FALSE;
+      for (i = 0; strv[i]; i++)
+        {
+          if (!strcmp (strv[i], current_desktop))
+            {
+              show_in = TRUE;
+              break;
+            }
+        }
+    }
+  else
+    {
+      strv = g_key_file_get_string_list (key_file,
+                                         DESKTOP_ENTRY_GROUP,
+                                         "NotShowIn",
+                                         NULL,
+                                         NULL);
+      if (strv)
+        {
+          show_in = TRUE;
+          for (i = 0; strv[i]; i++)
+            {
+              if (!strcmp (strv[i], current_desktop))
+                {
+                  show_in = FALSE;
+                }
+            }
+        }
+    }
+  g_strfreev (strv);
+
+  return show_in;
+}
+
+static gboolean
+desktop_entry_load_directory (DesktopEntry  *entry,
+                              GKeyFile      *key_file,
+                              GError       **error)
+{
+  DesktopEntryDirectory *entry_directory = (DesktopEntryDirectory*)entry;
+  char *type_str;
+
+  type_str = g_key_file_get_string (key_file, DESKTOP_ENTRY_GROUP, "Type", error);
+  if (!type_str)
+    return FALSE;
+
+  if (strcmp (type_str, "Directory") != 0)
+    {
+      g_set_error (error,
+                   G_KEY_FILE_ERROR,
+                   G_KEY_FILE_ERROR_INVALID_VALUE,
+                   "\"%s\" does not contain the correct \"Type\" value\n", entry->path);
+      g_free (type_str);
+      return FALSE;
+    }
+
+  g_free (type_str);
+
+  entry_directory->name = g_key_file_get_locale_string (key_file, DESKTOP_ENTRY_GROUP, "Name", NULL, error);
+  if (entry_directory->name == NULL)
+    return FALSE;
+
+  entry_directory->generic_name = g_key_file_get_locale_string (key_file, DESKTOP_ENTRY_GROUP, "GenericName", NULL, NULL);
+  entry_directory->comment      = g_key_file_get_locale_string (key_file, DESKTOP_ENTRY_GROUP, "Comment", NULL, NULL);
+  entry_directory->icon         = key_file_get_icon (key_file);
+  entry_directory->nodisplay    = g_key_file_get_boolean (key_file, DESKTOP_ENTRY_GROUP, "NoDisplay", NULL) != FALSE;
+  entry_directory->hidden       = g_key_file_get_boolean (key_file, DESKTOP_ENTRY_GROUP, "Hidden", NULL) != FALSE;
+  entry_directory->showin       = key_file_get_show_in (key_file) != FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+desktop_entry_load (DesktopEntry *entry)
+{
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    {
+      DesktopEntryDesktop *entry_desktop = (DesktopEntryDesktop*)entry;
+      const char *categories_str;
+
+      entry_desktop->appinfo = g_desktop_app_info_new_from_filename (entry->path);
+      if (!entry_desktop->appinfo ||
+          !g_app_info_get_name (G_APP_INFO (entry_desktop->appinfo)) ||
+          !g_app_info_get_executable (G_APP_INFO (entry_desktop->appinfo)))
+        {
+          menu_verbose ("Failed to load \"%s\"\n", entry->path);
+          return FALSE;
+        }
+
+      categories_str = g_desktop_app_info_get_categories (entry_desktop->appinfo);
+      if (categories_str)
+        {
+          char **categories;
+          int i;
+
+          categories = g_strsplit (categories_str, ";", -1);
+          entry_desktop->categories = g_new0 (GQuark, g_strv_length (categories) + 1);
+
+          for (i = 0; categories[i]; i++)
+            entry_desktop->categories[i] = g_quark_from_string (categories[i]);
+
+          g_strfreev (categories);
+        }
+
+      return TRUE;
+    }
+  else if (entry->type == DESKTOP_ENTRY_DIRECTORY)
+    {
+      GKeyFile *key_file = NULL;
+      GError   *error = NULL;
+      gboolean  retval = FALSE;
+
+      key_file = g_key_file_new ();
+
+      if (!g_key_file_load_from_file (key_file, entry->path, 0, &error))
+        goto out;
+
+      if (!desktop_entry_load_directory (entry, key_file, &error))
+        goto out;
+
+      retval = TRUE;
+
+    out:
+      g_key_file_free (key_file);
+
+      if (!retval)
+        {
+          if (error)
+            {
+              menu_verbose ("Failed to load \"%s\": %s\n", entry->path, error->message);
+              g_error_free (error);
+            }
+          else
+            {
+              menu_verbose ("Failed to load \"%s\"\n", entry->path);
+            }
+        }
+
+      return retval;
+    }
+  else
+    g_assert_not_reached ();
+
+  return FALSE;
+}
+
+DesktopEntry* desktop_entry_new(const char* path)
+{
+  DesktopEntryType  type;
+  DesktopEntry     *retval;
+
+  menu_verbose ("Loading desktop entry \"%s\"\n", path);
+
+  if (g_str_has_suffix (path, ".desktop"))
+    {
+      type = DESKTOP_ENTRY_DESKTOP;
+      retval = (DesktopEntry*)g_new0 (DesktopEntryDesktop, 1);
+    }
+  else if (g_str_has_suffix (path, ".directory"))
+    {
+      type = DESKTOP_ENTRY_DIRECTORY;
+      retval = (DesktopEntry*)g_new0 (DesktopEntryDirectory, 1);
+    }
+  else
+    {
+      menu_verbose ("Unknown desktop entry suffix in \"%s\"\n",
+                    path);
+      return NULL;
+    }
+
+  retval->refcount = 1;
+  retval->type     = type;
+  retval->path     = g_strdup (path);
+  retval->basename = unix_basename_from_path (retval->path);
+
+  if (!desktop_entry_load (retval))
+    {
+      desktop_entry_unref (retval);
+      return NULL;
+    }
+
+  return retval;
+}
+
+DesktopEntry* desktop_entry_reload(DesktopEntry* entry)
+{
+  g_return_val_if_fail (entry != NULL, NULL);
+
+  menu_verbose ("Re-loading desktop entry \"%s\"\n", entry->path);
+
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    {
+      DesktopEntryDesktop *entry_desktop = (DesktopEntryDesktop *) entry;
+
+      g_object_unref (entry_desktop->appinfo);
+      entry_desktop->appinfo = NULL;
+
+      g_free (entry_desktop->categories);
+      entry_desktop->categories = NULL;
+    }
+  else if (entry->type == DESKTOP_ENTRY_DIRECTORY)
+    {
+      DesktopEntryDirectory *entry_directory = (DesktopEntryDirectory*) entry;
+
+      g_free (entry_directory->name);
+      entry_directory->name = NULL;
+
+      g_free (entry_directory->comment);
+      entry_directory->comment = NULL;
+
+      g_object_unref (entry_directory->icon);
+      entry_directory->icon = NULL;
+    }
+  else
+    g_assert_not_reached ();
+
+  if (!desktop_entry_load (entry))
+    {
+      desktop_entry_unref (entry);
+      return NULL;
+    }
+
+  return entry;
+}
+
+DesktopEntry* desktop_entry_ref(DesktopEntry* entry)
+{
+  g_return_val_if_fail (entry != NULL, NULL);
+  g_return_val_if_fail (entry->refcount > 0, NULL);
+
+  entry->refcount += 1;
+
+  return entry;
+}
+
+DesktopEntry* desktop_entry_copy(DesktopEntry* entry)
+{
+  DesktopEntry *retval;
+
+  menu_verbose ("Copying desktop entry \"%s\"\n",
+                entry->basename);
+
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    retval = (DesktopEntry*)g_new0 (DesktopEntryDesktop, 1);
+  else if (entry->type == DESKTOP_ENTRY_DIRECTORY)
+    retval = (DesktopEntry*)g_new0 (DesktopEntryDirectory, 1);
+  else
+    g_assert_not_reached ();
+
+  retval->refcount     = 1;
+  retval->type         = entry->type;
+  retval->path         = g_strdup (entry->path);
+  retval->basename     = unix_basename_from_path (retval->path);
+
+  if (retval->type == DESKTOP_ENTRY_DESKTOP)
+    {
+      DesktopEntryDesktop *desktop_entry = (DesktopEntryDesktop*) entry;
+      DesktopEntryDesktop *retval_desktop_entry = (DesktopEntryDesktop*) retval;
+
+      retval_desktop_entry->appinfo = g_object_ref (desktop_entry->appinfo);
+
+      if (desktop_entry->categories != NULL)
+        {
+          gsize i;
+
+          i = 0;
+          for (; desktop_entry->categories[i]; i++);
+
+          retval_desktop_entry->categories = g_new0 (GQuark, i + 1);
+
+          i = 0;
+          for (; desktop_entry->categories[i]; i++)
+            retval_desktop_entry->categories[i] = desktop_entry->categories[i];
+        }
+      else
+        retval_desktop_entry->categories = NULL;
+    }
+  else if (entry->type == DESKTOP_ENTRY_DIRECTORY)
+    {
+      DesktopEntryDirectory *entry_directory = (DesktopEntryDirectory*)entry;
+      DesktopEntryDirectory *retval_directory = (DesktopEntryDirectory*)retval;
+
+      retval_directory->name         = g_strdup (entry_directory->name);
+      retval_directory->comment      = g_strdup (entry_directory->comment);
+      retval_directory->icon         = g_object_ref (entry_directory->icon);
+      retval_directory->nodisplay    = entry_directory->nodisplay;
+      retval_directory->hidden       = entry_directory->hidden;
+      retval_directory->showin       = entry_directory->showin;
+    }
+
+  return retval;
+}
+
+void desktop_entry_unref(DesktopEntry* entry)
+{
+  g_return_if_fail (entry != NULL);
+  g_return_if_fail (entry->refcount > 0);
+
+  entry->refcount -= 1;
+  if (entry->refcount != 0)
+    return;
+
+  g_free (entry->path);
+  entry->path = NULL;
+
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    {
+      DesktopEntryDesktop *desktop_entry = (DesktopEntryDesktop*) entry;
+      g_free (desktop_entry->categories);
+      if (desktop_entry->appinfo)
+        g_object_unref (desktop_entry->appinfo);
+    }
+  else if (entry->type == DESKTOP_ENTRY_DIRECTORY)
+    {
+      DesktopEntryDirectory *entry_directory = (DesktopEntryDirectory*) entry;
+
+      g_free (entry_directory->name);
+      entry_directory->name = NULL;
+
+      g_free (entry_directory->comment);
+      entry_directory->comment = NULL;
+
+      if (entry_directory->icon != NULL)
+        {
+          g_object_unref (entry_directory->icon);
+          entry_directory->icon = NULL;
+        }
+    }
+  else
+    g_assert_not_reached ();
+
+  g_free (entry);
+}
+
+DesktopEntryType desktop_entry_get_type(DesktopEntry* entry)<--- Parameter 'entry' can be declared as pointer to const
+{
+	return entry->type;
+}
+
+const char* desktop_entry_get_path(DesktopEntry* entry)<--- Parameter 'entry' can be declared as pointer to const
+{
+	return entry->path;
+}
+
+const char *
+desktop_entry_get_basename (DesktopEntry *entry)<--- Parameter 'entry' can be declared as pointer to const
+{
+	return entry->basename;
+}
+
+const char* desktop_entry_get_name(DesktopEntry* entry)
+{
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    return g_app_info_get_name (G_APP_INFO (((DesktopEntryDesktop*)entry)->appinfo));
+  return ((DesktopEntryDirectory*)entry)->name;
+}
+
+const char* desktop_entry_get_generic_name(DesktopEntry* entry)
+{
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    return g_desktop_app_info_get_generic_name (((DesktopEntryDesktop*)entry)->appinfo);
+  return ((DesktopEntryDirectory*)entry)->generic_name;
+}
+
+const char* desktop_entry_get_comment(DesktopEntry* entry)
+{
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    return g_app_info_get_description (G_APP_INFO (((DesktopEntryDesktop*)entry)->appinfo));
+  return ((DesktopEntryDirectory*)entry)->comment;
+}
+
+GIcon *
+desktop_entry_get_icon (DesktopEntry *entry)
+{
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    return g_app_info_get_icon (G_APP_INFO (((DesktopEntryDesktop*)entry)->appinfo));
+  return ((DesktopEntryDirectory*)entry)->icon;
+}
+
+gboolean desktop_entry_get_no_display (DesktopEntry *entry)
+{
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    return g_desktop_app_info_get_nodisplay (((DesktopEntryDesktop*)entry)->appinfo);
+  return ((DesktopEntryDirectory*)entry)->nodisplay;
+}
+
+gboolean desktop_entry_get_hidden(DesktopEntry* entry)
+{
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    return g_desktop_app_info_get_is_hidden (((DesktopEntryDesktop*)entry)->appinfo);
+  return ((DesktopEntryDirectory*)entry)->hidden;
+}
+
+gboolean
+desktop_entry_get_show_in (DesktopEntry *entry)
+{
+  if (entry->type == DESKTOP_ENTRY_DESKTOP)
+    {
+      const char *current_desktop = get_current_desktop ();
+
+      if (current_desktop == NULL)
+        return TRUE;
+      else
+        return g_desktop_app_info_get_show_in (((DesktopEntryDesktop*)entry)->appinfo, current_desktop);
+    }
+  return ((DesktopEntryDirectory*)entry)->showin;
+}
+
+GDesktopAppInfo  *
+desktop_entry_get_app_info (DesktopEntry *entry)
+{
+  g_return_val_if_fail (entry->type == DESKTOP_ENTRY_DESKTOP, NULL);
+  return ((DesktopEntryDesktop*)entry)->appinfo;
+}
+
+gboolean desktop_entry_has_categories(DesktopEntry* entry)
+{
+  DesktopEntryDesktop *desktop_entry;
+  if (entry->type != DESKTOP_ENTRY_DESKTOP)
+    return FALSE;
+
+  desktop_entry = (DesktopEntryDesktop*) entry;
+  return (desktop_entry->categories != NULL && desktop_entry->categories[0] != 0);
+}
+
+gboolean desktop_entry_has_category(DesktopEntry* entry, const char* category)
+{
+  GQuark quark;
+  int    i;
+  DesktopEntryDesktop *desktop_entry;<--- Variable 'desktop_entry' can be declared as pointer to const
+
+  if (entry->type != DESKTOP_ENTRY_DESKTOP)
+    return FALSE;
+
+  desktop_entry = (DesktopEntryDesktop*) entry;
+
+  if (desktop_entry->categories == NULL)
+    return FALSE;
+
+  if (!(quark = g_quark_try_string (category)))
+    return FALSE;
+
+  for (i = 0; desktop_entry->categories[i]; i++)
+    {
+      if (quark == desktop_entry->categories[i])
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+void desktop_entry_add_legacy_category(DesktopEntry* entry)
+{
+  GQuark *categories;
+  gsize   i;
+  DesktopEntryDesktop *desktop_entry;
+
+  g_return_if_fail (entry->type == DESKTOP_ENTRY_DESKTOP);
+
+  desktop_entry = (DesktopEntryDesktop*) entry;
+
+  menu_verbose ("Adding Legacy category to \"%s\"\n",
+                entry->basename);
+
+  if (desktop_entry->categories != NULL)
+    {
+      i = 0;
+      for (; desktop_entry->categories[i]; i++);
+
+      categories = g_new0 (GQuark, i + 2);
+
+      i = 0;
+      for (; desktop_entry->categories[i]; i++)
+        categories[i] = desktop_entry->categories[i];
+    }
+  else
+    {
+      categories = g_new0 (GQuark, 2);
+      i = 0;
+    }
+
+  categories[i] = g_quark_from_string ("Legacy");
+
+  g_free (desktop_entry->categories);
+  desktop_entry->categories = categories;
+}
+
+/*
+ * Entry sets
+ */
+
+DesktopEntrySet* desktop_entry_set_new(void)
+{
+  DesktopEntrySet *set;
+
+  set = g_new0 (DesktopEntrySet, 1);
+  set->refcount = 1;
+
+  menu_verbose (" New entry set %p\n", set);
+
+  return set;
+}
+
+DesktopEntrySet* desktop_entry_set_ref(DesktopEntrySet* set)
+{
+  g_return_val_if_fail (set != NULL, NULL);
+  g_return_val_if_fail (set->refcount > 0, NULL);
+
+  set->refcount += 1;
+
+  return set;
+}
+
+void desktop_entry_set_unref(DesktopEntrySet* set)
+{
+  g_return_if_fail (set != NULL);
+  g_return_if_fail (set->refcount > 0);
+
+  set->refcount -= 1;
+  if (set->refcount == 0)
+    {
+      menu_verbose (" Deleting entry set %p\n", set);
+
+      if (set->hash)
+        g_hash_table_destroy (set->hash);
+      set->hash = NULL;
+
+      g_free (set);
+    }
+}
+
+void desktop_entry_set_add_entry(DesktopEntrySet* set, DesktopEntry* entry, const char* file_id)
+{
+  menu_verbose (" Adding to set %p entry %s\n", set, file_id);
+
+  if (set->hash == NULL)
+    {
+      set->hash = g_hash_table_new_full (g_str_hash,
+                                         g_str_equal,
+                                         g_free,
+                                         (GDestroyNotify) desktop_entry_unref);
+    }
+
+  g_hash_table_replace (set->hash,
+                        g_strdup (file_id),
+                        desktop_entry_ref (entry));
+}
+
+DesktopEntry* desktop_entry_set_lookup(DesktopEntrySet* set, const char* file_id)
+{
+  if (set->hash == NULL)
+    return NULL;
+
+  return g_hash_table_lookup (set->hash, file_id);
+}
+
+typedef struct {
+	DesktopEntrySetForeachFunc func;
+	gpointer user_data;
+} EntryHashForeachData;
+
+static void entry_hash_foreach(const char* file_id, DesktopEntry* entry, EntryHashForeachData* fd)
+{
+	fd->func(file_id, entry, fd->user_data);
+}
+
+void desktop_entry_set_foreach(DesktopEntrySet* set, DesktopEntrySetForeachFunc func, gpointer user_data)
+{
+  g_return_if_fail (set != NULL);
+  g_return_if_fail (func != NULL);
+
+  if (set->hash != NULL)
+    {
+      EntryHashForeachData fd;
+
+      fd.func      = func;
+      fd.user_data = user_data;
+
+      g_hash_table_foreach (set->hash,
+                            (GHFunc) entry_hash_foreach,
+                            &fd);
+    }
+}
+
+static void desktop_entry_set_clear(DesktopEntrySet* set)
+{
+  menu_verbose (" Clearing set %p\n", set);
+
+  if (set->hash != NULL)
+    {
+      g_hash_table_destroy (set->hash);
+      set->hash = NULL;
+    }
+}
+
+guint
+desktop_entry_set_get_count (DesktopEntrySet *set)
+{
+  if (set->hash == NULL)
+    return 0;
+
+  return g_hash_table_size (set->hash);
+}
+
+static void union_foreach(const char* file_id, DesktopEntry* entry, DesktopEntrySet* set)
+{
+	/* we are iterating over "with" adding anything not
+	 * already in "set". We unconditionally overwrite
+	 * the stuff in "set" because we can assume
+	 * two entries with the same name are equivalent.
+	 */
+	desktop_entry_set_add_entry(set, entry, file_id);
+}
+
+void desktop_entry_set_union(DesktopEntrySet* set, DesktopEntrySet* with)
+{
+  menu_verbose (" Union of %p and %p\n", set, with);
+
+  if (desktop_entry_set_get_count (with) == 0)
+    return; /* A fast simple case */
+
+  g_hash_table_foreach (with->hash,
+                        (GHFunc) union_foreach,
+                        set);
+}
+
+typedef struct {
+	DesktopEntrySet *set;
+	DesktopEntrySet *with;
+} IntersectData;
+
+static gboolean intersect_foreach_remove(const char* file_id, DesktopEntry* entry, IntersectData* id)
+{
+  /* Remove everything in "set" which is not in "with" */
+
+  if (g_hash_table_lookup (id->with->hash, file_id) != NULL)
+    return FALSE;
+
+  menu_verbose (" Removing from %p entry %s\n", id->set, file_id);
+
+  return TRUE; /* return TRUE to remove */
+}
+
+void desktop_entry_set_intersection(DesktopEntrySet* set, DesktopEntrySet* with)
+{
+  IntersectData id;
+
+  menu_verbose (" Intersection of %p and %p\n", set, with);
+
+  if (desktop_entry_set_get_count (set) == 0 ||
+      desktop_entry_set_get_count (with) == 0)
+    {
+      /* A fast simple case */
+      desktop_entry_set_clear (set);
+      return;
+    }
+
+  id.set  = set;
+  id.with = with;
+
+  g_hash_table_foreach_remove (set->hash,
+                               (GHRFunc) intersect_foreach_remove,
+                               &id);
+}
+
+typedef struct {
+	DesktopEntrySet *set;
+	DesktopEntrySet *other;
+} SubtractData;
+
+static gboolean subtract_foreach_remove(const char* file_id, DesktopEntry* entry, SubtractData* sd)
+{
+  /* Remove everything in "set" which is not in "other" */
+
+  if (g_hash_table_lookup (sd->other->hash, file_id) == NULL)
+    return FALSE;
+
+  menu_verbose (" Removing from %p entry %s\n", sd->set, file_id);
+
+  return TRUE; /* return TRUE to remove */
+}
+
+void desktop_entry_set_subtract(DesktopEntrySet* set, DesktopEntrySet* other)
+{
+  SubtractData sd;
+
+  menu_verbose (" Subtract from %p set %p\n", set, other);
+
+  if (desktop_entry_set_get_count (set) == 0 ||
+      desktop_entry_set_get_count (other) == 0)
+    return; /* A fast simple case */
+
+  sd.set   = set;
+  sd.other = other;
+
+  g_hash_table_foreach_remove (set->hash,
+                               (GHRFunc) subtract_foreach_remove,
+                               &sd);
+}
+
+void desktop_entry_set_swap_contents(DesktopEntrySet* a, DesktopEntrySet* b)
+{
+	GHashTable *tmp;
+
+	menu_verbose (" Swap contents of %p and %p\n", a, b);
+
+	tmp = a->hash;
+	 a->hash = b->hash;
+	b->hash = tmp;
+}
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/1.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/1.html new file mode 100644 index 0000000..a7ec54b --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/1.html @@ -0,0 +1,403 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
/*
+ * Copyright (C) 2002 - 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __DESKTOP_ENTRIES_H__
+#define __DESKTOP_ENTRIES_H__
+
+#include <gio/gdesktopappinfo.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+G_BEGIN_DECLS
+
+typedef enum {
+	DESKTOP_ENTRY_INVALID = 0,
+	DESKTOP_ENTRY_DESKTOP,
+	DESKTOP_ENTRY_DIRECTORY
+} DesktopEntryType;
+
+typedef struct DesktopEntry DesktopEntry;
+
+DesktopEntry* desktop_entry_new(const char* path);
+
+DesktopEntry* desktop_entry_ref(DesktopEntry* entry);
+DesktopEntry* desktop_entry_copy(DesktopEntry* entry);
+DesktopEntry* desktop_entry_reload(DesktopEntry* entry);
+void desktop_entry_unref(DesktopEntry* entry);
+
+DesktopEntryType  desktop_entry_get_type     (DesktopEntry *entry);
+const char       *desktop_entry_get_path     (DesktopEntry *entry);
+const char       *desktop_entry_get_basename (DesktopEntry *entry);
+const char       *desktop_entry_get_name     (DesktopEntry *entry);
+const char       *desktop_entry_get_generic_name (DesktopEntry *entry);
+const char       *desktop_entry_get_comment  (DesktopEntry *entry);
+GIcon            *desktop_entry_get_icon     (DesktopEntry *entry);
+gboolean          desktop_entry_get_hidden   (DesktopEntry *entry);
+gboolean          desktop_entry_get_no_display (DesktopEntry *entry);
+gboolean          desktop_entry_get_show_in  (DesktopEntry *entry);
+
+/* Only valid for DESKTOP_ENTRY_DESKTOP */
+GDesktopAppInfo  *desktop_entry_get_app_info (DesktopEntry *entry);
+gboolean desktop_entry_has_categories (DesktopEntry *entry);
+gboolean desktop_entry_has_category   (DesktopEntry *entry,
+                                       const char   *category);
+
+void desktop_entry_add_legacy_category(DesktopEntry* src);
+
+typedef struct DesktopEntrySet DesktopEntrySet;
+
+DesktopEntrySet* desktop_entry_set_new(void);
+DesktopEntrySet* desktop_entry_set_ref(DesktopEntrySet* set);
+void desktop_entry_set_unref(DesktopEntrySet* set);
+
+void desktop_entry_set_add_entry(DesktopEntrySet* set, DesktopEntry* entry, const char* file_id);
+DesktopEntry* desktop_entry_set_lookup(DesktopEntrySet* set, const char* file_id);
+guint desktop_entry_set_get_count (DesktopEntrySet *set);
+
+void desktop_entry_set_union(DesktopEntrySet* set, DesktopEntrySet* with);
+void desktop_entry_set_intersection(DesktopEntrySet* set, DesktopEntrySet* with);
+void desktop_entry_set_subtract(DesktopEntrySet* set, DesktopEntrySet* other);
+void desktop_entry_set_swap_contents(DesktopEntrySet* a, DesktopEntrySet* b);
+
+typedef void (*DesktopEntrySetForeachFunc) (const char* file_id, DesktopEntry* entry, gpointer user_data);
+
+void desktop_entry_set_foreach(DesktopEntrySet* set, DesktopEntrySetForeachFunc func, gpointer user_data);
+
+G_END_DECLS
+
+#endif /* __DESKTOP_ENTRIES_H__ */
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/10.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/10.html new file mode 100644 index 0000000..7e6a3da --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/10.html @@ -0,0 +1,1103 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
/*
+ * Copyright (C) 2005 Red Hat, Inc.
+ * Copyright (C) 2006 Mark McLoughlin
+ * Copyright (C) 2007 Sebastian Dröge
+ * Copyright (C) 2008 Vincent Untz
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "menu-monitor.h"
+
+#include <gio/gio.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "menu-util.h"
+
+struct MenuMonitor {
+	char* path;
+	guint refcount;
+
+	GSList* notifies;
+
+	GFileMonitor* monitor;
+
+	guint is_directory: 1;
+};
+
+typedef struct {
+	MenuMonitor* monitor;
+	MenuMonitorEvent event;
+	char* path;
+} MenuMonitorEventInfo;
+
+typedef struct {
+	MenuMonitorNotifyFunc notify_func;
+	gpointer user_data;
+	guint refcount;
+} MenuMonitorNotify;
+
+static MenuMonitorNotify* mate_menu_monitor_notify_ref(MenuMonitorNotify* notify);
+static void mate_menu_monitor_notify_unref(MenuMonitorNotify* notify);
+
+static GHashTable* monitors_registry = NULL;
+static guint events_idle_handler = 0;
+static GSList* pending_events = NULL;
+
+static void invoke_notifies(MenuMonitor* monitor, MenuMonitorEvent  event, const char* path)
+{
+  GSList *copy;
+  GSList *tmp;
+
+  copy = g_slist_copy (monitor->notifies);
+  g_slist_foreach (copy,
+		   (GFunc) mate_menu_monitor_notify_ref,
+		   NULL);
+
+  tmp = copy;
+  while (tmp != NULL)
+    {
+      MenuMonitorNotify *notify = tmp->data;
+      GSList            *next   = tmp->next;
+
+      if (notify->notify_func)
+	{
+	  notify->notify_func (monitor, event, path, notify->user_data);
+	}
+
+      mate_menu_monitor_notify_unref(notify);
+
+      tmp = next;
+    }
+
+  g_slist_free (copy);
+}
+
+static gboolean emit_events_in_idle(void)
+{
+  GSList *events_to_emit;
+  GSList *tmp;
+
+  events_to_emit = pending_events;
+
+  pending_events = NULL;
+  events_idle_handler = 0;
+
+  tmp = events_to_emit;
+  while (tmp != NULL)
+    {
+      MenuMonitorEventInfo *event_info = tmp->data;
+
+      mate_menu_monitor_ref(event_info->monitor);
+
+      tmp = tmp->next;
+    }
+
+  tmp = events_to_emit;
+  while (tmp != NULL)
+    {
+      MenuMonitorEventInfo *event_info = tmp->data;
+
+      invoke_notifies (event_info->monitor,
+		       event_info->event,
+		       event_info->path);
+
+      menu_monitor_unref (event_info->monitor);
+      event_info->monitor = NULL;
+
+      g_free (event_info->path);
+      event_info->path = NULL;
+
+      event_info->event = MENU_MONITOR_EVENT_INVALID;
+
+      g_free (event_info);
+
+      tmp = tmp->next;
+    }
+
+  g_slist_free (events_to_emit);
+
+  return FALSE;
+}
+
+static void menu_monitor_queue_event(MenuMonitorEventInfo* event_info)
+{
+  pending_events = g_slist_append (pending_events, event_info);
+
+  if (events_idle_handler == 0)
+    {
+      events_idle_handler = g_idle_add ((GSourceFunc) emit_events_in_idle, NULL);
+    }
+}
+
+static inline char* get_registry_key(const char* path, gboolean is_directory)
+{
+  return g_strdup_printf ("%s:%s",
+			  path,
+			  is_directory ? "<dir>" : "<file>");
+}
+
+static gboolean monitor_callback (GFileMonitor* monitor, GFile* child, GFile* other_file, GFileMonitorEvent eflags, gpointer user_data)
+{
+  MenuMonitorEventInfo *event_info;
+  MenuMonitorEvent      event;
+  MenuMonitor          *menu_monitor = (MenuMonitor *) user_data;
+
+  event = MENU_MONITOR_EVENT_INVALID;
+  switch (eflags)
+    {
+    case G_FILE_MONITOR_EVENT_CHANGED:
+      event = MENU_MONITOR_EVENT_CHANGED;
+      break;
+    case G_FILE_MONITOR_EVENT_CREATED:
+      event = MENU_MONITOR_EVENT_CREATED;
+      break;
+    case G_FILE_MONITOR_EVENT_DELETED:
+      event = MENU_MONITOR_EVENT_DELETED;
+      break;
+    default:
+      return TRUE;
+    }
+
+  event_info = g_new0 (MenuMonitorEventInfo, 1);
+
+  event_info->path    = g_file_get_path (child);
+  event_info->event   = event;
+  event_info->monitor = menu_monitor;
+
+  menu_monitor_queue_event (event_info);
+
+  return TRUE;
+}
+
+static MenuMonitor* register_monitor(const char* path, gboolean is_directory)
+{
+  MenuMonitor     *retval;
+  GFile           *file;
+
+  retval = g_new0 (MenuMonitor, 1);
+
+  retval->path         = g_strdup (path);
+  retval->refcount     = 1;
+  retval->is_directory = is_directory != FALSE;
+
+  file = g_file_new_for_path (retval->path);
+
+  if (file == NULL)
+    {
+      menu_verbose ("Not adding monitor on '%s', failed to create GFile\n",
+                    retval->path);
+      return retval;
+    }
+
+  if (retval->is_directory)
+      retval->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE,
+                                                  NULL, NULL);
+  else
+      retval->monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE,
+                                             NULL, NULL);
+
+  g_object_unref (G_OBJECT (file));
+
+  if (retval->monitor == NULL)
+    {
+      menu_verbose ("Not adding monitor on '%s', failed to create monitor\n",
+                    retval->path);
+      return retval;
+    }
+
+  g_signal_connect (retval->monitor, "changed",
+                    G_CALLBACK (monitor_callback), retval);
+
+  return retval;
+}
+
+static MenuMonitor* lookup_monitor(const char* path, gboolean is_directory)
+{
+  MenuMonitor *retval;
+  char        *registry_key;
+
+  retval = NULL;
+
+  registry_key = get_registry_key (path, is_directory);
+
+  if (monitors_registry == NULL)
+    {
+      monitors_registry = g_hash_table_new_full (g_str_hash,
+						 g_str_equal,
+						 g_free,
+						 NULL);
+    }
+  else
+    {
+      retval = g_hash_table_lookup (monitors_registry, registry_key);
+    }
+
+  if (retval == NULL)
+    {
+      retval = register_monitor (path, is_directory);
+      g_hash_table_insert (monitors_registry, registry_key, retval);
+
+      return retval;
+    }
+  else
+    {
+      g_free (registry_key);
+
+      return mate_menu_monitor_ref(retval);
+    }
+}
+
+MenuMonitor* mate_menu_monitor_file_get(const char* path)
+{
+	g_return_val_if_fail(path != NULL, NULL);
+
+	return lookup_monitor(path, FALSE);
+}
+
+MenuMonitor* menu_get_directory_monitor(const char* path)
+{
+  g_return_val_if_fail (path != NULL, NULL);
+
+  return lookup_monitor (path, TRUE);
+}
+
+MenuMonitor* mate_menu_monitor_ref(MenuMonitor* monitor)
+{
+	g_return_val_if_fail(monitor != NULL, NULL);
+	g_return_val_if_fail(monitor->refcount > 0, NULL);
+
+	monitor->refcount++;
+
+	return monitor;
+}
+
+static void menu_monitor_clear_pending_events(MenuMonitor* monitor)<--- Parameter 'monitor' can be declared as pointer to const
+{
+  GSList *tmp;
+
+  tmp = pending_events;
+  while (tmp != NULL)
+    {
+      MenuMonitorEventInfo *event_info = tmp->data;
+      GSList               *next = tmp->next;
+
+      if (event_info->monitor == monitor)
+	{
+	  pending_events = g_slist_delete_link (pending_events, tmp);
+
+	  g_free (event_info->path);
+	  event_info->path = NULL;
+
+	  event_info->monitor = NULL;
+	  event_info->event   = MENU_MONITOR_EVENT_INVALID;
+
+	  g_free (event_info);
+	}
+
+      tmp = next;
+    }
+}
+
+void menu_monitor_unref(MenuMonitor* monitor)
+{
+  char *registry_key;
+
+  g_return_if_fail (monitor != NULL);
+  g_return_if_fail (monitor->refcount > 0);
+
+  if (--monitor->refcount > 0)
+    return;
+
+  registry_key = get_registry_key (monitor->path, monitor->is_directory);
+  g_hash_table_remove (monitors_registry, registry_key);
+  g_free (registry_key);
+
+  if (g_hash_table_size (monitors_registry) == 0)
+    {
+      g_hash_table_destroy (monitors_registry);
+      monitors_registry = NULL;
+    }
+
+  if (monitor->monitor)
+    {
+      g_file_monitor_cancel (monitor->monitor);
+      g_object_unref (monitor->monitor);
+      monitor->monitor = NULL;
+    }
+
+  g_slist_foreach (monitor->notifies, (GFunc) mate_menu_monitor_notify_unref, NULL);
+  g_slist_free (monitor->notifies);
+  monitor->notifies = NULL;
+
+  menu_monitor_clear_pending_events (monitor);
+
+  g_free (monitor->path);
+  monitor->path = NULL;
+
+  g_free (monitor);
+}
+
+static MenuMonitorNotify* mate_menu_monitor_notify_ref(MenuMonitorNotify* notify)
+{
+	g_return_val_if_fail(notify != NULL, NULL);
+	g_return_val_if_fail(notify->refcount > 0, NULL);
+
+	notify->refcount++;
+
+	return notify;
+}
+
+static void mate_menu_monitor_notify_unref(MenuMonitorNotify* notify)
+{
+	g_return_if_fail(notify != NULL);
+	g_return_if_fail(notify->refcount > 0);
+
+	if (--notify->refcount > 0)
+	{
+		return;
+	}
+
+	g_free(notify);
+}
+
+void menu_monitor_add_notify(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data)
+{
+	GSList* tmp;<--- Variable 'tmp' can be declared as pointer to const
+	MenuMonitorNotify* notify;
+
+	g_return_if_fail(monitor != NULL);
+	g_return_if_fail(notify_func != NULL);
+
+	tmp = monitor->notifies;
+
+	while (tmp != NULL)
+	{
+		notify = tmp->data;
+
+		if (notify->notify_func == notify_func && notify->user_data == user_data)
+		{
+			break;
+		}
+
+		tmp = tmp->next;
+	}
+
+	if (tmp == NULL)
+	{
+		notify = g_new0(MenuMonitorNotify, 1);
+		notify->notify_func = notify_func;
+		notify->user_data = user_data;
+		notify->refcount = 1;
+
+		monitor->notifies = g_slist_append(monitor->notifies, notify);
+	}
+}
+
+void mate_menu_monitor_notify_remove(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data)
+{
+	GSList* tmp = monitor->notifies;
+
+	while (tmp != NULL)
+	{
+		MenuMonitorNotify* notify = tmp->data;
+		GSList* next = tmp->next;
+
+		if (notify->notify_func == notify_func && notify->user_data == user_data)
+		{
+			notify->notify_func = NULL;
+			notify->user_data = NULL;
+
+			mate_menu_monitor_notify_unref(notify);
+
+			monitor->notifies = g_slist_delete_link(monitor->notifies, tmp);
+		}
+
+		tmp = next;
+	}
+}
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/11.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/11.html new file mode 100644 index 0000000..3975c85 --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/11.html @@ -0,0 +1,1109 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
/* Random utility functions for menu code */
+
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "menu-util.h"
+
+#include <stdio.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <stdarg.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#ifdef G_ENABLE_DEBUG
+
+static gboolean verbose = FALSE;
+static gboolean initted = FALSE;
+
+static inline gboolean menu_verbose_enabled(void)
+{
+	if (!initted)
+	{
+		verbose = g_getenv("MENU_VERBOSE") != NULL;
+		initted = TRUE;
+	}
+
+	return verbose;
+}
+
+static int utf8_fputs(const char* str, FILE* f)
+{
+	char* l;
+	int ret;
+
+	l = g_locale_from_utf8(str, -1, NULL, NULL, NULL);
+
+	if (l == NULL)
+	{
+		ret = fputs(str, f); /* just print it anyway, better than nothing */
+	}
+	else
+	{
+		ret = fputs(l, f);
+	}
+
+	g_free(l);
+
+	return ret;
+}
+
+void menu_verbose(const char* format, ...)
+{
+	va_list args;
+	char* str;
+
+	if (!menu_verbose_enabled())
+	{
+		return;
+	}
+
+	va_start(args, format);
+	str = g_strdup_vprintf(format, args);
+	va_end(args);
+
+	utf8_fputs(str, stderr);
+	fflush(stderr);
+
+	g_free(str);
+}
+
+static void append_to_string(MenuLayoutNode* node, gboolean onelevel, int depth, GString* str);
+
+static void append_spaces(GString* str, int depth)
+{
+	while (depth > 0)
+	{
+		g_string_append_c(str, ' ');
+		--depth;
+	}
+}
+
+static void append_children(MenuLayoutNode* node, int depth, GString* str)
+{
+	MenuLayoutNode* iter;
+
+	iter = menu_layout_node_get_children(node);
+
+	while (iter != NULL)
+	{
+		append_to_string(iter, FALSE, depth, str);
+
+		iter = menu_layout_node_get_next(iter);
+	}
+}
+
+static void append_simple_with_attr(MenuLayoutNode* node, int depth, const char* node_name, const char* attr_name, const char* attr_value, GString* str)
+{
+	const char* content;
+
+	append_spaces(str, depth);
+
+	if ((content = menu_layout_node_get_content(node)))
+	{
+		char* escaped;
+
+		escaped = g_markup_escape_text(content, -1);
+
+		if (attr_name && attr_value)
+		{
+			char* attr_escaped;
+
+			attr_escaped = g_markup_escape_text(attr_value, -1);
+
+			g_string_append_printf(str, "<%s %s=\"%s\">%s</%s>\n", node_name, attr_name, attr_escaped, escaped, node_name);
+
+			g_free(attr_escaped);
+		}
+		else
+		{
+			g_string_append_printf(str, "<%s>%s</%s>\n", node_name, escaped, node_name);
+		}
+
+		g_free(escaped);
+	}
+	else
+	{
+		if (attr_name && attr_value)
+		{
+			char* attr_escaped;
+
+			attr_escaped = g_markup_escape_text(attr_value, -1);
+
+			g_string_append_printf(str, "<%s %s=\"%s\"/>\n", node_name, attr_name, attr_escaped);
+
+			g_free(attr_escaped);
+		}
+		else
+		{
+			g_string_append_printf(str, "<%s/>\n", node_name);
+		}
+	}
+}
+
+static void append_layout(MenuLayoutNode* node, int depth, const char* node_name, MenuLayoutValues* layout_values, GString* str)
+{
+	const char* content;
+
+	append_spaces(str, depth);
+
+	if ((content = menu_layout_node_get_content(node)))
+	{
+		char* escaped;
+
+		escaped = g_markup_escape_text(content, -1);
+
+		g_string_append_printf(str,
+			"<%s show_empty=\"%s\" inline=\"%s\" inline_header=\"%s\""
+			" inline_alias=\"%s\" inline_limit=\"%d\">%s</%s>\n",
+			node_name,
+			layout_values->show_empty    ? "true" : "false",
+			layout_values->inline_menus  ? "true" : "false",
+			layout_values->inline_header ? "true" : "false",
+			layout_values->inline_alias  ? "true" : "false",
+			(gint) layout_values->inline_limit,
+			escaped,
+			node_name);
+
+		g_free(escaped);
+	}
+	else
+	{
+	  g_string_append_printf(str,
+		"<%s show_empty=\"%s\" inline=\"%s\" inline_header=\"%s\""
+		" inline_alias=\"%s\" inline_limit=\"%d\"/>\n",
+		node_name,
+		layout_values->show_empty    ? "true" : "false",
+		layout_values->inline_menus  ? "true" : "false",
+		layout_values->inline_header ? "true" : "false",
+		layout_values->inline_alias  ? "true" : "false",
+		(gint) layout_values->inline_limit);
+	}
+}
+
+static void append_merge(MenuLayoutNode* node, int depth, const char* node_name, MenuLayoutMergeType merge_type, GString* str)
+{
+	const char* merge_type_str;
+
+	merge_type_str = NULL;
+
+	switch (merge_type)
+	{
+		case MENU_LAYOUT_MERGE_NONE:
+			merge_type_str = "none";
+			break;
+
+		case MENU_LAYOUT_MERGE_MENUS:
+			merge_type_str = "menus";
+			break;
+
+		case MENU_LAYOUT_MERGE_FILES:
+			merge_type_str = "files";
+			break;
+
+		case MENU_LAYOUT_MERGE_ALL:
+			merge_type_str = "all";
+			break;
+
+		default:
+			g_assert_not_reached();
+			break;
+	}
+
+	append_simple_with_attr(node, depth, node_name, "type", merge_type_str, str);
+}
+
+static void append_simple(MenuLayoutNode* node, int depth, const char* node_name, GString* str)
+{
+	append_simple_with_attr(node, depth, node_name, NULL, NULL, str);
+}
+
+static void append_start(MenuLayoutNode* node, int depth, const char* node_name, GString* str)
+{
+	append_spaces(str, depth);
+
+	g_string_append_printf(str, "<%s>\n", node_name);
+}
+
+static void append_end(MenuLayoutNode* node, int depth, const char* node_name, GString* str)
+{
+	append_spaces(str, depth);
+
+	g_string_append_printf(str, "</%s>\n", node_name);
+}
+
+static void append_container(MenuLayoutNode* node, gboolean onelevel, int depth, const char* node_name, GString* str)
+{
+	append_start(node, depth, node_name, str);
+
+	if (!onelevel)
+	{
+		append_children(node, depth + 2, str);
+		append_end(node, depth, node_name, str);
+	}
+}
+
+static void append_to_string(MenuLayoutNode* node, gboolean onelevel, int depth, GString* str)
+{
+	MenuLayoutValues layout_values;
+
+	switch (menu_layout_node_get_type(node))
+	{
+		case MENU_LAYOUT_NODE_ROOT:
+			if (!onelevel)
+				append_children(node, depth - 1, str); /* -1 to ignore depth of root */
+			else
+			append_start(node, depth - 1, "Root", str);
+			break;
+
+		case MENU_LAYOUT_NODE_PASSTHROUGH:
+			g_string_append(str, menu_layout_node_get_content(node));
+			g_string_append_c(str, '\n');
+			break;
+
+		case MENU_LAYOUT_NODE_MENU:
+			append_container(node, onelevel, depth, "Menu", str);
+			break;
+
+		case MENU_LAYOUT_NODE_APP_DIR:
+			append_simple(node, depth, "AppDir", str);
+			break;
+
+		case MENU_LAYOUT_NODE_DEFAULT_APP_DIRS:
+			append_simple(node, depth, "DefaultAppDirs", str);
+			break;
+
+		case MENU_LAYOUT_NODE_DIRECTORY_DIR:
+			append_simple(node, depth, "DirectoryDir", str);
+			break;
+
+		case MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS:
+			append_simple(node, depth, "DefaultDirectoryDirs", str);
+			break;
+
+		case MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS:
+			append_simple(node, depth, "DefaultMergeDirs", str);
+			break;
+
+		case MENU_LAYOUT_NODE_NAME:
+			append_simple(node, depth, "Name", str);
+			break;
+
+		case MENU_LAYOUT_NODE_DIRECTORY:
+			append_simple(node, depth, "Directory", str);
+			break;
+
+		case MENU_LAYOUT_NODE_ONLY_UNALLOCATED:
+			append_simple(node, depth, "OnlyUnallocated", str);
+			break;
+
+		case MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED:
+			append_simple(node, depth, "NotOnlyUnallocated", str);
+			break;
+
+		case MENU_LAYOUT_NODE_INCLUDE:
+			append_container(node, onelevel, depth, "Include", str);
+			break;
+
+		case MENU_LAYOUT_NODE_EXCLUDE:
+			append_container(node, onelevel, depth, "Exclude", str);
+			break;
+
+		case MENU_LAYOUT_NODE_FILENAME:
+			append_simple(node, depth, "Filename", str);
+			break;
+
+		case MENU_LAYOUT_NODE_CATEGORY:
+			append_simple(node, depth, "Category", str);
+			break;
+
+		case MENU_LAYOUT_NODE_ALL:
+			append_simple(node, depth, "All", str);
+			break;
+
+		case MENU_LAYOUT_NODE_AND:
+			append_container(node, onelevel, depth, "And", str);
+			break;
+
+		case MENU_LAYOUT_NODE_OR:
+			append_container(node, onelevel, depth, "Or", str);
+			break;
+
+		case MENU_LAYOUT_NODE_NOT:
+			append_container(node, onelevel, depth, "Not", str);
+			break;
+
+		case MENU_LAYOUT_NODE_MERGE_FILE:
+		{
+			MenuMergeFileType type;
+
+			type = menu_layout_node_merge_file_get_type(node);
+
+			append_simple_with_attr(node, depth, "MergeFile", "type", type == MENU_MERGE_FILE_TYPE_PARENT ? "parent" : "path", str);
+			break;
+		}
+
+		case MENU_LAYOUT_NODE_MERGE_DIR:
+			append_simple(node, depth, "MergeDir", str);
+			break;
+
+		case MENU_LAYOUT_NODE_LEGACY_DIR:
+			append_simple_with_attr(node, depth, "LegacyDir", "prefix", menu_layout_node_legacy_dir_get_prefix (node), str);
+			break;
+
+		case MENU_LAYOUT_NODE_KDE_LEGACY_DIRS:
+			append_simple(node, depth, "KDELegacyDirs", str);
+			break;
+
+		case MENU_LAYOUT_NODE_MOVE:
+			append_container(node, onelevel, depth, "Move", str);
+			break;
+
+		case MENU_LAYOUT_NODE_OLD:
+			append_simple(node, depth, "Old", str);
+			break;
+
+		case MENU_LAYOUT_NODE_NEW:
+			append_simple(node, depth, "New", str);
+			break;
+
+		case MENU_LAYOUT_NODE_DELETED:
+			append_simple(node, depth, "Deleted", str);
+			break;
+
+		case MENU_LAYOUT_NODE_NOT_DELETED:
+			append_simple(node, depth, "NotDeleted", str);
+			break;
+
+		case MENU_LAYOUT_NODE_LAYOUT:
+			append_container(node, onelevel, depth, "Layout", str);
+			break;
+
+		case MENU_LAYOUT_NODE_DEFAULT_LAYOUT:
+			menu_layout_node_default_layout_get_values(node, &layout_values);
+			append_layout(node, depth, "DefaultLayout", &layout_values, str);
+			break;
+
+		case MENU_LAYOUT_NODE_MENUNAME:
+			menu_layout_node_menuname_get_values(node, &layout_values);
+			append_layout(node, depth, "MenuName", &layout_values, str);
+			break;
+
+		case MENU_LAYOUT_NODE_SEPARATOR:
+			append_simple(node, depth, "Name", str);
+			break;
+
+		case MENU_LAYOUT_NODE_MERGE:
+			append_merge(node, depth, "Merge", menu_layout_node_merge_get_type(node), str);
+			break;
+
+		default:
+			g_assert_not_reached();
+			break;
+	}
+}
+
+void menu_debug_print_layout(MenuLayoutNode* node, gboolean onelevel)
+{
+	if (menu_verbose_enabled())
+	{
+		GString* str = g_string_new(NULL);
+		append_to_string(node, onelevel, 0, str);
+
+		utf8_fputs(str->str, stderr);
+		fflush(stderr);
+
+		g_string_free(str, TRUE);
+	}
+}
+
+#endif /* G_ENABLE_DEBUG */
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/12.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/12.html new file mode 100644 index 0000000..7d9316f --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/12.html @@ -0,0 +1,765 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
/*
+ * Copyright (C) 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <glib/gi18n.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#ifdef ENABLE_NLS
+#include <locale.h>
+#endif
+
+#include "matemenu-tree.h"<--- Include file: "matemenu-tree.h" not found.
+
+#include <string.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+static char     *menu_file = NULL;
+static gboolean  monitor = FALSE;
+static gboolean  include_excluded = FALSE;
+static gboolean  include_nodisplay = FALSE;
+static gboolean  include_unallocated = FALSE;
+
+static GOptionEntry options[] = {
+	{ "file",                'f', 0, G_OPTION_ARG_STRING, &menu_file,           N_("Menu file"),                      N_("MENU_FILE") },
+	{ "monitor",             'm', 0, G_OPTION_ARG_NONE,   &monitor,             N_("Monitor for menu changes"),       NULL },
+	{ "include-excluded",    'i', 0, G_OPTION_ARG_NONE,   &include_excluded,    N_("Include <Exclude>d entries"),     NULL },
+	{ "include-nodisplay",   'n', 0, G_OPTION_ARG_NONE,   &include_nodisplay,   N_("Include NoDisplay=true entries"), NULL },
+	{ "include-unallocated", 'u', 0, G_OPTION_ARG_NONE,   &include_unallocated, N_("Include unallocated entries"),    NULL },
+	{ NULL,                    0, 0, G_OPTION_ARG_NONE,   NULL,                 NULL,                                 NULL }
+};
+
+static void
+append_directory_path (MateMenuTreeDirectory *directory,
+		GString            *path)
+{
+	MateMenuTreeDirectory *parent;
+
+	parent = matemenu_tree_directory_get_parent(directory);
+
+	if (!parent)
+	{
+		g_string_append_c(path, '/');
+		return;
+	}
+
+	append_directory_path(parent, path);
+
+	g_string_append(path, matemenu_tree_directory_get_name (directory));
+	g_string_append_c(path, '/');
+
+	matemenu_tree_item_unref(parent);
+}
+
+static char *
+make_path (MateMenuTreeDirectory *directory)
+{
+	GString *path;
+
+	g_return_val_if_fail(directory != NULL, NULL);
+
+	path = g_string_new(NULL);
+
+	append_directory_path(directory, path);
+
+	return g_string_free(path, FALSE);
+}
+
+static void
+print_entry (MateMenuTreeEntry *entry,
+		const char     *path)
+{
+	char *utf8_path;
+	char *utf8_file_id;
+
+	utf8_path = g_filename_to_utf8(matemenu_tree_entry_get_desktop_file_path (entry),
+			-1, NULL, NULL, NULL);
+
+	utf8_file_id = g_filename_to_utf8(matemenu_tree_entry_get_desktop_file_id (entry),
+			-1, NULL, NULL, NULL);
+
+	g_print("%s\t%s\t%s%s\n",
+			path,
+			utf8_file_id ? utf8_file_id : _("Invalid desktop file ID"),
+			utf8_path ? utf8_path : _("[Invalid Filename]"),
+			matemenu_tree_entry_get_is_excluded(entry) ? _(" <excluded>") : "");
+
+	g_free(utf8_file_id);
+	g_free(utf8_path);
+}
+
+static void
+print_directory(MateMenuTreeDirectory *directory)
+{
+	MateMenuTreeIter *iter;
+	const char *path;
+	char       *freeme;
+
+	freeme = make_path(directory);
+	if (!strcmp (freeme, "/"))
+		path = freeme;
+	else
+		path = freeme + 1;
+
+	iter = matemenu_tree_directory_iter(directory);
+
+	while(TRUE)
+	{
+		gpointer item;
+
+		switch (matemenu_tree_iter_next (iter))
+		{
+			case MATEMENU_TREE_ITEM_INVALID:
+				goto done;
+
+			case MATEMENU_TREE_ITEM_ENTRY:
+				item = matemenu_tree_iter_get_entry(iter);
+				print_entry((MateMenuTreeEntry*)item, path);
+				break;
+
+			case MATEMENU_TREE_ITEM_DIRECTORY:
+				item = matemenu_tree_iter_get_directory(iter);
+				print_directory((MateMenuTreeDirectory*)item);
+				break;
+
+			case MATEMENU_TREE_ITEM_HEADER:
+			case MATEMENU_TREE_ITEM_SEPARATOR:
+				item = NULL;
+				break;
+
+			case MATEMENU_TREE_ITEM_ALIAS:
+				{
+					item = matemenu_tree_iter_get_alias(iter);
+
+					if (matemenu_tree_alias_get_aliased_item_type (item) == MATEMENU_TREE_ITEM_ENTRY)
+					{
+						MateMenuTreeEntry *entry = matemenu_tree_alias_get_aliased_entry(item);
+						print_entry(entry, path);
+						matemenu_tree_item_unref(entry);
+					}
+				}
+				break;
+
+			default:
+				g_assert_not_reached();
+				break;
+		}
+
+		matemenu_tree_item_unref(item);
+		continue;
+done:
+		break;
+	}
+
+	matemenu_tree_iter_unref(iter);
+
+	g_free(freeme);
+}
+
+static void
+handle_tree_changed (MateMenuTree *tree)
+{
+	MateMenuTreeDirectory *root;
+	GError *error = NULL;
+
+	g_print(_("\n\n\n==== Menu changed, reloading ====\n\n\n"));
+
+	if(!matemenu_tree_load_sync (tree, &error))
+	{
+		g_printerr("Failed to load tree: %s\n", error->message);
+		g_clear_error(&error);
+		return;
+	}
+
+	root = matemenu_tree_get_root_directory(tree);
+	if (root == NULL)
+	{
+		g_warning(_("Menu tree is empty"));
+		return;
+	}
+
+	print_directory(root);
+	matemenu_tree_item_unref(root);
+}
+
+int
+main (int argc, char **argv)
+{
+	GOptionContext    *options_context;
+	MateMenuTree          *tree;
+	MateMenuTreeDirectory *root;
+	MateMenuTreeFlags      flags;
+	GError             *error = NULL;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_ALL, "");
+	bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+#endif /* ENABLE_NLS */
+
+	options_context = g_option_context_new(_("- test MATE's implementation of the Desktop Menu Specification"));
+	g_option_context_add_main_entries(options_context, options, GETTEXT_PACKAGE);
+	g_option_context_parse(options_context, &argc, &argv, NULL);
+	g_option_context_free(options_context);
+
+	flags = MATEMENU_TREE_FLAGS_NONE;
+	if (include_excluded)
+		flags |= MATEMENU_TREE_FLAGS_INCLUDE_EXCLUDED;
+	if (include_nodisplay)
+		flags |= MATEMENU_TREE_FLAGS_INCLUDE_NODISPLAY;
+	if (include_unallocated)
+		flags |= MATEMENU_TREE_FLAGS_INCLUDE_UNALLOCATED;
+
+	tree = matemenu_tree_new(menu_file ? menu_file : "mate-applications.menu", flags);
+	g_assert(tree != NULL);
+
+	if (!matemenu_tree_load_sync (tree, &error))
+	{
+		g_printerr("Failed to load tree: %s\n", error->message);
+		return 1;
+	}
+
+	g_print("Loaded menu from %s\n", matemenu_tree_get_canonical_menu_path(tree));
+
+	root = matemenu_tree_get_root_directory(tree);
+	if (root != NULL)
+	{
+		print_directory(root);
+		matemenu_tree_item_unref(root);
+	}
+	else
+	{
+		g_warning(_("Menu tree is empty"));
+	}
+
+	if (monitor)
+	{
+		GMainLoop *main_loop;
+
+		g_signal_connect(tree, "changed", G_CALLBACK(handle_tree_changed), NULL);
+
+		main_loop = g_main_loop_new(NULL, FALSE);
+		g_main_loop_run(main_loop);
+		g_main_loop_unref(main_loop);
+	}
+
+	g_object_unref(tree);
+
+	return 0;
+}
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/2.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/2.html new file mode 100644 index 0000000..27c0f8d --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/2.html @@ -0,0 +1,345 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
/* Random utility functions for menu code */
+
+/*
+ * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MENU_UTIL_H__
+#define __MENU_UTIL_H__
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "menu-layout.h"
+
+G_BEGIN_DECLS
+
+
+#ifdef G_ENABLE_DEBUG
+
+void menu_verbose(const char* format, ...) G_GNUC_PRINTF(1, 2);
+void menu_debug_print_layout(MenuLayoutNode* node, gboolean onelevel);
+
+#else /* !defined(G_ENABLE_DEBUG) */
+
+#ifdef G_HAVE_ISO_VARARGS
+#define menu_verbose(...)
+#elif defined(G_HAVE_GNUC_VARARGS)
+#define menu_verbose(format...)
+#else
+#error "Cannot disable verbose mode due to lack of varargs macros"
+#endif
+
+#define menu_debug_print_layout(n, o)
+
+#endif /* G_ENABLE_DEBUG */
+
+G_END_DECLS
+
+#endif /* __MENU_UTIL_H__ */
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/3.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/3.html new file mode 100644 index 0000000..9348217 --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/3.html @@ -0,0 +1,553 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
/* Menu layout in-memory data structure (a custom "DOM tree") */
+
+/*
+ * Copyright (C) 2002 - 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MENU_LAYOUT_H__
+#define __MENU_LAYOUT_H__
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "entry-directories.h"
+
+G_BEGIN_DECLS
+
+typedef struct MenuLayoutNode MenuLayoutNode;
+
+typedef enum {
+	MENU_LAYOUT_NODE_ROOT,
+	MENU_LAYOUT_NODE_PASSTHROUGH,
+	MENU_LAYOUT_NODE_MENU,
+	MENU_LAYOUT_NODE_APP_DIR,
+	MENU_LAYOUT_NODE_DEFAULT_APP_DIRS,
+	MENU_LAYOUT_NODE_DIRECTORY_DIR,
+	MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS,
+	MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS,
+	MENU_LAYOUT_NODE_NAME,
+	MENU_LAYOUT_NODE_DIRECTORY,
+	MENU_LAYOUT_NODE_ONLY_UNALLOCATED,
+	MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED,
+	MENU_LAYOUT_NODE_INCLUDE,
+	MENU_LAYOUT_NODE_EXCLUDE,
+	MENU_LAYOUT_NODE_FILENAME,
+	MENU_LAYOUT_NODE_CATEGORY,
+	MENU_LAYOUT_NODE_ALL,
+	MENU_LAYOUT_NODE_AND,
+	MENU_LAYOUT_NODE_OR,
+	MENU_LAYOUT_NODE_NOT,
+	MENU_LAYOUT_NODE_MERGE_FILE,
+	MENU_LAYOUT_NODE_MERGE_DIR,
+	MENU_LAYOUT_NODE_LEGACY_DIR,
+	MENU_LAYOUT_NODE_KDE_LEGACY_DIRS,
+	MENU_LAYOUT_NODE_MOVE,
+	MENU_LAYOUT_NODE_OLD,
+	MENU_LAYOUT_NODE_NEW,
+	MENU_LAYOUT_NODE_DELETED,
+	MENU_LAYOUT_NODE_NOT_DELETED,
+	MENU_LAYOUT_NODE_LAYOUT,
+	MENU_LAYOUT_NODE_DEFAULT_LAYOUT,
+	MENU_LAYOUT_NODE_MENUNAME,
+	MENU_LAYOUT_NODE_SEPARATOR,
+	MENU_LAYOUT_NODE_MERGE
+} MenuLayoutNodeType;
+
+typedef enum {
+	MENU_MERGE_FILE_TYPE_PATH = 0,
+	MENU_MERGE_FILE_TYPE_PARENT
+} MenuMergeFileType;
+
+typedef enum {
+	MENU_LAYOUT_MERGE_NONE,
+	MENU_LAYOUT_MERGE_MENUS,
+	MENU_LAYOUT_MERGE_FILES,
+	MENU_LAYOUT_MERGE_ALL
+} MenuLayoutMergeType;
+
+typedef enum {
+	MENU_LAYOUT_VALUES_NONE          = 0,
+	MENU_LAYOUT_VALUES_SHOW_EMPTY    = 1 << 0,
+	MENU_LAYOUT_VALUES_INLINE_MENUS  = 1 << 1,
+	MENU_LAYOUT_VALUES_INLINE_LIMIT  = 1 << 2,
+	MENU_LAYOUT_VALUES_INLINE_HEADER = 1 << 3,
+	MENU_LAYOUT_VALUES_INLINE_ALIAS  = 1 << 4
+} MenuLayoutValuesMask;
+
+typedef struct {
+	MenuLayoutValuesMask mask;
+
+	guint show_empty: 1;
+	guint inline_menus: 1;
+	guint inline_header: 1;
+	guint inline_alias: 1;
+
+	guint inline_limit;
+} MenuLayoutValues;
+
+
+MenuLayoutNode *menu_layout_load (const char* filename, const char  *non_prefixed_basename, GError** error);
+
+MenuLayoutNode *menu_layout_node_new   (MenuLayoutNodeType  type);
+MenuLayoutNode *menu_layout_node_ref   (MenuLayoutNode     *node);
+void            menu_layout_node_unref (MenuLayoutNode     *node);
+
+MenuLayoutNodeType menu_layout_node_get_type (MenuLayoutNode *node);
+
+MenuLayoutNode *menu_layout_node_get_root     (MenuLayoutNode *node);
+MenuLayoutNode *menu_layout_node_get_parent   (MenuLayoutNode *node);
+MenuLayoutNode *menu_layout_node_get_children (MenuLayoutNode *node);
+MenuLayoutNode *menu_layout_node_get_next     (MenuLayoutNode *node);
+
+void menu_layout_node_insert_before (MenuLayoutNode *node, MenuLayoutNode *new_sibling);
+void menu_layout_node_insert_after  (MenuLayoutNode *node, MenuLayoutNode *new_sibling);
+void menu_layout_node_prepend_child (MenuLayoutNode *parent, MenuLayoutNode *new_child);
+void menu_layout_node_append_child  (MenuLayoutNode *parent, MenuLayoutNode *new_child);
+
+void menu_layout_node_unlink (MenuLayoutNode *node);
+void menu_layout_node_steal  (MenuLayoutNode *node);
+
+const char *menu_layout_node_get_content (MenuLayoutNode *node);
+void        menu_layout_node_set_content (MenuLayoutNode *node, const char     *content);
+
+char *menu_layout_node_get_content_as_path (MenuLayoutNode *node);
+
+const char *menu_layout_node_root_get_name    (MenuLayoutNode *node);
+const char *menu_layout_node_root_get_basedir (MenuLayoutNode *node);
+
+const char         *menu_layout_node_menu_get_name           (MenuLayoutNode *node);
+EntryDirectoryList *menu_layout_node_menu_get_app_dirs       (MenuLayoutNode *node);
+EntryDirectoryList *menu_layout_node_menu_get_directory_dirs (MenuLayoutNode *node);
+
+const char *menu_layout_node_move_get_old (MenuLayoutNode *node);
+const char *menu_layout_node_move_get_new (MenuLayoutNode *node);
+
+const char *menu_layout_node_legacy_dir_get_prefix (MenuLayoutNode *node);
+void        menu_layout_node_legacy_dir_set_prefix (MenuLayoutNode *node, const char     *prefix);
+
+MenuMergeFileType menu_layout_node_merge_file_get_type (MenuLayoutNode    *node);
+void              menu_layout_node_merge_file_set_type (MenuLayoutNode    *node, MenuMergeFileType  type);
+
+MenuLayoutMergeType menu_layout_node_merge_get_type (MenuLayoutNode *node);
+
+void menu_layout_node_default_layout_get_values (MenuLayoutNode   *node, MenuLayoutValues *values);
+void menu_layout_node_menuname_get_values       (MenuLayoutNode   *node, MenuLayoutValues *values);
+
+typedef void (*MenuLayoutNodeEntriesChangedFunc) (MenuLayoutNode* node, gpointer user_data);
+
+void menu_layout_node_root_add_entries_monitor    (MenuLayoutNode* node, MenuLayoutNodeEntriesChangedFunc callback, gpointer user_data);
+void menu_layout_node_root_remove_entries_monitor (MenuLayoutNode* node, MenuLayoutNodeEntriesChangedFunc callback, gpointer user_data);
+
+G_END_DECLS
+
+#endif /* __MENU_LAYOUT_H__ */
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/4.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/4.html new file mode 100644 index 0000000..f08400a --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/4.html @@ -0,0 +1,365 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
/*
+ * Copyright (C) 2002 - 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ENTRY_DIRECTORIES_H__
+#define __ENTRY_DIRECTORIES_H__
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include "desktop-entries.h"
+
+G_BEGIN_DECLS
+
+typedef struct EntryDirectory EntryDirectory;
+
+typedef void (*EntryDirectoryChangedFunc) (EntryDirectory* ed, gpointer user_data);
+
+EntryDirectory* entry_directory_new(DesktopEntryType entry_type, const char* path);
+EntryDirectory* entry_directory_new_legacy(DesktopEntryType entry_type, const char* path, const char* legacy_prefix);
+
+EntryDirectory* entry_directory_ref(EntryDirectory* ed);
+void entry_directory_unref(EntryDirectory* ed);
+
+void entry_directory_get_flat_contents(EntryDirectory* ed, DesktopEntrySet* desktop_entries, DesktopEntrySet* directory_entries, GSList** subdirs);
+
+
+typedef struct EntryDirectoryList EntryDirectoryList;
+
+EntryDirectoryList* entry_directory_list_new(void);
+EntryDirectoryList* entry_directory_list_ref(EntryDirectoryList* list);
+void entry_directory_list_unref(EntryDirectoryList* list);
+
+int  entry_directory_list_get_length(EntryDirectoryList* list);
+gboolean _entry_directory_list_compare(const EntryDirectoryList* a, const EntryDirectoryList* b);
+
+void entry_directory_list_prepend(EntryDirectoryList* list, EntryDirectory* ed);
+void entry_directory_list_append_list(EntryDirectoryList* list, EntryDirectoryList* to_append);
+
+void entry_directory_list_add_monitors(EntryDirectoryList* list, EntryDirectoryChangedFunc callback, gpointer user_data);
+void entry_directory_list_remove_monitors(EntryDirectoryList* list, EntryDirectoryChangedFunc callback, gpointer user_data);
+
+DesktopEntry* entry_directory_list_get_directory (EntryDirectoryList* list, const char* relative_path);
+
+DesktopEntrySet* _entry_directory_list_get_all_desktops(EntryDirectoryList* list);
+void _entry_directory_list_empty_desktop_cache(void);
+
+G_END_DECLS
+
+#endif /* __ENTRY_DIRECTORIES_H__ */
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/5.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/5.html new file mode 100644 index 0000000..1c6ad40 --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/5.html @@ -0,0 +1,2695 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
/*
+ * Copyright (C) 2002 - 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* used for realpath() */
+#define _XOPEN_SOURCE 500
+
+#include <config.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "entry-directories.h"
+
+#include <string.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <errno.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <sys/types.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <dirent.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <stdlib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "menu-util.h"
+#include "menu-monitor.h"
+
+typedef struct CachedDir CachedDir;
+typedef struct CachedDirMonitor CachedDirMonitor;
+
+struct EntryDirectory {
+	CachedDir* dir;
+	char* legacy_prefix;
+
+	guint entry_type: 2;
+	guint is_legacy: 1;
+	guint refcount: 24;
+};
+
+struct EntryDirectoryList {
+	int refcount;
+	int length;
+	GList* dirs;
+};
+
+struct CachedDir {
+	CachedDir* parent;
+	char* name;
+
+	GSList* entries;
+	GSList* subdirs;
+
+	MenuMonitor* dir_monitor;
+	GSList* monitors;
+
+	guint have_read_entries: 1;
+	guint deleted: 1;
+
+  guint references;
+
+  GFunc    notify;
+  gpointer notify_data;
+};
+
+struct CachedDirMonitor {
+	EntryDirectory* ed;
+	EntryDirectoryChangedFunc callback;
+	gpointer user_data;
+};
+
+static void     cached_dir_add_reference          (CachedDir *dir);
+static void     cached_dir_remove_reference       (CachedDir *dir);
+static void     cached_dir_free                   (CachedDir  *dir);
+static gboolean cached_dir_load_entries_recursive (CachedDir  *dir,
+                                                   const char *dirname);
+static void     cached_dir_unref                  (CachedDir *dir);
+static void     cached_dir_unref_noparent         (CachedDir *dir);
+static CachedDir * cached_dir_add_subdir          (CachedDir  *dir,
+                                                   const char *basename,
+                                                   const char *path);
+static gboolean cached_dir_remove_subdir          (CachedDir  *dir,
+                                                   const char *basename);
+
+static void handle_cached_dir_changed (MenuMonitor      *monitor,
+				       MenuMonitorEvent  event,
+				       const char       *path,
+				       CachedDir        *dir);
+
+/*
+ * Entry directory cache
+ */
+
+static CachedDir* dir_cache = NULL;
+
+static void
+clear_cache (CachedDir *dir,
+             gpointer  *cache)
+{
+  *cache = NULL;
+}
+
+static CachedDir *
+cached_dir_new (const char *name)
+{
+	CachedDir* dir;
+
+  dir = g_new0 (CachedDir, 1);
+  dir->name = g_strdup (name);
+
+	return dir;
+}
+
+static CachedDir *
+cached_dir_new_full (const char *name,
+                     GFunc       notify,
+                     gpointer    notify_data)
+{
+  CachedDir *dir;
+
+  dir = cached_dir_new (name);
+
+  dir->notify = notify;
+  dir->notify_data = notify_data;
+
+  return dir;
+}
+
+static void
+cached_dir_free (CachedDir *dir)
+{
+  if (dir->dir_monitor)
+    {
+      menu_monitor_remove_notify (dir->dir_monitor,
+				  (MenuMonitorNotifyFunc) handle_cached_dir_changed,
+				  dir);
+      menu_monitor_unref (dir->dir_monitor);
+      dir->dir_monitor = NULL;
+    }
+
+  g_slist_foreach (dir->monitors, (GFunc) g_free, NULL);
+  g_slist_free (dir->monitors);
+  dir->monitors = NULL;
+
+  g_slist_foreach (dir->entries,
+                   (GFunc) desktop_entry_unref,
+                   NULL);
+  g_slist_free (dir->entries);
+  dir->entries = NULL;
+
+  g_slist_foreach (dir->subdirs,
+                   (GFunc) cached_dir_unref_noparent,
+                   NULL);
+  g_slist_free (dir->subdirs);
+  dir->subdirs = NULL;
+
+  g_free (dir->name);
+  g_free (dir);
+}
+
+static CachedDir *
+cached_dir_ref (CachedDir *dir)
+{
+  dir->references++;
+  return dir;
+}
+
+static void
+cached_dir_unref (CachedDir *dir)
+{
+  if (--dir->references == 0)
+    {
+      CachedDir *parent;
+
+      parent = dir->parent;
+
+      if (parent != NULL)
+        cached_dir_remove_subdir (parent, dir->name);
+
+      if (dir->notify)
+        dir->notify (dir, dir->notify_data);
+
+      cached_dir_free (dir);
+    }
+}
+
+static void
+cached_dir_unref_noparent (CachedDir *dir)
+{
+  if (--dir->references == 0)
+    {
+      if (dir->notify)
+        dir->notify (dir, dir->notify_data);
+
+      cached_dir_free (dir);
+    }
+}
+
+static inline CachedDir* find_subdir(CachedDir* dir, const char* subdir)
+{
+  GSList *tmp;<--- Variable 'tmp' can be declared as pointer to const
+
+  tmp = dir->subdirs;
+  while (tmp != NULL)
+    {
+      CachedDir *sub = tmp->data;
+
+      if (strcmp (sub->name, subdir) == 0)
+        return sub;
+
+      tmp = tmp->next;
+    }
+
+  return NULL;
+}
+
+static DesktopEntry* find_entry(CachedDir* dir, const char* basename)
+{
+  GSList *tmp;
+
+  tmp = dir->entries;
+  while (tmp != NULL)
+    {
+      if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
+        return tmp->data;
+
+      tmp = tmp->next;
+    }
+
+  return NULL;
+}
+
+static DesktopEntry* cached_dir_find_relative_path(CachedDir* dir, const char* relative_path)
+{
+  DesktopEntry  *retval = NULL;
+  char         **split;
+  int            i;
+
+  split = g_strsplit (relative_path, "/", -1);
+
+  i = 0;
+  while (split[i] != NULL)
+    {
+      if (split[i + 1] != NULL)
+        {
+          if ((dir = find_subdir (dir, split[i])) == NULL)
+            break;
+        }
+      else
+        {
+          retval = find_entry (dir, split[i]);
+          break;
+        }
+
+      ++i;
+    }
+
+  g_strfreev (split);
+
+  return retval;
+}
+
+static CachedDir* cached_dir_lookup(const char* canonical)
+{
+  CachedDir  *dir;
+  char      **split;
+  int         i;
+
+  if (dir_cache == NULL)
+    dir_cache = cached_dir_new_full ("/",
+                                     (GFunc) clear_cache,
+                                     &dir_cache);
+  dir = dir_cache;
+
+  g_assert (canonical != NULL && canonical[0] == G_DIR_SEPARATOR);
+
+  menu_verbose ("Looking up cached dir \"%s\"\n", canonical);
+
+  split = g_strsplit (canonical + 1, "/", -1);
+
+  i = 0;
+  while (split[i] != NULL)
+    {
+      CachedDir *subdir;
+
+      subdir = cached_dir_add_subdir (dir, split[i], NULL);
+
+      dir = subdir;
+
+      ++i;
+    }
+
+  g_strfreev (split);
+
+  g_assert (dir != NULL);
+
+  return dir;
+}
+
+static gboolean cached_dir_add_entry(CachedDir* dir, const char* basename, const char* path)
+{
+  DesktopEntry *entry;
+
+  entry = desktop_entry_new (path);
+  if (entry == NULL)
+    return FALSE;
+
+  dir->entries = g_slist_prepend (dir->entries, entry);
+
+  return TRUE;
+}
+
+static gboolean cached_dir_update_entry(CachedDir* dir, const char* basename, const char* path)
+{
+  GSList *tmp;
+
+  tmp = dir->entries;
+  while (tmp != NULL)
+    {
+      if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
+        {
+          if (!desktop_entry_reload (tmp->data))
+	    {
+	      dir->entries = g_slist_delete_link (dir->entries, tmp);
+	    }
+
+          return TRUE;
+        }
+
+      tmp = tmp->next;
+    }
+
+  return cached_dir_add_entry (dir, basename, path);
+}
+
+static gboolean cached_dir_remove_entry(CachedDir* dir, const char* basename)
+{
+  GSList *tmp;
+
+  tmp = dir->entries;
+  while (tmp != NULL)
+    {
+      if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
+        {
+          desktop_entry_unref (tmp->data);
+          dir->entries = g_slist_delete_link (dir->entries, tmp);
+          return TRUE;
+        }
+
+      tmp = tmp->next;
+    }
+
+  return FALSE;
+}
+
+static CachedDir *
+cached_dir_add_subdir (CachedDir  *dir,
+                       const char *basename,
+                       const char *path)
+{
+  CachedDir *subdir;
+
+  subdir = find_subdir (dir, basename);
+
+  if (subdir != NULL)
+    {
+      subdir->deleted = FALSE;
+      return subdir;
+    }
+
+  subdir = cached_dir_new (basename);
+
+  if (path != NULL && !cached_dir_load_entries_recursive (subdir, path))
+    {
+      cached_dir_free (subdir);
+      return NULL;
+    }
+
+  menu_verbose ("Caching dir \"%s\"\n", basename);
+
+  subdir->parent = dir;
+  dir->subdirs = g_slist_prepend (dir->subdirs, cached_dir_ref (subdir));
+
+  return subdir;
+}
+
+static gboolean cached_dir_remove_subdir(CachedDir* dir, const char* basename)
+{
+  CachedDir *subdir;
+
+  subdir = find_subdir (dir, basename);
+
+  if (subdir != NULL)
+    {
+      subdir->deleted = TRUE;
+
+      dir->subdirs = g_slist_remove (dir->subdirs, subdir);
+      cached_dir_unref (subdir);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static guint   monitors_idle_handler = 0;
+static GSList *pending_monitors_dirs = NULL;
+
+static void
+cached_dir_invoke_monitors (CachedDir *dir)
+{
+  GSList *tmp;
+
+  tmp = dir->monitors;
+  while (tmp != NULL)
+    {
+      CachedDirMonitor *monitor = tmp->data;
+      GSList           *next    = tmp->next;
+
+      monitor->callback (monitor->ed, monitor->user_data);
+
+      tmp = next;
+    }
+
+  /* we explicitly don't invoke monitors of the parent since an
+   * event has been queued for it too */
+}
+
+static gboolean
+emit_monitors_in_idle (void)
+{
+  GSList *monitors_to_emit;
+  GSList *tmp;
+
+  monitors_to_emit = pending_monitors_dirs;
+
+  pending_monitors_dirs = NULL;
+  monitors_idle_handler = 0;
+
+  tmp = monitors_to_emit;
+  while (tmp != NULL)
+    {
+      CachedDir *dir = tmp->data;
+
+      cached_dir_invoke_monitors (dir);
+      cached_dir_remove_reference (dir);
+
+      tmp = tmp->next;
+    }
+
+  g_slist_free (monitors_to_emit);
+
+  return FALSE;
+}
+
+static void
+cached_dir_queue_monitor_event (CachedDir *dir)
+{
+  GSList *tmp;<--- Variable 'tmp' can be declared as pointer to const
+
+  tmp = pending_monitors_dirs;
+  while (tmp != NULL)
+    {
+      CachedDir *d    = tmp->data;
+      GSList    *next = tmp->next;
+
+      if (dir->parent == d->parent &&
+          g_strcmp0 (dir->name, d->name) == 0)
+        break;
+
+      tmp = next;
+    }
+
+  /* not found, so let's queue it */
+  if (tmp == NULL)
+    {
+      cached_dir_add_reference (dir);
+      pending_monitors_dirs = g_slist_append (pending_monitors_dirs, dir);
+    }
+
+  if (dir->parent)
+    {
+      cached_dir_queue_monitor_event (dir->parent);
+    }
+
+  if (monitors_idle_handler == 0)
+    {
+      monitors_idle_handler = g_idle_add ((GSourceFunc) emit_monitors_in_idle, NULL);
+    }
+}
+
+static void handle_cached_dir_changed (MenuMonitor* monitor, MenuMonitorEvent event, const char* path, CachedDir* dir)
+{
+  gboolean  handled = FALSE;
+  char     *basename;
+  char     *dirname;
+
+  dirname  = g_path_get_dirname  (path);
+  basename = g_path_get_basename (path);
+
+  dir = cached_dir_lookup (dirname);
+  cached_dir_add_reference (dir);
+
+  if (g_str_has_suffix (basename, ".desktop") ||
+      g_str_has_suffix (basename, ".directory"))
+    {
+      switch (event)
+        {
+        case MENU_MONITOR_EVENT_CREATED:
+        case MENU_MONITOR_EVENT_CHANGED:
+          handled = cached_dir_update_entry (dir, basename, path);
+          break;
+
+        case MENU_MONITOR_EVENT_DELETED:
+          handled = cached_dir_remove_entry (dir, basename);
+          break;
+
+        default:
+          g_assert_not_reached ();
+          break;
+        }
+    }
+  else if (g_file_test (path, G_FILE_TEST_IS_DIR)) /* Try recursing */
+    {
+      switch (event)
+        {
+        case MENU_MONITOR_EVENT_CREATED:
+          handled = cached_dir_add_subdir (dir, basename, path) != NULL;
+          break;
+
+        case MENU_MONITOR_EVENT_CHANGED:
+          break;
+
+        case MENU_MONITOR_EVENT_DELETED:
+          handled = cached_dir_remove_subdir (dir, basename);
+          break;
+
+        default:
+          g_assert_not_reached ();
+          break;
+        }
+    }
+
+  g_free (basename);
+  g_free (dirname);
+
+  if (handled)
+    {
+      menu_verbose ("'%s' notified of '%s' %s - invalidating cache\n",
+                    dir->name,
+                    path,
+                    event == MENU_MONITOR_EVENT_CREATED ? ("created") :
+                    event == MENU_MONITOR_EVENT_DELETED ? ("deleted") : ("changed"));
+
+      /* CHANGED events don't change the set of desktop entries */
+      if (event == MENU_MONITOR_EVENT_CREATED || event == MENU_MONITOR_EVENT_DELETED)
+        {
+          _entry_directory_list_empty_desktop_cache ();
+        }
+
+      cached_dir_queue_monitor_event (dir);
+    }
+
+  cached_dir_remove_reference (dir);
+}
+
+static void cached_dir_ensure_monitor(CachedDir* dir, const char* dirname)
+{
+  if (dir->dir_monitor == NULL)
+    {
+      dir->dir_monitor = menu_get_directory_monitor (dirname);
+      menu_monitor_add_notify (dir->dir_monitor,
+			       (MenuMonitorNotifyFunc) handle_cached_dir_changed,
+			       dir);
+    }
+}
+
+static gboolean cached_dir_load_entries_recursive(CachedDir* dir, const char* dirname)
+{
+  DIR           *dp;
+  struct dirent *dent;
+  GString       *fullpath;
+  gsize          fullpath_len;
+
+  g_assert (dir != NULL);
+
+  if (dir->have_read_entries)
+    return TRUE;
+
+  menu_verbose ("Attempting to read entries from %s (full path %s)\n",
+                dir->name, dirname);
+
+  dp = opendir (dirname);
+  if (dp == NULL)
+    {
+      menu_verbose ("Unable to list directory \"%s\"\n",
+                    dirname);
+      return FALSE;
+    }
+
+  cached_dir_ensure_monitor (dir, dirname);
+
+  fullpath = g_string_new (dirname);
+  if (fullpath->str[fullpath->len - 1] != G_DIR_SEPARATOR)
+    g_string_append_c (fullpath, G_DIR_SEPARATOR);
+
+  fullpath_len = fullpath->len;
+
+  while ((dent = readdir (dp)) != NULL)
+    {
+      /* ignore . and .. */
+      if (dent->d_name[0] == '.' &&
+          (dent->d_name[1] == '\0' ||
+           (dent->d_name[1] == '.' &&
+            dent->d_name[2] == '\0')))
+        continue;
+
+      g_string_append (fullpath, dent->d_name);
+
+      if (g_str_has_suffix (dent->d_name, ".desktop") ||
+          g_str_has_suffix (dent->d_name, ".directory"))
+        {
+          cached_dir_add_entry (dir, dent->d_name, fullpath->str);
+        }
+      else /* Try recursing */
+        {
+          cached_dir_add_subdir (dir, dent->d_name, fullpath->str);
+        }
+
+      g_string_truncate (fullpath, fullpath_len);
+    }
+
+  closedir (dp);
+
+  g_string_free (fullpath, TRUE);
+
+  dir->have_read_entries = TRUE;
+
+  return TRUE;
+}
+
+static void cached_dir_add_monitor(CachedDir* dir, EntryDirectory* ed, EntryDirectoryChangedFunc callback, gpointer user_data)
+{
+  CachedDirMonitor *monitor;
+  GSList           *tmp;<--- Variable 'tmp' can be declared as pointer to const
+
+  tmp = dir->monitors;
+  while (tmp != NULL)
+    {
+      monitor = tmp->data;
+
+      if (monitor->ed == ed &&
+          monitor->callback == callback &&
+          monitor->user_data == user_data)
+        break;
+
+      tmp = tmp->next;
+    }
+
+  if (tmp == NULL)
+    {
+      monitor            = g_new0 (CachedDirMonitor, 1);
+      monitor->ed        = ed;
+      monitor->callback  = callback;
+      monitor->user_data = user_data;
+
+      dir->monitors = g_slist_append (dir->monitors, monitor);
+    }
+}
+
+static void cached_dir_remove_monitor(CachedDir* dir, EntryDirectory* ed, EntryDirectoryChangedFunc callback, gpointer user_data)<--- Parameter 'ed' can be declared as pointer to const
+{
+  GSList *tmp;
+
+  tmp = dir->monitors;
+  while (tmp != NULL)
+    {
+      CachedDirMonitor *monitor = tmp->data;
+      GSList           *next = tmp->next;
+
+      if (monitor->ed == ed &&
+          monitor->callback == callback &&
+          monitor->user_data == user_data)
+        {
+          dir->monitors = g_slist_delete_link (dir->monitors, tmp);
+          g_free (monitor);
+        }
+
+      tmp = next;
+    }
+}
+
+static void cached_dir_add_reference(CachedDir* dir)
+{
+  cached_dir_ref (dir);
+
+  if (dir->parent != NULL)
+    {
+      cached_dir_add_reference (dir->parent);
+    }
+}
+
+static void cached_dir_remove_reference(CachedDir* dir)
+{
+  CachedDir *parent;
+
+  parent = dir->parent;
+
+  cached_dir_unref (dir);
+
+  if (parent != NULL)
+    {
+      cached_dir_remove_reference (parent);
+    }
+}
+
+/*
+ * Entry directories
+ */
+
+static EntryDirectory* entry_directory_new_full(DesktopEntryType entry_type, const char* path, gboolean is_legacy, const char* legacy_prefix)
+{
+  EntryDirectory *ed;
+  char           *canonical;
+
+  menu_verbose ("Loading entry directory \"%s\" (legacy %s)\n",
+                path,
+                is_legacy ? "<yes>" : "<no>");
+
+  canonical = realpath (path, NULL);
+  if (canonical == NULL)
+    {
+      menu_verbose ("Failed to canonicalize \"%s\": %s\n",
+                    path, g_strerror (errno));
+      return NULL;
+    }
+
+  ed = g_new0 (EntryDirectory, 1);
+
+  ed->dir = cached_dir_lookup (canonical);
+  g_assert (ed->dir != NULL);
+
+  cached_dir_add_reference (ed->dir);
+  cached_dir_load_entries_recursive (ed->dir, canonical);
+
+  ed->legacy_prefix = g_strdup (legacy_prefix);
+  ed->entry_type    = entry_type;
+  ed->is_legacy     = is_legacy != FALSE;
+  ed->refcount      = 1;
+
+  g_free (canonical);
+
+  return ed;
+}
+
+EntryDirectory* entry_directory_new(DesktopEntryType entry_type, const char* path)
+{
+	return entry_directory_new_full (entry_type, path, FALSE, NULL);
+}
+
+EntryDirectory* entry_directory_new_legacy(DesktopEntryType entry_type, const char* path, const char* legacy_prefix)
+{
+	return entry_directory_new_full(entry_type, path, TRUE, legacy_prefix);
+}
+
+EntryDirectory* entry_directory_ref(EntryDirectory* ed)
+{
+	g_return_val_if_fail(ed != NULL, NULL);
+	g_return_val_if_fail(ed->refcount > 0, NULL);
+
+	ed->refcount++;
+
+	return ed;
+}
+
+void entry_directory_unref(EntryDirectory* ed)
+{
+  g_return_if_fail (ed != NULL);
+  g_return_if_fail (ed->refcount > 0);
+
+  if (--ed->refcount == 0)
+    {
+      cached_dir_remove_reference (ed->dir);
+
+      ed->dir        = NULL;
+      ed->entry_type = DESKTOP_ENTRY_INVALID;
+      ed->is_legacy  = FALSE;
+
+      g_free (ed->legacy_prefix);
+      ed->legacy_prefix = NULL;
+
+      g_free (ed);
+    }
+}
+
+static void entry_directory_add_monitor(EntryDirectory* ed, EntryDirectoryChangedFunc callback, gpointer user_data)
+{
+  cached_dir_add_monitor (ed->dir, ed, callback, user_data);
+}
+
+static void entry_directory_remove_monitor(EntryDirectory* ed, EntryDirectoryChangedFunc callback, gpointer user_data)
+{
+  cached_dir_remove_monitor (ed->dir, ed, callback, user_data);
+}
+
+static DesktopEntry* entry_directory_get_directory(EntryDirectory* ed, const char* relative_path)
+{
+  DesktopEntry *entry;
+
+  if (ed->entry_type != DESKTOP_ENTRY_DIRECTORY)
+    return NULL;
+
+  entry = cached_dir_find_relative_path (ed->dir, relative_path);
+  if (entry == NULL || desktop_entry_get_type (entry) != DESKTOP_ENTRY_DIRECTORY)
+    return NULL;
+
+  return desktop_entry_ref (entry);
+}
+
+static char* get_desktop_file_id_from_path(EntryDirectory* ed, DesktopEntryType  entry_type, const char* relative_path)
+{
+  char *retval;
+
+  retval = NULL;
+
+  if (entry_type == DESKTOP_ENTRY_DESKTOP)
+    {
+      if (!ed->is_legacy)
+	{
+	  retval = g_strdelimit (g_strdup (relative_path), "/", '-');
+	}
+      else
+	{
+	  char *basename;
+
+	  basename = g_path_get_basename (relative_path);
+
+	  if (ed->legacy_prefix)
+	    {
+	      retval = g_strjoin ("-", ed->legacy_prefix, basename, NULL);
+	      g_free (basename);
+	    }
+	  else
+	    {
+	      retval = basename;
+	    }
+	}
+    }
+  else
+    {
+      retval = g_strdup (relative_path);
+    }
+
+  return retval;
+}
+
+typedef gboolean (*EntryDirectoryForeachFunc) (EntryDirectory* ed, DesktopEntry* entry, const char* file_id, DesktopEntrySet* set, gpointer user_data);
+
+static gboolean entry_directory_foreach_recursive(EntryDirectory* ed, CachedDir* cd, GString* relative_path, EntryDirectoryForeachFunc func, DesktopEntrySet* set, gpointer user_data)
+{
+  GSList *tmp;
+  gsize   relative_path_len;
+
+  if (cd->deleted)
+    return TRUE;
+
+  relative_path_len = relative_path->len;
+
+  tmp = cd->entries;
+  while (tmp != NULL)
+    {
+      DesktopEntry *entry = tmp->data;
+
+      if (desktop_entry_get_type (entry) == ed->entry_type)
+        {
+          gboolean  ret;
+          char     *file_id;
+
+          g_string_append (relative_path,
+                           desktop_entry_get_basename (entry));
+
+	  file_id = get_desktop_file_id_from_path (ed,
+						   ed->entry_type,
+						   relative_path->str);
+
+          ret = func (ed, entry, file_id, set, user_data);
+
+          g_free (file_id);
+
+          g_string_truncate (relative_path, relative_path_len);
+
+          if (!ret)
+            return FALSE;
+        }
+
+      tmp = tmp->next;
+    }
+
+  tmp = cd->subdirs;
+  while (tmp != NULL)
+    {
+      CachedDir *subdir = tmp->data;
+
+      g_string_append (relative_path, subdir->name);
+      g_string_append_c (relative_path, G_DIR_SEPARATOR);
+
+      if (!entry_directory_foreach_recursive (ed,
+                                              subdir,
+                                              relative_path,
+                                              func,
+                                              set,
+                                              user_data))
+        return FALSE;
+
+      g_string_truncate (relative_path, relative_path_len);
+
+      tmp = tmp->next;
+    }
+
+  return TRUE;
+}
+
+static void entry_directory_foreach(EntryDirectory* ed, EntryDirectoryForeachFunc func, DesktopEntrySet* set, gpointer user_data)
+{
+  GString *path;
+
+  path = g_string_new (NULL);
+
+  entry_directory_foreach_recursive (ed,
+                                     ed->dir,
+                                     path,
+                                     func,
+                                     set,
+                                     user_data);
+
+  g_string_free (path, TRUE);
+}
+
+void entry_directory_get_flat_contents(EntryDirectory* ed, DesktopEntrySet* desktop_entries, DesktopEntrySet* directory_entries, GSList** subdirs)
+{
+  GSList *tmp;
+
+  if (subdirs)
+    *subdirs = NULL;
+
+  tmp = ed->dir->entries;
+  while (tmp != NULL)
+    {
+      DesktopEntry *entry = tmp->data;
+      const char   *basename;
+
+      basename = desktop_entry_get_basename (entry);
+
+      if (desktop_entries &&
+          desktop_entry_get_type (entry) == DESKTOP_ENTRY_DESKTOP)
+        {
+          char *file_id;
+
+          file_id = get_desktop_file_id_from_path (ed,
+						   DESKTOP_ENTRY_DESKTOP,
+						   basename);
+
+          desktop_entry_set_add_entry (desktop_entries,
+                                       entry,
+                                       file_id);
+
+          g_free (file_id);
+        }
+
+      if (directory_entries &&
+          desktop_entry_get_type (entry) == DESKTOP_ENTRY_DIRECTORY)
+        {
+          desktop_entry_set_add_entry (directory_entries,
+				       entry,
+				       basename);
+        }
+
+      tmp = tmp->next;
+    }
+
+  if (subdirs)
+    {
+      tmp = ed->dir->subdirs;
+      while (tmp != NULL)
+        {
+          CachedDir *cd = tmp->data;
+
+	  if (!cd->deleted)
+	    {
+	      *subdirs = g_slist_prepend (*subdirs, g_strdup (cd->name));
+	    }
+
+          tmp = tmp->next;
+        }
+    }
+
+  if (subdirs)
+    *subdirs = g_slist_reverse (*subdirs);
+}
+
+/*
+ * Entry directory lists
+ */
+
+EntryDirectoryList* entry_directory_list_new(void)
+{
+  EntryDirectoryList *list;
+
+  list = g_new0 (EntryDirectoryList, 1);
+
+  list->refcount = 1;
+  list->dirs = NULL;
+  list->length = 0;
+
+  return list;
+}
+
+EntryDirectoryList* entry_directory_list_ref(EntryDirectoryList* list)
+{
+  g_return_val_if_fail (list != NULL, NULL);
+  g_return_val_if_fail (list->refcount > 0, NULL);
+
+  list->refcount += 1;
+
+  return list;
+}
+
+void entry_directory_list_unref(EntryDirectoryList* list)
+{
+  g_return_if_fail (list != NULL);
+  g_return_if_fail (list->refcount > 0);
+
+  list->refcount -= 1;
+  if (list->refcount == 0)
+    {
+      g_list_foreach (list->dirs, (GFunc) entry_directory_unref, NULL);
+      g_list_free (list->dirs);
+      list->dirs = NULL;
+      list->length = 0;
+      g_free (list);
+    }
+}
+
+void entry_directory_list_prepend(EntryDirectoryList* list, EntryDirectory* ed)
+{
+  list->length += 1;
+  list->dirs = g_list_prepend (list->dirs,
+                               entry_directory_ref (ed));
+}
+
+int entry_directory_list_get_length(EntryDirectoryList* list)<--- Parameter 'list' can be declared as pointer to const
+{
+  return list->length;
+}
+
+void entry_directory_list_append_list(EntryDirectoryList* list, EntryDirectoryList* to_append)
+{
+  GList *tmp;
+  GList *new_dirs = NULL;
+
+  if (to_append->length == 0)
+    return;
+
+  tmp = to_append->dirs;
+  while (tmp != NULL)
+    {
+      list->length += 1;
+      new_dirs = g_list_prepend (new_dirs,
+                                 entry_directory_ref (tmp->data));
+
+      tmp = tmp->next;
+    }
+
+  new_dirs   = g_list_reverse (new_dirs);
+  list->dirs = g_list_concat (list->dirs, new_dirs);
+}
+
+DesktopEntry* entry_directory_list_get_directory(EntryDirectoryList *list, const char* relative_path)
+{
+  DesktopEntry *retval = NULL;
+  GList        *tmp;
+
+  tmp = list->dirs;
+  while (tmp != NULL)
+    {
+      if ((retval = entry_directory_get_directory (tmp->data, relative_path)) != NULL)
+        break;
+
+      tmp = tmp->next;
+    }
+
+  return retval;
+}
+
+gboolean _entry_directory_list_compare(const EntryDirectoryList* a, const EntryDirectoryList* b)
+{
+  GList *al, *bl;<--- Variable 'al' can be declared as pointer to const<--- Variable 'bl' can be declared as pointer to const
+
+  if (a == NULL && b == NULL)
+    return TRUE;
+
+  if ((a == NULL || b == NULL))
+    return FALSE;
+
+  if (a->length != b->length)
+    return FALSE;
+
+  al = a->dirs; bl = b->dirs;
+  while (al && bl && al->data == bl->data)
+    {
+      al = al->next;
+      bl = bl->next;
+    }
+
+  return (al == NULL && bl == NULL);
+}
+
+static gboolean get_all_func(EntryDirectory* ed, DesktopEntry* entry, const char* file_id, DesktopEntrySet* set, gpointer user_data)<--- Parameter 'ed' can be declared as pointer to const
+{
+  if (ed->is_legacy && !desktop_entry_has_categories (entry))
+    {
+      entry = desktop_entry_copy (entry);
+      desktop_entry_add_legacy_category (entry);
+    }
+  else
+    {
+      entry = desktop_entry_ref (entry);
+    }
+
+  desktop_entry_set_add_entry (set, entry, file_id);
+  desktop_entry_unref (entry);
+
+  return TRUE;
+}
+
+static DesktopEntrySet* entry_directory_last_set = NULL;
+static EntryDirectoryList* entry_directory_last_list = NULL;
+
+void _entry_directory_list_empty_desktop_cache(void)
+{
+  if (entry_directory_last_set != NULL)
+    desktop_entry_set_unref (entry_directory_last_set);
+  entry_directory_last_set = NULL;
+
+  if (entry_directory_last_list != NULL)
+    entry_directory_list_unref (entry_directory_last_list);
+  entry_directory_last_list = NULL;
+}
+
+DesktopEntrySet* _entry_directory_list_get_all_desktops(EntryDirectoryList* list)
+{
+  GList *tmp;
+  DesktopEntrySet *set;
+
+  /* The only tricky thing here is that desktop files later
+   * in the search list with the same relative path
+   * are "hidden" by desktop files earlier in the path,
+   * so we have to do the earlier files first causing
+   * the later files to replace the earlier files
+   * in the DesktopEntrySet
+   *
+   * We go from the end of the list so we can just
+   * g_hash_table_replace and not have to do two
+   * hash lookups (check for existing entry, then insert new
+   * entry)
+   */
+
+  /* This method is -extremely- slow, so we have a simple
+     one-entry cache here */
+  if (_entry_directory_list_compare (list, entry_directory_last_list))
+    {
+      menu_verbose (" Hit desktop list (%p) cache\n", list);
+      return desktop_entry_set_ref (entry_directory_last_set);
+    }
+
+  if (entry_directory_last_set != NULL)
+    desktop_entry_set_unref (entry_directory_last_set);
+  if (entry_directory_last_list != NULL)
+    entry_directory_list_unref (entry_directory_last_list);
+
+  set = desktop_entry_set_new ();
+  menu_verbose (" Storing all of list %p in set %p\n",
+                list, set);
+
+  tmp = g_list_last (list->dirs);
+  while (tmp != NULL)
+    {
+      entry_directory_foreach (tmp->data, get_all_func, set, NULL);<--- You might need to cast the function pointer here
+
+      tmp = tmp->prev;
+    }
+
+  entry_directory_last_list = entry_directory_list_ref (list);
+  entry_directory_last_set = desktop_entry_set_ref (set);
+
+  return set;
+}
+
+void entry_directory_list_add_monitors(EntryDirectoryList* list, EntryDirectoryChangedFunc callback, gpointer user_data)
+{
+  GList *tmp;
+
+  tmp = list->dirs;
+  while (tmp != NULL)
+    {
+      entry_directory_add_monitor (tmp->data, callback, user_data);
+      tmp = tmp->next;
+    }
+}
+
+void entry_directory_list_remove_monitors(EntryDirectoryList* list, EntryDirectoryChangedFunc callback, gpointer user_data)
+{
+  GList *tmp;
+
+  tmp = list->dirs;
+  while (tmp != NULL)
+    {
+      entry_directory_remove_monitor (tmp->data, callback, user_data);
+      tmp = tmp->next;
+    }
+}
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/6.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/6.html new file mode 100644 index 0000000..dd64055 --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/6.html @@ -0,0 +1,371 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
/*
+ * Copyright (C) 2005 Red Hat, Inc.
+ * Copyright (C) 2011 Perberos
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MENU_MONITOR_H__
+#define __MENU_MONITOR_H__
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+G_BEGIN_DECLS
+
+typedef struct MenuMonitor MenuMonitor;
+
+typedef enum {
+	MENU_MONITOR_EVENT_INVALID = 0,
+	MENU_MONITOR_EVENT_CREATED = 1,
+	MENU_MONITOR_EVENT_DELETED = 2,
+	MENU_MONITOR_EVENT_CHANGED = 3
+} MenuMonitorEvent;
+
+typedef void (*MenuMonitorNotifyFunc) (MenuMonitor* monitor, MenuMonitorEvent event, const char* path, gpointer user_data);
+
+
+MenuMonitor* menu_get_file_monitor(const char* path);
+MenuMonitor* menu_get_directory_monitor(const char* path);
+
+MenuMonitor* menu_monitor_ref(MenuMonitor* monitor);
+void menu_monitor_unref(MenuMonitor* monitor);
+
+void menu_monitor_add_notify(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data);
+void menu_monitor_remove_notify(MenuMonitor* monitor, MenuMonitorNotifyFunc notify_func, gpointer user_data);
+
+
+/* Izquierda a derecha
+ */
+
+#define mate_menu_monitor_file_get       menu_get_file_monitor
+#define mate_menu_monitor_directory_get  menu_get_directory_monitor
+
+#define mate_menu_monitor_ref    menu_monitor_ref
+#define mate_menu_monitor_unref  menu_monitor_unref
+
+#define mate_menu_monitor_notify_add     menu_monitor_add_notify
+#define mate_menu_monitor_notify_remove  menu_monitor_remove_notify
+#define mate_menu_monitor_notify_ref     menu_monitor_notify_ref /* private */
+#define mate_menu_monitor_notify_unref   menu_monitor_notify_unref /* private */
+
+G_END_DECLS
+
+#endif /* __MENU_MONITOR_H__ */
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/7.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/7.html new file mode 100644 index 0000000..e4c958a --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/7.html @@ -0,0 +1,10425 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
+2073
+2074
+2075
+2076
+2077
+2078
+2079
+2080
+2081
+2082
+2083
+2084
+2085
+2086
+2087
+2088
+2089
+2090
+2091
+2092
+2093
+2094
+2095
+2096
+2097
+2098
+2099
+2100
+2101
+2102
+2103
+2104
+2105
+2106
+2107
+2108
+2109
+2110
+2111
+2112
+2113
+2114
+2115
+2116
+2117
+2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127
+2128
+2129
+2130
+2131
+2132
+2133
+2134
+2135
+2136
+2137
+2138
+2139
+2140
+2141
+2142
+2143
+2144
+2145
+2146
+2147
+2148
+2149
+2150
+2151
+2152
+2153
+2154
+2155
+2156
+2157
+2158
+2159
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2180
+2181
+2182
+2183
+2184
+2185
+2186
+2187
+2188
+2189
+2190
+2191
+2192
+2193
+2194
+2195
+2196
+2197
+2198
+2199
+2200
+2201
+2202
+2203
+2204
+2205
+2206
+2207
+2208
+2209
+2210
+2211
+2212
+2213
+2214
+2215
+2216
+2217
+2218
+2219
+2220
+2221
+2222
+2223
+2224
+2225
+2226
+2227
+2228
+2229
+2230
+2231
+2232
+2233
+2234
+2235
+2236
+2237
+2238
+2239
+2240
+2241
+2242
+2243
+2244
+2245
+2246
+2247
+2248
+2249
+2250
+2251
+2252
+2253
+2254
+2255
+2256
+2257
+2258
+2259
+2260
+2261
+2262
+2263
+2264
+2265
+2266
+2267
+2268
+2269
+2270
+2271
+2272
+2273
+2274
+2275
+2276
+2277
+2278
+2279
+2280
+2281
+2282
+2283
+2284
+2285
+2286
+2287
+2288
+2289
+2290
+2291
+2292
+2293
+2294
+2295
+2296
+2297
+2298
+2299
+2300
+2301
+2302
+2303
+2304
+2305
+2306
+2307
+2308
+2309
+2310
+2311
+2312
+2313
+2314
+2315
+2316
+2317
+2318
+2319
+2320
+2321
+2322
+2323
+2324
+2325
+2326
+2327
+2328
+2329
+2330
+2331
+2332
+2333
+2334
+2335
+2336
+2337
+2338
+2339
+2340
+2341
+2342
+2343
+2344
+2345
+2346
+2347
+2348
+2349
+2350
+2351
+2352
+2353
+2354
+2355
+2356
+2357
+2358
+2359
+2360
+2361
+2362
+2363
+2364
+2365
+2366
+2367
+2368
+2369
+2370
+2371
+2372
+2373
+2374
+2375
+2376
+2377
+2378
+2379
+2380
+2381
+2382
+2383
+2384
+2385
+2386
+2387
+2388
+2389
+2390
+2391
+2392
+2393
+2394
+2395
+2396
+2397
+2398
+2399
+2400
+2401
+2402
+2403
+2404
+2405
+2406
+2407
+2408
+2409
+2410
+2411
+2412
+2413
+2414
+2415
+2416
+2417
+2418
+2419
+2420
+2421
+2422
+2423
+2424
+2425
+2426
+2427
+2428
+2429
+2430
+2431
+2432
+2433
+2434
+2435
+2436
+2437
+2438
+2439
+2440
+2441
+2442
+2443
+2444
+2445
+2446
+2447
+2448
+2449
+2450
+2451
+2452
+2453
+2454
+2455
+2456
+2457
+2458
+2459
+2460
+2461
+2462
+2463
+2464
+2465
+2466
+2467
+2468
+2469
+2470
+2471
+2472
+2473
+2474
+2475
+2476
+2477
+2478
+2479
+2480
+2481
+2482
+2483
+2484
+2485
+2486
+2487
+2488
+2489
+2490
+2491
+2492
+2493
+2494
+2495
+2496
+2497
+2498
+2499
+2500
+2501
+2502
+2503
+2504
+2505
+2506
+2507
+2508
+2509
+2510
+2511
+2512
+2513
+2514
+2515
+2516
+2517
+2518
+2519
+2520
+2521
+2522
+2523
+2524
+2525
+2526
+2527
+2528
+2529
+2530
+2531
+2532
+2533
+2534
+2535
+2536
+2537
+2538
+2539
+2540
+2541
+2542
+2543
+2544
+2545
+2546
+2547
+2548
+2549
+2550
+2551
+2552
+2553
+2554
+2555
+2556
+2557
+2558
+2559
+2560
+2561
+2562
+2563
+2564
+2565
+2566
+2567
+2568
+2569
+2570
+2571
+2572
+2573
+2574
+2575
+2576
+2577
+2578
+2579
+2580
+2581
+2582
+2583
+2584
+2585
+2586
+2587
+2588
+2589
+2590
+2591
+2592
+2593
+2594
+2595
+2596
+2597
+2598
+2599
+2600
+2601
+2602
+2603
+2604
+2605
+2606
+2607
+2608
+2609
+2610
+2611
+2612
+2613
+2614
+2615
+2616
+2617
+2618
+2619
+2620
+2621
+2622
+2623
+2624
+2625
+2626
+2627
+2628
+2629
+2630
+2631
+2632
+2633
+2634
+2635
+2636
+2637
+2638
+2639
+2640
+2641
+2642
+2643
+2644
+2645
+2646
+2647
+2648
+2649
+2650
+2651
+2652
+2653
+2654
+2655
+2656
+2657
+2658
+2659
+2660
+2661
+2662
+2663
+2664
+2665
+2666
+2667
+2668
+2669
+2670
+2671
+2672
+2673
+2674
+2675
+2676
+2677
+2678
+2679
+2680
+2681
+2682
+2683
+2684
+2685
+2686
+2687
+2688
+2689
+2690
+2691
+2692
+2693
+2694
+2695
+2696
+2697
+2698
+2699
+2700
+2701
+2702
+2703
+2704
+2705
+2706
+2707
+2708
+2709
+2710
+2711
+2712
+2713
+2714
+2715
+2716
+2717
+2718
+2719
+2720
+2721
+2722
+2723
+2724
+2725
+2726
+2727
+2728
+2729
+2730
+2731
+2732
+2733
+2734
+2735
+2736
+2737
+2738
+2739
+2740
+2741
+2742
+2743
+2744
+2745
+2746
+2747
+2748
+2749
+2750
+2751
+2752
+2753
+2754
+2755
+2756
+2757
+2758
+2759
+2760
+2761
+2762
+2763
+2764
+2765
+2766
+2767
+2768
+2769
+2770
+2771
+2772
+2773
+2774
+2775
+2776
+2777
+2778
+2779
+2780
+2781
+2782
+2783
+2784
+2785
+2786
+2787
+2788
+2789
+2790
+2791
+2792
+2793
+2794
+2795
+2796
+2797
+2798
+2799
+2800
+2801
+2802
+2803
+2804
+2805
+2806
+2807
+2808
+2809
+2810
+2811
+2812
+2813
+2814
+2815
+2816
+2817
+2818
+2819
+2820
+2821
+2822
+2823
+2824
+2825
+2826
+2827
+2828
+2829
+2830
+2831
+2832
+2833
+2834
+2835
+2836
+2837
+2838
+2839
+2840
+2841
+2842
+2843
+2844
+2845
+2846
+2847
+2848
+2849
+2850
+2851
+2852
+2853
+2854
+2855
+2856
+2857
+2858
+2859
+2860
+2861
+2862
+2863
+2864
+2865
+2866
+2867
+2868
+2869
+2870
+2871
+2872
+2873
+2874
+2875
+2876
+2877
+2878
+2879
+2880
+2881
+2882
+2883
+2884
+2885
+2886
+2887
+2888
+2889
+2890
+2891
+2892
+2893
+2894
+2895
+2896
+2897
+2898
+2899
+2900
+2901
+2902
+2903
+2904
+2905
+2906
+2907
+2908
+2909
+2910
+2911
+2912
+2913
+2914
+2915
+2916
+2917
+2918
+2919
+2920
+2921
+2922
+2923
+2924
+2925
+2926
+2927
+2928
+2929
+2930
+2931
+2932
+2933
+2934
+2935
+2936
+2937
+2938
+2939
+2940
+2941
+2942
+2943
+2944
+2945
+2946
+2947
+2948
+2949
+2950
+2951
+2952
+2953
+2954
+2955
+2956
+2957
+2958
+2959
+2960
+2961
+2962
+2963
+2964
+2965
+2966
+2967
+2968
+2969
+2970
+2971
+2972
+2973
+2974
+2975
+2976
+2977
+2978
+2979
+2980
+2981
+2982
+2983
+2984
+2985
+2986
+2987
+2988
+2989
+2990
+2991
+2992
+2993
+2994
+2995
+2996
+2997
+2998
+2999
+3000
+3001
+3002
+3003
+3004
+3005
+3006
+3007
+3008
+3009
+3010
+3011
+3012
+3013
+3014
+3015
+3016
+3017
+3018
+3019
+3020
+3021
+3022
+3023
+3024
+3025
+3026
+3027
+3028
+3029
+3030
+3031
+3032
+3033
+3034
+3035
+3036
+3037
+3038
+3039
+3040
+3041
+3042
+3043
+3044
+3045
+3046
+3047
+3048
+3049
+3050
+3051
+3052
+3053
+3054
+3055
+3056
+3057
+3058
+3059
+3060
+3061
+3062
+3063
+3064
+3065
+3066
+3067
+3068
+3069
+3070
+3071
+3072
+3073
+3074
+3075
+3076
+3077
+3078
+3079
+3080
+3081
+3082
+3083
+3084
+3085
+3086
+3087
+3088
+3089
+3090
+3091
+3092
+3093
+3094
+3095
+3096
+3097
+3098
+3099
+3100
+3101
+3102
+3103
+3104
+3105
+3106
+3107
+3108
+3109
+3110
+3111
+3112
+3113
+3114
+3115
+3116
+3117
+3118
+3119
+3120
+3121
+3122
+3123
+3124
+3125
+3126
+3127
+3128
+3129
+3130
+3131
+3132
+3133
+3134
+3135
+3136
+3137
+3138
+3139
+3140
+3141
+3142
+3143
+3144
+3145
+3146
+3147
+3148
+3149
+3150
+3151
+3152
+3153
+3154
+3155
+3156
+3157
+3158
+3159
+3160
+3161
+3162
+3163
+3164
+3165
+3166
+3167
+3168
+3169
+3170
+3171
+3172
+3173
+3174
+3175
+3176
+3177
+3178
+3179
+3180
+3181
+3182
+3183
+3184
+3185
+3186
+3187
+3188
+3189
+3190
+3191
+3192
+3193
+3194
+3195
+3196
+3197
+3198
+3199
+3200
+3201
+3202
+3203
+3204
+3205
+3206
+3207
+3208
+3209
+3210
+3211
+3212
+3213
+3214
+3215
+3216
+3217
+3218
+3219
+3220
+3221
+3222
+3223
+3224
+3225
+3226
+3227
+3228
+3229
+3230
+3231
+3232
+3233
+3234
+3235
+3236
+3237
+3238
+3239
+3240
+3241
+3242
+3243
+3244
+3245
+3246
+3247
+3248
+3249
+3250
+3251
+3252
+3253
+3254
+3255
+3256
+3257
+3258
+3259
+3260
+3261
+3262
+3263
+3264
+3265
+3266
+3267
+3268
+3269
+3270
+3271
+3272
+3273
+3274
+3275
+3276
+3277
+3278
+3279
+3280
+3281
+3282
+3283
+3284
+3285
+3286
+3287
+3288
+3289
+3290
+3291
+3292
+3293
+3294
+3295
+3296
+3297
+3298
+3299
+3300
+3301
+3302
+3303
+3304
+3305
+3306
+3307
+3308
+3309
+3310
+3311
+3312
+3313
+3314
+3315
+3316
+3317
+3318
+3319
+3320
+3321
+3322
+3323
+3324
+3325
+3326
+3327
+3328
+3329
+3330
+3331
+3332
+3333
+3334
+3335
+3336
+3337
+3338
+3339
+3340
+3341
+3342
+3343
+3344
+3345
+3346
+3347
+3348
+3349
+3350
+3351
+3352
+3353
+3354
+3355
+3356
+3357
+3358
+3359
+3360
+3361
+3362
+3363
+3364
+3365
+3366
+3367
+3368
+3369
+3370
+3371
+3372
+3373
+3374
+3375
+3376
+3377
+3378
+3379
+3380
+3381
+3382
+3383
+3384
+3385
+3386
+3387
+3388
+3389
+3390
+3391
+3392
+3393
+3394
+3395
+3396
+3397
+3398
+3399
+3400
+3401
+3402
+3403
+3404
+3405
+3406
+3407
+3408
+3409
+3410
+3411
+3412
+3413
+3414
+3415
+3416
+3417
+3418
+3419
+3420
+3421
+3422
+3423
+3424
+3425
+3426
+3427
+3428
+3429
+3430
+3431
+3432
+3433
+3434
+3435
+3436
+3437
+3438
+3439
+3440
+3441
+3442
+3443
+3444
+3445
+3446
+3447
+3448
+3449
+3450
+3451
+3452
+3453
+3454
+3455
+3456
+3457
+3458
+3459
+3460
+3461
+3462
+3463
+3464
+3465
+3466
+3467
+3468
+3469
+3470
+3471
+3472
+3473
+3474
+3475
+3476
+3477
+3478
+3479
+3480
+3481
+3482
+3483
+3484
+3485
+3486
+3487
+3488
+3489
+3490
+3491
+3492
+3493
+3494
+3495
+3496
+3497
+3498
+3499
+3500
+3501
+3502
+3503
+3504
+3505
+3506
+3507
+3508
+3509
+3510
+3511
+3512
+3513
+3514
+3515
+3516
+3517
+3518
+3519
+3520
+3521
+3522
+3523
+3524
+3525
+3526
+3527
+3528
+3529
+3530
+3531
+3532
+3533
+3534
+3535
+3536
+3537
+3538
+3539
+3540
+3541
+3542
+3543
+3544
+3545
+3546
+3547
+3548
+3549
+3550
+3551
+3552
+3553
+3554
+3555
+3556
+3557
+3558
+3559
+3560
+3561
+3562
+3563
+3564
+3565
+3566
+3567
+3568
+3569
+3570
+3571
+3572
+3573
+3574
+3575
+3576
+3577
+3578
+3579
+3580
+3581
+3582
+3583
+3584
+3585
+3586
+3587
+3588
+3589
+3590
+3591
+3592
+3593
+3594
+3595
+3596
+3597
+3598
+3599
+3600
+3601
+3602
+3603
+3604
+3605
+3606
+3607
+3608
+3609
+3610
+3611
+3612
+3613
+3614
+3615
+3616
+3617
+3618
+3619
+3620
+3621
+3622
+3623
+3624
+3625
+3626
+3627
+3628
+3629
+3630
+3631
+3632
+3633
+3634
+3635
+3636
+3637
+3638
+3639
+3640
+3641
+3642
+3643
+3644
+3645
+3646
+3647
+3648
+3649
+3650
+3651
+3652
+3653
+3654
+3655
+3656
+3657
+3658
+3659
+3660
+3661
+3662
+3663
+3664
+3665
+3666
+3667
+3668
+3669
+3670
+3671
+3672
+3673
+3674
+3675
+3676
+3677
+3678
+3679
+3680
+3681
+3682
+3683
+3684
+3685
+3686
+3687
+3688
+3689
+3690
+3691
+3692
+3693
+3694
+3695
+3696
+3697
+3698
+3699
+3700
+3701
+3702
+3703
+3704
+3705
+3706
+3707
+3708
+3709
+3710
+3711
+3712
+3713
+3714
+3715
+3716
+3717
+3718
+3719
+3720
+3721
+3722
+3723
+3724
+3725
+3726
+3727
+3728
+3729
+3730
+3731
+3732
+3733
+3734
+3735
+3736
+3737
+3738
+3739
+3740
+3741
+3742
+3743
+3744
+3745
+3746
+3747
+3748
+3749
+3750
+3751
+3752
+3753
+3754
+3755
+3756
+3757
+3758
+3759
+3760
+3761
+3762
+3763
+3764
+3765
+3766
+3767
+3768
+3769
+3770
+3771
+3772
+3773
+3774
+3775
+3776
+3777
+3778
+3779
+3780
+3781
+3782
+3783
+3784
+3785
+3786
+3787
+3788
+3789
+3790
+3791
+3792
+3793
+3794
+3795
+3796
+3797
+3798
+3799
+3800
+3801
+3802
+3803
+3804
+3805
+3806
+3807
+3808
+3809
+3810
+3811
+3812
+3813
+3814
+3815
+3816
+3817
+3818
+3819
+3820
+3821
+3822
+3823
+3824
+3825
+3826
+3827
+3828
+3829
+3830
+3831
+3832
+3833
+3834
+3835
+3836
+3837
+3838
+3839
+3840
+3841
+3842
+3843
+3844
+3845
+3846
+3847
+3848
+3849
+3850
+3851
+3852
+3853
+3854
+3855
+3856
+3857
+3858
+3859
+3860
+3861
+3862
+3863
+3864
+3865
+3866
+3867
+3868
+3869
+3870
+3871
+3872
+3873
+3874
+3875
+3876
+3877
+3878
+3879
+3880
+3881
+3882
+3883
+3884
+3885
+3886
+3887
+3888
+3889
+3890
+3891
+3892
+3893
+3894
+3895
+3896
+3897
+3898
+3899
+3900
+3901
+3902
+3903
+3904
+3905
+3906
+3907
+3908
+3909
+3910
+3911
+3912
+3913
+3914
+3915
+3916
+3917
+3918
+3919
+3920
+3921
+3922
+3923
+3924
+3925
+3926
+3927
+3928
+3929
+3930
+3931
+3932
+3933
+3934
+3935
+3936
+3937
+3938
+3939
+3940
+3941
+3942
+3943
+3944
+3945
+3946
+3947
+3948
+3949
+3950
+3951
+3952
+3953
+3954
+3955
+3956
+3957
+3958
+3959
+3960
+3961
+3962
+3963
+3964
+3965
+3966
+3967
+3968
+3969
+3970
+3971
+3972
+3973
+3974
+3975
+3976
+3977
+3978
+3979
+3980
+3981
+3982
+3983
+3984
+3985
+3986
+3987
+3988
+3989
+3990
+3991
+3992
+3993
+3994
+3995
+3996
+3997
+3998
+3999
+4000
+4001
+4002
+4003
+4004
+4005
+4006
+4007
+4008
+4009
+4010
+4011
+4012
+4013
+4014
+4015
+4016
+4017
+4018
+4019
+4020
+4021
+4022
+4023
+4024
+4025
+4026
+4027
+4028
+4029
+4030
+4031
+4032
+4033
+4034
+4035
+4036
+4037
+4038
+4039
+4040
+4041
+4042
+4043
+4044
+4045
+4046
+4047
+4048
+4049
+4050
+4051
+4052
+4053
+4054
+4055
+4056
+4057
+4058
+4059
+4060
+4061
+4062
+4063
+4064
+4065
+4066
+4067
+4068
+4069
+4070
+4071
+4072
+4073
+4074
+4075
+4076
+4077
+4078
+4079
+4080
+4081
+4082
+4083
+4084
+4085
+4086
+4087
+4088
+4089
+4090
+4091
+4092
+4093
+4094
+4095
+4096
+4097
+4098
+4099
+4100
+4101
+4102
+4103
+4104
+4105
+4106
+4107
+4108
+4109
+4110
+4111
+4112
+4113
+4114
+4115
+4116
+4117
+4118
+4119
+4120
+4121
+4122
+4123
+4124
+4125
+4126
+4127
+4128
+4129
+4130
+4131
+4132
+4133
+4134
+4135
+4136
+4137
+4138
+4139
+4140
+4141
+4142
+4143
+4144
+4145
+4146
+4147
+4148
+4149
+4150
+4151
+4152
+4153
+4154
+4155
+4156
+4157
+4158
+4159
+4160
+4161
+4162
+4163
+4164
+4165
+4166
+4167
+4168
+4169
+4170
+4171
+4172
+4173
+4174
+4175
+4176
+4177
+4178
+4179
+4180
+4181
+4182
+4183
+4184
+4185
+4186
+4187
+4188
+4189
+4190
+4191
+4192
+4193
+4194
+4195
+4196
+4197
+4198
+4199
+4200
+4201
+4202
+4203
+4204
+4205
+4206
+4207
+4208
+4209
+4210
+4211
+4212
+4213
+4214
+4215
+4216
+4217
+4218
+4219
+4220
+4221
+4222
+4223
+4224
+4225
+4226
+4227
+4228
+4229
+4230
+4231
+4232
+4233
+4234
+4235
+4236
+4237
+4238
+4239
+4240
+4241
+4242
+4243
+4244
+4245
+4246
+4247
+4248
+4249
+4250
+4251
+4252
+4253
+4254
+4255
+4256
+4257
+4258
+4259
+4260
+4261
+4262
+4263
+4264
+4265
+4266
+4267
+4268
+4269
+4270
+4271
+4272
+4273
+4274
+4275
+4276
+4277
+4278
+4279
+4280
+4281
+4282
+4283
+4284
+4285
+4286
+4287
+4288
+4289
+4290
+4291
+4292
+4293
+4294
+4295
+4296
+4297
+4298
+4299
+4300
+4301
+4302
+4303
+4304
+4305
+4306
+4307
+4308
+4309
+4310
+4311
+4312
+4313
+4314
+4315
+4316
+4317
+4318
+4319
+4320
+4321
+4322
+4323
+4324
+4325
+4326
+4327
+4328
+4329
+4330
+4331
+4332
+4333
+4334
+4335
+4336
+4337
+4338
+4339
+4340
+4341
+4342
+4343
+4344
+4345
+4346
+4347
+4348
+4349
+4350
+4351
+4352
+4353
+4354
+4355
+4356
+4357
+4358
+4359
+4360
+4361
+4362
+4363
+4364
+4365
+4366
+4367
+4368
+4369
+4370
+4371
+4372
+4373
+4374
+4375
+4376
+4377
+4378
+4379
+4380
+4381
+4382
+4383
+4384
+4385
+4386
+4387
+4388
+4389
+4390
+4391
+4392
+4393
+4394
+4395
+4396
+4397
+4398
+4399
+4400
+4401
+4402
+4403
+4404
+4405
+4406
+4407
+4408
+4409
+4410
+4411
+4412
+4413
+4414
+4415
+4416
+4417
+4418
+4419
+4420
+4421
+4422
+4423
+4424
+4425
+4426
+4427
+4428
+4429
+4430
+4431
+4432
+4433
+4434
+4435
+4436
+4437
+4438
+4439
+4440
+4441
+4442
+4443
+4444
+4445
+4446
+4447
+4448
+4449
+4450
+4451
+4452
+4453
+4454
+4455
+4456
+4457
+4458
+4459
+4460
+4461
+4462
+4463
+4464
+4465
+4466
+4467
+4468
+4469
+4470
+4471
+4472
+4473
+4474
+4475
+4476
+4477
+4478
+4479
+4480
+4481
+4482
+4483
+4484
+4485
+4486
+4487
+4488
+4489
+4490
+4491
+4492
+4493
+4494
+4495
+4496
+4497
+4498
+4499
+4500
+4501
+4502
+4503
+4504
+4505
+4506
+4507
+4508
+4509
+4510
+4511
+4512
+4513
+4514
+4515
+4516
+4517
+4518
+4519
+4520
+4521
+4522
+4523
+4524
+4525
+4526
+4527
+4528
+4529
+4530
+4531
+4532
+4533
+4534
+4535
+4536
+4537
+4538
+4539
+4540
+4541
+4542
+4543
+4544
+4545
+4546
+4547
+4548
+4549
+4550
+4551
+4552
+4553
+4554
+4555
+4556
+4557
+4558
+4559
+4560
+4561
+4562
+4563
+4564
+4565
+4566
+4567
+4568
+4569
+4570
+4571
+4572
+4573
+4574
+4575
+4576
+4577
+4578
+4579
+4580
+4581
+4582
+4583
+4584
+4585
+4586
+4587
+4588
+4589
+4590
+4591
+4592
+4593
+4594
+4595
+4596
+4597
+4598
+4599
+4600
+4601
+4602
+4603
+4604
+4605
+4606
+4607
+4608
+4609
+4610
+4611
+4612
+4613
+4614
+4615
+4616
+4617
+4618
+4619
+4620
+4621
+4622
+4623
+4624
+4625
+4626
+4627
+4628
+4629
+4630
+4631
+4632
+4633
+4634
+4635
+4636
+4637
+4638
+4639
+4640
+4641
+4642
+4643
+4644
+4645
+4646
+4647
+4648
+4649
+4650
+4651
+4652
+4653
+4654
+4655
+4656
+4657
+4658
+4659
+4660
+4661
+4662
+4663
+4664
+4665
+4666
+4667
+4668
+4669
+4670
+4671
+4672
+4673
+4674
+4675
+4676
+4677
+4678
+4679
+4680
+4681
+4682
+4683
+4684
+4685
+4686
+4687
+4688
+4689
+4690
+4691
+4692
+4693
+4694
+4695
+4696
+4697
+4698
+4699
+4700
+4701
+4702
+4703
+4704
+4705
+4706
+4707
+4708
+4709
+4710
+4711
+4712
+4713
+4714
+4715
+4716
+4717
+4718
+4719
+4720
+4721
+4722
+4723
+4724
+4725
+4726
+4727
+4728
+4729
+4730
+4731
+4732
+4733
+4734
+4735
+4736
+4737
+4738
+4739
+4740
+4741
+4742
+4743
+4744
+4745
+4746
+4747
+4748
+4749
+4750
+4751
+4752
+4753
+4754
+4755
+4756
+4757
+4758
+4759
+4760
+4761
+4762
+4763
+4764
+4765
+4766
+4767
+4768
+4769
+4770
+4771
+4772
+4773
+4774
+4775
+4776
+4777
+4778
+4779
+4780
+4781
+4782
+4783
+4784
+4785
+4786
+4787
+4788
+4789
+4790
+4791
+4792
+4793
+4794
+4795
+4796
+4797
+4798
+4799
+4800
+4801
+4802
+4803
+4804
+4805
+4806
+4807
+4808
+4809
+4810
+4811
+4812
+4813
+4814
+4815
+4816
+4817
+4818
+4819
+4820
+4821
+4822
+4823
+4824
+4825
+4826
+4827
+4828
+4829
+4830
+4831
+4832
+4833
+4834
+4835
+4836
+4837
+4838
+4839
+4840
+4841
+4842
+4843
+4844
+4845
+4846
+4847
+4848
+4849
+4850
+4851
+4852
+4853
+4854
+4855
+4856
+4857
+4858
+4859
+4860
+4861
+4862
+4863
+4864
+4865
+4866
+4867
+4868
+4869
+4870
+4871
+4872
+4873
+4874
+4875
+4876
+4877
+4878
+4879
+4880
+4881
+4882
+4883
+4884
+4885
+4886
+4887
+4888
+4889
+4890
+4891
+4892
+4893
+4894
+4895
+4896
+4897
+4898
+4899
+4900
+4901
+4902
+4903
+4904
+4905
+4906
+4907
+4908
+4909
+4910
+4911
+4912
+4913
+4914
+4915
+4916
+4917
+4918
+4919
+4920
+4921
+4922
+4923
+4924
+4925
+4926
+4927
+4928
+4929
+4930
+4931
+4932
+4933
+4934
+4935
+4936
+4937
+4938
+4939
+4940
+4941
+4942
+4943
+4944
+4945
+4946
+4947
+4948
+4949
+4950
+4951
+4952
+4953
+4954
+4955
+4956
+4957
+4958
+4959
+4960
+4961
+4962
+4963
+4964
+4965
+4966
+4967
+4968
+4969
+4970
+4971
+4972
+4973
+4974
+4975
+4976
+4977
+4978
+4979
+4980
+4981
+4982
+4983
+4984
+4985
+4986
+4987
+4988
+4989
+4990
+4991
+4992
+4993
+4994
+4995
+4996
+4997
+4998
+4999
+5000
+5001
+5002
+5003
+5004
+5005
+5006
+5007
+5008
+5009
+5010
+5011
+5012
+5013
+5014
+5015
+5016
+5017
+5018
+5019
+5020
+5021
+5022
+5023
+5024
+5025
+5026
+5027
+5028
+5029
+5030
+5031
+5032
+5033
+5034
+5035
+5036
+5037
+5038
+5039
+5040
+5041
+5042
+5043
+5044
+5045
+5046
+5047
+5048
+5049
+5050
+5051
+5052
+5053
+5054
+5055
+5056
+5057
+5058
+5059
+5060
+5061
+5062
+5063
+5064
+5065
+5066
+5067
+5068
+5069
+5070
+5071
+5072
+5073
+5074
+5075
+5076
+5077
+5078
+5079
+5080
+5081
+5082
+5083
+5084
+5085
+5086
+5087
+5088
+5089
+5090
+5091
+5092
+5093
+5094
/*
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* used for realpath() */
+#define _XOPEN_SOURCE 500
+
+#include <config.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "matemenu-tree.h"
+
+#include <gio/gio.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <string.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <errno.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <stdlib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "menu-layout.h"
+#include "menu-monitor.h"
+#include "menu-util.h"
+
+/* private */
+typedef struct MateMenuTreeItem MateMenuTreeItem;
+#define MATEMENU_TREE_ITEM(i)      ((MateMenuTreeItem *)(i))
+#define MATEMENU_TREE_DIRECTORY(i) ((MateMenuTreeDirectory *)(i))
+#define MATEMENU_TREE_ENTRY(i)     ((MateMenuTreeEntry *)(i))
+#define MATEMENU_TREE_SEPARATOR(i) ((MateMenuTreeSeparator *)(i))
+#define MATEMENU_TREE_HEADER(i)    ((MateMenuTreeHeader *)(i))
+#define MATEMENU_TREE_ALIAS(i)     ((MateMenuTreeAlias *)(i))
+
+enum {
+  PROP_0,
+
+  PROP_MENU_BASENAME,
+  PROP_MENU_PATH,
+  PROP_FLAGS
+};
+
+#ifdef WITH_COLLECTION
+typedef enum
+{
+  OBJECT_DRAWER,
+  OBJECT_MENU,
+  OBJECT_LAUNCHER,
+  OBJECT_APPLET,
+  OBJECT_ACTION,
+  OBJECT_MENU_BAR,
+  OBJECT_SEPARATOR,
+} ObjectType;
+#endif /* WITH_COLLECTION */
+
+/* Signals */
+enum
+{
+  CHANGED,
+  LAST_SIGNAL
+};
+
+static guint matemenu_tree_signals [LAST_SIGNAL] = { 0 };
+
+struct _MateMenuTree
+{
+  GObject       parent_instance;
+
+  char *basename;
+  char *non_prefixed_basename;
+  char *path;
+  char *canonical_path;
+
+#ifdef WITH_COLLECTION
+  GPtrArray *collection_applet;
+  GSettings *settings;
+  guint emit_changed_signal;
+#endif /* WITH_COLLECTION */
+
+  MateMenuTreeFlags flags;
+
+  GSList *menu_file_monitors;
+
+  MenuLayoutNode *layout;
+  MateMenuTreeDirectory *root;
+  GHashTable *entries_by_id;
+
+  guint canonical : 1;
+  guint loaded    : 1;
+};
+
+G_DEFINE_TYPE (MateMenuTree, matemenu_tree, G_TYPE_OBJECT)
+
+struct MateMenuTreeItem
+{
+  volatile gint refcount;
+
+  MateMenuTreeItemType type;
+
+  MateMenuTreeDirectory *parent;
+  MateMenuTree *tree;
+};
+
+struct MateMenuTreeIter
+{
+  volatile gint refcount;
+
+  MateMenuTreeItem *item;
+  GSList        *contents;
+  GSList        *contents_iter;
+};
+
+struct MateMenuTreeDirectory
+{
+  MateMenuTreeItem  item;
+
+  DesktopEntry     *directory_entry;
+  char             *name;
+
+  GSList           *entries;
+  GSList           *subdirs;
+
+  MenuLayoutValues  default_layout_values;
+  GSList           *default_layout_info;
+  GSList           *layout_info;
+  GSList           *contents;
+
+  guint             only_unallocated         : 1;
+  guint             is_nodisplay             : 1;
+  guint             layout_pending_separator : 1;
+  guint             preprocessed             : 1;
+
+  /* 16 bits should be more than enough; G_MAXUINT16 means no inline header */
+  guint             will_inline_header       : 16;
+};
+
+struct MateMenuTreeEntry
+{
+  MateMenuTreeItem  item;
+
+  DesktopEntry     *desktop_entry;
+  char             *desktop_file_id;
+
+  guint             is_excluded    : 1;
+  guint             is_unallocated : 1;
+};
+
+struct MateMenuTreeSeparator
+{
+  MateMenuTreeItem item;
+};
+
+struct MateMenuTreeHeader
+{
+  MateMenuTreeItem item;
+
+  MateMenuTreeDirectory *directory;
+};
+
+struct MateMenuTreeAlias
+{
+  MateMenuTreeItem item;
+
+  MateMenuTreeDirectory *directory;
+  MateMenuTreeItem      *aliased_item;
+};
+
+static gboolean  matemenu_tree_load_layout          (MateMenuTree       *tree,
+                                                  GError         **error);
+static void      matemenu_tree_force_reload         (MateMenuTree       *tree);
+static gboolean  matemenu_tree_build_from_layout    (MateMenuTree       *tree,
+                                                  GError         **error);
+static void      matemenu_tree_force_rebuild        (MateMenuTree       *tree);
+static void      matemenu_tree_resolve_files        (MateMenuTree       *tree,
+						  GHashTable      *loaded_menu_files,
+						  MenuLayoutNode  *layout);
+static void      matemenu_tree_force_recanonicalize (MateMenuTree       *tree);
+static void      matemenu_tree_invoke_monitors      (MateMenuTree       *tree);
+
+static void matemenu_tree_item_unref_and_unset_parent (gpointer itemp);
+
+#ifdef WITH_COLLECTION
+static void collection_applet_changed (GSettings    *settings,
+                                       gchar        *key,
+                                       MateMenuTree *self);
+#endif /* WITH_COLLECTION */
+
+typedef enum
+{
+  MENU_FILE_MONITOR_INVALID = 0,
+  MENU_FILE_MONITOR_FILE,
+  MENU_FILE_MONITOR_NONEXISTENT_FILE,
+  MENU_FILE_MONITOR_DIRECTORY
+} MenuFileMonitorType;
+
+typedef struct
+{
+  MenuFileMonitorType  type;
+  MenuMonitor         *monitor;
+} MenuFileMonitor;
+
+static void
+handle_nonexistent_menu_file_changed (MenuMonitor      *monitor,
+				      MenuMonitorEvent  event,
+				      const char       *path,
+				      MateMenuTree        *tree)
+{
+  if (event == MENU_MONITOR_EVENT_CHANGED ||
+      event == MENU_MONITOR_EVENT_CREATED)
+    {
+      menu_verbose ("\"%s\" %s, marking tree for recanonicalization\n",
+                    path,
+                    event == MENU_MONITOR_EVENT_CREATED ? "created" : "changed");
+
+      matemenu_tree_force_recanonicalize (tree);
+      matemenu_tree_invoke_monitors (tree);
+    }
+}
+
+static void
+handle_menu_file_changed (MenuMonitor      *monitor,
+			  MenuMonitorEvent  event,
+			  const char       *path,
+                          MateMenuTree        *tree)
+{
+  menu_verbose ("\"%s\" %s, marking tree for recanicalization\n",
+		path,
+		event == MENU_MONITOR_EVENT_CREATED ? "created" :
+		event == MENU_MONITOR_EVENT_CHANGED ? "changed" : "deleted");
+
+  matemenu_tree_force_recanonicalize (tree);
+  matemenu_tree_invoke_monitors (tree);
+}
+
+static void
+handle_menu_file_directory_changed (MenuMonitor      *monitor,
+				    MenuMonitorEvent  event,
+				    const char       *path,
+				    MateMenuTree        *tree)
+{
+  if (!g_str_has_suffix (path, ".menu"))
+    return;
+
+  menu_verbose ("\"%s\" %s, marking tree for recanicalization\n",
+		path,
+		event == MENU_MONITOR_EVENT_CREATED ? "created" :
+		event == MENU_MONITOR_EVENT_CHANGED ? "changed" : "deleted");
+
+  matemenu_tree_force_recanonicalize (tree);
+  matemenu_tree_invoke_monitors (tree);
+}
+
+static void
+matemenu_tree_add_menu_file_monitor (MateMenuTree           *tree,
+				  const char          *path,
+				  MenuFileMonitorType  type)
+{
+  MenuFileMonitor *monitor;
+
+  monitor = g_slice_new0 (MenuFileMonitor);
+
+  monitor->type = type;
+
+  switch (type)
+    {
+    case MENU_FILE_MONITOR_FILE:
+      menu_verbose ("Adding a menu file monitor for \"%s\"\n", path);
+
+      monitor->monitor = menu_get_file_monitor (path);
+      menu_monitor_add_notify (monitor->monitor,
+			       (MenuMonitorNotifyFunc) handle_menu_file_changed,
+			       tree);
+      break;
+
+    case MENU_FILE_MONITOR_NONEXISTENT_FILE:
+      menu_verbose ("Adding a menu file monitor for non-existent \"%s\"\n", path);
+
+      monitor->monitor = menu_get_file_monitor (path);
+      menu_monitor_add_notify (monitor->monitor,
+			       (MenuMonitorNotifyFunc) handle_nonexistent_menu_file_changed,
+			       tree);
+      break;
+
+    case MENU_FILE_MONITOR_DIRECTORY:
+      menu_verbose ("Adding a menu directory monitor for \"%s\"\n", path);
+
+      monitor->monitor = menu_get_directory_monitor (path);
+      menu_monitor_add_notify (monitor->monitor,
+			       (MenuMonitorNotifyFunc) handle_menu_file_directory_changed,
+			       tree);
+      break;
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  tree->menu_file_monitors = g_slist_prepend (tree->menu_file_monitors, monitor);
+}
+
+static void
+remove_menu_file_monitor (MenuFileMonitor *monitor,
+			  MateMenuTree       *tree)
+{
+  switch (monitor->type)
+    {
+    case MENU_FILE_MONITOR_FILE:
+      menu_monitor_remove_notify (monitor->monitor,
+				  (MenuMonitorNotifyFunc) handle_menu_file_changed,
+				  tree);
+      break;
+
+    case MENU_FILE_MONITOR_NONEXISTENT_FILE:
+      menu_monitor_remove_notify (monitor->monitor,
+				  (MenuMonitorNotifyFunc) handle_nonexistent_menu_file_changed,
+				  tree);
+      break;
+
+    case MENU_FILE_MONITOR_DIRECTORY:
+      menu_monitor_remove_notify (monitor->monitor,
+				  (MenuMonitorNotifyFunc) handle_menu_file_directory_changed,
+				  tree);
+      break;
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  menu_monitor_unref (monitor->monitor);
+  monitor->monitor = NULL;
+
+  monitor->type = MENU_FILE_MONITOR_INVALID;
+
+  g_slice_free (MenuFileMonitor, monitor);
+}
+
+static void
+matemenu_tree_remove_menu_file_monitors (MateMenuTree *tree)
+{
+  menu_verbose ("Removing all menu file monitors\n");
+
+  g_slist_foreach (tree->menu_file_monitors,
+                   (GFunc) remove_menu_file_monitor,
+                   tree);
+  g_slist_free (tree->menu_file_monitors);
+  tree->menu_file_monitors = NULL;
+}
+
+static gboolean
+canonicalize_path (MateMenuTree  *tree,
+                   const char *path)
+{
+  tree->canonical_path = realpath (path, NULL);
+  if (tree->canonical_path)
+    {
+      tree->canonical = TRUE;
+      matemenu_tree_add_menu_file_monitor (tree,
+					tree->canonical_path,
+					MENU_FILE_MONITOR_FILE);
+    }
+  else
+    {
+      matemenu_tree_add_menu_file_monitor (tree,
+					path,
+					MENU_FILE_MONITOR_NONEXISTENT_FILE);
+    }
+
+  return tree->canonical;
+}
+
+static gboolean
+canonicalize_basename_with_config_dir (MateMenuTree   *tree,
+                                       const char *basename,
+                                       const char *config_dir)
+{
+  gboolean  ret;
+  char     *path;
+
+  path = g_build_filename (config_dir, "menus",  basename,  NULL);
+  ret = canonicalize_path (tree, path);
+  g_free (path);
+
+  return ret;
+}
+
+static void
+canonicalize_basename (MateMenuTree  *tree,
+                       const char *basename)
+{
+  if (!canonicalize_basename_with_config_dir (tree,
+                                              basename,
+                                              g_get_user_config_dir ()))
+    {
+      const char * const *system_config_dirs;
+      int                 i;
+
+      system_config_dirs = g_get_system_config_dirs ();
+
+      i = 0;
+      while (system_config_dirs[i] != NULL)
+        {
+          if (canonicalize_basename_with_config_dir (tree,
+                                                     basename,
+                                                     system_config_dirs[i]))
+            break;
+
+          ++i;
+        }
+    }
+}
+
+static gboolean matemenu_tree_canonicalize_path(MateMenuTree* tree,
+                              GError   **error)
+{
+  const char *menu_file = NULL;
+
+  if (tree->canonical)
+    return TRUE;
+
+	g_assert(tree->canonical_path == NULL);
+
+  matemenu_tree_remove_menu_file_monitors (tree);
+
+  if (tree->path)
+    {
+      menu_file = tree->path;
+      canonicalize_path (tree, tree->path);
+    }
+  else
+    {
+      const gchar *xdg_menu_prefix;
+
+      menu_file = tree->basename;
+      xdg_menu_prefix = g_getenv ("XDG_MENU_PREFIX");
+
+      if (xdg_menu_prefix != NULL)
+        {
+          gchar *prefixed_basename;
+
+          prefixed_basename = g_strdup_printf ("%sapplications.menu",
+                                               xdg_menu_prefix);
+
+          /* Some gnome-menus using applications just use "applications.menu"
+           * as the basename and expect gnome-menus to prefix it. Others (e.g.
+           * Alacarte) explicitly use "${XDG_MENU_PREFIX}applications.menu" as
+           * the basename, because they want to save changes to the right files
+           * in ~. In both cases, we want to use "applications-merged" as the
+           * merge directory (as required by the fd.o menu spec), so we save
+           * the non-prefixed basename and use it later when calling
+           * menu_layout_load().
+           */
+          if (!g_strcmp0 (tree->basename, "mate-applications.menu") ||
+              !g_strcmp0 (tree->basename, prefixed_basename))
+            {
+              canonicalize_basename (tree, prefixed_basename);
+              g_free (tree->non_prefixed_basename);
+              tree->non_prefixed_basename = g_strdup ("mate-applications.menu");
+            }
+          g_free (prefixed_basename);
+        }
+
+      if (!tree->canonical)
+        canonicalize_basename (tree, tree->basename);
+    }
+
+  if (tree->canonical)
+    {
+      menu_verbose ("Successfully looked up menu_file for \"%s\": %s\n",
+                    menu_file, tree->canonical_path);
+      return TRUE;
+    }
+  else
+    {
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_FAILED,
+                   "Failed to look up menu_file for \"%s\"\n",
+                   menu_file);
+      return FALSE;
+    }
+}
+
+static void
+matemenu_tree_force_recanonicalize (MateMenuTree *tree)
+{
+  matemenu_tree_remove_menu_file_monitors (tree);
+
+  if (tree->canonical)
+    {
+      matemenu_tree_force_reload (tree);
+
+      g_free (tree->canonical_path);
+      tree->canonical_path = NULL;
+
+      tree->canonical = FALSE;
+    }
+}
+
+/**
+ * matemenu_tree_new:
+ * @menu_basename: Basename of menu file
+ * @flags: Flags controlling menu content
+ *
+ * Returns: (transfer full): A new #MateMenuTree instance
+ */
+MateMenuTree *
+matemenu_tree_new (const char     *menu_basename,
+                MateMenuTreeFlags  flags)
+{
+  g_return_val_if_fail (menu_basename != NULL, NULL);
+
+  return g_object_new (MATEMENU_TYPE_TREE,
+                       "menu-basename", menu_basename,
+                       "flags", flags,
+                       NULL);
+}
+
+/**
+ * matemenu_tree_new_fo_path:
+ * @menu_path: Path of menu file
+ * @flags: Flags controlling menu content
+ *
+ * Returns: (transfer full): A new #MateMenuTree instance
+ */
+MateMenuTree *
+matemenu_tree_new_for_path (const char     *menu_path,
+                         MateMenuTreeFlags  flags)
+{
+  g_return_val_if_fail (menu_path != NULL, NULL);
+
+  return g_object_new (MATEMENU_TYPE_TREE,
+                       "menu-path", menu_path,
+                       "flags", flags,
+                       NULL);
+}
+
+static GObject *
+matemenu_tree_constructor (GType                  type,
+                        guint                  n_construct_properties,
+                        GObjectConstructParam *construct_properties)
+{
+	GObject   *obj;
+	MateMenuTree *self;
+
+	obj = G_OBJECT_CLASS (matemenu_tree_parent_class)->constructor (type,
+                                                                     n_construct_properties,
+                                                                     construct_properties);
+
+        /* If MateMenuTree:menu-path is set, then we should make sure that
+         * MateMenuTree:menu-basename is unset (especially as it has a default
+         * value). This has to be done here, in the constructor, since the
+         * properties are construct-only. */
+
+	self = MATEMENU_TREE (obj);
+
+        if (self->path != NULL)
+          g_object_set (self, "menu-basename", NULL, NULL);
+
+	return obj;
+}
+
+static void
+matemenu_tree_set_property (GObject         *object,
+                         guint            prop_id,
+                         const GValue    *value,
+                         GParamSpec      *pspec)
+{
+  MateMenuTree *self = MATEMENU_TREE (object);
+
+  switch (prop_id)
+    {
+    case PROP_MENU_BASENAME:
+      self->basename = g_value_dup_string (value);
+      break;
+
+    case PROP_MENU_PATH:
+      self->path = g_value_dup_string (value);
+      break;
+
+    case PROP_FLAGS:
+      self->flags = g_value_get_flags (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+matemenu_tree_get_property (GObject         *object,
+                         guint            prop_id,
+                         GValue          *value,
+                         GParamSpec      *pspec)
+{
+  MateMenuTree *self = MATEMENU_TREE (object);
+
+  switch (prop_id)
+    {
+    case PROP_MENU_BASENAME:
+      g_value_set_string (value, self->basename);
+      break;
+    case PROP_MENU_PATH:
+      g_value_set_string (value, self->path);
+      break;
+    case PROP_FLAGS:
+      g_value_set_flags (value, self->flags);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+matemenu_tree_finalize (GObject *object)
+{
+  MateMenuTree *tree = MATEMENU_TREE (object);
+
+  matemenu_tree_force_recanonicalize (tree);
+
+  if (tree->basename != NULL)
+    g_free (tree->basename);
+  tree->basename = NULL;
+
+  g_free (tree->non_prefixed_basename);
+  tree->non_prefixed_basename = NULL;
+
+  if (tree->path != NULL)
+    g_free (tree->path);
+  tree->path = NULL;
+
+  if (tree->canonical_path != NULL)
+    g_free (tree->canonical_path);
+  tree->canonical_path = NULL;
+
+  g_hash_table_destroy (tree->entries_by_id);
+  tree->entries_by_id = NULL;
+
+#ifdef WITH_COLLECTION
+  if (tree->collection_applet != NULL)
+  {
+    g_ptr_array_free (tree->collection_applet, TRUE);
+    tree->collection_applet = NULL;
+  }
+
+  g_signal_handlers_disconnect_by_func (tree->settings,
+                                        G_CALLBACK (collection_applet_changed),
+                                        tree);
+
+  g_object_unref (tree->settings);
+  if (tree->emit_changed_signal != 0)
+    g_source_remove (tree->emit_changed_signal);
+  tree->emit_changed_signal = 0;
+#endif /* WITH_COLLECTION */
+
+  G_OBJECT_CLASS (matemenu_tree_parent_class)->finalize (object);
+}
+
+#ifdef WITH_COLLECTION
+static void
+load_object (char         *id,
+             MateMenuTree *self)
+{
+  ObjectType   object_type;
+  char        *object_path;
+  GSettings   *settings;
+
+  object_path = g_strdup_printf ("/org/mate/panel/objects/%s/", id);
+  settings = g_settings_new_with_path ("org.mate.panel.object", object_path);
+
+  object_type = g_settings_get_enum (settings, "object-type");
+  if (object_type == OBJECT_LAUNCHER)
+  {
+    char *location;
+    char *desktop_name;
+
+    if (self->collection_applet == NULL)
+        self->collection_applet = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
+
+    location = g_settings_get_string (settings, "launcher-location");
+    desktop_name = g_path_get_basename (location);
+    if (strstr (desktop_name, "-1.") != NULL )
+    {
+      char **str;
+
+      str = g_strsplit (desktop_name, "-1.", -1);
+      g_free (desktop_name);
+      desktop_name = g_strdup_printf ("%s.%s", str[0], str[1]);
+      g_strfreev (str);
+    }
+    g_ptr_array_add (self->collection_applet, desktop_name);
+    g_free (location);
+  }
+  g_free (object_path);
+  g_object_unref (settings);
+}
+
+static gboolean
+emit_changed_signal (gpointer data)
+{
+  MateMenuTree *self = data;
+  self->emit_changed_signal = 0;
+
+  matemenu_tree_force_rebuild (self);
+  matemenu_tree_invoke_monitors (self);
+
+  return FALSE;
+}
+
+static void
+get_panel_collection_applet (MateMenuTree *self)
+{
+  gchar **list;
+  guint   i;
+
+  list = g_settings_get_strv (self->settings, "object-id-list");
+  for (i = 0; list[i]; i++)
+  {
+    load_object (list[i], self);
+  }
+  g_strfreev (list);
+}
+
+static void
+collection_applet_changed (GSettings    *settings,
+                           gchar        *key,
+                           MateMenuTree *self)
+{
+  if (self->collection_applet != NULL)
+  {
+    g_ptr_array_free (self->collection_applet, TRUE);
+    self->collection_applet = NULL;
+  }
+  get_panel_collection_applet (self);
+  if (self->emit_changed_signal == 0)
+    self->emit_changed_signal = g_idle_add (emit_changed_signal, (gpointer)self);
+}
+#endif /* WITH_COLLECTION */
+
+static void
+matemenu_tree_init (MateMenuTree *self)
+{
+  self->entries_by_id = g_hash_table_new (g_str_hash, g_str_equal);
+#ifdef WITH_COLLECTION
+  self->collection_applet = NULL;
+  self->settings = g_settings_new ("org.mate.panel");
+  get_panel_collection_applet (self);
+  g_signal_connect (self->settings, "changed::object-id-list",
+                    G_CALLBACK (collection_applet_changed),
+                    self);
+  self->emit_changed_signal = 0;
+#endif /* WITH_COLLECTION */
+}
+
+static void
+matemenu_tree_class_init (MateMenuTreeClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->constructor = matemenu_tree_constructor;
+  gobject_class->get_property = matemenu_tree_get_property;
+  gobject_class->set_property = matemenu_tree_set_property;
+  gobject_class->finalize = matemenu_tree_finalize;
+
+  /**
+   * MateMenuTree:menu-basename:
+   *
+   * The name of the menu file; must be a basename or a relative path. The file
+   * will be looked up in $XDG_CONFIG_DIRS/menus/. See the Desktop Menu
+   * specification.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_MENU_BASENAME,
+                                   g_param_spec_string ("menu-basename", "", "",
+                                                        "applications.menu",
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  /**
+   * MateMenuTree:menu-path:
+   *
+   * The full path of the menu file. If set, MateMenuTree:menu-basename will get
+   * ignored.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_MENU_PATH,
+                                   g_param_spec_string ("menu-path", "", "",
+                                                        NULL,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  /**
+   * MateMenuTree:flags:
+   *
+   * Flags controlling the content of the menu.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_FLAGS,
+                                   g_param_spec_flags ("flags", "", "",
+                                                       MATEMENU_TYPE_TREE_FLAGS,
+                                                       MATEMENU_TREE_FLAGS_NONE,
+                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  /**
+   * MateMenuTree:changed:
+   *
+   * This signal is emitted when applications are added, removed, or
+   * upgraded.  But note the new data will only be visible after
+   * matemenu_tree_load_sync() or a variant thereof is invoked.
+   */
+  matemenu_tree_signals[CHANGED] =
+      g_signal_new ("changed",
+                    G_TYPE_FROM_CLASS (klass),
+                    G_SIGNAL_RUN_LAST,
+                    0,
+                    NULL, NULL,
+                    g_cclosure_marshal_VOID__VOID,
+                    G_TYPE_NONE, 0);
+}
+
+/**
+ * matemenu_tree_get_canonical_menu_path:
+ * @tree: a #MateMenuTree
+ *
+ * This function is only available if the tree has been loaded via
+ * matemenu_tree_load_sync() or a variant thereof.
+ *
+ * Returns: The absolute and canonicalized path to the loaded menu file
+ */
+const char *
+matemenu_tree_get_canonical_menu_path (MateMenuTree *tree)
+{
+  g_return_val_if_fail (MATEMENU_IS_TREE (tree), NULL);
+  g_return_val_if_fail (tree->loaded, NULL);
+
+  return tree->canonical_path;
+}
+
+/**
+ * matemenu_tree_load_sync:
+ * @tree: a #MateMenuTree
+ * @error: a #GError
+ *
+ * Synchronously load the menu contents.  This function
+ * performs a significant amount of blocking I/O if the
+ * tree has not been loaded yet.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ */
+gboolean
+matemenu_tree_load_sync (MateMenuTree  *tree,
+                      GError    **error)
+{
+  GError *local_error = NULL;
+
+  if (tree->loaded)
+    return TRUE;
+
+  if (!matemenu_tree_build_from_layout (tree, &local_error))
+    {
+      if (local_error)
+        g_propagate_error (error, local_error);
+      return FALSE;
+    }
+
+  tree->loaded = TRUE;
+
+  return TRUE;
+}
+
+/**
+ * matemenu_tree_get_root_directory:
+ * @tree: a #MateMenuTree
+ *
+ * Get the root directory; you must have loaded the tree first (at
+ * least once) via matemenu_tree_load_sync() or a variant thereof.
+ *
+ * Returns: (transfer full): Root of the tree
+ */
+MateMenuTreeDirectory *
+matemenu_tree_get_root_directory (MateMenuTree *tree)
+{
+  g_return_val_if_fail (tree != NULL, NULL);
+  g_return_val_if_fail (tree->loaded, NULL);
+
+  return matemenu_tree_item_ref (tree->root);
+}
+
+static MateMenuTreeDirectory *
+find_path (MateMenuTreeDirectory *directory,
+	   const char         *path)
+{
+  const char *name;
+  char       *slash;
+  char       *freeme;
+  GSList     *tmp;<--- Variable 'tmp' can be declared as pointer to const
+
+  while (path[0] == G_DIR_SEPARATOR) path++;
+
+  if (path[0] == '\0')
+    return directory;
+
+  freeme = NULL;
+  slash = strchr (path, G_DIR_SEPARATOR);
+  if (slash)
+    {
+      name = freeme = g_strndup (path, (gsize)(slash - path));
+      path = slash + 1;
+    }
+  else
+    {
+      name = path;
+      path = NULL;
+    }
+
+  tmp = directory->contents;
+  while (tmp != NULL)
+    {
+      MateMenuTreeItem *item = tmp->data;
+
+      if (item->type != MATEMENU_TREE_ITEM_DIRECTORY)
+        {
+          tmp = tmp->next;
+          continue;
+        }
+
+      if (!strcmp (name, MATEMENU_TREE_DIRECTORY (item)->name))
+	{
+	  g_free (freeme);
+
+	  if (path)
+	    return find_path (MATEMENU_TREE_DIRECTORY (item), path);
+	  else
+	    return MATEMENU_TREE_DIRECTORY (item);
+	}
+
+      tmp = tmp->next;
+    }
+
+  g_free (freeme);
+
+  return NULL;
+}
+
+MateMenuTreeDirectory *
+matemenu_tree_get_directory_from_path (MateMenuTree  *tree,
+				    const char *path)
+{
+  MateMenuTreeDirectory *root;
+  MateMenuTreeDirectory *directory;
+
+  g_return_val_if_fail (tree != NULL, NULL);
+  g_return_val_if_fail (path != NULL, NULL);
+
+  if (path[0] != G_DIR_SEPARATOR)
+    return NULL;
+
+  if (!(root = matemenu_tree_get_root_directory (tree)))
+    return NULL;
+
+  directory = find_path (root, path);
+
+  matemenu_tree_item_unref (root);
+
+  return directory ? matemenu_tree_item_ref (directory) : NULL;
+}
+
+/**
+ * matemenu_tree_get_entry_by_id:
+ * @tree: a #MateMenuTree
+ * @id: a desktop file ID
+ *
+ * Look up the entry corresponding to the given "desktop file id".
+ *
+ * Returns: (transfer full): A newly referenced #MateMenuTreeEntry, or %NULL if none
+ */
+MateMenuTreeEntry     *
+matemenu_tree_get_entry_by_id (MateMenuTree  *tree,
+			    const char *id)
+{
+  MateMenuTreeEntry *entry;
+
+  g_return_val_if_fail (tree->loaded, NULL);
+
+  entry = g_hash_table_lookup (tree->entries_by_id, id);
+  if (entry != NULL)
+    matemenu_tree_item_ref (entry);
+
+  return entry;
+}
+
+static void
+matemenu_tree_invoke_monitors (MateMenuTree *tree)
+{
+  g_signal_emit (tree, matemenu_tree_signals[CHANGED], 0);
+}
+
+static MateMenuTreeDirectory *
+get_parent (MateMenuTreeItem *item)
+{
+  g_return_val_if_fail (item != NULL, NULL);
+  return item->parent ? matemenu_tree_item_ref (item->parent) : NULL;
+}
+
+/**
+ * matemenu_tree_directory_get_parent:
+ * @directory: a #MateMenuTreeDirectory
+ *
+ * Returns: (transfer full): The parent directory, or %NULL if none
+ */
+MateMenuTreeDirectory *
+matemenu_tree_directory_get_parent (MateMenuTreeDirectory *directory)
+{
+  return get_parent ((MateMenuTreeItem *)directory);
+}
+
+/**
+ * matemenu_tree_entry_get_parent:
+ * @entry: a #MateMenuTreeEntry
+ *
+ * Returns: (transfer full): The parent directory, or %NULL if none
+ */
+MateMenuTreeDirectory *
+matemenu_tree_entry_get_parent (MateMenuTreeEntry *entry)
+{
+  return get_parent ((MateMenuTreeItem *)entry);
+}
+
+/**
+ * matemenu_tree_alias_get_parent:
+ * @alias: a #MateMenuTreeAlias
+ *
+ * Returns: (transfer full): The parent directory, or %NULL if none
+ */
+MateMenuTreeDirectory *
+matemenu_tree_alias_get_parent (MateMenuTreeAlias *alias)
+{
+  return get_parent ((MateMenuTreeItem *)alias);
+}
+
+/**
+ * matemenu_tree_header_get_parent:
+ * @header: a #MateMenuTreeHeader
+ *
+ * Returns: (transfer full): The parent directory, or %NULL if none
+ */
+MateMenuTreeDirectory *
+matemenu_tree_header_get_parent (MateMenuTreeHeader *header)
+{
+  return get_parent ((MateMenuTreeItem *)header);
+}
+
+/**
+ * matemenu_tree_separator_get_parent:
+ * @separator: a #MateMenuTreeSeparator
+ *
+ * Returns: (transfer full): The parent directory, or %NULL if none
+ */
+MateMenuTreeDirectory *
+matemenu_tree_separator_get_parent (MateMenuTreeSeparator *separator)
+{
+  return get_parent ((MateMenuTreeItem *)separator);
+}
+
+static void
+matemenu_tree_item_set_parent (MateMenuTreeItem      *item,
+			    MateMenuTreeDirectory *parent)
+{
+  g_return_if_fail (item != NULL);
+
+  item->parent = parent;
+}
+
+/**
+ * matemenu_tree_iter_ref: (skip)
+ * @iter: iter
+ *
+ * Increment the reference count of @iter
+ */
+MateMenuTreeIter *
+matemenu_tree_iter_ref (MateMenuTreeIter *iter)
+{
+  g_atomic_int_inc (&iter->refcount);
+  return iter;
+}
+
+/**
+ * matemenu_tree_iter_unref: (skip)
+ * @iter: iter
+ *
+ * Decrement the reference count of @iter
+ */
+void
+matemenu_tree_iter_unref (MateMenuTreeIter *iter)
+{
+  if (!g_atomic_int_dec_and_test (&iter->refcount))
+    return;
+
+  g_slist_free_full (iter->contents, (GDestroyNotify)matemenu_tree_item_unref);
+
+  g_slice_free (MateMenuTreeIter, iter);
+}
+
+/**
+ * matemenu_tree_directory_iter:
+ * @directory: directory
+ *
+ * Returns: (transfer full): A new iterator over the directory contents
+ */
+MateMenuTreeIter *
+matemenu_tree_directory_iter (MateMenuTreeDirectory *directory)
+{
+  MateMenuTreeIter *iter;
+
+  g_return_val_if_fail (directory != NULL, NULL);
+
+  iter = g_slice_new0 (MateMenuTreeIter);
+  iter->refcount = 1;
+
+  iter->contents = g_slist_copy (directory->contents);
+  iter->contents_iter = iter->contents;
+  g_slist_foreach (iter->contents, (GFunc) matemenu_tree_item_ref, NULL);
+
+  return iter;
+}
+
+/**
+ * matemenu_tree_iter_next:
+ * @iter: iter
+ *
+ * Change the iterator to the next item, and return its type.  If
+ * there are no more items, %MATEMENU_TREE_ITEM_INVALID is returned.
+ *
+ * Returns: The type of the next item that can be retrived from the iterator
+ */
+MateMenuTreeItemType
+matemenu_tree_iter_next (MateMenuTreeIter *iter)
+{
+  g_return_val_if_fail (iter != NULL, MATEMENU_TREE_ITEM_INVALID);
+
+  if (iter->contents_iter)
+    {
+      iter->item = iter->contents_iter->data;
+      iter->contents_iter = iter->contents_iter->next;
+      return iter->item->type;
+    }
+  else
+    return MATEMENU_TREE_ITEM_INVALID;
+}
+
+/**
+ * matemenu_tree_iter_get_directory:
+ * @iter: iter
+ *
+ * This method may only be called if matemenu_tree_iter_next()
+ * returned MATEMENU_TREE_ITEM_DIRECTORY.
+ *
+ * Returns: (transfer full): A directory
+ */
+MateMenuTreeDirectory *
+matemenu_tree_iter_get_directory (MateMenuTreeIter *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == MATEMENU_TREE_ITEM_DIRECTORY, NULL);
+
+  return (MateMenuTreeDirectory*)matemenu_tree_item_ref (iter->item);
+}
+
+/**
+ * matemenu_tree_iter_get_entry:
+ * @iter: iter
+ *
+ * This method may only be called if matemenu_tree_iter_next()
+ * returned MATEMENU_TREE_ITEM_ENTRY.
+ *
+ * Returns: (transfer full): An entry
+ */
+MateMenuTreeEntry *
+matemenu_tree_iter_get_entry (MateMenuTreeIter *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == MATEMENU_TREE_ITEM_ENTRY, NULL);
+
+  return (MateMenuTreeEntry*)matemenu_tree_item_ref (iter->item);
+}
+
+/**
+ * matemenu_tree_iter_get_header:
+ * @iter: iter
+ *
+ * This method may only be called if matemenu_tree_iter_next()
+ * returned MATEMENU_TREE_ITEM_HEADER.
+ *
+ * Returns: (transfer full): A header
+ */
+MateMenuTreeHeader *
+matemenu_tree_iter_get_header (MateMenuTreeIter *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == MATEMENU_TREE_ITEM_HEADER, NULL);
+
+  return (MateMenuTreeHeader*)matemenu_tree_item_ref (iter->item);
+}
+
+/**
+ * matemenu_tree_iter_get_alias:
+ * @iter: iter
+ *
+ * This method may only be called if matemenu_tree_iter_next()
+ * returned MATEMENU_TREE_ITEM_ALIAS.
+ *
+ * Returns: (transfer full): An alias
+ */
+MateMenuTreeAlias *
+matemenu_tree_iter_get_alias (MateMenuTreeIter *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == MATEMENU_TREE_ITEM_ALIAS, NULL);
+
+  return (MateMenuTreeAlias*)matemenu_tree_item_ref (iter->item);
+}
+
+/**
+ * matemenu_tree_iter_get_separator:
+ * @iter: iter
+ *
+ * This method may only be called if matemenu_tree_iter_next()
+ * returned #MATEMENU_TREE_ITEM_SEPARATOR.
+ *
+ * Returns: (transfer full): A separator
+ */
+MateMenuTreeSeparator *
+matemenu_tree_iter_get_separator (MateMenuTreeIter *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == MATEMENU_TREE_ITEM_SEPARATOR, NULL);
+
+  return (MateMenuTreeSeparator*)matemenu_tree_item_ref (iter->item);
+}
+
+const char *
+matemenu_tree_directory_get_name (MateMenuTreeDirectory *directory)
+{
+  g_return_val_if_fail (directory != NULL, NULL);
+
+  if (!directory->directory_entry)
+    return directory->name;
+
+  return desktop_entry_get_name (directory->directory_entry);
+}
+
+const char *
+matemenu_tree_directory_get_generic_name (MateMenuTreeDirectory *directory)
+{
+  g_return_val_if_fail (directory != NULL, NULL);
+
+  if (!directory->directory_entry)
+    return NULL;
+
+  return desktop_entry_get_generic_name (directory->directory_entry);
+}
+
+const char *
+matemenu_tree_directory_get_comment (MateMenuTreeDirectory *directory)
+{
+  g_return_val_if_fail (directory != NULL, NULL);
+
+  if (!directory->directory_entry)
+    return NULL;
+
+  return desktop_entry_get_comment (directory->directory_entry);
+}
+
+/**
+ * matemenu_tree_directory_get_icon:
+ * @directory: a #MateMenuTreeDirectory
+ *
+ * Gets the icon for the directory.
+ *
+ * Returns: (transfer none): The #GIcon for this directory
+ */
+GIcon *
+matemenu_tree_directory_get_icon (MateMenuTreeDirectory *directory)
+{
+	g_return_val_if_fail(directory != NULL, NULL);
+
+	if (!directory->directory_entry)
+		return NULL;
+
+	return desktop_entry_get_icon(directory->directory_entry);
+}
+
+const char *
+matemenu_tree_directory_get_desktop_file_path (MateMenuTreeDirectory *directory)
+{
+  g_return_val_if_fail (directory != NULL, NULL);
+
+  if (!directory->directory_entry)
+    return NULL;
+
+  return desktop_entry_get_path (directory->directory_entry);
+}
+
+const char *
+matemenu_tree_directory_get_menu_id (MateMenuTreeDirectory *directory)<--- Parameter 'directory' can be declared as pointer to const
+{
+  g_return_val_if_fail (directory != NULL, NULL);
+
+  return directory->name;
+}
+
+gboolean
+matemenu_tree_directory_get_is_nodisplay (MateMenuTreeDirectory *directory)<--- Parameter 'directory' can be declared as pointer to const
+{
+  g_return_val_if_fail (directory != NULL, FALSE);
+
+  return directory->is_nodisplay;
+}
+
+/**
+ * matemenu_tree_directory_get_tree:
+ * @directory: A #MateMenuTreeDirectory
+ *
+ * Grab the tree associated with a #MateMenuTreeItem.
+ *
+ * Returns: (transfer full): The #MateMenuTree
+ */
+MateMenuTree *
+matemenu_tree_directory_get_tree (MateMenuTreeDirectory *directory)
+{
+  g_return_val_if_fail (directory != NULL, NULL);
+
+  return g_object_ref (directory->item.tree);
+}
+
+static void
+append_directory_path (MateMenuTreeDirectory *directory,
+		       GString            *path)
+{
+
+  if (!directory->item.parent)
+    {
+      g_string_append_c (path, G_DIR_SEPARATOR);
+      return;
+    }
+
+  append_directory_path (directory->item.parent, path);
+
+  g_string_append (path, directory->name);
+  g_string_append_c (path, G_DIR_SEPARATOR);
+}
+
+char *
+matemenu_tree_directory_make_path (MateMenuTreeDirectory *directory,
+				MateMenuTreeEntry     *entry)
+{
+  GString *path;
+
+  g_return_val_if_fail (directory != NULL, NULL);
+
+  path = g_string_new (NULL);
+
+  append_directory_path (directory, path);
+
+  if (entry != NULL)
+    g_string_append (path,
+		     desktop_entry_get_basename (entry->desktop_entry));
+
+  return g_string_free (path, FALSE);
+}
+
+/**
+ * matemenu_tree_entry_get_app_info:
+ * @entry: a #MateMenuTreeEntry
+ *
+ * Returns: (transfer none): The #GDesktopAppInfo for this entry
+ */
+GDesktopAppInfo *
+matemenu_tree_entry_get_app_info (MateMenuTreeEntry *entry)
+{
+  g_return_val_if_fail (entry != NULL, NULL);
+
+  return desktop_entry_get_app_info (entry->desktop_entry);
+}
+
+const char *
+matemenu_tree_entry_get_desktop_file_path (MateMenuTreeEntry *entry)
+{
+  g_return_val_if_fail (entry != NULL, NULL);
+
+  return desktop_entry_get_path (entry->desktop_entry);
+}
+
+const char *
+matemenu_tree_entry_get_desktop_file_id (MateMenuTreeEntry *entry)<--- Parameter 'entry' can be declared as pointer to const
+{
+  g_return_val_if_fail (entry != NULL, NULL);
+
+  return entry->desktop_file_id;
+}
+
+gboolean
+matemenu_tree_entry_get_is_nodisplay_recurse (MateMenuTreeEntry *entry)
+{
+  MateMenuTreeDirectory *directory;
+  GDesktopAppInfo *app_info;
+
+  g_return_val_if_fail (entry != NULL, FALSE);
+
+  app_info = matemenu_tree_entry_get_app_info (entry);
+
+  if (g_desktop_app_info_get_nodisplay (app_info))
+    return TRUE;
+
+  directory = entry->item.parent;
+  while (directory != NULL)
+    {
+      if (directory->is_nodisplay)
+        return TRUE;
+
+      directory = directory->item.parent;
+    }
+
+  return FALSE;
+}
+
+gboolean
+matemenu_tree_entry_get_is_excluded (MateMenuTreeEntry *entry)<--- Parameter 'entry' can be declared as pointer to const
+{
+  g_return_val_if_fail(entry != NULL, FALSE);
+
+  return entry->is_excluded;
+}
+
+gboolean
+matemenu_tree_entry_get_is_unallocated (MateMenuTreeEntry *entry)<--- Parameter 'entry' can be declared as pointer to const
+{
+  g_return_val_if_fail (entry != NULL, FALSE);
+
+  return entry->is_unallocated;
+}
+
+/**
+ * matemenu_tree_entry_get_tree:
+ * @entry: A #MateMenuTreeEntry
+ *
+ * Grab the tree associated with a #MateMenuTreeEntry.
+ *
+ * Returns: (transfer full): The #MateMenuTree
+ */
+MateMenuTree *
+matemenu_tree_entry_get_tree (MateMenuTreeEntry *entry)
+{
+	g_return_val_if_fail(entry != NULL, NULL);
+
+  return g_object_ref (entry->item.tree);
+}
+
+MateMenuTreeDirectory *
+matemenu_tree_header_get_directory (MateMenuTreeHeader *header)
+{
+  g_return_val_if_fail (header != NULL, NULL);
+
+  return matemenu_tree_item_ref (header->directory);
+}
+
+/**
+ * matemenu_tree_header_get_tree:
+ * @header: A #MateMenuTreeHeader
+ *
+ * Grab the tree associated with a #MateMenuTreeHeader.
+ *
+ * Returns: (transfer full): The #MateMenuTree
+ */
+MateMenuTree *
+matemenu_tree_header_get_tree (MateMenuTreeHeader *header)
+{
+  g_return_val_if_fail (header != NULL, NULL);
+
+  return g_object_ref (header->item.tree);
+}
+
+MateMenuTreeItemType
+matemenu_tree_alias_get_aliased_item_type (MateMenuTreeAlias *alias)
+{
+  g_return_val_if_fail (alias != NULL, MATEMENU_TREE_ITEM_INVALID);
+
+  g_assert (alias->aliased_item != NULL);
+  return alias->aliased_item->type;
+}
+
+MateMenuTreeDirectory* matemenu_tree_alias_get_directory(MateMenuTreeAlias* alias)
+{
+	g_return_val_if_fail (alias != NULL, NULL);
+
+	return matemenu_tree_item_ref(alias->directory);
+}
+
+/**
+ * matemenu_tree_alias_get_tree:
+ * @alias: A #MateMenuTreeAlias
+ *
+ * Grab the tree associated with a #MateMenuTreeAlias.
+ *
+ * Returns: (transfer full): The #MateMenuTree
+ */
+MateMenuTree *
+matemenu_tree_alias_get_tree (MateMenuTreeAlias *alias)
+{
+  g_return_val_if_fail (alias != NULL, NULL);
+
+  return g_object_ref (alias->item.tree);
+}
+
+/**
+ * matemenu_tree_separator_get_tree:
+ * @separator: A #MateMenuTreeSeparator
+ *
+ * Grab the tree associated with a #MateMenuTreeSeparator.
+ *
+ * Returns: (transfer full): The #MateMenuTree
+ */
+MateMenuTree *
+matemenu_tree_separator_get_tree (MateMenuTreeSeparator *separator)
+{
+  g_return_val_if_fail (separator != NULL, NULL);
+
+  return g_object_ref (separator->item.tree);
+}
+
+/**
+ * matemenu_tree_alias_get_aliased_directory:
+ * @alias: alias
+ *
+ * Returns: (transfer full): The aliased directory entry
+ */
+MateMenuTreeDirectory *
+matemenu_tree_alias_get_aliased_directory (MateMenuTreeAlias *alias)
+{
+  g_return_val_if_fail (alias != NULL, NULL);
+  g_return_val_if_fail (alias->aliased_item->type == MATEMENU_TREE_ITEM_DIRECTORY, NULL);
+
+  return (MateMenuTreeDirectory *) matemenu_tree_item_ref (alias->aliased_item);
+}
+
+/**
+ * matemenu_tree_alias_get_aliased_entry:
+ * @alias: alias
+ *
+ * Returns: (transfer full): The aliased entry
+ */
+MateMenuTreeEntry *
+matemenu_tree_alias_get_aliased_entry (MateMenuTreeAlias *alias)
+{
+  g_return_val_if_fail (alias != NULL, NULL);
+  g_return_val_if_fail (alias->aliased_item->type == MATEMENU_TREE_ITEM_ENTRY, NULL);
+
+  return (MateMenuTreeEntry *) matemenu_tree_item_ref (alias->aliased_item);
+}
+
+static MateMenuTreeDirectory *
+matemenu_tree_directory_new (MateMenuTree          *tree,
+                          MateMenuTreeDirectory *parent,
+			  const char         *name)
+{
+  MateMenuTreeDirectory *retval;
+
+  retval = g_slice_new0 (MateMenuTreeDirectory);
+
+  retval->item.type     = MATEMENU_TREE_ITEM_DIRECTORY;
+  retval->item.parent   = parent;
+  retval->item.refcount = 1;
+  retval->item.tree     = tree;
+
+  retval->name                = g_strdup (name);
+  retval->directory_entry     = NULL;
+  retval->entries             = NULL;
+  retval->subdirs             = NULL;
+  retval->default_layout_info = NULL;
+  retval->layout_info         = NULL;
+  retval->contents            = NULL;
+  retval->only_unallocated    = FALSE;
+  retval->is_nodisplay        = FALSE;
+  retval->layout_pending_separator = FALSE;
+  retval->preprocessed        = FALSE;
+  retval->will_inline_header  = G_MAXUINT16;
+
+  retval->default_layout_values.mask          = MENU_LAYOUT_VALUES_NONE;
+  retval->default_layout_values.show_empty    = FALSE;
+  retval->default_layout_values.inline_menus  = FALSE;
+  retval->default_layout_values.inline_limit  = 4;
+  retval->default_layout_values.inline_header = FALSE;
+  retval->default_layout_values.inline_alias  = FALSE;
+
+  return retval;
+}
+
+static void
+matemenu_tree_directory_finalize (MateMenuTreeDirectory *directory)
+{
+  g_assert (directory->item.refcount == 0);
+
+  g_slist_free_full (directory->contents,
+                     (GDestroyNotify) matemenu_tree_item_unref_and_unset_parent);
+  directory->contents = NULL;
+
+  g_slist_free_full (directory->default_layout_info,
+                     (GDestroyNotify) menu_layout_node_unref);
+  directory->default_layout_info = NULL;
+
+  g_slist_free_full (directory->layout_info,
+                     (GDestroyNotify) menu_layout_node_unref);
+  directory->layout_info = NULL;
+
+  g_slist_free_full (directory->subdirs,
+                     (GDestroyNotify) matemenu_tree_item_unref_and_unset_parent);
+  directory->subdirs = NULL;
+
+  g_slist_free_full (directory->entries,
+                     (GDestroyNotify) matemenu_tree_item_unref_and_unset_parent);
+  directory->entries = NULL;
+
+  if (directory->directory_entry)
+    desktop_entry_unref (directory->directory_entry);
+  directory->directory_entry = NULL;
+
+  g_free (directory->name);
+  directory->name = NULL;
+
+  g_slice_free (MateMenuTreeDirectory, directory);
+}
+
+static MateMenuTreeSeparator *
+matemenu_tree_separator_new (MateMenuTreeDirectory *parent)
+{
+  MateMenuTreeSeparator *retval;
+
+  retval = g_slice_new0 (MateMenuTreeSeparator);
+
+  retval->item.type     = MATEMENU_TREE_ITEM_SEPARATOR;
+  retval->item.parent   = parent;
+  retval->item.refcount = 1;
+  retval->item.tree     = parent->item.tree;
+
+  return retval;
+}
+
+static void
+matemenu_tree_separator_finalize (MateMenuTreeSeparator *separator)
+{
+  g_assert (separator->item.refcount == 0);
+
+  g_slice_free (MateMenuTreeSeparator, separator);
+}
+
+static MateMenuTreeHeader *
+matemenu_tree_header_new (MateMenuTreeDirectory *parent,
+		       MateMenuTreeDirectory *directory)
+{
+  MateMenuTreeHeader *retval;
+
+  retval = g_slice_new0 (MateMenuTreeHeader);
+
+  retval->item.type     = MATEMENU_TREE_ITEM_HEADER;
+  retval->item.parent   = parent;
+  retval->item.refcount = 1;
+  retval->item.tree     = parent->item.tree;
+
+  retval->directory = matemenu_tree_item_ref (directory);
+
+  matemenu_tree_item_set_parent (MATEMENU_TREE_ITEM (retval->directory), NULL);
+
+  return retval;
+}
+
+static void
+matemenu_tree_header_finalize (MateMenuTreeHeader *header)
+{
+  g_assert (header->item.refcount == 0);
+
+  if (header->directory != NULL)
+    matemenu_tree_item_unref (header->directory);
+  header->directory = NULL;
+
+  g_slice_free (MateMenuTreeHeader, header);
+}
+
+static MateMenuTreeAlias *
+matemenu_tree_alias_new (MateMenuTreeDirectory *parent,
+		      MateMenuTreeDirectory *directory,
+		      MateMenuTreeItem      *item)
+{
+  MateMenuTreeAlias *retval;
+
+  retval = g_slice_new0 (MateMenuTreeAlias);
+
+  retval->item.type     = MATEMENU_TREE_ITEM_ALIAS;
+  retval->item.parent   = parent;
+  retval->item.refcount = 1;
+  retval->item.tree     = parent->item.tree;
+
+  retval->directory    = matemenu_tree_item_ref (directory);
+  if (item->type != MATEMENU_TREE_ITEM_ALIAS)
+    retval->aliased_item = matemenu_tree_item_ref (item);
+  else
+    {
+      MateMenuTreeAlias *alias = MATEMENU_TREE_ALIAS (item);
+      retval->aliased_item = matemenu_tree_item_ref (alias->aliased_item);
+    }
+
+  matemenu_tree_item_set_parent (MATEMENU_TREE_ITEM (retval->directory), NULL);
+  matemenu_tree_item_set_parent (retval->aliased_item, NULL);
+
+  return retval;
+}
+
+static void
+matemenu_tree_alias_finalize (MateMenuTreeAlias *alias)
+{
+  g_assert (alias->item.refcount == 0);
+
+  if (alias->directory != NULL)
+    matemenu_tree_item_unref (alias->directory);
+  alias->directory = NULL;
+
+  if (alias->aliased_item != NULL)
+    matemenu_tree_item_unref (alias->aliased_item);
+  alias->aliased_item = NULL;
+
+  g_slice_free (MateMenuTreeAlias, alias);
+}
+
+static MateMenuTreeEntry *
+matemenu_tree_entry_new (MateMenuTreeDirectory *parent,
+		      DesktopEntry       *desktop_entry,
+		      const char         *desktop_file_id,
+		      gboolean            is_excluded,
+                      gboolean            is_unallocated)
+{
+  MateMenuTreeEntry *retval;
+
+  retval = g_slice_new0 (MateMenuTreeEntry);
+
+  retval->item.type     = MATEMENU_TREE_ITEM_ENTRY;
+  retval->item.parent   = parent;
+  retval->item.refcount = 1;
+  retval->item.tree     = parent->item.tree;
+
+  retval->desktop_entry   = desktop_entry_ref (desktop_entry);
+  retval->desktop_file_id = g_strdup (desktop_file_id);
+  retval->is_excluded     = is_excluded != FALSE;
+  retval->is_unallocated  = is_unallocated != FALSE;
+
+  return retval;
+}
+
+static void
+matemenu_tree_entry_finalize (MateMenuTreeEntry *entry)
+{
+  g_assert (entry->item.refcount == 0);
+
+  g_free (entry->desktop_file_id);
+  entry->desktop_file_id = NULL;
+
+  if (entry->desktop_entry)
+    desktop_entry_unref (entry->desktop_entry);
+  entry->desktop_entry = NULL;
+
+  g_slice_free (MateMenuTreeEntry, entry);
+}
+
+static int
+matemenu_tree_entry_compare_by_id (MateMenuTreeItem *a,
+				MateMenuTreeItem *b)
+{
+  if (a->type == MATEMENU_TREE_ITEM_ALIAS)
+    a = MATEMENU_TREE_ALIAS (a)->aliased_item;
+
+  if (b->type == MATEMENU_TREE_ITEM_ALIAS)
+    b = MATEMENU_TREE_ALIAS (b)->aliased_item;
+
+  return strcmp (MATEMENU_TREE_ENTRY (a)->desktop_file_id,
+                 MATEMENU_TREE_ENTRY (b)->desktop_file_id);
+}
+
+/**
+ * matemenu_tree_item_ref:
+ * @item: a #MateMenuTreeItem
+ *
+ * Returns: (transfer full): The same @item, or %NULL if @item is not a valid #MateMenuTreeItem
+ */
+gpointer
+matemenu_tree_item_ref (gpointer itemp)
+{
+  MateMenuTreeItem* item = (MateMenuTreeItem*) itemp;
+  g_return_val_if_fail(item != NULL, NULL);
+  g_return_val_if_fail(item->refcount > 0, NULL);
+
+  g_atomic_int_inc (&item->refcount);
+
+  return item;
+}
+
+void
+matemenu_tree_item_unref (gpointer itemp)
+{
+  MateMenuTreeItem *item;
+
+  item = (MateMenuTreeItem *) itemp;
+
+  g_return_if_fail (item != NULL);
+  g_return_if_fail (item->refcount > 0);
+
+  if (g_atomic_int_dec_and_test (&(item->refcount)))
+    {
+      switch (item->type)
+	{
+	case MATEMENU_TREE_ITEM_DIRECTORY:
+	  matemenu_tree_directory_finalize (MATEMENU_TREE_DIRECTORY (item));
+	  break;
+
+	case MATEMENU_TREE_ITEM_ENTRY:
+	  matemenu_tree_entry_finalize (MATEMENU_TREE_ENTRY (item));
+	  break;
+
+	case MATEMENU_TREE_ITEM_SEPARATOR:
+	  matemenu_tree_separator_finalize (MATEMENU_TREE_SEPARATOR (item));
+	  break;
+
+	case MATEMENU_TREE_ITEM_HEADER:
+	  matemenu_tree_header_finalize (MATEMENU_TREE_HEADER (item));
+	  break;
+
+	case MATEMENU_TREE_ITEM_ALIAS:
+	  matemenu_tree_alias_finalize (MATEMENU_TREE_ALIAS (item));
+	  break;
+
+	default:
+	  g_assert_not_reached ();
+	  break;
+	}
+    }
+}
+
+static void
+matemenu_tree_item_unref_and_unset_parent (gpointer itemp)
+{
+  MateMenuTreeItem *item;
+
+  item = (MateMenuTreeItem *) itemp;
+
+  g_return_if_fail (item != NULL);
+
+  matemenu_tree_item_set_parent (item, NULL);
+  matemenu_tree_item_unref (item);
+}
+
+static inline const char *
+matemenu_tree_item_compare_get_name_helper (MateMenuTreeItem    *item,
+					 MateMenuTreeFlags    flags)
+{
+  const char *name;
+
+  name = NULL;
+
+  switch (item->type)
+    {
+    case MATEMENU_TREE_ITEM_DIRECTORY:
+      if (MATEMENU_TREE_DIRECTORY (item)->directory_entry)
+	name = desktop_entry_get_name (MATEMENU_TREE_DIRECTORY (item)->directory_entry);
+      else
+	name = MATEMENU_TREE_DIRECTORY (item)->name;
+      break;
+
+    case MATEMENU_TREE_ITEM_ENTRY:
+      if (flags & MATEMENU_TREE_FLAGS_SORT_DISPLAY_NAME)
+        name = g_app_info_get_display_name (G_APP_INFO (matemenu_tree_entry_get_app_info (MATEMENU_TREE_ENTRY (item))));
+      else
+        name = desktop_entry_get_name (MATEMENU_TREE_ENTRY (item)->desktop_entry);
+      break;
+
+    case MATEMENU_TREE_ITEM_ALIAS:
+      {
+        MateMenuTreeItem *dir;
+        dir = MATEMENU_TREE_ITEM (MATEMENU_TREE_ALIAS (item)->directory);
+        name = matemenu_tree_item_compare_get_name_helper (dir, flags);
+      }
+      break;
+
+    case MATEMENU_TREE_ITEM_SEPARATOR:
+    case MATEMENU_TREE_ITEM_HEADER:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  return name;
+}
+
+static int
+matemenu_tree_item_compare (MateMenuTreeItem  *a,
+                            MateMenuTreeItem  *b,
+                            MateMenuTreeFlags  flags)
+{
+  const char       *name_a;
+  const char       *name_b;
+
+  name_a = matemenu_tree_item_compare_get_name_helper (a, flags);
+  name_b = matemenu_tree_item_compare_get_name_helper (b, flags);
+
+  return g_utf8_collate (name_a, name_b);
+}
+
+static MenuLayoutNode *
+find_menu_child (MenuLayoutNode *layout)
+{
+  MenuLayoutNode *child;
+
+  child = menu_layout_node_get_children (layout);
+  while (child && menu_layout_node_get_type (child) != MENU_LAYOUT_NODE_MENU)
+    child = menu_layout_node_get_next (child);
+
+  return child;
+}
+
+static void
+merge_resolved_children (MateMenuTree      *tree,
+			 GHashTable     *loaded_menu_files,
+                         MenuLayoutNode *where,
+                         MenuLayoutNode *from)
+{
+  MenuLayoutNode *insert_after;
+  MenuLayoutNode *menu_child;
+  MenuLayoutNode *from_child;
+
+  matemenu_tree_resolve_files (tree, loaded_menu_files, from);
+
+  insert_after = where;
+  g_assert (menu_layout_node_get_type (insert_after) != MENU_LAYOUT_NODE_ROOT);
+  g_assert (menu_layout_node_get_parent (insert_after) != NULL);
+
+  /* skip root node */
+  menu_child = find_menu_child (from);
+  g_assert (menu_child != NULL);
+  g_assert (menu_layout_node_get_type (menu_child) == MENU_LAYOUT_NODE_MENU);
+
+  /* merge children of toplevel <Menu> */
+  from_child = menu_layout_node_get_children (menu_child);
+  while (from_child != NULL)
+    {
+      MenuLayoutNode *next;
+
+      next = menu_layout_node_get_next (from_child);
+
+      menu_verbose ("Merging ");
+      menu_debug_print_layout (from_child, FALSE);
+      menu_verbose (" after ");
+      menu_debug_print_layout (insert_after, FALSE);
+
+      switch (menu_layout_node_get_type (from_child))
+        {
+        case MENU_LAYOUT_NODE_NAME:
+          menu_layout_node_unlink (from_child); /* delete this */
+          break;
+
+        default:
+          menu_layout_node_steal (from_child);
+          menu_layout_node_insert_after (insert_after, from_child);
+          menu_layout_node_unref (from_child);
+
+          insert_after = from_child;
+          break;
+        }
+
+      from_child = next;
+    }
+}
+
+static gboolean
+load_merge_file (MateMenuTree      *tree,
+		 GHashTable     *loaded_menu_files,
+                 const char     *filename,
+                 gboolean        is_canonical,
+		 gboolean        add_monitor,
+                 MenuLayoutNode *where)
+{
+  MenuLayoutNode *to_merge;
+  const char     *canonical;
+  char           *freeme;
+  gboolean        retval;
+
+  freeme = NULL;
+  retval = FALSE;
+
+  if (!is_canonical)
+    {
+      canonical = freeme = realpath (filename, NULL);
+      if (canonical == NULL)
+        {
+	  if (add_monitor)
+	    matemenu_tree_add_menu_file_monitor (tree,
+					     filename,
+					     MENU_FILE_MONITOR_NONEXISTENT_FILE);
+
+          menu_verbose ("Failed to canonicalize merge file path \"%s\": %s\n",
+                        filename, g_strerror (errno));
+	  goto out;
+        }
+    }
+  else
+    {
+      canonical = filename;
+    }
+
+  if (g_hash_table_lookup (loaded_menu_files, canonical) != NULL)
+    {
+      g_warning ("Not loading \"%s\": recursive loop detected in .menu files",
+		 canonical);
+      retval = TRUE;
+      goto out;
+    }
+
+  menu_verbose ("Merging file \"%s\"\n", canonical);
+
+  to_merge = menu_layout_load (canonical, tree->non_prefixed_basename, NULL);
+  if (to_merge == NULL)
+    {
+      menu_verbose ("No menu for file \"%s\" found when merging\n",
+                    canonical);
+      goto out;
+    }
+
+  retval = TRUE;
+
+  g_hash_table_insert (loaded_menu_files, (char *) canonical, GUINT_TO_POINTER (TRUE));
+
+  if (add_monitor)
+    matemenu_tree_add_menu_file_monitor (tree,
+				      canonical,
+				      MENU_FILE_MONITOR_FILE);
+
+  merge_resolved_children (tree, loaded_menu_files, where, to_merge);
+
+  g_hash_table_remove (loaded_menu_files, canonical);
+
+  menu_layout_node_unref (to_merge);
+
+ out:
+  if (freeme)
+    g_free (freeme);
+
+  return retval;
+}
+
+static gboolean
+load_merge_file_with_config_dir (MateMenuTree      *tree,
+				 GHashTable     *loaded_menu_files,
+				 const char     *menu_file,
+				 const char     *config_dir,
+				 MenuLayoutNode *where)
+{
+  char     *merge_file;
+  gboolean  loaded;
+
+  loaded = FALSE;
+
+  merge_file = g_build_filename (config_dir, "menus", menu_file, NULL);
+
+  if (load_merge_file (tree, loaded_menu_files, merge_file, FALSE, TRUE, where))
+    loaded = TRUE;
+
+  g_free (merge_file);
+
+  return loaded;
+}
+
+static gboolean
+compare_basedir_to_config_dir (const char *canonical_basedir,
+			       const char *config_dir)
+{
+  char     *dirname;
+  char     *canonical_menus_dir;
+  gboolean  retval;
+
+  menu_verbose ("Checking to see if basedir '%s' is in '%s'\n",
+		canonical_basedir, config_dir);
+
+  dirname = g_build_filename (config_dir, "menus", NULL);
+
+  retval = FALSE;
+
+  canonical_menus_dir = realpath (dirname, NULL);
+  if (canonical_menus_dir != NULL &&
+      strcmp (canonical_basedir, canonical_menus_dir) == 0)
+    {
+      retval = TRUE;
+    }
+
+  g_free (canonical_menus_dir);
+  g_free (dirname);
+
+  return retval;
+}
+
+static gboolean
+load_parent_merge_file_from_basename (MateMenuTree      *tree,
+                                      GHashTable     *loaded_menu_files,
+			              MenuLayoutNode *layout,
+                                      const char     *menu_file,
+                                      const char     *canonical_basedir)
+{
+  gboolean            found_basedir;
+  const char * const *system_config_dirs;
+  int                 i;
+
+  /* We're not interested in menu files that are in directories which are not a
+   * parent of the base directory of this menu file */
+  found_basedir = compare_basedir_to_config_dir (canonical_basedir,
+						 g_get_user_config_dir ());
+
+  system_config_dirs = g_get_system_config_dirs ();
+
+  i = 0;
+  while (system_config_dirs[i] != NULL)
+    {
+      if (!found_basedir)
+	{
+	  found_basedir = compare_basedir_to_config_dir (canonical_basedir,
+							 system_config_dirs[i]);
+	}
+      else
+	{
+	  menu_verbose ("Looking for parent menu file '%s' in '%s'\n",
+			menu_file, system_config_dirs[i]);
+
+	  if (load_merge_file_with_config_dir (tree,
+					       loaded_menu_files,
+					       menu_file,
+					       system_config_dirs[i],
+					       layout))
+	    {
+	      break;
+	    }
+	}
+
+      ++i;
+    }
+
+  return system_config_dirs[i] != NULL;
+}
+
+static gboolean load_parent_merge_file(MateMenuTree* tree, GHashTable* loaded_menu_files, MenuLayoutNode* layout)
+{
+	MenuLayoutNode* root;
+	const char* basedir;
+	const char* menu_name;
+	char* canonical_basedir;
+	char* menu_file;
+	gboolean found;
+
+	root = menu_layout_node_get_root(layout);
+
+	basedir   = menu_layout_node_root_get_basedir(root);
+	menu_name = menu_layout_node_root_get_name(root);
+
+	canonical_basedir = realpath (basedir, NULL);
+
+	if (canonical_basedir == NULL)
+	{
+		menu_verbose("Menu basedir '%s' no longer exists, not merging parent\n", basedir);
+		return FALSE;
+	}
+
+	found = FALSE;
+	menu_file = g_strconcat(menu_name, ".menu", NULL);
+
+	if (strcmp(menu_file, "mate-applications.menu") == 0 && g_getenv("XDG_MENU_PREFIX"))
+	{
+		char* prefixed_basename;
+		prefixed_basename = g_strdup_printf("%s%s", g_getenv("XDG_MENU_PREFIX"), menu_file);
+		found = load_parent_merge_file_from_basename(tree, loaded_menu_files, layout, prefixed_basename, canonical_basedir);
+		g_free(prefixed_basename);
+	}
+
+	if (!found)
+	{
+		found = load_parent_merge_file_from_basename(tree, loaded_menu_files, layout, menu_file, canonical_basedir);
+	}
+
+	g_free(menu_file);
+	g_free(canonical_basedir);
+
+	return found;
+}
+
+static void
+load_merge_dir (MateMenuTree      *tree,
+		GHashTable     *loaded_menu_files,
+                const char     *dirname,
+                MenuLayoutNode *where)
+{
+  GDir       *dir;
+  const char *menu_file;
+
+  menu_verbose ("Loading merge dir \"%s\"\n", dirname);
+
+  matemenu_tree_add_menu_file_monitor (tree,
+				    dirname,
+				    MENU_FILE_MONITOR_DIRECTORY);
+
+  if ((dir = g_dir_open (dirname, 0, NULL)) == NULL)
+    return;
+
+  while ((menu_file = g_dir_read_name (dir)))
+    {
+      if (g_str_has_suffix (menu_file, ".menu"))
+        {
+          char *full_path;
+
+          full_path = g_build_filename (dirname, menu_file, NULL);
+
+          load_merge_file (tree, loaded_menu_files, full_path, TRUE, FALSE, where);
+
+          g_free (full_path);
+        }
+    }
+
+  g_dir_close (dir);
+}
+
+static void
+load_merge_dir_with_config_dir (MateMenuTree      *tree,
+				GHashTable     *loaded_menu_files,
+                                const char     *config_dir,
+                                const char     *dirname,
+                                MenuLayoutNode *where)
+{
+  char *path;
+
+  path = g_build_filename (config_dir, "menus", dirname, NULL);
+
+  load_merge_dir (tree, loaded_menu_files, path, where);
+
+  g_free (path);
+}
+
+static void
+resolve_merge_file (MateMenuTree      *tree,
+		    GHashTable     *loaded_menu_files,
+                    MenuLayoutNode *layout)
+{
+  char *filename;
+
+  if (menu_layout_node_merge_file_get_type (layout) == MENU_MERGE_FILE_TYPE_PARENT)
+    {
+      if (load_parent_merge_file (tree, loaded_menu_files, layout))
+        return;
+    }
+
+  filename = menu_layout_node_get_content_as_path (layout);
+  if (filename == NULL)
+    {
+      menu_verbose ("didn't get node content as a path, not merging file\n");
+    }
+  else
+    {
+      load_merge_file (tree, loaded_menu_files, filename, FALSE, TRUE, layout);
+
+      g_free (filename);
+    }
+
+  /* remove the now-replaced node */
+  menu_layout_node_unlink (layout);
+}
+
+static void
+resolve_merge_dir (MateMenuTree      *tree,
+		   GHashTable     *loaded_menu_files,
+                   MenuLayoutNode *layout)
+{
+  char *path;
+
+  path = menu_layout_node_get_content_as_path (layout);
+  if (path == NULL)
+    {
+      menu_verbose ("didn't get layout node content as a path, not merging dir\n");
+    }
+  else
+    {
+      load_merge_dir (tree, loaded_menu_files, path, layout);
+
+      g_free (path);
+    }
+
+  /* remove the now-replaced node */
+  menu_layout_node_unlink (layout);
+}
+
+static MenuLayoutNode *
+add_app_dir (MateMenuTree      *tree,
+             MenuLayoutNode *before,
+             const char     *data_dir)
+{
+  MenuLayoutNode *tmp;
+  char           *dirname;
+
+  tmp = menu_layout_node_new (MENU_LAYOUT_NODE_APP_DIR);
+  dirname = g_build_filename (data_dir, "applications", NULL);
+  menu_layout_node_set_content (tmp, dirname);
+  menu_layout_node_insert_before (before, tmp);
+  menu_layout_node_unref (before);
+
+  menu_verbose ("Adding <AppDir>%s</AppDir> in <DefaultAppDirs/>\n",
+                dirname);
+
+  g_free (dirname);
+
+  return tmp;
+}
+
+static void
+resolve_default_app_dirs (MateMenuTree      *tree,
+                          MenuLayoutNode *layout)
+{
+  MenuLayoutNode     *before;
+  const char * const *system_data_dirs;
+  int                 i;
+
+  system_data_dirs = g_get_system_data_dirs ();
+
+  before = add_app_dir (tree,
+			menu_layout_node_ref (layout),
+			g_get_user_data_dir ());
+
+  i = 0;
+  while (system_data_dirs[i] != NULL)
+    {
+      before = add_app_dir (tree, before, system_data_dirs[i]);
+
+      ++i;
+    }
+
+  menu_layout_node_unref (before);
+
+  /* remove the now-replaced node */
+  menu_layout_node_unlink (layout);
+}
+
+static MenuLayoutNode* add_directory_dir(MateMenuTree* tree, MenuLayoutNode* before, const char* data_dir)
+{
+	MenuLayoutNode* tmp;
+	char* dirname;
+
+	tmp = menu_layout_node_new(MENU_LAYOUT_NODE_DIRECTORY_DIR);
+	dirname = g_build_filename(data_dir, "desktop-directories", NULL);
+	menu_layout_node_set_content(tmp, dirname);
+	menu_layout_node_insert_before(before, tmp);
+	menu_layout_node_unref(before);
+
+	menu_verbose("Adding <DirectoryDir>%s</DirectoryDir> in <DefaultDirectoryDirs/>\n", dirname);
+
+	g_free(dirname);
+
+	return tmp;
+}
+
+/* According to desktop spec, since our menu file is called 'mate-applications', our
+ * merged menu folders need to be called 'mate-applications-merged'.  We'll setup the folder
+ * 'applications-merged' if it doesn't exist yet, and a symlink pointing to it in the
+ * ~/.config/menus directory
+ */
+static void
+setup_merge_dir_symlink(void)
+{
+    gchar *user_config = (gchar *) g_get_user_config_dir();
+    gchar *merge_path = g_build_filename (user_config, "menus", "applications-merged", NULL);
+    GFile *merge_file = g_file_new_for_path (merge_path);
+    gchar *sym_path;
+    GFile *sym_file;
+
+    g_file_make_directory_with_parents (merge_file, NULL, NULL);
+
+    sym_path = g_build_filename (user_config, "menus", "mate-applications-merged", NULL);
+    sym_file = g_file_new_for_path (sym_path);
+    if (!g_file_query_exists (sym_file, NULL)) {
+        g_file_make_symbolic_link (sym_file, merge_path, NULL, NULL);
+    }
+
+    g_free (merge_path);
+    g_free (sym_path);
+    g_object_unref (merge_file);
+    g_object_unref (sym_file);
+}
+
+static void
+resolve_default_directory_dirs (MateMenuTree      *tree,
+                                MenuLayoutNode *layout)
+{
+  MenuLayoutNode     *before;
+  const char * const *system_data_dirs;
+  int                 i;
+
+  system_data_dirs = g_get_system_data_dirs ();
+
+  before = add_directory_dir (tree,
+			      menu_layout_node_ref (layout),
+			      g_get_user_data_dir ());
+
+  i = 0;
+  while (system_data_dirs[i] != NULL)
+    {
+		/* Parche para tomar las carpetas /mate/ */
+		char* path = g_build_filename(system_data_dirs[i], "mate", NULL);
+		before = add_directory_dir(tree, before, path);
+		g_free(path);
+		/* /fin parche */
+      before = add_directory_dir (tree, before, system_data_dirs[i]);
+
+      ++i;
+    }
+
+  menu_layout_node_unref (before);
+
+  /* remove the now-replaced node */
+  menu_layout_node_unlink (layout);
+}
+
+static void
+resolve_default_merge_dirs (MateMenuTree      *tree,
+			    GHashTable     *loaded_menu_files,
+                            MenuLayoutNode *layout)
+{
+  MenuLayoutNode     *root;
+  const char         *menu_name;
+  char               *merge_name;
+  const char * const *system_config_dirs;
+  int                 i;
+
+  setup_merge_dir_symlink();
+
+  root = menu_layout_node_get_root (layout);
+  menu_name = menu_layout_node_root_get_name (root);
+
+  merge_name = g_strconcat (menu_name, "-merged", NULL);
+
+  system_config_dirs = g_get_system_config_dirs ();
+
+  /* Merge in reverse order */
+  i = 0;
+  while (system_config_dirs[i] != NULL) i++;
+  while (i > 0)
+    {
+      i--;
+      load_merge_dir_with_config_dir (tree,
+				      loaded_menu_files,
+                                      system_config_dirs[i],
+                                      merge_name,
+                                      layout);
+    }
+
+  load_merge_dir_with_config_dir (tree,
+				  loaded_menu_files,
+                                  g_get_user_config_dir (),
+                                  merge_name,
+                                  layout);
+
+  g_free (merge_name);
+
+  /* remove the now-replaced node */
+  menu_layout_node_unlink (layout);
+}
+
+static void
+add_filename_include (const char     *desktop_file_id,
+                      DesktopEntry   *entry,
+                      MenuLayoutNode *include)
+{
+  if (!desktop_entry_has_categories (entry))
+    {
+      MenuLayoutNode *node;
+
+      node = menu_layout_node_new (MENU_LAYOUT_NODE_FILENAME);
+      menu_layout_node_set_content (node, desktop_file_id);
+
+      menu_layout_node_append_child (include, node);
+      menu_layout_node_unref (node);
+    }
+}
+
+static void
+is_dot_directory (const char   *basename,
+		  DesktopEntry *entry,
+		  gboolean     *has_dot_directory)
+{
+  if (!strcmp (basename, ".directory"))
+    *has_dot_directory = TRUE;
+}
+
+static gboolean
+add_menu_for_legacy_dir (MenuLayoutNode *parent,
+                         const char     *legacy_dir,
+                	 const char     *relative_path,
+                         const char     *legacy_prefix,
+                         const char     *menu_name)
+{
+  EntryDirectory  *ed;
+  DesktopEntrySet *desktop_entries;
+  DesktopEntrySet *directory_entries;
+  GSList          *subdirs;
+  gboolean         menu_added;
+  gboolean         has_dot_directory;
+
+  ed = entry_directory_new_legacy (DESKTOP_ENTRY_INVALID, legacy_dir, legacy_prefix);
+  if (!ed)
+    return FALSE;
+
+  subdirs = NULL;
+  desktop_entries   = desktop_entry_set_new ();
+  directory_entries = desktop_entry_set_new ();
+
+  entry_directory_get_flat_contents (ed,
+                                     desktop_entries,
+                                     directory_entries,
+                                     &subdirs);
+  entry_directory_unref (ed);
+
+  has_dot_directory = FALSE;
+  desktop_entry_set_foreach (directory_entries,
+			     (DesktopEntrySetForeachFunc) is_dot_directory,
+			     &has_dot_directory);
+  desktop_entry_set_unref (directory_entries);
+
+  menu_added = FALSE;
+  if (desktop_entry_set_get_count (desktop_entries) > 0 || subdirs)
+    {
+      MenuLayoutNode *menu;
+      MenuLayoutNode *node;
+      GString        *subdir_path;
+      GString        *subdir_relative;
+      GSList         *tmp;
+      size_t          legacy_dir_len;
+      size_t          relative_path_len;
+
+      menu = menu_layout_node_new (MENU_LAYOUT_NODE_MENU);
+      menu_layout_node_append_child (parent, menu);
+
+      menu_added = TRUE;
+
+      g_assert (menu_name != NULL);
+
+      node = menu_layout_node_new (MENU_LAYOUT_NODE_NAME);
+      menu_layout_node_set_content (node, menu_name);
+      menu_layout_node_append_child (menu, node);
+      menu_layout_node_unref (node);
+
+      if (has_dot_directory)
+	{
+	  node = menu_layout_node_new (MENU_LAYOUT_NODE_DIRECTORY);
+	  if (relative_path != NULL)
+	    {
+	      char *directory_entry_path;
+
+	      directory_entry_path = g_strdup_printf ("%s/.directory", relative_path);
+	      menu_layout_node_set_content (node, directory_entry_path);
+	      g_free (directory_entry_path);
+	    }
+	  else
+	    {
+	      menu_layout_node_set_content (node, ".directory");
+	    }
+	  menu_layout_node_append_child (menu, node);
+	  menu_layout_node_unref (node);
+	}
+
+      if (desktop_entry_set_get_count (desktop_entries) > 0)
+	{
+	  MenuLayoutNode *include;
+
+	  include = menu_layout_node_new (MENU_LAYOUT_NODE_INCLUDE);
+	  menu_layout_node_append_child (menu, include);
+
+	  desktop_entry_set_foreach (desktop_entries,
+				     (DesktopEntrySetForeachFunc) add_filename_include,
+				     include);
+
+	  menu_layout_node_unref (include);
+	}
+
+      subdir_path = g_string_new (legacy_dir);
+      legacy_dir_len = strlen (legacy_dir);
+
+      subdir_relative = g_string_new (relative_path);
+      relative_path_len = relative_path ? strlen (relative_path) : 0;
+
+      tmp = subdirs;
+      while (tmp != NULL)
+        {
+          const char *subdir = tmp->data;
+
+          g_string_append_c (subdir_path, G_DIR_SEPARATOR);
+          g_string_append (subdir_path, subdir);
+
+	  if (relative_path_len)
+	    {
+	      g_string_append_c (subdir_relative, G_DIR_SEPARATOR);
+	    }
+          g_string_append (subdir_relative, subdir);
+
+          add_menu_for_legacy_dir (menu,
+                                   subdir_path->str,
+				   subdir_relative->str,
+                                   legacy_prefix,
+                                   subdir);
+
+          g_string_truncate (subdir_relative, relative_path_len);
+          g_string_truncate (subdir_path, legacy_dir_len);
+
+          tmp = tmp->next;
+        }
+
+      g_string_free (subdir_path, TRUE);
+      g_string_free (subdir_relative, TRUE);
+
+      menu_layout_node_unref (menu);
+    }
+
+  desktop_entry_set_unref (desktop_entries);
+
+  g_slist_free_full (subdirs, (GDestroyNotify) g_free);
+
+  return menu_added;
+}
+
+static void
+resolve_legacy_dir (MateMenuTree      *tree,
+		    GHashTable     *loaded_menu_files,
+                    MenuLayoutNode *legacy)
+{
+  MenuLayoutNode *to_merge;
+  MenuLayoutNode *menu;
+
+  to_merge = menu_layout_node_new (MENU_LAYOUT_NODE_ROOT);
+
+  menu = menu_layout_node_get_parent (legacy);
+  g_assert (menu_layout_node_get_type (menu) == MENU_LAYOUT_NODE_MENU);
+
+  if (add_menu_for_legacy_dir (to_merge,
+                               menu_layout_node_get_content (legacy),
+			       NULL,
+                               menu_layout_node_legacy_dir_get_prefix (legacy),
+                               menu_layout_node_menu_get_name (menu)))
+    {
+      merge_resolved_children (tree, loaded_menu_files, legacy, to_merge);
+    }
+
+  menu_layout_node_unref (to_merge);
+}
+
+static MenuLayoutNode *
+add_legacy_dir (MateMenuTree      *tree,
+		GHashTable     *loaded_menu_files,
+                MenuLayoutNode *before,
+                const char     *data_dir)
+{
+  MenuLayoutNode *legacy;
+  char           *dirname;
+
+  dirname = g_build_filename (data_dir, "applnk", NULL);
+
+  legacy = menu_layout_node_new (MENU_LAYOUT_NODE_LEGACY_DIR);
+  menu_layout_node_set_content (legacy, dirname);
+  menu_layout_node_legacy_dir_set_prefix (legacy, "kde");
+  menu_layout_node_insert_before (before, legacy);
+  menu_layout_node_unref (before);
+
+  menu_verbose ("Adding <LegacyDir>%s</LegacyDir> in <KDELegacyDirs/>\n",
+                dirname);
+
+  resolve_legacy_dir (tree, loaded_menu_files, legacy);
+
+  g_free (dirname);
+
+  return legacy;
+}
+
+static void
+resolve_kde_legacy_dirs (MateMenuTree      *tree,
+			 GHashTable     *loaded_menu_files,
+                         MenuLayoutNode *layout)
+{
+  MenuLayoutNode     *before;
+  const char * const *system_data_dirs;
+  int                 i;
+
+  system_data_dirs = g_get_system_data_dirs ();
+
+  before = add_legacy_dir (tree,
+			   loaded_menu_files,
+			   menu_layout_node_ref (layout),
+			   g_get_user_data_dir ());
+
+  i = 0;
+  while (system_data_dirs[i] != NULL)
+    {
+      before = add_legacy_dir (tree, loaded_menu_files, before, system_data_dirs[i]);
+
+      ++i;
+    }
+
+  menu_layout_node_unref (before);
+
+  /* remove the now-replaced node */
+  menu_layout_node_unlink (layout);
+}
+
+static void
+matemenu_tree_resolve_files (MateMenuTree      *tree,
+			  GHashTable     *loaded_menu_files,
+			  MenuLayoutNode *layout)
+{
+  MenuLayoutNode *child;
+
+  menu_verbose ("Resolving files in: ");
+  menu_debug_print_layout (layout, TRUE);
+
+  switch (menu_layout_node_get_type (layout))
+    {
+    case MENU_LAYOUT_NODE_MERGE_FILE:
+      resolve_merge_file (tree, loaded_menu_files, layout);
+      break;
+
+    case MENU_LAYOUT_NODE_MERGE_DIR:
+      resolve_merge_dir (tree, loaded_menu_files, layout);
+      break;
+
+    case MENU_LAYOUT_NODE_DEFAULT_APP_DIRS:
+      resolve_default_app_dirs (tree, layout);
+      break;
+
+    case MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS:
+      resolve_default_directory_dirs (tree, layout);
+      break;
+
+    case MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS:
+      resolve_default_merge_dirs (tree, loaded_menu_files, layout);
+      break;
+
+    case MENU_LAYOUT_NODE_LEGACY_DIR:
+      resolve_legacy_dir (tree, loaded_menu_files, layout);
+      break;
+
+    case MENU_LAYOUT_NODE_KDE_LEGACY_DIRS:
+      resolve_kde_legacy_dirs (tree, loaded_menu_files, layout);
+      break;
+
+    case MENU_LAYOUT_NODE_PASSTHROUGH:
+      /* Just get rid of these, we don't need the memory usage */
+      menu_layout_node_unlink (layout);
+      break;
+
+    default:
+      /* Recurse */
+      child = menu_layout_node_get_children (layout);
+      while (child != NULL)
+        {
+          MenuLayoutNode *next = menu_layout_node_get_next (child);
+
+          matemenu_tree_resolve_files (tree, loaded_menu_files, child);
+
+          child = next;
+        }
+      break;
+    }
+}
+
+static void
+move_children (MenuLayoutNode *from,
+               MenuLayoutNode *to)
+{
+  MenuLayoutNode *from_child;
+  MenuLayoutNode *insert_before;
+
+  insert_before = menu_layout_node_get_children (to);
+  from_child    = menu_layout_node_get_children (from);
+
+  while (from_child != NULL)
+    {
+      MenuLayoutNode *next;
+
+      next = menu_layout_node_get_next (from_child);
+
+      menu_layout_node_steal (from_child);
+
+      if (menu_layout_node_get_type (from_child) == MENU_LAYOUT_NODE_NAME)
+        {
+          ; /* just drop the Name in the old <Menu> */
+        }
+      else if (insert_before)
+        {
+          menu_layout_node_insert_before (insert_before, from_child);
+          g_assert (menu_layout_node_get_next (from_child) == insert_before);
+        }
+      else
+        {
+          menu_layout_node_append_child (to, from_child);
+        }
+
+      menu_layout_node_unref (from_child);
+
+      from_child = next;
+    }
+}
+
+static int
+null_safe_strcmp (const char *a,
+                  const char *b)
+{
+  if (a == NULL && b == NULL)
+    return 0;
+  else if (a == NULL)
+    return -1;
+  else if (b == NULL)
+    return 1;
+  else
+    return strcmp (a, b);
+}
+
+static int
+node_compare_func (const void *a,
+                   const void *b)
+{
+  MenuLayoutNode *node_a = (MenuLayoutNode*) a;
+  MenuLayoutNode *node_b = (MenuLayoutNode*) b;
+  MenuLayoutNodeType t_a = menu_layout_node_get_type (node_a);
+  MenuLayoutNodeType t_b = menu_layout_node_get_type (node_b);
+
+  if (t_a < t_b)
+    return -1;
+  else if (t_a > t_b)
+    return 1;
+  else
+    {
+      const char *c_a = menu_layout_node_get_content (node_a);
+      const char *c_b = menu_layout_node_get_content (node_b);
+
+      return null_safe_strcmp (c_a, c_b);
+    }
+}
+
+static int
+node_menu_compare_func (const void *a,
+                        const void *b)
+{
+  MenuLayoutNode *node_a = (MenuLayoutNode*) a;
+  MenuLayoutNode *node_b = (MenuLayoutNode*) b;
+  MenuLayoutNode *parent_a = menu_layout_node_get_parent (node_a);
+  MenuLayoutNode *parent_b = menu_layout_node_get_parent (node_b);
+
+  if (parent_a < parent_b)
+    return -1;
+  else if (parent_a > parent_b)
+    return 1;
+  else
+    return null_safe_strcmp (menu_layout_node_menu_get_name (node_a),
+                             menu_layout_node_menu_get_name (node_b));
+}
+
+static void
+matemenu_tree_strip_duplicate_children (MateMenuTree      *tree,
+				     MenuLayoutNode *layout)
+{
+  MenuLayoutNode *child;
+  GSList         *simple_nodes;
+  GSList         *menu_layout_nodes;
+  GSList         *prev;
+  GSList         *tmp;
+
+  /* to strip dups, we find all the child nodes where
+   * we want to kill dups, sort them,
+   * then nuke the adjacent nodes that are equal
+   */
+
+  simple_nodes = NULL;
+  menu_layout_nodes = NULL;
+
+  child = menu_layout_node_get_children (layout);
+  while (child != NULL)
+    {
+      switch (menu_layout_node_get_type (child))
+        {
+          /* These are dups if their content is the same */
+        case MENU_LAYOUT_NODE_APP_DIR:
+        case MENU_LAYOUT_NODE_DIRECTORY_DIR:
+        case MENU_LAYOUT_NODE_DIRECTORY:
+          simple_nodes = g_slist_prepend (simple_nodes, child);
+          break;
+
+          /* These have to be merged in a more complicated way,
+           * and then recursed
+           */
+        case MENU_LAYOUT_NODE_MENU:
+          menu_layout_nodes = g_slist_prepend (menu_layout_nodes, child);
+          break;
+
+        default:
+          break;
+        }
+
+      child = menu_layout_node_get_next (child);
+    }
+
+  /* Note that the lists are all backward. So we want to keep
+   * the items that are earlier in the list, because they were
+   * later in the file
+   */
+
+  /* stable sort the simple nodes */
+  simple_nodes = g_slist_sort (simple_nodes,
+                               node_compare_func);
+
+  prev = NULL;
+  tmp = simple_nodes;
+  while (tmp != NULL)
+    {
+      GSList *next = tmp->next;
+
+      if (prev)
+        {
+          MenuLayoutNode *p = prev->data;
+          MenuLayoutNode *n = tmp->data;
+
+          if (node_compare_func (p, n) == 0)
+            {
+              /* nuke it! */
+              menu_layout_node_unlink (n);
+	      simple_nodes = g_slist_delete_link (simple_nodes, tmp);
+	      tmp = prev;
+            }
+        }
+
+      prev = tmp;
+      tmp = next;
+    }
+
+  g_slist_free (simple_nodes);
+  simple_nodes = NULL;
+
+  /* stable sort the menu nodes (the sort includes the
+   * parents of the nodes in the comparison). Remember
+   * the list is backward.
+   */
+  menu_layout_nodes = g_slist_sort (menu_layout_nodes,
+				    node_menu_compare_func);
+
+  prev = NULL;
+  tmp = menu_layout_nodes;
+  while (tmp != NULL)
+    {
+      GSList *next = tmp->next;
+
+      if (prev)
+        {
+          MenuLayoutNode *p = prev->data;
+          MenuLayoutNode *n = tmp->data;
+
+          if (node_menu_compare_func (p, n) == 0)
+            {
+              /* Move children of first menu to the start of second
+               * menu and nuke the first menu
+               */
+              move_children (n, p);
+              menu_layout_node_unlink (n);
+	      menu_layout_nodes = g_slist_delete_link (menu_layout_nodes, tmp);
+	      tmp = prev;
+            }
+        }
+
+      prev = tmp;
+      tmp = next;
+    }
+
+  g_slist_free (menu_layout_nodes);
+  menu_layout_nodes = NULL;
+
+  /* Recursively clean up all children */
+  child = menu_layout_node_get_children (layout);
+  while (child != NULL)
+    {
+      if (menu_layout_node_get_type (child) == MENU_LAYOUT_NODE_MENU)
+        matemenu_tree_strip_duplicate_children (tree, child);
+
+      child = menu_layout_node_get_next (child);
+    }
+}
+
+static MenuLayoutNode *
+find_submenu (MenuLayoutNode *layout,
+              const char     *path,
+              gboolean        create_if_not_found)
+{
+  MenuLayoutNode *child;
+  const char     *slash;
+  const char     *next_path;
+  char           *name;
+
+  menu_verbose (" (splitting \"%s\")\n", path);
+
+  if (path[0] == '\0' || path[0] == G_DIR_SEPARATOR)
+    return NULL;
+
+  slash = strchr (path, G_DIR_SEPARATOR);
+  if (slash != NULL)
+    {
+      name = g_strndup (path, (gsize)(slash - path));
+      next_path = slash + 1;
+      if (*next_path == '\0')
+        next_path = NULL;
+    }
+  else
+    {
+      name = g_strdup (path);
+      next_path = NULL;
+    }
+
+  child = menu_layout_node_get_children (layout);
+  while (child != NULL)
+    {
+      switch (menu_layout_node_get_type (child))
+        {
+        case MENU_LAYOUT_NODE_MENU:
+          {
+            if (strcmp (name, menu_layout_node_menu_get_name (child)) == 0)
+              {
+                menu_verbose ("MenuNode %p found for path component \"%s\"\n",
+                              child, name);
+
+                g_free (name);
+
+                if (!next_path)
+                  {
+                    menu_verbose (" Found menu node %p parent is %p\n",
+                                  child, layout);
+                    return child;
+                  }
+
+                return find_submenu (child, next_path, create_if_not_found);
+              }
+          }
+          break;
+
+        default:
+          break;
+        }
+
+      child = menu_layout_node_get_next (child);
+    }
+
+  if (create_if_not_found)
+    {
+      MenuLayoutNode *name_node;
+
+      child = menu_layout_node_new (MENU_LAYOUT_NODE_MENU);
+      menu_layout_node_append_child (layout, child);
+
+      name_node = menu_layout_node_new (MENU_LAYOUT_NODE_NAME);
+      menu_layout_node_set_content (name_node, name);
+      menu_layout_node_append_child (child, name_node);
+      menu_layout_node_unref (name_node);
+
+      menu_verbose (" Created menu node %p parent is %p\n",
+                    child, layout);
+
+      menu_layout_node_unref (child);
+      g_free (name);
+
+      if (!next_path)
+        return child;
+
+      return find_submenu (child, next_path, create_if_not_found);
+    }
+  else
+    {
+      g_free (name);
+      return NULL;
+    }
+}
+
+/* To call this you first have to strip duplicate children once,
+ * otherwise when you move a menu Foo to Bar then you may only
+ * move one of Foo, not all the merged Foo.
+ */
+static void
+matemenu_tree_execute_moves (MateMenuTree      *tree,
+			  MenuLayoutNode *layout,
+			  gboolean       *need_remove_dups_p)
+{
+  MenuLayoutNode *child;
+  gboolean        need_remove_dups;
+  GSList         *move_nodes;
+  GSList         *tmp;
+
+  need_remove_dups = FALSE;
+
+  move_nodes = NULL;
+
+  child = menu_layout_node_get_children (layout);
+  while (child != NULL)
+    {
+      switch (menu_layout_node_get_type (child))
+        {
+        case MENU_LAYOUT_NODE_MENU:
+          /* Recurse - we recurse first and process the current node
+           * second, as the spec dictates.
+           */
+          matemenu_tree_execute_moves (tree, child, &need_remove_dups);
+          break;
+
+        case MENU_LAYOUT_NODE_MOVE:
+          move_nodes = g_slist_prepend (move_nodes, child);
+          break;
+
+        default:
+          break;
+        }
+
+      child = menu_layout_node_get_next (child);
+    }
+
+  /* We need to execute the move operations in the order that they appear */
+  move_nodes = g_slist_reverse (move_nodes);
+
+  tmp = move_nodes;
+  while (tmp != NULL)
+    {
+      MenuLayoutNode *move_node = tmp->data;
+      MenuLayoutNode *old_node;
+      GSList         *next = tmp->next;
+      const char     *old;
+      const char     *new;
+
+      old = menu_layout_node_move_get_old (move_node);
+      new = menu_layout_node_move_get_new (move_node);
+      g_assert (old != NULL && new != NULL);
+
+      menu_verbose ("executing <Move> old = \"%s\" new = \"%s\"\n",
+                    old, new);
+
+      old_node = find_submenu (layout, old, FALSE);
+      if (old_node != NULL)
+        {
+          MenuLayoutNode *new_node;
+
+          /* here we can create duplicates anywhere below the
+           * node
+           */
+          need_remove_dups = TRUE;
+
+          /* look up new node creating it and its parents if
+           * required
+           */
+          new_node = find_submenu (layout, new, TRUE);
+          g_assert (new_node != NULL);
+
+          move_children (old_node, new_node);
+
+          menu_layout_node_unlink (old_node);
+        }
+
+      menu_layout_node_unlink (move_node);
+
+      tmp = next;
+    }
+
+  g_slist_free (move_nodes);
+
+  /* This oddness is to ensure we only remove dups once,
+   * at the root, instead of recursing the tree over
+   * and over.
+   */
+  if (need_remove_dups_p)
+    *need_remove_dups_p = need_remove_dups;
+  else if (need_remove_dups)
+    matemenu_tree_strip_duplicate_children (tree, layout);
+}
+
+static gboolean
+matemenu_tree_load_layout (MateMenuTree  *tree,
+                        GError    **error)
+{
+  GHashTable *loaded_menu_files;
+
+  if (tree->layout)
+    return TRUE;
+
+  if (!matemenu_tree_canonicalize_path (tree, error))
+    return FALSE;
+
+  menu_verbose ("Loading menu layout from \"%s\"\n",
+                tree->canonical_path);
+
+  tree->layout = menu_layout_load (tree->canonical_path,
+                                   tree->non_prefixed_basename,
+                                   error);
+  if (!tree->layout)
+    return FALSE;
+
+  loaded_menu_files = g_hash_table_new (g_str_hash, g_str_equal);
+  g_hash_table_insert (loaded_menu_files, tree->canonical_path, GUINT_TO_POINTER (TRUE));
+  matemenu_tree_resolve_files (tree, loaded_menu_files, tree->layout);
+  g_hash_table_destroy (loaded_menu_files);
+
+  matemenu_tree_strip_duplicate_children (tree, tree->layout);
+  matemenu_tree_execute_moves (tree, tree->layout, NULL);
+
+  return TRUE;
+}
+
+static void
+matemenu_tree_force_reload (MateMenuTree *tree)
+{
+  matemenu_tree_force_rebuild (tree);
+
+  if (tree->layout)
+    menu_layout_node_unref (tree->layout);
+  tree->layout = NULL;
+}
+
+typedef struct
+{
+  DesktopEntrySet *set;
+  const char      *category;
+} GetByCategoryForeachData;
+
+static void
+get_by_category_foreach (const char               *file_id,
+			 DesktopEntry             *entry,
+			 GetByCategoryForeachData *data)
+{
+  if (desktop_entry_has_category (entry, data->category))
+    desktop_entry_set_add_entry (data->set, entry, file_id);
+}
+
+#ifdef WITH_COLLECTION
+static void
+get_by_desktop_foreach (const char               *file_id,
+                        DesktopEntry             *entry,
+                        GetByCategoryForeachData *data)
+{
+  if (g_strcmp0 (file_id, data->category) == 0)
+    desktop_entry_set_add_entry (data->set, entry, file_id);
+}
+#endif /* WITH_COLLECTION */
+
+static void
+get_by_category (DesktopEntrySet *entry_pool,
+		 DesktopEntrySet *set,
+		 const char      *category)
+{
+  GetByCategoryForeachData data;
+
+  data.set      = set;
+  data.category = category;
+
+  desktop_entry_set_foreach (entry_pool,
+                             (DesktopEntrySetForeachFunc) get_by_category_foreach,
+                             &data);
+}
+
+#ifdef WITH_COLLECTION
+static void
+get_by_desktop (DesktopEntrySet *entry_pool,
+                DesktopEntrySet *set,
+                const char      *desktop_name)
+{
+  GetByCategoryForeachData data;
+
+  data.set      = set;
+  data.category = desktop_name;
+
+  desktop_entry_set_foreach (entry_pool,
+                             (DesktopEntrySetForeachFunc) get_by_desktop_foreach,
+                             &data);
+}
+#endif /* WITH_COLLECTION */
+
+static DesktopEntrySet *
+process_include_rules (MenuLayoutNode  *layout,
+		       DesktopEntrySet *entry_pool)
+{
+  DesktopEntrySet *set = NULL;
+
+  switch (menu_layout_node_get_type (layout))
+    {
+    case MENU_LAYOUT_NODE_AND:
+      {
+        MenuLayoutNode *child;
+
+	menu_verbose ("Processing <And>\n");
+
+        child = menu_layout_node_get_children (layout);
+        while (child != NULL)
+          {
+            DesktopEntrySet *child_set;
+
+            child_set = process_include_rules (child, entry_pool);
+
+            if (set == NULL)
+              {
+                set = child_set;
+              }
+            else
+              {
+                desktop_entry_set_intersection (set, child_set);
+                desktop_entry_set_unref (child_set);
+              }
+
+            /* as soon as we get empty results, we can bail,
+             * because it's an AND
+             */
+            if (desktop_entry_set_get_count (set) == 0)
+              break;
+
+            child = menu_layout_node_get_next (child);
+          }
+	menu_verbose ("Processed <And>\n");
+      }
+      break;
+
+    case MENU_LAYOUT_NODE_OR:
+      {
+        MenuLayoutNode *child;
+
+	menu_verbose ("Processing <Or>\n");
+
+        child = menu_layout_node_get_children (layout);
+        while (child != NULL)
+          {
+            DesktopEntrySet *child_set;
+
+            child_set = process_include_rules (child, entry_pool);
+
+            if (set == NULL)
+              {
+                set = child_set;
+              }
+            else
+              {
+                desktop_entry_set_union (set, child_set);
+                desktop_entry_set_unref (child_set);
+              }
+
+            child = menu_layout_node_get_next (child);
+          }
+	menu_verbose ("Processed <Or>\n");
+      }
+      break;
+
+    case MENU_LAYOUT_NODE_NOT:
+      {
+        /* First get the OR of all the rules */
+        MenuLayoutNode *child;
+
+	menu_verbose ("Processing <Not>\n");
+
+        child = menu_layout_node_get_children (layout);
+        while (child != NULL)
+          {
+            DesktopEntrySet *child_set;
+
+            child_set = process_include_rules (child, entry_pool);
+
+            if (set == NULL)
+              {
+                set = child_set;
+              }
+            else
+              {
+                desktop_entry_set_union (set, child_set);
+                desktop_entry_set_unref (child_set);
+              }
+
+            child = menu_layout_node_get_next (child);
+          }
+
+        if (set != NULL)
+          {
+	    DesktopEntrySet *inverted;
+
+	    /* Now invert the result */
+	    inverted = desktop_entry_set_new ();
+	    desktop_entry_set_union (inverted, entry_pool);
+	    desktop_entry_set_subtract (inverted, set);
+	    desktop_entry_set_unref (set);
+	    set = inverted;
+          }
+	menu_verbose ("Processed <Not>\n");
+      }
+      break;
+
+    case MENU_LAYOUT_NODE_ALL:
+      menu_verbose ("Processing <All>\n");
+      set = desktop_entry_set_new ();
+      desktop_entry_set_union (set, entry_pool);
+      menu_verbose ("Processed <All>\n");
+      break;
+
+    case MENU_LAYOUT_NODE_FILENAME:
+      {
+        DesktopEntry *entry;
+
+	menu_verbose ("Processing <Filename>%s</Filename>\n",
+		      menu_layout_node_get_content (layout));
+
+        entry = desktop_entry_set_lookup (entry_pool,
+					  menu_layout_node_get_content (layout));
+        if (entry != NULL)
+          {
+            set = desktop_entry_set_new ();
+            desktop_entry_set_add_entry (set,
+                                         entry,
+                                         menu_layout_node_get_content (layout));
+          }
+	menu_verbose ("Processed <Filename>%s</Filename>\n",
+		      menu_layout_node_get_content (layout));
+      }
+      break;
+
+    case MENU_LAYOUT_NODE_CATEGORY:
+      menu_verbose ("Processing <Category>%s</Category>\n",
+		    menu_layout_node_get_content (layout));
+      set = desktop_entry_set_new ();
+      get_by_category (entry_pool, set, menu_layout_node_get_content (layout));
+      menu_verbose ("Processed <Category>%s</Category>\n",
+		    menu_layout_node_get_content (layout));
+      break;
+
+    default:
+      break;
+    }
+
+  if (set == NULL)
+    set = desktop_entry_set_new (); /* create an empty set */
+
+  menu_verbose ("Matched %u entries\n", desktop_entry_set_get_count (set));
+
+  return set;
+}
+
+static void
+collect_layout_info (MenuLayoutNode  *layout,
+		     GSList         **layout_info)
+{
+  MenuLayoutNode *iter;
+
+  g_slist_foreach (*layout_info,
+		   (GFunc) menu_layout_node_unref,
+		   NULL);
+  g_slist_free (*layout_info);
+  *layout_info = NULL;
+
+  iter = menu_layout_node_get_children (layout);
+  while (iter != NULL)
+    {
+      switch (menu_layout_node_get_type (iter))
+	{
+	case MENU_LAYOUT_NODE_MENUNAME:
+	case MENU_LAYOUT_NODE_FILENAME:
+	case MENU_LAYOUT_NODE_SEPARATOR:
+	case MENU_LAYOUT_NODE_MERGE:
+	  *layout_info = g_slist_prepend (*layout_info,
+					  menu_layout_node_ref (iter));
+	  break;
+
+	default:
+	  break;
+	}
+
+      iter = menu_layout_node_get_next (iter);
+    }
+
+  *layout_info = g_slist_reverse (*layout_info);
+}
+
+static void
+entries_listify_foreach (const char         *desktop_file_id,
+                         DesktopEntry       *desktop_entry,
+                         MateMenuTreeDirectory *directory)
+{
+  directory->entries =
+    g_slist_prepend (directory->entries,
+		     matemenu_tree_entry_new (directory,
+                                           desktop_entry,
+                                           desktop_file_id,
+                                           FALSE,
+                                           FALSE));
+}
+
+static void
+excluded_entries_listify_foreach (const char         *desktop_file_id,
+				  DesktopEntry       *desktop_entry,
+				  MateMenuTreeDirectory *directory)
+{
+  directory->entries =
+    g_slist_prepend (directory->entries,
+		     matemenu_tree_entry_new (directory,
+					   desktop_entry,
+					   desktop_file_id,
+					   TRUE,
+                                           FALSE));
+}
+
+static void
+unallocated_entries_listify_foreach (const char         *desktop_file_id,
+                                     DesktopEntry       *desktop_entry,
+                                     MateMenuTreeDirectory *directory)
+{
+  directory->entries =
+    g_slist_prepend (directory->entries,
+		     matemenu_tree_entry_new (directory,
+                                           desktop_entry,
+                                           desktop_file_id,
+                                           FALSE,
+                                           TRUE));
+}
+
+static void
+set_default_layout_values (MateMenuTreeDirectory *parent,<--- Parameter 'parent' can be declared as pointer to const
+                           MateMenuTreeDirectory *child)
+{
+  GSList *tmp;
+
+  /* if the child has a defined default layout, we don't want to override its
+   * values. The parent might have a non-defined layout info (ie, no child of
+   * the DefaultLayout node) but it doesn't meant the default layout values
+   * (ie, DefaultLayout attributes) aren't different from the global defaults.
+   */
+  if (child->default_layout_info != NULL ||
+      child->default_layout_values.mask != MENU_LAYOUT_VALUES_NONE)
+    return;
+
+  child->default_layout_values = parent->default_layout_values;
+
+  tmp = child->subdirs;
+  while (tmp != NULL)
+    {
+      MateMenuTreeDirectory *subdir = tmp->data;
+
+      set_default_layout_values (child, subdir);
+
+      tmp = tmp->next;
+   }
+}
+
+static MateMenuTreeDirectory *
+process_layout (MateMenuTree          *tree,
+                MateMenuTreeDirectory *parent,
+                MenuLayoutNode     *layout,
+                DesktopEntrySet    *allocated)
+{
+  MenuLayoutNode     *layout_iter;
+  MateMenuTreeDirectory *directory;
+  DesktopEntrySet    *entry_pool;
+  DesktopEntrySet    *entries;
+  DesktopEntrySet    *allocated_set;
+  DesktopEntrySet    *excluded_set;
+  gboolean            deleted;
+  gboolean            only_unallocated;
+  GSList             *tmp;
+
+  g_assert (menu_layout_node_get_type (layout) == MENU_LAYOUT_NODE_MENU);
+  g_assert (menu_layout_node_menu_get_name (layout) != NULL);
+
+  directory = matemenu_tree_directory_new (tree, parent,
+					menu_layout_node_menu_get_name (layout));
+
+  menu_verbose ("=== Menu name = %s ===\n", directory->name);
+
+  deleted = FALSE;
+  only_unallocated = FALSE;
+
+  entries = desktop_entry_set_new ();
+  allocated_set = desktop_entry_set_new ();
+
+  if (tree->flags & MATEMENU_TREE_FLAGS_INCLUDE_EXCLUDED)
+    excluded_set = desktop_entry_set_new ();
+  else
+    excluded_set = NULL;
+
+  entry_pool = _entry_directory_list_get_all_desktops (menu_layout_node_menu_get_app_dirs (layout));
+
+  layout_iter = menu_layout_node_get_children (layout);
+  while (layout_iter != NULL)
+    {
+      switch (menu_layout_node_get_type (layout_iter))
+        {
+        case MENU_LAYOUT_NODE_MENU:
+          /* recurse */
+          {
+            MateMenuTreeDirectory *child_dir;
+
+	    menu_verbose ("Processing <Menu>\n");
+
+            child_dir = process_layout (tree,
+                                        directory,
+                                        layout_iter,
+                                        allocated);
+            if (child_dir)
+              directory->subdirs = g_slist_prepend (directory->subdirs,
+                                                    child_dir);
+
+	    menu_verbose ("Processed <Menu>\n");
+          }
+          break;
+
+        case MENU_LAYOUT_NODE_INCLUDE:
+          {
+            /* The match rule children of the <Include> are
+             * independent (logical OR) so we can process each one by
+             * itself
+             */
+            MenuLayoutNode *rule;
+
+	    menu_verbose ("Processing <Include> (%u entries)\n",
+			  desktop_entry_set_get_count (entries));
+
+            rule = menu_layout_node_get_children (layout_iter);
+            while (rule != NULL)
+              {
+                DesktopEntrySet *rule_set;
+
+                rule_set = process_include_rules (rule, entry_pool);
+                if (rule_set != NULL)
+                  {
+                    desktop_entry_set_union (entries, rule_set);
+                    desktop_entry_set_union (allocated_set, rule_set);
+		    if (excluded_set != NULL)
+		      desktop_entry_set_subtract (excluded_set, rule_set);
+                    desktop_entry_set_unref (rule_set);
+                  }
+
+                rule = menu_layout_node_get_next (rule);
+              }
+
+	    menu_verbose ("Processed <Include> (%u entries)\n",
+			  desktop_entry_set_get_count (entries));
+          }
+          break;
+
+        case MENU_LAYOUT_NODE_EXCLUDE:
+          {
+            /* The match rule children of the <Exclude> are
+             * independent (logical OR) so we can process each one by
+             * itself
+             */
+            MenuLayoutNode *rule;
+
+	    menu_verbose ("Processing <Exclude> (%u entries)\n",
+			  desktop_entry_set_get_count (entries));
+
+            rule = menu_layout_node_get_children (layout_iter);
+            while (rule != NULL)
+              {
+                DesktopEntrySet *rule_set;
+
+                rule_set = process_include_rules (rule, entry_pool);
+                if (rule_set != NULL)
+                  {
+		    if (excluded_set != NULL)
+		      desktop_entry_set_union (excluded_set, rule_set);
+		    desktop_entry_set_subtract (entries, rule_set);
+		    desktop_entry_set_unref (rule_set);
+                  }
+
+                rule = menu_layout_node_get_next (rule);
+              }
+
+	    menu_verbose ("Processed <Exclude> (%u entries)\n",
+			  desktop_entry_set_get_count (entries));
+          }
+          break;
+
+        case MENU_LAYOUT_NODE_DIRECTORY:
+          {
+            DesktopEntry *entry;
+
+	    menu_verbose ("Processing <Directory>%s</Directory>\n",
+			  menu_layout_node_get_content (layout_iter));
+
+	    /*
+             * The last <Directory> to exist wins, so we always try overwriting
+             */
+            entry = entry_directory_list_get_directory (menu_layout_node_menu_get_directory_dirs (layout),
+                                                        menu_layout_node_get_content (layout_iter));
+
+            if (entry != NULL)
+              {
+                if (!desktop_entry_get_hidden (entry))
+                  {
+                    if (directory->directory_entry)
+                      desktop_entry_unref (directory->directory_entry);
+                    directory->directory_entry = entry; /* pass ref ownership */
+                  }
+                else
+                  {
+                    desktop_entry_unref (entry);
+                  }
+              }
+
+            menu_verbose ("Processed <Directory> new directory entry = %p (%s)\n",
+                          directory->directory_entry,
+			  directory->directory_entry? desktop_entry_get_path (directory->directory_entry) : "null");
+          }
+          break;
+
+        case MENU_LAYOUT_NODE_DELETED:
+	  menu_verbose ("Processed <Deleted/>\n");
+          deleted = TRUE;
+          break;
+
+        case MENU_LAYOUT_NODE_NOT_DELETED:
+	  menu_verbose ("Processed <NotDeleted/>\n");
+          deleted = FALSE;
+          break;
+
+        case MENU_LAYOUT_NODE_ONLY_UNALLOCATED:
+	  menu_verbose ("Processed <OnlyUnallocated/>\n");
+          only_unallocated = TRUE;
+          break;
+
+        case MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED:
+	  menu_verbose ("Processed <NotOnlyUnallocated/>\n");
+          only_unallocated = FALSE;
+          break;
+
+	case MENU_LAYOUT_NODE_DEFAULT_LAYOUT:
+	  menu_layout_node_default_layout_get_values (layout_iter,
+						      &directory->default_layout_values);
+	  collect_layout_info (layout_iter, &directory->default_layout_info);
+	  menu_verbose ("Processed <DefaultLayout/>\n");
+	  break;
+
+	case MENU_LAYOUT_NODE_LAYOUT:
+	  collect_layout_info (layout_iter, &directory->layout_info);
+	  menu_verbose ("Processed <Layout/>\n");
+	  break;
+
+        default:
+          break;
+        }
+
+      layout_iter = menu_layout_node_get_next (layout_iter);
+    }
+
+  desktop_entry_set_unref (entry_pool);
+
+  directory->only_unallocated = only_unallocated != FALSE;
+
+  if (!directory->only_unallocated)
+    desktop_entry_set_union (allocated, allocated_set);
+
+  desktop_entry_set_unref (allocated_set);
+
+  if (directory->directory_entry)
+    {
+      if (desktop_entry_get_no_display (directory->directory_entry))
+        {
+          directory->is_nodisplay = TRUE;
+
+          if (!(tree->flags & MATEMENU_TREE_FLAGS_INCLUDE_NODISPLAY))
+            {
+              menu_verbose ("Not showing menu %s because NoDisplay=true\n",
+                        desktop_entry_get_name (directory->directory_entry));
+              deleted = TRUE;
+            }
+        }
+
+      if (!desktop_entry_get_show_in (directory->directory_entry))
+        {
+          menu_verbose ("Not showing menu %s because OnlyShowIn!=$DESKTOP or NotShowIn=$DESKTOP (with $DESKTOP=${XDG_CURRENT_DESKTOP:-GNOME})\n",
+                        desktop_entry_get_name (directory->directory_entry));
+          deleted = TRUE;
+        }
+    }
+
+  if (deleted)
+    {
+      if (excluded_set != NULL)
+	desktop_entry_set_unref (excluded_set);
+      desktop_entry_set_unref (entries);
+      matemenu_tree_item_unref (directory);
+      return NULL;
+    }
+
+#ifdef WITH_COLLECTION
+  if (tree->collection_applet && !g_strcmp0 (directory->name, "Collection"))
+    {
+      guint i;
+      for (i = 0; i < tree->collection_applet->len; i++)
+      {
+        const char *desktop_name = g_ptr_array_index (tree->collection_applet, i);
+        get_by_desktop (entry_pool, entries, desktop_name);
+      }
+    }
+#endif /* WITH_COLLECTION */
+
+  desktop_entry_set_foreach (entries,
+                             (DesktopEntrySetForeachFunc) entries_listify_foreach,
+                             directory);
+  desktop_entry_set_unref (entries);
+
+  if (excluded_set != NULL)
+    {
+      desktop_entry_set_foreach (excluded_set,
+				 (DesktopEntrySetForeachFunc) excluded_entries_listify_foreach,
+				 directory);
+      desktop_entry_set_unref (excluded_set);
+    }
+
+  tmp = directory->subdirs;
+  while (tmp != NULL)
+    {
+      MateMenuTreeDirectory *subdir = tmp->data;
+
+      set_default_layout_values (directory, subdir);
+
+      tmp = tmp->next;
+    }
+
+  tmp = directory->entries;
+  while (tmp != NULL)
+    {
+      MateMenuTreeEntry *entry = tmp->data;
+      GSList         *next  = tmp->next;
+      gboolean        delete = FALSE;
+
+      /* If adding a new condition to delete here, it has to be added to
+       * get_still_unallocated_foreach() too */
+
+      if (desktop_entry_get_hidden (entry->desktop_entry))
+        {
+          menu_verbose ("Deleting %s because Hidden=true\n",
+                        desktop_entry_get_name (entry->desktop_entry));
+          delete = TRUE;
+        }
+
+      if (!(tree->flags & MATEMENU_TREE_FLAGS_INCLUDE_NODISPLAY) &&
+          desktop_entry_get_no_display (entry->desktop_entry))
+        {
+          menu_verbose ("Deleting %s because NoDisplay=true\n",
+                        desktop_entry_get_name (entry->desktop_entry));
+          delete = TRUE;
+        }
+
+      if (!desktop_entry_get_show_in (entry->desktop_entry))
+        {
+          menu_verbose ("Deleting %s because OnlyShowIn!=$DESKTOP or NotShowIn=$DESKTOP (with $DESKTOP=${XDG_CURRENT_DESKTOP:-GNOME})\n",
+                        desktop_entry_get_name (entry->desktop_entry));
+          delete = TRUE;
+        }
+
+      /* No need to filter out based on TryExec since GDesktopAppInfo cannot
+       * deal with .desktop files with a failed TryExec. */
+
+      if (delete)
+        {
+          directory->entries = g_slist_delete_link (directory->entries,
+                                                   tmp);
+          matemenu_tree_item_unref_and_unset_parent (entry);
+        }
+
+      tmp = next;
+    }
+
+  g_assert (directory->name != NULL);
+
+  return directory;
+}
+
+static void
+process_only_unallocated (MateMenuTree          *tree,
+			  MateMenuTreeDirectory *directory,
+			  DesktopEntrySet    *allocated,
+			  DesktopEntrySet    *unallocated_used)
+{
+  GSList *tmp;
+
+  /* For any directory marked only_unallocated, we have to remove any
+   * entries that were in fact allocated.
+   */
+
+  if (directory->only_unallocated)
+    {
+      tmp = directory->entries;
+      while (tmp != NULL)
+        {
+          MateMenuTreeEntry *entry = tmp->data;
+          GSList         *next  = tmp->next;
+
+          if (desktop_entry_set_lookup (allocated, entry->desktop_file_id))
+            {
+              directory->entries = g_slist_delete_link (directory->entries,
+                                                        tmp);
+              matemenu_tree_item_unref_and_unset_parent (entry);
+            }
+          else
+            {
+              desktop_entry_set_add_entry (unallocated_used, entry->desktop_entry, entry->desktop_file_id);
+            }
+
+          tmp = next;
+        }
+    }
+
+  tmp = directory->subdirs;
+  while (tmp != NULL)
+    {
+      MateMenuTreeDirectory *subdir = tmp->data;
+
+      process_only_unallocated (tree, subdir, allocated, unallocated_used);
+
+      tmp = tmp->next;
+   }
+}
+
+typedef struct
+{
+  MateMenuTree *tree;
+  DesktopEntrySet *allocated;
+  DesktopEntrySet *unallocated_used;
+  DesktopEntrySet *still_unallocated;
+} GetStillUnallocatedForeachData;
+
+static void
+get_still_unallocated_foreach (const char                     *file_id,
+                               DesktopEntry                   *entry,
+                               GetStillUnallocatedForeachData *data)
+{
+  if (desktop_entry_set_lookup (data->allocated, file_id))
+    return;
+
+  if (desktop_entry_set_lookup (data->unallocated_used, file_id))
+    return;
+
+  /* Same rules than at the end of process_layout() */
+  if (desktop_entry_get_hidden (entry))
+    return;
+
+  if (!(data->tree->flags & MATEMENU_TREE_FLAGS_INCLUDE_NODISPLAY) &&
+      desktop_entry_get_no_display (entry))
+    return;
+
+  if (!desktop_entry_get_show_in (entry))
+    return;
+
+  desktop_entry_set_add_entry (data->still_unallocated, entry, file_id);
+}
+
+static void preprocess_layout_info (MateMenuTree          *tree,
+                                    MateMenuTreeDirectory *directory);
+
+static GSList *
+get_layout_info (MateMenuTreeDirectory *directory,
+                 gboolean           *is_default_layout)
+{
+  MateMenuTreeDirectory *iter;
+
+  if (directory->layout_info != NULL)
+    {
+      if (is_default_layout)
+        {
+          *is_default_layout = FALSE;
+        }
+      return directory->layout_info;
+    }
+
+  /* Even if there's no layout information at all, the result will be an
+   * implicit default layout */
+  if (is_default_layout)
+    {
+      *is_default_layout = TRUE;
+    }
+
+  iter = directory;
+  while (iter != NULL)
+    {
+      /* FIXME: this is broken: we might skip real parent in the
+       * XML structure, that are hidden because of inlining. */
+      if (iter->default_layout_info != NULL)
+	{
+	  return iter->default_layout_info;
+	}
+
+      iter = MATEMENU_TREE_ITEM (iter)->parent;
+    }
+
+  return NULL;
+}
+
+static void
+get_values_with_defaults (MenuLayoutNode   *node,
+			  MenuLayoutValues *layout_values,
+			  MenuLayoutValues *default_layout_values)<--- Parameter 'default_layout_values' can be declared as pointer to const
+{
+  menu_layout_node_menuname_get_values (node, layout_values);
+
+  if (!(layout_values->mask & MENU_LAYOUT_VALUES_SHOW_EMPTY))
+    layout_values->show_empty = default_layout_values->show_empty;
+
+  if (!(layout_values->mask & MENU_LAYOUT_VALUES_INLINE_MENUS))
+    layout_values->inline_menus = default_layout_values->inline_menus;
+
+  if (!(layout_values->mask & MENU_LAYOUT_VALUES_INLINE_LIMIT))
+    layout_values->inline_limit = default_layout_values->inline_limit;
+
+  if (!(layout_values->mask & MENU_LAYOUT_VALUES_INLINE_HEADER))
+    layout_values->inline_header = default_layout_values->inline_header;
+
+  if (!(layout_values->mask & MENU_LAYOUT_VALUES_INLINE_ALIAS))
+    layout_values->inline_alias = default_layout_values->inline_alias;
+}
+
+static guint
+get_real_subdirs_len (MateMenuTreeDirectory *directory)
+{
+  guint   len;
+  GSList *tmp;<--- Variable 'tmp' can be declared as pointer to const
+
+  len = 0;
+
+  tmp = directory->subdirs;
+  while (tmp != NULL)
+    {
+      MateMenuTreeDirectory *subdir = tmp->data;
+
+      tmp = tmp->next;
+
+      if (subdir->will_inline_header != G_MAXUINT16)
+        {
+          len += get_real_subdirs_len (subdir) + g_slist_length (subdir->entries) + 1;
+        }
+      else
+        len += 1;
+    }
+
+  return len;
+}
+
+static void
+preprocess_layout_info_subdir_helper (MateMenuTree          *tree,
+                                      MateMenuTreeDirectory *directory,
+                                      MateMenuTreeDirectory *subdir,
+                                      MenuLayoutValues   *layout_values,
+                                      gboolean           *contents_added,
+                                      gboolean           *should_remove)
+{
+  preprocess_layout_info (tree, subdir);
+
+  *should_remove = FALSE;
+  *contents_added = FALSE;
+
+  if (subdir->subdirs == NULL && subdir->entries == NULL)
+    {
+      if (!(tree->flags & MATEMENU_TREE_FLAGS_SHOW_EMPTY) &&
+          !layout_values->show_empty)
+	{
+	  menu_verbose ("Not showing empty menu '%s'\n", subdir->name);
+	  *should_remove = TRUE;
+	}
+    }
+
+  else if (layout_values->inline_menus)
+    {
+      guint real_subdirs_len;
+
+      real_subdirs_len = get_real_subdirs_len (subdir);
+
+      if (layout_values->inline_alias &&
+          real_subdirs_len + g_slist_length (subdir->entries) == 1)
+        {
+          MateMenuTreeAlias *alias;
+          MateMenuTreeItem  *item;
+          GSList         *list;
+
+          if (subdir->subdirs != NULL)
+            list = subdir->subdirs;
+          else
+            list = subdir->entries;
+
+          item = MATEMENU_TREE_ITEM (list->data);
+
+          menu_verbose ("Inline aliasing '%s' to '%s'\n",
+                        item->type == MATEMENU_TREE_ITEM_ENTRY ?
+                          g_app_info_get_name (G_APP_INFO (matemenu_tree_entry_get_app_info (MATEMENU_TREE_ENTRY (item)))) :
+                          (item->type == MATEMENU_TREE_ITEM_DIRECTORY ?
+                             matemenu_tree_directory_get_name (MATEMENU_TREE_DIRECTORY (item)) :
+                             matemenu_tree_directory_get_name (MATEMENU_TREE_ALIAS (item)->directory)),
+                        subdir->name);
+
+          alias = matemenu_tree_alias_new (directory, subdir, item);
+
+          g_slist_free_full (list,
+                             (GDestroyNotify) matemenu_tree_item_unref_and_unset_parent);
+          subdir->subdirs = NULL;
+          subdir->entries = NULL;
+
+          if (item->type == MATEMENU_TREE_ITEM_DIRECTORY)
+            directory->subdirs = g_slist_append (directory->subdirs, alias);
+          else
+            directory->entries = g_slist_append (directory->entries, alias);
+
+          *contents_added = TRUE;
+          *should_remove = TRUE;
+        }
+
+      else if (layout_values->inline_limit == 0 ||
+               layout_values->inline_limit >= real_subdirs_len + g_slist_length (subdir->entries))
+        {
+          if (layout_values->inline_header)
+            {
+              menu_verbose ("Creating inline header with name '%s'\n", subdir->name);
+              /* we're limited to 16-bits to spare some memory; if the limit is
+               * higher than that (would be crazy), we just consider it's
+               * unlimited */
+              if (layout_values->inline_limit < G_MAXUINT16)
+                subdir->will_inline_header = (guint16) layout_values->inline_limit;
+              else
+                subdir->will_inline_header = 0;
+            }
+          else
+            {
+              g_slist_foreach (subdir->subdirs,
+                               (GFunc) matemenu_tree_item_set_parent,
+                               directory);
+              directory->subdirs = g_slist_concat (directory->subdirs,
+                                                   subdir->subdirs);
+              subdir->subdirs = NULL;
+
+              g_slist_foreach (subdir->entries,
+                               (GFunc) matemenu_tree_item_set_parent,
+                               directory);
+              directory->entries = g_slist_concat (directory->entries,
+                                                   subdir->entries);
+              subdir->entries = NULL;
+
+              *contents_added = TRUE;
+              *should_remove = TRUE;
+            }
+
+          menu_verbose ("Inlining directory contents of '%s' to '%s'\n",
+                        subdir->name, directory->name);
+        }
+    }
+}
+
+static void
+preprocess_layout_info (MateMenuTree          *tree,
+                        MateMenuTreeDirectory *directory)
+{
+  GSList   *tmp;
+  GSList   *layout_info;
+  gboolean  using_default_layout;
+  GSList   *last_subdir;<--- Variable 'last_subdir' can be declared as pointer to const
+  gboolean  strip_duplicates;
+  gboolean  contents_added;
+  gboolean  should_remove;
+  GSList   *subdirs_sentinel;
+
+  /* Note: we need to preprocess all menus, even if the layout mask for a menu
+   * is MENU_LAYOUT_VALUES_NONE: in this case, we need to remove empty menus;
+   * and the layout mask can be different for a submenu anyway */
+
+  menu_verbose ("Processing menu layout inline hints for %s\n", directory->name);
+  g_assert (!directory->preprocessed);
+
+  strip_duplicates = FALSE;
+  /* we use last_subdir to track the last non-inlined subdirectory */
+  last_subdir = g_slist_last (directory->subdirs);
+
+  /*
+   * First process subdirectories with explicit layout
+   */
+  layout_info = get_layout_info (directory, &using_default_layout);
+  tmp = layout_info;
+  /* see comment below about Menuname to understand why we leave the loop if
+   * last_subdir is NULL */
+  while (tmp != NULL && last_subdir != NULL)
+    {
+      MenuLayoutNode     *node = tmp->data;
+      MenuLayoutValues    layout_values;
+      const char         *name;
+      MateMenuTreeDirectory *subdir;
+      GSList             *subdir_l;<--- Variable 'subdir_l' can be declared as pointer to const
+
+      tmp = tmp->next;
+
+      /* only Menuname nodes are relevant here */
+      if (menu_layout_node_get_type (node) != MENU_LAYOUT_NODE_MENUNAME)
+        continue;
+
+      get_values_with_defaults (node,
+                                &layout_values,
+                                &directory->default_layout_values);
+
+      /* find the subdirectory that is affected by those attributes */
+      name = menu_layout_node_get_content (node);
+      subdir = NULL;
+      subdir_l = directory->subdirs;
+      while (subdir_l != NULL)
+        {
+          subdir = subdir_l->data;
+
+          if (!strcmp (subdir->name, name))
+            break;
+
+          subdir = NULL;
+          subdir_l = subdir_l->next;
+
+          /* We do not want to use Menuname on a menu that appeared via
+           * inlining: without inlining, the Menuname wouldn't have matched
+           * anything, and we want to keep the same behavior.
+           * Unless the layout is a default layout, in which case the Menuname
+           * does match the subdirectory. */
+          if (!using_default_layout && subdir_l == last_subdir)
+            {
+              subdir_l = NULL;
+              break;
+            }
+        }
+
+      if (subdir == NULL)
+        continue;
+
+      preprocess_layout_info_subdir_helper (tree, directory,
+                                            subdir, &layout_values,
+                                            &contents_added, &should_remove);
+      strip_duplicates = strip_duplicates || contents_added;
+      if (should_remove)
+        {
+          if (last_subdir == subdir_l)
+            {
+              /* we need to recompute last_subdir since we'll remove it from
+               * the list */
+              GSList *buf;
+
+              if (subdir_l == directory->subdirs)
+                last_subdir = NULL;
+              else
+                {
+                  buf = directory->subdirs;
+                  while (buf != NULL && buf->next != subdir_l)
+                    buf = buf->next;
+                  last_subdir = buf;
+                }
+            }
+
+          directory->subdirs = g_slist_remove (directory->subdirs, subdir);
+          matemenu_tree_item_unref_and_unset_parent (MATEMENU_TREE_ITEM (subdir));
+        }
+    }
+
+  /*
+   * Now process the subdirectories with no explicit layout
+   */
+  /* this is bogus data, but we just need the pointer anyway */
+  subdirs_sentinel = g_slist_prepend (directory->subdirs, PACKAGE);
+  directory->subdirs = subdirs_sentinel;
+
+  tmp = directory->subdirs;
+  while (tmp->next != NULL)
+    {
+      MateMenuTreeDirectory *subdir = tmp->next->data;
+
+      if (subdir->preprocessed)
+        {
+          tmp = tmp->next;
+          continue;
+        }
+
+      preprocess_layout_info_subdir_helper (tree, directory,
+                                            subdir, &directory->default_layout_values,
+                                            &contents_added, &should_remove);
+      strip_duplicates = strip_duplicates || contents_added;
+      if (should_remove)
+        {
+          tmp = g_slist_delete_link (tmp, tmp->next);
+          matemenu_tree_item_unref_and_unset_parent (MATEMENU_TREE_ITEM (subdir));
+        }
+      else
+        tmp = tmp->next;
+    }
+
+  /* remove the sentinel */
+  directory->subdirs = g_slist_delete_link (directory->subdirs,
+                                            directory->subdirs);
+
+  /*
+   * Finally, remove duplicates if needed
+   */
+  if (strip_duplicates)
+    {
+      /* strip duplicate entries; there should be no duplicate directories */
+      directory->entries = g_slist_sort (directory->entries,
+                                         (GCompareFunc) matemenu_tree_entry_compare_by_id);
+      tmp = directory->entries;
+      while (tmp != NULL && tmp->next != NULL)
+        {
+          MateMenuTreeItem *a = tmp->data;
+          MateMenuTreeItem *b = tmp->next->data;
+
+          if (a->type == MATEMENU_TREE_ITEM_ALIAS)
+            a = MATEMENU_TREE_ALIAS (a)->aliased_item;
+
+          if (b->type == MATEMENU_TREE_ITEM_ALIAS)
+            b = MATEMENU_TREE_ALIAS (b)->aliased_item;
+
+          if (strcmp (MATEMENU_TREE_ENTRY (a)->desktop_file_id,
+                      MATEMENU_TREE_ENTRY (b)->desktop_file_id) == 0)
+            {
+              tmp = g_slist_delete_link (tmp, tmp->next);
+              matemenu_tree_item_unref (b);
+            }
+          else
+            tmp = tmp->next;
+        }
+    }
+
+  directory->preprocessed = TRUE;
+}
+
+static void process_layout_info (MateMenuTree          *tree,
+				 MateMenuTreeDirectory *directory);
+
+static void
+check_pending_separator (MateMenuTreeDirectory *directory)
+{
+  if (directory->layout_pending_separator)
+    {
+      menu_verbose ("Adding pending separator in '%s'\n", directory->name);
+
+      directory->contents = g_slist_append (directory->contents,
+					    matemenu_tree_separator_new (directory));
+      directory->layout_pending_separator = FALSE;
+    }
+}
+
+static void
+merge_alias (MateMenuTree          *tree,
+	     MateMenuTreeDirectory *directory,
+	     MateMenuTreeAlias     *alias)
+{
+  menu_verbose ("Merging alias '%s' in directory '%s'\n",
+		alias->directory->name, directory->name);
+
+  if (alias->aliased_item->type == MATEMENU_TREE_ITEM_DIRECTORY)
+    {
+      process_layout_info (tree, MATEMENU_TREE_DIRECTORY (alias->aliased_item));
+    }
+
+  check_pending_separator (directory);
+
+  directory->contents = g_slist_append (directory->contents,
+					matemenu_tree_item_ref (alias));
+}
+
+static void
+merge_subdir (MateMenuTree          *tree,
+	      MateMenuTreeDirectory *directory,
+	      MateMenuTreeDirectory *subdir)
+{
+  menu_verbose ("Merging subdir '%s' in directory '%s'\n",
+		subdir->name, directory->name);
+
+  process_layout_info (tree, subdir);
+
+  check_pending_separator (directory);
+
+  if (subdir->will_inline_header == 0 ||
+      (subdir->will_inline_header != G_MAXUINT16 &&
+       g_slist_length (subdir->contents) <= subdir->will_inline_header))
+    {
+      MateMenuTreeHeader *header;
+
+      header = matemenu_tree_header_new (directory, subdir);
+      directory->contents = g_slist_append (directory->contents, header);
+
+      g_slist_foreach (subdir->contents,
+                       (GFunc) matemenu_tree_item_set_parent,
+                       directory);
+      directory->contents = g_slist_concat (directory->contents,
+                                            subdir->contents);
+      subdir->contents = NULL;
+      subdir->will_inline_header = G_MAXUINT16;
+
+      matemenu_tree_item_set_parent (MATEMENU_TREE_ITEM (subdir), NULL);
+    }
+  else
+    {
+      directory->contents = g_slist_append (directory->contents,
+					    matemenu_tree_item_ref (subdir));
+    }
+}
+
+static void
+merge_subdir_by_name (MateMenuTree          *tree,
+		      MateMenuTreeDirectory *directory,
+		      const char         *subdir_name)
+{
+  GSList *tmp;
+
+  menu_verbose ("Attempting to merge subdir '%s' in directory '%s'\n",
+		subdir_name, directory->name);
+
+  tmp = directory->subdirs;
+  while (tmp != NULL)
+    {
+      MateMenuTreeDirectory *subdir = tmp->data;
+      GSList             *next = tmp->next;
+
+      /* if it's an alias, then it cannot be affected by
+       * the Merge nodes in the layout */
+      if (MATEMENU_TREE_ITEM (subdir)->type == MATEMENU_TREE_ITEM_ALIAS)
+        continue;
+
+      if (!strcmp (subdir->name, subdir_name))
+	{
+	  directory->subdirs = g_slist_delete_link (directory->subdirs, tmp);
+	  merge_subdir (tree, directory, subdir);
+	  matemenu_tree_item_unref (subdir);
+	}
+
+      tmp = next;
+    }
+}
+
+static void
+merge_entry (MateMenuTree          *tree,
+	     MateMenuTreeDirectory *directory,
+	     MateMenuTreeEntry     *entry)
+{
+  menu_verbose ("Merging entry '%s' in directory '%s'\n",
+		entry->desktop_file_id, directory->name);
+
+  check_pending_separator (directory);
+  directory->contents = g_slist_append (directory->contents,
+					matemenu_tree_item_ref (entry));
+}
+
+static void
+merge_entry_by_id (MateMenuTree          *tree,
+		   MateMenuTreeDirectory *directory,
+		   const char         *file_id)
+{
+  GSList *tmp;
+
+  menu_verbose ("Attempting to merge entry '%s' in directory '%s'\n",
+		file_id, directory->name);
+
+  tmp = directory->entries;
+  while (tmp != NULL)
+    {
+      MateMenuTreeEntry *entry = tmp->data;
+      GSList         *next = tmp->next;
+
+      /* if it's an alias, then it cannot be affected by
+       * the Merge nodes in the layout */
+      if (MATEMENU_TREE_ITEM (entry)->type == MATEMENU_TREE_ITEM_ALIAS)
+        continue;
+
+      if (!strcmp (entry->desktop_file_id, file_id))
+	{
+	  directory->entries = g_slist_delete_link (directory->entries, tmp);
+	  merge_entry (tree, directory, entry);
+	  matemenu_tree_item_unref (entry);
+	}
+
+      tmp = next;
+    }
+}
+
+static inline gboolean
+find_name_in_list (const char *name,
+		   GSList     *list)<--- Parameter 'list' can be declared as pointer to const
+{
+  while (list != NULL)
+    {
+      if (!strcmp (name, list->data))
+	return TRUE;
+
+      list = list->next;
+    }
+
+  return FALSE;
+}
+
+static void
+merge_subdirs (MateMenuTree          *tree,
+	       MateMenuTreeDirectory *directory,
+	       GSList             *except)
+{
+  GSList *subdirs;
+  GSList *tmp;
+
+  menu_verbose ("Merging subdirs in directory '%s'\n", directory->name);
+
+  subdirs = directory->subdirs;
+  directory->subdirs = NULL;
+
+  subdirs = g_slist_sort_with_data (subdirs,
+                                    (GCompareDataFunc) matemenu_tree_item_compare,
+                                    (void *) MATEMENU_TREE_FLAGS_NONE);
+
+  tmp = subdirs;
+  while (tmp != NULL)
+    {
+      MateMenuTreeDirectory *subdir = tmp->data;
+
+      if (MATEMENU_TREE_ITEM (subdir)->type == MATEMENU_TREE_ITEM_ALIAS)
+        {
+	  merge_alias (tree, directory, MATEMENU_TREE_ALIAS (subdir));
+	  matemenu_tree_item_unref (subdir);
+        }
+      else if (!find_name_in_list (subdir->name, except))
+	{
+	  merge_subdir (tree, directory, subdir);
+	  matemenu_tree_item_unref (subdir);
+	}
+      else
+	{
+	  menu_verbose ("Not merging directory '%s' yet\n", subdir->name);
+	  directory->subdirs = g_slist_append (directory->subdirs, subdir);
+	}
+
+      tmp = tmp->next;
+    }
+
+  g_slist_free (subdirs);
+  g_slist_free (except);
+}
+
+static void
+merge_entries (MateMenuTree          *tree,
+	       MateMenuTreeDirectory *directory,
+	       GSList             *except)
+{
+  GSList *entries;
+  GSList *tmp;
+
+  menu_verbose ("Merging entries in directory '%s'\n", directory->name);
+
+  entries = directory->entries;
+  directory->entries = NULL;
+
+  entries = g_slist_sort_with_data (entries,
+				    (GCompareDataFunc) matemenu_tree_item_compare,
+                                    (void *) tree->flags);
+
+  tmp = entries;
+  while (tmp != NULL)
+    {
+      MateMenuTreeEntry *entry = tmp->data;
+
+      if (MATEMENU_TREE_ITEM (entry)->type == MATEMENU_TREE_ITEM_ALIAS)
+        {
+	  merge_alias (tree, directory, MATEMENU_TREE_ALIAS (entry));
+	  matemenu_tree_item_unref (entry);
+        }
+      else if (!find_name_in_list (entry->desktop_file_id, except))
+	{
+	  merge_entry (tree, directory, entry);
+	  matemenu_tree_item_unref (entry);
+	}
+      else
+	{
+	  menu_verbose ("Not merging entry '%s' yet\n", entry->desktop_file_id);
+	  directory->entries = g_slist_append (directory->entries, entry);
+	}
+
+      tmp = tmp->next;
+    }
+
+  g_slist_free (entries);
+  g_slist_free (except);
+}
+
+static void
+merge_subdirs_and_entries (MateMenuTree          *tree,
+			   MateMenuTreeDirectory *directory,
+			   GSList             *except_subdirs,
+			   GSList             *except_entries)
+{
+  GSList *items;
+  GSList *tmp;
+
+  menu_verbose ("Merging subdirs and entries together in directory %s\n",
+		directory->name);
+
+  items = g_slist_concat (directory->subdirs, directory->entries);
+
+  directory->subdirs = NULL;
+  directory->entries = NULL;
+
+  items = g_slist_sort_with_data (items,
+                                  (GCompareDataFunc) matemenu_tree_item_compare,
+                                  (void *) tree->flags);
+
+  tmp = items;
+  while (tmp != NULL)
+    {
+      MateMenuTreeItem     *item = tmp->data;
+      MateMenuTreeItemType  type;
+
+      type = item->type;
+
+      if (type == MATEMENU_TREE_ITEM_ALIAS)
+        {
+          merge_alias (tree, directory, MATEMENU_TREE_ALIAS (item));
+          matemenu_tree_item_unref (item);
+        }
+      else if (type == MATEMENU_TREE_ITEM_DIRECTORY)
+	{
+	  if (!find_name_in_list (MATEMENU_TREE_DIRECTORY (item)->name, except_subdirs))
+	    {
+	      merge_subdir (tree,
+			    directory,
+			    MATEMENU_TREE_DIRECTORY (item));
+	      matemenu_tree_item_unref (item);
+	    }
+	  else
+	    {
+	      menu_verbose ("Not merging directory '%s' yet\n",
+			    MATEMENU_TREE_DIRECTORY (item)->name);
+	      directory->subdirs = g_slist_append (directory->subdirs, item);
+	    }
+	}
+      else if (type == MATEMENU_TREE_ITEM_ENTRY)
+	{
+	  if (!find_name_in_list (MATEMENU_TREE_ENTRY (item)->desktop_file_id, except_entries))
+	    {
+	      merge_entry (tree, directory, MATEMENU_TREE_ENTRY (item));
+	      matemenu_tree_item_unref (item);
+	    }
+	  else
+	    {
+	      menu_verbose ("Not merging entry '%s' yet\n",
+			    MATEMENU_TREE_ENTRY (item)->desktop_file_id);
+	      directory->entries = g_slist_append (directory->entries, item);
+	    }
+	}
+      else
+        {
+          g_assert_not_reached ();
+        }
+
+      tmp = tmp->next;
+    }
+
+  g_slist_free (items);
+  g_slist_free (except_subdirs);
+  g_slist_free (except_entries);
+}
+
+static GSList *
+get_subdirs_from_layout_info (GSList *layout_info)
+{
+  GSList *subdirs;
+  GSList *tmp;<--- Variable 'tmp' can be declared as pointer to const
+
+  subdirs = NULL;
+
+  tmp = layout_info;
+  while (tmp != NULL)
+    {
+      MenuLayoutNode *node = tmp->data;
+
+      if (menu_layout_node_get_type (node) == MENU_LAYOUT_NODE_MENUNAME)
+	{
+	  subdirs = g_slist_append (subdirs,
+				    (char *) menu_layout_node_get_content (node));
+	}
+
+      tmp = tmp->next;
+    }
+
+  return subdirs;
+}
+
+static GSList *
+get_entries_from_layout_info (GSList *layout_info)
+{
+  GSList *entries;
+  GSList *tmp;<--- Variable 'tmp' can be declared as pointer to const
+
+  entries = NULL;
+
+  tmp = layout_info;
+  while (tmp != NULL)
+    {
+      MenuLayoutNode *node = tmp->data;
+
+      if (menu_layout_node_get_type (node) == MENU_LAYOUT_NODE_FILENAME)
+	{
+	  entries = g_slist_append (entries,
+				    (char *) menu_layout_node_get_content (node));
+	}
+
+      tmp = tmp->next;
+    }
+
+  return entries;
+}
+
+static void
+process_layout_info (MateMenuTree          *tree,
+		     MateMenuTreeDirectory *directory)
+{
+  GSList *layout_info;
+
+  menu_verbose ("Processing menu layout hints for %s\n", directory->name);
+
+  g_slist_foreach (directory->contents,
+		   (GFunc) matemenu_tree_item_unref_and_unset_parent,
+		   NULL);
+  g_slist_free (directory->contents);
+  directory->contents = NULL;
+  directory->layout_pending_separator = FALSE;
+
+  layout_info = get_layout_info (directory, NULL);
+
+  if (layout_info == NULL)
+    {
+      merge_subdirs (tree, directory, NULL);
+      merge_entries (tree, directory, NULL);
+    }
+  else
+    {
+      GSList *tmp;
+
+      tmp = layout_info;
+      while (tmp != NULL)
+	{
+	  MenuLayoutNode *node = tmp->data;
+
+	  switch (menu_layout_node_get_type (node))
+	    {
+	    case MENU_LAYOUT_NODE_MENUNAME:
+              merge_subdir_by_name (tree,
+                                    directory,
+                                    menu_layout_node_get_content (node));
+	      break;
+
+	    case MENU_LAYOUT_NODE_FILENAME:
+	      merge_entry_by_id (tree,
+				 directory,
+				 menu_layout_node_get_content (node));
+	      break;
+
+	    case MENU_LAYOUT_NODE_SEPARATOR:
+	      /* Unless explicitly told to show all separators, do not show a
+	       * separator at the beginning of a menu. Note that we don't add
+	       * the separators now, and instead make it pending. This way, we
+	       * won't show two consecutive separators nor will we show a
+	       * separator at the end of a menu. */
+              if (tree->flags & MATEMENU_TREE_FLAGS_SHOW_ALL_SEPARATORS)
+		{
+		  directory->layout_pending_separator = TRUE;
+		  check_pending_separator (directory);
+		}
+	      else if (directory->contents)
+		{
+		  menu_verbose ("Adding a potential separator in '%s'\n",
+				directory->name);
+
+		  directory->layout_pending_separator = TRUE;
+		}
+	      else
+		{
+		  menu_verbose ("Skipping separator at the beginning of '%s'\n",
+				directory->name);
+		}
+	      break;
+
+	    case MENU_LAYOUT_NODE_MERGE:
+	      switch (menu_layout_node_merge_get_type (node))
+		{
+		case MENU_LAYOUT_MERGE_NONE:
+		  break;
+
+		case MENU_LAYOUT_MERGE_MENUS:
+		  merge_subdirs (tree,
+				 directory,
+				 get_subdirs_from_layout_info (tmp->next));
+		  break;
+
+		case MENU_LAYOUT_MERGE_FILES:
+		  merge_entries (tree,
+				 directory,
+				 get_entries_from_layout_info (tmp->next));
+		  break;
+
+		case MENU_LAYOUT_MERGE_ALL:
+		  merge_subdirs_and_entries (tree,
+					     directory,
+					     get_subdirs_from_layout_info (tmp->next),
+					     get_entries_from_layout_info (tmp->next));
+		  break;
+
+		default:
+		  g_assert_not_reached ();
+		  break;
+		}
+	      break;
+
+	    default:
+	      g_assert_not_reached ();
+	      break;
+	    }
+
+	  tmp = tmp->next;
+	}
+    }
+
+  g_slist_free_full (directory->subdirs,
+                     matemenu_tree_item_unref);
+  directory->subdirs = NULL;
+
+  g_slist_free_full (directory->entries,
+                     matemenu_tree_item_unref);
+  directory->entries = NULL;
+
+  g_slist_free_full (directory->default_layout_info,
+                     (GDestroyNotify) menu_layout_node_unref);
+  directory->default_layout_info = NULL;
+
+  g_slist_free_full (directory->layout_info,
+                     (GDestroyNotify) menu_layout_node_unref);
+  directory->layout_info = NULL;
+}
+
+static void
+handle_entries_changed (MenuLayoutNode *layout,<--- Parameter 'layout' can be declared as pointer to const
+                        MateMenuTree       *tree)
+{
+  if (tree->layout == layout)
+    {
+      matemenu_tree_force_rebuild (tree);
+      matemenu_tree_invoke_monitors (tree);
+    }
+}
+
+static void
+update_entry_index (MateMenuTree           *tree,
+		    MateMenuTreeDirectory  *dir)
+{
+  MateMenuTreeIter *iter = matemenu_tree_directory_iter (dir);
+  MateMenuTreeItemType next_type;
+
+  while ((next_type = matemenu_tree_iter_next (iter)) != MATEMENU_TREE_ITEM_INVALID)
+    {
+      gpointer item = NULL;
+
+      switch (next_type)
+        {
+        case MATEMENU_TREE_ITEM_ENTRY:
+          {
+	    const char *id;
+
+            item = matemenu_tree_iter_get_entry (iter);
+            id = matemenu_tree_entry_get_desktop_file_id (item);
+            if (id != NULL)
+              g_hash_table_insert (tree->entries_by_id, (char*)id, item);
+          }
+          break;
+        case MATEMENU_TREE_ITEM_DIRECTORY:
+          {
+            item = matemenu_tree_iter_get_directory (iter);
+            update_entry_index (tree, (MateMenuTreeDirectory*)item);
+          }
+          break;
+        default:
+          break;
+        }
+      if (item != NULL)
+        matemenu_tree_item_unref (item);
+    }
+
+  matemenu_tree_iter_unref (iter);
+}
+
+static gboolean
+matemenu_tree_build_from_layout (MateMenuTree  *tree,
+                              GError    **error)
+{
+  DesktopEntrySet *allocated;
+
+  if (tree->root)
+    return TRUE;
+
+  if (!matemenu_tree_load_layout (tree, error))
+    return FALSE;
+
+  menu_verbose ("Building menu tree from layout\n");
+
+  allocated = desktop_entry_set_new ();
+
+  /* create the menu structure */
+  tree->root = process_layout (tree,
+                               NULL,
+                               find_menu_child (tree->layout),
+                               allocated);
+  if (tree->root)
+    {
+      DesktopEntrySet *unallocated_used;
+
+      unallocated_used = desktop_entry_set_new ();
+
+      process_only_unallocated (tree, tree->root, allocated, unallocated_used);
+      if (tree->flags & MATEMENU_TREE_FLAGS_INCLUDE_UNALLOCATED)
+        {
+          DesktopEntrySet *entry_pool;
+          DesktopEntrySet *still_unallocated;
+          GetStillUnallocatedForeachData data;
+
+          entry_pool = _entry_directory_list_get_all_desktops (menu_layout_node_menu_get_app_dirs (find_menu_child (tree->layout)));
+          still_unallocated = desktop_entry_set_new ();
+
+          data.tree = tree;
+          data.allocated = allocated;
+          data.unallocated_used = unallocated_used;
+          data.still_unallocated = still_unallocated;
+
+          desktop_entry_set_foreach (entry_pool,
+                                     (DesktopEntrySetForeachFunc) get_still_unallocated_foreach,
+                                     &data);
+
+          desktop_entry_set_unref (entry_pool);
+
+          desktop_entry_set_foreach (still_unallocated,
+                                     (DesktopEntrySetForeachFunc) unallocated_entries_listify_foreach,
+                                     tree->root);
+
+          desktop_entry_set_unref (still_unallocated);
+        }
+
+      desktop_entry_set_unref (unallocated_used);
+
+      /* process the layout info part that can move/remove items:
+       * inline, show_empty, etc. */
+      preprocess_layout_info (tree, tree->root);
+      /* populate the menu structure that we got with the items, and order it
+       * according to the layout info */
+      process_layout_info (tree, tree->root);
+
+      update_entry_index (tree, tree->root);
+
+      menu_layout_node_root_add_entries_monitor (tree->layout,
+                                                 (MenuLayoutNodeEntriesChangedFunc) handle_entries_changed,
+                                                 tree);
+    }
+
+  desktop_entry_set_unref (allocated);
+
+  return TRUE;
+}
+
+static void
+matemenu_tree_force_rebuild (MateMenuTree *tree)
+{
+  if (tree->root)
+    {
+      g_hash_table_remove_all (tree->entries_by_id);
+      matemenu_tree_item_unref (tree->root);
+      tree->root = NULL;
+      tree->loaded = FALSE;
+
+      g_assert (tree->layout != NULL);
+
+      menu_layout_node_root_remove_entries_monitor (tree->layout,
+                                                    (MenuLayoutNodeEntriesChangedFunc) handle_entries_changed,<--- You might need to cast the function pointer here
+                                                    tree);
+    }
+}
+
+GType
+matemenu_tree_iter_get_type (void)
+{
+  static GType gtype = G_TYPE_INVALID;
+  if (gtype == G_TYPE_INVALID)
+    {
+      gtype = g_boxed_type_register_static ("MateMenuTreeIter",
+          (GBoxedCopyFunc)matemenu_tree_iter_ref,
+          (GBoxedFreeFunc)matemenu_tree_iter_unref);
+    }
+  return gtype;
+}
+
+GType
+matemenu_tree_directory_get_type (void)
+{
+  static GType gtype = G_TYPE_INVALID;
+  if (gtype == G_TYPE_INVALID)
+    {
+      gtype = g_boxed_type_register_static ("MateMenuTreeDirectory",
+          (GBoxedCopyFunc)matemenu_tree_item_ref,
+          (GBoxedFreeFunc)matemenu_tree_item_unref);
+    }
+  return gtype;
+}
+
+GType
+matemenu_tree_entry_get_type (void)
+{
+  static GType gtype = G_TYPE_INVALID;
+  if (gtype == G_TYPE_INVALID)
+    {
+      gtype = g_boxed_type_register_static ("MateMenuTreeEntry",
+          (GBoxedCopyFunc)matemenu_tree_item_ref,
+          (GBoxedFreeFunc)matemenu_tree_item_unref);
+    }
+  return gtype;
+}
+
+GType
+matemenu_tree_separator_get_type (void)
+{
+  static GType gtype = G_TYPE_INVALID;
+  if (gtype == G_TYPE_INVALID)
+    {
+      gtype = g_boxed_type_register_static ("MateMenuTreeSeparator",
+          (GBoxedCopyFunc)matemenu_tree_item_ref,
+          (GBoxedFreeFunc)matemenu_tree_item_unref);
+    }
+  return gtype;
+}
+
+GType
+matemenu_tree_header_get_type (void)
+{
+  static GType gtype = G_TYPE_INVALID;
+  if (gtype == G_TYPE_INVALID)
+    {
+      gtype = g_boxed_type_register_static ("MateMenuTreeHeader",
+          (GBoxedCopyFunc)matemenu_tree_item_ref,
+          (GBoxedFreeFunc)matemenu_tree_item_unref);
+    }
+  return gtype;
+}
+
+GType
+matemenu_tree_alias_get_type (void)
+{
+  static GType gtype = G_TYPE_INVALID;
+  if (gtype == G_TYPE_INVALID)
+    {
+      gtype = g_boxed_type_register_static ("MateMenuTreeAlias",
+          (GBoxedCopyFunc)matemenu_tree_item_ref,
+          (GBoxedFreeFunc)matemenu_tree_item_unref);
+    }
+  return gtype;
+}
+
+GType
+matemenu_tree_flags_get_type (void)
+{
+  static GType enum_type_id = 0;
+  if (G_UNLIKELY (!enum_type_id))
+    {
+      static const GFlagsValue values[] = {
+        { MATEMENU_TREE_FLAGS_NONE, "MATEMENU_TREE_FLAGS_NONE", "none" },
+        { MATEMENU_TREE_FLAGS_INCLUDE_EXCLUDED, "MATEMENU_TREE_FLAGS_INCLUDE_EXCLUDED", "include-excluded" },
+        { MATEMENU_TREE_FLAGS_SHOW_EMPTY, "MATEMENU_TREE_FLAGS_SHOW_EMPTY", "show-empty" },
+        { MATEMENU_TREE_FLAGS_INCLUDE_NODISPLAY, "MATEMENU_TREE_FLAGS_INCLUDE_NODISPLAY", "include-nodisplay" },
+        { MATEMENU_TREE_FLAGS_SHOW_ALL_SEPARATORS, "MATEMENU_TREE_FLAGS_SHOW_ALL_SEPARATORS", "show-all-separators" },
+        { MATEMENU_TREE_FLAGS_SORT_DISPLAY_NAME, "MATEMENU_TREE_FLAGS_SORT_DISPLAY_NAME", "sort-display-name" },
+        { MATEMENU_TREE_FLAGS_INCLUDE_UNALLOCATED, "MATEMENU_TREE_FLAGS_INCLUDE_UNALLOCATED,", "include-unallocated" },
+        { 0, NULL, NULL }
+      };
+      enum_type_id = g_flags_register_static ("MateMenuTreeFlags", values);
+    }
+  return enum_type_id;
+}
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/8.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/8.html new file mode 100644 index 0000000..c57d072 --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/8.html @@ -0,0 +1,563 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
/*
+ * Copyright (C) 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MATEMENU_TREE_H__
+#define __MATEMENU_TREE_H__
+
+#ifndef MATEMENU_I_KNOW_THIS_IS_UNSTABLE
+#error "libmate-menu should only be used if you understand that it's subject to frequent change, and is not supported as a fixed API/ABI or as part of the platform"
+#endif
+
+#include <gio/gdesktopappinfo.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+G_BEGIN_DECLS
+
+#define MATEMENU_TYPE_TREE         (matemenu_tree_get_type ())
+#define MATEMENU_TREE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), MATEMENU_TYPE_TREE, MateMenuTree))
+#define MATEMENU_TREE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), MATEMENU_TYPE_TREE, MateMenuTreeClass))
+#define MATEMENU_IS_TREE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATEMENU_TYPE_TREE))
+#define MATEMENU_IS_TREE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), MATEMENU_TYPE_TREE))
+#define MATEMENU_TREE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DESKTOP_APP_INFO, MateMenuTreeClass))
+
+typedef struct _MateMenuTree        MateMenuTree;
+typedef struct _MateMenuTreeClass   MateMenuTreeClass;
+
+struct _MateMenuTreeClass
+{
+  GObjectClass parent_class;
+};
+
+GType matemenu_tree_get_type (void) G_GNUC_CONST;
+
+typedef struct MateMenuTreeIter      MateMenuTreeIter;
+typedef struct MateMenuTreeDirectory MateMenuTreeDirectory;
+typedef struct MateMenuTreeEntry     MateMenuTreeEntry;
+typedef struct MateMenuTreeSeparator MateMenuTreeSeparator;
+typedef struct MateMenuTreeHeader    MateMenuTreeHeader;
+typedef struct MateMenuTreeAlias     MateMenuTreeAlias;
+
+typedef enum
+{
+  MATEMENU_TREE_ITEM_INVALID = 0,
+  MATEMENU_TREE_ITEM_DIRECTORY,
+  MATEMENU_TREE_ITEM_ENTRY,
+  MATEMENU_TREE_ITEM_SEPARATOR,
+  MATEMENU_TREE_ITEM_HEADER,
+  MATEMENU_TREE_ITEM_ALIAS
+} MateMenuTreeItemType;
+
+GType matemenu_tree_iter_get_type (void);
+
+/* Explicitly skip item, it's a "hidden" base class */
+GType matemenu_tree_directory_get_type (void);
+GType matemenu_tree_entry_get_type (void);
+GType matemenu_tree_separator_get_type (void);
+GType matemenu_tree_header_get_type (void);
+GType matemenu_tree_alias_get_type (void);
+
+typedef enum
+{
+  MATEMENU_TREE_FLAGS_NONE                = 0,
+  MATEMENU_TREE_FLAGS_INCLUDE_EXCLUDED    = 1 << 0,
+  MATEMENU_TREE_FLAGS_INCLUDE_NODISPLAY   = 1 << 1,
+  MATEMENU_TREE_FLAGS_INCLUDE_UNALLOCATED = 1 << 2,
+  /* leave some space for more include flags */
+  MATEMENU_TREE_FLAGS_SHOW_EMPTY          = 1 << 8,
+  MATEMENU_TREE_FLAGS_SHOW_ALL_SEPARATORS = 1 << 9,
+  /* leave some space for more show flags */
+  MATEMENU_TREE_FLAGS_SORT_DISPLAY_NAME   = 1 << 16
+} MateMenuTreeFlags;
+GType matemenu_tree_flags_get_type (void);
+#define MATEMENU_TYPE_TREE_FLAGS (matemenu_tree_flags_get_type ())
+
+MateMenuTree *matemenu_tree_new (const char     *menu_basename,
+                           MateMenuTreeFlags  flags);
+
+MateMenuTree *matemenu_tree_new_for_path (const char     *menu_path,
+                                    MateMenuTreeFlags  flags);
+
+gboolean   matemenu_tree_load_sync (MateMenuTree  *tree,
+                                 GError    **error);
+
+const char         *matemenu_tree_get_canonical_menu_path (MateMenuTree  *tree);
+MateMenuTreeDirectory *matemenu_tree_get_root_directory      (MateMenuTree  *tree);
+MateMenuTreeDirectory *matemenu_tree_get_directory_from_path (MateMenuTree  *tree,
+							const char *path);
+MateMenuTreeEntry     *matemenu_tree_get_entry_by_id         (MateMenuTree  *tree,
+							const char *id);
+
+gpointer matemenu_tree_item_ref   (gpointer item);
+void     matemenu_tree_item_unref (gpointer item);
+
+MateMenuTreeDirectory *matemenu_tree_directory_get_parent    (MateMenuTreeDirectory *directory);
+const char *matemenu_tree_directory_get_name              (MateMenuTreeDirectory *directory);
+const char *matemenu_tree_directory_get_generic_name      (MateMenuTreeDirectory *directory);
+const char *matemenu_tree_directory_get_comment           (MateMenuTreeDirectory *directory);
+GIcon      *matemenu_tree_directory_get_icon              (MateMenuTreeDirectory *directory);
+const char *matemenu_tree_directory_get_desktop_file_path (MateMenuTreeDirectory *directory);
+const char *matemenu_tree_directory_get_menu_id           (MateMenuTreeDirectory *directory);
+MateMenuTree  *matemenu_tree_directory_get_tree              (MateMenuTreeDirectory *directory);
+
+gboolean matemenu_tree_directory_get_is_nodisplay (MateMenuTreeDirectory *directory);
+
+MateMenuTreeIter      *matemenu_tree_directory_iter            (MateMenuTreeDirectory *directory);
+
+MateMenuTreeIter      *matemenu_tree_iter_ref                  (MateMenuTreeIter *iter);
+void                matemenu_tree_iter_unref                (MateMenuTreeIter *iter);
+
+MateMenuTreeItemType   matemenu_tree_iter_next                 (MateMenuTreeIter *iter);
+MateMenuTreeDirectory *matemenu_tree_iter_get_directory        (MateMenuTreeIter *iter);
+MateMenuTreeEntry     *matemenu_tree_iter_get_entry            (MateMenuTreeIter *iter);
+MateMenuTreeHeader    *matemenu_tree_iter_get_header           (MateMenuTreeIter *iter);
+MateMenuTreeAlias     *matemenu_tree_iter_get_alias            (MateMenuTreeIter *iter);
+MateMenuTreeSeparator *matemenu_tree_iter_get_separator        (MateMenuTreeIter *iter);
+
+char *matemenu_tree_directory_make_path (MateMenuTreeDirectory *directory,
+				      MateMenuTreeEntry     *entry);
+
+
+GDesktopAppInfo    *matemenu_tree_entry_get_app_info       (MateMenuTreeEntry *entry);
+MateMenuTreeDirectory *matemenu_tree_entry_get_parent         (MateMenuTreeEntry *entry);
+MateMenuTree          *matemenu_tree_entry_get_tree           (MateMenuTreeEntry *entry);
+
+const char *matemenu_tree_entry_get_desktop_file_path (MateMenuTreeEntry *entry);
+const char *matemenu_tree_entry_get_desktop_file_id   (MateMenuTreeEntry *entry);
+
+gboolean matemenu_tree_entry_get_is_nodisplay_recurse  (MateMenuTreeEntry *entry);
+gboolean matemenu_tree_entry_get_is_excluded  (MateMenuTreeEntry *entry);
+gboolean matemenu_tree_entry_get_is_unallocated  (MateMenuTreeEntry *entry);
+
+MateMenuTreeDirectory *matemenu_tree_header_get_directory (MateMenuTreeHeader *header);
+MateMenuTree          *matemenu_tree_header_get_tree      (MateMenuTreeHeader *header);
+MateMenuTreeDirectory *matemenu_tree_header_get_parent    (MateMenuTreeHeader *header);
+
+MateMenuTreeDirectory *matemenu_tree_alias_get_directory         (MateMenuTreeAlias *alias);
+MateMenuTreeItemType   matemenu_tree_alias_get_aliased_item_type (MateMenuTreeAlias *alias);
+MateMenuTreeDirectory *matemenu_tree_alias_get_aliased_directory (MateMenuTreeAlias *alias);
+MateMenuTreeEntry     *matemenu_tree_alias_get_aliased_entry     (MateMenuTreeAlias *alias);
+MateMenuTree          *matemenu_tree_alias_get_tree              (MateMenuTreeAlias *alias);
+MateMenuTreeDirectory *matemenu_tree_alias_get_parent            (MateMenuTreeAlias *alias);
+
+MateMenuTree          *matemenu_tree_separator_get_tree (MateMenuTreeSeparator *separator);
+MateMenuTreeDirectory *matemenu_tree_separator_get_parent (MateMenuTreeSeparator *separator);
+
+G_END_DECLS
+
+#endif /* __MATEMENU_TREE_H__ */
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/9.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/9.html new file mode 100644 index 0000000..4e5a440 --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/9.html @@ -0,0 +1,5217 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
+1951
+1952
+1953
+1954
+1955
+1956
+1957
+1958
+1959
+1960
+1961
+1962
+1963
+1964
+1965
+1966
+1967
+1968
+1969
+1970
+1971
+1972
+1973
+1974
+1975
+1976
+1977
+1978
+1979
+1980
+1981
+1982
+1983
+1984
+1985
+1986
+1987
+1988
+1989
+1990
+1991
+1992
+1993
+1994
+1995
+1996
+1997
+1998
+1999
+2000
+2001
+2002
+2003
+2004
+2005
+2006
+2007
+2008
+2009
+2010
+2011
+2012
+2013
+2014
+2015
+2016
+2017
+2018
+2019
+2020
+2021
+2022
+2023
+2024
+2025
+2026
+2027
+2028
+2029
+2030
+2031
+2032
+2033
+2034
+2035
+2036
+2037
+2038
+2039
+2040
+2041
+2042
+2043
+2044
+2045
+2046
+2047
+2048
+2049
+2050
+2051
+2052
+2053
+2054
+2055
+2056
+2057
+2058
+2059
+2060
+2061
+2062
+2063
+2064
+2065
+2066
+2067
+2068
+2069
+2070
+2071
+2072
+2073
+2074
+2075
+2076
+2077
+2078
+2079
+2080
+2081
+2082
+2083
+2084
+2085
+2086
+2087
+2088
+2089
+2090
+2091
+2092
+2093
+2094
+2095
+2096
+2097
+2098
+2099
+2100
+2101
+2102
+2103
+2104
+2105
+2106
+2107
+2108
+2109
+2110
+2111
+2112
+2113
+2114
+2115
+2116
+2117
+2118
+2119
+2120
+2121
+2122
+2123
+2124
+2125
+2126
+2127
+2128
+2129
+2130
+2131
+2132
+2133
+2134
+2135
+2136
+2137
+2138
+2139
+2140
+2141
+2142
+2143
+2144
+2145
+2146
+2147
+2148
+2149
+2150
+2151
+2152
+2153
+2154
+2155
+2156
+2157
+2158
+2159
+2160
+2161
+2162
+2163
+2164
+2165
+2166
+2167
+2168
+2169
+2170
+2171
+2172
+2173
+2174
+2175
+2176
+2177
+2178
+2179
+2180
+2181
+2182
+2183
+2184
+2185
+2186
+2187
+2188
+2189
+2190
+2191
+2192
+2193
+2194
+2195
+2196
+2197
+2198
+2199
+2200
+2201
+2202
+2203
+2204
+2205
+2206
+2207
+2208
+2209
+2210
+2211
+2212
+2213
+2214
+2215
+2216
+2217
+2218
+2219
+2220
+2221
+2222
+2223
+2224
+2225
+2226
+2227
+2228
+2229
+2230
+2231
+2232
+2233
+2234
+2235
+2236
+2237
+2238
+2239
+2240
+2241
+2242
+2243
+2244
+2245
+2246
+2247
+2248
+2249
+2250
+2251
+2252
+2253
+2254
+2255
+2256
+2257
+2258
+2259
+2260
+2261
+2262
+2263
+2264
+2265
+2266
+2267
+2268
+2269
+2270
+2271
+2272
+2273
+2274
+2275
+2276
+2277
+2278
+2279
+2280
+2281
+2282
+2283
+2284
+2285
+2286
+2287
+2288
+2289
+2290
+2291
+2292
+2293
+2294
+2295
+2296
+2297
+2298
+2299
+2300
+2301
+2302
+2303
+2304
+2305
+2306
+2307
+2308
+2309
+2310
+2311
+2312
+2313
+2314
+2315
+2316
+2317
+2318
+2319
+2320
+2321
+2322
+2323
+2324
+2325
+2326
+2327
+2328
+2329
+2330
+2331
+2332
+2333
+2334
+2335
+2336
+2337
+2338
+2339
+2340
+2341
+2342
+2343
+2344
+2345
+2346
+2347
+2348
+2349
+2350
+2351
+2352
+2353
+2354
+2355
+2356
+2357
+2358
+2359
+2360
+2361
+2362
+2363
+2364
+2365
+2366
+2367
+2368
+2369
+2370
+2371
+2372
+2373
+2374
+2375
+2376
+2377
+2378
+2379
+2380
+2381
+2382
+2383
+2384
+2385
+2386
+2387
+2388
+2389
+2390
+2391
+2392
+2393
+2394
+2395
/* Menu layout in-memory data structure (a custom "DOM tree") */
+
+/*
+ * Copyright (C) 2002 - 2004 Red Hat, Inc.
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "menu-layout.h"
+
+#include <string.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <stdio.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <stdlib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <unistd.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <errno.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "entry-directories.h"
+#include "menu-util.h"
+
+typedef struct MenuLayoutNodeMenu          MenuLayoutNodeMenu;
+typedef struct MenuLayoutNodeRoot          MenuLayoutNodeRoot;
+typedef struct MenuLayoutNodeLegacyDir     MenuLayoutNodeLegacyDir;
+typedef struct MenuLayoutNodeMergeFile     MenuLayoutNodeMergeFile;
+typedef struct MenuLayoutNodeDefaultLayout MenuLayoutNodeDefaultLayout;
+typedef struct MenuLayoutNodeMenuname      MenuLayoutNodeMenuname;
+typedef struct MenuLayoutNodeMerge         MenuLayoutNodeMerge;
+
+struct MenuLayoutNode
+{
+  /* Node lists are circular, for length-one lists
+   * prev/next point back to the node itself.
+   */
+  MenuLayoutNode *prev;
+  MenuLayoutNode *next;
+  MenuLayoutNode *parent;
+  MenuLayoutNode *children;
+
+  char *content;
+
+  guint refcount : 20;
+  guint type : 7;
+};
+
+struct MenuLayoutNodeRoot
+{
+  MenuLayoutNode node;
+
+  char *basedir;
+  char *name;
+
+  GMainContext *main_context;
+
+  GSList *monitors;
+  GSource *monitors_idle_handler;
+};
+
+struct MenuLayoutNodeMenu
+{
+  MenuLayoutNode node;
+
+  MenuLayoutNode *name_node; /* cache of the <Name> node */
+
+  EntryDirectoryList *app_dirs;
+  EntryDirectoryList *dir_dirs;
+};
+
+struct MenuLayoutNodeLegacyDir
+{
+  MenuLayoutNode node;
+
+  char *prefix;
+};
+
+struct MenuLayoutNodeMergeFile
+{
+  MenuLayoutNode node;
+
+  MenuMergeFileType type;
+};
+
+struct MenuLayoutNodeDefaultLayout
+{
+  MenuLayoutNode node;
+
+  MenuLayoutValues layout_values;
+};
+
+struct MenuLayoutNodeMenuname
+{
+  MenuLayoutNode node;
+
+  MenuLayoutValues layout_values;
+};
+
+struct MenuLayoutNodeMerge
+{
+  MenuLayoutNode node;
+
+  MenuLayoutMergeType merge_type;
+};
+
+typedef struct
+{
+  MenuLayoutNodeEntriesChangedFunc callback;
+  gpointer                         user_data;
+} MenuLayoutNodeEntriesMonitor;
+
+static inline MenuLayoutNode *
+node_next (MenuLayoutNode *node)<--- Parameter 'node' can be declared as pointer to const
+{
+  /* root nodes (no parent) never have siblings */
+  if (node->parent == NULL)
+    return NULL;
+
+  /* circular list */
+  if (node->next == node->parent->children)
+    return NULL;
+
+  return node->next;
+}
+
+static gboolean
+menu_layout_invoke_monitors (MenuLayoutNodeRoot *nr)
+{
+  GSList *tmp;
+
+  g_assert (nr->node.type == MENU_LAYOUT_NODE_ROOT);
+
+  nr->monitors_idle_handler = NULL;
+
+  tmp = nr->monitors;
+  while (tmp != NULL)
+    {
+      MenuLayoutNodeEntriesMonitor *monitor = tmp->data;
+      GSList                       *next    = tmp->next;
+
+      monitor->callback ((MenuLayoutNode *) nr, monitor->user_data);
+
+      tmp = next;
+    }
+
+  return FALSE;
+}
+
+static void
+handle_entry_directory_changed (EntryDirectory *dir,
+                                MenuLayoutNode *node)
+{
+  MenuLayoutNodeRoot *nr;
+
+  g_assert (node->type == MENU_LAYOUT_NODE_MENU);
+
+  nr = (MenuLayoutNodeRoot *) menu_layout_node_get_root (node);
+
+  if (nr->monitors_idle_handler == NULL)
+    {
+      nr->monitors_idle_handler = g_idle_source_new ();
+      g_source_set_callback (nr->monitors_idle_handler,
+                             (GSourceFunc) menu_layout_invoke_monitors, nr, NULL);
+      g_source_attach (nr->monitors_idle_handler, nr->main_context);
+      g_source_unref (nr->monitors_idle_handler);
+    }
+}
+
+static void
+remove_entry_directory_list (MenuLayoutNodeMenu  *nm,
+                             EntryDirectoryList **dirs)
+{
+  if (*dirs)
+    {
+      entry_directory_list_remove_monitors (*dirs,
+                                            (EntryDirectoryChangedFunc) handle_entry_directory_changed,
+                                            nm);
+      entry_directory_list_unref (*dirs);
+      *dirs = NULL;
+    }
+}
+
+MenuLayoutNode *
+menu_layout_node_ref (MenuLayoutNode *node)
+{
+  g_return_val_if_fail (node != NULL, NULL);
+
+  node->refcount += 1;
+
+  return node;
+}
+
+void
+menu_layout_node_unref (MenuLayoutNode *node)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (node->refcount > 0);
+
+  node->refcount -= 1;
+  if (node->refcount == 0)
+    {
+      MenuLayoutNode *iter;
+
+      iter = node->children;
+      while (iter != NULL)
+        {
+          MenuLayoutNode *next = node_next (iter);
+
+          menu_layout_node_unref (iter);
+
+          iter = next;
+        }
+
+      if (node->type == MENU_LAYOUT_NODE_MENU)
+        {
+          MenuLayoutNodeMenu *nm = (MenuLayoutNodeMenu *) node;
+
+          if (nm->name_node)
+            menu_layout_node_unref (nm->name_node);
+
+          remove_entry_directory_list (nm, &nm->app_dirs);
+          remove_entry_directory_list (nm, &nm->dir_dirs);
+        }
+      else if (node->type == MENU_LAYOUT_NODE_LEGACY_DIR)
+        {
+          MenuLayoutNodeLegacyDir *legacy = (MenuLayoutNodeLegacyDir *) node;
+
+          g_free (legacy->prefix);
+        }
+      else if (node->type == MENU_LAYOUT_NODE_ROOT)
+        {
+          MenuLayoutNodeRoot *nr = (MenuLayoutNodeRoot*) node;
+
+          g_slist_foreach (nr->monitors, (GFunc) g_free, NULL);
+          g_slist_free (nr->monitors);
+
+          if (nr->monitors_idle_handler != NULL)
+            g_source_destroy (nr->monitors_idle_handler);
+          nr->monitors_idle_handler = NULL;
+
+          if (nr->main_context != NULL)
+            g_main_context_unref (nr->main_context);
+          nr->main_context = NULL;
+
+          g_free (nr->basedir);
+          g_free (nr->name);
+        }
+
+      g_free (node->content);
+      g_free (node);
+    }
+}
+
+MenuLayoutNode *
+menu_layout_node_new (MenuLayoutNodeType type)
+{
+  MenuLayoutNode *node;
+
+  switch (type)
+    {
+    case MENU_LAYOUT_NODE_MENU:
+      node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMenu, 1);
+      break;
+
+    case MENU_LAYOUT_NODE_LEGACY_DIR:
+      node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeLegacyDir, 1);
+      break;
+
+    case MENU_LAYOUT_NODE_ROOT:
+      node = (MenuLayoutNode*) g_new0 (MenuLayoutNodeRoot, 1);
+      break;
+
+    case MENU_LAYOUT_NODE_MERGE_FILE:
+      node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMergeFile, 1);
+      break;
+
+    case MENU_LAYOUT_NODE_DEFAULT_LAYOUT:
+      node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeDefaultLayout, 1);
+      break;
+
+    case MENU_LAYOUT_NODE_MENUNAME:
+      node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMenuname, 1);
+      break;
+
+    case MENU_LAYOUT_NODE_MERGE:
+      node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMerge, 1);
+      break;
+
+    default:
+      node = g_new0 (MenuLayoutNode, 1);
+      break;
+    }
+
+  node->type = type;
+
+  node->refcount = 1;
+
+  /* we're in a list of one node */
+  node->next = node;
+  node->prev = node;
+
+  return node;
+}
+
+MenuLayoutNode *
+menu_layout_node_get_next (MenuLayoutNode *node)
+{
+  return node_next (node);
+}
+
+MenuLayoutNode *
+menu_layout_node_get_parent (MenuLayoutNode *node)<--- Parameter 'node' can be declared as pointer to const
+{
+  return node->parent;
+}
+
+MenuLayoutNode *
+menu_layout_node_get_children (MenuLayoutNode *node)<--- Parameter 'node' can be declared as pointer to const
+{
+  return node->children;
+}
+
+MenuLayoutNode *
+menu_layout_node_get_root (MenuLayoutNode *node)
+{
+  MenuLayoutNode *parent;
+
+  parent = node;
+  while (parent->parent != NULL)
+    parent = parent->parent;
+
+  g_assert (parent->type == MENU_LAYOUT_NODE_ROOT);
+
+  return parent;
+}
+
+char *
+menu_layout_node_get_content_as_path (MenuLayoutNode *node)
+{
+  if (node->content == NULL)
+    {
+      menu_verbose ("  (node has no content to get as a path)\n");
+      return NULL;
+    }
+
+  if (g_path_is_absolute (node->content))
+    {
+      return g_strdup (node->content);
+    }
+  else
+    {
+      MenuLayoutNodeRoot *root;
+
+      root = (MenuLayoutNodeRoot *) menu_layout_node_get_root (node);
+
+      if (root->basedir == NULL)
+        {
+          menu_verbose ("No basedir available, using \"%s\" as-is\n",
+                        node->content);
+          return g_strdup (node->content);
+        }
+      else
+        {
+          menu_verbose ("Using basedir \"%s\" filename \"%s\"\n",
+                        root->basedir, node->content);
+          return g_build_filename (root->basedir, node->content, NULL);
+        }
+    }
+}
+
+#define RETURN_IF_NO_PARENT(node) G_STMT_START {                  \
+    if ((node)->parent == NULL)                                   \
+      {                                                           \
+        g_warning ("To add siblings to a menu node, "             \
+                   "it must not be the root node, "               \
+                   "and must be linked in below some root node\n" \
+                   "node parent = %p and type = %d",              \
+                   (node)->parent, (node)->type);                 \
+        return;                                                   \
+      }                                                           \
+  } G_STMT_END
+
+#define RETURN_IF_HAS_ENTRY_DIRS(node) G_STMT_START {             \
+    if ((node)->type == MENU_LAYOUT_NODE_MENU &&                  \
+        (((MenuLayoutNodeMenu*)(node))->app_dirs != NULL ||       \
+         ((MenuLayoutNodeMenu*)(node))->dir_dirs != NULL))        \
+      {                                                           \
+        g_warning ("node acquired ->app_dirs or ->dir_dirs "      \
+                   "while not rooted in a tree\n");               \
+        return;                                                   \
+      }                                                           \
+  } G_STMT_END                                                    \
+
+void
+menu_layout_node_insert_before (MenuLayoutNode *node,
+                                MenuLayoutNode *new_sibling)
+{
+  g_return_if_fail (new_sibling != NULL);
+  g_return_if_fail (new_sibling->parent == NULL);
+
+  RETURN_IF_NO_PARENT (node);
+  RETURN_IF_HAS_ENTRY_DIRS (new_sibling);
+
+  new_sibling->next = node;
+  new_sibling->prev = node->prev;
+
+  node->prev = new_sibling;
+  new_sibling->prev->next = new_sibling;
+
+  new_sibling->parent = node->parent;
+
+  if (node == node->parent->children)
+    node->parent->children = new_sibling;
+
+  menu_layout_node_ref (new_sibling);
+}
+
+void
+menu_layout_node_insert_after (MenuLayoutNode *node,
+                               MenuLayoutNode *new_sibling)
+{
+  g_return_if_fail (new_sibling != NULL);
+  g_return_if_fail (new_sibling->parent == NULL);
+
+  RETURN_IF_NO_PARENT (node);
+  RETURN_IF_HAS_ENTRY_DIRS (new_sibling);
+
+  new_sibling->prev = node;
+  new_sibling->next = node->next;
+
+  node->next = new_sibling;
+  new_sibling->next->prev = new_sibling;
+
+  new_sibling->parent = node->parent;
+
+  menu_layout_node_ref (new_sibling);
+}
+
+void
+menu_layout_node_prepend_child (MenuLayoutNode *parent,
+                                MenuLayoutNode *new_child)
+{
+  RETURN_IF_HAS_ENTRY_DIRS (new_child);
+
+  if (parent->children)
+    {
+      menu_layout_node_insert_before (parent->children, new_child);
+    }
+  else
+    {
+      parent->children = menu_layout_node_ref (new_child);
+      new_child->parent = parent;
+    }
+}
+
+void
+menu_layout_node_append_child (MenuLayoutNode *parent,
+                               MenuLayoutNode *new_child)
+{
+  RETURN_IF_HAS_ENTRY_DIRS (new_child);
+
+  if (parent->children)
+    {
+      menu_layout_node_insert_after (parent->children->prev, new_child);
+    }
+  else
+    {
+      parent->children = menu_layout_node_ref (new_child);
+      new_child->parent = parent;
+    }
+}
+
+void
+menu_layout_node_unlink (MenuLayoutNode *node)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (node->parent != NULL);
+
+  menu_layout_node_steal (node);
+  menu_layout_node_unref (node);
+}
+
+static void
+recursive_clean_entry_directory_lists (MenuLayoutNode *node,
+                                       gboolean        apps)
+{
+  EntryDirectoryList **dirs;
+  MenuLayoutNodeMenu  *nm;
+  MenuLayoutNode      *iter;
+
+  if (node->type != MENU_LAYOUT_NODE_MENU)
+    return;
+
+  nm = (MenuLayoutNodeMenu *) node;
+
+  dirs = apps ? &nm->app_dirs : &nm->dir_dirs;
+
+  if (*dirs == NULL || entry_directory_list_get_length (*dirs) == 0)
+    return; /* child menus continue to have valid lists */
+
+  remove_entry_directory_list (nm, dirs);
+
+  iter = node->children;
+  while (iter != NULL)
+    {
+      if (iter->type == MENU_LAYOUT_NODE_MENU)
+        recursive_clean_entry_directory_lists (iter, apps);
+
+      iter = node_next (iter);
+    }
+}
+
+void
+menu_layout_node_steal (MenuLayoutNode *node)
+{
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (node->parent != NULL);
+
+  switch (node->type)
+    {
+    case MENU_LAYOUT_NODE_NAME:
+      {
+        MenuLayoutNodeMenu *nm = (MenuLayoutNodeMenu *) node->parent;
+
+        if (nm->name_node == node)
+          {
+            menu_layout_node_unref (nm->name_node);
+            nm->name_node = NULL;
+          }
+      }
+      break;
+
+    case MENU_LAYOUT_NODE_APP_DIR:
+      recursive_clean_entry_directory_lists (node->parent, TRUE);
+      break;
+
+    case MENU_LAYOUT_NODE_DIRECTORY_DIR:
+      recursive_clean_entry_directory_lists (node->parent, FALSE);
+      break;
+
+    default:
+      break;
+    }
+
+  if (node->parent && node->parent->children == node)
+    {
+      if (node->next != node)
+        node->parent->children = node->next;
+      else
+        node->parent->children = NULL;
+    }
+
+  /* these are no-ops for length-one node lists */
+  node->prev->next = node->next;
+  node->next->prev = node->prev;
+
+  node->parent = NULL;
+
+  /* point to ourselves, now we're length one */
+  node->next = node;
+  node->prev = node;
+}
+
+MenuLayoutNodeType
+menu_layout_node_get_type (MenuLayoutNode *node)<--- Parameter 'node' can be declared as pointer to const
+{
+  return node->type;
+}
+
+const char *
+menu_layout_node_get_content (MenuLayoutNode *node)<--- Parameter 'node' can be declared as pointer to const
+{
+  return node->content;
+}
+
+void
+menu_layout_node_set_content (MenuLayoutNode *node,
+                              const char     *content)
+{
+  if (node->content == content)
+    return;
+
+  g_free (node->content);
+  node->content = g_strdup (content);
+}
+
+const char *
+menu_layout_node_root_get_name (MenuLayoutNode *node)
+{
+  MenuLayoutNodeRoot *nr;<--- Variable 'nr' can be declared as pointer to const
+
+  g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_ROOT, NULL);
+
+  nr = (MenuLayoutNodeRoot*) node;
+
+  return nr->name;
+}
+
+const char *
+menu_layout_node_root_get_basedir (MenuLayoutNode *node)
+{
+  MenuLayoutNodeRoot *nr;<--- Variable 'nr' can be declared as pointer to const
+
+  g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_ROOT, NULL);
+
+  nr = (MenuLayoutNodeRoot*) node;
+
+  return nr->basedir;
+}
+
+const char *
+menu_layout_node_menu_get_name (MenuLayoutNode *node)
+{
+  MenuLayoutNodeMenu *nm;
+
+  g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MENU, NULL);
+
+  nm = (MenuLayoutNodeMenu*) node;
+
+  if (nm->name_node == NULL)
+    {
+      MenuLayoutNode *iter;
+
+      iter = node->children;
+      while (iter != NULL)
+        {
+          if (iter->type == MENU_LAYOUT_NODE_NAME)
+            {
+              nm->name_node = menu_layout_node_ref (iter);
+              break;
+            }
+
+          iter = node_next (iter);
+        }
+    }
+
+  if (nm->name_node == NULL)
+    return NULL;
+
+  return menu_layout_node_get_content (nm->name_node);
+}
+
+static void
+ensure_dir_lists (MenuLayoutNodeMenu *nm)
+{
+  MenuLayoutNode     *node;
+  MenuLayoutNode     *iter;
+  EntryDirectoryList *app_dirs;
+  EntryDirectoryList *dir_dirs;
+
+  node = (MenuLayoutNode *) nm;
+
+  if (nm->app_dirs && nm->dir_dirs)
+    return;
+
+  app_dirs = NULL;
+  dir_dirs = NULL;
+
+  if (nm->app_dirs == NULL)
+    {
+      app_dirs = entry_directory_list_new ();
+
+      if (node->parent && node->parent->type == MENU_LAYOUT_NODE_MENU)
+        {
+          EntryDirectoryList *dirs;
+
+          if ((dirs = menu_layout_node_menu_get_app_dirs (node->parent)))
+            entry_directory_list_append_list (app_dirs, dirs);
+        }
+    }
+
+  if (nm->dir_dirs == NULL)
+    {
+      dir_dirs = entry_directory_list_new ();
+
+      if (node->parent && node->parent->type == MENU_LAYOUT_NODE_MENU)
+        {
+          EntryDirectoryList *dirs;
+
+          if ((dirs = menu_layout_node_menu_get_directory_dirs (node->parent)))
+            entry_directory_list_append_list (dir_dirs, dirs);
+        }
+    }
+
+  iter = node->children;
+  while (iter != NULL)
+    {
+      EntryDirectory *ed;
+
+      if (app_dirs != NULL && iter->type == MENU_LAYOUT_NODE_APP_DIR)
+        {
+          char *path;
+
+          path = menu_layout_node_get_content_as_path (iter);
+
+          ed = entry_directory_new (DESKTOP_ENTRY_DESKTOP, path);
+          if (ed != NULL)
+            {
+              entry_directory_list_prepend (app_dirs, ed);
+              entry_directory_unref (ed);
+            }
+
+          g_free (path);
+        }
+
+      if (dir_dirs != NULL && iter->type == MENU_LAYOUT_NODE_DIRECTORY_DIR)
+        {
+          char *path;
+
+          path = menu_layout_node_get_content_as_path (iter);
+
+          ed = entry_directory_new (DESKTOP_ENTRY_DIRECTORY, path);
+          if (ed != NULL)
+            {
+              entry_directory_list_prepend (dir_dirs, ed);
+              entry_directory_unref (ed);
+            }
+
+          g_free (path);
+        }
+
+      if (iter->type == MENU_LAYOUT_NODE_LEGACY_DIR)
+        {
+          MenuLayoutNodeLegacyDir *legacy = (MenuLayoutNodeLegacyDir *) iter;<--- Variable 'legacy' can be declared as pointer to const
+          char                    *path;
+
+          path = menu_layout_node_get_content_as_path (iter);
+
+          if (app_dirs != NULL) /* we're loading app dirs */
+            {
+              ed = entry_directory_new_legacy (DESKTOP_ENTRY_DESKTOP,
+                                               path,
+                                               legacy->prefix);
+              if (ed != NULL)
+                {
+                  entry_directory_list_prepend (app_dirs, ed);
+                  entry_directory_unref (ed);
+                }
+            }
+
+          if (dir_dirs != NULL) /* we're loading dir dirs */
+            {
+              ed = entry_directory_new_legacy (DESKTOP_ENTRY_DIRECTORY,
+                                               path,
+                                               legacy->prefix);
+              if (ed != NULL)
+                {
+                  entry_directory_list_prepend (dir_dirs, ed);
+                  entry_directory_unref (ed);
+                }
+            }
+
+          g_free (path);
+        }
+
+      iter = node_next (iter);
+    }
+
+  if (app_dirs)
+    {
+      g_assert (nm->app_dirs == NULL);
+
+      nm->app_dirs = app_dirs;
+      entry_directory_list_add_monitors (nm->app_dirs,
+                                         (EntryDirectoryChangedFunc) handle_entry_directory_changed,
+                                         nm);
+    }
+
+  if (dir_dirs)
+    {
+      g_assert (nm->dir_dirs == NULL);
+
+      nm->dir_dirs = dir_dirs;
+      entry_directory_list_add_monitors (nm->dir_dirs,
+                                         (EntryDirectoryChangedFunc) handle_entry_directory_changed,
+                                         nm);
+    }
+}
+
+EntryDirectoryList *
+menu_layout_node_menu_get_app_dirs (MenuLayoutNode *node)
+{
+  MenuLayoutNodeMenu *nm;
+
+  g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MENU, NULL);
+
+  nm = (MenuLayoutNodeMenu *) node;
+
+  ensure_dir_lists (nm);
+
+  return nm->app_dirs;
+}
+
+EntryDirectoryList *
+menu_layout_node_menu_get_directory_dirs (MenuLayoutNode *node)
+{
+  MenuLayoutNodeMenu *nm;
+
+  g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MENU, NULL);
+
+  nm = (MenuLayoutNodeMenu *) node;
+
+  ensure_dir_lists (nm);
+
+  return nm->dir_dirs;
+}
+
+const char *
+menu_layout_node_move_get_old (MenuLayoutNode *node)<--- Parameter 'node' can be declared as pointer to const
+{
+  MenuLayoutNode *iter;
+
+  iter = node->children;
+  while (iter != NULL)
+    {
+      if (iter->type == MENU_LAYOUT_NODE_OLD)
+        return iter->content;
+
+      iter = node_next (iter);
+    }
+
+  return NULL;
+}
+
+const char *
+menu_layout_node_move_get_new (MenuLayoutNode *node)<--- Parameter 'node' can be declared as pointer to const
+{
+  MenuLayoutNode *iter;
+
+  iter = node->children;
+  while (iter != NULL)
+    {
+      if (iter->type == MENU_LAYOUT_NODE_NEW)
+        return iter->content;
+
+      iter = node_next (iter);
+    }
+
+  return NULL;
+}
+
+const char *
+menu_layout_node_legacy_dir_get_prefix (MenuLayoutNode *node)
+{
+  MenuLayoutNodeLegacyDir *legacy;<--- Variable 'legacy' can be declared as pointer to const
+
+  g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_LEGACY_DIR, NULL);
+
+  legacy = (MenuLayoutNodeLegacyDir *) node;
+
+  return legacy->prefix;
+}
+
+void
+menu_layout_node_legacy_dir_set_prefix (MenuLayoutNode *node,
+                                        const char     *prefix)
+{
+  MenuLayoutNodeLegacyDir *legacy;
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_LEGACY_DIR);
+
+  legacy = (MenuLayoutNodeLegacyDir *) node;
+
+  g_free (legacy->prefix);
+  legacy->prefix = g_strdup (prefix);
+}
+
+MenuMergeFileType
+menu_layout_node_merge_file_get_type (MenuLayoutNode *node)
+{
+  MenuLayoutNodeMergeFile *merge_file;<--- Variable 'merge_file' can be declared as pointer to const
+
+  g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MERGE_FILE, FALSE);
+
+  merge_file = (MenuLayoutNodeMergeFile *) node;
+
+  return merge_file->type;
+}
+
+void
+menu_layout_node_merge_file_set_type (MenuLayoutNode    *node,
+				      MenuMergeFileType  type)
+{
+  MenuLayoutNodeMergeFile *merge_file;
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_MERGE_FILE);
+
+  merge_file = (MenuLayoutNodeMergeFile *) node;
+
+  merge_file->type = type;
+}
+
+MenuLayoutMergeType
+menu_layout_node_merge_get_type (MenuLayoutNode *node)
+{
+  MenuLayoutNodeMerge *merge;<--- Variable 'merge' can be declared as pointer to const
+
+  g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MERGE, 0);
+
+  merge = (MenuLayoutNodeMerge *) node;
+
+  return merge->merge_type;
+}
+
+static void
+menu_layout_node_merge_set_type (MenuLayoutNode *node,
+                                 const char     *merge_type)
+{
+  MenuLayoutNodeMerge *merge;
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_MERGE);
+
+  merge = (MenuLayoutNodeMerge *) node;
+
+  merge->merge_type = MENU_LAYOUT_MERGE_NONE;
+
+  if (strcmp (merge_type, "menus") == 0)
+    {
+      merge->merge_type = MENU_LAYOUT_MERGE_MENUS;
+    }
+  else if (strcmp (merge_type, "files") == 0)
+    {
+      merge->merge_type = MENU_LAYOUT_MERGE_FILES;
+    }
+  else if (strcmp (merge_type, "all") == 0)
+    {
+      merge->merge_type = MENU_LAYOUT_MERGE_ALL;
+    }
+}
+
+void
+menu_layout_node_default_layout_get_values (MenuLayoutNode   *node,
+					    MenuLayoutValues *values)
+{
+  MenuLayoutNodeDefaultLayout *default_layout;<--- Variable 'default_layout' can be declared as pointer to const
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_DEFAULT_LAYOUT);
+  g_return_if_fail (values != NULL);
+
+  default_layout = (MenuLayoutNodeDefaultLayout *) node;
+
+  *values = default_layout->layout_values;
+}
+
+void
+menu_layout_node_menuname_get_values (MenuLayoutNode   *node,
+				      MenuLayoutValues *values)
+{
+  MenuLayoutNodeMenuname *menuname;<--- Variable 'menuname' can be declared as pointer to const
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_MENUNAME);
+  g_return_if_fail (values != NULL);
+
+  menuname = (MenuLayoutNodeMenuname *) node;
+
+  *values = menuname->layout_values;
+}
+
+static void
+menu_layout_values_set (MenuLayoutValues *values,
+			const char       *show_empty,
+			const char       *inline_menus,
+			const char       *inline_limit,
+			const char       *inline_header,
+			const char       *inline_alias)
+{
+  values->mask          = MENU_LAYOUT_VALUES_NONE;
+  values->show_empty    = FALSE;
+  values->inline_menus  = FALSE;
+  values->inline_limit  = 4;
+  values->inline_header = FALSE;
+  values->inline_alias  = FALSE;
+
+  if (show_empty != NULL)
+    {
+      values->show_empty = strcmp (show_empty, "true") == 0;
+      values->mask |= MENU_LAYOUT_VALUES_SHOW_EMPTY;
+    }
+
+  if (inline_menus != NULL)
+    {
+      values->inline_menus = strcmp (inline_menus, "true") == 0;
+      values->mask |= MENU_LAYOUT_VALUES_INLINE_MENUS;
+    }
+
+  if (inline_limit != NULL)
+    {
+      char *end;
+      unsigned long limit;
+
+      limit = strtoul (inline_limit, &end, 10);
+      if (*end == '\0')
+	{
+	  values->inline_limit = (guint) limit;
+	  values->mask |= MENU_LAYOUT_VALUES_INLINE_LIMIT;
+	}
+    }
+
+  if (inline_header != NULL)
+    {
+      values->inline_header = strcmp (inline_header, "true") == 0;
+      values->mask |= MENU_LAYOUT_VALUES_INLINE_HEADER;
+    }
+
+  if (inline_alias != NULL)
+    {
+      values->inline_alias = strcmp (inline_alias, "true") == 0;
+      values->mask |= MENU_LAYOUT_VALUES_INLINE_ALIAS;
+    }
+}
+
+static void
+menu_layout_node_default_layout_set_values (MenuLayoutNode *node,
+					    const char     *show_empty,
+					    const char     *inline_menus,
+					    const char     *inline_limit,
+					    const char     *inline_header,
+					    const char     *inline_alias)
+{
+  MenuLayoutNodeDefaultLayout *default_layout;
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_DEFAULT_LAYOUT);
+
+  default_layout = (MenuLayoutNodeDefaultLayout *) node;
+
+  menu_layout_values_set (&default_layout->layout_values,
+			  show_empty,
+			  inline_menus,
+			  inline_limit,
+			  inline_header,
+			  inline_alias);
+}
+
+static void
+menu_layout_node_menuname_set_values (MenuLayoutNode *node,
+				      const char     *show_empty,
+				      const char     *inline_menus,
+				      const char     *inline_limit,
+				      const char     *inline_header,
+				      const char     *inline_alias)
+{
+  MenuLayoutNodeMenuname *menuname;
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_MENUNAME);
+
+  menuname = (MenuLayoutNodeMenuname *) node;
+
+  menu_layout_values_set (&menuname->layout_values,
+			  show_empty,
+			  inline_menus,
+			  inline_limit,
+			  inline_header,
+			  inline_alias);
+}
+
+void
+menu_layout_node_root_add_entries_monitor (MenuLayoutNode                   *node,
+                                           MenuLayoutNodeEntriesChangedFunc  callback,
+                                           gpointer                          user_data)
+{
+  MenuLayoutNodeEntriesMonitor *monitor;
+  MenuLayoutNodeRoot           *nr;
+  GSList                       *tmp;<--- Variable 'tmp' can be declared as pointer to const
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_ROOT);
+
+  nr = (MenuLayoutNodeRoot *) node;
+
+  tmp = nr->monitors;
+  while (tmp != NULL)
+    {
+      monitor = tmp->data;
+
+      if (monitor->callback  == callback &&
+          monitor->user_data == user_data)
+        break;
+
+      tmp = tmp->next;
+    }
+
+  if (tmp == NULL)
+    {
+      monitor            = g_new0 (MenuLayoutNodeEntriesMonitor, 1);
+      monitor->callback  = callback;
+      monitor->user_data = user_data;
+
+      nr->monitors = g_slist_append (nr->monitors, monitor);
+    }
+}
+
+void
+menu_layout_node_root_remove_entries_monitor (MenuLayoutNode                   *node,
+                                              MenuLayoutNodeEntriesChangedFunc  callback,
+                                              gpointer                          user_data)
+{
+  MenuLayoutNodeRoot *nr;
+  GSList             *tmp;
+
+  g_return_if_fail (node->type == MENU_LAYOUT_NODE_ROOT);
+
+  nr = (MenuLayoutNodeRoot *) node;
+
+  tmp = nr->monitors;
+  while (tmp != NULL)
+    {
+      MenuLayoutNodeEntriesMonitor *monitor = tmp->data;
+      GSList                       *next = tmp->next;
+
+      if (monitor->callback == callback &&
+          monitor->user_data == user_data)
+        {
+          nr->monitors = g_slist_delete_link (nr->monitors, tmp);
+          g_free (monitor);
+        }
+
+      tmp = next;
+    }
+}
+
+/*
+ * Menu file parsing
+ */
+
+typedef struct
+{
+  MenuLayoutNode *root;
+  MenuLayoutNode *stack_top;
+} MenuParser;
+
+static void set_error (GError             **err,
+                       GMarkupParseContext *context,
+                       GQuark               error_domain,
+                       int                  error_code,
+                       const char          *format,
+                       ...) G_GNUC_PRINTF (5, 6);
+
+static void add_context_to_error (GError             **err,
+                                  GMarkupParseContext *context);
+
+static void start_element_handler (GMarkupParseContext  *context,
+                                   const char           *element_name,
+                                   const char          **attribute_names,
+                                   const char          **attribute_values,
+                                   gpointer              user_data,
+                                   GError              **error);
+static void end_element_handler   (GMarkupParseContext  *context,
+                                   const char           *element_name,
+                                   gpointer              user_data,
+                                   GError              **error);
+static void text_handler          (GMarkupParseContext  *context,
+                                   const char           *text,
+                                   gsize                 text_len,
+                                   gpointer              user_data,
+                                   GError              **error);
+static void passthrough_handler   (GMarkupParseContext  *context,
+                                   const char           *passthrough_text,
+                                   gsize                 text_len,
+                                   gpointer              user_data,
+                                   GError              **error);
+
+static GMarkupParser menu_funcs = {
+  start_element_handler,
+  end_element_handler,
+  text_handler,
+  passthrough_handler,
+  NULL
+};
+
+static void
+set_error (GError              **err,
+           GMarkupParseContext  *context,
+           GQuark                error_domain,
+           int                   error_code,
+           const char           *format,
+           ...)
+{
+  int      line, ch;
+  va_list  args;
+  char    *str;
+
+  g_markup_parse_context_get_position (context, &line, &ch);
+
+  va_start (args, format);
+  str = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  g_set_error (err, error_domain, error_code,
+               "Line %d character %d: %s",
+               line, ch, str);
+
+  g_free (str);
+}
+
+static void
+add_context_to_error (GError             **err,
+                      GMarkupParseContext *context)
+{
+  int   line, ch;
+  char *str;
+
+  if (err == NULL || *err == NULL)
+    return;
+
+  g_markup_parse_context_get_position (context, &line, &ch);
+
+  str = g_strdup_printf ("Line %d character %d: %s",
+                         line, ch, (*err)->message);
+  g_free ((*err)->message);
+  (*err)->message = str;
+}
+
+#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0)
+
+typedef struct
+{
+  const char  *name;
+  const char **retloc;
+} LocateAttr;
+
+static gboolean
+locate_attributes (GMarkupParseContext  *context,
+                   const char           *element_name,
+                   const char          **attribute_names,
+                   const char          **attribute_values,
+                   GError              **error,
+                   const char           *first_attribute_name,
+                   const char          **first_attribute_retloc,
+                   ...)
+{
+#define MAX_ATTRS 24
+  LocateAttr   attrs[MAX_ATTRS];
+  int          n_attrs;
+  va_list      args;
+  const char  *name;
+  const char **retloc;
+  gboolean     retval;
+  int          i;
+
+  g_return_val_if_fail (first_attribute_name != NULL, FALSE);
+  g_return_val_if_fail (first_attribute_retloc != NULL, FALSE);
+
+  retval = TRUE;
+
+  n_attrs = 1;
+  attrs[0].name = first_attribute_name;
+  attrs[0].retloc = first_attribute_retloc;
+  *first_attribute_retloc = NULL;
+
+  va_start (args, first_attribute_retloc);
+
+  name = va_arg (args, const char *);
+  retloc = va_arg (args, const char **);
+
+  while (name != NULL)
+    {
+      g_return_val_if_fail (retloc != NULL, FALSE);
+
+      g_assert (n_attrs < MAX_ATTRS);
+
+      attrs[n_attrs].name = name;
+      attrs[n_attrs].retloc = retloc;
+      n_attrs += 1;
+      *retloc = NULL;
+
+      name = va_arg (args, const char *);
+      retloc = va_arg (args, const char **);
+    }
+
+  va_end (args);
+
+  i = 0;
+  while (attribute_names[i])
+    {
+      int j;
+
+      j = 0;
+      while (j < n_attrs)
+        {
+          if (strcmp (attrs[j].name, attribute_names[i]) == 0)
+            {
+              retloc = attrs[j].retloc;
+
+              if (*retloc != NULL)
+                {
+                  set_error (error, context,
+                             G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                             "Attribute \"%s\" repeated twice on the same <%s> element",
+                             attrs[j].name, element_name);
+                  retval = FALSE;
+                  goto out;
+                }
+
+              *retloc = attribute_values[i];
+              break;
+            }
+
+          ++j;
+        }
+
+      if (j == n_attrs)
+        {
+          set_error (error, context,
+                     G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                     "Attribute \"%s\" is invalid on <%s> element in this context",
+                     attribute_names[i], element_name);
+          retval = FALSE;
+          goto out;
+        }
+
+      ++i;
+    }
+
+ out:
+  return retval;
+
+#undef MAX_ATTRS
+}
+
+static gboolean
+check_no_attributes (GMarkupParseContext  *context,
+                     const char           *element_name,
+                     const char          **attribute_names,
+                     const char          **attribute_values,
+                     GError              **error)
+{
+  if (attribute_names[0] != NULL)
+    {
+      set_error (error, context,
+                 G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                 "Attribute \"%s\" is invalid on <%s> element in this context",
+                 attribute_names[0], element_name);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static int
+has_child_of_type (MenuLayoutNode     *node,<--- Parameter 'node' can be declared as pointer to const
+                   MenuLayoutNodeType  type)
+{
+  MenuLayoutNode *iter;
+
+  iter = node->children;
+  while (iter)
+    {
+      if (iter->type == type)
+        return TRUE;
+
+      iter = node_next (iter);
+    }
+
+  return FALSE;
+}
+
+static void
+push_node (MenuParser         *parser,
+           MenuLayoutNodeType  type)
+{
+  MenuLayoutNode *node;
+
+  node = menu_layout_node_new (type);
+  menu_layout_node_append_child (parser->stack_top, node);
+  menu_layout_node_unref (node);
+
+  parser->stack_top = node;
+}
+
+static void
+start_menu_element (MenuParser           *parser,
+                    GMarkupParseContext  *context,
+                    const char           *element_name,
+                    const char          **attribute_names,
+                    const char          **attribute_values,
+                    GError              **error)
+{
+  if (!check_no_attributes (context, element_name,
+                            attribute_names, attribute_values,
+                            error))
+    return;
+
+  if (!(parser->stack_top->type == MENU_LAYOUT_NODE_ROOT ||
+        parser->stack_top->type == MENU_LAYOUT_NODE_MENU))
+    {
+      set_error (error, context,
+                 G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                 "<Menu> element can only appear below other <Menu> elements or at toplevel\n");
+    }
+  else
+    {
+      push_node (parser, MENU_LAYOUT_NODE_MENU);
+    }
+}
+
+static void
+start_menu_child_element (MenuParser           *parser,
+                          GMarkupParseContext  *context,
+                          const char           *element_name,
+                          const char          **attribute_names,
+                          const char          **attribute_values,
+                          GError              **error)
+{
+  if (ELEMENT_IS ("LegacyDir"))
+    {
+      const char *prefix;
+
+      push_node (parser, MENU_LAYOUT_NODE_LEGACY_DIR);
+
+      if (!locate_attributes (context, element_name,
+                              attribute_names, attribute_values,
+                              error,
+                              "prefix", &prefix,
+                              NULL))
+        return;
+
+      menu_layout_node_legacy_dir_set_prefix (parser->stack_top, prefix);
+    }
+  else if (ELEMENT_IS ("MergeFile"))
+    {
+      const char *type;
+
+      push_node (parser, MENU_LAYOUT_NODE_MERGE_FILE);
+
+      if (!locate_attributes (context, element_name,
+                              attribute_names, attribute_values,
+                              error,
+                              "type", &type,
+                              NULL))
+        return;
+
+      if (type != NULL && strcmp (type, "parent") == 0)
+	{
+	  menu_layout_node_merge_file_set_type (parser->stack_top,
+						MENU_MERGE_FILE_TYPE_PARENT);
+	}
+    }
+  else if (ELEMENT_IS ("DefaultLayout"))
+    {
+      const char *show_empty;
+      const char *inline_menus;
+      const char *inline_limit;
+      const char *inline_header;
+      const char *inline_alias;
+
+      push_node (parser, MENU_LAYOUT_NODE_DEFAULT_LAYOUT);
+
+      locate_attributes (context, element_name,
+                         attribute_names, attribute_values,
+                         error,
+                         "show_empty",    &show_empty,
+                         "inline",        &inline_menus,
+                         "inline_limit",  &inline_limit,
+                         "inline_header", &inline_header,
+                         "inline_alias",  &inline_alias,
+                         NULL);
+
+      menu_layout_node_default_layout_set_values (parser->stack_top,
+						  show_empty,
+						  inline_menus,
+						  inline_limit,
+						  inline_header,
+						  inline_alias);
+    }
+  else
+    {
+      if (!check_no_attributes (context, element_name,
+                                attribute_names, attribute_values,
+                                error))
+        return;
+
+      if (ELEMENT_IS ("AppDir"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_APP_DIR);
+        }
+      else if (ELEMENT_IS ("DefaultAppDirs"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_DEFAULT_APP_DIRS);
+        }
+      else if (ELEMENT_IS ("DirectoryDir"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_DIRECTORY_DIR);
+        }
+      else if (ELEMENT_IS ("DefaultDirectoryDirs"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS);
+        }
+      else if (ELEMENT_IS ("DefaultMergeDirs"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS);
+        }
+      else if (ELEMENT_IS ("Name"))
+        {
+          if (has_child_of_type (parser->stack_top, MENU_LAYOUT_NODE_NAME))
+            {
+              set_error (error, context,
+                         G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                         "Multiple <Name> elements in a <Menu> element is not allowed\n");
+              return;
+            }
+
+          push_node (parser, MENU_LAYOUT_NODE_NAME);
+        }
+      else if (ELEMENT_IS ("Directory"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_DIRECTORY);
+        }
+      else if (ELEMENT_IS ("OnlyUnallocated"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_ONLY_UNALLOCATED);
+        }
+      else if (ELEMENT_IS ("NotOnlyUnallocated"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED);
+        }
+      else if (ELEMENT_IS ("Include"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_INCLUDE);
+        }
+      else if (ELEMENT_IS ("Exclude"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_EXCLUDE);
+        }
+      else if (ELEMENT_IS ("MergeDir"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_MERGE_DIR);
+        }
+      else if (ELEMENT_IS ("KDELegacyDirs"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_KDE_LEGACY_DIRS);
+        }
+      else if (ELEMENT_IS ("Move"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_MOVE);
+        }
+      else if (ELEMENT_IS ("Deleted"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_DELETED);
+
+        }
+      else if (ELEMENT_IS ("NotDeleted"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_NOT_DELETED);
+        }
+      else if (ELEMENT_IS ("Layout"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_LAYOUT);
+        }
+      else
+        {
+          set_error (error, context,
+                     G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                     "Element <%s> may not appear below <%s>\n",
+                     element_name, "Menu");
+        }
+    }
+}
+
+static void
+start_matching_rule_element (MenuParser           *parser,
+                             GMarkupParseContext  *context,
+                             const char           *element_name,
+                             const char          **attribute_names,
+                             const char          **attribute_values,
+                             GError              **error)
+{
+  if (!check_no_attributes (context, element_name,
+                            attribute_names, attribute_values,
+                            error))
+    return;
+
+  if (ELEMENT_IS ("Filename"))
+    {
+      push_node (parser, MENU_LAYOUT_NODE_FILENAME);
+    }
+  else if (ELEMENT_IS ("Category"))
+    {
+      push_node (parser, MENU_LAYOUT_NODE_CATEGORY);
+    }
+  else if (ELEMENT_IS ("All"))
+    {
+      push_node (parser, MENU_LAYOUT_NODE_ALL);
+    }
+  else if (ELEMENT_IS ("And"))
+    {
+      push_node (parser, MENU_LAYOUT_NODE_AND);
+    }
+  else if (ELEMENT_IS ("Or"))
+    {
+      push_node (parser, MENU_LAYOUT_NODE_OR);
+    }
+  else if (ELEMENT_IS ("Not"))
+    {
+      push_node (parser, MENU_LAYOUT_NODE_NOT);
+    }
+  else
+    {
+      set_error (error, context,
+                 G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                 "Element <%s> may not appear in this context\n",
+                 element_name);
+    }
+}
+
+static void
+start_move_child_element (MenuParser           *parser,
+                          GMarkupParseContext  *context,
+                          const char           *element_name,
+                          const char          **attribute_names,
+                          const char          **attribute_values,
+                          GError              **error)
+{
+  if (!check_no_attributes (context, element_name,
+                            attribute_names, attribute_values,
+                            error))
+    return;
+
+  if (ELEMENT_IS ("Old"))
+    {
+      push_node (parser, MENU_LAYOUT_NODE_OLD);
+    }
+  else if (ELEMENT_IS ("New"))
+    {
+      push_node (parser, MENU_LAYOUT_NODE_NEW);
+    }
+  else
+    {
+      set_error (error, context,
+                 G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                 "Element <%s> may not appear below <%s>\n",
+                 element_name, "Move");
+    }
+}
+
+static void
+start_layout_child_element (MenuParser           *parser,
+                            GMarkupParseContext  *context,
+                            const char           *element_name,
+                            const char          **attribute_names,
+                            const char          **attribute_values,
+                            GError              **error)
+{
+  if (ELEMENT_IS ("Menuname"))
+    {
+      const char *show_empty;
+      const char *inline_menus;
+      const char *inline_limit;
+      const char *inline_header;
+      const char *inline_alias;
+
+      push_node (parser, MENU_LAYOUT_NODE_MENUNAME);
+
+      locate_attributes (context, element_name,
+                         attribute_names, attribute_values,
+                         error,
+                         "show_empty",    &show_empty,
+                         "inline",        &inline_menus,
+                         "inline_limit",  &inline_limit,
+                         "inline_header", &inline_header,
+                         "inline_alias",  &inline_alias,
+                         NULL);
+
+       menu_layout_node_menuname_set_values (parser->stack_top,
+					     show_empty,
+					     inline_menus,
+					     inline_limit,
+					     inline_header,
+					     inline_alias);
+    }
+  else if (ELEMENT_IS ("Merge"))
+    {
+        const char *type;
+
+        push_node (parser, MENU_LAYOUT_NODE_MERGE);
+
+        locate_attributes (context, element_name,
+                           attribute_names, attribute_values,
+                           error,
+                           "type", &type,
+                           NULL);
+
+	menu_layout_node_merge_set_type (parser->stack_top, type);
+    }
+  else
+    {
+      if (!check_no_attributes (context, element_name,
+                                attribute_names, attribute_values,
+                                error))
+        return;
+
+      if (ELEMENT_IS ("Filename"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_FILENAME);
+        }
+      else if (ELEMENT_IS ("Separator"))
+        {
+          push_node (parser, MENU_LAYOUT_NODE_SEPARATOR);
+        }
+      else
+        {
+          set_error (error, context,
+                     G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                     "Element <%s> may not appear below <%s>\n",
+                     element_name, "Move");
+        }
+    }
+}
+
+static void
+start_element_handler (GMarkupParseContext   *context,
+                       const char            *element_name,
+                       const char           **attribute_names,
+                       const char           **attribute_values,
+                       gpointer               user_data,
+                       GError               **error)
+{
+  MenuParser *parser = user_data;
+
+  if (ELEMENT_IS ("Menu"))
+    {
+      if (parser->stack_top == parser->root &&
+          has_child_of_type (parser->root, MENU_LAYOUT_NODE_MENU))
+        {
+          set_error (error, context,
+                     G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                     "Multiple root elements in menu file, only one toplevel <Menu> is allowed\n");
+          return;
+        }
+
+      start_menu_element (parser, context, element_name,
+                          attribute_names, attribute_values,
+                          error);
+    }
+  else if (parser->stack_top == parser->root)
+    {
+      set_error (error, context,
+                 G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                 "Root element in a menu file must be <Menu>, not <%s>\n",
+                 element_name);
+    }
+  else if (parser->stack_top->type == MENU_LAYOUT_NODE_MENU)
+    {
+      start_menu_child_element (parser, context, element_name,
+                                attribute_names, attribute_values,
+                                error);
+    }
+  else if (parser->stack_top->type == MENU_LAYOUT_NODE_INCLUDE ||
+           parser->stack_top->type == MENU_LAYOUT_NODE_EXCLUDE ||
+           parser->stack_top->type == MENU_LAYOUT_NODE_AND     ||
+           parser->stack_top->type == MENU_LAYOUT_NODE_OR      ||
+           parser->stack_top->type == MENU_LAYOUT_NODE_NOT)
+    {
+      start_matching_rule_element (parser, context, element_name,
+                                   attribute_names, attribute_values,
+                                   error);
+    }
+  else if (parser->stack_top->type == MENU_LAYOUT_NODE_MOVE)
+    {
+      start_move_child_element (parser, context, element_name,
+                                attribute_names, attribute_values,
+                                error);
+    }
+  else if (parser->stack_top->type == MENU_LAYOUT_NODE_LAYOUT ||
+           parser->stack_top->type == MENU_LAYOUT_NODE_DEFAULT_LAYOUT)
+    {
+      start_layout_child_element (parser, context, element_name,
+                                  attribute_names, attribute_values,
+                                  error);
+    }
+  else
+    {
+      set_error (error, context,
+                 G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                 "Element <%s> may not appear in this context\n",
+                 element_name);
+    }
+
+  add_context_to_error (error, context);
+}
+
+/* we want to make sure that the <Layout> or <DefaultLayout> is either empty,
+ * or contain one <Merge> of type "all", or contain one <Merge> of type "menus"
+ * and one <Merge> of type "files". If this is not the case, we try to clean up
+ * things:
+ *  + if there is at least one <Merge> of type "all", then we only keep the
+ *    last <Merge> of type "all" and remove all others <Merge>
+ *  + if there is no <Merge> with type "all", we keep only the last <Merge> of
+ *    type "menus" and the last <Merge> of type "files". If there's no <Merge>
+ *    of type "menus" we append one, and then if there's no <Merge> of type
+ *    "files", we append one. (So menus are before files)
+ */
+static gboolean
+fixup_layout_node (GMarkupParseContext   *context,
+                   MenuParser            *parser,
+                   MenuLayoutNode        *node,
+                   GError              **error)
+{
+  MenuLayoutNode *child;
+  MenuLayoutNode *last_all;
+  MenuLayoutNode *last_menus;
+  MenuLayoutNode *last_files;
+  int             n_all;
+  int             n_menus;
+  int             n_files;
+
+  if (!node->children)
+    {
+      return TRUE;
+    }
+
+  last_all   = NULL;
+  last_menus = NULL;
+  last_files = NULL;
+  n_all   = 0;
+  n_menus = 0;
+  n_files = 0;
+
+  child = node->children;
+  while (child != NULL)
+    {
+      switch (child->type)
+        {
+        case MENU_LAYOUT_NODE_MERGE:
+	  switch (menu_layout_node_merge_get_type (child))
+	    {
+	    case MENU_LAYOUT_MERGE_NONE:
+	      break;
+
+	    case MENU_LAYOUT_MERGE_MENUS:
+	      last_menus = child;
+	      n_menus++;
+	      break;
+
+	    case MENU_LAYOUT_MERGE_FILES:
+	      last_files = child;
+	      n_files++;
+	      break;
+
+	    case MENU_LAYOUT_MERGE_ALL:
+	      last_all = child;
+	      n_all++;
+	      break;
+
+	    default:
+	      g_assert_not_reached ();
+	      break;
+	    }
+          break;
+
+	  default:
+	    break;
+	}
+
+      child = node_next (child);
+    }
+
+  if ((n_all == 1 && n_menus == 0 && n_files == 0) ||
+      (n_all == 0 && n_menus == 1 && n_files == 1))
+    {
+      return TRUE;
+    }
+  else if (n_all > 1 || n_menus > 1 || n_files > 1 ||
+           (n_all == 1 && (n_menus != 0 || n_files != 0)))
+    {
+      child = node->children;
+      while (child != NULL)
+	{
+	  MenuLayoutNode *next;
+
+	  next = node_next (child);
+
+	  switch (child->type)
+	    {
+	    case MENU_LAYOUT_NODE_MERGE:
+	      switch (menu_layout_node_merge_get_type (child))
+		{
+		case MENU_LAYOUT_MERGE_NONE:
+		  break;
+
+		case MENU_LAYOUT_MERGE_MENUS:
+		  if (n_all || last_menus != child)
+		    {
+		      menu_verbose ("removing duplicated merge menus element\n");
+		      menu_layout_node_unlink (child);
+		    }
+		  break;
+
+		case MENU_LAYOUT_MERGE_FILES:
+		  if (n_all || last_files != child)
+		    {
+		      menu_verbose ("removing duplicated merge files element\n");
+		      menu_layout_node_unlink (child);
+		    }
+		  break;
+
+		case MENU_LAYOUT_MERGE_ALL:
+		  if (last_all != child)
+		    {
+		      menu_verbose ("removing duplicated merge all element\n");
+		      menu_layout_node_unlink (child);
+		    }
+		  break;
+
+		default:
+		  g_assert_not_reached ();
+		  break;
+		}
+	      break;
+
+	      default:
+		break;
+	    }
+
+	  child = next;
+	}
+    }
+
+  if (n_all == 0 && n_menus == 0)
+    {
+      last_menus = menu_layout_node_new (MENU_LAYOUT_NODE_MERGE);
+      menu_layout_node_merge_set_type (last_menus, "menus");
+      menu_verbose ("appending missing merge menus element\n");
+      menu_layout_node_append_child (node, last_menus);
+    }
+
+  if (n_all == 0 && n_files == 0)
+    {
+      last_files = menu_layout_node_new (MENU_LAYOUT_NODE_MERGE);
+      menu_layout_node_merge_set_type (last_files, "files");
+      menu_verbose ("appending missing merge files element\n");
+      menu_layout_node_append_child (node, last_files);
+    }
+
+  return TRUE;
+}
+
+/* we want to a) check that we have old-new pairs and b) canonicalize
+ * such that each <Move> has exactly one old-new pair
+ */
+static gboolean
+fixup_move_node (GMarkupParseContext   *context,
+                 MenuParser            *parser,
+                 MenuLayoutNode        *node,
+                 GError              **error)
+{
+  MenuLayoutNode *child;
+  int             n_old;
+  int             n_new;
+
+  n_old = 0;
+  n_new = 0;
+
+  child = node->children;
+  while (child != NULL)
+    {
+      switch (child->type)
+        {
+        case MENU_LAYOUT_NODE_OLD:
+          if (n_new != n_old)
+            {
+              set_error (error, context,
+                         G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                         "<Old>/<New> elements not paired properly\n");
+              return FALSE;
+            }
+
+          n_old += 1;
+
+          break;
+
+        case MENU_LAYOUT_NODE_NEW:
+          n_new += 1;
+
+          if (n_new != n_old)
+            {
+              set_error (error, context,
+                         G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                         "<Old>/<New> elements not paired properly\n");
+              return FALSE;
+            }
+
+          break;
+
+        default:
+          g_assert_not_reached ();
+          break;
+        }
+
+      child = node_next (child);
+    }
+
+  if (n_new == 0 || n_old == 0)
+    {
+      set_error (error, context,
+                 G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                 "<Old>/<New> elements missing under <Move>\n");
+      return FALSE;
+    }
+
+  g_assert (n_new == n_old);
+  g_assert ((n_new + n_old) % 2 == 0);
+
+  if (n_new > 1)
+    {
+      MenuLayoutNode *prev;
+      MenuLayoutNode *append_after;
+
+      /* Need to split the <Move> into multiple <Move> */
+
+      n_old = 0;
+      n_new = 0;
+      prev = NULL;
+      append_after = node;
+
+      child = node->children;
+      while (child != NULL)
+        {
+          MenuLayoutNode *next;
+
+          next = node_next (child);
+
+          switch (child->type)
+            {
+            case MENU_LAYOUT_NODE_OLD:
+              n_old += 1;
+              break;
+
+            case MENU_LAYOUT_NODE_NEW:
+              n_new += 1;
+              break;
+
+            default:
+              g_assert_not_reached ();
+              break;
+            }
+
+          if (n_old == n_new &&
+              n_old > 1)
+            {
+              /* Move the just-completed pair */
+              MenuLayoutNode *new_move;
+
+              g_assert (prev != NULL);
+
+              new_move = menu_layout_node_new (MENU_LAYOUT_NODE_MOVE);
+              menu_verbose ("inserting new_move after append_after\n");
+              menu_layout_node_insert_after (append_after, new_move);
+              append_after = new_move;
+
+              menu_layout_node_steal (prev);
+              menu_layout_node_steal (child);
+
+              menu_verbose ("appending prev to new_move\n");
+              menu_layout_node_append_child (new_move, prev);
+              menu_verbose ("appending child to new_move\n");
+              menu_layout_node_append_child (new_move, child);
+
+              menu_verbose ("Created new move element old = %s new = %s\n",
+                            menu_layout_node_move_get_old (new_move),
+                            menu_layout_node_move_get_new (new_move));
+
+              menu_layout_node_unref (new_move);
+              menu_layout_node_unref (prev);
+              menu_layout_node_unref (child);
+
+              prev = NULL;
+            }
+          else
+            {
+              prev = child;<--- prev is assigned
+            }
+
+          prev = child;<--- prev is overwritten
+          child = next;
+        }
+    }
+
+  return TRUE;
+}
+
+static void
+end_element_handler (GMarkupParseContext  *context,
+                     const char           *element_name,
+                     gpointer              user_data,
+                     GError              **error)
+{
+  MenuParser *parser = user_data;
+
+  g_assert (parser->stack_top != NULL);
+
+  switch (parser->stack_top->type)
+    {
+    case MENU_LAYOUT_NODE_APP_DIR:
+    case MENU_LAYOUT_NODE_DIRECTORY_DIR:
+    case MENU_LAYOUT_NODE_NAME:
+    case MENU_LAYOUT_NODE_DIRECTORY:
+    case MENU_LAYOUT_NODE_FILENAME:
+    case MENU_LAYOUT_NODE_CATEGORY:
+    case MENU_LAYOUT_NODE_MERGE_DIR:
+    case MENU_LAYOUT_NODE_LEGACY_DIR:
+    case MENU_LAYOUT_NODE_OLD:
+    case MENU_LAYOUT_NODE_NEW:
+    case MENU_LAYOUT_NODE_MENUNAME:
+      if (menu_layout_node_get_content (parser->stack_top) == NULL)
+        {
+          set_error (error, context,
+                     G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                     "Element <%s> is required to contain text and was empty\n",
+                     element_name);
+          goto out;
+        }
+      break;
+
+    case MENU_LAYOUT_NODE_MENU:
+      if (!has_child_of_type (parser->stack_top, MENU_LAYOUT_NODE_NAME))
+        {
+          set_error (error, context,
+                     G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                     "<Menu> elements are required to contain a <Name> element\n");
+          goto out;
+        }
+      break;
+
+    case MENU_LAYOUT_NODE_ROOT:
+    case MENU_LAYOUT_NODE_PASSTHROUGH:
+    case MENU_LAYOUT_NODE_DEFAULT_APP_DIRS:
+    case MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS:
+    case MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS:
+    case MENU_LAYOUT_NODE_ONLY_UNALLOCATED:
+    case MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED:
+    case MENU_LAYOUT_NODE_INCLUDE:
+    case MENU_LAYOUT_NODE_EXCLUDE:
+    case MENU_LAYOUT_NODE_ALL:
+    case MENU_LAYOUT_NODE_AND:
+    case MENU_LAYOUT_NODE_OR:
+    case MENU_LAYOUT_NODE_NOT:
+    case MENU_LAYOUT_NODE_KDE_LEGACY_DIRS:
+    case MENU_LAYOUT_NODE_DELETED:
+    case MENU_LAYOUT_NODE_NOT_DELETED:
+    case MENU_LAYOUT_NODE_SEPARATOR:
+    case MENU_LAYOUT_NODE_MERGE:
+    case MENU_LAYOUT_NODE_MERGE_FILE:
+      break;
+
+    case MENU_LAYOUT_NODE_LAYOUT:
+    case MENU_LAYOUT_NODE_DEFAULT_LAYOUT:
+      if (!fixup_layout_node (context, parser, parser->stack_top, error))
+        goto out;
+      break;
+
+    case MENU_LAYOUT_NODE_MOVE:
+      if (!fixup_move_node (context, parser, parser->stack_top, error))
+        goto out;
+      break;
+    default:
+      g_assert_not_reached();
+    }
+
+ out:
+  parser->stack_top = parser->stack_top->parent;
+}
+
+static gboolean
+all_whitespace (const char *text,
+                gsize       text_len)
+{
+  const char *p;
+  const char *end;
+
+  p = text;
+  end = text + text_len;
+
+  while (p != end)
+    {
+      if (!g_ascii_isspace (*p))
+        return FALSE;
+
+      p = g_utf8_next_char (p);
+    }
+
+  return TRUE;
+}
+
+static void
+text_handler (GMarkupParseContext  *context,
+              const char           *text,
+              gsize                 text_len,
+              gpointer              user_data,
+              GError              **error)
+{
+  MenuParser *parser = user_data;
+
+  switch (parser->stack_top->type)
+    {
+    case MENU_LAYOUT_NODE_APP_DIR:
+    case MENU_LAYOUT_NODE_DIRECTORY_DIR:
+    case MENU_LAYOUT_NODE_NAME:
+    case MENU_LAYOUT_NODE_DIRECTORY:
+    case MENU_LAYOUT_NODE_FILENAME:
+    case MENU_LAYOUT_NODE_CATEGORY:
+    case MENU_LAYOUT_NODE_MERGE_FILE:
+    case MENU_LAYOUT_NODE_MERGE_DIR:
+    case MENU_LAYOUT_NODE_LEGACY_DIR:
+    case MENU_LAYOUT_NODE_OLD:
+    case MENU_LAYOUT_NODE_NEW:
+    case MENU_LAYOUT_NODE_MENUNAME:
+      g_assert (menu_layout_node_get_content (parser->stack_top) == NULL);
+
+      menu_layout_node_set_content (parser->stack_top, text);
+      break;
+
+    case MENU_LAYOUT_NODE_ROOT:
+    case MENU_LAYOUT_NODE_PASSTHROUGH:
+    case MENU_LAYOUT_NODE_MENU:
+    case MENU_LAYOUT_NODE_DEFAULT_APP_DIRS:
+    case MENU_LAYOUT_NODE_DEFAULT_DIRECTORY_DIRS:
+    case MENU_LAYOUT_NODE_DEFAULT_MERGE_DIRS:
+    case MENU_LAYOUT_NODE_ONLY_UNALLOCATED:
+    case MENU_LAYOUT_NODE_NOT_ONLY_UNALLOCATED:
+    case MENU_LAYOUT_NODE_INCLUDE:
+    case MENU_LAYOUT_NODE_EXCLUDE:
+    case MENU_LAYOUT_NODE_ALL:
+    case MENU_LAYOUT_NODE_AND:
+    case MENU_LAYOUT_NODE_OR:
+    case MENU_LAYOUT_NODE_NOT:
+    case MENU_LAYOUT_NODE_KDE_LEGACY_DIRS:
+    case MENU_LAYOUT_NODE_MOVE:
+    case MENU_LAYOUT_NODE_DELETED:
+    case MENU_LAYOUT_NODE_NOT_DELETED:
+    case MENU_LAYOUT_NODE_LAYOUT:
+    case MENU_LAYOUT_NODE_DEFAULT_LAYOUT:
+    case MENU_LAYOUT_NODE_SEPARATOR:
+    case MENU_LAYOUT_NODE_MERGE:
+      if (!all_whitespace (text, text_len))
+        {
+          set_error (error, context,
+                     G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                     "No text is allowed inside element <%s>",
+                     g_markup_parse_context_get_element (context));
+        }
+      break;
+    default:
+      g_assert_not_reached();
+    }
+
+  add_context_to_error (error, context);
+}
+
+static void
+passthrough_handler (GMarkupParseContext  *context,
+                     const char           *passthrough_text,
+                     gsize                 text_len,
+                     gpointer              user_data,
+                     GError              **error)
+{
+  MenuParser *parser = user_data;
+  MenuLayoutNode *node;
+
+  /* don't push passthrough on the stack, it's not an element */
+
+  node = menu_layout_node_new (MENU_LAYOUT_NODE_PASSTHROUGH);
+  menu_layout_node_set_content (node, passthrough_text);
+
+  menu_layout_node_append_child (parser->stack_top, node);
+  menu_layout_node_unref (node);
+
+  add_context_to_error (error, context);
+}
+
+static void
+menu_parser_init (MenuParser *parser)
+{
+  parser->root = menu_layout_node_new (MENU_LAYOUT_NODE_ROOT);
+  parser->stack_top = parser->root;
+}
+
+static void
+menu_parser_free (MenuParser *parser)
+{
+  if (parser->root)
+    menu_layout_node_unref (parser->root);
+}
+
+MenuLayoutNode *
+menu_layout_load (const char  *filename,
+                  const char  *non_prefixed_basename,
+                  GError     **err)
+{
+  GMainContext        *main_context;
+  GMarkupParseContext *context;
+  MenuLayoutNodeRoot  *root;
+  MenuLayoutNode      *retval;
+  MenuParser           parser;
+  GError              *error;
+  GString             *str;
+  char                *text;
+  char                *s;
+  gsize                length;
+
+  text = NULL;
+  length = 0;
+  retval = NULL;
+  context = NULL;
+
+  main_context = g_main_context_get_thread_default ();
+
+  menu_verbose ("Loading \"%s\" from disk\n", filename);
+
+  if (!g_file_get_contents (filename,
+                            &text,
+                            &length,
+                            err))
+    {
+      menu_verbose ("Failed to load \"%s\"\n",
+                    filename);
+      return NULL;
+    }
+
+  g_assert (text != NULL);
+
+  menu_parser_init (&parser);
+
+  root = (MenuLayoutNodeRoot *) parser.root;
+
+  root->basedir = g_path_get_dirname (filename);
+  menu_verbose ("Set basedir \"%s\"\n", root->basedir);
+
+  if (non_prefixed_basename)
+    s = g_strdup (non_prefixed_basename);
+  else
+    s = g_path_get_basename (filename);
+  str = g_string_new (s);
+  if (g_str_has_suffix (str->str, ".menu"))
+    g_string_truncate (str, str->len - strlen (".menu"));
+
+  root->name = str->str;
+  menu_verbose ("Set menu name \"%s\"\n", root->name);
+
+  g_string_free (str, FALSE);
+  g_free (s);
+
+  context = g_markup_parse_context_new (&menu_funcs, 0, &parser, NULL);
+
+  error = NULL;
+  if (!g_markup_parse_context_parse (context,
+                                     text,
+                                     (gssize) length,
+                                     &error))
+    goto out;
+
+  error = NULL;
+  g_markup_parse_context_end_parse (context, &error);
+
+  root->main_context = main_context ? g_main_context_ref (main_context) : NULL;
+
+ out:
+  if (context)
+    g_markup_parse_context_free (context);
+  g_free (text);
+
+  if (error)
+    {
+      menu_verbose ("Error \"%s\" loading \"%s\"\n",
+                    error->message, filename);
+      g_propagate_error (err, error);
+    }
+  else if (has_child_of_type (parser.root, MENU_LAYOUT_NODE_MENU))
+    {
+      menu_verbose ("File loaded OK\n");
+      retval = parser.root;
+      parser.root = NULL;
+    }
+  else
+    {
+      menu_verbose ("Did not have a root element in file\n");
+      g_set_error (err, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
+                   "Menu file %s did not contain a root <Menu> element",
+                   filename);
+    }
+
+  menu_parser_free (&parser);
+
+  return retval;
+}
+
+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/index.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/index.html new file mode 100644 index 0000000..13b3a5e --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/index.html @@ -0,0 +1,313 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineIdCWESeverityMessage
checkersReportinformationActive checkers: 106/592 (use --checkers-report=<filename> to see details)
libmenu/desktop-entries.c
21missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
24missingIncludeSysteminformationInclude file: <gio/gdesktopappinfo.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
26missingIncludeSysteminformationInclude file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
509constParameterPointer398styleParameter 'entry' can be declared as pointer to const
514constParameterPointer398styleParameter 'entry' can be declared as pointer to const
520constParameterPointer398styleParameter 'entry' can be declared as pointer to const
604constVariablePointer398styleVariable 'desktop_entry' can be declared as pointer to const
libmenu/desktop-entries.h
24missingIncludeSysteminformationInclude file: <gio/gdesktopappinfo.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
libmenu/entry-directories.c
24missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
29missingIncludeSysteminformationInclude file: <errno.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
30missingIncludeSysteminformationInclude file: <sys/types.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
31missingIncludeSysteminformationInclude file: <dirent.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
32missingIncludeSysteminformationInclude file: <stdlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
209constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
467constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
653constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
679constParameterPointer398styleParameter 'ed' can be declared as pointer to const
1059constParameterPointer398styleParameter 'list' can be declared as pointer to const
1105constVariablePointer398styleVariable 'al' can be declared as pointer to const
1105constVariablePointer398styleVariable 'bl' can be declared as pointer to const
1126constParameterCallback398styleParameter 'ed' can be declared as pointer to const. However it seems that 'get_all_func' is a callback function, if 'ed' is declared with const you might also need to cast function pointer(s).
libmenu/entry-directories.h
24missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
libmenu/matemenu-tree.c
24missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <gio/gio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
29missingIncludeSysteminformationInclude file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
30missingIncludeSysteminformationInclude file: <errno.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
31missingIncludeSysteminformationInclude file: <stdlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
905constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
1319constParameterPointer398styleParameter 'directory' can be declared as pointer to const
1327constParameterPointer398styleParameter 'directory' can be declared as pointer to const
1409constParameterPointer398styleParameter 'entry' can be declared as pointer to const
1442constParameterPointer398styleParameter 'entry' can be declared as pointer to const
1450constParameterPointer398styleParameter 'entry' can be declared as pointer to const
3541constParameterPointer398styleParameter 'parent' can be declared as pointer to const
4016constParameterPointer398styleParameter 'default_layout_values' can be declared as pointer to const
4040constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
4176constVariablePointer398styleVariable 'last_subdir' can be declared as pointer to const
4206constVariablePointer398styleVariable 'subdir_l' can be declared as pointer to const
4496constParameterPointer398styleParameter 'list' can be declared as pointer to const
4680constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
4705constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
4854constParameterCallback398styleParameter 'layout' can be declared as pointer to const. However it seems that 'handle_entries_changed' is a callback function, if 'layout' is declared with const you might also need to cast function pointer(s).
libmenu/matemenu-tree.h
28missingIncludeSysteminformationInclude file: <gio/gdesktopappinfo.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
libmenu/menu-layout.c
23missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
27missingIncludeSysteminformationInclude file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
29missingIncludeSysteminformationInclude file: <stdlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
30missingIncludeSysteminformationInclude file: <unistd.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
31missingIncludeSysteminformationInclude file: <errno.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
125constParameterPointer398styleParameter 'node' can be declared as pointer to const
324constParameterPointer398styleParameter 'node' can be declared as pointer to const
330constParameterPointer398styleParameter 'node' can be declared as pointer to const
577constParameterPointer398styleParameter 'node' can be declared as pointer to const
583constParameterPointer398styleParameter 'node' can be declared as pointer to const
602constVariablePointer398styleVariable 'nr' can be declared as pointer to const
614constVariablePointer398styleVariable 'nr' can be declared as pointer to const
736constVariablePointer398styleVariable 'legacy' can be declared as pointer to const
821constParameterPointer398styleParameter 'node' can be declared as pointer to const
838constParameterPointer398styleParameter 'node' can be declared as pointer to const
857constVariablePointer398styleVariable 'legacy' can be declared as pointer to const
883constVariablePointer398styleVariable 'merge_file' can be declared as pointer to const
908constVariablePointer398styleVariable 'merge' can be declared as pointer to const
947constVariablePointer398styleVariable 'default_layout' can be declared as pointer to const
961constVariablePointer398styleVariable 'menuname' can be declared as pointer to const
1075constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
1351constParameterPointer398styleParameter 'node' can be declared as pointer to const
1424varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
1439varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
1466varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
1671varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
1690varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
2084redundantAssignment563styleVariable 'prev' is reassigned a value before the old one has been used.
libmenu/menu-layout.h
26missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
libmenu/menu-monitor.c
24missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <gio/gio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
290constParameterPointer398styleParameter 'monitor' can be declared as pointer to const
381constVariablePointer398styleVariable 'tmp' can be declared as pointer to const
libmenu/menu-monitor.h
25missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
libmenu/menu-util.c
23missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
27missingIncludeSysteminformationInclude file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <stdarg.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
libmenu/menu-util.h
26missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
util/test-menu-spec.c
21missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
22missingIncludeSysteminformationInclude file: <glib/gi18n.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
27missingIncludeinformationInclude file: "matemenu-tree.h" not found.
29missingIncludeSysteminformationInclude file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/stats.html b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/stats.html new file mode 100644 index 0000000..ce27f2d --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/stats.html @@ -0,0 +1,186 @@ + + + + + + Cppcheck - HTML report - mate-menus + + + + + +
+ + + +
+

Top 10 files for portability severity, total findings: 5
+   5  libmenu/menu-layout.c
+

+

Top 10 files for style severity, total findings: 47
+   18  libmenu/menu-layout.c
+   15  libmenu/matemenu-tree.c
+   8   libmenu/entry-directories.c
+   4   libmenu/desktop-entries.c
+   2   libmenu/menu-monitor.c
+

+

Top 10 files for information severity, total findings: 35
+   6  libmenu/menu-layout.c
+   6  libmenu/entry-directories.c
+   5  libmenu/matemenu-tree.c
+   4  util/test-menu-spec.c
+   3  libmenu/menu-util.c
+   3  libmenu/desktop-entries.c
+   2  libmenu/menu-monitor.c
+   1  libmenu/menu-util.h
+   1  libmenu/menu-monitor.h
+   1  libmenu/menu-layout.h
+

+ +
+ +
+ + diff --git a/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/style.css b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2024-02-15-160930-2782-cppcheck@bfa5f0a8ebe1_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} -- cgit v1.2.1