/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
- obt/ddfile.c for the Openbox window manager
+ obt/ddparse.c for the Openbox window manager
Copyright (c) 2009 Dana Jansens
This program is free software; you can redistribute it and/or modify
See the COPYING file for a copy of the GNU General Public License.
*/
-#include "obt/ddfile.h"
-#include <glib.h>
+#include "obt/ddparse.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#endif
typedef struct _ObtDDParse ObtDDParse;
-typedef struct _ObtDDParseGroup ObtDDParseGroup;
-typedef void (*ObtDDParseGroupFunc)(gchar *key, const gchar *val,
+/* Parses the value and adds it to the group's key_hash, with the given
+ key */
+typedef void (*ObtDDParseValueFunc)(gchar *key, const gchar *val,
ObtDDParse *parse, gboolean *error);
-struct _ObtDDParseGroup {
- gchar *name;
- gboolean seen;
- ObtDDParseGroupFunc key_func;
- /* the key is a string (a key inside the group in the .desktop).
- the value is an ObtDDParseValue */
- GHashTable *key_hash;
-};
struct _ObtDDParse {
gchar *filename;
GHashTable *group_hash;
};
-typedef enum {
- DATA_STRING,
- DATA_LOCALESTRING,
- DATA_STRINGS,
- DATA_LOCALESTRINGS,
- DATA_BOOLEAN,
- DATA_NUMERIC,
- NUM_DATA_TYPES
-} ObtDDDataType;
-
-typedef struct _ObtDDParseValue {
- ObtDDDataType type;
- union _ObtDDParseValueValue {
- gchar *string;
- struct _ObtDDParseValueStrings {
- gchar *s;
- gulong n;
- } strings;
- gboolean boolean;
- gfloat numeric;
- } value;
-} ObtDDParseValue;
-
-struct _ObtDDFile {
- guint ref;
-
- ObtDDFileType type;
- gchar *name; /*!< Specific name for the object (eg Firefox) */
- gchar *generic; /*!< Generic name for the object (eg Web Browser) */
- gchar *comment; /*!< Comment/description to display for the object */
- gchar *icon; /*!< Name/path for an icon for the object */
-
- union _ObtDDFileData {
- struct _ObtDDFileApp {
- gchar *exec; /*!< Executable to run for the app */
- gchar *wdir; /*!< Working dir to run the app in */
- gboolean term; /*!< Run the app in a terminal or not */
- ObtDDFileAppOpen open;
-
- /* XXX gchar**? or something better, a mime struct.. maybe
- glib has something i can use. */
- gchar **mime; /*!< Mime types the app can open */
-
- ObtDDFileAppStartup startup;
- gchar *startup_wmclass;
- } app;
- struct _ObtDDFileLink {
- gchar *url;
- } link;
- struct _ObtDDFileDir {
- } dir;
- } d;
+struct _ObtDDParseGroup {
+ gchar *name;
+ gboolean seen;
+ ObtDDParseValueFunc value_func;
+ /* the key is a string (a key inside the group in the .desktop).
+ the value is an ObtDDParseValue */
+ GHashTable *key_hash;
};
-static void value_free(ObtDDParseValue *v)
+/* Displays a warning message including the file name and line number, and
+ sets the boolean @error to true if it points to a non-NULL address.
+*/
+static void parse_error(const gchar *m, const ObtDDParse *const parse,
+ gboolean *error)
+{
+ if (!parse->filename)
+ g_warning("%s at line %lu of input", m, parse->lineno);
+ else
+ g_warning("%s at line %lu of file %s",
+ m, parse->lineno, parse->filename);
+ if (error) *error = TRUE;
+}
+
+static void parse_value_free(ObtDDParseValue *v)
{
switch (v->type) {
- case DATA_STRING:
- case DATA_LOCALESTRING:
+ case OBT_DDPARSE_STRING:
+ case OBT_DDPARSE_LOCALESTRING:
g_free(v->value.string); break;
- case DATA_STRINGS:
- case DATA_LOCALESTRINGS:
+ case OBT_DDPARSE_STRINGS:
+ case OBT_DDPARSE_LOCALESTRINGS:
g_free(v->value.strings.s);
v->value.strings.n = 0;
break;
- case DATA_BOOLEAN:
+ case OBT_DDPARSE_BOOLEAN:
break;
- case DATA_NUMERIC:
+ case OBT_DDPARSE_NUMERIC:
break;
default:
g_assert_not_reached();
g_slice_free(ObtDDParseValue, v);
}
-static ObtDDParseGroup* group_new(gchar *name, ObtDDParseGroupFunc f)
+static ObtDDParseGroup* parse_group_new(gchar *name, ObtDDParseValueFunc f)
{
ObtDDParseGroup *g = g_slice_new(ObtDDParseGroup);
g->name = name;
- g->key_func = f;
+ g->value_func = f;
g->seen = FALSE;
g->key_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, (GDestroyNotify)value_free);
+ g_free,
+ (GDestroyNotify)parse_value_free);
return g;
}
-static void group_free(ObtDDParseGroup *g)
+static void parse_group_free(ObtDDParseGroup *g)
{
g_free(g->name);
g_hash_table_destroy(g->key_hash);
g_slice_free(ObtDDParseGroup, g);
}
-/* Displays a warning message including the file name and line number, and
- sets the boolean @error to true if it points to a non-NULL address.
-*/
-static void parse_error(const gchar *m, const ObtDDParse *const parse,
- gboolean *error)
-{
- if (!parse->filename)
- g_warning("%s at line %lu of input", m, parse->lineno);
- else
- g_warning("%s at line %lu of file %s",
- m, parse->lineno, parse->filename);
- if (error) *error = TRUE;
-}
-
-/* reads an input string, strips out invalid stuff, and parses
- backslash-stuff
- if @nstrings is not NULL, then it splits the output string at ';'
- characters. they are all returned in the same string with null zeros
- between them, @nstrings is set to the number of such strings.
+/*! Reads an input string, strips out invalid stuff, and parses
+ backslash-stuff.
+ If @nstrings is not NULL, then it splits the output string at ';'
+ characters. They are all returned in the same string with null zeros
+ between them, @nstrings is set to the number of such strings.
*/
-static gchar* parse_string(const gchar *in,
- gboolean locale,
- gulong *nstrings,
- const ObtDDParse *const parse,
- gboolean *error)
+static gchar* parse_value_string(const gchar *in,
+ gboolean locale,
+ gulong *nstrings,
+ const ObtDDParse *const parse,
+ gboolean *error)
{
const gint bytes = strlen(in);
gboolean backslash;
if (!locale) {
end = in + bytes;
for (i = in; i < end; ++i) {
- if ((guchar)*i > 126 || (guchar)*i < 32) {
+ if ((guchar)*i >= 127 || (guchar)*i < 32) {
/* non-control character ascii */
end = i;
parse_error("Invalid bytes in string", parse, error);
++nstrings;
*o = '\0';
}
- else if ((guchar)*i >= 127 || (guchar)*i < 32) {
+ else if ((guchar)*i == 127 || (guchar)*i < 32) {
/* avoid ascii control characters */
parse_error("Found control character in string", parse, error);
break;
return o;
}
-static gboolean parse_bool(const gchar *in, const ObtDDParse *const parse,
- gboolean *error)
+static gboolean parse_value_boolean(const gchar *in,
+ const ObtDDParse *const parse,
+ gboolean *error)
{
if (strcmp(in, "true") == 0)
return TRUE;
return FALSE;
}
-static gfloat parse_numeric(const gchar *in, const ObtDDParse *const parse,
- gboolean *error)
+static gfloat parse_value_numeric(const gchar *in,
+ const ObtDDParse *const parse,
+ gboolean *error)
{
gfloat out = 0;
if (sscanf(in, "%f", &out) == 0)
return out;
}
-static void parse_group_desktop_entry(gchar *key, const gchar *val,
- ObtDDParse *parse, gboolean *error)
-{
- ObtDDParseValue v, *pv;
-
- /* figure out value type */
- v.type = NUM_DATA_TYPES;
-
- /* parse the value */
-
- switch (v.type) {
- case DATA_STRING:
- v.value.string = parse_string(val, FALSE, NULL, parse, error);
- g_assert(v.value.string);
- break;
- case DATA_LOCALESTRING:
- v.value.string = parse_string(val, TRUE, NULL, parse, error);
- g_assert(v.value.string);
- break;
- case DATA_STRINGS:
- v.value.strings.s = parse_string(val, FALSE, &v.value.strings.n,
- parse, error);
- g_assert(v.value.strings.s);
- g_assert(v.value.strings.n);
- break;
- case DATA_LOCALESTRINGS:
- v.value.strings.s = parse_string(val, TRUE, &v.value.strings.n,
- parse, error);
- g_assert(v.value.strings.s);
- g_assert(v.value.strings.n);
- break;
- case DATA_BOOLEAN:
- v.value.boolean = parse_bool(val, parse, error);
- break;
- case DATA_NUMERIC:
- v.value.numeric = parse_numeric(val, parse, error);
- break;
- default:
- g_assert_not_reached();
- }
-
- pv = g_slice_new(ObtDDParseValue);
- *pv = v;
- g_hash_table_insert(parse->group->key_hash, key, pv);
-}
-
static gboolean parse_file_line(FILE *f, gchar **buf,
gulong *size, gulong *read,
ObtDDParse *parse, gboolean *error)
}
else {
if (!g) {
- g = group_new(group, NULL);
+ g = parse_group_new(group, NULL);
g_hash_table_insert(parse->group_hash, g->name, g);
}
else
return;
}
g_print("Found key/value %s=%s.\n", key, buf+valstart);
- if (parse->group->key_func)
- parse->group->key_func(key, buf+valstart, parse, error);
+ if (parse->group->value_func)
+ parse->group->value_func(key, buf+valstart, parse, error);
}
-static gboolean parse_file(ObtDDFile *dd, FILE *f, ObtDDParse *parse)
+static gboolean parse_file(FILE *f, ObtDDParse *parse)
{
gchar *buf = NULL;
gulong bytes = 0, read = 0;
gboolean error = FALSE;
while (!error && parse_file_line(f, &buf, &bytes, &read, parse, &error)) {
- /* XXX use the string in buf */
gulong len = strlen(buf);
if (buf[0] == '#' || buf[0] == '\0')
; /* ignore comment lines */
return !error;
}
-ObtDDFile* obt_ddfile_new_from_file(const gchar *name, GSList *paths)
+static void parse_desktop_entry_value(gchar *key, const gchar *val,
+ ObtDDParse *parse, gboolean *error)
+{
+ ObtDDParseValue v, *pv;
+
+ /* figure out value type */
+ v.type = OBT_DDPARSE_NUM_VALUE_TYPES;
+ /* XXX do this part */
+
+ /* parse the value */
+ switch (v.type) {
+ case OBT_DDPARSE_STRING:
+ v.value.string = parse_value_string(val, FALSE, NULL, parse, error);
+ g_assert(v.value.string);
+ break;
+ case OBT_DDPARSE_LOCALESTRING:
+ v.value.string = parse_value_string(val, TRUE, NULL, parse, error);
+ g_assert(v.value.string);
+ break;
+ case OBT_DDPARSE_STRINGS:
+ v.value.strings.s = parse_value_string(val, FALSE, &v.value.strings.n,
+ parse, error);
+ g_assert(v.value.strings.s);
+ g_assert(v.value.strings.n);
+ break;
+ case OBT_DDPARSE_LOCALESTRINGS:
+ v.value.strings.s = parse_value_string(val, TRUE, &v.value.strings.n,
+ parse, error);
+ g_assert(v.value.strings.s);
+ g_assert(v.value.strings.n);
+ break;
+ case OBT_DDPARSE_BOOLEAN:
+ v.value.boolean = parse_value_boolean(val, parse, error);
+ break;
+ case OBT_DDPARSE_NUMERIC:
+ v.value.numeric = parse_value_numeric(val, parse, error);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ pv = g_slice_new(ObtDDParseValue);
+ *pv = v;
+ g_hash_table_insert(parse->group->key_hash, key, pv);
+}
+
+GHashTable* obt_ddparse_file(const gchar *name, GSList *paths)
{
- ObtDDFile *dd;
ObtDDParse parse;
ObtDDParseGroup *desktop_entry;
GSList *it;
FILE *f;
gboolean success;
- dd = g_slice_new(ObtDDFile);
- dd->ref = 1;
-
parse.filename = NULL;
parse.lineno = 0;
parse.group = NULL;
parse.group_hash = g_hash_table_new_full(g_str_hash,
g_str_equal,
NULL,
- (GDestroyNotify)group_free);
+ (GDestroyNotify)parse_group_free);
/* set up the groups (there's only one right now) */
- desktop_entry = group_new(g_strdup("Desktop Entry"),
- parse_group_desktop_entry);
+ desktop_entry = parse_group_new(g_strdup("Desktop Entry"),
+ parse_desktop_entry_value);
g_hash_table_insert(parse.group_hash, desktop_entry->name, desktop_entry);
success = FALSE;
if ((f = fopen(path, "r"))) {
parse.filename = path;
parse.lineno = 1;
- success = parse_file(dd, f, &parse);
+ success = parse_file(f, &parse);
fclose(f);
}
g_free(path);
}
if (!success) {
- obt_ddfile_unref(dd);
- dd = NULL;
+ g_hash_table_destroy(parse.group_hash);
+ return NULL;
}
-
- g_hash_table_destroy(parse.group_hash);
-
- return dd;
-}
-
-void obt_ddfile_ref(ObtDDFile *dd)
-{
- ++dd->ref;
+ else
+ return parse.group_hash;
}
-void obt_ddfile_unref(ObtDDFile *dd)
+GHashTable* obt_ddparse_group_keys(ObtDDParseGroup *g)
{
- if (--dd->ref < 1) {
- g_slice_free(ObtDDFile, dd);
- }
+ return g->key_hash;
}
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
- obt/ddfile.h for the Openbox window manager
+ obt/link.h for the Openbox window manager
Copyright (c) 2009 Dana Jansens
This program is free software; you can redistribute it and/or modify
See the COPYING file for a copy of the GNU General Public License.
*/
-#ifndef __obt_ddfile_h
-#define __obt_ddfile_h
+#ifndef __obt_link_h
+#define __obt_link_h
#include <glib.h>
G_BEGIN_DECLS
typedef enum {
- OBT_DDFILE_TYPE_APPLICATION = 1,
- OBT_DDFILE_TYPE_LINK = 2,
- OBT_DDFILE_TYPE_DIRECTORY = 3
-} ObtDDFileType;
+ OBT_LINK_TYPE_APPLICATION = 1,
+ OBT_LINK_TYPE_URL = 2,
+ OBT_LINK_TYPE_DIRECTORY = 3
+} ObtLinkType;
typedef enum {
- OBT_DDFILE_APP_STARTUP_NO_SUPPORT,
- OBT_DDFILE_APP_STARTUP_PROTOCOL_SUPPORT,
- OBT_DDFILE_APP_STARTUP_LEGACY_SUPPORT
-} ObtDDFileAppStartup;
+ OBT_LINK_APP_STARTUP_NO_SUPPORT,
+ OBT_LINK_APP_STARTUP_PROTOCOL_SUPPORT,
+ OBT_LINK_APP_STARTUP_LEGACY_SUPPORT
+} ObtLinkAppStartup;
typedef enum {
/*! The app can be launched with a single local file */
- OBT_DDFILE_APP_SINGLE_LOCAL = 1 << 0,
+ OBT_LINK_APP_SINGLE_LOCAL = 1 << 0,
/*! The app can be launched with multiple local files */
- OBT_DDFILE_APP_MULTI_LOCAL = 1 << 1,
+ OBT_LINK_APP_MULTI_LOCAL = 1 << 1,
/*! The app can be launched with a single URL */
- OBT_DDFILE_APP_SINGLE_URL = 1 << 2,
+ OBT_LINK_APP_SINGLE_URL = 1 << 2,
/*! The app can be launched with multiple URLs */
- OBT_DDFILE_APP_MULTI_URL = 1 << 3
-} ObtDDFileAppOpen;
+ OBT_LINK_APP_MULTI_URL = 1 << 3
+} ObtLinkAppOpen;
-typedef struct _ObtDDFile ObtDDFile;
+typedef struct _ObtLink ObtLink;
-ObtDDFile* obt_ddfile_new_from_file(const gchar *name, GSList *paths);
+ObtLink* obt_link_from_ddfile(const gchar *name, GSList *paths);
-void obt_ddfile_ref(ObtDDFile *e);
-void obt_ddfile_unref(ObtDDFile *e);
+void obt_link_ref(ObtLink *e);
+void obt_link_unref(ObtLink *e);
/*! Returns TRUE if the file exists but says it should be ignored, with
- the Hidden flag. No other functions can be used for the ObtDDFile
+ the Hidden flag. No other functions can be used for the ObtLink
in this case. */
-gboolean obt_ddfile_deleted (ObtDDFile *e);
+gboolean obt_link_deleted (ObtLink *e);
/*! Returns the type of object refered to by the .desktop file. */
-ObtDDFileType obt_ddfile_type (ObtDDFile *e);
+ObtLinkType obt_link_type (ObtLink *e);
/*! Returns TRUE if the .desktop file should be displayed to users, given the
current environment. If FALSE, the .desktop file should not be showed.
@env A semicolon-deliminated list of environemnts. Can be one or more of:
GNOME, KDE, ROX, XFCE. Other environments not listed here may also
be supported. This can be null also if not listing any environment. */
-gboolean obt_ddfile_display(ObtDDFile *e, const gchar *env);
+gboolean obt_link_display(ObtLink *e, const gchar *env);
-const gchar* obt_ddfile_name (ObtDDFile *e);
-const gchar* obt_ddfile_generic_name (ObtDDFile *e);
-const gchar* obt_ddfile_comment (ObtDDFile *e);
+const gchar* obt_link_name (ObtLink *e);
+const gchar* obt_link_generic_name (ObtLink *e);
+const gchar* obt_link_comment (ObtLink *e);
/*! Returns the icon for the object referred to by the .desktop file.
Returns either an absolute path, or a string which can be used to find the
icon using the algorithm given by:
http://freedesktop.org/wiki/Specifications/icon-theme-spec?action=show&redirect=Standards/icon-theme-spec
*/
-const gchar* obt_ddfile_icon (ObtDDFile *e);
+const gchar* obt_link_icon (ObtLink *e);
-const gchar *obt_ddfile_link_url(ObtDDFile *e);
+const gchar *obt_link_url_path(ObtLink *e);
-const gchar* obt_ddfile_app_executable (ObtDDFile *e);
+const gchar* obt_link_app_executable (ObtLink *e);
/*! Returns the path in which the application should be run */
-const gchar* obt_ddfile_app_path (ObtDDFile *e);
-gboolean obt_ddfile_app_run_in_terminal (ObtDDFile *e);
-const gchar** obt_ddfile_app_mime_types (ObtDDFile *e);
-/*! Returns a combination of values in the ObtDDFileAppOpen enum,
+const gchar* obt_link_app_path (ObtLink *e);
+gboolean obt_link_app_run_in_terminal (ObtLink *e);
+const gchar** obt_link_app_mime_types (ObtLink *e);
+/*! Returns a combination of values in the ObtLinkAppOpen enum,
specifying if the application can be launched to open one or more files
and URLs. */
-ObtDDFileAppOpen obt_ddfile_app_open(ObtDDFile *e);
+ObtLinkAppOpen obt_link_app_open(ObtLink *e);
-ObtDDFileAppStartup obt_ddfile_app_startup_notify(ObtDDFile *e);
-const gchar* obt_ddfile_app_startup_wmclass(ObtDDFile *e);
+ObtLinkAppStartup obt_link_app_startup_notify(ObtLink *e);
+const gchar* obt_link_app_startup_wmclass(ObtLink *e);
G_END_DECLS