Add a new ObtLink type, which is going to be a generalization of a .desktop entry.
Move the .desktop file parsing details into obt/ddparse.c, which generates some hash tables holding the data of the file. Add a new obt/link.c which will build an ObtLink from a parsed .desktop file, and may support other ways to create these links in the unforseeable future
This commit is contained in:
parent
fbc0597d3f
commit
0d90bd57ab
5 changed files with 312 additions and 235 deletions
|
@ -135,8 +135,10 @@ obt_libobt_la_SOURCES = \
|
||||||
obt/mainloop.c \
|
obt/mainloop.c \
|
||||||
obt/xml.h \
|
obt/xml.h \
|
||||||
obt/xml.c \
|
obt/xml.c \
|
||||||
obt/ddfile.h \
|
obt/ddparse.h \
|
||||||
obt/ddfile.c \
|
obt/ddparse.c \
|
||||||
|
obt/link.h \
|
||||||
|
obt/link.c \
|
||||||
obt/paths.h \
|
obt/paths.h \
|
||||||
obt/paths.c \
|
obt/paths.c \
|
||||||
obt/prop.h \
|
obt/prop.h \
|
||||||
|
@ -429,7 +431,7 @@ rrpubinclude_HEADERS = \
|
||||||
obrender/version.h
|
obrender/version.h
|
||||||
|
|
||||||
obtpubinclude_HEADERS = \
|
obtpubinclude_HEADERS = \
|
||||||
obt/ddfile.h \
|
obt/link.h \
|
||||||
obt/display.h \
|
obt/display.h \
|
||||||
obt/keyboard.h \
|
obt/keyboard.h \
|
||||||
obt/mainloop.h \
|
obt/mainloop.h \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
|
/* -*- 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
|
Copyright (c) 2009 Dana Jansens
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -16,8 +16,7 @@
|
||||||
See the COPYING file for a copy of the GNU General Public License.
|
See the COPYING file for a copy of the GNU General Public License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "obt/ddfile.h"
|
#include "obt/ddparse.h"
|
||||||
#include <glib.h>
|
|
||||||
#ifdef HAVE_STRING_H
|
#ifdef HAVE_STRING_H
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,19 +25,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct _ObtDDParse ObtDDParse;
|
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);
|
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 {
|
struct _ObtDDParse {
|
||||||
gchar *filename;
|
gchar *filename;
|
||||||
|
@ -48,99 +40,15 @@ struct _ObtDDParse {
|
||||||
GHashTable *group_hash;
|
GHashTable *group_hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
struct _ObtDDParseGroup {
|
||||||
DATA_STRING,
|
gchar *name;
|
||||||
DATA_LOCALESTRING,
|
gboolean seen;
|
||||||
DATA_STRINGS,
|
ObtDDParseValueFunc value_func;
|
||||||
DATA_LOCALESTRINGS,
|
/* the key is a string (a key inside the group in the .desktop).
|
||||||
DATA_BOOLEAN,
|
the value is an ObtDDParseValue */
|
||||||
DATA_NUMERIC,
|
GHashTable *key_hash;
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void value_free(ObtDDParseValue *v)
|
|
||||||
{
|
|
||||||
switch (v->type) {
|
|
||||||
case DATA_STRING:
|
|
||||||
case DATA_LOCALESTRING:
|
|
||||||
g_free(v->value.string); break;
|
|
||||||
case DATA_STRINGS:
|
|
||||||
case DATA_LOCALESTRINGS:
|
|
||||||
g_free(v->value.strings.s);
|
|
||||||
v->value.strings.n = 0;
|
|
||||||
break;
|
|
||||||
case DATA_BOOLEAN:
|
|
||||||
break;
|
|
||||||
case DATA_NUMERIC:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
g_slice_free(ObtDDParseValue, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ObtDDParseGroup* group_new(gchar *name, ObtDDParseGroupFunc f)
|
|
||||||
{
|
|
||||||
ObtDDParseGroup *g = g_slice_new(ObtDDParseGroup);
|
|
||||||
g->name = name;
|
|
||||||
g->key_func = f;
|
|
||||||
g->seen = FALSE;
|
|
||||||
g->key_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
|
|
||||||
g_free, (GDestroyNotify)value_free);
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void 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
|
/* 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.
|
sets the boolean @error to true if it points to a non-NULL address.
|
||||||
*/
|
*/
|
||||||
|
@ -155,17 +63,57 @@ static void parse_error(const gchar *m, const ObtDDParse *const parse,
|
||||||
if (error) *error = TRUE;
|
if (error) *error = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reads an input string, strips out invalid stuff, and parses
|
static void parse_value_free(ObtDDParseValue *v)
|
||||||
backslash-stuff
|
{
|
||||||
if @nstrings is not NULL, then it splits the output string at ';'
|
switch (v->type) {
|
||||||
characters. they are all returned in the same string with null zeros
|
case OBT_DDPARSE_STRING:
|
||||||
between them, @nstrings is set to the number of such strings.
|
case OBT_DDPARSE_LOCALESTRING:
|
||||||
|
g_free(v->value.string); break;
|
||||||
|
case OBT_DDPARSE_STRINGS:
|
||||||
|
case OBT_DDPARSE_LOCALESTRINGS:
|
||||||
|
g_free(v->value.strings.s);
|
||||||
|
v->value.strings.n = 0;
|
||||||
|
break;
|
||||||
|
case OBT_DDPARSE_BOOLEAN:
|
||||||
|
break;
|
||||||
|
case OBT_DDPARSE_NUMERIC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
g_slice_free(ObtDDParseValue, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ObtDDParseGroup* parse_group_new(gchar *name, ObtDDParseValueFunc f)
|
||||||
|
{
|
||||||
|
ObtDDParseGroup *g = g_slice_new(ObtDDParseGroup);
|
||||||
|
g->name = name;
|
||||||
|
g->value_func = f;
|
||||||
|
g->seen = FALSE;
|
||||||
|
g->key_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||||
|
g_free,
|
||||||
|
(GDestroyNotify)parse_value_free);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_group_free(ObtDDParseGroup *g)
|
||||||
|
{
|
||||||
|
g_free(g->name);
|
||||||
|
g_hash_table_destroy(g->key_hash);
|
||||||
|
g_slice_free(ObtDDParseGroup, g);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! 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,
|
static gchar* parse_value_string(const gchar *in,
|
||||||
gboolean locale,
|
gboolean locale,
|
||||||
gulong *nstrings,
|
gulong *nstrings,
|
||||||
const ObtDDParse *const parse,
|
const ObtDDParse *const parse,
|
||||||
gboolean *error)
|
gboolean *error)
|
||||||
{
|
{
|
||||||
const gint bytes = strlen(in);
|
const gint bytes = strlen(in);
|
||||||
gboolean backslash;
|
gboolean backslash;
|
||||||
|
@ -177,7 +125,7 @@ static gchar* parse_string(const gchar *in,
|
||||||
if (!locale) {
|
if (!locale) {
|
||||||
end = in + bytes;
|
end = in + bytes;
|
||||||
for (i = in; i < end; ++i) {
|
for (i = in; i < end; ++i) {
|
||||||
if ((guchar)*i > 126 || (guchar)*i < 32) {
|
if ((guchar)*i >= 127 || (guchar)*i < 32) {
|
||||||
/* non-control character ascii */
|
/* non-control character ascii */
|
||||||
end = i;
|
end = i;
|
||||||
parse_error("Invalid bytes in string", parse, error);
|
parse_error("Invalid bytes in string", parse, error);
|
||||||
|
@ -217,7 +165,7 @@ static gchar* parse_string(const gchar *in,
|
||||||
++nstrings;
|
++nstrings;
|
||||||
*o = '\0';
|
*o = '\0';
|
||||||
}
|
}
|
||||||
else if ((guchar)*i >= 127 || (guchar)*i < 32) {
|
else if ((guchar)*i == 127 || (guchar)*i < 32) {
|
||||||
/* avoid ascii control characters */
|
/* avoid ascii control characters */
|
||||||
parse_error("Found control character in string", parse, error);
|
parse_error("Found control character in string", parse, error);
|
||||||
break;
|
break;
|
||||||
|
@ -232,8 +180,9 @@ static gchar* parse_string(const gchar *in,
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean parse_bool(const gchar *in, const ObtDDParse *const parse,
|
static gboolean parse_value_boolean(const gchar *in,
|
||||||
gboolean *error)
|
const ObtDDParse *const parse,
|
||||||
|
gboolean *error)
|
||||||
{
|
{
|
||||||
if (strcmp(in, "true") == 0)
|
if (strcmp(in, "true") == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -242,8 +191,9 @@ static gboolean parse_bool(const gchar *in, const ObtDDParse *const parse,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gfloat parse_numeric(const gchar *in, const ObtDDParse *const parse,
|
static gfloat parse_value_numeric(const gchar *in,
|
||||||
gboolean *error)
|
const ObtDDParse *const parse,
|
||||||
|
gboolean *error)
|
||||||
{
|
{
|
||||||
gfloat out = 0;
|
gfloat out = 0;
|
||||||
if (sscanf(in, "%f", &out) == 0)
|
if (sscanf(in, "%f", &out) == 0)
|
||||||
|
@ -251,52 +201,6 @@ static gfloat parse_numeric(const gchar *in, const ObtDDParse *const parse,
|
||||||
return out;
|
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,
|
static gboolean parse_file_line(FILE *f, gchar **buf,
|
||||||
gulong *size, gulong *read,
|
gulong *size, gulong *read,
|
||||||
ObtDDParse *parse, gboolean *error)
|
ObtDDParse *parse, gboolean *error)
|
||||||
|
@ -417,7 +321,7 @@ static void parse_group(const gchar *buf, gulong len,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!g) {
|
if (!g) {
|
||||||
g = group_new(group, NULL);
|
g = parse_group_new(group, NULL);
|
||||||
g_hash_table_insert(parse->group_hash, g->name, g);
|
g_hash_table_insert(parse->group_hash, g->name, g);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -482,18 +386,17 @@ static void parse_key_value(const gchar *buf, gulong len,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_print("Found key/value %s=%s.\n", key, buf+valstart);
|
g_print("Found key/value %s=%s.\n", key, buf+valstart);
|
||||||
if (parse->group->key_func)
|
if (parse->group->value_func)
|
||||||
parse->group->key_func(key, buf+valstart, parse, error);
|
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;
|
gchar *buf = NULL;
|
||||||
gulong bytes = 0, read = 0;
|
gulong bytes = 0, read = 0;
|
||||||
gboolean error = FALSE;
|
gboolean error = FALSE;
|
||||||
|
|
||||||
while (!error && parse_file_line(f, &buf, &bytes, &read, parse, &error)) {
|
while (!error && parse_file_line(f, &buf, &bytes, &read, parse, &error)) {
|
||||||
/* XXX use the string in buf */
|
|
||||||
gulong len = strlen(buf);
|
gulong len = strlen(buf);
|
||||||
if (buf[0] == '#' || buf[0] == '\0')
|
if (buf[0] == '#' || buf[0] == '\0')
|
||||||
; /* ignore comment lines */
|
; /* ignore comment lines */
|
||||||
|
@ -512,29 +415,71 @@ static gboolean parse_file(ObtDDFile *dd, FILE *f, ObtDDParse *parse)
|
||||||
return !error;
|
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;
|
ObtDDParse parse;
|
||||||
ObtDDParseGroup *desktop_entry;
|
ObtDDParseGroup *desktop_entry;
|
||||||
GSList *it;
|
GSList *it;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
|
|
||||||
dd = g_slice_new(ObtDDFile);
|
|
||||||
dd->ref = 1;
|
|
||||||
|
|
||||||
parse.filename = NULL;
|
parse.filename = NULL;
|
||||||
parse.lineno = 0;
|
parse.lineno = 0;
|
||||||
parse.group = NULL;
|
parse.group = NULL;
|
||||||
parse.group_hash = g_hash_table_new_full(g_str_hash,
|
parse.group_hash = g_hash_table_new_full(g_str_hash,
|
||||||
g_str_equal,
|
g_str_equal,
|
||||||
NULL,
|
NULL,
|
||||||
(GDestroyNotify)group_free);
|
(GDestroyNotify)parse_group_free);
|
||||||
|
|
||||||
/* set up the groups (there's only one right now) */
|
/* set up the groups (there's only one right now) */
|
||||||
desktop_entry = group_new(g_strdup("Desktop Entry"),
|
desktop_entry = parse_group_new(g_strdup("Desktop Entry"),
|
||||||
parse_group_desktop_entry);
|
parse_desktop_entry_value);
|
||||||
g_hash_table_insert(parse.group_hash, desktop_entry->name, desktop_entry);
|
g_hash_table_insert(parse.group_hash, desktop_entry->name, desktop_entry);
|
||||||
|
|
||||||
success = FALSE;
|
success = FALSE;
|
||||||
|
@ -543,29 +488,20 @@ ObtDDFile* obt_ddfile_new_from_file(const gchar *name, GSList *paths)
|
||||||
if ((f = fopen(path, "r"))) {
|
if ((f = fopen(path, "r"))) {
|
||||||
parse.filename = path;
|
parse.filename = path;
|
||||||
parse.lineno = 1;
|
parse.lineno = 1;
|
||||||
success = parse_file(dd, f, &parse);
|
success = parse_file(f, &parse);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
g_free(path);
|
g_free(path);
|
||||||
}
|
}
|
||||||
if (!success) {
|
if (!success) {
|
||||||
obt_ddfile_unref(dd);
|
g_hash_table_destroy(parse.group_hash);
|
||||||
dd = NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
g_hash_table_destroy(parse.group_hash);
|
return parse.group_hash;
|
||||||
|
|
||||||
return dd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void obt_ddfile_ref(ObtDDFile *dd)
|
GHashTable* obt_ddparse_group_keys(ObtDDParseGroup *g)
|
||||||
{
|
{
|
||||||
++dd->ref;
|
return g->key_hash;
|
||||||
}
|
|
||||||
|
|
||||||
void obt_ddfile_unref(ObtDDFile *dd)
|
|
||||||
{
|
|
||||||
if (--dd->ref < 1) {
|
|
||||||
g_slice_free(ObtDDFile, dd);
|
|
||||||
}
|
|
||||||
}
|
}
|
52
obt/ddparse.h
Normal file
52
obt/ddparse.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
|
||||||
|
|
||||||
|
obt/ddparse.h for the Openbox window manager
|
||||||
|
Copyright (c) 2009 Dana Jansens
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
See the COPYING file for a copy of the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
typedef struct _ObtDDParseGroup ObtDDParseGroup;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OBT_DDPARSE_STRING,
|
||||||
|
OBT_DDPARSE_LOCALESTRING,
|
||||||
|
OBT_DDPARSE_STRINGS,
|
||||||
|
OBT_DDPARSE_LOCALESTRINGS,
|
||||||
|
OBT_DDPARSE_BOOLEAN,
|
||||||
|
OBT_DDPARSE_NUMERIC,
|
||||||
|
OBT_DDPARSE_NUM_VALUE_TYPES
|
||||||
|
} ObtDDParseValueType;
|
||||||
|
|
||||||
|
typedef struct _ObtDDParseValue {
|
||||||
|
ObtDDParseValueType type;
|
||||||
|
union _ObtDDParseValueValue {
|
||||||
|
gchar *string;
|
||||||
|
struct _ObtDDParseValueStrings {
|
||||||
|
gchar *s;
|
||||||
|
gulong n;
|
||||||
|
} strings;
|
||||||
|
gboolean boolean;
|
||||||
|
gfloat numeric;
|
||||||
|
} value;
|
||||||
|
} ObtDDParseValue;
|
||||||
|
|
||||||
|
/* Returns a hash table where the keys are groups, and the values are
|
||||||
|
ObtDDParseGroups */
|
||||||
|
GHashTable* obt_ddparse_file(const gchar *name, GSList *paths);
|
||||||
|
|
||||||
|
/* Returns a hash table where the keys are "keys" in the .desktop file,
|
||||||
|
and the values are "values" in the .desktop file, for the group @g. */
|
||||||
|
GHashTable* obt_ddparse_group_keys(ObtDDParseGroup *g);
|
87
obt/link.c
Normal file
87
obt/link.c
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
|
||||||
|
|
||||||
|
obt/link.c for the Openbox window manager
|
||||||
|
Copyright (c) 2009 Dana Jansens
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
See the COPYING file for a copy of the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "obt/link.h"
|
||||||
|
#include "obt/ddparse.h"
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
struct _ObtLink {
|
||||||
|
guint ref;
|
||||||
|
|
||||||
|
ObtLinkType 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 _ObtLinkData {
|
||||||
|
struct _ObtLinkApp {
|
||||||
|
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 */
|
||||||
|
ObtLinkAppOpen open;
|
||||||
|
|
||||||
|
/* XXX gchar**? or something better, a mime struct.. maybe
|
||||||
|
glib has something i can use. */
|
||||||
|
gchar **mime; /*!< Mime types the app can open */
|
||||||
|
|
||||||
|
ObtLinkAppStartup startup;
|
||||||
|
gchar *startup_wmclass;
|
||||||
|
} app;
|
||||||
|
struct _ObtLinkLink {
|
||||||
|
gchar *url;
|
||||||
|
} link;
|
||||||
|
struct _ObtLinkDir {
|
||||||
|
} dir;
|
||||||
|
} d;
|
||||||
|
};
|
||||||
|
|
||||||
|
ObtLink* obt_link_from_ddfile(const gchar *name, GSList *paths)
|
||||||
|
{
|
||||||
|
ObtLink *lnk;
|
||||||
|
GHashTable *groups, *keys;
|
||||||
|
ObtDDParseGroup *g;
|
||||||
|
|
||||||
|
groups = obt_ddparse_file(name, paths);
|
||||||
|
if (!groups) return NULL;
|
||||||
|
g = g_hash_table_lookup(groups, "Desktop Entry");
|
||||||
|
if (!g) {
|
||||||
|
g_hash_table_destroy(groups);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys = obt_ddparse_group_keys(g);
|
||||||
|
|
||||||
|
lnk = g_slice_new(ObtLink);
|
||||||
|
lnk->ref = 1;
|
||||||
|
/* XXX turn the values in the .desktop file into an ObtLink */
|
||||||
|
|
||||||
|
return lnk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void obt_link_ref(ObtLink *dd)
|
||||||
|
{
|
||||||
|
++dd->ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
void obt_link_unref(ObtLink *dd)
|
||||||
|
{
|
||||||
|
if (--dd->ref < 1) {
|
||||||
|
g_slice_free(ObtLink, dd);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
|
/* -*- 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
|
Copyright (c) 2009 Dana Jansens
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -16,50 +16,50 @@
|
||||||
See the COPYING file for a copy of the GNU General Public License.
|
See the COPYING file for a copy of the GNU General Public License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __obt_ddfile_h
|
#ifndef __obt_link_h
|
||||||
#define __obt_ddfile_h
|
#define __obt_link_h
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OBT_DDFILE_TYPE_APPLICATION = 1,
|
OBT_LINK_TYPE_APPLICATION = 1,
|
||||||
OBT_DDFILE_TYPE_LINK = 2,
|
OBT_LINK_TYPE_URL = 2,
|
||||||
OBT_DDFILE_TYPE_DIRECTORY = 3
|
OBT_LINK_TYPE_DIRECTORY = 3
|
||||||
} ObtDDFileType;
|
} ObtLinkType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OBT_DDFILE_APP_STARTUP_NO_SUPPORT,
|
OBT_LINK_APP_STARTUP_NO_SUPPORT,
|
||||||
OBT_DDFILE_APP_STARTUP_PROTOCOL_SUPPORT,
|
OBT_LINK_APP_STARTUP_PROTOCOL_SUPPORT,
|
||||||
OBT_DDFILE_APP_STARTUP_LEGACY_SUPPORT
|
OBT_LINK_APP_STARTUP_LEGACY_SUPPORT
|
||||||
} ObtDDFileAppStartup;
|
} ObtLinkAppStartup;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/*! The app can be launched with a single local file */
|
/*! 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 */
|
/*! 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 */
|
/*! 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 */
|
/*! The app can be launched with multiple URLs */
|
||||||
OBT_DDFILE_APP_MULTI_URL = 1 << 3
|
OBT_LINK_APP_MULTI_URL = 1 << 3
|
||||||
} ObtDDFileAppOpen;
|
} 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_link_ref(ObtLink *e);
|
||||||
void obt_ddfile_unref(ObtDDFile *e);
|
void obt_link_unref(ObtLink *e);
|
||||||
|
|
||||||
/*! Returns TRUE if the file exists but says it should be ignored, with
|
/*! 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. */
|
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. */
|
/*! 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
|
/*! Returns TRUE if the .desktop file should be displayed to users, given the
|
||||||
current environment. If FALSE, the .desktop file should not be showed.
|
current environment. If FALSE, the .desktop file should not be showed.
|
||||||
|
@ -67,32 +67,32 @@ ObtDDFileType obt_ddfile_type (ObtDDFile *e);
|
||||||
@env A semicolon-deliminated list of environemnts. Can be one or more of:
|
@env A semicolon-deliminated list of environemnts. Can be one or more of:
|
||||||
GNOME, KDE, ROX, XFCE. Other environments not listed here may also
|
GNOME, KDE, ROX, XFCE. Other environments not listed here may also
|
||||||
be supported. This can be null also if not listing any environment. */
|
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_link_name (ObtLink *e);
|
||||||
const gchar* obt_ddfile_generic_name (ObtDDFile *e);
|
const gchar* obt_link_generic_name (ObtLink *e);
|
||||||
const gchar* obt_ddfile_comment (ObtDDFile *e);
|
const gchar* obt_link_comment (ObtLink *e);
|
||||||
/*! Returns the icon for the object referred to by the .desktop file.
|
/*! 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
|
Returns either an absolute path, or a string which can be used to find the
|
||||||
icon using the algorithm given by:
|
icon using the algorithm given by:
|
||||||
http://freedesktop.org/wiki/Specifications/icon-theme-spec?action=show&redirect=Standards/icon-theme-spec
|
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 */
|
/*! Returns the path in which the application should be run */
|
||||||
const gchar* obt_ddfile_app_path (ObtDDFile *e);
|
const gchar* obt_link_app_path (ObtLink *e);
|
||||||
gboolean obt_ddfile_app_run_in_terminal (ObtDDFile *e);
|
gboolean obt_link_app_run_in_terminal (ObtLink *e);
|
||||||
const gchar** obt_ddfile_app_mime_types (ObtDDFile *e);
|
const gchar** obt_link_app_mime_types (ObtLink *e);
|
||||||
/*! Returns a combination of values in the ObtDDFileAppOpen enum,
|
/*! Returns a combination of values in the ObtLinkAppOpen enum,
|
||||||
specifying if the application can be launched to open one or more files
|
specifying if the application can be launched to open one or more files
|
||||||
and URLs. */
|
and URLs. */
|
||||||
ObtDDFileAppOpen obt_ddfile_app_open(ObtDDFile *e);
|
ObtLinkAppOpen obt_link_app_open(ObtLink *e);
|
||||||
|
|
||||||
ObtDDFileAppStartup obt_ddfile_app_startup_notify(ObtDDFile *e);
|
ObtLinkAppStartup obt_link_app_startup_notify(ObtLink *e);
|
||||||
const gchar* obt_ddfile_app_startup_wmclass(ObtDDFile *e);
|
const gchar* obt_link_app_startup_wmclass(ObtLink *e);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
Loading…
Reference in a new issue