(ediff-verbose-p): This var is not a constant.
[emacs.git] / lwlib / lwlib.c
blobbd5d9adbf9dfe4db851b26630963de929681ef87
1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
3 Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007 Free Software Foundation, Inc.
6 This file is part of the Lucid Widget Library.
8 The Lucid Widget Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 The Lucid Widget Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 #ifdef NeXT
24 #undef __STRICT_BSD__ /* ick */
25 #endif
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
31 #include "../src/lisp.h"
33 #include <sys/types.h>
34 #include <stdio.h>
35 #include <ctype.h>
36 #include "lwlib-int.h"
37 #include "lwlib-utils.h"
38 #include <X11/StringDefs.h>
40 #if defined (USE_LUCID)
41 #include "lwlib-Xlw.h"
42 #endif
43 #if defined (USE_MOTIF)
44 #include "lwlib-Xm.h"
45 #else /* not USE_MOTIF */
46 #if defined (USE_LUCID)
47 #define USE_XAW
48 #endif /* not USE_MOTIF && USE_LUCID */
49 #endif
50 #if defined (USE_XAW)
51 #include <X11/Xaw/Paned.h>
52 #include "lwlib-Xaw.h"
53 #endif
55 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
56 #error At least one of USE_LUCID or USE_MOTIF must be defined.
57 #endif
59 #ifndef max
60 #define max(x, y) ((x) > (y) ? (x) : (y))
61 #endif
63 /* List of all widgets managed by the library. */
64 static widget_info*
65 all_widget_info = NULL;
67 #ifdef USE_MOTIF
68 char *lwlib_toolkit_type = "motif";
69 #else
70 char *lwlib_toolkit_type = "lucid";
71 #endif
73 static widget_value *merge_widget_value P_ ((widget_value *,
74 widget_value *,
75 int, int *));
76 static void instantiate_widget_instance P_ ((widget_instance *));
77 static int my_strcasecmp P_ ((char *, char *));
78 static void safe_free_str P_ ((char *));
79 static void free_widget_value_tree P_ ((widget_value *));
80 static widget_value *copy_widget_value_tree P_ ((widget_value *,
81 change_type));
82 static widget_info *allocate_widget_info P_ ((char *, char *, LWLIB_ID,
83 widget_value *,
84 lw_callback, lw_callback,
85 lw_callback, lw_callback));
86 static void free_widget_info P_ ((widget_info *));
87 static void mark_widget_destroyed P_ ((Widget, XtPointer, XtPointer));
88 static widget_instance *allocate_widget_instance P_ ((widget_info *,
89 Widget, Boolean));
90 static void free_widget_instance P_ ((widget_instance *));
91 static widget_info *get_widget_info P_ ((LWLIB_ID, Boolean));
92 static widget_instance *get_widget_instance P_ ((Widget, Boolean));
93 static widget_instance *find_instance P_ ((LWLIB_ID, Widget, Boolean));
94 static Boolean safe_strcmp P_ ((char *, char *));
95 static Widget name_to_widget P_ ((widget_instance *, char *));
96 static void set_one_value P_ ((widget_instance *, widget_value *, Boolean));
97 static void update_one_widget_instance P_ ((widget_instance *, Boolean));
98 static void update_all_widget_values P_ ((widget_info *, Boolean));
99 static void initialize_widget_instance P_ ((widget_instance *));
100 static widget_creation_function find_in_table P_ ((char *, widget_creation_entry *));
101 static Boolean dialog_spec_p P_ ((char *));
102 static void destroy_one_instance P_ ((widget_instance *));
103 static void lw_pop_all_widgets P_ ((LWLIB_ID, Boolean));
104 static Boolean get_one_value P_ ((widget_instance *, widget_value *));
105 static void show_one_widget_busy P_ ((Widget, Boolean));
107 void
108 lwlib_memset (address, value, length)
109 char *address;
110 int value;
111 size_t length;
113 int i;
115 for (i = 0; i < length; i++)
116 address[i] = value;
119 void
120 lwlib_bcopy (from, to, length)
121 char *from;
122 char *to;
123 int length;
125 int i;
127 for (i = 0; i < length; i++)
128 to[i] = from[i];
130 \f/* utility functions for widget_instance and widget_info */
131 char *
132 safe_strdup (s)
133 const char *s;
135 char *result;
136 if (! s) return 0;
137 result = (char *) malloc (strlen (s) + 1);
138 if (! result)
139 return 0;
140 strcpy (result, s);
141 return result;
144 /* Like strcmp but ignore differences in case. */
146 static int
147 my_strcasecmp (s1, s2)
148 char *s1, *s2;
150 while (1)
152 int c1 = *s1++;
153 int c2 = *s2++;
154 if (isupper (c1))
155 c1 = tolower (c1);
156 if (isupper (c2))
157 c2 = tolower (c2);
158 if (c1 != c2)
159 return (c1 > c2 ? 1 : -1);
160 if (c1 == 0)
161 return 0;
165 static void
166 safe_free_str (s)
167 char *s;
169 if (s) free (s);
172 static widget_value *widget_value_free_list = 0;
173 static int malloc_cpt = 0;
175 widget_value *
176 malloc_widget_value ()
178 widget_value *wv;
179 if (widget_value_free_list)
181 wv = widget_value_free_list;
182 widget_value_free_list = wv->free_list;
183 wv->free_list = 0;
185 else
187 wv = (widget_value *) malloc (sizeof (widget_value));
188 malloc_cpt++;
190 lwlib_memset ((void*) wv, 0, sizeof (widget_value));
191 return wv;
194 /* this is analogous to free(). It frees only what was allocated
195 by malloc_widget_value(), and no substructures.
197 void
198 free_widget_value (wv)
199 widget_value *wv;
201 if (wv->free_list)
202 abort ();
204 if (malloc_cpt > 25)
206 /* When the number of already allocated cells is too big,
207 We free it. */
208 free (wv);
209 malloc_cpt--;
211 else
213 wv->free_list = widget_value_free_list;
214 widget_value_free_list = wv;
218 static void
219 free_widget_value_tree (wv)
220 widget_value *wv;
222 if (!wv)
223 return;
225 if (wv->name) free (wv->name);
226 if (wv->value) free (wv->value);
227 if (wv->key) free (wv->key);
229 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
231 if (wv->toolkit_data && wv->free_toolkit_data)
233 XtFree (wv->toolkit_data);
234 wv->toolkit_data = (void *) 0xDEADBEEF;
237 if (wv->contents && (wv->contents != (widget_value*)1))
239 free_widget_value_tree (wv->contents);
240 wv->contents = (widget_value *) 0xDEADBEEF;
242 if (wv->next)
244 free_widget_value_tree (wv->next);
245 wv->next = (widget_value *) 0xDEADBEEF;
247 free_widget_value (wv);
250 static widget_value *
251 copy_widget_value_tree (val, change)
252 widget_value* val;
253 change_type change;
255 widget_value* copy;
257 if (!val)
258 return NULL;
259 if (val == (widget_value *) 1)
260 return val;
262 copy = malloc_widget_value ();
263 copy->name = safe_strdup (val->name);
264 copy->value = safe_strdup (val->value);
265 copy->key = safe_strdup (val->key);
266 copy->help = val->help;
267 copy->enabled = val->enabled;
268 copy->button_type = val->button_type;
269 copy->selected = val->selected;
270 copy->edited = False;
271 copy->change = change;
272 copy->this_one_change = change;
273 copy->contents = copy_widget_value_tree (val->contents, change);
274 copy->call_data = val->call_data;
275 copy->next = copy_widget_value_tree (val->next, change);
276 copy->toolkit_data = NULL;
277 copy->free_toolkit_data = False;
278 return copy;
281 static widget_info *
282 allocate_widget_info (type, name, id, val, pre_activate_cb,
283 selection_cb, post_activate_cb, highlight_cb)
284 char* type;
285 char* name;
286 LWLIB_ID id;
287 widget_value* val;
288 lw_callback pre_activate_cb;
289 lw_callback selection_cb;
290 lw_callback post_activate_cb;
291 lw_callback highlight_cb;
293 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
294 info->type = safe_strdup (type);
295 info->name = safe_strdup (name);
296 info->id = id;
297 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
298 info->busy = False;
299 info->pre_activate_cb = pre_activate_cb;
300 info->selection_cb = selection_cb;
301 info->post_activate_cb = post_activate_cb;
302 info->highlight_cb = highlight_cb;
303 info->instances = NULL;
305 info->next = all_widget_info;
306 all_widget_info = info;
308 return info;
311 static void
312 free_widget_info (info)
313 widget_info* info;
315 safe_free_str (info->type);
316 safe_free_str (info->name);
317 free_widget_value_tree (info->val);
318 lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
319 free (info);
322 static void
323 mark_widget_destroyed (widget, closure, call_data)
324 Widget widget;
325 XtPointer closure;
326 XtPointer call_data;
328 widget_instance* instance = (widget_instance*)closure;
330 /* be very conservative */
331 if (instance->widget == widget)
332 instance->widget = NULL;
335 /* The messy #ifdef PROTOTYPES here and elsewhere are prompted by a
336 flood of warnings about argument promotion from proprietary ISO C
337 compilers. (etags still only makes one entry for each function.) */
338 static widget_instance *
339 #ifdef PROTOTYPES
340 allocate_widget_instance (widget_info* info, Widget parent, Boolean pop_up_p)
341 #else
342 allocate_widget_instance (info, parent, pop_up_p)
343 widget_info* info;
344 Widget parent;
345 Boolean pop_up_p;
346 #endif
348 widget_instance* instance =
349 (widget_instance*)malloc (sizeof (widget_instance));
350 bzero (instance, sizeof *instance);
351 instance->parent = parent;
352 instance->pop_up_p = pop_up_p;
353 instance->info = info;
354 instance->next = info->instances;
355 info->instances = instance;
357 instantiate_widget_instance (instance);
359 XtAddCallback (instance->widget, XtNdestroyCallback,
360 mark_widget_destroyed, (XtPointer)instance);
361 return instance;
364 static void
365 free_widget_instance (instance)
366 widget_instance* instance;
368 lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
369 free (instance);
372 static widget_info *
373 #ifdef PROTOTYPES
374 get_widget_info (LWLIB_ID id, Boolean remove_p)
375 #else
376 get_widget_info (id, remove_p)
377 LWLIB_ID id;
378 Boolean remove_p;
379 #endif
381 widget_info* info;
382 widget_info* prev;
383 for (prev = NULL, info = all_widget_info;
384 info;
385 prev = info, info = info->next)
386 if (info->id == id)
388 if (remove_p)
390 if (prev)
391 prev->next = info->next;
392 else
393 all_widget_info = info->next;
395 return info;
397 return NULL;
400 /* Internal function used by the library dependent implementation to get the
401 widget_value for a given widget in an instance */
402 widget_info *
403 lw_get_widget_info (id)
404 LWLIB_ID id;
406 return get_widget_info (id, 0);
409 static widget_instance *
410 #ifdef PROTOTYPES
411 get_widget_instance (Widget widget, Boolean remove_p)
412 #else
413 get_widget_instance (widget, remove_p)
414 Widget widget;
415 Boolean remove_p;
416 #endif
418 widget_info* info;
419 widget_instance* instance;
420 widget_instance* prev;
421 for (info = all_widget_info; info; info = info->next)
422 for (prev = NULL, instance = info->instances;
423 instance;
424 prev = instance, instance = instance->next)
425 if (instance->widget == widget)
427 if (remove_p)
429 if (prev)
430 prev->next = instance->next;
431 else
432 info->instances = instance->next;
434 return instance;
436 return (widget_instance *) 0;
439 /* Value is a pointer to the widget_instance corresponding to
440 WIDGET, or null if WIDGET is not a lwlib widget. */
442 widget_instance *
443 lw_get_widget_instance (widget)
444 Widget widget;
446 return get_widget_instance (widget, False);
449 static widget_instance*
450 #ifdef PROTOTYPES
451 find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
452 #else
453 find_instance (id, parent, pop_up_p)
454 LWLIB_ID id;
455 Widget parent;
456 Boolean pop_up_p;
457 #endif
459 widget_info* info = get_widget_info (id, False);
460 widget_instance* instance;
462 if (info)
463 for (instance = info->instances; instance; instance = instance->next)
464 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
465 return instance;
467 return NULL;
471 /* utility function for widget_value */
472 static Boolean
473 safe_strcmp (s1, s2)
474 char* s1;
475 char* s2;
477 if (!!s1 ^ !!s2) return True;
478 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
482 #if 0
483 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
484 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
485 name, \
486 (oc == NO_CHANGE ? "none" : \
487 (oc == INVISIBLE_CHANGE ? "invisible" : \
488 (oc == VISIBLE_CHANGE ? "visible" : \
489 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
490 oc, \
491 (nc == NO_CHANGE ? "none" : \
492 (nc == INVISIBLE_CHANGE ? "invisible" : \
493 (nc == VISIBLE_CHANGE ? "visible" : \
494 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
495 nc, desc, a1, a2)
496 #else
497 # define EXPLAIN(name, oc, nc, desc, a1, a2)
498 #endif
501 static widget_value *
502 merge_widget_value (val1, val2, level, change_p)
503 widget_value* val1;
504 widget_value* val2;
505 int level;
506 int *change_p;
508 change_type change, this_one_change;
509 widget_value* merged_next;
510 widget_value* merged_contents;
512 if (!val1)
514 if (val2)
516 *change_p = 1;
517 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
519 else
520 return NULL;
522 if (!val2)
524 *change_p = 1;
525 free_widget_value_tree (val1);
526 return NULL;
529 change = NO_CHANGE;
531 if (safe_strcmp (val1->name, val2->name))
533 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
534 val1->name, val2->name);
535 change = max (change, STRUCTURAL_CHANGE);
536 safe_free_str (val1->name);
537 val1->name = safe_strdup (val2->name);
539 if (safe_strcmp (val1->value, val2->value))
541 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
542 val1->value, val2->value);
543 change = max (change, VISIBLE_CHANGE);
544 safe_free_str (val1->value);
545 val1->value = safe_strdup (val2->value);
547 if (safe_strcmp (val1->key, val2->key))
549 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
550 val1->key, val2->key);
551 change = max (change, VISIBLE_CHANGE);
552 safe_free_str (val1->key);
553 val1->key = safe_strdup (val2->key);
555 if (! EQ (val1->help, val2->help))
557 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "help change",
558 val1->help, val2->help);
559 change = max (change, VISIBLE_CHANGE);
560 val1->help = val2->help;
562 if (val1->enabled != val2->enabled)
564 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
565 val1->enabled, val2->enabled);
566 change = max (change, VISIBLE_CHANGE);
567 val1->enabled = val2->enabled;
569 if (val1->button_type != val2->button_type)
571 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "button type change",
572 val1->button_type, val2->button_type);
573 change = max (change, VISIBLE_CHANGE);
574 val1->button_type = val2->button_type;
576 if (val1->selected != val2->selected)
578 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
579 val1->selected, val2->selected);
580 change = max (change, VISIBLE_CHANGE);
581 val1->selected = val2->selected;
583 if (val1->call_data != val2->call_data)
585 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
586 val1->call_data, val2->call_data);
587 change = max (change, INVISIBLE_CHANGE);
588 val1->call_data = val2->call_data;
591 if (level > 0)
593 merged_contents =
594 merge_widget_value (val1->contents, val2->contents, level - 1,
595 change_p);
597 if (val1->contents && !merged_contents)
599 /* This used to say INVISIBLE_CHANGE,
600 but it is visible and vitally important when
601 the contents of the menu bar itself are entirely deleted.
603 But maybe it doesn't matter. This fails to fix the bug. */
604 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
605 0, 0);
606 change = max (change, STRUCTURAL_CHANGE);
608 else if (merged_contents && merged_contents->change != NO_CHANGE)
610 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
611 0, 0);
612 change = max (change, INVISIBLE_CHANGE);
613 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
614 #ifdef USE_MOTIF
615 change = max (merged_contents->change, change);
616 #endif
617 #endif
620 val1->contents = merged_contents;
623 this_one_change = change;
625 merged_next = merge_widget_value (val1->next, val2->next, level, change_p);
627 if (val1->next && !merged_next)
629 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
630 0, 0);
631 change = max (change, STRUCTURAL_CHANGE);
633 else if (merged_next)
635 if (merged_next->change)
636 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
637 0, 0);
638 change = max (change, merged_next->change);
641 val1->next = merged_next;
643 val1->this_one_change = this_one_change;
644 val1->change = change;
646 if (change > NO_CHANGE && val1->toolkit_data)
648 *change_p = 1;
649 if (val1->free_toolkit_data)
650 XtFree (val1->toolkit_data);
651 val1->toolkit_data = NULL;
654 return val1;
658 /* modifying the widgets */
659 static Widget
660 name_to_widget (instance, name)
661 widget_instance* instance;
662 char* name;
664 Widget widget = NULL;
666 if (!instance->widget)
667 return NULL;
669 if (!strcmp (XtName (instance->widget), name))
670 widget = instance->widget;
671 else
673 int length = strlen (name) + 2;
674 char* real_name = (char *) xmalloc (length);
675 real_name [0] = '*';
676 strcpy (real_name + 1, name);
678 widget = XtNameToWidget (instance->widget, real_name);
680 free (real_name);
682 return widget;
685 static void
686 #ifdef PROTOTYPES
687 set_one_value (widget_instance* instance, widget_value* val, Boolean deep_p)
688 #else
689 set_one_value (instance, val, deep_p)
690 widget_instance* instance;
691 widget_value* val;
692 Boolean deep_p;
693 #endif
695 Widget widget = name_to_widget (instance, val->name);
697 if (widget)
699 #if defined (USE_LUCID)
700 if (lw_lucid_widget_p (instance->widget))
701 xlw_update_one_widget (instance, widget, val, deep_p);
702 #endif
703 #if defined (USE_MOTIF)
704 if (lw_motif_widget_p (instance->widget))
705 xm_update_one_widget (instance, widget, val, deep_p);
706 #endif
707 #if defined (USE_XAW)
708 if (lw_xaw_widget_p (instance->widget))
709 xaw_update_one_widget (instance, widget, val, deep_p);
710 #endif
714 static void
715 #ifdef PROTOTYPES
716 update_one_widget_instance (widget_instance* instance, Boolean deep_p)
717 #else
718 update_one_widget_instance (instance, deep_p)
719 widget_instance* instance;
720 Boolean deep_p;
721 #endif
723 widget_value *val;
725 if (!instance->widget)
726 /* the widget was destroyed */
727 return;
729 for (val = instance->info->val; val; val = val->next)
730 if (val->change != NO_CHANGE)
731 set_one_value (instance, val, deep_p);
734 static void
735 #ifdef PROTOTYPES
736 update_all_widget_values (widget_info* info, Boolean deep_p)
737 #else
738 update_all_widget_values (info, deep_p)
739 widget_info* info;
740 Boolean deep_p;
741 #endif
743 widget_instance* instance;
744 widget_value* val;
746 for (instance = info->instances; instance; instance = instance->next)
747 update_one_widget_instance (instance, deep_p);
749 for (val = info->val; val; val = val->next)
750 val->change = NO_CHANGE;
754 #ifdef PROTOTYPES
755 lw_modify_all_widgets (LWLIB_ID id, widget_value* val, Boolean deep_p)
756 #else
757 lw_modify_all_widgets (id, val, deep_p)
758 LWLIB_ID id;
759 widget_value* val;
760 Boolean deep_p;
761 #endif
763 widget_info* info = get_widget_info (id, False);
764 widget_value* new_val;
765 widget_value* next_new_val;
766 widget_value* cur;
767 widget_value* prev;
768 widget_value* next;
769 int found;
770 int change_p = 0;
772 if (!info)
773 return 0;
775 for (new_val = val; new_val; new_val = new_val->next)
777 next_new_val = new_val->next;
778 new_val->next = NULL;
779 found = False;
780 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
781 if (!strcmp (cur->name, new_val->name))
783 found = True;
784 next = cur->next;
785 cur->next = NULL;
786 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1,
787 &change_p);
788 if (prev)
789 prev->next = cur ? cur : next;
790 else
791 info->val = cur ? cur : next;
792 if (cur)
793 cur->next = next;
794 break;
796 if (!found)
798 /* Could not find it, add it */
799 if (prev)
800 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
801 else
802 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
803 change_p = 1;
805 new_val->next = next_new_val;
808 update_all_widget_values (info, deep_p);
809 return change_p;
813 /* creating the widgets */
815 static void
816 initialize_widget_instance (instance)
817 widget_instance* instance;
819 widget_value* val;
821 for (val = instance->info->val; val; val = val->next)
822 val->change = STRUCTURAL_CHANGE;
824 update_one_widget_instance (instance, True);
826 for (val = instance->info->val; val; val = val->next)
827 val->change = NO_CHANGE;
831 static widget_creation_function
832 find_in_table (type, table)
833 char* type;
834 widget_creation_entry* table;
836 widget_creation_entry* cur;
837 for (cur = table; cur->type; cur++)
838 if (!my_strcasecmp (type, cur->type))
839 return cur->function;
840 return NULL;
843 static Boolean
844 dialog_spec_p (name)
845 char* name;
847 /* return True if name matches [EILPQeilpq][1-9][Bb] or
848 [EILPQeilpq][1-9][Bb][Rr][1-9] */
849 if (!name)
850 return False;
852 switch (name [0])
854 case 'E': case 'I': case 'L': case 'P': case 'Q':
855 case 'e': case 'i': case 'l': case 'p': case 'q':
856 if (name [1] >= '0' && name [1] <= '9')
858 if (name [2] != 'B' && name [2] != 'b')
859 return False;
860 if (!name [3])
861 return True;
862 if ((name [3] == 'T' || name [3] == 't') && !name [4])
863 return True;
864 if ((name [3] == 'R' || name [3] == 'r')
865 && name [4] >= '0' && name [4] <= '9' && !name [5])
866 return True;
867 return False;
869 else
870 return False;
872 default:
873 return False;
877 static void
878 instantiate_widget_instance (instance)
879 widget_instance* instance;
881 widget_creation_function function = NULL;
883 #if defined (USE_LUCID)
884 if (!function)
885 function = find_in_table (instance->info->type, xlw_creation_table);
886 #endif
887 #if defined(USE_MOTIF)
888 if (!function)
889 function = find_in_table (instance->info->type, xm_creation_table);
890 #endif
891 #if defined (USE_XAW)
892 if (!function)
893 function = find_in_table (instance->info->type, xaw_creation_table);
894 #endif
896 if (!function)
898 if (dialog_spec_p (instance->info->type))
900 #if defined (USE_LUCID)
901 /* not yet */
902 #endif
903 #if defined(USE_MOTIF)
904 if (!function)
905 function = xm_create_dialog;
906 #endif
907 #if defined (USE_XAW)
908 if (!function)
909 function = xaw_create_dialog;
910 #endif
914 if (!function)
916 printf ("No creation function for widget type %s\n",
917 instance->info->type);
918 abort ();
921 instance->widget = (*function) (instance);
923 if (!instance->widget)
924 abort ();
926 /* XtRealizeWidget (instance->widget);*/
929 void
930 lw_register_widget (type, name, id, val, pre_activate_cb,
931 selection_cb, post_activate_cb, highlight_cb)
932 char* type;
933 char* name;
934 LWLIB_ID id;
935 widget_value* val;
936 lw_callback pre_activate_cb;
937 lw_callback selection_cb;
938 lw_callback post_activate_cb;
939 lw_callback highlight_cb;
941 if (!get_widget_info (id, False))
942 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
943 post_activate_cb, highlight_cb);
946 Widget
947 #ifdef PROTOTYPES
948 lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
949 #else
950 lw_get_widget (id, parent, pop_up_p)
951 LWLIB_ID id;
952 Widget parent;
953 Boolean pop_up_p;
954 #endif
956 widget_instance* instance;
958 instance = find_instance (id, parent, pop_up_p);
959 return instance ? instance->widget : NULL;
962 Widget
963 #ifdef PROTOTYPES
964 lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
965 #else
966 lw_make_widget (id, parent, pop_up_p)
967 LWLIB_ID id;
968 Widget parent;
969 Boolean pop_up_p;
970 #endif
972 widget_instance* instance;
973 widget_info* info;
975 instance = find_instance (id, parent, pop_up_p);
976 if (!instance)
978 info = get_widget_info (id, False);
979 if (!info)
980 return NULL;
981 instance = allocate_widget_instance (info, parent, pop_up_p);
982 initialize_widget_instance (instance);
984 if (!instance->widget)
985 abort ();
986 return instance->widget;
989 Widget
990 #ifdef PROTOTYPES
991 lw_create_widget (char* type, char* name, LWLIB_ID id, widget_value* val,
992 Widget parent, Boolean pop_up_p,
993 lw_callback pre_activate_cb, lw_callback selection_cb,
994 lw_callback post_activate_cb, lw_callback highlight_cb)
995 #else
996 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb,
997 selection_cb, post_activate_cb, highlight_cb)
998 char* type;
999 char* name;
1000 LWLIB_ID id;
1001 widget_value* val;
1002 Widget parent;
1003 Boolean pop_up_p;
1004 lw_callback pre_activate_cb;
1005 lw_callback selection_cb;
1006 lw_callback post_activate_cb;
1007 lw_callback highlight_cb;
1008 #endif
1010 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
1011 post_activate_cb, highlight_cb);
1012 return lw_make_widget (id, parent, pop_up_p);
1016 /* destroying the widgets */
1017 static void
1018 destroy_one_instance (instance)
1019 widget_instance* instance;
1021 /* Remove the destroy callback on the widget; that callback will try to
1022 dereference the instance object (to set its widget slot to 0, since the
1023 widget is dead.) Since the instance is now dead, we don't have to worry
1024 about the fact that its widget is dead too.
1026 This happens in the Phase2Destroy of the widget, so this callback would
1027 not have been run until arbitrarily long after the instance was freed.
1029 if (instance->widget)
1030 XtRemoveCallback (instance->widget, XtNdestroyCallback,
1031 mark_widget_destroyed, (XtPointer)instance);
1033 if (instance->widget)
1035 /* The else are pretty tricky here, including the empty statement
1036 at the end because it would be very bad to destroy a widget
1037 twice. */
1038 #if defined (USE_LUCID)
1039 if (lw_lucid_widget_p (instance->widget))
1040 xlw_destroy_instance (instance);
1041 else
1042 #endif
1043 #if defined (USE_MOTIF)
1044 if (lw_motif_widget_p (instance->widget))
1045 xm_destroy_instance (instance);
1046 else
1047 #endif
1048 #if defined (USE_XAW)
1049 if (lw_xaw_widget_p (instance->widget))
1050 xaw_destroy_instance (instance);
1051 else
1052 #endif
1053 /* do not remove the empty statement */
1057 free_widget_instance (instance);
1060 void
1061 lw_destroy_widget (w)
1062 Widget w;
1064 widget_instance* instance = get_widget_instance (w, True);
1066 if (instance)
1068 widget_info *info = instance->info;
1069 /* instance has already been removed from the list; free it */
1070 destroy_one_instance (instance);
1071 /* if there are no instances left, free the info too */
1072 if (!info->instances)
1073 lw_destroy_all_widgets (info->id);
1077 void
1078 lw_destroy_all_widgets (id)
1079 LWLIB_ID id;
1081 widget_info* info = get_widget_info (id, True);
1082 widget_instance* instance;
1083 widget_instance* next;
1085 if (info)
1087 for (instance = info->instances; instance; )
1089 next = instance->next;
1090 destroy_one_instance (instance);
1091 instance = next;
1093 free_widget_info (info);
1097 void
1098 lw_destroy_everything ()
1100 while (all_widget_info)
1101 lw_destroy_all_widgets (all_widget_info->id);
1104 void
1105 lw_destroy_all_pop_ups ()
1107 widget_info* info;
1108 widget_info* next;
1109 widget_instance* instance;
1111 for (info = all_widget_info; info; info = next)
1113 next = info->next;
1114 instance = info->instances;
1115 if (instance && instance->pop_up_p)
1116 lw_destroy_all_widgets (info->id);
1120 #ifdef USE_MOTIF
1121 extern Widget first_child (/* Widget */); /* garbage */
1122 #endif
1124 Widget
1125 lw_raise_all_pop_up_widgets ()
1127 widget_info* info;
1128 widget_instance* instance;
1129 Widget result = NULL;
1131 for (info = all_widget_info; info; info = info->next)
1132 for (instance = info->instances; instance; instance = instance->next)
1133 if (instance->pop_up_p)
1135 Widget widget = instance->widget;
1136 if (widget)
1138 if (XtIsManaged (widget)
1139 #ifdef USE_MOTIF
1140 /* What a complete load of crap!!!!
1141 When a dialogShell is on the screen, it is not managed!
1143 || (lw_motif_widget_p (instance->widget) &&
1144 XtIsManaged (first_child (widget)))
1145 #endif
1148 if (!result)
1149 result = widget;
1150 XMapRaised (XtDisplay (widget), XtWindow (widget));
1154 return result;
1157 static void
1158 #ifdef PROTOTYPES
1159 lw_pop_all_widgets (LWLIB_ID id, Boolean up)
1160 #else
1161 lw_pop_all_widgets (id, up)
1162 LWLIB_ID id;
1163 Boolean up;
1164 #endif
1166 widget_info* info = get_widget_info (id, False);
1167 widget_instance* instance;
1169 if (info)
1170 for (instance = info->instances; instance; instance = instance->next)
1171 if (instance->pop_up_p && instance->widget)
1173 #if defined (USE_LUCID)
1174 if (lw_lucid_widget_p (instance->widget))
1176 XtRealizeWidget (instance->widget);
1177 xlw_pop_instance (instance, up);
1179 #endif
1180 #if defined (USE_MOTIF)
1181 if (lw_motif_widget_p (instance->widget))
1183 XtRealizeWidget (instance->widget);
1184 xm_pop_instance (instance, up);
1186 #endif
1187 #if defined (USE_XAW)
1188 if (lw_xaw_widget_p (instance->widget))
1190 XtRealizeWidget (XtParent (instance->widget));
1191 XtRealizeWidget (instance->widget);
1192 xaw_pop_instance (instance, up);
1194 #endif
1198 void
1199 lw_pop_up_all_widgets (id)
1200 LWLIB_ID id;
1202 lw_pop_all_widgets (id, True);
1205 void
1206 lw_pop_down_all_widgets (id)
1207 LWLIB_ID id;
1209 lw_pop_all_widgets (id, False);
1212 void
1213 lw_popup_menu (widget, event)
1214 Widget widget;
1215 XEvent *event;
1217 #if defined (USE_LUCID)
1218 if (lw_lucid_widget_p (widget))
1219 xlw_popup_menu (widget, event);
1220 #endif
1221 #if defined (USE_MOTIF)
1222 if (lw_motif_widget_p (widget))
1223 xm_popup_menu (widget, event);
1224 #endif
1225 #if defined (USE_XAW)
1226 if (lw_xaw_widget_p (widget))
1227 xaw_popup_menu (widget, event);
1228 #endif
1231 \f/* get the values back */
1232 static Boolean
1233 get_one_value (instance, val)
1234 widget_instance* instance;
1235 widget_value* val;
1237 Widget widget = name_to_widget (instance, val->name);
1239 if (widget)
1241 #if defined (USE_LUCID)
1242 if (lw_lucid_widget_p (instance->widget))
1243 xlw_update_one_value (instance, widget, val);
1244 #endif
1245 #if defined (USE_MOTIF)
1246 if (lw_motif_widget_p (instance->widget))
1247 xm_update_one_value (instance, widget, val);
1248 #endif
1249 #if defined (USE_XAW)
1250 if (lw_xaw_widget_p (instance->widget))
1251 xaw_update_one_value (instance, widget, val);
1252 #endif
1253 return True;
1255 else
1256 return False;
1259 Boolean
1260 lw_get_some_values (id, val_out)
1261 LWLIB_ID id;
1262 widget_value* val_out;
1264 widget_info* info = get_widget_info (id, False);
1265 widget_instance* instance;
1266 widget_value* val;
1267 Boolean result = False;
1269 if (!info)
1270 return False;
1272 instance = info->instances;
1273 if (!instance)
1274 return False;
1276 for (val = val_out; val; val = val->next)
1277 if (get_one_value (instance, val))
1278 result = True;
1280 return result;
1283 widget_value*
1284 lw_get_all_values (id)
1285 LWLIB_ID id;
1287 widget_info* info = get_widget_info (id, False);
1288 widget_value* val = info->val;
1289 if (lw_get_some_values (id, val))
1290 return val;
1291 else
1292 return NULL;
1295 /* internal function used by the library dependent implementation to get the
1296 widget_value for a given widget in an instance */
1297 widget_value*
1298 lw_get_widget_value_for_widget (instance, w)
1299 widget_instance* instance;
1300 Widget w;
1302 char* name = XtName (w);
1303 widget_value* cur;
1304 for (cur = instance->info->val; cur; cur = cur->next)
1305 if (!strcmp (cur->name, name))
1306 return cur;
1307 return NULL;
1310 \f/* update other instances value when one thing changed */
1312 /* To forbid recursive calls */
1313 static Boolean lwlib_updating;
1315 /* This function can be used as a an XtCallback for the widgets that get
1316 modified to update other instances of the widgets. Closure should be the
1317 widget_instance. */
1318 void
1319 lw_internal_update_other_instances (widget, closure, call_data)
1320 Widget widget;
1321 XtPointer closure;
1322 XtPointer call_data;
1324 widget_instance* instance = (widget_instance*)closure;
1325 char* name = XtName (widget);
1326 widget_info* info;
1327 widget_instance* cur;
1328 widget_value* val;
1330 /* Avoid possibly infinite recursion. */
1331 if (lwlib_updating)
1332 return;
1334 /* protect against the widget being destroyed */
1335 if (XtWidgetBeingDestroyedP (widget))
1336 return;
1338 /* Return immediately if there are no other instances */
1339 info = instance->info;
1340 if (!info->instances->next)
1341 return;
1343 lwlib_updating = True;
1345 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1347 if (val && get_one_value (instance, val))
1348 for (cur = info->instances; cur; cur = cur->next)
1349 if (cur != instance)
1350 set_one_value (cur, val, True);
1352 lwlib_updating = False;
1356 \f/* get the id */
1358 LWLIB_ID
1359 lw_get_widget_id (w)
1360 Widget w;
1362 widget_instance* instance = get_widget_instance (w, False);
1364 return instance ? instance->info->id : 0;
1367 \f/* set the keyboard focus */
1368 void
1369 lw_set_keyboard_focus (parent, w)
1370 Widget parent;
1371 Widget w;
1373 #if defined (USE_MOTIF)
1374 xm_set_keyboard_focus (parent, w);
1375 #else
1376 XtSetKeyboardFocus (parent, w);
1377 #endif
1380 \f/* Show busy */
1381 static void
1382 #ifdef PROTOTYPES
1383 show_one_widget_busy (Widget w, Boolean flag)
1384 #else
1385 show_one_widget_busy (w, flag)
1386 Widget w;
1387 Boolean flag;
1388 #endif
1390 Pixel foreground = 0;
1391 Pixel background = 1;
1392 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1393 if (!widget_to_invert)
1394 widget_to_invert = w;
1396 XtVaGetValues (widget_to_invert,
1397 XtNforeground, &foreground,
1398 XtNbackground, &background,
1399 NULL);
1400 XtVaSetValues (widget_to_invert,
1401 XtNforeground, background,
1402 XtNbackground, foreground,
1403 NULL);
1406 void
1407 #ifdef PROTOTYPES
1408 lw_show_busy (Widget w, Boolean busy)
1409 #else
1410 lw_show_busy (w, busy)
1411 Widget w;
1412 Boolean busy;
1413 #endif
1415 widget_instance* instance = get_widget_instance (w, False);
1416 widget_info* info;
1417 widget_instance* next;
1419 if (instance)
1421 info = instance->info;
1422 if (info->busy != busy)
1424 for (next = info->instances; next; next = next->next)
1425 if (next->widget)
1426 show_one_widget_busy (next->widget, busy);
1427 info->busy = busy;
1432 /* This hack exists because Lucid/Athena need to execute the strange
1433 function below to support geometry management. */
1434 void
1435 #ifdef PROTOTYPES
1436 lw_refigure_widget (Widget w, Boolean doit)
1437 #else
1438 lw_refigure_widget (w, doit)
1439 Widget w;
1440 Boolean doit;
1441 #endif
1443 #if defined (USE_XAW)
1444 XawPanedSetRefigureMode (w, doit);
1445 #endif
1446 #if defined (USE_MOTIF)
1447 if (doit)
1448 XtManageChild (w);
1449 else
1450 XtUnmanageChild (w);
1451 #endif
1454 /* Toolkit independent way of determining if an event window is in the
1455 menubar. */
1456 Boolean
1457 lw_window_is_in_menubar (win, menubar_widget)
1458 Window win;
1459 Widget menubar_widget;
1461 return menubar_widget
1462 #if defined (USE_LUCID)
1463 && XtWindow (menubar_widget) == win;
1464 #endif
1465 #if defined (USE_MOTIF)
1466 && ((XtWindow (menubar_widget) == win)
1467 || (XtWindowToWidget (XtDisplay (menubar_widget), win)
1468 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
1469 == menubar_widget)));
1470 #endif
1473 /* Motif hack to set the main window areas. */
1474 void
1475 lw_set_main_areas (parent, menubar, work_area)
1476 Widget parent;
1477 Widget menubar;
1478 Widget work_area;
1480 #if defined (USE_MOTIF)
1481 xm_set_main_areas (parent, menubar, work_area);
1482 #endif
1485 /* Manage resizing for Motif. This disables resizing when the menubar
1486 is about to be modified. */
1487 void
1488 #ifdef PROTOTYPES
1489 lw_allow_resizing (Widget w, Boolean flag)
1490 #else
1491 lw_allow_resizing (w, flag)
1492 Widget w;
1493 Boolean flag;
1494 #endif
1496 #if defined (USE_MOTIF)
1497 xm_manage_resizing (w, flag);
1498 #endif
1502 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1503 set to an appropriate enumerator of type enum menu_separator.
1504 MOTIF_P non-zero means map separator types not supported by Motif
1505 to similar ones that are supported. */
1508 lw_separator_p (label, type, motif_p)
1509 char *label;
1510 enum menu_separator *type;
1511 int motif_p;
1513 int separator_p = 0;
1515 if (strlen (label) >= 3
1516 && bcmp (label, "--:", 3) == 0)
1518 static struct separator_table
1520 char *name;
1521 enum menu_separator type;
1523 separator_names[] =
1525 {"space", SEPARATOR_NO_LINE},
1526 {"noLine", SEPARATOR_NO_LINE},
1527 {"singleLine", SEPARATOR_SINGLE_LINE},
1528 {"doubleLine", SEPARATOR_DOUBLE_LINE},
1529 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE},
1530 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE},
1531 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN},
1532 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT},
1533 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH},
1534 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH},
1535 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
1536 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
1537 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
1538 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
1539 {0,0}
1542 int i;
1544 label += 3;
1545 for (i = 0; separator_names[i].name; ++i)
1546 if (strcmp (label, separator_names[i].name) == 0)
1548 separator_p = 1;
1549 *type = separator_names[i].type;
1551 /* If separator type is not supported under Motif,
1552 use a similar one. */
1553 if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
1554 *type -= 4;
1555 break;
1558 else if (strlen (label) > 3
1559 && bcmp (label, "--", 2) == 0
1560 && label[2] != '-')
1562 /* Alternative, more Emacs-style names. */
1563 static struct separator_table
1565 char *name;
1566 enum menu_separator type;
1568 separator_names[] =
1570 {"space", SEPARATOR_NO_LINE},
1571 {"no-line", SEPARATOR_NO_LINE},
1572 {"single-line", SEPARATOR_SINGLE_LINE},
1573 {"double-line", SEPARATOR_DOUBLE_LINE},
1574 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE},
1575 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE},
1576 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN},
1577 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT},
1578 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH},
1579 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH},
1580 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
1581 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
1582 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
1583 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
1584 {0,0}
1587 int i;
1589 label += 2;
1590 for (i = 0; separator_names[i].name; ++i)
1591 if (strcmp (label, separator_names[i].name) == 0)
1593 separator_p = 1;
1594 *type = separator_names[i].type;
1596 /* If separator type is not supported under Motif,
1597 use a similar one. */
1598 if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
1599 *type -= 4;
1600 break;
1603 else
1605 /* Old-style separator, maybe. It's a separator if it contains
1606 only dashes. */
1607 while (*label == '-')
1608 ++label;
1609 separator_p = *label == 0;
1610 *type = SEPARATOR_SHADOW_ETCHED_IN;
1613 return separator_p;
1616 /* arch-tag: 3d730f36-a441-4a71-9971-48ef3b5a4d9f
1617 (do not change this comment) */