Skip to content

Commit da7d710

Browse files
committed
xml.c: make nodename() more xpath-like
Use nodesnames like /a/b/c instead of c.b.a to represent <A><B><C></C></B></A> Add xml_get_node() and make it case-insensitive. XML is case-sensitive but in labwc we don't treat it as such so let's be consistent here.
1 parent 5e103a2 commit da7d710

File tree

3 files changed

+47
-44
lines changed

3 files changed

+47
-44
lines changed

main.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ static void
8686
update(GtkWidget *widget, gpointer data)
8787
{
8888
/* ~/.config/labwc/rc.xml */
89-
xml_set_num("cornerradius.theme", SPIN_BUTTON_VAL(corner_radius));
90-
xml_set("name.theme", COMBO_TEXT(openbox_theme_name));
91-
xml_set("naturalscroll.device.libinput", COMBO_TEXT(natural_scroll));
89+
xml_set_num("/labwc_config/theme/cornerradius", SPIN_BUTTON_VAL(corner_radius));
90+
xml_set("/labwc_config/theme/name", COMBO_TEXT(openbox_theme_name));
91+
xml_set("/labwc_config/libinput/device/naturalscroll", COMBO_TEXT(natural_scroll));
9292
xml_save();
9393

9494
/* gsettings */
@@ -135,7 +135,7 @@ activate(GtkApplication *app, gpointer user_data)
135135
gtk_grid_attach(GTK_GRID(grid), widget, 0, row, 1, 1);
136136
openbox_theme_name = gtk_combo_box_text_new();
137137
int active = -1;
138-
char *active_id = xml_get("name.theme");
138+
char *active_id = xml_get("/labwc_config/theme/name");
139139
struct theme *theme;
140140
for (int i = 0; i < openbox_themes.nr; ++i) {
141141
theme = openbox_themes.data + i;
@@ -153,7 +153,7 @@ activate(GtkApplication *app, gpointer user_data)
153153
gtk_grid_attach(GTK_GRID(grid), widget, 0, row, 1, 1);
154154
GtkAdjustment *adjustment = gtk_adjustment_new(0, 0, 10, 1, 2, 0);
155155
corner_radius = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 1, 0);
156-
gtk_spin_button_set_value(GTK_SPIN_BUTTON(corner_radius), xml_get_int("cornerradius.theme"));
156+
gtk_spin_button_set_value(GTK_SPIN_BUTTON(corner_radius), xml_get_int("/labwc_config/theme/cornerradius"));
157157
gtk_grid_attach(GTK_GRID(grid), corner_radius, 1, row++, 1, 1);
158158

159159
/* gtk theme combobox */
@@ -217,7 +217,7 @@ activate(GtkApplication *app, gpointer user_data)
217217
natural_scroll = gtk_combo_box_text_new();
218218
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(natural_scroll), "no");
219219
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(natural_scroll), "yes");
220-
gtk_combo_box_set_active(GTK_COMBO_BOX(natural_scroll), xml_get_bool_text("naturalscroll.device.libinput"));
220+
gtk_combo_box_set_active(GTK_COMBO_BOX(natural_scroll), xml_get_bool_text("/labwc_config/libinput/device/naturalscroll"));
221221
gtk_grid_attach(GTK_GRID(grid), natural_scroll, 1, row++, 1, 1);
222222

223223
/* bottom button box */

tests/t1001-nodenames.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ int main(int argc, char **argv)
3838
diag("generate simple xpath style nodename");
3939
xml_init(in);
4040
xmlNode *node = get_node((xmlChar *)"/labwc_config/core/gap");
41-
char *name = nodename(node, buffer, sizeof(buffer), false);
41+
char *name = nodename(node, buffer, sizeof(buffer));
4242
xml_finish();
4343
test(name, "/labwc_config/core/gap");
4444

xml.c

+40-37
Original file line numberDiff line numberDiff line change
@@ -19,79 +19,70 @@ static struct ctx {
1919
xmlXPathContextPtr xpath_ctx_ptr;
2020
char *nodename;
2121
char *value;
22+
xmlNode *node;
2223
enum {
2324
XML_MODE_SETTING = 0,
2425
XML_MODE_GETTING,
2526
} mode;
2627
} ctx;
2728

28-
29-
static void
30-
string_truncate_at_pattern(char *buf, const char *pattern)
31-
{
32-
char *p = strstr(buf, pattern);
33-
if (!p) {
34-
return;
35-
}
36-
*p = '\0';
37-
}
38-
3929
static void
4030
entry(xmlNode *node, char *nodename, char *content)
4131
{
4232
if (!nodename)
4333
return;
44-
string_truncate_at_pattern(nodename, ".openbox_config");
45-
string_truncate_at_pattern(nodename, ".labwc_config");
46-
if (!strcmp(nodename, ctx.nodename)) {
34+
if (!strcasecmp(nodename, ctx.nodename)) {
4735
if (ctx.mode == XML_MODE_SETTING) {
4836
xmlNodeSetContent(node, (const xmlChar *)ctx.value);
4937
} else if (ctx.mode == XML_MODE_GETTING) {
5038
ctx.value = (char *)content;
39+
ctx.node = node;
5140
}
5241
}
5342
}
5443

44+
/**
45+
* nodename - return simplistic xpath style nodename
46+
* For example: <A><B><C></C></B></A> is represented by nodename /a/b/c
47+
*/
5548
static char *
56-
nodename(xmlNode *node, char *buf, int len, bool is_attribute)
49+
nodename(xmlNode *node, char *buf, int len)
5750
{
5851
if (!node || !node->name) {
5952
return NULL;
6053
}
6154

62-
/* Ignore superflous 'text.' in node name */
55+
/* Ignore superflous '/text' in node name */
6356
if (node->parent && !strcmp((char *)node->name, "text")) {
6457
node = node->parent;
6558
}
6659

67-
char *p = buf;
68-
p[--len] = 0;
69-
if (is_attribute) {
70-
*p++ = '@';
71-
--len;
72-
}
73-
for (;;) {
60+
buf += len;
61+
*--buf = 0;
62+
len--;
63+
64+
for(;;) {
7465
const char *name = (char *)node->name;
75-
char c;
76-
while ((c = *name++) != 0) {
77-
*p++ = tolower(c);
66+
int i = strlen(name);
67+
while (--i >= 0) {
68+
unsigned char c = name[i];
69+
*--buf = tolower(c);
7870
if (!--len)
7971
return buf;
8072
}
81-
*p = 0;
8273
node = node->parent;
8374
if (!node || !node->name) {
75+
*--buf = '/';
8476
return buf;
8577
}
86-
*p++ = '.';
87-
if (!--len) {
78+
*--buf = '/';
79+
if (!--len)
8880
return buf;
89-
}
9081
}
9182
}
9283

9384
static void
94-
process_node(xmlNode *node, bool is_attribute)
85+
process_node(xmlNode *node)
9586
{
9687
char *content;
9788
static char buffer[256];
@@ -101,7 +92,7 @@ process_node(xmlNode *node, bool is_attribute)
10192
if (xmlIsBlankNode(node)) {
10293
return;
10394
}
104-
name = nodename(node, buffer, sizeof(buffer), is_attribute);
95+
name = nodename(node, buffer, sizeof(buffer));
10596
entry(node, name, content);
10697
}
10798

@@ -110,14 +101,10 @@ static void xml_tree_walk(xmlNode *node);
110101
static void
111102
traverse(xmlNode *n)
112103
{
113-
static bool is_attribute;
114-
115-
process_node(n, is_attribute);
116-
is_attribute = true;
104+
process_node(n);
117105
for (xmlAttr *attr = n->properties; attr; attr = attr->next) {
118106
xml_tree_walk(attr->children);
119107
}
120-
is_attribute = false;
121108
xml_tree_walk(n->children);
122109
}
123110

@@ -232,6 +219,17 @@ xml_get_bool_text(char *nodename)
232219
}
233220
}
234221

222+
/* case-insensitive */
223+
static xmlNode *
224+
xml_get_node(char *nodename)
225+
{
226+
ctx.node = NULL;
227+
ctx.nodename = nodename;
228+
ctx.mode = XML_MODE_GETTING;
229+
xml_tree_walk(xmlDocGetRootElement(ctx.doc));
230+
return ctx.node;
231+
}
232+
235233
char *
236234
xml_get_content(char *xpath_expr)
237235
{
@@ -266,6 +264,7 @@ xml_get_content(char *xpath_expr)
266264
return (char *)ret;
267265
}
268266

267+
/* case-sensitive */
269268
static xmlNode *
270269
get_node(xmlChar *expr)
271270
{
@@ -295,6 +294,10 @@ get_node(xmlChar *expr)
295294
void
296295
xml_add_node(char *xpath_expr)
297296
{
297+
if (xml_get_node(xpath_expr)) {
298+
return;
299+
}
300+
298301
/* find existing parent */
299302
char *parent_expr = strdup(xpath_expr);
300303
xmlNode *parent_node = NULL;

0 commit comments

Comments
 (0)