~ubuntu-branches/ubuntu/saucy/menu-cache/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/gmenu-2.30.5.patch/menu-cache-gen/desktop-entries.c

  • Committer: Package Import Robot
  • Author(s): Daniel Baumann
  • Date: 2012-05-20 20:12:11 UTC
  • mfrom: (3.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20120520201211-i7maz7xakyi2n3p5
Tags: 0.3.3-1
* Merging upstream version 0.3.3.
* Removing binutils-gold.patch, included upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2002 - 2004 Red Hat, Inc.
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License along with this library; if not, write to the
16
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 
 * Boston, MA 02111-1307, USA.
18
 
 */
19
 
 
20
 
#include <config.h>
21
 
 
22
 
#include "desktop-entries.h"
23
 
 
24
 
#include <string.h>
25
 
 
26
 
#include "menu-util.h"
27
 
 
28
 
#define DESKTOP_ENTRY_GROUP     "Desktop Entry"
29
 
#define KDE_DESKTOP_ENTRY_GROUP "KDE Desktop Entry"
30
 
 
31
 
enum
32
 
{
33
 
  DESKTOP_ENTRY_NO_DISPLAY     = 1 << 0,
34
 
  DESKTOP_ENTRY_HIDDEN         = 1 << 1,
35
 
  DESKTOP_ENTRY_SHOW_IN_GNOME  = 1 << 2,
36
 
  DESKTOP_ENTRY_TRYEXEC_FAILED = 1 << 3
37
 
};
38
 
 
39
 
struct DesktopEntry
40
 
{
41
 
  char *path;
42
 
  char *basename;
43
 
 
44
 
  GQuark *categories;
45
 
 
46
 
  char     *name;
47
 
  char     *generic_name;
48
 
  char     *comment;
49
 
  char     *icon;
50
 
  char     *exec;
51
 
  gboolean terminal : 1;
52
 
  gboolean startup_notify : 1;
53
 
 
54
 
  guint32 show_in_flags;
55
 
 
56
 
  guint type : 2;
57
 
  guint flags : 4;
58
 
  guint refcount : 24;
59
 
};
60
 
 
61
 
struct DesktopEntrySet
62
 
{
63
 
  int         refcount;
64
 
  GHashTable *hash;
65
 
};
66
 
 
67
 
/* defined in menu-cache-gen.c */
68
 
guint32 menu_cache_get_de_flag( const char* de_name );
69
 
 
70
 
/*
71
 
 * Desktop entries
72
 
 */
73
 
 
74
 
static guint
75
 
get_flags_from_key_file (DesktopEntry *entry,
76
 
                         GKeyFile     *key_file,
77
 
                         const char   *desktop_entry_group)
78
 
{
79
 
  GError    *error;
80
 
  char     **strv;
81
 
  gboolean   no_display;
82
 
  gboolean   hidden;
83
 
  gboolean   show_in_gnome;
84
 
  gboolean   tryexec_failed;
85
 
  char      *tryexec;
86
 
  guint      flags;
87
 
  int        i;
88
 
 
89
 
  error = NULL;
90
 
  no_display = g_key_file_get_boolean (key_file,
91
 
                                       desktop_entry_group,
92
 
                                       "NoDisplay",
93
 
                                       &error);
94
 
  if (error)
95
 
    {
96
 
      no_display = FALSE;
97
 
      g_error_free (error);
98
 
    }
99
 
 
100
 
  error = NULL;
101
 
  hidden = g_key_file_get_boolean (key_file,
102
 
                                   desktop_entry_group,
103
 
                                   "Hidden",
104
 
                                   &error);
105
 
  if (error)
106
 
    {
107
 
      hidden = FALSE;
108
 
      g_error_free (error);
109
 
    }
110
 
 
111
 
  show_in_gnome = TRUE;
112
 
  strv = g_key_file_get_string_list (key_file,
113
 
                                     desktop_entry_group,
114
 
                                     "OnlyShowIn",
115
 
                                     NULL,
116
 
                                     NULL);
117
 
  if (strv)
118
 
    {
119
 
/*      show_in_gnome = FALSE; */
120
 
      for (i = 0; strv[i]; i++)
121
 
        {
122
 
          guint32 de_flag = menu_cache_get_de_flag(strv[i]);
123
 
          entry->show_in_flags |= de_flag; /* add the DE */
124
 
/*
125
 
          if (!strcmp (strv[i], "GNOME"))
126
 
            {
127
 
              show_in_gnome = TRUE;
128
 
              break;
129
 
            }
130
 
*/
131
 
        }
132
 
    }
133
 
  else
134
 
    {
135
 
      strv = g_key_file_get_string_list (key_file,
136
 
                                         desktop_entry_group,
137
 
                                         "NotShowIn",
138
 
                                         NULL,
139
 
                                         NULL);
140
 
      if (strv)
141
 
        {
142
 
          /* show in all DEs by default */
143
 
          entry->show_in_flags = (guint32)-1;
144
 
/*          show_in_gnome = TRUE; */
145
 
          for (i = 0; strv[i]; i++)
146
 
            {
147
 
              guint32 de_flag = menu_cache_get_de_flag(strv[i]);
148
 
              entry->show_in_flags &= (~de_flag); /* remove the DE */
149
 
/*
150
 
              if (!strcmp (strv[i], "GNOME"))
151
 
                {
152
 
                  show_in_gnome = FALSE;
153
 
                }
154
 
*/
155
 
            }
156
 
        }
157
 
    }
158
 
  g_strfreev (strv);
159
 
  /* printf( "DE flag of %s is %d\n", entry->name, entry->show_in_flags); */
160
 
  tryexec_failed = FALSE;
161
 
  tryexec = g_key_file_get_string (key_file,
162
 
                                   desktop_entry_group,
163
 
                                   "TryExec",
164
 
                                   NULL);
165
 
  if (tryexec)
166
 
    {
167
 
      char *path;
168
 
 
169
 
      path = g_find_program_in_path (g_strstrip (tryexec));
170
 
 
171
 
      tryexec_failed = (path == NULL);
172
 
 
173
 
      g_free (path);
174
 
      g_free (tryexec);
175
 
    }
176
 
 
177
 
  flags = 0;
178
 
  if (no_display)
179
 
    flags |= DESKTOP_ENTRY_NO_DISPLAY;
180
 
  if (hidden)
181
 
    flags |= DESKTOP_ENTRY_HIDDEN;
182
 
  if (show_in_gnome)
183
 
    flags |= DESKTOP_ENTRY_SHOW_IN_GNOME;
184
 
  if (tryexec_failed)
185
 
    flags |= DESKTOP_ENTRY_TRYEXEC_FAILED;
186
 
 
187
 
  return flags;
188
 
}
189
 
 
190
 
static GQuark *
191
 
get_categories_from_key_file (DesktopEntry *entry,
192
 
                              GKeyFile     *key_file,
193
 
                              const char   *desktop_entry_group)
194
 
{
195
 
  GQuark  *retval;
196
 
  char   **strv;
197
 
  gsize    len;
198
 
  int      i;
199
 
 
200
 
  strv = g_key_file_get_string_list (key_file,
201
 
                                     desktop_entry_group,
202
 
                                     "Categories",
203
 
                                     &len,
204
 
                                     NULL);
205
 
  if (!strv)
206
 
    return NULL;
207
 
 
208
 
  retval = g_new0 (GQuark, len + 1);
209
 
 
210
 
  for (i = 0; strv[i]; i++)
211
 
    retval[i] = g_quark_from_string (strv[i]);
212
 
 
213
 
  g_strfreev (strv);
214
 
 
215
 
  return retval;
216
 
}
217
 
 
218
 
static DesktopEntry *
219
 
desktop_entry_load (DesktopEntry *entry)
220
 
{
221
 
  DesktopEntry *retval = NULL;
222
 
  GKeyFile     *key_file;
223
 
  GError       *error;
224
 
  const char   *desktop_entry_group;
225
 
  char         *name_str;
226
 
  char         *type_str;
227
 
 
228
 
  key_file = g_key_file_new ();
229
 
 
230
 
  error = NULL;
231
 
  if (!g_key_file_load_from_file (key_file, entry->path, 0, &error))
232
 
    {
233
 
      menu_verbose ("Failed to load \"%s\": %s\n",
234
 
                    entry->path, error->message);
235
 
      g_error_free (error);
236
 
      goto out;
237
 
    }
238
 
 
239
 
  if (g_key_file_has_group (key_file, DESKTOP_ENTRY_GROUP))
240
 
    {
241
 
      desktop_entry_group = DESKTOP_ENTRY_GROUP;
242
 
    }
243
 
  else
244
 
    {
245
 
      menu_verbose ("\"%s\" contains no \"" DESKTOP_ENTRY_GROUP "\" group\n",
246
 
                    entry->path);
247
 
 
248
 
      if (g_key_file_has_group (key_file, KDE_DESKTOP_ENTRY_GROUP))
249
 
        {
250
 
          desktop_entry_group = KDE_DESKTOP_ENTRY_GROUP;
251
 
          menu_verbose ("\"%s\" contains deprecated \"" KDE_DESKTOP_ENTRY_GROUP "\" group\n",
252
 
                        entry->path);
253
 
        }
254
 
      else
255
 
        {
256
 
          goto out;
257
 
        }
258
 
    }
259
 
 
260
 
  if (!g_key_file_has_key (key_file, desktop_entry_group, "Name", NULL))
261
 
    {
262
 
      menu_verbose ("\"%s\" contains no \"Name\" key\n", entry->path);
263
 
      goto out;
264
 
    }
265
 
 
266
 
  name_str = g_key_file_get_locale_string (key_file, desktop_entry_group, "Name", NULL, NULL);
267
 
  if (!name_str)
268
 
    {
269
 
      menu_verbose ("\"%s\" contains an invalid \"Name\" key\n", entry->path);
270
 
      goto out;
271
 
    }
272
 
 
273
 
  g_free (name_str);
274
 
 
275
 
  type_str = g_key_file_get_string (key_file, desktop_entry_group, "Type", NULL);
276
 
  if (!type_str)
277
 
    {
278
 
      menu_verbose ("\"%s\" contains no \"Type\" key\n", entry->path);
279
 
      goto out;
280
 
    }
281
 
 
282
 
  if ((entry->type == DESKTOP_ENTRY_DESKTOP && strcmp (type_str, "Application") != 0) ||
283
 
      (entry->type == DESKTOP_ENTRY_DIRECTORY && strcmp (type_str, "Directory") != 0))
284
 
    {
285
 
      menu_verbose ("\"%s\" does not contain the correct \"Type\" value\n", entry->path);
286
 
      g_free (type_str);
287
 
      goto out;
288
 
    }
289
 
 
290
 
  g_free (type_str);
291
 
 
292
 
  if (entry->type == DESKTOP_ENTRY_DESKTOP &&
293
 
      !g_key_file_has_key (key_file, desktop_entry_group, "Exec", NULL))
294
 
    {
295
 
      menu_verbose ("\"%s\" does not contain an \"Exec\" key\n", entry->path);
296
 
      goto out;
297
 
    }
298
 
 
299
 
  retval = entry;
300
 
 
301
 
#define GET_LOCALE_STRING(n) g_key_file_get_locale_string (key_file, desktop_entry_group, (n), NULL, NULL)
302
 
 
303
 
  retval->name         = GET_LOCALE_STRING ("Name");
304
 
  retval->generic_name = GET_LOCALE_STRING ("GenericName");
305
 
  retval->comment      = GET_LOCALE_STRING ("Comment");
306
 
  retval->icon         = GET_LOCALE_STRING ("Icon");
307
 
  retval->flags        = get_flags_from_key_file (retval, key_file, desktop_entry_group);
308
 
  retval->categories   = get_categories_from_key_file (retval, key_file, desktop_entry_group);
309
 
 
310
 
  if (entry->type == DESKTOP_ENTRY_DESKTOP)
311
 
    {
312
 
      retval->exec = g_key_file_get_string (key_file, desktop_entry_group, "Exec", NULL);
313
 
      retval->terminal = g_key_file_get_boolean (key_file, desktop_entry_group, "Terminal", NULL);
314
 
          retval->startup_notify = g_key_file_get_boolean (key_file, desktop_entry_group, "StartupNotify", NULL);
315
 
    }
316
 
  
317
 
#undef GET_LOCALE_STRING
318
 
 
319
 
  menu_verbose ("Desktop entry \"%s\" (%s, %s, %s) flags: NoDisplay=%s, Hidden=%s, ShowInGNOME=%s, TryExecFailed=%s\n",
320
 
                retval->basename,
321
 
                retval->name,
322
 
                retval->comment ? retval->comment : "(null)",
323
 
                retval->icon ? retval->icon : "(null)",
324
 
                retval->flags & DESKTOP_ENTRY_NO_DISPLAY     ? "(true)" : "(false)",
325
 
                retval->flags & DESKTOP_ENTRY_HIDDEN         ? "(true)" : "(false)",
326
 
                retval->flags & DESKTOP_ENTRY_SHOW_IN_GNOME  ? "(true)" : "(false)",
327
 
                retval->flags & DESKTOP_ENTRY_TRYEXEC_FAILED ? "(true)" : "(false)");
328
 
 
329
 
 out:
330
 
  g_key_file_free (key_file);
331
 
 
332
 
  if (!retval)
333
 
    desktop_entry_unref (entry);
334
 
 
335
 
  return retval;
336
 
}
337
 
 
338
 
DesktopEntry *
339
 
desktop_entry_new (const char *path)
340
 
{
341
 
  DesktopEntryType  type;
342
 
  DesktopEntry     *retval;
343
 
 
344
 
  menu_verbose ("Loading desktop entry \"%s\"\n", path);
345
 
 
346
 
  if (g_str_has_suffix (path, ".desktop"))
347
 
    {
348
 
      type = DESKTOP_ENTRY_DESKTOP;
349
 
    }
350
 
  else if (g_str_has_suffix (path, ".directory"))
351
 
    {
352
 
      type = DESKTOP_ENTRY_DIRECTORY;
353
 
    }
354
 
  else
355
 
    {
356
 
      menu_verbose ("Unknown desktop entry suffix in \"%s\"\n",
357
 
                    path);
358
 
      return NULL;
359
 
    }
360
 
 
361
 
  retval = g_new0 (DesktopEntry, 1);
362
 
 
363
 
  retval->refcount = 1;
364
 
  retval->type     = type;
365
 
  retval->basename = g_path_get_basename (path);
366
 
  retval->path     = g_strdup (path);
367
 
 
368
 
  return desktop_entry_load (retval);
369
 
}
370
 
 
371
 
DesktopEntry *
372
 
desktop_entry_reload (DesktopEntry *entry)
373
 
{
374
 
  g_return_val_if_fail (entry != NULL, NULL);
375
 
 
376
 
  menu_verbose ("Re-loading desktop entry \"%s\"\n", entry->path);
377
 
 
378
 
  g_free (entry->categories);
379
 
  entry->categories = NULL;
380
 
 
381
 
  g_free (entry->name);
382
 
  entry->name = NULL;
383
 
 
384
 
  g_free (entry->generic_name);
385
 
  entry->generic_name = NULL;
386
 
 
387
 
  g_free (entry->comment);
388
 
  entry->comment = NULL;
389
 
 
390
 
  g_free (entry->icon);
391
 
  entry->icon = NULL;
392
 
 
393
 
  g_free (entry->exec);
394
 
  entry->exec = NULL;
395
 
 
396
 
  entry->terminal = 0;
397
 
  entry->startup_notify = 0;
398
 
  entry->flags = 0;
399
 
 
400
 
  return desktop_entry_load (entry);
401
 
}
402
 
 
403
 
DesktopEntry *
404
 
desktop_entry_ref (DesktopEntry *entry)
405
 
{
406
 
  g_return_val_if_fail (entry != NULL, NULL);
407
 
  g_return_val_if_fail (entry->refcount > 0, NULL);
408
 
 
409
 
  entry->refcount += 1;
410
 
 
411
 
  return entry;
412
 
}
413
 
 
414
 
DesktopEntry *
415
 
desktop_entry_copy (DesktopEntry *entry)
416
 
{
417
 
  DesktopEntry *retval;
418
 
  int           i;
419
 
 
420
 
  menu_verbose ("Copying desktop entry \"%s\"\n",
421
 
                entry->basename);
422
 
 
423
 
  retval = g_new0 (DesktopEntry, 1);
424
 
 
425
 
  retval->refcount = 1;
426
 
  retval->type     = entry->type;
427
 
  retval->basename = g_strdup (entry->basename);
428
 
  retval->path     = g_strdup (entry->path);
429
 
  retval->name     = g_strdup (entry->name);
430
 
  retval->generic_name = g_strdup (entry->generic_name);
431
 
  retval->comment  = g_strdup (entry->comment);
432
 
  retval->icon     = g_strdup (entry->icon);
433
 
  retval->exec     = g_strdup (entry->exec);
434
 
  retval->terminal = entry->terminal;
435
 
  retval->startup_notify = entry->startup_notify;
436
 
  retval->flags    = entry->flags;
437
 
 
438
 
  i = 0;
439
 
  if (entry->categories != NULL)
440
 
    {
441
 
      for (; entry->categories[i]; i++);
442
 
    }
443
 
 
444
 
  retval->categories = g_new0 (GQuark, i + 1);
445
 
 
446
 
  i = 0;
447
 
  if (entry->categories != NULL)
448
 
    {
449
 
      for (; entry->categories[i]; i++)
450
 
        retval->categories[i] = entry->categories[i];
451
 
    }
452
 
 
453
 
  return retval;
454
 
}
455
 
 
456
 
void
457
 
desktop_entry_unref (DesktopEntry *entry)
458
 
{
459
 
  g_return_if_fail (entry != NULL);
460
 
  g_return_if_fail (entry->refcount > 0);
461
 
 
462
 
  entry->refcount -= 1;
463
 
  if (entry->refcount == 0)
464
 
    {
465
 
      g_free (entry->categories);
466
 
      entry->categories = NULL;
467
 
 
468
 
      g_free (entry->name);
469
 
      entry->name = NULL;
470
 
 
471
 
      g_free (entry->generic_name);
472
 
      entry->generic_name = NULL;
473
 
 
474
 
      g_free (entry->comment);
475
 
      entry->comment = NULL;
476
 
 
477
 
      g_free (entry->icon);
478
 
      entry->icon = NULL;
479
 
 
480
 
      g_free (entry->exec);
481
 
      entry->exec = NULL;
482
 
 
483
 
      g_free (entry->basename);
484
 
      entry->basename = NULL;
485
 
 
486
 
      g_free (entry->path);
487
 
      entry->path = NULL;
488
 
 
489
 
      g_free (entry);
490
 
    }
491
 
}
492
 
 
493
 
DesktopEntryType
494
 
desktop_entry_get_type (DesktopEntry *entry)
495
 
{
496
 
  return entry->type;
497
 
}
498
 
 
499
 
const char *
500
 
desktop_entry_get_path (DesktopEntry *entry)
501
 
{
502
 
  return entry->path;
503
 
}
504
 
 
505
 
const char *
506
 
desktop_entry_get_basename (DesktopEntry *entry)
507
 
{
508
 
  return entry->basename;
509
 
}
510
 
 
511
 
const char *
512
 
desktop_entry_get_name (DesktopEntry *entry)
513
 
{
514
 
  return entry->name;
515
 
}
516
 
 
517
 
const char *
518
 
desktop_entry_get_generic_name (DesktopEntry *entry)
519
 
{
520
 
  return entry->generic_name;
521
 
}
522
 
 
523
 
const char *
524
 
desktop_entry_get_comment (DesktopEntry *entry)
525
 
{
526
 
  return entry->comment;
527
 
}
528
 
 
529
 
const char *
530
 
desktop_entry_get_icon (DesktopEntry *entry)
531
 
{
532
 
  return entry->icon;
533
 
}
534
 
 
535
 
const char *
536
 
desktop_entry_get_exec (DesktopEntry *entry)
537
 
{
538
 
  return entry->exec;
539
 
}
540
 
 
541
 
const GQuark *
542
 
desktop_entry_get_categories (DesktopEntry *entry)
543
 
{
544
 
  return entry->categories;
545
 
}
546
 
 
547
 
gboolean
548
 
desktop_entry_get_launch_in_terminal (DesktopEntry *entry)
549
 
{
550
 
  return entry->terminal;
551
 
}
552
 
 
553
 
gboolean
554
 
desktop_entry_get_use_startup_notify (DesktopEntry *entry)
555
 
{
556
 
  return entry->startup_notify;
557
 
}
558
 
 
559
 
gboolean
560
 
desktop_entry_get_hidden (DesktopEntry *entry)
561
 
{
562
 
  return (entry->flags & DESKTOP_ENTRY_HIDDEN) != 0;
563
 
}
564
 
 
565
 
gboolean
566
 
desktop_entry_get_no_display (DesktopEntry *entry)
567
 
{
568
 
  return (entry->flags & DESKTOP_ENTRY_NO_DISPLAY) != 0;
569
 
}
570
 
 
571
 
gboolean
572
 
desktop_entry_get_show_in_gnome (DesktopEntry *entry)
573
 
{
574
 
  return (entry->flags & DESKTOP_ENTRY_SHOW_IN_GNOME) != 0;
575
 
}
576
 
 
577
 
gboolean
578
 
desktop_entry_get_show_in_flags (DesktopEntry *entry)
579
 
{
580
 
  return entry->show_in_flags;
581
 
}
582
 
 
583
 
gboolean
584
 
desktop_entry_get_tryexec_failed (DesktopEntry *entry)
585
 
{
586
 
  return (entry->flags & DESKTOP_ENTRY_TRYEXEC_FAILED) != 0;
587
 
}
588
 
 
589
 
gboolean
590
 
desktop_entry_has_categories (DesktopEntry *entry)
591
 
{
592
 
  return (entry->categories != NULL && entry->categories[0] != 0);
593
 
}
594
 
 
595
 
gboolean
596
 
desktop_entry_has_category (DesktopEntry *entry,
597
 
                            const char   *category)
598
 
{
599
 
  GQuark quark;
600
 
  int    i;
601
 
 
602
 
  if (entry->categories == NULL)
603
 
    return FALSE;
604
 
 
605
 
  if (!(quark = g_quark_try_string (category)))
606
 
    return FALSE;
607
 
 
608
 
  for (i = 0; entry->categories[i]; i++)
609
 
    {
610
 
      if (quark == entry->categories[i])
611
 
        return TRUE;
612
 
    }
613
 
 
614
 
  return FALSE;
615
 
}
616
 
 
617
 
void
618
 
desktop_entry_add_legacy_category (DesktopEntry *entry)
619
 
{
620
 
  GQuark *categories;
621
 
  int     i;
622
 
 
623
 
  menu_verbose ("Adding Legacy category to \"%s\"\n",
624
 
                entry->basename);
625
 
 
626
 
  i = 0;
627
 
  if (entry->categories != NULL)
628
 
    {
629
 
      for (; entry->categories[i]; i++);
630
 
    }
631
 
 
632
 
  categories = g_new0 (GQuark, i + 2);
633
 
 
634
 
  i = 0;
635
 
  if (entry->categories != NULL)
636
 
    {
637
 
      for (; entry->categories[i]; i++)
638
 
        categories[i] = entry->categories[i];
639
 
    }
640
 
 
641
 
  categories[i] = g_quark_from_string ("Legacy");
642
 
 
643
 
  g_free (entry->categories);
644
 
  entry->categories = categories;
645
 
}
646
 
 
647
 
/*
648
 
 * Entry sets
649
 
 */
650
 
 
651
 
DesktopEntrySet *
652
 
desktop_entry_set_new (void)
653
 
{
654
 
  DesktopEntrySet *set;
655
 
 
656
 
  set = g_new0 (DesktopEntrySet, 1);
657
 
  set->refcount = 1;
658
 
 
659
 
  menu_verbose (" New entry set %p\n", set);
660
 
 
661
 
  return set;
662
 
}
663
 
 
664
 
DesktopEntrySet *
665
 
desktop_entry_set_ref (DesktopEntrySet *set)
666
 
{
667
 
  g_return_val_if_fail (set != NULL, NULL);
668
 
  g_return_val_if_fail (set->refcount > 0, NULL);
669
 
 
670
 
  set->refcount += 1;
671
 
 
672
 
  return set;
673
 
}
674
 
 
675
 
void
676
 
desktop_entry_set_unref (DesktopEntrySet *set)
677
 
{
678
 
  g_return_if_fail (set != NULL);
679
 
  g_return_if_fail (set->refcount > 0);
680
 
 
681
 
  set->refcount -= 1;
682
 
  if (set->refcount == 0)
683
 
    {
684
 
      menu_verbose (" Deleting entry set %p\n", set);
685
 
 
686
 
      if (set->hash)
687
 
        g_hash_table_destroy (set->hash);
688
 
      set->hash = NULL;
689
 
 
690
 
      g_free (set);
691
 
    }
692
 
}
693
 
 
694
 
void
695
 
desktop_entry_set_add_entry (DesktopEntrySet *set,
696
 
                             DesktopEntry    *entry,
697
 
                             const char      *file_id)
698
 
{
699
 
  menu_verbose (" Adding to set %p entry %s\n", set, file_id);
700
 
 
701
 
  if (set->hash == NULL)
702
 
    {
703
 
      set->hash = g_hash_table_new_full (g_str_hash,
704
 
                                         g_str_equal,
705
 
                                         g_free,
706
 
                                         (GDestroyNotify) desktop_entry_unref);
707
 
    }
708
 
 
709
 
  g_hash_table_replace (set->hash,
710
 
                        g_strdup (file_id),
711
 
                        desktop_entry_ref (entry));
712
 
}
713
 
 
714
 
DesktopEntry *
715
 
desktop_entry_set_lookup (DesktopEntrySet *set,
716
 
                          const char      *file_id)
717
 
{
718
 
  if (set->hash == NULL)
719
 
    return NULL;
720
 
 
721
 
  return g_hash_table_lookup (set->hash, file_id);
722
 
}
723
 
 
724
 
typedef struct
725
 
{
726
 
  DesktopEntrySetForeachFunc func;
727
 
  gpointer                   user_data;
728
 
} EntryHashForeachData;
729
 
 
730
 
static void
731
 
entry_hash_foreach (const char           *file_id,
732
 
                    DesktopEntry         *entry,
733
 
                    EntryHashForeachData *fd)
734
 
{
735
 
  fd->func (file_id, entry, fd->user_data);
736
 
}
737
 
 
738
 
void
739
 
desktop_entry_set_foreach (DesktopEntrySet            *set,
740
 
                           DesktopEntrySetForeachFunc  func,
741
 
                           gpointer                    user_data)
742
 
{
743
 
  g_return_if_fail (set != NULL);
744
 
  g_return_if_fail (func != NULL);
745
 
 
746
 
  if (set->hash != NULL)
747
 
    {
748
 
      EntryHashForeachData fd;
749
 
 
750
 
      fd.func      = func;
751
 
      fd.user_data = user_data;
752
 
 
753
 
      g_hash_table_foreach (set->hash,
754
 
                            (GHFunc) entry_hash_foreach,
755
 
                            &fd);
756
 
    }
757
 
}
758
 
 
759
 
static void
760
 
desktop_entry_set_clear (DesktopEntrySet *set)
761
 
{
762
 
  menu_verbose (" Clearing set %p\n", set);
763
 
 
764
 
  if (set->hash != NULL)
765
 
    {
766
 
      g_hash_table_destroy (set->hash);
767
 
      set->hash = NULL;
768
 
    }
769
 
}
770
 
 
771
 
int
772
 
desktop_entry_set_get_count (DesktopEntrySet *set)
773
 
{
774
 
  if (set->hash == NULL)
775
 
    return 0;
776
 
 
777
 
  return g_hash_table_size (set->hash);
778
 
}
779
 
 
780
 
static void
781
 
union_foreach (const char      *file_id,
782
 
               DesktopEntry    *entry,
783
 
               DesktopEntrySet *set)
784
 
{
785
 
  /* we are iterating over "with" adding anything not
786
 
   * already in "set". We unconditionally overwrite
787
 
   * the stuff in "set" because we can assume
788
 
   * two entries with the same name are equivalent.
789
 
   */
790
 
  desktop_entry_set_add_entry (set, entry, file_id);
791
 
}
792
 
 
793
 
void
794
 
desktop_entry_set_union (DesktopEntrySet *set,
795
 
                         DesktopEntrySet *with)
796
 
{
797
 
  menu_verbose (" Union of %p and %p\n", set, with);
798
 
 
799
 
  if (desktop_entry_set_get_count (with) == 0)
800
 
    return; /* A fast simple case */
801
 
 
802
 
  g_hash_table_foreach (with->hash,
803
 
                        (GHFunc) union_foreach,
804
 
                        set);
805
 
}
806
 
 
807
 
typedef struct
808
 
{
809
 
  DesktopEntrySet *set;
810
 
  DesktopEntrySet *with;
811
 
} IntersectData;
812
 
 
813
 
static gboolean
814
 
intersect_foreach_remove (const char    *file_id,
815
 
                          DesktopEntry  *entry,
816
 
                          IntersectData *id)
817
 
{
818
 
  /* Remove everything in "set" which is not in "with" */
819
 
 
820
 
  if (g_hash_table_lookup (id->with->hash, file_id) != NULL)
821
 
    return FALSE;
822
 
 
823
 
  menu_verbose (" Removing from %p entry %s\n", id->set, file_id);
824
 
 
825
 
  return TRUE; /* return TRUE to remove */
826
 
}
827
 
 
828
 
void
829
 
desktop_entry_set_intersection (DesktopEntrySet *set,
830
 
                                DesktopEntrySet *with)
831
 
{
832
 
  IntersectData id;
833
 
 
834
 
  menu_verbose (" Intersection of %p and %p\n", set, with);
835
 
 
836
 
  if (desktop_entry_set_get_count (set) == 0 ||
837
 
      desktop_entry_set_get_count (with) == 0)
838
 
    {
839
 
      /* A fast simple case */
840
 
      desktop_entry_set_clear (set);
841
 
      return;
842
 
    }
843
 
 
844
 
  id.set  = set;
845
 
  id.with = with;
846
 
 
847
 
  g_hash_table_foreach_remove (set->hash,
848
 
                               (GHRFunc) intersect_foreach_remove,
849
 
                               &id);
850
 
}
851
 
 
852
 
typedef struct
853
 
{
854
 
  DesktopEntrySet *set;
855
 
  DesktopEntrySet *other;
856
 
} SubtractData;
857
 
 
858
 
static gboolean
859
 
subtract_foreach_remove (const char   *file_id,
860
 
                         DesktopEntry *entry,
861
 
                         SubtractData *sd)
862
 
{
863
 
  /* Remove everything in "set" which is not in "other" */
864
 
 
865
 
  if (g_hash_table_lookup (sd->other->hash, file_id) == NULL)
866
 
    return FALSE;
867
 
 
868
 
  menu_verbose (" Removing from %p entry %s\n", sd->set, file_id);
869
 
 
870
 
  return TRUE; /* return TRUE to remove */
871
 
}
872
 
 
873
 
void
874
 
desktop_entry_set_subtract (DesktopEntrySet *set,
875
 
                            DesktopEntrySet *other)
876
 
{
877
 
  SubtractData sd;
878
 
 
879
 
  menu_verbose (" Subtract from %p set %p\n", set, other);
880
 
 
881
 
  if (desktop_entry_set_get_count (set) == 0 ||
882
 
      desktop_entry_set_get_count (other) == 0)
883
 
    return; /* A fast simple case */
884
 
 
885
 
  sd.set   = set;
886
 
  sd.other = other;
887
 
 
888
 
  g_hash_table_foreach_remove (set->hash,
889
 
                               (GHRFunc) subtract_foreach_remove,
890
 
                               &sd);
891
 
}
892
 
 
893
 
void
894
 
desktop_entry_set_swap_contents (DesktopEntrySet *a,
895
 
                                 DesktopEntrySet *b)
896
 
{
897
 
  GHashTable *tmp;
898
 
 
899
 
  menu_verbose (" Swap contents of %p and %p\n", a, b);
900
 
 
901
 
  tmp = a->hash;
902
 
  a->hash = b->hash;
903
 
  b->hash = tmp;
904
 
}