9a05370716e39758a3bb677f4e27c229e0bbfb65
[dana/openbox.git] / obt / link.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    obt/link.c for the Openbox window manager
4    Copyright (c) 2009        Dana Jansens
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "obt/link.h"
20 #include "obt/ddparse.h"
21 #include "obt/paths.h"
22 #include <glib.h>
23
24 struct _ObtLink {
25     guint ref;
26
27     ObtLinkType type;
28     gchar *name; /*!< Specific name for the object (eg Firefox) */
29     gboolean display; /*<! When false, do not display this link in menus or
30                            launchers, etc */
31     gboolean deleted; /*<! When true, the Link could exist but is deleted
32                            for the current user */
33     gchar *generic; /*!< Generic name for the object (eg Web Browser) */
34     gchar *comment; /*!< Comment/description to display for the object */
35     gchar *icon; /*!< Name/path for an icon for the object */
36
37     union _ObtLinkData {
38         struct _ObtLinkApp {
39             gchar *exec; /*!< Executable to run for the app */
40             gchar *wdir; /*!< Working dir to run the app in */
41             gboolean term; /*!< Run the app in a terminal or not */
42             ObtLinkAppOpen open;
43
44             /* XXX gchar**? or something better, a mime struct.. maybe
45                glib has something i can use. */
46             gchar **mime; /*!< Mime types the app can open */
47
48             ObtLinkAppStartup startup;
49             gchar *startup_wmclass;
50         } app;
51         struct _ObtLinkLink {
52             gchar *addr;
53         } url;
54         struct _ObtLinkDir {
55         } dir;
56     } d;
57 };
58
59 ObtLink* obt_link_from_ddfile(const gchar *ddname, GSList *paths,
60                               ObtPaths *p)
61 {
62     ObtLink *link;
63     GHashTable *groups, *keys;
64     ObtDDParseGroup *g;
65     ObtDDParseValue *v, *type, *name, *target;
66
67     groups = obt_ddparse_file(ddname, paths);
68     if (!groups) return NULL;
69     g = g_hash_table_lookup(groups, "Desktop Entry");
70     if (!g) {
71         g_hash_table_destroy(groups);
72         return NULL;
73     }
74
75     keys = obt_ddparse_group_keys(g);
76
77     /* check that required keys exist */
78
79     if (!(type = g_hash_table_lookup(keys, "Type")))
80     { g_hash_table_destroy(groups); return NULL; }
81     if (!(name = g_hash_table_lookup(keys, "Name")))
82     { g_hash_table_destroy(groups); return NULL; }
83
84     if (type->value.enumerable == OBT_LINK_TYPE_APPLICATION) {
85         if (!(target = g_hash_table_lookup(keys, "Exec")))
86         { g_hash_table_destroy(groups); return NULL; }
87     }
88     else if (type->value.enumerable == OBT_LINK_TYPE_URL) {
89         if (!(target = g_hash_table_lookup(keys, "URL")))
90         { g_hash_table_destroy(groups); return NULL; }
91     }
92     else
93         target = NULL;
94
95     /* parse all the optional keys and build ObtLink (steal the strings) */
96     link = g_slice_new0(ObtLink);
97     link->ref = 1;
98     link->type = type->value.enumerable;
99     if (link->type == OBT_LINK_TYPE_APPLICATION)
100         link->d.app.exec = target->value.string, target->value.string = NULL;
101     else if (link->type == OBT_LINK_TYPE_URL)
102         link->d.url.addr = target->value.string, target->value.string = NULL;
103     link->display = TRUE;
104
105     if ((v = g_hash_table_lookup(keys, "Hidden")))
106         link->deleted = v->value.boolean;
107
108     if ((v = g_hash_table_lookup(keys, "NoDisplay")))
109         link->display = !v->value.boolean;
110
111     if ((v = g_hash_table_lookup(keys, "GenericName")))
112         link->generic = v->value.string, v->value.string = NULL;
113
114     if ((v = g_hash_table_lookup(keys, "Comment")))
115         link->comment = v->value.string, v->value.string = NULL;
116
117     if ((v = g_hash_table_lookup(keys, "Icon")))
118         link->icon = v->value.string, v->value.string = NULL;
119
120     /* XXX handle Only/NotShowIn, better know the current environment */
121
122     if (link->type == OBT_LINK_TYPE_APPLICATION) {
123         if ((v = g_hash_table_lookup(keys, "TryExec"))) {
124             /* XXX spawn a thread to check TryExec? */
125             link->display = link->display &&
126                 obt_paths_try_exec(p, v->value.string);
127         }
128
129         /* XXX there's more app specific stuff */
130     }
131
132     else if (link->type == OBT_LINK_TYPE_URL) {
133         /* XXX there's URL specific stuff */
134     }
135
136     return link;
137 }
138
139 void obt_link_ref(ObtLink *dd)
140 {
141     ++dd->ref;
142 }
143
144 void obt_link_unref(ObtLink *dd)
145 {
146     if (--dd->ref < 1) {
147         g_slice_free(ObtLink, dd);
148     }
149 }