2001-02-24 Michael Kifer <kifer@cs.sunysb.edu>
[emacs.git] / lwlib / lwlib.c
blob81ab8d5d2c7b755c007955095f12c34275dd2989
1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #ifdef NeXT
22 #undef __STRICT_BSD__ /* ick */
23 #endif
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <ctype.h>
32 #include "lwlib-int.h"
33 #include "lwlib-utils.h"
34 #include <X11/StringDefs.h>
36 extern long *xmalloc();
38 #if defined (USE_LUCID)
39 #include "lwlib-Xlw.h"
40 #endif
41 #if defined (USE_MOTIF)
42 #include "lwlib-Xm.h"
43 #else /* not USE_MOTIF */
44 #if defined (USE_LUCID)
45 #define USE_XAW
46 #endif /* not USE_MOTIF && USE_LUCID */
47 #endif
48 #if defined (USE_OLIT)
49 #include "lwlib-Xol.h"
50 #endif
51 #if defined (USE_XAW)
52 #include <X11/Xaw/Paned.h>
53 #include "lwlib-Xaw.h"
54 #endif
56 #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
57 ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
58 #endif
60 #if defined (USE_MOTIF) && defined (USE_OLIT)
61 ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
62 #endif
64 #ifndef max
65 #define max(x, y) ((x) > (y) ? (x) : (y))
66 #endif
68 /* List of all widgets managed by the library. */
69 static widget_info*
70 all_widget_info = NULL;
72 #ifdef USE_MOTIF
73 char *lwlib_toolkit_type = "motif";
74 #else
75 char *lwlib_toolkit_type = "lucid";
76 #endif
78 #if defined __STDC__ || defined PROTOTYPES
79 #define P_(x) x
80 #else
81 #define P_(x) ()
82 #endif
84 static widget_value *merge_widget_value P_ ((widget_value *,
85 widget_value *,
86 int, int *));
87 static void instantiate_widget_instance P_ ((widget_instance *));
88 static int my_strcasecmp P_ ((char *, char *));
89 static void safe_free_str P_ ((char *));
90 static void free_widget_value_tree P_ ((widget_value *));
91 static widget_value *copy_widget_value_tree P_ ((widget_value *,
92 change_type));
93 static widget_info *allocate_widget_info P_ ((char *, char *, LWLIB_ID,
94 widget_value *,
95 lw_callback, lw_callback,
96 lw_callback, lw_callback));
97 static void free_widget_info P_ ((widget_info *));
98 static void mark_widget_destroyed P_ ((Widget, XtPointer, XtPointer));
99 static widget_instance *allocate_widget_instance P_ ((widget_info *,
100 Widget, Boolean));
101 static void free_widget_instance P_ ((widget_instance *));
102 static widget_info *get_widget_info P_ ((LWLIB_ID, Boolean));
103 static widget_instance *get_widget_instance P_ ((Widget, Boolean));
104 static widget_instance *find_instance P_ ((LWLIB_ID, Widget, Boolean));
105 static Boolean safe_strcmp P_ ((char *, char *));
106 static Widget name_to_widget P_ ((widget_instance *, char *));
107 static void set_one_value P_ ((widget_instance *, widget_value *, Boolean));
108 static void update_one_widget_instance P_ ((widget_instance *, Boolean));
109 static void update_all_widget_values P_ ((widget_info *, Boolean));
110 static void initialize_widget_instance P_ ((widget_instance *));
111 static widget_creation_function find_in_table P_ ((char *, widget_creation_entry *));
112 static Boolean dialog_spec_p P_ ((char *));
113 static void instantiate_widget_instance P_ ((widget_instance *));
114 static void destroy_one_instance P_ ((widget_instance *));
115 static void lw_pop_all_widgets P_ ((LWLIB_ID, Boolean));
116 static Boolean get_one_value P_ ((widget_instance *, widget_value *));
117 static void show_one_widget_busy P_ ((Widget, Boolean));
119 void
120 lwlib_memset (address, value, length)
121 char *address;
122 int value;
123 int length;
125 int i;
127 for (i = 0; i < length; i++)
128 address[i] = value;
131 void
132 lwlib_bcopy (from, to, length)
133 char *from;
134 char *to;
135 int length;
137 int i;
139 for (i = 0; i < length; i++)
140 to[i] = from[i];
142 \f/* utility functions for widget_instance and widget_info */
143 char *
144 safe_strdup (s)
145 const char *s;
147 char *result;
148 if (! s) return 0;
149 result = (char *) malloc (strlen (s) + 1);
150 if (! result)
151 return 0;
152 strcpy (result, s);
153 return result;
156 /* Like strcmp but ignore differences in case. */
158 static int
159 my_strcasecmp (s1, s2)
160 char *s1, *s2;
162 while (1)
164 int c1 = *s1++;
165 int c2 = *s2++;
166 if (isupper (c1))
167 c1 = tolower (c1);
168 if (isupper (c2))
169 c2 = tolower (c2);
170 if (c1 != c2)
171 return (c1 > c2 ? 1 : -1);
172 if (c1 == 0)
173 return 0;
177 static void
178 safe_free_str (s)
179 char *s;
181 if (s) free (s);
184 static widget_value *widget_value_free_list = 0;
185 static int malloc_cpt = 0;
187 widget_value *
188 malloc_widget_value ()
190 widget_value *wv;
191 if (widget_value_free_list)
193 wv = widget_value_free_list;
194 widget_value_free_list = wv->free_list;
195 wv->free_list = 0;
197 else
199 wv = (widget_value *) malloc (sizeof (widget_value));
200 malloc_cpt++;
202 lwlib_memset (wv, 0, sizeof (widget_value));
203 return wv;
206 /* this is analogous to free(). It frees only what was allocated
207 by malloc_widget_value(), and no substructures.
209 void
210 free_widget_value (wv)
211 widget_value *wv;
213 if (wv->free_list)
214 abort ();
216 if (malloc_cpt > 25)
218 /* When the number of already allocated cells is too big,
219 We free it. */
220 free (wv);
221 malloc_cpt--;
223 else
225 wv->free_list = widget_value_free_list;
226 widget_value_free_list = wv;
230 static void
231 free_widget_value_tree (wv)
232 widget_value *wv;
234 if (!wv)
235 return;
237 if (wv->name) free (wv->name);
238 if (wv->value) free (wv->value);
239 if (wv->key) free (wv->key);
240 if (wv->help) free (wv->help);
242 wv->name = wv->value = wv->key = wv->help = (char *) 0xDEADBEEF;
244 if (wv->toolkit_data && wv->free_toolkit_data)
246 XtFree (wv->toolkit_data);
247 wv->toolkit_data = (void *) 0xDEADBEEF;
250 if (wv->contents && (wv->contents != (widget_value*)1))
252 free_widget_value_tree (wv->contents);
253 wv->contents = (widget_value *) 0xDEADBEEF;
255 if (wv->next)
257 free_widget_value_tree (wv->next);
258 wv->next = (widget_value *) 0xDEADBEEF;
260 free_widget_value (wv);
263 static widget_value *
264 copy_widget_value_tree (val, change)
265 widget_value* val;
266 change_type change;
268 widget_value* copy;
270 if (!val)
271 return NULL;
272 if (val == (widget_value *) 1)
273 return val;
275 copy = malloc_widget_value ();
276 copy->name = safe_strdup (val->name);
277 copy->value = safe_strdup (val->value);
278 copy->key = safe_strdup (val->key);
279 copy->help = safe_strdup (val->help);
280 copy->enabled = val->enabled;
281 copy->button_type = val->button_type;
282 copy->selected = val->selected;
283 copy->edited = False;
284 copy->change = change;
285 copy->this_one_change = change;
286 copy->contents = copy_widget_value_tree (val->contents, change);
287 copy->call_data = val->call_data;
288 copy->next = copy_widget_value_tree (val->next, change);
289 copy->toolkit_data = NULL;
290 copy->free_toolkit_data = False;
291 return copy;
294 static widget_info *
295 allocate_widget_info (type, name, id, val, pre_activate_cb,
296 selection_cb, post_activate_cb, highlight_cb)
297 char* type;
298 char* name;
299 LWLIB_ID id;
300 widget_value* val;
301 lw_callback pre_activate_cb;
302 lw_callback selection_cb;
303 lw_callback post_activate_cb;
304 lw_callback highlight_cb;
306 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
307 info->type = safe_strdup (type);
308 info->name = safe_strdup (name);
309 info->id = id;
310 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
311 info->busy = False;
312 info->pre_activate_cb = pre_activate_cb;
313 info->selection_cb = selection_cb;
314 info->post_activate_cb = post_activate_cb;
315 info->highlight_cb = highlight_cb;
316 info->instances = NULL;
318 info->next = all_widget_info;
319 all_widget_info = info;
321 return info;
324 static void
325 free_widget_info (info)
326 widget_info* info;
328 safe_free_str (info->type);
329 safe_free_str (info->name);
330 free_widget_value_tree (info->val);
331 lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
332 free (info);
335 static void
336 mark_widget_destroyed (widget, closure, call_data)
337 Widget widget;
338 XtPointer closure;
339 XtPointer call_data;
341 widget_instance* instance = (widget_instance*)closure;
343 /* be very conservative */
344 if (instance->widget == widget)
345 instance->widget = NULL;
348 static widget_instance *
349 allocate_widget_instance (info, parent, pop_up_p)
350 widget_info* info;
351 Widget parent;
352 Boolean pop_up_p;
354 widget_instance* instance =
355 (widget_instance*)malloc (sizeof (widget_instance));
356 bzero (instance, sizeof *instance);
357 instance->parent = parent;
358 instance->pop_up_p = pop_up_p;
359 instance->info = info;
360 instance->next = info->instances;
361 info->instances = instance;
363 instantiate_widget_instance (instance);
365 XtAddCallback (instance->widget, XtNdestroyCallback,
366 mark_widget_destroyed, (XtPointer)instance);
367 return instance;
370 static void
371 free_widget_instance (instance)
372 widget_instance* instance;
374 lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
375 free (instance);
378 static widget_info *
379 get_widget_info (id, remove_p)
380 LWLIB_ID id;
381 Boolean remove_p;
383 widget_info* info;
384 widget_info* prev;
385 for (prev = NULL, info = all_widget_info;
386 info;
387 prev = info, info = info->next)
388 if (info->id == id)
390 if (remove_p)
392 if (prev)
393 prev->next = info->next;
394 else
395 all_widget_info = info->next;
397 return info;
399 return NULL;
402 /* Internal function used by the library dependent implementation to get the
403 widget_value for a given widget in an instance */
404 widget_info *
405 lw_get_widget_info (id)
406 LWLIB_ID id;
408 return get_widget_info (id, 0);
411 static widget_instance *
412 get_widget_instance (widget, remove_p)
413 Widget widget;
414 Boolean remove_p;
416 widget_info* info;
417 widget_instance* instance;
418 widget_instance* prev;
419 for (info = all_widget_info; info; info = info->next)
420 for (prev = NULL, instance = info->instances;
421 instance;
422 prev = instance, instance = instance->next)
423 if (instance->widget == widget)
425 if (remove_p)
427 if (prev)
428 prev->next = instance->next;
429 else
430 info->instances = instance->next;
432 return instance;
434 return (widget_instance *) 0;
437 /* Value is a pointer to the widget_instance corresponding to
438 WIDGET, or null if WIDGET is not a lwlib widget. */
440 widget_instance *
441 lw_get_widget_instance (widget)
442 Widget widget;
444 return get_widget_instance (widget, False);
447 static widget_instance*
448 find_instance (id, parent, pop_up_p)
449 LWLIB_ID id;
450 Widget parent;
451 Boolean pop_up_p;
453 widget_info* info = get_widget_info (id, False);
454 widget_instance* instance;
456 if (info)
457 for (instance = info->instances; instance; instance = instance->next)
458 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
459 return instance;
461 return NULL;
465 /* utility function for widget_value */
466 static Boolean
467 safe_strcmp (s1, s2)
468 char* s1;
469 char* s2;
471 if (!!s1 ^ !!s2) return True;
472 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
476 #if 0
477 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
478 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
479 name, \
480 (oc == NO_CHANGE ? "none" : \
481 (oc == INVISIBLE_CHANGE ? "invisible" : \
482 (oc == VISIBLE_CHANGE ? "visible" : \
483 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
484 oc, \
485 (nc == NO_CHANGE ? "none" : \
486 (nc == INVISIBLE_CHANGE ? "invisible" : \
487 (nc == VISIBLE_CHANGE ? "visible" : \
488 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
489 nc, desc, a1, a2)
490 #else
491 # define EXPLAIN(name, oc, nc, desc, a1, a2)
492 #endif
495 static widget_value *
496 merge_widget_value (val1, val2, level, change_p)
497 widget_value* val1;
498 widget_value* val2;
499 int level;
500 int *change_p;
502 change_type change, this_one_change;
503 widget_value* merged_next;
504 widget_value* merged_contents;
506 if (!val1)
508 if (val2)
510 *change_p = 1;
511 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
513 else
514 return NULL;
516 if (!val2)
518 *change_p = 1;
519 free_widget_value_tree (val1);
520 return NULL;
523 change = NO_CHANGE;
525 if (safe_strcmp (val1->name, val2->name))
527 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
528 val1->name, val2->name);
529 change = max (change, STRUCTURAL_CHANGE);
530 safe_free_str (val1->name);
531 val1->name = safe_strdup (val2->name);
533 if (safe_strcmp (val1->value, val2->value))
535 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
536 val1->value, val2->value);
537 change = max (change, VISIBLE_CHANGE);
538 safe_free_str (val1->value);
539 val1->value = safe_strdup (val2->value);
541 if (safe_strcmp (val1->key, val2->key))
543 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
544 val1->key, val2->key);
545 change = max (change, VISIBLE_CHANGE);
546 safe_free_str (val1->key);
547 val1->key = safe_strdup (val2->key);
549 if (safe_strcmp (val1->help, val2->help))
551 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "help change",
552 val1->help, val2->help);
553 change = max (change, VISIBLE_CHANGE);
554 safe_free_str (val1->help);
555 val1->help = safe_strdup (val2->help);
557 if (val1->enabled != val2->enabled)
559 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
560 val1->enabled, val2->enabled);
561 change = max (change, VISIBLE_CHANGE);
562 val1->enabled = val2->enabled;
564 if (val1->button_type != val2->button_type)
566 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "button type change",
567 val1->button_type, val2->button_type);
568 change = max (change, VISIBLE_CHANGE);
569 val1->button_type = val2->button_type;
571 if (val1->selected != val2->selected)
573 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
574 val1->selected, val2->selected);
575 change = max (change, VISIBLE_CHANGE);
576 val1->selected = val2->selected;
578 if (val1->call_data != val2->call_data)
580 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
581 val1->call_data, val2->call_data);
582 change = max (change, INVISIBLE_CHANGE);
583 val1->call_data = val2->call_data;
586 if (level > 0)
588 merged_contents =
589 merge_widget_value (val1->contents, val2->contents, level - 1,
590 change_p);
592 if (val1->contents && !merged_contents)
594 /* This used to say INVISIBLE_CHANGE,
595 but it is visible and vitally important when
596 the contents of the menu bar itself are entirely deleted.
598 But maybe it doesn't matter. This fails to fix the bug. */
599 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
600 0, 0);
601 change = max (change, STRUCTURAL_CHANGE);
603 else if (merged_contents && merged_contents->change != NO_CHANGE)
605 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
606 0, 0);
607 change = max (change, INVISIBLE_CHANGE);
608 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
609 #ifdef USE_MOTIF
610 change = max (merged_contents->change, change);
611 #endif
612 #endif
615 val1->contents = merged_contents;
618 this_one_change = change;
620 merged_next = merge_widget_value (val1->next, val2->next, level, change_p);
622 if (val1->next && !merged_next)
624 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
625 0, 0);
626 change = max (change, STRUCTURAL_CHANGE);
628 else if (merged_next)
630 if (merged_next->change)
631 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
632 0, 0);
633 change = max (change, merged_next->change);
636 val1->next = merged_next;
638 val1->this_one_change = this_one_change;
639 val1->change = change;
641 if (change > NO_CHANGE && val1->toolkit_data)
643 *change_p = 1;
644 if (val1->free_toolkit_data)
645 XtFree (val1->toolkit_data);
646 val1->toolkit_data = NULL;
649 return val1;
653 /* modifying the widgets */
654 static Widget
655 name_to_widget (instance, name)
656 widget_instance* instance;
657 char* name;
659 Widget widget = NULL;
661 if (!instance->widget)
662 return NULL;
664 if (!strcmp (XtName (instance->widget), name))
665 widget = instance->widget;
666 else
668 int length = strlen (name) + 2;
669 char* real_name = (char *) xmalloc (length);
670 real_name [0] = '*';
671 strcpy (real_name + 1, name);
673 widget = XtNameToWidget (instance->widget, real_name);
675 free (real_name);
677 return widget;
680 static void
681 set_one_value (instance, val, deep_p)
682 widget_instance* instance;
683 widget_value* val;
684 Boolean deep_p;
686 Widget widget = name_to_widget (instance, val->name);
688 if (widget)
690 #if defined (USE_LUCID)
691 if (lw_lucid_widget_p (instance->widget))
692 xlw_update_one_widget (instance, widget, val, deep_p);
693 #endif
694 #if defined (USE_MOTIF)
695 if (lw_motif_widget_p (instance->widget))
696 xm_update_one_widget (instance, widget, val, deep_p);
697 #endif
698 #if defined (USE_OLIT)
699 if (lw_olit_widget_p (instance->widget))
700 xol_update_one_widget (instance, widget, val, deep_p);
701 #endif
702 #if defined (USE_XAW)
703 if (lw_xaw_widget_p (instance->widget))
704 xaw_update_one_widget (instance, widget, val, deep_p);
705 #endif
709 static void
710 update_one_widget_instance (instance, deep_p)
711 widget_instance* instance;
712 Boolean deep_p;
714 widget_value *val;
716 if (!instance->widget)
717 /* the widget was destroyed */
718 return;
720 for (val = instance->info->val; val; val = val->next)
721 if (val->change != NO_CHANGE)
722 set_one_value (instance, val, deep_p);
725 static void
726 update_all_widget_values (info, deep_p)
727 widget_info* info;
728 Boolean deep_p;
730 widget_instance* instance;
731 widget_value* val;
733 for (instance = info->instances; instance; instance = instance->next)
734 update_one_widget_instance (instance, deep_p);
736 for (val = info->val; val; val = val->next)
737 val->change = NO_CHANGE;
741 lw_modify_all_widgets (id, val, deep_p)
742 LWLIB_ID id;
743 widget_value* val;
744 Boolean deep_p;
746 widget_info* info = get_widget_info (id, False);
747 widget_value* new_val;
748 widget_value* next_new_val;
749 widget_value* cur;
750 widget_value* prev;
751 widget_value* next;
752 int found;
753 int change_p = 0;
755 if (!info)
756 return 0;
758 for (new_val = val; new_val; new_val = new_val->next)
760 next_new_val = new_val->next;
761 new_val->next = NULL;
762 found = False;
763 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
764 if (!strcmp (cur->name, new_val->name))
766 found = True;
767 next = cur->next;
768 cur->next = NULL;
769 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1,
770 &change_p);
771 if (prev)
772 prev->next = cur ? cur : next;
773 else
774 info->val = cur ? cur : next;
775 if (cur)
776 cur->next = next;
777 break;
779 if (!found)
781 /* Could not find it, add it */
782 if (prev)
783 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
784 else
785 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
786 change_p = 1;
788 new_val->next = next_new_val;
791 update_all_widget_values (info, deep_p);
792 return change_p;
796 /* creating the widgets */
798 static void
799 initialize_widget_instance (instance)
800 widget_instance* instance;
802 widget_value* val;
804 for (val = instance->info->val; val; val = val->next)
805 val->change = STRUCTURAL_CHANGE;
807 update_one_widget_instance (instance, True);
809 for (val = instance->info->val; val; val = val->next)
810 val->change = NO_CHANGE;
814 static widget_creation_function
815 find_in_table (type, table)
816 char* type;
817 widget_creation_entry* table;
819 widget_creation_entry* cur;
820 for (cur = table; cur->type; cur++)
821 if (!my_strcasecmp (type, cur->type))
822 return cur->function;
823 return NULL;
826 static Boolean
827 dialog_spec_p (name)
828 char* name;
830 /* return True if name matches [EILPQeilpq][1-9][Bb] or
831 [EILPQeilpq][1-9][Bb][Rr][1-9] */
832 if (!name)
833 return False;
835 switch (name [0])
837 case 'E': case 'I': case 'L': case 'P': case 'Q':
838 case 'e': case 'i': case 'l': case 'p': case 'q':
839 if (name [1] >= '0' && name [1] <= '9')
841 if (name [2] != 'B' && name [2] != 'b')
842 return False;
843 if (!name [3])
844 return True;
845 if ((name [3] == 'T' || name [3] == 't') && !name [4])
846 return True;
847 if ((name [3] == 'R' || name [3] == 'r')
848 && name [4] >= '0' && name [4] <= '9' && !name [5])
849 return True;
850 return False;
852 else
853 return False;
855 default:
856 return False;
860 static void
861 instantiate_widget_instance (instance)
862 widget_instance* instance;
864 widget_creation_function function = NULL;
866 #if defined (USE_LUCID)
867 if (!function)
868 function = find_in_table (instance->info->type, xlw_creation_table);
869 #endif
870 #if defined(USE_MOTIF)
871 if (!function)
872 function = find_in_table (instance->info->type, xm_creation_table);
873 #endif
874 #if defined (USE_OLIT)
875 if (!function)
876 function = find_in_table (instance->info->type, xol_creation_table);
877 #endif
878 #if defined (USE_XAW)
879 if (!function)
880 function = find_in_table (instance->info->type, xaw_creation_table);
881 #endif
883 if (!function)
885 if (dialog_spec_p (instance->info->type))
887 #if defined (USE_LUCID)
888 /* not yet */
889 #endif
890 #if defined(USE_MOTIF)
891 if (!function)
892 function = xm_create_dialog;
893 #endif
894 #if defined (USE_XAW)
895 if (!function)
896 function = xaw_create_dialog;
897 #endif
898 #if defined (USE_OLIT)
899 /* not yet */
900 #endif
904 if (!function)
906 printf ("No creation function for widget type %s\n",
907 instance->info->type);
908 abort ();
911 instance->widget = (*function) (instance);
913 if (!instance->widget)
914 abort ();
916 /* XtRealizeWidget (instance->widget);*/
919 void
920 lw_register_widget (type, name, id, val, pre_activate_cb,
921 selection_cb, post_activate_cb, highlight_cb)
922 char* type;
923 char* name;
924 LWLIB_ID id;
925 widget_value* val;
926 lw_callback pre_activate_cb;
927 lw_callback selection_cb;
928 lw_callback post_activate_cb;
929 lw_callback highlight_cb;
931 if (!get_widget_info (id, False))
932 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
933 post_activate_cb, highlight_cb);
936 Widget
937 lw_get_widget (id, parent, pop_up_p)
938 LWLIB_ID id;
939 Widget parent;
940 Boolean pop_up_p;
942 widget_instance* instance;
944 instance = find_instance (id, parent, pop_up_p);
945 return instance ? instance->widget : NULL;
948 Widget
949 lw_make_widget (id, parent, pop_up_p)
950 LWLIB_ID id;
951 Widget parent;
952 Boolean pop_up_p;
954 widget_instance* instance;
955 widget_info* info;
957 instance = find_instance (id, parent, pop_up_p);
958 if (!instance)
960 info = get_widget_info (id, False);
961 if (!info)
962 return NULL;
963 instance = allocate_widget_instance (info, parent, pop_up_p);
964 initialize_widget_instance (instance);
966 if (!instance->widget)
967 abort ();
968 return instance->widget;
971 Widget
972 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb,
973 selection_cb, post_activate_cb, highlight_cb)
974 char* type;
975 char* name;
976 LWLIB_ID id;
977 widget_value* val;
978 Widget parent;
979 Boolean pop_up_p;
980 lw_callback pre_activate_cb;
981 lw_callback selection_cb;
982 lw_callback post_activate_cb;
983 lw_callback highlight_cb;
985 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
986 post_activate_cb, highlight_cb);
987 return lw_make_widget (id, parent, pop_up_p);
991 /* destroying the widgets */
992 static void
993 destroy_one_instance (instance)
994 widget_instance* instance;
996 /* Remove the destroy callback on the widget; that callback will try to
997 dereference the instance object (to set its widget slot to 0, since the
998 widget is dead.) Since the instance is now dead, we don't have to worry
999 about the fact that its widget is dead too.
1001 This happens in the Phase2Destroy of the widget, so this callback would
1002 not have been run until arbitrarily long after the instance was freed.
1004 if (instance->widget)
1005 XtRemoveCallback (instance->widget, XtNdestroyCallback,
1006 mark_widget_destroyed, (XtPointer)instance);
1008 if (instance->widget)
1010 /* The else are pretty tricky here, including the empty statement
1011 at the end because it would be very bad to destroy a widget
1012 twice. */
1013 #if defined (USE_LUCID)
1014 if (lw_lucid_widget_p (instance->widget))
1015 xlw_destroy_instance (instance);
1016 else
1017 #endif
1018 #if defined (USE_MOTIF)
1019 if (lw_motif_widget_p (instance->widget))
1020 xm_destroy_instance (instance);
1021 else
1022 #endif
1023 #if defined (USE_OLIT)
1024 if (lw_olit_widget_p (instance->widget))
1025 xol_destroy_instance (instance);
1026 else
1027 #endif
1028 #if defined (USE_XAW)
1029 if (lw_xaw_widget_p (instance->widget))
1030 xaw_destroy_instance (instance);
1031 else
1032 #endif
1033 /* do not remove the empty statement */
1037 free_widget_instance (instance);
1040 void
1041 lw_destroy_widget (w)
1042 Widget w;
1044 widget_instance* instance = get_widget_instance (w, True);
1046 if (instance)
1048 widget_info *info = instance->info;
1049 /* instance has already been removed from the list; free it */
1050 destroy_one_instance (instance);
1051 /* if there are no instances left, free the info too */
1052 if (!info->instances)
1053 lw_destroy_all_widgets (info->id);
1057 void
1058 lw_destroy_all_widgets (id)
1059 LWLIB_ID id;
1061 widget_info* info = get_widget_info (id, True);
1062 widget_instance* instance;
1063 widget_instance* next;
1065 if (info)
1067 for (instance = info->instances; instance; )
1069 next = instance->next;
1070 destroy_one_instance (instance);
1071 instance = next;
1073 free_widget_info (info);
1077 void
1078 lw_destroy_everything ()
1080 while (all_widget_info)
1081 lw_destroy_all_widgets (all_widget_info->id);
1084 void
1085 lw_destroy_all_pop_ups ()
1087 widget_info* info;
1088 widget_info* next;
1089 widget_instance* instance;
1091 for (info = all_widget_info; info; info = next)
1093 next = info->next;
1094 instance = info->instances;
1095 if (instance && instance->pop_up_p)
1096 lw_destroy_all_widgets (info->id);
1100 #ifdef USE_MOTIF
1101 extern Widget first_child (/* Widget */); /* garbage */
1102 #endif
1104 Widget
1105 lw_raise_all_pop_up_widgets ()
1107 widget_info* info;
1108 widget_instance* instance;
1109 Widget result = NULL;
1111 for (info = all_widget_info; info; info = info->next)
1112 for (instance = info->instances; instance; instance = instance->next)
1113 if (instance->pop_up_p)
1115 Widget widget = instance->widget;
1116 if (widget)
1118 if (XtIsManaged (widget)
1119 #ifdef USE_MOTIF
1120 /* What a complete load of crap!!!!
1121 When a dialogShell is on the screen, it is not managed!
1123 || (lw_motif_widget_p (instance->widget) &&
1124 XtIsManaged (first_child (widget)))
1125 #endif
1128 if (!result)
1129 result = widget;
1130 XMapRaised (XtDisplay (widget), XtWindow (widget));
1134 return result;
1137 static void
1138 lw_pop_all_widgets (id, up)
1139 LWLIB_ID id;
1140 Boolean up;
1142 widget_info* info = get_widget_info (id, False);
1143 widget_instance* instance;
1145 if (info)
1146 for (instance = info->instances; instance; instance = instance->next)
1147 if (instance->pop_up_p && instance->widget)
1149 #if defined (USE_LUCID)
1150 if (lw_lucid_widget_p (instance->widget))
1152 XtRealizeWidget (instance->widget);
1153 xlw_pop_instance (instance, up);
1155 #endif
1156 #if defined (USE_MOTIF)
1157 if (lw_motif_widget_p (instance->widget))
1159 XtRealizeWidget (instance->widget);
1160 xm_pop_instance (instance, up);
1162 #endif
1163 #if defined (USE_OLIT)
1164 if (lw_olit_widget_p (instance->widget))
1166 XtRealizeWidget (instance->widget);
1167 xol_pop_instance (instance, up);
1169 #endif
1170 #if defined (USE_XAW)
1171 if (lw_xaw_widget_p (instance->widget))
1173 XtRealizeWidget (XtParent (instance->widget));
1174 XtRealizeWidget (instance->widget);
1175 xaw_pop_instance (instance, up);
1177 #endif
1181 void
1182 lw_pop_up_all_widgets (id)
1183 LWLIB_ID id;
1185 lw_pop_all_widgets (id, True);
1188 void
1189 lw_pop_down_all_widgets (id)
1190 LWLIB_ID id;
1192 lw_pop_all_widgets (id, False);
1195 void
1196 lw_popup_menu (widget, event)
1197 Widget widget;
1198 XEvent *event;
1200 #if defined (USE_LUCID)
1201 if (lw_lucid_widget_p (widget))
1202 xlw_popup_menu (widget, event);
1203 #endif
1204 #if defined (USE_MOTIF)
1205 if (lw_motif_widget_p (widget))
1206 xm_popup_menu (widget, event);
1207 #endif
1208 #if defined (USE_OLIT)
1209 if (lw_olit_widget_p (widget))
1210 xol_popup_menu (widget, event);
1211 #endif
1212 #if defined (USE_XAW)
1213 if (lw_xaw_widget_p (widget))
1214 xaw_popup_menu (widget, event);
1215 #endif
1218 \f/* get the values back */
1219 static Boolean
1220 get_one_value (instance, val)
1221 widget_instance* instance;
1222 widget_value* val;
1224 Widget widget = name_to_widget (instance, val->name);
1226 if (widget)
1228 #if defined (USE_LUCID)
1229 if (lw_lucid_widget_p (instance->widget))
1230 xlw_update_one_value (instance, widget, val);
1231 #endif
1232 #if defined (USE_MOTIF)
1233 if (lw_motif_widget_p (instance->widget))
1234 xm_update_one_value (instance, widget, val);
1235 #endif
1236 #if defined (USE_OLIT)
1237 if (lw_olit_widget_p (instance->widget))
1238 xol_update_one_value (instance, widget, val);
1239 #endif
1240 #if defined (USE_XAW)
1241 if (lw_xaw_widget_p (instance->widget))
1242 xaw_update_one_value (instance, widget, val);
1243 #endif
1244 return True;
1246 else
1247 return False;
1250 Boolean
1251 lw_get_some_values (id, val_out)
1252 LWLIB_ID id;
1253 widget_value* val_out;
1255 widget_info* info = get_widget_info (id, False);
1256 widget_instance* instance;
1257 widget_value* val;
1258 Boolean result = False;
1260 if (!info)
1261 return False;
1263 instance = info->instances;
1264 if (!instance)
1265 return False;
1267 for (val = val_out; val; val = val->next)
1268 if (get_one_value (instance, val))
1269 result = True;
1271 return result;
1274 widget_value*
1275 lw_get_all_values (id)
1276 LWLIB_ID id;
1278 widget_info* info = get_widget_info (id, False);
1279 widget_value* val = info->val;
1280 if (lw_get_some_values (id, val))
1281 return val;
1282 else
1283 return NULL;
1286 /* internal function used by the library dependent implementation to get the
1287 widget_value for a given widget in an instance */
1288 widget_value*
1289 lw_get_widget_value_for_widget (instance, w)
1290 widget_instance* instance;
1291 Widget w;
1293 char* name = XtName (w);
1294 widget_value* cur;
1295 for (cur = instance->info->val; cur; cur = cur->next)
1296 if (!strcmp (cur->name, name))
1297 return cur;
1298 return NULL;
1301 \f/* update other instances value when one thing changed */
1303 /* To forbid recursive calls */
1304 static Boolean lwlib_updating;
1306 /* This function can be used as a an XtCallback for the widgets that get
1307 modified to update other instances of the widgets. Closure should be the
1308 widget_instance. */
1309 void
1310 lw_internal_update_other_instances (widget, closure, call_data)
1311 Widget widget;
1312 XtPointer closure;
1313 XtPointer call_data;
1315 widget_instance* instance = (widget_instance*)closure;
1316 char* name = XtName (widget);
1317 widget_info* info;
1318 widget_instance* cur;
1319 widget_value* val;
1321 /* Avoid possibly infinite recursion. */
1322 if (lwlib_updating)
1323 return;
1325 /* protect against the widget being destroyed */
1326 if (XtWidgetBeingDestroyedP (widget))
1327 return;
1329 /* Return immediately if there are no other instances */
1330 info = instance->info;
1331 if (!info->instances->next)
1332 return;
1334 lwlib_updating = True;
1336 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1338 if (val && get_one_value (instance, val))
1339 for (cur = info->instances; cur; cur = cur->next)
1340 if (cur != instance)
1341 set_one_value (cur, val, True);
1343 lwlib_updating = False;
1347 \f/* get the id */
1349 LWLIB_ID
1350 lw_get_widget_id (w)
1351 Widget w;
1353 widget_instance* instance = get_widget_instance (w, False);
1355 return instance ? instance->info->id : 0;
1358 \f/* set the keyboard focus */
1359 void
1360 lw_set_keyboard_focus (parent, w)
1361 Widget parent;
1362 Widget w;
1364 #if defined (USE_MOTIF)
1365 xm_set_keyboard_focus (parent, w);
1366 #else
1367 XtSetKeyboardFocus (parent, w);
1368 #endif
1371 \f/* Show busy */
1372 static void
1373 show_one_widget_busy (w, flag)
1374 Widget w;
1375 Boolean flag;
1377 Pixel foreground = 0;
1378 Pixel background = 1;
1379 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1380 if (!widget_to_invert)
1381 widget_to_invert = w;
1383 XtVaGetValues (widget_to_invert,
1384 XtNforeground, &foreground,
1385 XtNbackground, &background,
1386 NULL);
1387 XtVaSetValues (widget_to_invert,
1388 XtNforeground, background,
1389 XtNbackground, foreground,
1390 NULL);
1393 void
1394 lw_show_busy (w, busy)
1395 Widget w;
1396 Boolean busy;
1398 widget_instance* instance = get_widget_instance (w, False);
1399 widget_info* info;
1400 widget_instance* next;
1402 if (instance)
1404 info = instance->info;
1405 if (info->busy != busy)
1407 for (next = info->instances; next; next = next->next)
1408 if (next->widget)
1409 show_one_widget_busy (next->widget, busy);
1410 info->busy = busy;
1415 /* This hack exists because Lucid/Athena need to execute the strange
1416 function below to support geometry management. */
1417 void
1418 lw_refigure_widget (w, doit)
1419 Widget w;
1420 Boolean doit;
1422 #if defined (USE_XAW)
1423 XawPanedSetRefigureMode (w, doit);
1424 #endif
1425 #if defined (USE_MOTIF)
1426 if (doit)
1427 XtManageChild (w);
1428 else
1429 XtUnmanageChild (w);
1430 #endif
1433 /* Toolkit independent way of determining if an event window is in the
1434 menubar. */
1435 Boolean
1436 lw_window_is_in_menubar (win, menubar_widget)
1437 Window win;
1438 Widget menubar_widget;
1440 return menubar_widget
1441 #if defined (USE_LUCID)
1442 && XtWindow (menubar_widget) == win;
1443 #endif
1444 #if defined (USE_MOTIF)
1445 && ((XtWindow (menubar_widget) == win)
1446 || (XtWindowToWidget (XtDisplay (menubar_widget), win)
1447 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
1448 == menubar_widget)));
1449 #endif
1452 /* Motif hack to set the main window areas. */
1453 void
1454 lw_set_main_areas (parent, menubar, work_area)
1455 Widget parent;
1456 Widget menubar;
1457 Widget work_area;
1459 #if defined (USE_MOTIF)
1460 xm_set_main_areas (parent, menubar, work_area);
1461 #endif
1464 /* Manage resizing for Motif. This disables resizing when the menubar
1465 is about to be modified. */
1466 void
1467 lw_allow_resizing (w, flag)
1468 Widget w;
1469 Boolean flag;
1471 #if defined (USE_MOTIF)
1472 xm_manage_resizing (w, flag);
1473 #endif
1477 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1478 set to an appropriate enumerator of type enum menu_separator.
1479 MOTIF_P non-zero means map separator types not supported by Motif
1480 to similar ones that are supported. */
1483 lw_separator_p (label, type, motif_p)
1484 char *label;
1485 enum menu_separator *type;
1486 int motif_p;
1488 int separator_p = 0;
1490 if (strlen (label) >= 3
1491 && bcmp (label, "--:", 3) == 0)
1493 static struct separator_table
1495 char *name;
1496 enum menu_separator type;
1498 separator_names[] =
1500 "space", SEPARATOR_NO_LINE,
1501 "noLine", SEPARATOR_NO_LINE,
1502 "singleLine", SEPARATOR_SINGLE_LINE,
1503 "doubleLine", SEPARATOR_DOUBLE_LINE,
1504 "singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE,
1505 "doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE,
1506 "shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN,
1507 "shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT,
1508 "shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH,
1509 "shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH,
1510 "shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN,
1511 "shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT,
1512 "shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH,
1513 "shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH,
1517 int i;
1519 label += 3;
1520 for (i = 0; separator_names[i].name; ++i)
1521 if (strcmp (label, separator_names[i].name) == 0)
1523 separator_p = 1;
1524 *type = separator_names[i].type;
1526 /* If separator type is not supported under Motif,
1527 use a similar one. */
1528 if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
1529 *type -= 4;
1530 break;
1533 else if (strlen (label) > 3
1534 && bcmp (label, "--", 2) == 0
1535 && label[2] != '-')
1537 /* Alternative, more Emacs-style names. */
1538 static struct separator_table
1540 char *name;
1541 enum menu_separator type;
1543 separator_names[] =
1545 "space", SEPARATOR_NO_LINE,
1546 "no-line", SEPARATOR_NO_LINE,
1547 "single-line", SEPARATOR_SINGLE_LINE,
1548 "double-line", SEPARATOR_DOUBLE_LINE,
1549 "single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE,
1550 "double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE,
1551 "shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN,
1552 "shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT,
1553 "shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH,
1554 "shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH,
1555 "shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN,
1556 "shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT,
1557 "shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH,
1558 "shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH,
1562 int i;
1564 label += 2;
1565 for (i = 0; separator_names[i].name; ++i)
1566 if (strcmp (label, separator_names[i].name) == 0)
1568 separator_p = 1;
1569 *type = separator_names[i].type;
1571 /* If separator type is not supported under Motif,
1572 use a similar one. */
1573 if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
1574 *type -= 4;
1575 break;
1578 else
1580 /* Old-style separator, maybe. It's a separator if it contains
1581 only dashes. */
1582 while (*label == '-')
1583 ++label;
1584 separator_p = *label == 0;
1585 *type = SEPARATOR_SHADOW_ETCHED_IN;
1588 return separator_p;