From 6bf75a1e100910c33c9675045a58e48e221c4611 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 27 Jul 2011 16:32:05 -0400 Subject: [PATCH] Parse ObActionsList*s from the config file (out of the xml for now). - config.c: use the new actions parser - actions.c: provide the actions parser a way to create a new action (takes a hash table of options for it) - actions/*.c: take a hash table of options instead of an xml subtree - *: us ObActionsList* instead of a GList* of ObActionAct*s. TODO: 1. make filters openbox/filters/*.c openbox/filters.c as interface to them store filters in parsed filter tests instead of key/value pairs 2. make action(s) to change config options includes key and mouse binding 3. rm -rf *xml* --- Makefile.am | 3 +- openbox/actions.c | 63 +++-- openbox/actions.h | 28 ++- openbox/actions/addremovedesktop.c | 49 ++-- openbox/actions/all.c | 1 - openbox/actions/all.h | 1 - openbox/actions/cyclewindows.c | 101 ++++---- openbox/actions/debug.c | 12 +- openbox/actions/desktop.c | 329 ++------------------------- openbox/actions/directionalwindows.c | 181 ++++++++------- openbox/actions/execute.c | 48 ++-- openbox/actions/exit.c | 12 +- openbox/actions/focus.c | 17 +- openbox/actions/growtoedge.c | 35 +-- openbox/actions/layer.c | 33 +-- openbox/actions/maximize.c | 59 +---- openbox/actions/moverelative.c | 24 +- openbox/actions/moveresizeto.c | 54 +++-- openbox/actions/movetoedge.c | 29 +-- openbox/actions/resize.c | 14 +- openbox/actions/resizerelative.c | 38 ++-- openbox/actions/restart.c | 17 +- openbox/actions/showmenu.c | 12 +- openbox/actions_list.c | 111 +-------- openbox/actions_list.h | 31 +-- openbox/actions_parser.c | 167 ++++++++------ openbox/actions_parser.h | 14 +- openbox/actions_value.c | 166 ++++++++++++++ openbox/actions_value.h | 45 ++++ openbox/config.c | 58 ++++- openbox/keyboard.c | 32 ++- openbox/keyboard.h | 2 +- openbox/keytree.c | 6 +- openbox/keytree.h | 4 +- openbox/menu.c | 28 ++- openbox/menu.h | 7 +- openbox/menuframe.c | 3 +- openbox/mouse.c | 20 +- openbox/mouse.h | 4 +- openbox/openbox.c | 2 +- 40 files changed, 852 insertions(+), 1008 deletions(-) create mode 100644 openbox/actions_value.c create mode 100644 openbox/actions_value.h diff --git a/Makefile.am b/Makefile.am index 542a2474..9c281a1e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -215,7 +215,6 @@ openbox_openbox_SOURCES = \ openbox/actions/fullscreen.c \ openbox/actions/growtoedge.c \ openbox/actions/iconify.c \ - openbox/actions/if.c \ openbox/actions/kill.c \ openbox/actions/layer.c \ openbox/actions/lower.c \ @@ -242,6 +241,8 @@ openbox_openbox_SOURCES = \ openbox/actions_list.h \ openbox/actions_parser.c \ openbox/actions_parser.h \ + openbox/actions_value.c \ + openbox/actions_value.h \ openbox/apps_menu.c \ openbox/apps_menu.h \ openbox/client.c \ diff --git a/openbox/actions.c b/openbox/actions.c index 2288ea6d..76c7cb50 100644 --- a/openbox/actions.c +++ b/openbox/actions.c @@ -17,6 +17,7 @@ */ #include "actions.h" +#include "actions_list.h" #include "gettext.h" #include "grab.h" #include "screen.h" @@ -33,7 +34,7 @@ static void actions_definition_ref(ObActionsDefinition *def); static void actions_definition_unref(ObActionsDefinition *def); static gboolean actions_interactive_begin_act(ObActionsAct *act, guint state); static void actions_interactive_end_act(); -static ObActionsAct* actions_build_act_from_string(const gchar *name); +static ObActionsAct* actions_act_find_name(const gchar *name); static ObActionsAct *interactive_act = NULL; static guint interactive_initial_state = 0; @@ -169,7 +170,7 @@ static void actions_definition_unref(ObActionsDefinition *def) } } -static ObActionsAct* actions_build_act_from_string(const gchar *name) +static ObActionsAct* actions_act_find_name(const gchar *name) { GSList *it; ObActionsDefinition *def = NULL; @@ -205,7 +206,7 @@ ObActionsAct* actions_parse_string(const gchar *name) { ObActionsAct *act = NULL; - if ((act = actions_build_act_from_string(name))) { + if ((act = actions_act_find_name(name))) { if (act->def->canbeinteractive) { if (act->def->setup.i) act->options = act->def->setup.i(NULL, @@ -230,11 +231,11 @@ ObActionsAct* actions_parse(xmlNodePtr node) ObActionsAct *act = NULL; if (obt_xml_attr_string(node, "name", &name)) { - if ((act = actions_build_act_from_string(name))) { + if ((act = actions_act_find_name(name))) { /* there is more stuff to parse here */ if (act->def->canbeinteractive) { if (act->def->setup.i) - act->options = act->def->setup.i(node->children, + act->options = act->def->setup.i(NULL, &act->i_pre, &act->i_input, &act->i_cancel, @@ -242,7 +243,7 @@ ObActionsAct* actions_parse(xmlNodePtr node) } else { if (act->def->setup.n) - act->options = act->def->setup.n(node->children); + act->options = act->def->setup.n(NULL); } } g_free(name); @@ -251,17 +252,16 @@ ObActionsAct* actions_parse(xmlNodePtr node) return act; } -ObActionsAct* actions_act_new(const gchar *name, GList *keys, GList *values) +ObActionsAct* actions_act_new(const gchar *name, GHashTable *config) { ObActionsAct *act = NULL; - act = actions_build_act_from_string(name); + act = actions_act_find_name(name); if (act) { /* there is more stuff to parse here */ if (act->def->canbeinteractive) { if (act->def->setup.i) -//XXX act->options = act->def->setup.i(keys, values, - act->options = act->def->setup.i(NULL, + act->options = act->def->setup.i(config, &act->i_pre, &act->i_input, &act->i_cancel, @@ -269,11 +269,9 @@ ObActionsAct* actions_act_new(const gchar *name, GList *keys, GList *values) } else { if (act->def->setup.n) -//XXX act->options = act->def->setup.n(keys, values); - act->options = act->def->setup.n(NULL); + act->options = act->def->setup.n(config); } } - g_free(name); return act; } @@ -318,16 +316,16 @@ static void actions_setup_data(ObActionsData *data, data->client = client; } -void actions_run_acts(GSList *acts, - ObUserAction uact, - guint state, - gint x, - gint y, - gint button, - ObFrameContext con, - struct _ObClient *client) +gboolean actions_run_acts(ObActionsList *acts, + ObUserAction uact, + guint state, + gint x, + gint y, + gint button, + ObFrameContext con, + struct _ObClient *client) { - GSList *it; + gboolean ran_interactive; gboolean update_user_time; /* Don't allow saving the initial state when running things from the @@ -338,12 +336,22 @@ void actions_run_acts(GSList *acts, if (x < 0 && y < 0) screen_pointer_pos(&x, &y); + ran_interactive = FALSE; update_user_time = FALSE; - for (it = acts; it; it = g_slist_next(it)) { + while (acts) { + ObActionsAct *act; ObActionsData data; - ObActionsAct *act = it->data; gboolean ok = TRUE; + if (acts->isfilter) { + g_warning("filters not implemented!"); + acts = acts->next; + continue; + } + else { + act = acts->u.action; + } + actions_setup_data(&data, uact, state, x, y, button, con, client); /* if they have the same run function, then we'll assume they are @@ -356,10 +364,13 @@ void actions_run_acts(GSList *acts, if (act->i_pre) if (!act->i_pre(state, act->options)) act->i_input = NULL; /* remove the interactivity */ + ran_interactive = TRUE; } /* check again cuz it might have been cancelled */ - if (actions_act_is_interactive(act)) + if (actions_act_is_interactive(act)) { ok = actions_interactive_begin_act(act, state); + ran_interactive = TRUE; + } } /* fire the action's run function with this data */ @@ -377,9 +388,11 @@ void actions_run_acts(GSList *acts, break; } } + acts = acts->next; } if (update_user_time) event_update_user_time(); + return ran_interactive; } gboolean actions_interactive_act_running(void) diff --git a/openbox/actions.h b/openbox/actions.h index 16a48ca8..55b0f138 100644 --- a/openbox/actions.h +++ b/openbox/actions.h @@ -24,6 +24,8 @@ #include #include +struct _ObActionsList; + typedef struct _ObActionsDefinition ObActionsDefinition; typedef struct _ObActionsAct ObActionsAct; typedef struct _ObActionsData ObActionsData; @@ -35,7 +37,7 @@ typedef struct _ObActionsSelectorData ObActionsSelectorData; typedef void (*ObActionsDataFreeFunc)(gpointer options); typedef gboolean (*ObActionsRunFunc)(ObActionsData *data, gpointer options); -typedef gpointer (*ObActionsDataSetupFunc)(xmlNodePtr node); +typedef gpointer (*ObActionsDataSetupFunc)(GHashTable *config); typedef void (*ObActionsShutdownFunc)(void); /* functions for interactive actions */ @@ -49,7 +51,7 @@ typedef gboolean (*ObActionsIInputFunc)(guint initial_state, gpointer options, gboolean *used); typedef void (*ObActionsICancelFunc)(gpointer options); -typedef gpointer (*ObActionsIDataSetupFunc)(xmlNodePtr node, +typedef gpointer (*ObActionsIDataSetupFunc)(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, @@ -94,7 +96,7 @@ gboolean actions_act_is_interactive(ObActionsAct *act); @values The values of the options passed to the action, paired with the keys. These are ObActionsListValue objects. */ -ObActionsAct* actions_act_new(const gchar *name, GList *keys, GList *values); +ObActionsAct* actions_act_new(const gchar *name, GHashTable *config); void actions_act_ref(ObActionsAct *act); void actions_act_unref(ObActionsAct *act); @@ -108,15 +110,17 @@ void actions_set_need_pointer_replay_before_move(gboolean replay); actions then this will be false */ gboolean actions_get_need_pointer_replay_before_move(void); -/*! Pass in a GSList of ObActionsAct's to be run. */ -void actions_run_acts(GSList *acts, - ObUserAction uact, - guint state, - gint x, - gint y, - gint button, - ObFrameContext con, - struct _ObClient *client); +/*! Runs a list of actions. + @return TRUE if an interactive action was started, FALSE otherwise. +*/ +gboolean actions_run_acts(struct _ObActionsList *acts, + ObUserAction uact, + guint state, + gint x, + gint y, + gint button, + ObFrameContext con, + struct _ObClient *client); gboolean actions_interactive_act_running(void); void actions_interactive_cancel_act(void); diff --git a/openbox/actions/addremovedesktop.c b/openbox/actions/addremovedesktop.c index ff6767e2..10458d57 100644 --- a/openbox/actions/addremovedesktop.c +++ b/openbox/actions/addremovedesktop.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/screen.h" #include @@ -7,16 +8,16 @@ typedef struct { gboolean add; } Options; -static gpointer setup_func(xmlNodePtr node); -static gpointer setup_add_func(xmlNodePtr node); -static gpointer setup_remove_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); +static gpointer setup_add_func(GHashTable *config); +static gpointer setup_remove_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); /* 3.4-compatibility */ -static gpointer setup_addcurrent_func(xmlNodePtr node); -static gpointer setup_addlast_func(xmlNodePtr node); -static gpointer setup_removecurrent_func(xmlNodePtr node); -static gpointer setup_removelast_func(xmlNodePtr node); +static gpointer setup_addcurrent_func(GHashTable *config); +static gpointer setup_addlast_func(GHashTable *config); +static gpointer setup_removecurrent_func(GHashTable *config); +static gpointer setup_removelast_func(GHashTable *config); void action_addremovedesktop_startup(void) { @@ -34,35 +35,35 @@ void action_addremovedesktop_startup(void) free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "where"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "where"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); if (!g_ascii_strcasecmp(s, "last")) o->current = FALSE; else if (!g_ascii_strcasecmp(s, "current")) o->current = TRUE; - g_free(s); } return o; } -static gpointer setup_add_func(xmlNodePtr node) +static gpointer setup_add_func(GHashTable *config) { - Options *o = setup_func(node); + Options *o = setup_func(config); o->add = TRUE; return o; } -static gpointer setup_remove_func(xmlNodePtr node) +static gpointer setup_remove_func(GHashTable *config) { - Options *o = setup_func(node); + Options *o = setup_func(config); o->add = FALSE; return o; } @@ -90,30 +91,30 @@ static gboolean run_func(ObActionsData *data, gpointer options) } /* 3.4-compatibility */ -static gpointer setup_addcurrent_func(xmlNodePtr node) +static gpointer setup_addcurrent_func(GHashTable *config) { - Options *o = setup_add_func(node); + Options *o = setup_add_func(config); o->current = TRUE; return o; } -static gpointer setup_addlast_func(xmlNodePtr node) +static gpointer setup_addlast_func(GHashTable *config) { - Options *o = setup_add_func(node); + Options *o = setup_add_func(config); o->current = FALSE; return o; } -static gpointer setup_removecurrent_func(xmlNodePtr node) +static gpointer setup_removecurrent_func(GHashTable *config) { - Options *o = setup_remove_func(node); + Options *o = setup_remove_func(config); o->current = TRUE; return o; } -static gpointer setup_removelast_func(xmlNodePtr node) +static gpointer setup_removelast_func(GHashTable *config) { - Options *o = setup_remove_func(node); + Options *o = setup_remove_func(config); o->current = FALSE; return o; } diff --git a/openbox/actions/all.c b/openbox/actions/all.c index 332e79ca..06e3074a 100644 --- a/openbox/actions/all.c +++ b/openbox/actions/all.c @@ -37,7 +37,6 @@ void action_all_startup(void) action_layer_startup(); action_movetoedge_startup(); action_growtoedge_startup(); - action_if_startup(); action_focustobottom_startup(); /* 3.4-compatibility */ action_shadelowerraise_startup(); diff --git a/openbox/actions/all.h b/openbox/actions/all.h index 54d63195..5bc337aa 100644 --- a/openbox/actions/all.h +++ b/openbox/actions/all.h @@ -38,7 +38,6 @@ void action_dockautohide_startup(void); void action_layer_startup(void); void action_movetoedge_startup(void); void action_growtoedge_startup(void); -void action_if_startup(void); void action_focustobottom_startup(void); /* 3.4-compatibility */ void action_shadelowerraise_startup(void); diff --git a/openbox/actions/cyclewindows.c b/openbox/actions/cyclewindows.c index 5f0db27c..5325a60a 100644 --- a/openbox/actions/cyclewindows.c +++ b/openbox/actions/cyclewindows.c @@ -1,4 +1,7 @@ #include "openbox/actions.h" +#include "openbox/actions_list.h" +#include "openbox/actions_parser.h" +#include "openbox/actions_value.h" #include "openbox/stacking.h" #include "openbox/window.h" #include "openbox/event.h" @@ -17,7 +20,7 @@ typedef struct { gboolean bar; gboolean raise; ObFocusCyclePopupMode dialog_mode; - GSList *actions; + ObActionsList *actions; /* options for after we're done */ @@ -25,17 +28,17 @@ typedef struct { guint state; /* keyboard state when finished */ } Options; -static gpointer setup_func(xmlNodePtr node, +static gpointer setup_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_forward_func(xmlNodePtr node, +static gpointer setup_forward_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_backward_func(xmlNodePtr node, +static gpointer setup_backward_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, @@ -57,59 +60,63 @@ void action_cyclewindows_startup(void) run_func); } -static gpointer setup_func(xmlNodePtr node, +static gpointer setup_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); o->bar = TRUE; o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_LIST; - if ((n = obt_xml_find_node(node, "linear"))) - o->linear = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "dialog"))) { - if (obt_xml_node_contains(n, "none")) + v = g_hash_table_lookup(config, "linear"); + if (v && actions_value_is_string(v)) + o->linear = actions_value_bool(v); + v = g_hash_table_lookup(config, "dialog"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); + if (g_strcasecmp(s, "none") == 0) o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_NONE; - else if (obt_xml_node_contains(n, "no")) + else if (g_strcasecmp(s, "no") == 0) o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_NONE; - else if (obt_xml_node_contains(n, "icons")) + else if (g_strcasecmp(s, "icons") == 0) o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_ICONS; } - if ((n = obt_xml_find_node(node, "bar"))) - o->bar = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "raise"))) - o->raise = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "panels"))) - o->dock_windows = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "hilite"))) - o->only_hilite_windows = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "desktop"))) - o->desktop_windows = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "allDesktops"))) - o->all_desktops = obt_xml_node_bool(n); - - if ((n = obt_xml_find_node(node, "finalactions"))) { - xmlNodePtr m; - - m = obt_xml_find_node(n->children, "action"); - while (m) { - ObActionsAct *action = actions_parse(m); - if (action) o->actions = g_slist_append(o->actions, action); - m = obt_xml_find_node(m->next, "action"); - } + v = g_hash_table_lookup(config, "bar"); + if (v && actions_value_is_string(v)) + o->bar = actions_value_bool(v); + v = g_hash_table_lookup(config, "raise"); + if (v && actions_value_is_string(v)) + o->raise = actions_value_bool(v); + v = g_hash_table_lookup(config, "panels"); + if (v && actions_value_is_string(v)) + o->dock_windows = actions_value_bool(v); + v = g_hash_table_lookup(config, "hilite"); + if (v && actions_value_is_string(v)) + o->only_hilite_windows = actions_value_bool(v); + v = g_hash_table_lookup(config, "desktop"); + if (v && actions_value_is_string(v)) + o->desktop_windows = actions_value_bool(v); + v = g_hash_table_lookup(config, "allDesktops"); + if (v && actions_value_is_string(v)) + o->all_desktops = actions_value_bool(v); + + v = g_hash_table_lookup(config, "finalactions"); + if (v && actions_value_is_actions_list(v)) { + o->actions = actions_value_actions_list(v); + actions_list_ref(o->actions); } else { - o->actions = g_slist_prepend(o->actions, - actions_parse_string("Focus")); - o->actions = g_slist_prepend(o->actions, - actions_parse_string("Raise")); - o->actions = g_slist_prepend(o->actions, - actions_parse_string("Unshade")); + ObActionsParser *p = actions_parser_new(); + o->actions = actions_parser_read_string(p, + "focus\n" + "raise\n" + "unshade\n"); + actions_parser_unref(p); } *input = i_input_func; @@ -118,24 +125,24 @@ static gpointer setup_func(xmlNodePtr node, return o; } -static gpointer setup_forward_func(xmlNodePtr node, +static gpointer setup_forward_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_func(node, pre, input, cancel, post); + Options *o = setup_func(config, pre, input, cancel, post); o->forward = TRUE; return o; } -static gpointer setup_backward_func(xmlNodePtr node, +static gpointer setup_backward_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_func(node, pre, input, cancel, post); + Options *o = setup_func(config, pre, input, cancel, post); o->forward = FALSE; return o; } @@ -144,11 +151,7 @@ static void free_func(gpointer options) { Options *o = options; - while (o->actions) { - actions_act_unref(o->actions->data); - o->actions = g_slist_delete_link(o->actions, o->actions); - } - + actions_list_unref(o->actions); g_slice_free(Options, o); } diff --git a/openbox/actions/debug.c b/openbox/actions/debug.c index 99446bc4..2ffd4f6e 100644 --- a/openbox/actions/debug.c +++ b/openbox/actions/debug.c @@ -1,11 +1,12 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include typedef struct { gchar *str; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); @@ -14,15 +15,16 @@ void action_debug_startup(void) actions_register("Debug", setup_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "string"))) - o->str = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "string"); + if (v && actions_value_is_string(v)) + o->str = g_strdup(actions_value_string(v)); return o; } diff --git a/openbox/actions/desktop.c b/openbox/actions/desktop.c index a3a1f6b9..0c08d855 100644 --- a/openbox/actions/desktop.c +++ b/openbox/actions/desktop.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/screen.h" #include "openbox/client.h" #include "openbox/openbox.h" @@ -29,12 +30,12 @@ typedef struct { gboolean interactive; } Options; -static gpointer setup_go_func(xmlNodePtr node, +static gpointer setup_go_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post); -static gpointer setup_send_func(xmlNodePtr node, +static gpointer setup_send_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, @@ -50,109 +51,20 @@ static gboolean i_input_func(guint initial_state, gboolean *used); static void i_post_func(gpointer options); -/* 3.4-compatibility */ -static gpointer setup_go_last_func(xmlNodePtr node); -static gpointer setup_send_last_func(xmlNodePtr node); -static gpointer setup_go_abs_func(xmlNodePtr node); -static gpointer setup_go_next_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_send_next_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_go_prev_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_send_prev_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_go_left_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_send_left_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_go_right_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_send_right_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_go_up_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_send_up_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_go_down_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); -static gpointer setup_send_down_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post); void action_desktop_startup(void) { actions_register_i("GoToDesktop", setup_go_func, free_func, run_func); actions_register_i("SendToDesktop", setup_send_func, free_func, run_func); - /* 3.4-compatibility */ - actions_register("DesktopLast", setup_go_last_func, free_func, run_func); - actions_register("SendToDesktopLast", setup_send_last_func, - free_func, run_func); - actions_register("Desktop", setup_go_abs_func, free_func, run_func); - actions_register_i("DesktopNext", setup_go_next_func, free_func, run_func); - actions_register_i("SendToDesktopNext", setup_send_next_func, - free_func, run_func); - actions_register_i("DesktopPrevious", setup_go_prev_func, - free_func, run_func); - actions_register_i("SendToDesktopPrevious", setup_send_prev_func, - free_func, run_func); - actions_register_i("DesktopLeft", setup_go_left_func, free_func, run_func); - actions_register_i("SendToDesktopLeft", setup_send_left_func, - free_func, run_func); - actions_register_i("DesktopRight", setup_go_right_func, - free_func, run_func); - actions_register_i("SendToDesktopRight", setup_send_right_func, - free_func, run_func); - actions_register_i("DesktopUp", setup_go_up_func, free_func, run_func); - actions_register_i("SendToDesktopUp", setup_send_up_func, - free_func, run_func); - actions_register_i("DesktopDown", setup_go_down_func, free_func, run_func); - actions_register_i("SendToDesktopDown", setup_send_down_func, - free_func, run_func); } -static gpointer setup_func(xmlNodePtr node, +static gpointer setup_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); @@ -162,8 +74,9 @@ static gpointer setup_func(xmlNodePtr node, /* wrap by default - it's handy! */ o->u.rel.wrap = TRUE; - if ((n = obt_xml_find_node(node, "to"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "to"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); if (!g_ascii_strcasecmp(s, "last")) o->type = LAST; else if (!g_ascii_strcasecmp(s, "current")) @@ -202,17 +115,17 @@ static gpointer setup_func(xmlNodePtr node, o->type = ABSOLUTE; o->u.abs.desktop = atoi(s) - 1; } - g_free(s); } - if ((n = obt_xml_find_node(node, "wrap"))) - o->u.rel.wrap = obt_xml_node_bool(n); + v = g_hash_table_lookup(config, "wrap"); + if (v && actions_value_is_string(v)) + o->u.rel.wrap = actions_value_bool(v); return o; } -static gpointer setup_go_func(xmlNodePtr node, +static gpointer setup_go_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, @@ -220,7 +133,7 @@ static gpointer setup_go_func(xmlNodePtr node, { Options *o; - o = setup_func(node, pre, input, cancel, post); + o = setup_func(config, pre, input, cancel, post); if (o->type == RELATIVE) { o->interactive = TRUE; *pre = i_pre_func; @@ -231,26 +144,22 @@ static gpointer setup_go_func(xmlNodePtr node, return o; } -static gpointer setup_send_func(xmlNodePtr node, +static gpointer setup_send_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - xmlNodePtr n; + ObActionsValue *v; Options *o; - o = setup_func(node, pre, input, cancel, post); - if ((n = obt_xml_find_node(node, "desktop"))) { - /* 3.4 compatibility */ - o->u.abs.desktop = obt_xml_node_int(n) - 1; - o->type = ABSOLUTE; - } + o = setup_func(config, pre, input, cancel, post); o->send = TRUE; o->follow = TRUE; - if ((n = obt_xml_find_node(node, "follow"))) - o->follow = obt_xml_node_bool(n); + v = g_hash_table_lookup(config, "follow"); + if (v && actions_value_is_string(v)) + o->follow = actions_value_bool(v); if (o->type == RELATIVE && o->follow) { o->interactive = TRUE; @@ -365,203 +274,3 @@ static void i_post_func(gpointer options) { screen_hide_desktop_popup(); } - -/* 3.4-compatilibity */ -static gpointer setup_follow(xmlNodePtr node) -{ - xmlNodePtr n; - Options *o = g_slice_new0(Options); - o->send = TRUE; - o->follow = TRUE; - if ((n = obt_xml_find_node(node, "follow"))) - o->follow = obt_xml_node_bool(n); - return o; -} - -static gpointer setup_go_last_func(xmlNodePtr node) -{ - Options *o = g_slice_new0(Options); - o->type = LAST; - return o; -} - -static gpointer setup_send_last_func(xmlNodePtr node) -{ - Options *o = setup_follow(node); - o->type = LAST; - return o; -} - -static gpointer setup_go_abs_func(xmlNodePtr node) -{ - xmlNodePtr n; - Options *o = g_slice_new0(Options); - o->type = ABSOLUTE; - if ((n = obt_xml_find_node(node, "desktop"))) - o->u.abs.desktop = obt_xml_node_int(n) - 1; - else - o->u.abs.desktop = screen_desktop; - return o; -} - -static void setup_rel(Options *o, xmlNodePtr node, gboolean lin, - ObDirection dir, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsIPostFunc *post) -{ - xmlNodePtr n; - - o->type = RELATIVE; - o->u.rel.linear = lin; - o->u.rel.dir = dir; - o->u.rel.wrap = TRUE; - - if ((n = obt_xml_find_node(node, "wrap"))) - o->u.rel.wrap = obt_xml_node_bool(n); - - if (input) { - o->interactive = TRUE; - *pre = i_pre_func; - *input = i_input_func; - *post = i_post_func; - } -} - -static gpointer setup_go_next_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = g_slice_new0(Options); - setup_rel(o, node, TRUE, OB_DIRECTION_EAST, pre, input, post); - return o; -} - -static gpointer setup_send_next_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = setup_follow(node); - setup_rel(o, node, TRUE, OB_DIRECTION_EAST, - pre, (o->follow ? input : NULL), post); - return o; -} - -static gpointer setup_go_prev_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = g_slice_new0(Options); - setup_rel(o, node, TRUE, OB_DIRECTION_WEST, pre, input, post); - return o; -} - -static gpointer setup_send_prev_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = setup_follow(node); - setup_rel(o, node, TRUE, OB_DIRECTION_WEST, - pre, (o->follow ? input : NULL), post); - return o; -} - -static gpointer setup_go_left_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = g_slice_new0(Options); - setup_rel(o, node, FALSE, OB_DIRECTION_WEST, pre, input, post); - return o; -} - -static gpointer setup_send_left_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = setup_follow(node); - setup_rel(o, node, FALSE, OB_DIRECTION_WEST, - pre, (o->follow ? input : NULL), post); - return o; -} - -static gpointer setup_go_right_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = g_slice_new0(Options); - setup_rel(o, node, FALSE, OB_DIRECTION_EAST, pre, input, post); - return o; -} - -static gpointer setup_send_right_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = setup_follow(node); - setup_rel(o, node, FALSE, OB_DIRECTION_EAST, - pre, (o->follow ? input : NULL), post); - return o; -} - -static gpointer setup_go_up_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = g_slice_new0(Options); - setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, pre, input, post); - return o; -} - -static gpointer setup_send_up_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = setup_follow(node); - setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, - pre, (o->follow ? input : NULL), post); - return o; -} - -static gpointer setup_go_down_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = g_slice_new0(Options); - setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, pre, input, post); - return o; -} - -static gpointer setup_send_down_func(xmlNodePtr node, - ObActionsIPreFunc *pre, - ObActionsIInputFunc *input, - ObActionsICancelFunc *cancel, - ObActionsIPostFunc *post) -{ - Options *o = setup_follow(node); - setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, - pre, (o->follow ? input : NULL), post); - return o; -} diff --git a/openbox/actions/directionalwindows.c b/openbox/actions/directionalwindows.c index 602e7edc..46ac6fd7 100644 --- a/openbox/actions/directionalwindows.c +++ b/openbox/actions/directionalwindows.c @@ -1,4 +1,7 @@ #include "openbox/actions.h" +#include "openbox/actions_list.h" +#include "openbox/actions_parser.h" +#include "openbox/actions_value.h" #include "openbox/event.h" #include "openbox/stacking.h" #include "openbox/window.h" @@ -16,18 +19,18 @@ typedef struct { ObDirection direction; gboolean bar; gboolean raise; - GSList *actions; + ObActionsList *actions; } Options; static gboolean cycling = FALSE; -static gpointer setup_func(xmlNodePtr node); -static gpointer setup_cycle_func(xmlNodePtr node, +static gpointer setup_func(GHashTable *config); +static gpointer setup_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post); -static gpointer setup_target_func(xmlNodePtr node); +static gpointer setup_target_func(GHashTable *config); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); static gboolean i_input_func(guint initial_state, @@ -40,54 +43,54 @@ static void i_cancel_func(gpointer options); static void end_cycle(gboolean cancel, guint state, Options *o); /* 3.4-compatibility */ -static gpointer setup_north_cycle_func(xmlNodePtr node, +static gpointer setup_north_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_south_cycle_func(xmlNodePtr node, +static gpointer setup_south_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_east_cycle_func(xmlNodePtr node, +static gpointer setup_east_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_west_cycle_func(xmlNodePtr node, +static gpointer setup_west_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_northwest_cycle_func(xmlNodePtr node, +static gpointer setup_northwest_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_northeast_cycle_func(xmlNodePtr node, +static gpointer setup_northeast_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_southwest_cycle_func(xmlNodePtr node, +static gpointer setup_southwest_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_southeast_cycle_func(xmlNodePtr node, +static gpointer setup_southeast_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *in, ObActionsICancelFunc *c, ObActionsIPostFunc *post); -static gpointer setup_north_target_func(xmlNodePtr node); -static gpointer setup_south_target_func(xmlNodePtr node); -static gpointer setup_east_target_func(xmlNodePtr node); -static gpointer setup_west_target_func(xmlNodePtr node); -static gpointer setup_northwest_target_func(xmlNodePtr node); -static gpointer setup_northeast_target_func(xmlNodePtr node); -static gpointer setup_southwest_target_func(xmlNodePtr node); -static gpointer setup_southeast_target_func(xmlNodePtr node); +static gpointer setup_north_target_func(GHashTable *config); +static gpointer setup_south_target_func(GHashTable *config); +static gpointer setup_east_target_func(GHashTable *config); +static gpointer setup_west_target_func(GHashTable *config); +static gpointer setup_northwest_target_func(GHashTable *config); +static gpointer setup_northeast_target_func(GHashTable *config); +static gpointer setup_southwest_target_func(GHashTable *config); +static gpointer setup_southeast_target_func(GHashTable *config); void action_directionalwindows_startup(void) { @@ -130,27 +133,33 @@ void action_directionalwindows_startup(void) free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); o->dialog = TRUE; o->bar = TRUE; - if ((n = obt_xml_find_node(node, "dialog"))) - o->dialog = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "bar"))) - o->bar = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "raise"))) - o->raise = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "panels"))) - o->dock_windows = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "desktop"))) - o->desktop_windows = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "direction"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "dialog"); + if (v && actions_value_is_string(v)) + o->dialog = actions_value_bool(v); + v = g_hash_table_lookup(config, "bar"); + if (v && actions_value_is_string(v)) + o->bar = actions_value_bool(v); + v = g_hash_table_lookup(config, "raise"); + if (v && actions_value_is_string(v)) + o->raise = actions_value_bool(v); + v = g_hash_table_lookup(config, "panels"); + if (v && actions_value_is_string(v)) + o->dock_windows = actions_value_bool(v); + v = g_hash_table_lookup(config, "desktop"); + if (v && actions_value_is_string(v)) + o->desktop_windows = actions_value_bool(v); + v = g_hash_table_lookup(config, "direction"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); if (!g_ascii_strcasecmp(s, "north") || !g_ascii_strcasecmp(s, "up")) o->direction = OB_DIRECTION_NORTH; @@ -171,47 +180,41 @@ static gpointer setup_func(xmlNodePtr node) o->direction = OB_DIRECTION_SOUTHWEST; else if (!g_ascii_strcasecmp(s, "southeast")) o->direction = OB_DIRECTION_SOUTHEAST; - g_free(s); } - if ((n = obt_xml_find_node(node, "finalactions"))) { - xmlNodePtr m; - - m = obt_xml_find_node(n->children, "action"); - while (m) { - ObActionsAct *action = actions_parse(m); - if (action) o->actions = g_slist_append(o->actions, action); - m = obt_xml_find_node(m->next, "action"); - } + v = g_hash_table_lookup(config, "finalactions"); + if (v && actions_value_is_actions_list(v)) { + o->actions = actions_value_actions_list(v); + actions_list_ref(o->actions); } else { - o->actions = g_slist_prepend(o->actions, - actions_parse_string("Focus")); - o->actions = g_slist_prepend(o->actions, - actions_parse_string("Raise")); - o->actions = g_slist_prepend(o->actions, - actions_parse_string("Unshade")); + ObActionsParser *p = actions_parser_new(); + o->actions = actions_parser_read_string(p, + "focus\n" + "raise\n" + "unshade\n"); + actions_parser_unref(p); } return o; } -static gpointer setup_cycle_func(xmlNodePtr node, +static gpointer setup_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_func(node); + Options *o = setup_func(config); o->interactive = TRUE; *input = i_input_func; *cancel = i_cancel_func; return o; } -static gpointer setup_target_func(xmlNodePtr node) +static gpointer setup_target_func(GHashTable *config) { - Options *o = setup_func(node); + Options *o = setup_func(config); o->interactive = FALSE; return o; } @@ -220,11 +223,7 @@ static void free_func(gpointer options) { Options *o = options; - while (o->actions) { - actions_act_unref(o->actions->data); - o->actions = g_slist_delete_link(o->actions, o->actions); - } - + actions_list_unref(o->actions); g_slice_free(Options, o); } @@ -322,146 +321,146 @@ static void end_cycle(gboolean cancel, guint state, Options *o) } /* 3.4-compatibility */ -static gpointer setup_north_cycle_func(xmlNodePtr node, +static gpointer setup_north_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_cycle_func(node, pre, input, cancel, post); + Options *o = setup_cycle_func(config, pre, input, cancel, post); o->direction = OB_DIRECTION_NORTH; return o; } -static gpointer setup_south_cycle_func(xmlNodePtr node, +static gpointer setup_south_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_cycle_func(node, pre, input, cancel, post); + Options *o = setup_cycle_func(config, pre, input, cancel, post); o->direction = OB_DIRECTION_SOUTH; return o; } -static gpointer setup_east_cycle_func(xmlNodePtr node, +static gpointer setup_east_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_cycle_func(node, pre, input, cancel, post); + Options *o = setup_cycle_func(config, pre, input, cancel, post); o->direction = OB_DIRECTION_EAST; return o; } -static gpointer setup_west_cycle_func(xmlNodePtr node, +static gpointer setup_west_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_cycle_func(node, pre, input, cancel, post); + Options *o = setup_cycle_func(config, pre, input, cancel, post); o->direction = OB_DIRECTION_WEST; return o; } -static gpointer setup_northwest_cycle_func(xmlNodePtr node, +static gpointer setup_northwest_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_cycle_func(node, pre, input, cancel, post); + Options *o = setup_cycle_func(config, pre, input, cancel, post); o->direction = OB_DIRECTION_NORTHWEST; return o; } -static gpointer setup_northeast_cycle_func(xmlNodePtr node, +static gpointer setup_northeast_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_cycle_func(node, pre, input, cancel, post); + Options *o = setup_cycle_func(config, pre, input, cancel, post); o->direction = OB_DIRECTION_EAST; return o; } -static gpointer setup_southwest_cycle_func(xmlNodePtr node, +static gpointer setup_southwest_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_cycle_func(node, pre, input, cancel, post); + Options *o = setup_cycle_func(config, pre, input, cancel, post); o->direction = OB_DIRECTION_SOUTHWEST; return o; } -static gpointer setup_southeast_cycle_func(xmlNodePtr node, +static gpointer setup_southeast_cycle_func(GHashTable *config, ObActionsIPreFunc *pre, ObActionsIInputFunc *input, ObActionsICancelFunc *cancel, ObActionsIPostFunc *post) { - Options *o = setup_cycle_func(node, pre, input, cancel, post); + Options *o = setup_cycle_func(config, pre, input, cancel, post); o->direction = OB_DIRECTION_SOUTHEAST; return o; } -static gpointer setup_north_target_func(xmlNodePtr node) +static gpointer setup_north_target_func(GHashTable *config) { - Options *o = setup_target_func(node); + Options *o = setup_target_func(config); o->direction = OB_DIRECTION_NORTH; return o; } -static gpointer setup_south_target_func(xmlNodePtr node) +static gpointer setup_south_target_func(GHashTable *config) { - Options *o = setup_target_func(node); + Options *o = setup_target_func(config); o->direction = OB_DIRECTION_SOUTH; return o; } -static gpointer setup_east_target_func(xmlNodePtr node) +static gpointer setup_east_target_func(GHashTable *config) { - Options *o = setup_target_func(node); + Options *o = setup_target_func(config); o->direction = OB_DIRECTION_EAST; return o; } -static gpointer setup_west_target_func(xmlNodePtr node) +static gpointer setup_west_target_func(GHashTable *config) { - Options *o = setup_target_func(node); + Options *o = setup_target_func(config); o->direction = OB_DIRECTION_WEST; return o; } -static gpointer setup_northwest_target_func(xmlNodePtr node) +static gpointer setup_northwest_target_func(GHashTable *config) { - Options *o = setup_target_func(node); + Options *o = setup_target_func(config); o->direction = OB_DIRECTION_NORTHWEST; return o; } -static gpointer setup_northeast_target_func(xmlNodePtr node) +static gpointer setup_northeast_target_func(GHashTable *config) { - Options *o = setup_target_func(node); + Options *o = setup_target_func(config); o->direction = OB_DIRECTION_NORTHEAST; return o; } -static gpointer setup_southwest_target_func(xmlNodePtr node) +static gpointer setup_southwest_target_func(GHashTable *config) { - Options *o = setup_target_func(node); + Options *o = setup_target_func(config); o->direction = OB_DIRECTION_SOUTHWEST; return o; } -static gpointer setup_southeast_target_func(xmlNodePtr node) +static gpointer setup_southeast_target_func(GHashTable *config) { - Options *o = setup_target_func(node); + Options *o = setup_target_func(config); o->direction = OB_DIRECTION_SOUTHEAST; return o; } diff --git a/openbox/actions/execute.c b/openbox/actions/execute.c index 380ffa00..c995829a 100644 --- a/openbox/actions/execute.c +++ b/openbox/actions/execute.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/event.h" #include "openbox/startupnotify.h" #include "openbox/client.h" @@ -21,7 +22,7 @@ typedef struct { ObActionsData *data; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); static void shutdown_func(void); @@ -48,34 +49,33 @@ static void client_dest(ObClient *client, gpointer data) } } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "command")) || - (n = obt_xml_find_node(node, "execute"))) - { - gchar *s = obt_xml_node_string(n); - o->cmd = obt_paths_expand_tilde(s); - g_free(s); - } - - if ((n = obt_xml_find_node(node, "prompt"))) - o->prompt = obt_xml_node_string(n); - - if ((n = obt_xml_find_node(node, "startupnotify"))) { - xmlNodePtr m; - if ((m = obt_xml_find_node(n->children, "enabled"))) - o->sn = obt_xml_node_bool(m); - if ((m = obt_xml_find_node(n->children, "name"))) - o->sn_name = obt_xml_node_string(m); - if ((m = obt_xml_find_node(n->children, "icon"))) - o->sn_icon = obt_xml_node_string(m); - if ((m = obt_xml_find_node(n->children, "wmclass"))) - o->sn_wmclass = obt_xml_node_string(m); + v = g_hash_table_lookup(config, "command"); + if (v && actions_value_is_string(v)) + o->cmd = obt_paths_expand_tilde(actions_value_string(v)); + + v = g_hash_table_lookup(config, "prompt"); + if (v && actions_value_is_string(v)) + o->prompt = g_strdup(actions_value_string(v)); + + v = g_hash_table_lookup(config, "startupnotify"); + if (v && actions_value_is_string(v) && actions_value_bool(v)) { + o->sn = TRUE; + v = g_hash_table_lookup(config, "name"); + if (v && actions_value_is_string(v)) + o->sn_name = g_strdup(actions_value_string(v)); + v = g_hash_table_lookup(config, "icon"); + if (v && actions_value_is_string(v)) + o->sn_icon = g_strdup(actions_value_string(v)); + v = g_hash_table_lookup(config, "wmclass"); + if (v && actions_value_is_string(v)) + o->sn_wmclass = g_strdup(actions_value_string(v)); } return o; } diff --git a/openbox/actions/exit.c b/openbox/actions/exit.c index 2d9fc633..f2785014 100644 --- a/openbox/actions/exit.c +++ b/openbox/actions/exit.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/openbox.h" #include "openbox/prompt.h" #include "openbox/session.h" @@ -8,7 +9,7 @@ typedef struct { gboolean prompt; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); @@ -18,16 +19,17 @@ void action_exit_startup(void) actions_register("SessionLogout", setup_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); o->prompt = TRUE; - if ((n = obt_xml_find_node(node, "prompt"))) - o->prompt = obt_xml_node_bool(n); + v = g_hash_table_lookup(config, "prompt"); + if (v && actions_value_is_string(v)) + o->prompt = actions_value_bool(v); return o; } diff --git a/openbox/actions/focus.c b/openbox/actions/focus.c index 6c8957c8..e5e5cc53 100644 --- a/openbox/actions/focus.c +++ b/openbox/actions/focus.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/event.h" #include "openbox/client.h" #include "openbox/focus.h" @@ -9,7 +10,7 @@ typedef struct { gboolean stop_int; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); @@ -18,18 +19,20 @@ void action_focus_startup(void) actions_register("Focus", setup_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); o->stop_int = TRUE; - if ((n = obt_xml_find_node(node, "here"))) - o->here = obt_xml_node_bool(n); - if ((n = obt_xml_find_node(node, "stopInteractive"))) - o->stop_int = obt_xml_node_bool(n); + v = g_hash_table_lookup(config, "here"); + if (v && actions_value_is_string(v)) + o->here = actions_value_bool(v); + v = g_hash_table_lookup(config, "stopInteractive"); + if (v && actions_value_is_string(v)) + o->stop_int = actions_value_bool(v); return o; } diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index d5a7bfdd..d7618321 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/misc.h" #include "openbox/client.h" #include "openbox/frame.h" @@ -10,15 +11,15 @@ typedef struct { gboolean shrink; } Options; -static gpointer setup_func(xmlNodePtr node); -static gpointer setup_shrink_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); +static gpointer setup_shrink_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); /* 3.4-compatibility */ -static gpointer setup_north_func(xmlNodePtr node); -static gpointer setup_south_func(xmlNodePtr node); -static gpointer setup_east_func(xmlNodePtr node); -static gpointer setup_west_func(xmlNodePtr node); +static gpointer setup_north_func(GHashTable *config); +static gpointer setup_south_func(GHashTable *config); +static gpointer setup_east_func(GHashTable *config); +static gpointer setup_west_func(GHashTable *config); void action_growtoedge_startup(void) { @@ -33,17 +34,18 @@ void action_growtoedge_startup(void) actions_register("GrowToEdgeWest", setup_west_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); o->dir = OB_DIRECTION_NORTH; o->shrink = FALSE; - if ((n = obt_xml_find_node(node, "direction"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "direction"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); if (!g_ascii_strcasecmp(s, "north") || !g_ascii_strcasecmp(s, "up")) o->dir = OB_DIRECTION_NORTH; @@ -56,17 +58,16 @@ static gpointer setup_func(xmlNodePtr node) else if (!g_ascii_strcasecmp(s, "east") || !g_ascii_strcasecmp(s, "right")) o->dir = OB_DIRECTION_EAST; - g_free(s); } return o; } -static gpointer setup_shrink_func(xmlNodePtr node) +static gpointer setup_shrink_func(GHashTable *config) { Options *o; - o = setup_func(node); + o = setup_func(config); o->shrink = TRUE; return o; @@ -167,7 +168,7 @@ static gboolean run_func(ObActionsData *data, gpointer options) } /* 3.4-compatibility */ -static gpointer setup_north_func(xmlNodePtr node) +static gpointer setup_north_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->shrink = FALSE; @@ -175,7 +176,7 @@ static gpointer setup_north_func(xmlNodePtr node) return o; } -static gpointer setup_south_func(xmlNodePtr node) +static gpointer setup_south_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->shrink = FALSE; @@ -183,7 +184,7 @@ static gpointer setup_south_func(xmlNodePtr node) return o; } -static gpointer setup_east_func(xmlNodePtr node) +static gpointer setup_east_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->shrink = FALSE; @@ -191,7 +192,7 @@ static gpointer setup_east_func(xmlNodePtr node) return o; } -static gpointer setup_west_func(xmlNodePtr node) +static gpointer setup_west_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->shrink = FALSE; diff --git a/openbox/actions/layer.c b/openbox/actions/layer.c index ed1eeedc..7baa5ab0 100644 --- a/openbox/actions/layer.c +++ b/openbox/actions/layer.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/client.h" typedef struct { @@ -6,15 +7,15 @@ typedef struct { gboolean toggle; } Options; -static gpointer setup_func_top(xmlNodePtr node); -static gpointer setup_func_bottom(xmlNodePtr node); -static gpointer setup_func_send(xmlNodePtr node); +static gpointer setup_func_top(GHashTable *config); +static gpointer setup_func_bottom(GHashTable *config); +static gpointer setup_func_send(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); /* 3.4-compatibility */ -static gpointer setup_sendtop_func(xmlNodePtr node); -static gpointer setup_sendbottom_func(xmlNodePtr node); -static gpointer setup_sendnormal_func(xmlNodePtr node); +static gpointer setup_sendtop_func(GHashTable *config); +static gpointer setup_sendbottom_func(GHashTable *config); +static gpointer setup_sendnormal_func(GHashTable *config); void action_layer_startup(void) { @@ -33,7 +34,7 @@ void action_layer_startup(void) run_func); } -static gpointer setup_func_top(xmlNodePtr node) +static gpointer setup_func_top(GHashTable *config) { Options *o = g_slice_new0(Options); o->layer = 1; @@ -41,7 +42,7 @@ static gpointer setup_func_top(xmlNodePtr node) return o; } -static gpointer setup_func_bottom(xmlNodePtr node) +static gpointer setup_func_bottom(GHashTable *config) { Options *o = g_slice_new0(Options); o->layer = -1; @@ -49,15 +50,16 @@ static gpointer setup_func_bottom(xmlNodePtr node) return o; } -static gpointer setup_func_send(xmlNodePtr node) +static gpointer setup_func_send(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "layer"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "layer"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); if (!g_ascii_strcasecmp(s, "above") || !g_ascii_strcasecmp(s, "top")) o->layer = 1; @@ -67,7 +69,6 @@ static gpointer setup_func_send(xmlNodePtr node) else if (!g_ascii_strcasecmp(s, "normal") || !g_ascii_strcasecmp(s, "middle")) o->layer = 0; - g_free(s); } return o; @@ -106,7 +107,7 @@ static gboolean run_func(ObActionsData *data, gpointer options) } /* 3.4-compatibility */ -static gpointer setup_sendtop_func(xmlNodePtr node) +static gpointer setup_sendtop_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->layer = 1; @@ -114,7 +115,7 @@ static gpointer setup_sendtop_func(xmlNodePtr node) return o; } -static gpointer setup_sendbottom_func(xmlNodePtr node) +static gpointer setup_sendbottom_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->layer = -1; @@ -122,7 +123,7 @@ static gpointer setup_sendbottom_func(xmlNodePtr node) return o; } -static gpointer setup_sendnormal_func(xmlNodePtr node) +static gpointer setup_sendnormal_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->layer = 0; diff --git a/openbox/actions/maximize.c b/openbox/actions/maximize.c index db7c36bb..2bb6a62b 100644 --- a/openbox/actions/maximize.c +++ b/openbox/actions/maximize.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/client.h" /* These match the values for client_maximize */ @@ -12,59 +13,36 @@ typedef struct { MaxDirection dir; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func_on(ObActionsData *data, gpointer options); static gboolean run_func_off(ObActionsData *data, gpointer options); static gboolean run_func_toggle(ObActionsData *data, gpointer options); -/* 3.4-compatibility */ -static gpointer setup_both_func(xmlNodePtr node); -static gpointer setup_horz_func(xmlNodePtr node); -static gpointer setup_vert_func(xmlNodePtr node); void action_maximize_startup(void) { actions_register("Maximize", setup_func, free_func, run_func_on); actions_register("Unmaximize", setup_func, free_func, run_func_off); actions_register("ToggleMaximize", setup_func, free_func, run_func_toggle); - /* 3.4-compatibility */ - actions_register("MaximizeFull", setup_both_func, free_func, - run_func_on); - actions_register("UnmaximizeFull", setup_both_func, free_func, - run_func_off); - actions_register("ToggleMaximizeFull", setup_both_func, free_func, - run_func_toggle); - actions_register("MaximizeHorz", setup_horz_func, free_func, - run_func_on); - actions_register("UnmaximizeHorz", setup_horz_func, free_func, - run_func_off); - actions_register("ToggleMaximizeHorz", setup_horz_func, free_func, - run_func_toggle); - actions_register("MaximizeVert", setup_vert_func, free_func, - run_func_on); - actions_register("UnmaximizeVert", setup_vert_func, free_func, - run_func_off); - actions_register("ToggleMaximizeVert", setup_vert_func, free_func, - run_func_toggle); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); o->dir = BOTH; - if ((n = obt_xml_find_node(node, "direction"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "dir"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); if (!g_ascii_strcasecmp(s, "vertical") || !g_ascii_strcasecmp(s, "vert")) o->dir = VERT; else if (!g_ascii_strcasecmp(s, "horizontal") || !g_ascii_strcasecmp(s, "horz")) o->dir = HORZ; - g_free(s); } return o; @@ -115,26 +93,3 @@ static gboolean run_func_toggle(ObActionsData *data, gpointer options) } return FALSE; } - -/* 3.4-compatibility */ -static gpointer setup_both_func(xmlNodePtr node) -{ - Options *o = g_slice_new0(Options); - o->dir = BOTH; - return o; -} - -static gpointer setup_horz_func(xmlNodePtr node) -{ - Options *o = g_slice_new0(Options); - o->dir = HORZ; - return o; -} - -static gpointer setup_vert_func(xmlNodePtr node) -{ - Options *o = g_slice_new0(Options); - o->dir = VERT; - return o; -} - diff --git a/openbox/actions/moverelative.c b/openbox/actions/moverelative.c index b67b5cf1..4b3a0c5a 100644 --- a/openbox/actions/moverelative.c +++ b/openbox/actions/moverelative.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/client.h" #include "openbox/screen.h" #include "openbox/frame.h" @@ -11,7 +12,7 @@ typedef struct { gint y_denom; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); @@ -20,24 +21,19 @@ void action_moverelative_startup(void) actions_register("MoveRelative", setup_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; - gchar *s; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "x"))) { - s = obt_xml_node_string(n); - config_parse_relative_number(s, &o->x, &o->x_denom); - g_free(s); - } - if ((n = obt_xml_find_node(node, "y"))) { - s = obt_xml_node_string(n); - config_parse_relative_number(s, &o->y, &o->y_denom); - g_free(s); - } + v = g_hash_table_lookup(config, "x"); + if (v && actions_value_is_string(v)) + actions_value_fraction(v, &o->x, &o->x_denom); + v = g_hash_table_lookup(config, "y"); + if (v && actions_value_is_string(v)) + actions_value_fraction(v, &o->y, &o->y_denom); return o; } diff --git a/openbox/actions/moveresizeto.c b/openbox/actions/moveresizeto.c index c23661cd..410fc709 100644 --- a/openbox/actions/moveresizeto.c +++ b/openbox/actions/moveresizeto.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/client.h" #include "openbox/screen.h" #include "openbox/frame.h" @@ -21,11 +22,11 @@ typedef struct { gint monitor; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); /* 3.4-compatibility */ -static gpointer setup_center_func(xmlNodePtr node); +static gpointer setup_center_func(GHashTable *config); void action_moveresizeto_startup(void) { @@ -34,9 +35,9 @@ void action_moveresizeto_startup(void) actions_register("MoveToCenter", setup_center_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); @@ -46,27 +47,25 @@ static gpointer setup_func(xmlNodePtr node) o->h = G_MININT; o->monitor = CURRENT_MONITOR; - if ((n = obt_xml_find_node(node, "x"))) - config_parse_gravity_coord(n, &o->x); - - if ((n = obt_xml_find_node(node, "y"))) - config_parse_gravity_coord(n, &o->y); - - if ((n = obt_xml_find_node(node, "width"))) { - gchar *s = obt_xml_node_string(n); - if (g_ascii_strcasecmp(s, "current") != 0) - config_parse_relative_number(s, &o->w, &o->w_denom); - g_free(s); - } - if ((n = obt_xml_find_node(node, "height"))) { - gchar *s = obt_xml_node_string(n); - if (g_ascii_strcasecmp(s, "current") != 0) - config_parse_relative_number(s, &o->h, &o->h_denom); - g_free(s); - } - - if ((n = obt_xml_find_node(node, "monitor"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "x"); + if (v && actions_value_is_string(v)) + actions_value_gravity_coord(v, &o->x); + v = g_hash_table_lookup(config, "y"); + if (v && actions_value_is_string(v)) + actions_value_gravity_coord(v, &o->y); + + v = g_hash_table_lookup(config, "width"); + if (v && actions_value_is_string(v)) + if (g_ascii_strcasecmp(actions_value_string(v), "current") != 0) + actions_value_fraction(v, &o->w, &o->w_denom); + v = g_hash_table_lookup(config, "height"); + if (v && actions_value_is_string(v)) + if (g_ascii_strcasecmp(actions_value_string(v), "current") != 0) + actions_value_fraction(v, &o->h, &o->h_denom); + + v = g_hash_table_lookup(config, "monitor"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); if (g_ascii_strcasecmp(s, "current") != 0) { if (!g_ascii_strcasecmp(s, "all")) o->monitor = ALL_MONITORS; @@ -75,9 +74,8 @@ static gpointer setup_func(xmlNodePtr node) else if(!g_ascii_strcasecmp(s, "prev")) o->monitor = PREV_MONITOR; else - o->monitor = obt_xml_node_int(n) - 1; + o->monitor = actions_value_int(v) - 1; } - g_free(s); } return o; @@ -173,7 +171,7 @@ static gboolean run_func(ObActionsData *data, gpointer options) } /* 3.4-compatibility */ -static gpointer setup_center_func(xmlNodePtr node) +static gpointer setup_center_func(GHashTable *config) { Options *o; diff --git a/openbox/actions/movetoedge.c b/openbox/actions/movetoedge.c index ef5b6920..cff299ec 100644 --- a/openbox/actions/movetoedge.c +++ b/openbox/actions/movetoedge.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/misc.h" #include "openbox/client.h" #include "openbox/frame.h" @@ -9,14 +10,14 @@ typedef struct { ObDirection dir; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); /* 3.4-compatibility */ -static gpointer setup_north_func(xmlNodePtr node); -static gpointer setup_south_func(xmlNodePtr node); -static gpointer setup_east_func(xmlNodePtr node); -static gpointer setup_west_func(xmlNodePtr node); +static gpointer setup_north_func(GHashTable *config); +static gpointer setup_south_func(GHashTable *config); +static gpointer setup_east_func(GHashTable *config); +static gpointer setup_west_func(GHashTable *config); void action_movetoedge_startup(void) { @@ -28,16 +29,17 @@ void action_movetoedge_startup(void) actions_register("MoveToEdgeWest", setup_west_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); o->dir = OB_DIRECTION_NORTH; - if ((n = obt_xml_find_node(node, "direction"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "direction"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); if (!g_ascii_strcasecmp(s, "north") || !g_ascii_strcasecmp(s, "up")) o->dir = OB_DIRECTION_NORTH; @@ -50,7 +52,6 @@ static gpointer setup_func(xmlNodePtr node) else if (!g_ascii_strcasecmp(s, "east") || !g_ascii_strcasecmp(s, "right")) o->dir = OB_DIRECTION_EAST; - g_free(s); } return o; @@ -81,28 +82,28 @@ static gboolean run_func(ObActionsData *data, gpointer options) } /* 3.4-compatibility */ -static gpointer setup_north_func(xmlNodePtr node) +static gpointer setup_north_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->dir = OB_DIRECTION_NORTH; return o; } -static gpointer setup_south_func(xmlNodePtr node) +static gpointer setup_south_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->dir = OB_DIRECTION_SOUTH; return o; } -static gpointer setup_east_func(xmlNodePtr node) +static gpointer setup_east_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->dir = OB_DIRECTION_EAST; return o; } -static gpointer setup_west_func(xmlNodePtr node) +static gpointer setup_west_func(GHashTable *config) { Options *o = g_slice_new0(Options); o->dir = OB_DIRECTION_WEST; diff --git a/openbox/actions/resize.c b/openbox/actions/resize.c index f6858d2d..5d6054d8 100644 --- a/openbox/actions/resize.c +++ b/openbox/actions/resize.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/moveresize.h" #include "openbox/client.h" #include "openbox/frame.h" @@ -9,7 +10,7 @@ typedef struct { guint32 corner; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); @@ -21,15 +22,16 @@ void action_resize_startup(void) actions_register("Resize", setup_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "edge"))) { - gchar *s = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "edge"); + if (v && actions_value_is_string(v)) { + const gchar *s = actions_value_string(v); o->corner_specified = TRUE; if (!g_ascii_strcasecmp(s, "top")) @@ -50,8 +52,6 @@ static gpointer setup_func(xmlNodePtr node) o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT); else o->corner_specified = FALSE; - - g_free(s); } return o; } diff --git a/openbox/actions/resizerelative.c b/openbox/actions/resizerelative.c index e32aff32..b0e4f71d 100644 --- a/openbox/actions/resizerelative.c +++ b/openbox/actions/resizerelative.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/client.h" #include "openbox/screen.h" #include "openbox/frame.h" @@ -15,7 +16,7 @@ typedef struct { gint bottom_denom; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); @@ -24,32 +25,25 @@ void action_resizerelative_startup(void) actions_register("ResizeRelative", setup_func, free_func, run_func); } -static void xml_node_relative(xmlNodePtr n, gint *num, gint *denom) +static gpointer setup_func(GHashTable *config) { - gchar *s; - - s = obt_xml_node_string(n); - config_parse_relative_number(s, num, denom); - g_free(s); -} - -static gpointer setup_func(xmlNodePtr node) -{ - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "left"))) - xml_node_relative(n, &o->left, &o->left_denom); - if ((n = obt_xml_find_node(node, "right"))) - xml_node_relative(n, &o->right, &o->right_denom); - if ((n = obt_xml_find_node(node, "top")) || - (n = obt_xml_find_node(node, "up"))) - xml_node_relative(n, &o->top, &o->top_denom); - if ((n = obt_xml_find_node(node, "bottom")) || - (n = obt_xml_find_node(node, "down"))) - xml_node_relative(n, &o->bottom, &o->bottom_denom); + v = g_hash_table_lookup(config, "left"); + if (v && actions_value_is_string(v)) + actions_value_fraction(v, &o->left, &o->left_denom); + v = g_hash_table_lookup(config, "right"); + if (v && actions_value_is_string(v)) + actions_value_fraction(v, &o->right, &o->right_denom); + v = g_hash_table_lookup(config, "top"); + if (v && actions_value_is_string(v)) + actions_value_fraction(v, &o->top, &o->top_denom); + v = g_hash_table_lookup(config, "bottom"); + if (v && actions_value_is_string(v)) + actions_value_fraction(v, &o->bottom, &o->bottom_denom); return o; } diff --git a/openbox/actions/restart.c b/openbox/actions/restart.c index dc9a218a..7387ba83 100644 --- a/openbox/actions/restart.c +++ b/openbox/actions/restart.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/openbox.h" #include "obt/paths.h" @@ -6,7 +7,7 @@ typedef struct { gchar *cmd; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); @@ -15,20 +16,16 @@ void action_restart_startup(void) actions_register("Restart", setup_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "command")) || - (n = obt_xml_find_node(node, "execute"))) - { - gchar *s = obt_xml_node_string(n); - o->cmd = obt_paths_expand_tilde(s); - g_free(s); - } + v = g_hash_table_lookup(config, "command"); + if (v && actions_value_is_string(v)) + o->cmd = obt_paths_expand_tilde(actions_value_string(v)); return o; } diff --git a/openbox/actions/showmenu.c b/openbox/actions/showmenu.c index 485a31d5..1687f2a4 100644 --- a/openbox/actions/showmenu.c +++ b/openbox/actions/showmenu.c @@ -1,4 +1,5 @@ #include "openbox/actions.h" +#include "openbox/actions_value.h" #include "openbox/menu.h" #include @@ -6,7 +7,7 @@ typedef struct { gchar *name; } Options; -static gpointer setup_func(xmlNodePtr node); +static gpointer setup_func(GHashTable *config); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); @@ -15,15 +16,16 @@ void action_showmenu_startup(void) actions_register("ShowMenu", setup_func, free_func, run_func); } -static gpointer setup_func(xmlNodePtr node) +static gpointer setup_func(GHashTable *config) { - xmlNodePtr n; + ObActionsValue *v; Options *o; o = g_slice_new0(Options); - if ((n = obt_xml_find_node(node, "menu"))) - o->name = obt_xml_node_string(n); + v = g_hash_table_lookup(config, "menu"); + if (v && actions_value_is_string(v)) + o->name = g_strdup(actions_value_string(v)); return o; } diff --git a/openbox/actions_list.c b/openbox/actions_list.c index 20f2b90e..345f47b9 100644 --- a/openbox/actions_list.c +++ b/openbox/actions_list.c @@ -17,26 +17,14 @@ */ #include "actions_list.h" +#include "actions.h" +#include "actions_value.h" #include -struct _ObActionsListValue { - gint ref; - enum { - OB_AL_STRING, - OB_AL_INTEGER, - OB_AL_ACTIONSLIST - } type; - union { - gchar *string; - guint integer; - ObActionsList *actions; - } v; -}; - void actions_list_ref(ObActionsList *l) { - ++l->ref; + if (l) ++l->ref; } void actions_list_unref(ObActionsList *l) @@ -63,97 +51,18 @@ void actions_list_test_destroy(ObActionsListTest *t) ObActionsListTest *n = t->next; g_free(t->key); - actions_list_value_unref(t->value); + actions_value_unref(t->value); g_slice_free(ObActionsListTest, t); t = n; } } -ObActionsListValue* actions_list_value_new_string(const gchar *s) -{ - return actions_list_value_new_string_steal(g_strdup(s)); -} - -ObActionsListValue* actions_list_value_new_string_steal(gchar *s) -{ - ObActionsListValue *v = g_slice_new(ObActionsListValue); - v->ref = 1; - v->type = OB_AL_STRING; - v->v.string = s; - return v; -} - -ObActionsListValue* actions_list_value_new_int(gint i) -{ - ObActionsListValue *v = g_slice_new(ObActionsListValue); - v->ref = 1; - v->type = OB_AL_INTEGER; - v->v.integer = i; - return v; -} - -ObActionsListValue* actions_list_value_new_actions_list(ObActionsList *al) -{ - ObActionsListValue *v = g_slice_new(ObActionsListValue); - v->ref = 1; - v->type = OB_AL_ACTIONSLIST; - v->v.actions = al; - actions_list_ref(al); - return v; -} - -void actions_list_value_ref(ObActionsListValue *v) -{ - ++v->ref; -} - -void actions_list_value_unref(ObActionsListValue *v) -{ - if (v && --v->ref < 1) { - switch (v->type) { - case OB_AL_STRING: - g_free(v->v.string); - break; - case OB_AL_ACTIONSLIST: - actions_list_unref(v->v.actions); - break; - case OB_AL_INTEGER: - break; - } - g_slice_free(ObActionsListValue, v); - } -} - -gboolean actions_list_value_is_string(ObActionsListValue *v) -{ - return v->type == OB_AL_STRING; -} - -gboolean actions_list_value_is_int(ObActionsListValue *v) -{ - return v->type == OB_AL_INTEGER; -} - -gboolean actions_list_value_is_actions_list(ObActionsListValue *v) +ObActionsList* actions_list_concat(ObActionsList *a, ObActionsList *b) { - return v->type == OB_AL_ACTIONSLIST; -} + ObActionsList *start = a; -gchar* actions_list_value_string(ObActionsListValue *v) -{ - g_return_val_if_fail(v->type == OB_AL_STRING, NULL); - return v->v.string; -} - -gint actions_list_value_int(ObActionsListValue *v) -{ - g_return_val_if_fail(v->type == OB_AL_INTEGER, 0); - return v->v.integer; + if (!start) return b; + while (a->next) a = a->next; + a->next = b; + return start; } - -ObActionsList* actions_list_value_actions_list(ObActionsListValue *v) -{ - g_return_val_if_fail(v->type == OB_AL_ACTIONSLIST, NULL); - return v->v.actions; -} - diff --git a/openbox/actions_list.h b/openbox/actions_list.h index f5710e36..6b84666e 100644 --- a/openbox/actions_list.h +++ b/openbox/actions_list.h @@ -16,13 +16,13 @@ See the COPYING file for a copy of the GNU General Public License. */ -#include "actions.h" - #include +struct _ObActionsAct; +struct _ObActionsValue; + typedef struct _ObActionsList ObActionsList; typedef struct _ObActionsListTest ObActionsListTest; -typedef struct _ObActionsListValue ObActionsListValue; /*! Each node of the Actions list is an action itself (or a filter bound to an action). */ @@ -35,14 +35,14 @@ struct _ObActionsList { ObActionsList *thendo; /* can be null */ ObActionsList *elsedo; /* can be null */ } f; - ObActionsAct *action; + struct _ObActionsAct *action; } u; ObActionsList *next; }; struct _ObActionsListTest { gchar *key; - ObActionsListValue *value; /* can be null */ + struct _ObActionsValue *value; /* can be null */ gboolean and; ObActionsListTest *next; }; @@ -52,23 +52,4 @@ void actions_list_unref(ObActionsList *l); void actions_list_test_destroy(ObActionsListTest *t); -/*! Creates a new value by making a copy of the given string. */ -ObActionsListValue* actions_list_value_new_string(const gchar *s); -/*! Creates a new value from a string, and steals ownership of the string. It - will be freed when then value is destroyed. */ -ObActionsListValue* actions_list_value_new_string_steal(gchar *s); -/*! Creates a new value that holds an integer. */ -ObActionsListValue* actions_list_value_new_int(gint i); -/*! Creates a new value with a given actions list. */ -ObActionsListValue* actions_list_value_new_actions_list(ObActionsList *al); - -void actions_list_value_ref(ObActionsListValue *v); -void actions_list_value_unref(ObActionsListValue *v); - -gboolean actions_list_value_is_string(ObActionsListValue *v); -gboolean actions_list_value_is_int(ObActionsListValue *v); -gboolean actions_list_value_is_actions_list(ObActionsListValue *v); - -gchar* actions_list_value_string(ObActionsListValue *v); -gint actions_list_value_int(ObActionsListValue *v); -ObActionsList* actions_list_value_actions_list(ObActionsListValue *v); +ObActionsList* actions_list_concat(ObActionsList *a, ObActionsList *b); diff --git a/openbox/actions_parser.c b/openbox/actions_parser.c index 2ef8ee8f..5947378d 100644 --- a/openbox/actions_parser.c +++ b/openbox/actions_parser.c @@ -17,25 +17,33 @@ */ #include "actions_parser.h" +#include "actions.h" +#include "actions_list.h" +#include "actions_value.h" #include "gettext.h" #ifdef HAVE_STRING_H # include #endif +struct _ObActionsList; +struct _ObActionsListTest; +struct _ObActionsValue; + #define SKIP " \t" -#define IDENTIFIER_FIRST G_CSET_a_2_z G_CSET_A_2_Z -#define IDENTIFIER_NTH G_CSET_a_2_z G_CSET_A_2_Z \ - G_CSET_DIGITS G_CSET_LATINS G_CSET_LATINC "_-" +#define IDENTIFIER_FIRST G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_" +#define IDENTIFIER_NTH IDENTIFIER_FIRST G_CSET_LATINS G_CSET_LATINC #define ESCAPE_SEQS "\"()" -ObActionsList* parse_list(ObActionsParser *p, GTokenType end, gboolean *e); -ObActionsList* parse_action(ObActionsParser *p, gboolean *e); -ObActionsList* parse_filter(ObActionsParser *p, gboolean *e); -ObActionsListTest* parse_filter_test(ObActionsParser *p, gboolean *e); -ObActionsListValue* parse_value(ObActionsParser *p, - gboolean allow_actions, - gboolean *e); +struct _ObActionsList* parse_list(ObActionsParser *p, + GTokenType end, + gboolean *e); +struct _ObActionsList* parse_action(ObActionsParser *p, gboolean *e); +struct _ObActionsList* parse_filter(ObActionsParser *p, gboolean *e); +struct _ObActionsListTest* parse_filter_test(ObActionsParser *p, gboolean *e); +struct _ObActionsValue* parse_value(ObActionsParser *p, + gboolean allow_actions, + gboolean *e); gchar* parse_string(ObActionsParser *p, guchar end, gboolean *e); struct _ObActionsParser @@ -103,6 +111,7 @@ ObActionsList* actions_parser_read_string(ObActionsParser *p, g_scanner_input_text(p->scan, text, strlen(text)); p->scan->input_name = "(console)"; + e = FALSE; return parse_list(p, G_TOKEN_EOF, &e); } @@ -119,6 +128,7 @@ ObActionsList* actions_parser_read_file(ObActionsParser *p, g_scanner_input_file(p->scan, g_io_channel_unix_get_fd(ch)); p->scan->input_name = file; + e = FALSE; return parse_list(p, G_TOKEN_EOF, &e); } @@ -126,9 +136,10 @@ ObActionsList* actions_parser_read_file(ObActionsParser *p, BNF for the language: TEST := KEY=VALUE | KEY -ACTION := [FILTER] ACTION ACTIONELSE | ACTIONNAME ACTIONOPTS | {ACTIONLIST} +ACTION := [FILTER] ACTION ELSE END | ACTIONNAME ACTIONOPTS | {ACTIONLIST} +ELSE := nil | \| ACTION +END := \n | ; | EOF ACTIONLIST := ACTION ACTIONLIST | ACTION -ACTIONELSE := nil | \| ACTION FILTER := FILTERORS FILTERORS := FILTERANDS \| FILTERORS | FILTERANDS FILTERANDS := TEST, FILTERANDS | TEST @@ -160,7 +171,10 @@ ObActionsList* parse_list(ObActionsParser *p, GTokenType end, gboolean *e) while (t != end && t != G_TOKEN_EOF) { if (t == '\n') g_scanner_get_next_token(p->scan); /* skip empty lines */ - else { + else if (t == ';') { + g_scanner_get_next_token(p->scan); /* separator */ + } + else if (t == G_TOKEN_IDENTIFIER) { ObActionsList *next; /* parse the next action and stick it on the end of the list */ @@ -168,9 +182,14 @@ ObActionsList* parse_list(ObActionsParser *p, GTokenType end, gboolean *e) if (last) last->next = next; if (!first) first = next; last = next; - - if (*e) break; /* don't parse any more after an error */ } + else { + g_scanner_get_next_token(p->scan); + parse_error(p, (end ? end : G_TOKEN_NONE), + _("Expected an action or end of action list"), e); + } + + if (*e) break; /* don't parse any more after an error */ t = g_scanner_peek_next_token(p->scan); } @@ -186,7 +205,7 @@ ObActionsList* parse_action(ObActionsParser *p, gboolean *e) GTokenType t; ObActionsList *al; gchar *name; - GList *keys, *values; + GHashTable *config; t = g_scanner_get_next_token(p->scan); @@ -199,44 +218,57 @@ ObActionsList* parse_action(ObActionsParser *p, gboolean *e) /* read the action's name */ name = g_strdup(p->scan->value.v_string); - keys = values = NULL; + config = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify)actions_value_unref); /* read the action's options key:value pairs */ t = g_scanner_peek_next_token(p->scan); - while (t == G_TOKEN_IDENTIFIER) { - gchar *key; - ObActionsListValue *value; - - g_scanner_get_next_token(p->scan); /* eat the key */ - t = g_scanner_peek_next_token(p->scan); /* check for ':' */ - if (t != ':') { - parse_error(p, ':', NULL, e); - break; /* don't read any more options */ + while (t == G_TOKEN_IDENTIFIER || t == '\\') { + if (t == '\\') { + g_scanner_get_next_token(p->scan); /* eat it */ + t = g_scanner_get_next_token(p->scan); /* check for '\n' */ + if (t != '\n') + parse_error(p, G_TOKEN_NONE, _("Expected newline"), e); } + else { + gchar *key; + ObActionsValue *value; + + g_scanner_get_next_token(p->scan); /* eat the key */ + t = g_scanner_peek_next_token(p->scan); /* check for ':' */ + if (t != ':') { + g_scanner_get_next_token(p->scan); + parse_error(p, ':', NULL, e); + break; /* don't read any more options */ + } - /* save the key */ - key = g_strdup(p->scan->value.v_string); - g_scanner_get_next_token(p->scan); /* eat the ':' */ + /* save the key */ + key = g_strdup(p->scan->value.v_string); + g_scanner_get_next_token(p->scan); /* eat the ':' */ - /* read the value */ - value = parse_value(p, TRUE, e); + /* read the value */ + value = parse_value(p, TRUE, e); - /* check if we read a value (regardless of errors), and save - the key:value pair if we did. */ - if (value) { - keys = g_list_prepend(keys, key); - values = g_list_prepend(values, value); + /* check if we read a value (regardless of errors), and save + the key:value pair if we did. */ + if (value) + g_hash_table_replace(config, key, value); + else + g_free(key); /* didn't read any value */ } - else - g_free(key); /* didn't read any value */ if (*e) break; /* don't parse any more if there was an error */ + + t = g_scanner_peek_next_token(p->scan); } al = g_slice_new(ObActionsList); al->ref = 1; al->isfilter = FALSE; - al->u.action = actions_act_new(name, keys, values); + al->u.action = actions_act_new(name, config); + al->next = NULL; + g_free(name); + g_hash_table_unref(config); return al; } @@ -274,6 +306,7 @@ ObActionsList* parse_filter(ObActionsParser *p, gboolean *e) al->u.f.test = test; al->u.f.thendo = thendo; al->u.f.elsedo = elsedo; + al->next = NULL; return al; } @@ -281,7 +314,7 @@ ObActionsListTest* parse_filter_test(ObActionsParser *p, gboolean *e) { GTokenType t; gchar *key; - ObActionsListValue *value; + ObActionsValue *value; gboolean and; ObActionsListTest *next; @@ -309,31 +342,29 @@ ObActionsListTest* parse_filter_test(ObActionsParser *p, gboolean *e) /* don't allow any errors (but value can be null if not present) */ if (*e) { g_free(key); - actions_list_value_unref(value); + actions_value_unref(value); return NULL; } /* check if there is another test and how we're connected */ t = g_scanner_get_next_token(p->scan); - switch (t) { - case ',': /* and */ + if (t == ',') { /* and */ and = TRUE; next = parse_filter_test(p, e); - break; - case '|': /* or */ + } + else if (t == '|') { /* or */ and = FALSE; next = parse_filter_test(p, e); - break; - case ']': /* end of the filter */ - break; - default: - parse_error(p, ']', NULL, e); } + else if (t == ']') /* end of the filter */ + ; + else + parse_error(p, ']', NULL, e); /* don't allow any errors */ if (*e) { g_free(key); - actions_list_value_unref(value); + actions_value_unref(value); actions_list_test_destroy(next); return NULL; } @@ -349,26 +380,25 @@ ObActionsListTest* parse_filter_test(ObActionsParser *p, gboolean *e) } } -ObActionsListValue* parse_value(ObActionsParser *p, +ObActionsValue* parse_value(ObActionsParser *p, gboolean allow_actions, gboolean *e) { GTokenType t; - ObActionsListValue *v; + ObActionsValue *v; v = NULL; t = g_scanner_get_next_token(p->scan); - if (t == G_TOKEN_IDENTIFIER) - v = actions_list_value_new_string(p->scan->value.v_string); - else if (t == G_TOKEN_INT) - v = actions_list_value_new_int(p->scan->value.v_int); + if (t == G_TOKEN_IDENTIFIER) { + v = actions_value_new_string(p->scan->value.v_string); + } else if (t == '"') - v = actions_list_value_new_string(parse_string(p, '"', e)); + v = actions_value_new_string(parse_string(p, '"', e)); else if (t == '(') - v = actions_list_value_new_string(parse_string(p, ')', e)); + v = actions_value_new_string(parse_string(p, ')', e)); else if (t == '{' && allow_actions) { ObActionsList *l = parse_list(p, '}', e); - if (l) v = actions_list_value_new_actions_list(l); + if (l) v = actions_value_new_actions_list(l); } else parse_error(p, G_TOKEN_NONE, _("Expected an option value"), e); @@ -391,27 +421,22 @@ gchar* parse_string(ObActionsParser *p, guchar end, gboolean *e) t = g_scanner_get_next_token(p->scan); while (t != end) { - switch (t) { - case G_TOKEN_IDENTIFIER: + if (t == G_TOKEN_IDENTIFIER) g_string_append(buf, p->scan->value.v_string); - break; - case G_TOKEN_EOF: + else if (t == G_TOKEN_EOF) { error_message = _("Missing end of quoted string"); goto parse_string_error; - case G_TOKEN_NONE: - error_message = _("Unknown token in quoted string"); - goto parse_string_error; - case '\\': /* escape sequence */ + } + else if (t == '\\') { /* escape sequence */ t = g_scanner_get_next_token(p->scan); if (!strchr(ESCAPE_SEQS, t)) { error_message = _("Unknown escape sequence"); goto parse_string_error; } g_string_append_c(buf, t); - break; - default: /* other single character */ - g_string_append_c(buf, t); } + else /* other single character */ + g_string_append_c(buf, t); t = g_scanner_get_next_token(p->scan); } diff --git a/openbox/actions_parser.h b/openbox/actions_parser.h index 5d26a293..44a19723 100644 --- a/openbox/actions_parser.h +++ b/openbox/actions_parser.h @@ -16,10 +16,10 @@ See the COPYING file for a copy of the GNU General Public License. */ -#include "actions_list.h" - #include +struct _ObActionsList; + typedef struct _ObActionsParser ObActionsParser; ObActionsParser* actions_parser_new(void); @@ -27,8 +27,8 @@ ObActionsParser* actions_parser_new(void); void actions_parser_ref(ObActionsParser *p); void actions_parser_unref(ObActionsParser *p); -ObActionsList* actions_parser_read_string(ObActionsParser *p, - const gchar *text); -ObActionsList* actions_parser_read_file(ObActionsParser *p, - const gchar *file, - GError **error); +struct _ObActionsList* actions_parser_read_string(ObActionsParser *p, + const gchar *text); +struct _ObActionsList* actions_parser_read_file(ObActionsParser *p, + const gchar *file, + GError **error); diff --git a/openbox/actions_value.c b/openbox/actions_value.c new file mode 100644 index 00000000..5603adef --- /dev/null +++ b/openbox/actions_value.c @@ -0,0 +1,166 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + actions_value.c for the Openbox window manager + Copyright (c) 2011 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 "actions_value.h" +#include "actions_list.h" +#include "geom.h" + +#include "stdlib.h" + +struct _ObActionsValue { + gint ref; + enum { + OB_AV_STRING, + OB_AV_ACTIONSLIST + } type; + union { + gchar *string; + gboolean boolean; + guint integer; + ObActionsList *actions; + } v; +}; + +ObActionsValue* actions_value_new_string(const gchar *s) +{ + return actions_value_new_string_steal(g_strdup(s)); +} + +ObActionsValue* actions_value_new_string_steal(gchar *s) +{ + ObActionsValue *v = g_slice_new(ObActionsValue); + v->ref = 1; + v->type = OB_AV_STRING; + v->v.string = s; + return v; +} + +ObActionsValue* actions_value_new_actions_list(ObActionsList *al) +{ + ObActionsValue *v = g_slice_new(ObActionsValue); + v->ref = 1; + v->type = OB_AV_ACTIONSLIST; + v->v.actions = al; + actions_list_ref(al); + return v; +} + +void actions_value_ref(ObActionsValue *v) +{ + ++v->ref; +} + +void actions_value_unref(ObActionsValue *v) +{ + if (v && --v->ref < 1) { + switch (v->type) { + case OB_AV_STRING: + g_free(v->v.string); + break; + case OB_AV_ACTIONSLIST: + actions_list_unref(v->v.actions); + break; + } + g_slice_free(ObActionsValue, v); + } +} + +gboolean actions_value_is_string(ObActionsValue *v) +{ + return v->type == OB_AV_STRING; +} + +gboolean actions_value_is_actions_list(ObActionsValue *v) +{ + return v->type == OB_AV_ACTIONSLIST; +} + +const gchar* actions_value_string(ObActionsValue *v) +{ + g_return_val_if_fail(v->type == OB_AV_STRING, NULL); + return v->v.string; +} + +gboolean actions_value_bool(ObActionsValue *v) +{ + g_return_val_if_fail(v->type == OB_AV_STRING, FALSE); + if (g_strcasecmp(v->v.string, "true") == 0 || + g_strcasecmp(v->v.string, "yes") == 0) + return TRUE; + else + return FALSE; +} + +gint actions_value_int(ObActionsValue *v) +{ + gchar *s; + + g_return_val_if_fail(v->type == OB_AV_STRING, 0); + s = v->v.string; + return strtol(s, &s, 10); +} + +void actions_value_fraction(ObActionsValue *v, gint *numer, gint *denom) +{ + gchar *s; + + *numer = *denom = 0; + + g_return_if_fail(v->type == OB_AV_STRING); + s = v->v.string; + + *numer = strtol(s, &s, 10); + if (*s == '%') + *denom = 100; + else if (*s == '/') + *denom = atoi(s+1); +} + +void actions_value_gravity_coord(ObActionsValue *v, GravityCoord *c) +{ + gchar *s; + + c->center = FALSE; + c->pos = 0; + c->denom = 0; + + g_return_if_fail(v->type == OB_AV_STRING); + s = v->v.string; + + if (!g_ascii_strcasecmp(s, "center")) + c->center = TRUE; + else { + if (s[0] == '-') + c->opposite = TRUE; + if (s[0] == '-' || s[0] == '+') + ++s; + + c->pos = strtol(s, &s, 10); + + if (*s == '%') + c->denom = 100; + else if (*s == '/') + c->denom = atoi(s+1); + } +} + +ObActionsList* actions_value_actions_list(ObActionsValue *v) +{ + g_return_val_if_fail(v->type == OB_AV_ACTIONSLIST, NULL); + return v->v.actions; +} diff --git a/openbox/actions_value.h b/openbox/actions_value.h new file mode 100644 index 00000000..681a00cc --- /dev/null +++ b/openbox/actions_value.h @@ -0,0 +1,45 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + actions_value.h for the Openbox window manager + Copyright (c) 2011 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 + +struct _GravityCoord; +struct _ObActionsList; + +typedef struct _ObActionsValue ObActionsValue; + +/*! Creates a new value by making a copy of the given string. */ +ObActionsValue* actions_value_new_string(const gchar *s); +/*! Creates a new value from a string, and steals ownership of the string. It + will be freed when then value is destroyed. */ +ObActionsValue* actions_value_new_string_steal(gchar *s); +/*! Creates a new value with a given actions list. */ +ObActionsValue* actions_value_new_actions_list(struct _ObActionsList *al); + +void actions_value_ref(ObActionsValue *v); +void actions_value_unref(ObActionsValue *v); + +gboolean actions_value_is_string(ObActionsValue *v); +gboolean actions_value_is_actions_list(ObActionsValue *v); + +const gchar* actions_value_string(ObActionsValue *v); +gboolean actions_value_bool(ObActionsValue *v); +gint actions_value_int(ObActionsValue *v); +void actions_value_fraction(ObActionsValue *v, gint *numer, gint *denom); +void actions_value_gravity_coord(ObActionsValue *v, struct _GravityCoord *c); +struct _ObActionsList* actions_value_actions_list(ObActionsValue *v); diff --git a/openbox/config.c b/openbox/config.c index 0d9eb689..8fda459d 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -21,6 +21,8 @@ #include "keyboard.h" #include "mouse.h" #include "actions.h" +#include "actions_list.h" +#include "actions_parser.h" #include "translate.h" #include "client.h" #include "screen.h" @@ -420,11 +422,20 @@ static void parse_key(xmlNodePtr node, GList *keylist) } else if ((n = obt_xml_find_node(node->children, "action"))) { while (n) { - ObActionsAct *action; + ObActionsParser *p; + ObActionsList *actions; + xmlChar *c; - action = actions_parse(n); - if (action) - keyboard_bind(keylist, action); + c = xmlNodeGetContent(node); + p = actions_parser_new(); + actions = actions_parser_read_string(p, (gchar*)c); + xmlFree(c); + actions_parser_unref(p); + + if (actions) + keyboard_bind(keylist, actions); + + actions_list_unref(actions); n = obt_xml_find_node(n->next, "action"); } } @@ -535,11 +546,18 @@ static void parse_mouse(xmlNodePtr node, gpointer d) nact = obt_xml_find_node(nbut->children, "action"); while (nact) { - ObActionsAct *action; - - if ((action = actions_parse(nact))) - mouse_bind(buttonstr, cx, mact, action); + ObActionsList *actions; + ObActionsParser *p; + xmlChar *c; + + c = xmlNodeGetContent(nact); + p = actions_parser_new(); + if ((actions = actions_parser_read_string(p, (gchar*)c))) + mouse_bind(buttonstr, cx, mact, actions); nact = obt_xml_find_node(nact->next, "action"); + actions_list_unref(actions); + xmlFree(c); + actions_parser_unref(p); } g_free(buttonstr); next_nbut: @@ -915,22 +933,31 @@ static void parse_resistance(xmlNodePtr node, gpointer d) typedef struct { const gchar *key; - const gchar *actname; + const gchar *actiontext; } ObDefKeyBind; static void bind_default_keyboard(void) { ObDefKeyBind *it; ObDefKeyBind binds[] = { + { "Left", + "Execute startupnotify:yes name:Konqueror \\\n" + " command:(kfmclient openProfile filemanagement)" }, { "A-Tab", "NextWindow" }, { "S-A-Tab", "PreviousWindow" }, { "A-F4", "Close" }, { NULL, NULL } }; + ObActionsParser *p; + + p = actions_parser_new(); for (it = binds; it->key; ++it) { GList *l = g_list_append(NULL, g_strdup(it->key)); - keyboard_bind(l, actions_parse_string(it->actname)); + ObActionsList *actions = actions_parser_read_string(p, it->actiontext); + keyboard_bind(l, actions); + actions_list_unref(actions); } + actions_parser_unref(p); } typedef struct @@ -994,10 +1021,17 @@ static void bind_default_mouse(void) { "A-Middle", "Frame", OB_MOUSE_ACTION_MOTION, "Resize" }, { NULL, NULL, 0, NULL } }; + ObActionsParser *p; + ObActionsList *actions; - for (it = binds; it->button; ++it) + p = actions_parser_new(); + for (it = binds; it->button; ++it) { + actions = actions_parser_read_string(p, it->actname); mouse_bind(it->button, frame_context_from_string(it->context), - it->mact, actions_parse_string(it->actname)); + it->mact, actions); + actions_list_unref(actions); + } + actions_parser_unref(p); } void config_startup(ObtXmlInst *i) diff --git a/openbox/keyboard.c b/openbox/keyboard.c index 8f4424ea..25d3b310 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -25,6 +25,7 @@ #include "grab.h" #include "client.h" #include "actions.h" +#include "actions_list.h" #include "menuframe.h" #include "config.h" #include "keytree.h" @@ -139,13 +140,15 @@ void keyboard_chroot(GList *keylist) } } -gboolean keyboard_bind(GList *keylist, ObActionsAct *action) +gboolean keyboard_bind(GList *keylist, ObActionsList *actions) { KeyBindingTree *tree, *t; gboolean conflict; g_assert(keylist != NULL); - g_assert(action != NULL); + + if (!actions) + return TRUE; if (!(tree = tree_build(keylist))) return FALSE; @@ -167,7 +170,9 @@ gboolean keyboard_bind(GList *keylist, ObActionsAct *action) for (; t->first_child; t = t->first_child); /* set the action */ - t->actions = g_slist_append(t->actions, action); + actions_list_ref(actions); + t->actions = actions_list_concat(t->actions, actions); + /* assimilate this built tree into the main tree. assimilation destroys/uses the tree */ if (tree) tree_assimilate(tree); @@ -259,16 +264,14 @@ gboolean keyboard_event(ObClient *client, const XEvent *e) } else if (p->chroot) /* an empty chroot */ set_curpos(p); else { - GSList *it; + gboolean i; - for (it = p->actions; it; it = g_slist_next(it)) - if (actions_act_is_interactive(it->data)) break; - if (it == NULL) /* reset if the actions are not interactive */ + i = actions_run_acts(p->actions, OB_USER_ACTION_KEYBOARD_KEY, + e->xkey.state, + e->xkey.x_root, e->xkey.y_root, + 0, OB_FRAME_CONTEXT_NONE, client); + if (!i) /* reset if an interactive was not run */ keyboard_reset_chains(0); - - actions_run_acts(p->actions, OB_USER_ACTION_KEYBOARD_KEY, - e->xkey.state, e->xkey.x_root, e->xkey.y_root, - 0, OB_FRAME_CONTEXT_NONE, client); } break; used = TRUE; @@ -292,12 +295,7 @@ static void node_rebind(KeyBindingTree *node) } else { /* for leaf nodes, rebind each action assigned to it */ - while (node->actions) { - /* add each action, and remove them from the original tree so - they don't get free'd on us */ - keyboard_bind(node->keylist, node->actions->data); - node->actions = g_slist_delete_link(node->actions, node->actions); - } + keyboard_bind(node->keylist, node->actions); if (node->chroot) keyboard_chroot(node->keylist); diff --git a/openbox/keyboard.h b/openbox/keyboard.h index c89f67e9..07059a26 100644 --- a/openbox/keyboard.h +++ b/openbox/keyboard.h @@ -37,7 +37,7 @@ void keyboard_shutdown(gboolean reconfig); void keyboard_rebind(void); void keyboard_chroot(GList *keylist); -gboolean keyboard_bind(GList *keylist, struct _ObActionsAct *action); +gboolean keyboard_bind(GList *keylist, struct _ObActionsList *actions); void keyboard_unbind_all(void); gboolean keyboard_event(struct _ObClient *client, const XEvent *e); diff --git a/openbox/keytree.c b/openbox/keytree.c index 93a0c7aa..7b4b0f72 100644 --- a/openbox/keytree.c +++ b/openbox/keytree.c @@ -20,6 +20,7 @@ #include "keyboard.h" #include "translate.h" #include "actions.h" +#include "actions_list.h" #include void tree_destroy(KeyBindingTree *tree) @@ -31,13 +32,10 @@ void tree_destroy(KeyBindingTree *tree) c = tree->first_child; if (c == NULL) { GList *it; - GSList *sit; for (it = tree->keylist; it != NULL; it = it->next) g_free(it->data); g_list_free(tree->keylist); - for (sit = tree->actions; sit != NULL; sit = sit->next) - actions_act_unref(sit->data); - g_slist_free(tree->actions); + actions_list_unref(tree->actions); } g_slice_free(KeyBindingTree, tree); tree = c; diff --git a/openbox/keytree.h b/openbox/keytree.h index 66edc3c7..8504772f 100644 --- a/openbox/keytree.h +++ b/openbox/keytree.h @@ -21,11 +21,13 @@ #include +struct _ObActionsList; + typedef struct KeyBindingTree { guint state; guint key; GList *keylist; - GSList *actions; /* list of Action pointers */ + struct _ObActionsList *actions; gboolean chroot; /* the level up in the tree */ diff --git a/openbox/menu.c b/openbox/menu.c index 93b3879e..28ac4edb 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -25,6 +25,8 @@ #include "client.h" #include "config.h" #include "actions.h" +#include "actions_list.h" +#include "actions_parser.h" #include "screen.h" #include "menuframe.h" #include "keyboard.h" @@ -284,16 +286,24 @@ static void parse_menu_item(xmlNodePtr node, gpointer data) if (obt_xml_attr_string(node, "label", &label)) { xmlNodePtr c; - GSList *acts = NULL; + xmlChar *cc; + ObActionsList *acts = NULL; + ObActionsParser *p; c = obt_xml_find_node(node->children, "action"); + p = actions_parser_new(); while (c) { - ObActionsAct *action = actions_parse(c); - if (action) - acts = g_slist_append(acts, action); + ObActionsList *al; + + cc = xmlNodeGetContent(c); + al = actions_parser_read_string(p, (gchar*)cc); + xmlFree(cc); + acts = actions_list_concat(acts, al); + c = obt_xml_find_node(c->next, "action"); } e = menu_add_normal(state->parent, -1, label, acts, TRUE); + actions_list_unref(acts); if (config_menu_show_icons && obt_xml_attr_string(node, "icon", &icon)) @@ -548,12 +558,7 @@ void menu_entry_unref(ObMenuEntry *self) RrImageUnref(self->data.normal.icon); g_free(self->data.normal.label); g_free(self->data.normal.collate_key); - while (self->data.normal.actions) { - actions_act_unref(self->data.normal.actions->data); - self->data.normal.actions = - g_slist_delete_link(self->data.normal.actions, - self->data.normal.actions); - } + actions_list_unref(self->data.normal.actions); break; case OB_MENU_ENTRY_TYPE_SUBMENU: RrImageUnref(self->data.submenu.icon); @@ -597,12 +602,13 @@ void menu_entry_remove(ObMenuEntry *self) } ObMenuEntry* menu_add_normal(ObMenu *self, gint id, const gchar *label, - GSList *actions, gboolean allow_shortcut) + ObActionsList *actions, gboolean allow_shortcut) { ObMenuEntry *e; e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_NORMAL, id); e->data.normal.actions = actions; + actions_list_ref(actions); menu_entry_set_label(e, label, allow_shortcut); diff --git a/openbox/menu.h b/openbox/menu.h index 7d719729..c20addb1 100644 --- a/openbox/menu.h +++ b/openbox/menu.h @@ -25,6 +25,7 @@ #include +struct _ObActionsList; struct _ObClient; struct _ObMenuFrame; struct _ObMenuEntryFrame; @@ -120,8 +121,7 @@ struct _ObNormalMenuEntry { /* state */ gboolean enabled; - /* List of ObActions */ - GSList *actions; + struct _ObActionsList *actions; /* Mask icon */ RrPixmapMask *mask; @@ -209,7 +209,8 @@ void menu_set_place_func(ObMenu *menu, ObMenuPlaceFunc func); /*! @param allow_shortcut this should be false when the label is coming from outside data like window or desktop titles */ ObMenuEntry* menu_add_normal(ObMenu *menu, gint id, const gchar *label, - GSList *actions, gboolean allow_shortcut); + struct _ObActionsList *actions, + gboolean allow_shortcut); ObMenuEntry* menu_add_submenu(ObMenu *menu, gint id, const gchar *submenu); ObMenuEntry* menu_add_separator(ObMenu *menu, gint id, const gchar *label); diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 4887173b..ab3f3b9f 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -22,6 +22,7 @@ #include "menu.h" #include "screen.h" #include "actions.h" +#include "actions_list.h" #include "event.h" #include "grab.h" #include "openbox.h" @@ -1289,7 +1290,7 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self, guint state) ObMenuEntry *entry = self->entry; ObMenuExecuteFunc func = self->frame->menu->execute_func; gpointer data = self->frame->menu->data; - GSList *acts = self->entry->data.normal.actions; + ObActionsList *acts = self->entry->data.normal.actions; ObClient *client = self->frame->client; ObMenuFrame *frame = self->frame; guint mods = obt_keyboard_only_modmasks(state); diff --git a/openbox/mouse.c b/openbox/mouse.c index 2f0c8f59..74b8b760 100644 --- a/openbox/mouse.c +++ b/openbox/mouse.c @@ -20,6 +20,7 @@ #include "openbox.h" #include "config.h" #include "actions.h" +#include "actions_list.h" #include "event.h" #include "client.h" #include "grab.h" @@ -34,7 +35,7 @@ typedef struct { guint state; guint button; - GSList *actions[OB_NUM_MOUSE_ACTIONS]; /* lists of Action pointers */ + ObActionsList *actions[OB_NUM_MOUSE_ACTIONS]; } ObMouseBinding; /* Array of GSList*s of ObMouseBinding*s. */ @@ -149,13 +150,8 @@ void mouse_unbind_all(void) ObMouseBinding *b = it->data; gint j; - for (j = 0; j < OB_NUM_MOUSE_ACTIONS; ++j) { - GSList *jt; - - for (jt = b->actions[j]; jt; jt = g_slist_next(jt)) - actions_act_unref(jt->data); - g_slist_free(b->actions[j]); - } + for (j = 0; j < OB_NUM_MOUSE_ACTIONS; ++j) + actions_list_unref(b->actions[j]); g_slice_free(ObMouseBinding, b); } g_slist_free(bound_contexts[i]); @@ -370,7 +366,7 @@ gboolean mouse_event(ObClient *client, XEvent *e) } gboolean mouse_bind(const gchar *buttonstr, ObFrameContext context, - ObMouseAction mact, ObActionsAct *action) + ObMouseAction mact, ObActionsList *actions) { guint state, button; ObMouseBinding *b; @@ -386,7 +382,8 @@ gboolean mouse_bind(const gchar *buttonstr, ObFrameContext context, for (it = bound_contexts[context]; it; it = g_slist_next(it)) { b = it->data; if (b->state == state && b->button == button) { - b->actions[mact] = g_slist_append(b->actions[mact], action); + actions_list_ref(actions); + b->actions[mact] = actions_list_concat(b->actions[mact], actions); return TRUE; } } @@ -395,7 +392,8 @@ gboolean mouse_bind(const gchar *buttonstr, ObFrameContext context, b = g_slice_new0(ObMouseBinding); b->state = state; b->button = button; - b->actions[mact] = g_slist_append(NULL, action); + b->actions[mact] = actions; + actions_list_ref(actions); bound_contexts[context] = g_slist_append(bound_contexts[context], b); return TRUE; diff --git a/openbox/mouse.h b/openbox/mouse.h index de4c0eca..b683cdf0 100644 --- a/openbox/mouse.h +++ b/openbox/mouse.h @@ -24,13 +24,13 @@ #include -struct _ObActionsAct; +struct _ObActionsList; void mouse_startup(gboolean reconfig); void mouse_shutdown(gboolean reconfig); gboolean mouse_bind(const gchar *buttonstr, ObFrameContext context, - ObMouseAction mact, struct _ObActionsAct *action); + ObMouseAction mact, struct _ObActionsList *actions); void mouse_unbind_all(void); gboolean mouse_event(struct _ObClient *client, XEvent *e); diff --git a/openbox/openbox.c b/openbox/openbox.c index fbc01fdd..fdf1c023 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -243,7 +243,7 @@ gint main(gint argc, gchar **argv) /* parse/load user options */ if ((config_file && obt_xml_load_file(i, config_file, "openbox_config")) || - obt_xml_load_config_file(i, "openbox", "rc.xml", + obt_xml_load_config_file(i, "openbox", "rc", "openbox_config")) { obt_xml_tree_from_root(i); -- 2.34.1