Hi, this version fixes the mistake in hid.h about void return value and contains the internals for registering/deregistering single actions.
Regards, Tibor Palinkas -- .O. ..O OOO
diff -uri pcb.orig/src/hid/common/actions.c pcb/src/hid/common/actions.c --- pcb.orig/src/hid/common/actions.c 2008-01-05 06:37:08.000000000 +0100 +++ pcb/src/hid/common/actions.c 2009-03-24 05:31:29.000000000 +0100 @@ -8,6 +8,7 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> +#include <assert.h> #include "global.h" #include "data.h" @@ -26,14 +27,27 @@ struct HID_ActionNode *next; HID_Action *actions; int n; + /* The registrar the callback function may use this pointer to remember + context; the action infrastructure will just pass it along. */ + void *context; + /* is this ActionNode registered runtime? (can be deregistered) */ + int dynamic; } HID_ActionNode; -HID_ActionNode *hid_action_nodes = 0; +/* The master list of all actions registered */ +typedef struct HID_ActionContext { + HID_Action action; + void *context; +} HID_ActionContext; static int n_actions = 0; -static HID_Action *all_actions = 0; +static HID_ActionContext *all_actions = NULL; -void -hid_register_actions (HID_Action * a, int n) +HID_ActionNode *hid_action_nodes = NULL; + +void *hid_action_context = NULL; + +static void +hid_register_actions_context (HID_Action * a, int n, void *context, int dynamic) { HID_ActionNode *ha; @@ -41,26 +55,87 @@ ha = (HID_ActionNode *) malloc (sizeof (HID_ActionNode)); ha->next = hid_action_nodes; hid_action_nodes = ha; - ha->actions = a; + if (dynamic) { + assert(n == 1); /* we register dynamic actions one by one */ + ha->actions = malloc(sizeof(HID_Action)); + memcpy(ha->actions, a, sizeof(HID_Action)); + } + else + ha->actions = a; + ha->n = n; + ha->context = context; + ha->dynamic = dynamic; n_actions += n; if (all_actions) { free (all_actions); - all_actions = 0; + all_actions = NULL; } } +void +hid_register_actions (HID_Action * a, int n) +{ + hid_register_actions_context (a, n, NULL, 0); +} + +void +hid_register_action (const HID_Action * a, void *context) +{ + hid_register_actions_context (a, 1, context, 1); +} + +void +hid_deregister_action (const char *name, void **context) +{ + HID_ActionNode *prev, *ha; + + if (context != NULL) + *context = NULL; + + /* find the action in hid_action_nodes */ + for(prev = NULL, ha = hid_action_nodes; ha != NULL; prev = ha, ha = ha->next) { + if (ha->dynamic) { + if (strcmp(ha->actions->name, name) == 0) { + /* found the action in the tree, save context */ + if (context != NULL) + *context = ha->context; + + /* remove ha */ + if (prev == NULL) + hid_action_nodes = ha->next; + else + prev->next = ha->next; + + free(ha->actions); + free(ha); + + /* to make sure the rebuild of the sorted list next time */ + if (all_actions != NULL) { + free (all_actions); + all_actions = NULL; + } + + n_actions--; + return; + } + } + } + + /* action not found - nothing to do */ +} + static int action_sort (const void *va, const void *vb) { - HID_Action *a = (HID_Action *) va; - HID_Action *b = (HID_Action *) vb; - return strcmp (a->name, b->name); + HID_ActionContext *a = (HID_ActionContext *) va; + HID_ActionContext *b = (HID_ActionContext *) vb; + return strcmp (a->action.name, b->action.name); } HID_Action * -hid_find_action (const char *name) +hid_find_action (const char *name, void **context) { HID_ActionNode *ha; int i, n, lower, upper; @@ -68,14 +143,17 @@ if (name == NULL) return 0; - if (all_actions == 0) + if (all_actions == NULL) { n = 0; - all_actions = malloc (n_actions * sizeof (HID_Action)); + all_actions = malloc (n_actions * sizeof (HID_ActionContext)); for (ha = hid_action_nodes; ha; ha = ha->next) - for (i = 0; i < ha->n; i++) - all_actions[n++] = ha->actions[i]; - qsort (all_actions, n_actions, sizeof (HID_Action), action_sort); + for (i = 0; i < ha->n; i++) { + all_actions[n].action = ha->actions[i]; + all_actions[n].context = ha->context; + n++; + } + qsort (all_actions, n_actions, sizeof (HID_ActionContext), action_sort); } @@ -85,10 +163,13 @@ while (lower < upper - 1) { i = (lower + upper) / 2; - n = strcmp (all_actions[i].name, name); + n = strcmp (all_actions[i].action.name, name); /*printf("try [%d].%s, cmp %d\n", i, all_actions[i].name, n); */ - if (n == 0) - return all_actions + i; + if (n == 0) { + if (context != NULL) + *context = all_actions[i].context; + return &(all_actions[i].action); + } if (n > 0) upper = i; else @@ -96,8 +177,11 @@ } for (i = 0; i < n_actions; i++) - if (strcasecmp (all_actions[i].name, name) == 0) - return all_actions + i; + if (strcasecmp (all_actions[i].action.name, name) == 0) { + if (*context != NULL) + *context = all_actions[i].context; + return &(all_actions[i].action); + } printf ("unknown action `%s'\n", name); return 0; @@ -108,19 +192,19 @@ { int i; /* Forces them to be sorted in all_actions */ - hid_find_action (hid_action_nodes->actions[0].name); + hid_find_action (hid_action_nodes->actions[0].name, NULL); fprintf (stderr, "Registered Actions:\n"); for (i = 0; i < n_actions; i++) { - if (all_actions[i].description) - fprintf (stderr, " %s - %s\n", all_actions[i].name, - all_actions[i].description); + if (all_actions[i].action.description) + fprintf (stderr, " %s - %s\n", all_actions[i].action.name, + all_actions[i].action.description); else - fprintf (stderr, " %s\n", all_actions[i].name); - if (all_actions[i].syntax) + fprintf (stderr, " %s\n", all_actions[i].action.name); + if (all_actions[i].action.syntax) { const char *bb, *eb; - bb = eb = all_actions[i].syntax; + bb = eb = all_actions[i].action.syntax; while (1) { for (eb = bb; *eb && *eb != '\n'; eb++) @@ -161,16 +245,16 @@ { int i; /* Forces them to be sorted in all_actions */ - hid_find_action (hid_action_nodes->actions[0].name); + hid_find_action (hid_action_nodes->actions[0].name, NULL); for (i = 0; i < n_actions; i++) { - const char *desc = all_actions[i].description; - const char *synt = all_actions[i].syntax; + const char *desc = all_actions[i].action.description; + const char *synt = all_actions[i].action.syntax; desc = desc ? desc : ""; synt = synt ? synt : ""; - printf ("A%s\n", all_actions[i].name); + printf ("A%s\n", all_actions[i].action.name); dump_string ('D', desc); dump_string ('S', synt); } @@ -200,8 +284,10 @@ int hid_actionv (const char *name, int argc, char **argv) { - int x = 0, y = 0, i; + int x = 0, y = 0, i, ret; HID_Action *a; + void *old_context; + void *context; if (Settings.verbose && name) { @@ -211,12 +297,21 @@ printf (")\033[0m\n"); } - a = hid_find_action (name); + a = hid_find_action (name, &context); if (!a) return 1; if (a->need_coord_msg) gui->get_coords (a->need_coord_msg, &x, &y); - return a->trigger_cb (argc, argv, x, y); + + /* save old action context and set it to the context associated with the action */ + old_context = hid_action_context; + hid_action_context = context; + + ret = a->trigger_cb (argc, argv, x, y); + + /* restore old context and return */ + hid_action_context = old_context; + return ret; } int diff -uri pcb.orig/src/hid/hidint.h pcb/src/hid/hidint.h --- pcb.orig/src/hid/hidint.h 2006-09-20 06:26:32.000000000 +0200 +++ pcb/src/hid/hidint.h 2009-03-19 09:02:17.000000000 +0100 @@ -35,7 +35,7 @@ extern HID_AttrNode *hid_attr_nodes; -HID_Action *hid_find_action (const char *name); +HID_Action *hid_find_action (const char *name, void **context); HID_Flag *hid_find_flag (const char *name); diff -uri pcb.orig/src/hid/lesstif/menu.c pcb/src/hid/lesstif/menu.c --- pcb.orig/src/hid/lesstif/menu.c 2008-12-21 05:15:39.000000000 +0100 +++ pcb/src/hid/lesstif/menu.c 2009-03-19 18:47:38.000000000 +0100 @@ -818,7 +818,7 @@ if (!aname) return 1; - a = hid_find_action (aname); + a = hid_find_action (aname, NULL); if (!a) { int i; diff -uri pcb.orig/src/hid.h pcb/src/hid.h --- pcb.orig/src/hid.h 2009-02-21 18:51:54.000000000 +0100 +++ pcb/src/hid.h 2009-03-24 05:31:17.000000000 +0100 @@ -86,7 +86,25 @@ const char *syntax; } HID_Action; + /* This global variable is always set to the action context, + before an action callback is called. Action context can + be specified when registering an action with hid_register_action() + Intended for plugins with hub action callbacks. */ + extern void *hid_action_context; + + /* Register a singe action associated with an action context. Makes + a copy of HID_Action. + Intended for plugins to register actions with a hub callback. */ + extern void hid_register_action(const HID_Action *, void *); + + /* Deregister an action registered using hid_register_action(). + Action context pointer is copied in the 2nd argument if it's not NULL. + Intended for plugins to deregister custom actions. */ + extern void hid_deregister_action(const char *, void **); + + /* Register a list of static actions without action context */ extern void hid_register_actions (HID_Action *, int); + #define REGISTER_ACTIONS(a) HIDCONCAT(void register_,a) ()\ { hid_register_actions(a, sizeof(a)/sizeof(a[0])); }
_______________________________________________ geda-user mailing list geda-user@moria.seul.org http://www.seul.org/cgi-bin/mailman/listinfo/geda-user