(A-IWDSU+271C4): New abstract node.
[chise/xemacs-chise.git.1] / lwlib / lwlib.c
index f55f092..f9c90f5 100644 (file)
@@ -76,7 +76,7 @@ static void free_widget_value_args (widget_value* wv);
 \f
 /* utility functions for widget_instance and widget_info */
 static char *
-safe_strdup (CONST char *s)
+safe_strdup (const char *s)
 {
   char *result;
   if (! s) return 0;
@@ -111,7 +111,7 @@ malloc_widget_value (void)
     }
   if (wv)
     {
-      memset (wv, 0, sizeof (widget_value));
+      memset (wv, '\0', sizeof (widget_value));
     }
   return wv;
 }
@@ -188,7 +188,7 @@ copy_scrollbar_values (widget_value *val, widget_value *copy)
   if (val->scrollbar_data)
     *copy->scrollbar_data = *val->scrollbar_data;
   else
-    memset (copy->scrollbar_data, 0, sizeof (scrollbar_values));
+    memset (copy->scrollbar_data, '\0', sizeof (scrollbar_values));
 }
 
 /*
@@ -257,14 +257,17 @@ merge_widget_value_args (widget_value *old, widget_value *new)
       lw_copy_widget_value_args (old, new);
       changed = True;
     }
-  else if (new->args && old->args)
+  else if (new->args && old->args && new->args != old->args)
     {
       /* #### Do something more sensible here than just copying the
          new values (like actually merging the values). */
-      free_widget_value_args (old);
       lw_copy_widget_value_args (new, old);
       changed = True;
     }
+  else if (new->args && new->args == old->args && new->args->args_changed == True)
+    {
+      changed = True;
+    }
 
   return changed;
 }
@@ -273,7 +276,7 @@ merge_widget_value_args (widget_value *old, widget_value *new)
 /* Make a complete copy of a widget_value tree.  Store CHANGE into
    the widget_value tree's `change' field. */
 
-static widget_value *
+widget_value *
 copy_widget_value_tree (widget_value *val, change_type change)
 {
   widget_value *copy;
@@ -330,7 +333,7 @@ replace_widget_value_tree (widget_value *node, widget_value *newtree)
 }
 
 static widget_info *
-allocate_widget_info (CONST char *type, CONST char *name,
+allocate_widget_info (const char *type, const char *name,
                       LWLIB_ID id, widget_value *val,
                      lw_callback pre_activate_cb, lw_callback selection_cb,
                      lw_callback post_activate_cb)
@@ -358,7 +361,7 @@ free_widget_info (widget_info *info)
   safe_free_str (info->type);
   safe_free_str (info->name);
   free_widget_value_tree (info->val);
-  memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
+  memset (info, '\0', sizeof (widget_info));
   free (info);
 }
 
@@ -393,7 +396,7 @@ allocate_widget_instance (widget_info *info, Widget parent, Boolean pop_up_p)
 static void
 free_widget_instance (widget_instance *instance)
 {
-  memset ((void *) instance, 0xDEADBEEF, sizeof (widget_instance));
+  memset (instance, '\0', sizeof (widget_instance));
   free (instance);
 }
 
@@ -503,13 +506,13 @@ find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
 \f
 /* utility function for widget_value */
 static Boolean
-safe_strcmp (CONST char *s1, CONST char *s2)
+safe_strcmp (const char *s1, const char *s2)
 {
   if (!!s1 ^ !!s2) return True;
   return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
 }
 
-#ifndef WINDOWSNT
+#ifndef WIN32_NATIVE
 static change_type
 max (change_type i1, change_type i2)
 {
@@ -690,7 +693,7 @@ merge_widget_value (widget_value *val1, widget_value *val2, int level)
 \f
 /* modifying the widgets */
 static Widget
-name_to_widget (widget_instance *instance, CONST char *name)
+name_to_widget (widget_instance *instance, const char *name)
 {
   Widget widget = NULL;
 
@@ -757,7 +760,11 @@ update_all_widget_values (widget_info *info, Boolean deep_p)
     update_one_widget_instance (instance, deep_p);
 
   for (val = info->val; val; val = val->next)
-    val->change = NO_CHANGE;
+    {
+      val->change = NO_CHANGE;
+      if (val->args)
+       val->args->args_changed = False;
+    }
 }
 
 void
@@ -822,22 +829,41 @@ initialize_widget_instance (widget_instance *instance)
   update_one_widget_instance (instance, True);
 
   for (val = instance->info->val; val; val = val->next)
-    val->change = NO_CHANGE;
+    {
+      val->change = NO_CHANGE;
+      if (val->args)
+       val->args->args_changed = False;
+    }
 }
 
+/* strcasecmp() is not sufficiently portable or standard,
+   and it's easier just to write our own. */
+static int
+ascii_strcasecmp (const char *s1, const char *s2)
+{
+  while (1)
+    {
+      char c1 = *s1++;
+      char c2 = *s2++;
+      if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A';
+      if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A';
+      if (c1 != c2) return c1 - c2;
+      if (c1 == '\0') return 0;
+    }
+}
 
 static widget_creation_function
-find_in_table (CONST char *type, widget_creation_entry *table)
+find_in_table (const char *type, const widget_creation_entry table[])
 {
-  widget_creation_entry *cur;
+  const widget_creation_entry *cur;
   for (cur = table; cur->type; cur++)
-    if (!strcasecmp (type, cur->type))
+    if (!ascii_strcasecmp (type, cur->type))
       return cur->function;
   return NULL;
 }
 
 static Boolean
-dialog_spec_p (CONST char *name)
+dialog_spec_p (const char *name)
 {
   /* return True if name matches [EILPQeilpq][1-9][Bb] or
      [EILPQeilpq][1-9][Bb][Rr][1-9] */
@@ -921,7 +947,7 @@ instantiate_widget_instance (widget_instance *instance)
 }
 
 void
-lw_register_widget (CONST char *type, CONST char *name,
+lw_register_widget (const char *type, const char *name,
                     LWLIB_ID id, widget_value *val,
                    lw_callback pre_activate_cb, lw_callback selection_cb,
                    lw_callback post_activate_cb)
@@ -957,7 +983,7 @@ lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
 }
 
 Widget
-lw_create_widget (CONST char *type, CONST char *name,
+lw_create_widget (const char *type, const char *name,
                   LWLIB_ID id, widget_value *val,
                  Widget parent, Boolean pop_up_p, lw_callback pre_activate_cb,
                  lw_callback selection_cb, lw_callback post_activate_cb)
@@ -1049,14 +1075,14 @@ lw_destroy_all_widgets (LWLIB_ID id)
 }
 
 void
-lw_destroy_everything ()
+lw_destroy_everything (void)
 {
   while (all_widget_info)
     lw_destroy_all_widgets (all_widget_info->id);
 }
 
 void
-lw_destroy_all_pop_ups ()
+lw_destroy_all_pop_ups (void)
 {
   widget_info *info;
   widget_info *next;
@@ -1363,22 +1389,53 @@ void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset)
     }
 }
 
+XtArgVal lw_get_value_arg (widget_value* wv, String name)
+{
+  int i;
+  if (wv->args)
+    {
+      for (i = 0; i < wv->args->nargs; i++)
+       {
+         if (!strcmp (wv->args->args[i].name, name))
+           {
+             return wv->args->args[i].value;
+           }
+       }
+    }
+  return (XtArgVal)0;
+}
+
 void lw_add_widget_value_arg (widget_value* wv, String name, XtArgVal value)
 {
+  int i = 0;
   if (!wv->args)
     {
       wv->args = (widget_args *) malloc (sizeof (widget_args));
-      memset (wv->args, 0, sizeof (widget_args));
+      memset (wv->args, '\0', sizeof (widget_args));
       wv->args->ref_count = 1;
       wv->args->nargs = 0;
       wv->args->args = (ArgList) malloc (sizeof (Arg) * 10);
-      memset (wv->args->args, 0, sizeof (Arg) * 10);
+      memset (wv->args->args, '\0', sizeof (Arg) * 10);
     }
   
   if (wv->args->nargs > 10)
     return;
 
-  XtSetArg (wv->args->args [wv->args->nargs], name, value);   wv->args->nargs++;
+  /* Register the change. */
+  wv->args->args_changed = True;
+  /* If the arg is already there then we must replace it. */
+  for (i = 0; i < wv->args->nargs; i++)
+    {
+      if (!strcmp (wv->args->args[i].name, name))
+       {
+         XtSetArg (wv->args->args [i], name, value);
+         break;
+       }
+    }
+  if (i >= wv->args->nargs)
+    {
+      XtSetArg (wv->args->args [wv->args->nargs], name, value);   wv->args->nargs++;
+    }
 }
 
 static void free_widget_value_args (widget_value* wv)
@@ -1397,23 +1454,46 @@ static void free_widget_value_args (widget_value* wv)
 #endif
          free (wv->args->args);
          free (wv->args);
-         wv->args = (widget_args*)0xDEADBEEF;
+         wv->args = 0;
        }
     }
 }
 
 void lw_copy_widget_value_args (widget_value* val, widget_value* copy)
 {
-  if (!val->args)
+  if (val == copy || val->args == copy->args)
+    return;
+
+  if (copy->args)
     {
-      if (copy->args)
-       free_widget_value_args (copy);
-      copy->args = 0;
+      free_widget_value_args (copy);
     }
-  else
+
+  if (val->args)
     {
       copy->args = val->args;
       copy->args->ref_count++;
     }
 }
 
+/* Remove %_ and convert %% to %.  We can do this in-place because we
+   are always shortening, never lengthening, the string. */
+void
+lw_remove_accelerator_spec (char *val)
+{
+  char *foo = val, *bar = val;
+
+  while (*bar)
+    {
+      if (*bar == '%' && *(bar+1) == '_')
+       bar += 2;
+      else if (*bar == '%' && *(bar+1) == '%')
+       {
+         *foo++ = *bar++;
+         bar++;
+       }
+      else
+       *foo++ = *bar++;
+    }
+  *foo = '\0';
+}