1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 obt/link.c for the Openbox window manager
4 Copyright (c) 2009 Dana Jansens
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.
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.
16 See the COPYING file for a copy of the GNU General Public License.
20 #include "obt/ddparse.h"
21 #include "obt/paths.h"
28 gchar *name; /*!< Specific name for the object (eg Firefox) */
29 gboolean display; /*<! When false, do not display this link in menus or
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 guint env_required; /*!< The environments that must be present to use this
38 guint env_restricted; /*!< The environments that must _not_ be present to
43 gchar *exec; /*!< Executable to run for the app */
44 gchar *wdir; /*!< Working dir to run the app in */
45 gboolean term; /*!< Run the app in a terminal or not */
48 gchar **mime; /*!< Mime types the app can open */
50 GQuark *categories; /*!< Array of quarks representing the
51 application's categories */
52 gulong n_categories; /*!< Number of categories for the app */
54 ObtLinkAppStartup startup;
55 gchar *startup_wmclass;
65 ObtLink* obt_link_from_ddfile(const gchar *basepath, const gchar *filename,
69 GHashTable *groups, *keys;
74 /* parse the file, and get a hash table of the groups */
75 path = g_strconcat(basepath, filename, NULL);
76 groups = obt_ddparse_file(path);
78 if (!groups) return NULL; /* parsing failed */
80 /* grab the Desktop Entry group */
81 g = g_hash_table_lookup(groups, "Desktop Entry");
83 /* grab the keys that appeared in the Desktop Entry group */
84 keys = obt_ddparse_group_keys(g);
86 /* build the ObtLink (we steal all strings from the parser) */
87 link = g_slice_new0(ObtLink);
91 v = g_hash_table_lookup(keys, "Type");
93 link->type = v->value.enumerable;
95 if ((v = g_hash_table_lookup(keys, "Hidden")))
96 link->deleted = v->value.boolean;
98 if ((v = g_hash_table_lookup(keys, "NoDisplay")))
99 link->display = !v->value.boolean;
101 if ((v = g_hash_table_lookup(keys, "GenericName")))
102 link->generic = v->value.string, v->value.string = NULL;
104 if ((v = g_hash_table_lookup(keys, "Comment")))
105 link->comment = v->value.string, v->value.string = NULL;
107 if ((v = g_hash_table_lookup(keys, "Icon")))
108 link->icon = v->value.string, v->value.string = NULL;
110 if ((v = g_hash_table_lookup(keys, "OnlyShowIn")))
111 link->env_required = v->value.environments;
113 link->env_required = 0;
115 if ((v = g_hash_table_lookup(keys, "NotShowIn")))
116 link->env_restricted = v->value.environments;
118 link->env_restricted = 0;
120 /* type-specific keys */
122 if (link->type == OBT_LINK_TYPE_APPLICATION) {
126 v = g_hash_table_lookup(keys, "Exec");
128 link->d.app.exec = v->value.string;
129 v->value.string = NULL;
131 /* parse link->d.app.exec to determine link->d.app.open */
133 for (c = link->d.app.exec; *c; ++c) {
136 case 'f': link->d.app.open = OBT_LINK_APP_SINGLE_LOCAL; break;
137 case 'F': link->d.app.open = OBT_LINK_APP_MULTI_LOCAL; break;
138 case 'u': link->d.app.open = OBT_LINK_APP_SINGLE_URL; break;
139 case 'U': link->d.app.open = OBT_LINK_APP_MULTI_URL; break;
140 default: percent = FALSE;
142 if (percent) break; /* found f/F/u/U */
144 else if (*c == '%') percent = TRUE;
147 if ((v = g_hash_table_lookup(keys, "TryExec"))) {
148 /* XXX spawn a thread to check TryExec? */
149 link->display = link->display &&
150 obt_paths_try_exec(p, v->value.string);
153 if ((v = g_hash_table_lookup(keys, "Path"))) {
154 /* steal the string */
155 link->d.app.wdir = v->value.string;
156 v->value.string = NULL;
159 if ((v = g_hash_table_lookup(keys, "Terminal")))
160 link->d.app.term = v->value.boolean;
162 if ((v = g_hash_table_lookup(keys, "StartupNotify")))
163 link->d.app.startup = v->value.boolean ?
164 OBT_LINK_APP_STARTUP_PROTOCOL_SUPPORT :
165 OBT_LINK_APP_STARTUP_NO_SUPPORT;
167 link->d.app.startup = OBT_LINK_APP_STARTUP_LEGACY_SUPPORT;
168 if ((v = g_hash_table_lookup(keys, "StartupWMClass"))) {
169 /* steal the string */
170 link->d.app.startup_wmclass = v->value.string;
171 v->value.string = NULL;
175 if ((v = g_hash_table_lookup(keys, "Categories"))) {
179 link->d.app.categories = g_new(GQuark, v->value.strings.n);
180 link->d.app.n_categories = v->value.strings.n;
182 for (i = 0; i < v->value.strings.n; ++i) {
183 link->d.app.categories[i] =
184 g_quark_from_string(v->value.strings.a[i]);
185 c = end = end+1; /* next */
189 if ((v = g_hash_table_lookup(keys, "MimeType"))) {
190 /* steal the string array */
191 link->d.app.mime = v->value.strings.a;
192 v->value.strings.a = NULL;
193 v->value.strings.n = 0;
196 else if (link->type == OBT_LINK_TYPE_URL) {
197 v = g_hash_table_lookup(keys, "URL");
199 link->d.url.addr = v->value.string;
200 v->value.string = NULL;
203 /* destroy the parsing info */
204 g_hash_table_destroy(groups);
209 void obt_link_ref(ObtLink *dd)
214 void obt_link_unref(ObtLink *dd)
221 if (dd->type == OBT_LINK_TYPE_APPLICATION) {
222 g_free(dd->d.app.exec);
223 g_free(dd->d.app.wdir);
224 g_strfreev(dd->d.app.mime);
225 g_free(dd->d.app.categories);
226 g_free(dd->d.app.startup_wmclass);
228 else if (dd->type == OBT_LINK_TYPE_URL)
229 g_free(dd->d.url.addr);
230 g_slice_free(ObtLink, dd);
234 const GQuark* obt_link_app_categories(ObtLink *e, gulong *n)
236 g_return_val_if_fail(e != NULL, NULL);
237 g_return_val_if_fail(e->type == OBT_LINK_TYPE_APPLICATION, NULL);
238 g_return_val_if_fail(n != NULL, NULL);
240 *n = e->d.app.n_categories;
241 return e->d.app.categories;