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"
27 gchar *path; /*!< The path to the file where the link came from */
30 gchar *name; /*!< Specific name for the object (eg Firefox) */
31 gboolean display; /*<! When false, do not display this link in menus or
33 gboolean deleted; /*<! When true, the Link could exist but is deleted
34 for the current user */
35 gchar *generic; /*!< Generic name for the object (eg Web Browser) */
36 gchar *comment; /*!< Comment/description to display for the object */
37 gchar *icon; /*!< Name/path for an icon for the object */
38 guint env_required; /*!< The environments that must be present to use this
40 guint env_restricted; /*!< The environments that must _not_ be present to
45 gchar *exec; /*!< Executable to run for the app */
46 gchar *wdir; /*!< Working dir to run the app in */
47 gboolean term; /*!< Run the app in a terminal or not */
50 gchar **mime; /*!< Mime types the app can open */
52 GQuark *categories; /*!< Array of quarks representing the
53 application's categories */
54 gulong n_categories; /*!< Number of categories for the app */
56 ObtLinkAppStartup startup;
57 gchar *startup_wmclass;
67 ObtLink* obt_link_from_ddfile(const gchar *path, ObtPaths *p,
68 const gchar *language,
70 const gchar *modifier)
73 GHashTable *groups, *keys;
77 /* parse the file, and get a hash table of the groups */
78 groups = obt_ddparse_file(path, language, country, modifier);
79 if (!groups) return NULL; /* parsing failed */
81 /* grab the Desktop Entry group */
82 g = g_hash_table_lookup(groups, "Desktop Entry");
84 /* grab the keys that appeared in the Desktop Entry group */
85 keys = obt_ddparse_group_keys(g);
87 /* build the ObtLink (we steal all strings from the parser) */
88 link = g_slice_new0(ObtLink);
90 link->path = g_strdup(path);
93 v = g_hash_table_lookup(keys, "Type");
95 link->type = v->value.enumerable;
97 if ((v = g_hash_table_lookup(keys, "Hidden")))
98 link->deleted = v->value.boolean;
100 if ((v = g_hash_table_lookup(keys, "NoDisplay")))
101 link->display = !v->value.boolean;
103 if ((v = g_hash_table_lookup(keys, "GenericName")))
104 link->generic = v->value.string, v->value.string = NULL;
106 if ((v = g_hash_table_lookup(keys, "Comment")))
107 link->comment = v->value.string, v->value.string = NULL;
109 if ((v = g_hash_table_lookup(keys, "Icon")))
110 link->icon = v->value.string, v->value.string = NULL;
112 if ((v = g_hash_table_lookup(keys, "OnlyShowIn")))
113 link->env_required = v->value.environments;
115 link->env_required = 0;
117 if ((v = g_hash_table_lookup(keys, "NotShowIn")))
118 link->env_restricted = v->value.environments;
120 link->env_restricted = 0;
122 /* type-specific keys */
124 if (link->type == OBT_LINK_TYPE_APPLICATION) {
128 v = g_hash_table_lookup(keys, "Exec");
130 link->d.app.exec = v->value.string;
131 v->value.string = NULL;
133 /* parse link->d.app.exec to determine link->d.app.open */
135 for (c = link->d.app.exec; *c; ++c) {
138 case 'f': link->d.app.open = OBT_LINK_APP_SINGLE_LOCAL; break;
139 case 'F': link->d.app.open = OBT_LINK_APP_MULTI_LOCAL; break;
140 case 'u': link->d.app.open = OBT_LINK_APP_SINGLE_URL; break;
141 case 'U': link->d.app.open = OBT_LINK_APP_MULTI_URL; break;
142 default: percent = FALSE;
144 if (percent) break; /* found f/F/u/U */
146 else if (*c == '%') percent = TRUE;
149 if ((v = g_hash_table_lookup(keys, "TryExec"))) {
150 /* XXX spawn a thread to check TryExec? */
151 link->display = link->display &&
152 obt_paths_try_exec(p, v->value.string);
155 if ((v = g_hash_table_lookup(keys, "Path"))) {
156 /* steal the string */
157 link->d.app.wdir = v->value.string;
158 v->value.string = NULL;
161 if ((v = g_hash_table_lookup(keys, "Terminal")))
162 link->d.app.term = v->value.boolean;
164 if ((v = g_hash_table_lookup(keys, "StartupNotify")))
165 link->d.app.startup = v->value.boolean ?
166 OBT_LINK_APP_STARTUP_PROTOCOL_SUPPORT :
167 OBT_LINK_APP_STARTUP_NO_SUPPORT;
169 link->d.app.startup = OBT_LINK_APP_STARTUP_LEGACY_SUPPORT;
170 if ((v = g_hash_table_lookup(keys, "StartupWMClass"))) {
171 /* steal the string */
172 link->d.app.startup_wmclass = v->value.string;
173 v->value.string = NULL;
177 if ((v = g_hash_table_lookup(keys, "Categories"))) {
181 link->d.app.categories = g_new(GQuark, v->value.strings.n);
182 link->d.app.n_categories = v->value.strings.n;
184 for (i = 0; i < v->value.strings.n; ++i) {
185 link->d.app.categories[i] =
186 g_quark_from_string(v->value.strings.a[i]);
187 c = end = end+1; /* next */
191 if ((v = g_hash_table_lookup(keys, "MimeType"))) {
192 /* steal the string array */
193 link->d.app.mime = v->value.strings.a;
194 v->value.strings.a = NULL;
195 v->value.strings.n = 0;
198 else if (link->type == OBT_LINK_TYPE_URL) {
199 v = g_hash_table_lookup(keys, "URL");
201 link->d.url.addr = v->value.string;
202 v->value.string = NULL;
205 /* destroy the parsing info */
206 g_hash_table_destroy(groups);
211 void obt_link_ref(ObtLink *dd)
216 void obt_link_unref(ObtLink *dd)
223 if (dd->type == OBT_LINK_TYPE_APPLICATION) {
224 g_free(dd->d.app.exec);
225 g_free(dd->d.app.wdir);
226 g_strfreev(dd->d.app.mime);
227 g_free(dd->d.app.categories);
228 g_free(dd->d.app.startup_wmclass);
230 else if (dd->type == OBT_LINK_TYPE_URL)
231 g_free(dd->d.url.addr);
232 g_slice_free(ObtLink, dd);
236 const GQuark* obt_link_app_categories(ObtLink *e, gulong *n)
238 g_return_val_if_fail(e != NULL, NULL);
239 g_return_val_if_fail(e->type == OBT_LINK_TYPE_APPLICATION, NULL);
240 g_return_val_if_fail(n != NULL, NULL);
242 *n = e->d.app.n_categories;
243 return e->d.app.categories;
246 const gchar *obt_link_source_file(ObtLink *e)
251 gchar* obt_link_id_from_ddfile(const gchar *filename)
253 return obt_ddparse_file_to_id(filename);