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-2011 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/bsearch.h"
21 #include "obt/ddparse.h"
22 #include "obt/paths.h"
33 gchar *path; /*!< The path to the file where the link came from */
36 gchar *name; /*!< Specific name for the object (eg Firefox) */
37 gboolean display; /*<! When false, do not display this link in menus or
39 gboolean deleted; /*<! When true, the Link could exist but is deleted
40 for the current user */
41 gchar *generic; /*!< Generic name for the object (eg Web Browser) */
42 gchar *comment; /*!< Comment/description to display for the object */
43 gchar *icon; /*!< Name/path for an icon for the object */
44 guint env_required; /*!< The environments that must be present to use this
46 guint env_restricted; /*!< The environments that must _not_ be present to
51 gchar *exec; /*!< Executable to run for the app */
52 gchar *wdir; /*!< Working dir to run the app in */
53 gboolean term; /*!< Run the app in a terminal or not */
56 gchar **mime; /*!< Mime types the app can open */
58 GQuark *categories; /*!< Array of quarks representing the
59 application's categories */
60 gulong n_categories; /*!< Number of categories for the app */
62 ObtLinkAppStartup startup;
63 gchar *startup_wmclass;
73 ObtLink* obt_link_from_ddfile(const gchar *path, ObtPaths *p,
74 const gchar *language,
76 const gchar *modifier)
79 GHashTable *groups, *keys;
83 /* parse the file, and get a hash table of the groups */
84 groups = obt_ddparse_file(path, language, country, modifier);
85 if (!groups) return NULL; /* parsing failed */
87 /* grab the Desktop Entry group */
88 g = g_hash_table_lookup(groups, "Desktop Entry");
90 /* grab the keys that appeared in the Desktop Entry group */
91 keys = obt_ddparse_group_keys(g);
93 /* build the ObtLink (we steal all strings from the parser) */
94 link = g_slice_new0(ObtLink);
96 link->path = g_strdup(path);
99 v = g_hash_table_lookup(keys, "Type");
101 link->type = v->value.enumerable;
103 if ((v = g_hash_table_lookup(keys, "Hidden")))
104 link->deleted = v->value.boolean;
106 if ((v = g_hash_table_lookup(keys, "NoDisplay")))
107 link->display = !v->value.boolean;
109 if ((v = g_hash_table_lookup(keys, "GenericName")))
110 link->generic = v->value.string, v->value.string = NULL;
112 if ((v = g_hash_table_lookup(keys, "Comment")))
113 link->comment = v->value.string, v->value.string = NULL;
115 if ((v = g_hash_table_lookup(keys, "Icon")))
116 link->icon = v->value.string, v->value.string = NULL;
118 if ((v = g_hash_table_lookup(keys, "OnlyShowIn")))
119 link->env_required = v->value.environments;
121 link->env_required = 0;
123 if ((v = g_hash_table_lookup(keys, "NotShowIn")))
124 link->env_restricted = v->value.environments;
126 link->env_restricted = 0;
128 /* type-specific keys */
130 if (link->type == OBT_LINK_TYPE_APPLICATION) {
134 v = g_hash_table_lookup(keys, "Exec");
136 link->d.app.exec = v->value.string;
137 v->value.string = NULL;
139 /* parse link->d.app.exec to determine link->d.app.open */
141 for (c = link->d.app.exec; *c; ++c) {
144 case 'f': link->d.app.open = OBT_LINK_APP_SINGLE_LOCAL; break;
145 case 'F': link->d.app.open = OBT_LINK_APP_MULTI_LOCAL; break;
146 case 'u': link->d.app.open = OBT_LINK_APP_SINGLE_URL; break;
147 case 'U': link->d.app.open = OBT_LINK_APP_MULTI_URL; break;
148 default: percent = FALSE;
150 if (percent) break; /* found f/F/u/U */
152 else if (*c == '%') percent = TRUE;
155 if ((v = g_hash_table_lookup(keys, "TryExec"))) {
156 /* XXX spawn a thread to check TryExec? */
157 link->display = link->display &&
158 obt_paths_try_exec(p, v->value.string);
161 if ((v = g_hash_table_lookup(keys, "Path"))) {
162 /* steal the string */
163 link->d.app.wdir = v->value.string;
164 v->value.string = NULL;
167 if ((v = g_hash_table_lookup(keys, "Terminal")))
168 link->d.app.term = v->value.boolean;
170 if ((v = g_hash_table_lookup(keys, "StartupNotify")))
171 link->d.app.startup = v->value.boolean ?
172 OBT_LINK_APP_STARTUP_PROTOCOL_SUPPORT :
173 OBT_LINK_APP_STARTUP_NO_SUPPORT;
175 link->d.app.startup = OBT_LINK_APP_STARTUP_LEGACY_SUPPORT;
176 if ((v = g_hash_table_lookup(keys, "StartupWMClass"))) {
177 /* steal the string */
178 link->d.app.startup_wmclass = v->value.string;
179 v->value.string = NULL;
183 if ((v = g_hash_table_lookup(keys, "Categories"))) {
186 link->d.app.categories = g_new(GQuark, v->value.strings.n);
187 link->d.app.n_categories = v->value.strings.n;
189 for (i = 0; i < v->value.strings.n; ++i) {
190 link->d.app.categories[i] =
191 g_quark_from_string(v->value.strings.a[i]);
195 if ((v = g_hash_table_lookup(keys, "MimeType"))) {
196 /* steal the string array */
197 link->d.app.mime = v->value.strings.a;
198 v->value.strings.a = NULL;
199 v->value.strings.n = 0;
202 else if (link->type == OBT_LINK_TYPE_URL) {
203 v = g_hash_table_lookup(keys, "URL");
205 link->d.url.addr = v->value.string;
206 v->value.string = NULL;
209 /* destroy the parsing info */
210 g_hash_table_destroy(groups);
215 void obt_link_ref(ObtLink *dd)
220 void obt_link_unref(ObtLink *dd)
227 if (dd->type == OBT_LINK_TYPE_APPLICATION) {
228 g_free(dd->d.app.exec);
229 g_free(dd->d.app.wdir);
230 g_strfreev(dd->d.app.mime);
231 g_free(dd->d.app.categories);
232 g_free(dd->d.app.startup_wmclass);
234 else if (dd->type == OBT_LINK_TYPE_URL)
235 g_free(dd->d.url.addr);
236 g_slice_free(ObtLink, dd);
240 ObtLinkType obt_link_type (ObtLink *e)
242 g_return_val_if_fail(e != NULL, 0);
247 const GQuark* obt_link_app_categories(ObtLink *e, gulong *n)
249 g_return_val_if_fail(e != NULL, NULL);
250 g_return_val_if_fail(e->type == OBT_LINK_TYPE_APPLICATION, NULL);
251 g_return_val_if_fail(n != NULL, NULL);
253 *n = e->d.app.n_categories;
254 return e->d.app.categories;
257 const gchar *obt_link_source_file(ObtLink *e)
262 gchar* obt_link_id_from_ddfile(const gchar *filename)
264 return obt_ddparse_file_to_id(filename);
267 gboolean obt_link_display(ObtLink *e, const guint environments)
270 /* display if the link wants to be displayed and TryExec passed */
272 /* display if no environment is required, or we match at least one of
274 (!e->env_required || (e->env_required & environments)) &&
275 /* display if no environment is restricted, or we do not match any of
277 (!e->env_restricted || !(e->env_restricted & environments));