#endif
#ifdef NEED_MOTIF
#include "lwlib-Xm.h"
+#ifdef LWLIB_WIDGETS_MOTIF
+#include <Xm/Xm.h>
+#endif
#endif
#ifdef NEED_ATHENA
#include "lwlib-Xaw.h"
\f
/* Forward declarations */
-static void
-instantiate_widget_instance (widget_instance *instance);
+static void instantiate_widget_instance (widget_instance *instance);
+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;
}
if (wv)
{
- memset (wv, 0, sizeof (widget_value));
+ memset (wv, '\0', sizeof (widget_value));
}
return wv;
}
free_widget_value_tree (wv->contents);
wv->contents = (widget_value *) 0xDEADBEEF;
}
- if (wv->args && wv->nargs)
- {
- if (wv->free_args)
- free (wv->args);
- wv->args = (ArgList) 0xDEADBEEF;
- wv->nargs = 0;
- wv->free_args = 0;
- }
+
+ free_widget_value_args (wv);
+
if (wv->next)
{
free_widget_value_tree (wv->next);
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));
}
/*
#endif /* NEED_SCROLLBARS */
+#ifdef HAVE_WIDGETS
+/*
+ * Return true if old->args was not equivalent
+ * to new->args.
+ */
+static Boolean
+merge_widget_value_args (widget_value *old, widget_value *new)
+{
+ Boolean changed = False;
+
+ if (new->args && !old->args)
+ {
+ lw_copy_widget_value_args (new, old);
+ changed = True;
+ }
+ /* Generally we don't want to lose values that are already in the
+ widget. */
+ else if (!new->args && old->args)
+ {
+ lw_copy_widget_value_args (old, new);
+ changed = True;
+ }
+ 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). */
+ 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;
+}
+#endif /* HAVE_WIDGETS */
+
/* 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;
copy->next = copy_widget_value_tree (val->next, change);
copy->toolkit_data = NULL;
copy->free_toolkit_data = False;
- if (val->nargs)
- {
- copy->args = (ArgList)malloc (sizeof (Arg) * val->nargs);
- memcpy (copy->args, val->args, sizeof(Arg) * val->nargs);
- copy->nargs = val->nargs;
- copy->free_args = True;
- }
+
+ lw_copy_widget_value_args (val, copy);
#ifdef NEED_SCROLLBARS
copy_scrollbar_values (val, copy);
#endif
}
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)
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);
}
static void
free_widget_instance (widget_instance *instance)
{
- memset ((void *) instance, 0xDEADBEEF, sizeof (widget_instance));
+ memset (instance, '\0', sizeof (widget_instance));
free (instance);
}
\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)
{
change = max (change, INVISIBLE_CHANGE);
val1->call_data = val2->call_data;
}
+#ifdef HAVE_WIDGETS
+ if (merge_widget_value_args (val1, val2))
+ {
+ EXPLAIN (val1->name, change, VISIBLE_CHANGE, "widget change", 0, 0);
+ change = max (change, VISIBLE_CHANGE);
+ }
+#endif
+
#ifdef NEED_SCROLLBARS
if (merge_scrollbar_values (val1, val2))
{
\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;
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
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] */
}
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)
}
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)
}
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;
void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset)
{
int i;
- if (wv->nargs && wv->args)
+ if (wv->args && wv->args->nargs)
+ {
+ for (i = 0; i<wv->args->nargs; i++)
+ {
+ addto[i + *offset] = wv->args->args[i];
+ }
+ *offset += wv->args->nargs;
+ }
+}
+
+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));
+ 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);
+ }
+
+ if (wv->args->nargs > 10)
+ return;
+
+ /* 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)
+{
+ if (wv->args)
{
- for (i = 0; i<wv->nargs; i++)
+ if (--wv->args->ref_count <= 0)
{
- addto[i + *offset] = wv->args[i];
+#ifdef LWLIB_WIDGETS_MOTIF
+ int i;
+ for (i = 0; i < wv->args->nargs; i++)
+ {
+ if (!strcmp (wv->args->args[i].name, XmNfontList))
+ XmFontListFree ((XmFontList)wv->args->args[i].value);
+ }
+#endif
+ free (wv->args->args);
+ free (wv->args);
+ wv->args = 0;
}
- *offset += wv->nargs;
}
}
+void lw_copy_widget_value_args (widget_value* val, widget_value* copy)
+{
+ if (val == copy || val->args == copy->args)
+ return;
+
+ if (copy->args)
+ {
+ free_widget_value_args (copy);
+ }
+
+ 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';
+}