[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: gEDA-user: [PCB] action context patch
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@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user