[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