]> code.delx.au - gnu-emacs/blob - lwlib/lwlib.c
(*): remove function prototypes.
[gnu-emacs] / lwlib / lwlib.c
1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
3
4 This file is part of the Lucid Widget Library.
5
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.
10
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.
15
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #ifdef NeXT
21 #undef __STRICT_BSD__ /* ick */
22 #endif
23
24 #include <sys/types.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include "lwlib-int.h"
28 #include "lwlib-utils.h"
29 #include <X11/StringDefs.h>
30
31 #if defined (USE_LUCID)
32 #include "lwlib-Xlw.h"
33 #endif
34 #if defined (USE_MOTIF)
35 #include "lwlib-Xm.h"
36 #else /* not USE_MOTIF */
37 #if defined (USE_LUCID)
38 #define USE_XAW
39 #endif /* not USE_MOTIF && USE_LUCID */
40 #endif
41 #if defined (USE_OLIT)
42 #include "lwlib-Xol.h"
43 #endif
44 #if defined (USE_XAW)
45 #include "lwlib-Xaw.h"
46 #endif
47
48 #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
49 ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
50 #endif
51
52 #if defined (USE_MOTIF) && defined (USE_OLIT)
53 ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
54 #endif
55
56 #ifndef max
57 #define max(x, y) ((x) > (y) ? (x) : (y))
58 #endif
59
60 /* List of all widgets managed by the library. */
61 static widget_info*
62 all_widget_info = NULL;
63
64 \f/* Forward declarations */
65 static void
66 instanciate_widget_instance (/* widget_instance* instance */);
67
68 lwlib_memset (address, value, length)
69 char *address;
70 int value;
71 int length;
72 {
73 int i;
74
75 for (i = 0; i < length; i++)
76 address[i] = value;
77 }
78
79 lwlib_bcopy (from, to, length)
80 char *from;
81 char *to;
82 int length;
83 {
84 int i;
85
86 for (i = 0; i < length; i++)
87 to[i] = from[i];
88 }
89 \f/* utility functions for widget_instance and widget_info */
90 char *
91 safe_strdup (s)
92 char *s;
93 {
94 char *result;
95 if (! s) return 0;
96 result = (char *) malloc (strlen (s) + 1);
97 if (! result)
98 return 0;
99 strcpy (result, s);
100 return result;
101 }
102
103 /* Like strcmp but ignore differences in case. */
104
105 static int
106 my_strcasecmp (s1, s2)
107 char *s1, *s2;
108 {
109 while (1)
110 {
111 int c1 = *s1++;
112 int c2 = *s2++;
113 if (isupper (c1))
114 c1 = tolower (c1);
115 if (isupper (c2))
116 c2 = tolower (c2);
117 if (c1 != c2)
118 return (c1 > c2 ? 1 : -1);
119 if (c1 == 0)
120 return 0;
121 }
122 }
123
124 static void
125 safe_free_str (s)
126 char *s;
127 {
128 if (s) free (s);
129 }
130
131 static widget_value *widget_value_free_list = 0;
132 static int malloc_cpt = 0;
133
134 widget_value *
135 malloc_widget_value ()
136 {
137 widget_value *wv;
138 if (widget_value_free_list)
139 {
140 wv = widget_value_free_list;
141 widget_value_free_list = wv->free_list;
142 wv->free_list = 0;
143 }
144 else
145 {
146 wv = (widget_value *) malloc (sizeof (widget_value));
147 malloc_cpt++;
148 }
149 lwlib_memset (wv, 0, sizeof (widget_value));
150 return wv;
151 }
152
153 /* this is analagous to free(). It frees only what was allocated
154 by malloc_widget_value(), and no substructures.
155 */
156 void
157 free_widget_value (wv)
158 widget_value *wv;
159 {
160 if (wv->free_list)
161 abort ();
162
163 if (malloc_cpt > 25)
164 {
165 /* When the number of already allocated cells is too big,
166 We free it. */
167 free (wv);
168 malloc_cpt--;
169 }
170 else
171 {
172 wv->free_list = widget_value_free_list;
173 widget_value_free_list = wv;
174 }
175 }
176
177 static void
178 free_widget_value_tree (wv)
179 widget_value *wv;
180 {
181 if (!wv)
182 return;
183
184 if (wv->name) free (wv->name);
185 if (wv->value) free (wv->value);
186 if (wv->key) free (wv->key);
187
188 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
189
190 if (wv->toolkit_data && wv->free_toolkit_data)
191 {
192 free (wv->toolkit_data);
193 wv->toolkit_data = (void *) 0xDEADBEEF;
194 }
195
196 if (wv->contents && (wv->contents != (widget_value*)1))
197 {
198 free_widget_value_tree (wv->contents);
199 wv->contents = (widget_value *) 0xDEADBEEF;
200 }
201 if (wv->next)
202 {
203 free_widget_value_tree (wv->next);
204 wv->next = (widget_value *) 0xDEADBEEF;
205 }
206 free_widget_value (wv);
207 }
208
209 static widget_value *
210 copy_widget_value_tree (val, change)
211 widget_value* val;
212 change_type change;
213 {
214 widget_value* copy;
215
216 if (!val)
217 return NULL;
218 if (val == (widget_value *) 1)
219 return val;
220
221 copy = malloc_widget_value ();
222 copy->name = safe_strdup (val->name);
223 copy->value = safe_strdup (val->value);
224 copy->key = safe_strdup (val->key);
225 copy->enabled = val->enabled;
226 copy->selected = val->selected;
227 copy->edited = False;
228 copy->change = change;
229 copy->contents = copy_widget_value_tree (val->contents, change);
230 copy->call_data = val->call_data;
231 copy->next = copy_widget_value_tree (val->next, change);
232 copy->toolkit_data = NULL;
233 copy->free_toolkit_data = False;
234 return copy;
235 }
236
237 static widget_info *
238 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
239 char* type;
240 char* name;
241 LWLIB_ID id;
242 widget_value* val;
243 lw_callback pre_activate_cb;
244 lw_callback selection_cb;
245 lw_callback post_activate_cb;
246 {
247 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
248 info->type = safe_strdup (type);
249 info->name = safe_strdup (name);
250 info->id = id;
251 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
252 info->busy = False;
253 info->pre_activate_cb = pre_activate_cb;
254 info->selection_cb = selection_cb;
255 info->post_activate_cb = post_activate_cb;
256 info->instances = NULL;
257
258 info->next = all_widget_info;
259 all_widget_info = info;
260
261 return info;
262 }
263
264 static void
265 free_widget_info (info)
266 widget_info* info;
267 {
268 safe_free_str (info->type);
269 safe_free_str (info->name);
270 free_widget_value_tree (info->val);
271 lwlib_memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
272 free (info);
273 }
274
275 static void
276 mark_widget_destroyed (widget, closure, call_data)
277 Widget widget;
278 XtPointer closure;
279 XtPointer call_data;
280 {
281 widget_instance* instance = (widget_instance*)closure;
282
283 /* be very conservative */
284 if (instance->widget == widget)
285 instance->widget = NULL;
286 }
287
288 static widget_instance *
289 allocate_widget_instance (info, parent, pop_up_p)
290 widget_info* info;
291 Widget parent;
292 Boolean pop_up_p;
293 {
294 widget_instance* instance =
295 (widget_instance*)malloc (sizeof (widget_instance));
296 instance->parent = parent;
297 instance->pop_up_p = pop_up_p;
298 instance->info = info;
299 instance->next = info->instances;
300 info->instances = instance;
301
302 instanciate_widget_instance (instance);
303
304 XtAddCallback (instance->widget, XtNdestroyCallback,
305 mark_widget_destroyed, (XtPointer)instance);
306 return instance;
307 }
308
309 static void
310 free_widget_instance (instance)
311 widget_instance* instance;
312 {
313 lwlib_memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
314 free (instance);
315 }
316
317 static widget_info *
318 get_widget_info (id, remove_p)
319 LWLIB_ID id;
320 Boolean remove_p;
321 {
322 widget_info* info;
323 widget_info* prev;
324 for (prev = NULL, info = all_widget_info;
325 info;
326 prev = info, info = info->next)
327 if (info->id == id)
328 {
329 if (remove_p)
330 {
331 if (prev)
332 prev->next = info->next;
333 else
334 all_widget_info = info->next;
335 }
336 return info;
337 }
338 return NULL;
339 }
340
341 /* Internal function used by the library dependent implementation to get the
342 widget_value for a given widget in an instance */
343 widget_info *
344 lw_get_widget_info (id)
345 LWLIB_ID id;
346 {
347 return get_widget_info (id, 0);
348 }
349
350 static widget_instance *
351 get_widget_instance (widget, remove_p)
352 Widget widget;
353 Boolean remove_p;
354 {
355 widget_info* info;
356 widget_instance* instance;
357 widget_instance* prev;
358 for (info = all_widget_info; info; info = info->next)
359 for (prev = NULL, instance = info->instances;
360 instance;
361 prev = instance, instance = instance->next)
362 if (instance->widget == widget)
363 {
364 if (remove_p)
365 {
366 if (prev)
367 prev->next = instance->next;
368 else
369 info->instances = instance->next;
370 }
371 return instance;
372 }
373 return (widget_instance *) 0;
374 }
375
376 static widget_instance*
377 find_instance (id, parent, pop_up_p)
378 LWLIB_ID id;
379 Widget parent;
380 Boolean pop_up_p;
381 {
382 widget_info* info = get_widget_info (id, False);
383 widget_instance* instance;
384
385 if (info)
386 for (instance = info->instances; instance; instance = instance->next)
387 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
388 return instance;
389
390 return NULL;
391 }
392
393 \f
394 /* utility function for widget_value */
395 static Boolean
396 safe_strcmp (s1, s2)
397 char* s1;
398 char* s2;
399 {
400 if (!!s1 ^ !!s2) return True;
401 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
402 }
403
404
405 #if 0
406 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
407 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
408 name, \
409 (oc == NO_CHANGE ? "none" : \
410 (oc == INVISIBLE_CHANGE ? "invisible" : \
411 (oc == VISIBLE_CHANGE ? "visible" : \
412 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
413 oc, \
414 (nc == NO_CHANGE ? "none" : \
415 (nc == INVISIBLE_CHANGE ? "invisible" : \
416 (nc == VISIBLE_CHANGE ? "visible" : \
417 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
418 nc, desc, a1, a2)
419 #else
420 # define EXPLAIN(name, oc, nc, desc, a1, a2)
421 #endif
422
423
424 static widget_value *
425 merge_widget_value (val1, val2, level)
426 widget_value* val1;
427 widget_value* val2;
428 int level;
429 {
430 change_type change;
431 widget_value* merged_next;
432 widget_value* merged_contents;
433
434 if (!val1)
435 {
436 if (val2)
437 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
438 else
439 return NULL;
440 }
441 if (!val2)
442 {
443 free_widget_value_tree (val1);
444 return NULL;
445 }
446
447 change = NO_CHANGE;
448
449 if (safe_strcmp (val1->name, val2->name))
450 {
451 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
452 val1->name, val2->name);
453 change = max (change, STRUCTURAL_CHANGE);
454 safe_free_str (val1->name);
455 val1->name = safe_strdup (val2->name);
456 }
457 if (safe_strcmp (val1->value, val2->value))
458 {
459 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
460 val1->value, val2->value);
461 change = max (change, VISIBLE_CHANGE);
462 safe_free_str (val1->value);
463 val1->value = safe_strdup (val2->value);
464 }
465 if (safe_strcmp (val1->key, val2->key))
466 {
467 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
468 val1->key, val2->key);
469 change = max (change, VISIBLE_CHANGE);
470 safe_free_str (val1->key);
471 val1->key = safe_strdup (val2->key);
472 }
473 if (val1->enabled != val2->enabled)
474 {
475 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
476 val1->enabled, val2->enabled);
477 change = max (change, VISIBLE_CHANGE);
478 val1->enabled = val2->enabled;
479 }
480 if (val1->selected != val2->selected)
481 {
482 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
483 val1->selected, val2->selected);
484 change = max (change, VISIBLE_CHANGE);
485 val1->selected = val2->selected;
486 }
487 if (val1->call_data != val2->call_data)
488 {
489 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
490 val1->call_data, val2->call_data);
491 change = max (change, INVISIBLE_CHANGE);
492 val1->call_data = val2->call_data;
493 }
494
495 if (level > 0)
496 {
497 merged_contents =
498 merge_widget_value (val1->contents, val2->contents, level - 1);
499
500 if (val1->contents && !merged_contents)
501 {
502 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
503 0, 0);
504 change = max (change, INVISIBLE_CHANGE);
505 }
506 else if (merged_contents && merged_contents->change != NO_CHANGE)
507 {
508 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
509 0, 0);
510 change = max (change, INVISIBLE_CHANGE);
511 }
512
513 val1->contents = merged_contents;
514 }
515
516 merged_next = merge_widget_value (val1->next, val2->next, level);
517
518 if (val1->next && !merged_next)
519 {
520 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
521 0, 0);
522 change = max (change, STRUCTURAL_CHANGE);
523 }
524 else if (merged_next)
525 {
526 if (merged_next->change)
527 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
528 0, 0);
529 change = max (change, merged_next->change);
530 }
531
532 val1->next = merged_next;
533
534 val1->change = change;
535
536 if (change > NO_CHANGE && val1->toolkit_data)
537 {
538 if (val1->free_toolkit_data)
539 free (val1->toolkit_data);
540 val1->toolkit_data = NULL;
541 }
542
543 return val1;
544 }
545
546 \f
547 /* modifying the widgets */
548 static Widget
549 name_to_widget (instance, name)
550 widget_instance* instance;
551 char* name;
552 {
553 Widget widget = NULL;
554
555 if (!instance->widget)
556 return NULL;
557
558 if (!strcmp (XtName (instance->widget), name))
559 widget = instance->widget;
560 else
561 {
562 int length = strlen (name) + 2;
563 char* real_name = (char *) xmalloc (length);
564 real_name [0] = '*';
565 strcpy (real_name + 1, name);
566
567 widget = XtNameToWidget (instance->widget, real_name);
568
569 free (real_name);
570 }
571 return widget;
572 }
573
574 static void
575 set_one_value (instance, val, deep_p)
576 widget_instance* instance;
577 widget_value* val;
578 Boolean deep_p;
579 {
580 Widget widget = name_to_widget (instance, val->name);
581
582 if (widget)
583 {
584 #if defined (USE_LUCID)
585 if (lw_lucid_widget_p (instance->widget))
586 xlw_update_one_widget (instance, widget, val, deep_p);
587 #endif
588 #if defined (USE_MOTIF)
589 if (lw_motif_widget_p (instance->widget))
590 xm_update_one_widget (instance, widget, val, deep_p);
591 #endif
592 #if defined (USE_OLIT)
593 if (lw_olit_widget_p (instance->widget))
594 xol_update_one_widget (instance, widget, val, deep_p);
595 #endif
596 #if defined (USE_XAW)
597 if (lw_xaw_widget_p (instance->widget))
598 xaw_update_one_widget (instance, widget, val, deep_p);
599 #endif
600 }
601 }
602
603 static void
604 update_one_widget_instance (instance, deep_p)
605 widget_instance* instance;
606 Boolean deep_p;
607 {
608 widget_value *val;
609
610 if (!instance->widget)
611 /* the widget was destroyed */
612 return;
613
614 for (val = instance->info->val; val; val = val->next)
615 if (val->change != NO_CHANGE)
616 set_one_value (instance, val, deep_p);
617 }
618
619 static void
620 update_all_widget_values (info, deep_p)
621 widget_info* info;
622 Boolean deep_p;
623 {
624 widget_instance* instance;
625 widget_value* val;
626
627 for (instance = info->instances; instance; instance = instance->next)
628 update_one_widget_instance (instance, deep_p);
629
630 for (val = info->val; val; val = val->next)
631 val->change = NO_CHANGE;
632 }
633
634 void
635 lw_modify_all_widgets (id, val, deep_p)
636 LWLIB_ID id;
637 widget_value* val;
638 Boolean deep_p;
639 {
640 widget_info* info = get_widget_info (id, False);
641 widget_value* new_val;
642 widget_value* next_new_val;
643 widget_value* cur;
644 widget_value* prev;
645 widget_value* next;
646 int found;
647
648 if (!info)
649 return;
650
651 for (new_val = val; new_val; new_val = new_val->next)
652 {
653 next_new_val = new_val->next;
654 new_val->next = NULL;
655 found = False;
656 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
657 if (!strcmp (cur->name, new_val->name))
658 {
659 found = True;
660 next = cur->next;
661 cur->next = NULL;
662 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
663 if (prev)
664 prev->next = cur ? cur : next;
665 else
666 info->val = cur ? cur : next;
667 if (cur)
668 cur->next = next;
669 break;
670 }
671 if (!found)
672 {
673 /* Could not find it, add it */
674 if (prev)
675 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
676 else
677 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
678 }
679 new_val->next = next_new_val;
680 }
681
682 update_all_widget_values (info, deep_p);
683 }
684
685 \f
686 /* creating the widgets */
687
688 static void
689 initialize_widget_instance (instance)
690 widget_instance* instance;
691 {
692 widget_value* val;
693
694 for (val = instance->info->val; val; val = val->next)
695 val->change = STRUCTURAL_CHANGE;
696
697 update_one_widget_instance (instance, True);
698
699 for (val = instance->info->val; val; val = val->next)
700 val->change = NO_CHANGE;
701 }
702
703
704 static widget_creation_function
705 find_in_table (type, table)
706 char* type;
707 widget_creation_entry* table;
708 {
709 widget_creation_entry* cur;
710 for (cur = table; cur->type; cur++)
711 if (!my_strcasecmp (type, cur->type))
712 return cur->function;
713 return NULL;
714 }
715
716 static Boolean
717 dialog_spec_p (name)
718 char* name;
719 {
720 /* return True if name matches [EILPQeilpq][1-9][Bb] or
721 [EILPQeilpq][1-9][Bb][Rr][1-9] */
722 if (!name)
723 return False;
724
725 switch (name [0])
726 {
727 case 'E': case 'I': case 'L': case 'P': case 'Q':
728 case 'e': case 'i': case 'l': case 'p': case 'q':
729 if (name [1] >= '0' && name [1] <= '9')
730 {
731 if (name [2] != 'B' && name [2] != 'b')
732 return False;
733 if (!name [3])
734 return True;
735 if ((name [3] == 'T' || name [3] == 't') && !name [4])
736 return True;
737 if ((name [3] == 'R' || name [3] == 'r')
738 && name [4] >= '0' && name [4] <= '9' && !name [5])
739 return True;
740 return False;
741 }
742 else
743 return False;
744
745 default:
746 return False;
747 }
748 }
749
750 static void
751 instanciate_widget_instance (instance)
752 widget_instance* instance;
753 {
754 widget_creation_function function = NULL;
755
756 #if defined (USE_LUCID)
757 if (!function)
758 function = find_in_table (instance->info->type, xlw_creation_table);
759 #endif
760 #if defined(USE_MOTIF)
761 if (!function)
762 function = find_in_table (instance->info->type, xm_creation_table);
763 #endif
764 #if defined (USE_OLIT)
765 if (!function)
766 function = find_in_table (instance->info->type, xol_creation_table);
767 #endif
768 #if defined (USE_XAW)
769 if (!function)
770 function = find_in_table (instance->info->type, xaw_creation_table);
771 #endif
772
773 if (!function)
774 {
775 if (dialog_spec_p (instance->info->type))
776 {
777 #if defined (USE_LUCID)
778 /* not yet */
779 #endif
780 #if defined(USE_MOTIF)
781 if (!function)
782 function = xm_create_dialog;
783 #endif
784 #if defined (USE_XAW)
785 if (!function)
786 function = xaw_create_dialog;
787 #endif
788 #if defined (USE_OLIT)
789 /* not yet */
790 #endif
791 }
792 }
793
794 if (!function)
795 {
796 printf ("No creation function for widget type %s\n",
797 instance->info->type);
798 abort ();
799 }
800
801 instance->widget = (*function) (instance);
802
803 if (!instance->widget)
804 abort ();
805
806 /* XtRealizeWidget (instance->widget);*/
807 }
808
809 void
810 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, post_activate_cb)
811 char* type;
812 char* name;
813 LWLIB_ID id;
814 widget_value* val;
815 lw_callback pre_activate_cb;
816 lw_callback selection_cb;
817 lw_callback post_activate_cb;
818 {
819 if (!get_widget_info (id, False))
820 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
821 post_activate_cb);
822 }
823
824 Widget
825 lw_get_widget (id, parent, pop_up_p)
826 LWLIB_ID id;
827 Widget parent;
828 Boolean pop_up_p;
829 {
830 widget_instance* instance;
831
832 instance = find_instance (id, parent, pop_up_p);
833 return instance ? instance->widget : NULL;
834 }
835
836 Widget
837 lw_make_widget (id, parent, pop_up_p)
838 LWLIB_ID id;
839 Widget parent;
840 Boolean pop_up_p;
841 {
842 widget_instance* instance;
843 widget_info* info;
844
845 instance = find_instance (id, parent, pop_up_p);
846 if (!instance)
847 {
848 info = get_widget_info (id, False);
849 if (!info)
850 return NULL;
851 instance = allocate_widget_instance (info, parent, pop_up_p);
852 initialize_widget_instance (instance);
853 }
854 if (!instance->widget)
855 abort ();
856 return instance->widget;
857 }
858
859 Widget
860 lw_create_widget (type, name, id, val, parent, pop_up_p, pre_activate_cb, selection_cb, post_activate_cb)
861 char* type;
862 char* name;
863 LWLIB_ID id;
864 widget_value* val;
865 Widget parent;
866 Boolean pop_up_p;
867 lw_callback pre_activate_cb;
868 lw_callback selection_cb;
869 lw_callback post_activate_cb;
870 {
871 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
872 post_activate_cb);
873 return lw_make_widget (id, parent, pop_up_p);
874 }
875
876 \f
877 /* destroying the widgets */
878 static void
879 destroy_one_instance (instance)
880 widget_instance* instance;
881 {
882 /* Remove the destroy callback on the widget; that callback will try to
883 dereference the instance object (to set its widget slot to 0, since the
884 widget is dead.) Since the instance is now dead, we don't have to worry
885 about the fact that its widget is dead too.
886
887 This happens in the Phase2Destroy of the widget, so this callback would
888 not have been run until arbitrarily long after the instance was freed.
889 */
890 if (instance->widget)
891 XtRemoveCallback (instance->widget, XtNdestroyCallback,
892 mark_widget_destroyed, (XtPointer)instance);
893
894 if (instance->widget)
895 {
896 /* The else are pretty tricky here, including the empty statement
897 at the end because it would be very bad to destroy a widget
898 twice. */
899 #if defined (USE_LUCID)
900 if (lw_lucid_widget_p (instance->widget))
901 xlw_destroy_instance (instance);
902 else
903 #endif
904 #if defined (USE_MOTIF)
905 if (lw_motif_widget_p (instance->widget))
906 xm_destroy_instance (instance);
907 else
908 #endif
909 #if defined (USE_OLIT)
910 if (lw_olit_widget_p (instance->widget))
911 xol_destroy_instance (instance);
912 else
913 #endif
914 #if defined (USE_XAW)
915 if (lw_xaw_widget_p (instance->widget))
916 xaw_destroy_instance (instance);
917 else
918 #endif
919 /* do not remove the empty statement */
920 ;
921 }
922
923 free_widget_instance (instance);
924 }
925
926 void
927 lw_destroy_widget (w)
928 Widget w;
929 {
930 widget_instance* instance = get_widget_instance (w, True);
931
932 if (instance)
933 {
934 widget_info *info = instance->info;
935 /* instance has already been removed from the list; free it */
936 destroy_one_instance (instance);
937 /* if there are no instances left, free the info too */
938 if (!info->instances)
939 lw_destroy_all_widgets (info->id);
940 }
941 }
942
943 void
944 lw_destroy_all_widgets (id)
945 LWLIB_ID id;
946 {
947 widget_info* info = get_widget_info (id, True);
948 widget_instance* instance;
949 widget_instance* next;
950
951 if (info)
952 {
953 for (instance = info->instances; instance; )
954 {
955 next = instance->next;
956 destroy_one_instance (instance);
957 instance = next;
958 }
959 free_widget_info (info);
960 }
961 }
962
963 void
964 lw_destroy_everything ()
965 {
966 while (all_widget_info)
967 lw_destroy_all_widgets (all_widget_info->id);
968 }
969
970 void
971 lw_destroy_all_pop_ups ()
972 {
973 widget_info* info;
974 widget_info* next;
975 widget_instance* instance;
976
977 for (info = all_widget_info; info; info = next)
978 {
979 next = info->next;
980 instance = info->instances;
981 if (instance && instance->pop_up_p)
982 lw_destroy_all_widgets (info->id);
983 }
984 }
985
986 #ifdef USE_MOTIF
987 extern Widget first_child (Widget); /* garbage */
988 #endif
989
990 Widget
991 lw_raise_all_pop_up_widgets ()
992 {
993 widget_info* info;
994 widget_instance* instance;
995 Widget result = NULL;
996
997 for (info = all_widget_info; info; info = info->next)
998 for (instance = info->instances; instance; instance = instance->next)
999 if (instance->pop_up_p)
1000 {
1001 Widget widget = instance->widget;
1002 if (widget)
1003 {
1004 if (XtIsManaged (widget)
1005 #ifdef USE_MOTIF
1006 /* What a complete load of crap!!!!
1007 When a dialogShell is on the screen, it is not managed!
1008 */
1009 || (lw_motif_widget_p (instance->widget) &&
1010 XtIsManaged (first_child (widget)))
1011 #endif
1012 )
1013 {
1014 if (!result)
1015 result = widget;
1016 XMapRaised (XtDisplay (widget), XtWindow (widget));
1017 }
1018 }
1019 }
1020 return result;
1021 }
1022
1023 static void
1024 lw_pop_all_widgets (id, up)
1025 LWLIB_ID id;
1026 Boolean up;
1027 {
1028 widget_info* info = get_widget_info (id, False);
1029 widget_instance* instance;
1030
1031 if (info)
1032 for (instance = info->instances; instance; instance = instance->next)
1033 if (instance->pop_up_p && instance->widget)
1034 {
1035 #if defined (USE_LUCID)
1036 if (lw_lucid_widget_p (instance->widget))
1037 {
1038 XtRealizeWidget (instance->widget);
1039 xlw_pop_instance (instance, up);
1040 }
1041 #endif
1042 #if defined (USE_MOTIF)
1043 if (lw_motif_widget_p (instance->widget))
1044 {
1045 XtRealizeWidget (instance->widget);
1046 xm_pop_instance (instance, up);
1047 }
1048 #endif
1049 #if defined (USE_OLIT)
1050 if (lw_olit_widget_p (instance->widget))
1051 {
1052 XtRealizeWidget (instance->widget);
1053 xol_pop_instance (instance, up);
1054 }
1055 #endif
1056 #if defined (USE_XAW)
1057 if (lw_xaw_widget_p (instance->widget))
1058 {
1059 XtRealizeWidget (XtParent (instance->widget));
1060 XtRealizeWidget (instance->widget);
1061 xaw_pop_instance (instance, up);
1062 }
1063 #endif
1064 }
1065 }
1066
1067 void
1068 lw_pop_up_all_widgets (id)
1069 LWLIB_ID id;
1070 {
1071 lw_pop_all_widgets (id, True);
1072 }
1073
1074 void
1075 lw_pop_down_all_widgets (id)
1076 LWLIB_ID id;
1077 {
1078 lw_pop_all_widgets (id, False);
1079 }
1080
1081 void
1082 lw_popup_menu (widget)
1083 Widget widget;
1084 {
1085 #if defined (USE_LUCID)
1086 if (lw_lucid_widget_p (widget))
1087 xlw_popup_menu (widget);
1088 #endif
1089 #if defined (USE_MOTIF)
1090 if (lw_motif_widget_p (widget))
1091 xm_popup_menu (widget);
1092 #endif
1093 #if defined (USE_OLIT)
1094 if (lw_olit_widget_p (widget))
1095 xol_popup_menu (widget);
1096 #endif
1097 #if defined (USE_XAW)
1098 if (lw_xaw_widget_p (widget))
1099 xaw_popup_menu (widget);
1100 #endif
1101 }
1102
1103 \f/* get the values back */
1104 static Boolean
1105 get_one_value (instance, val)
1106 widget_instance* instance;
1107 widget_value* val;
1108 {
1109 Widget widget = name_to_widget (instance, val->name);
1110
1111 if (widget)
1112 {
1113 #if defined (USE_LUCID)
1114 if (lw_lucid_widget_p (instance->widget))
1115 xlw_update_one_value (instance, widget, val);
1116 #endif
1117 #if defined (USE_MOTIF)
1118 if (lw_motif_widget_p (instance->widget))
1119 xm_update_one_value (instance, widget, val);
1120 #endif
1121 #if defined (USE_OLIT)
1122 if (lw_olit_widget_p (instance->widget))
1123 xol_update_one_value (instance, widget, val);
1124 #endif
1125 #if defined (USE_XAW)
1126 if (lw_xaw_widget_p (instance->widget))
1127 xaw_update_one_value (instance, widget, val);
1128 #endif
1129 return True;
1130 }
1131 else
1132 return False;
1133 }
1134
1135 Boolean
1136 lw_get_some_values (id, val_out)
1137 LWLIB_ID id;
1138 widget_value* val_out;
1139 {
1140 widget_info* info = get_widget_info (id, False);
1141 widget_instance* instance;
1142 widget_value* val;
1143 Boolean result = False;
1144
1145 if (!info)
1146 return False;
1147
1148 instance = info->instances;
1149 if (!instance)
1150 return False;
1151
1152 for (val = val_out; val; val = val->next)
1153 if (get_one_value (instance, val))
1154 result = True;
1155
1156 return result;
1157 }
1158
1159 widget_value*
1160 lw_get_all_values (id)
1161 LWLIB_ID id;
1162 {
1163 widget_info* info = get_widget_info (id, False);
1164 widget_value* val = info->val;
1165 if (lw_get_some_values (id, val))
1166 return val;
1167 else
1168 return NULL;
1169 }
1170
1171 /* internal function used by the library dependent implementation to get the
1172 widget_value for a given widget in an instance */
1173 widget_value*
1174 lw_get_widget_value_for_widget (instance, w)
1175 widget_instance* instance;
1176 Widget w;
1177 {
1178 char* name = XtName (w);
1179 widget_value* cur;
1180 for (cur = instance->info->val; cur; cur = cur->next)
1181 if (!strcmp (cur->name, name))
1182 return cur;
1183 return NULL;
1184 }
1185
1186 \f/* update other instances value when one thing changed */
1187 /* This function can be used as a an XtCallback for the widgets that get
1188 modified to update other instances of the widgets. Closure should be the
1189 widget_instance. */
1190 void
1191 lw_internal_update_other_instances (widget, closure, call_data)
1192 Widget widget;
1193 XtPointer closure;
1194 XtPointer call_data;
1195 {
1196 /* To forbid recursive calls */
1197 static Boolean updating;
1198
1199 widget_instance* instance = (widget_instance*)closure;
1200 char* name = XtName (widget);
1201 widget_info* info;
1202 widget_instance* cur;
1203 widget_value* val;
1204
1205 /* never recurse as this could cause infinite recursions. */
1206 if (updating)
1207 return;
1208
1209 /* protect against the widget being destroyed */
1210 if (XtWidgetBeingDestroyedP (widget))
1211 return;
1212
1213 /* Return immediately if there are no other instances */
1214 info = instance->info;
1215 if (!info->instances->next)
1216 return;
1217
1218 updating = True;
1219
1220 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1221
1222 if (val && get_one_value (instance, val))
1223 for (cur = info->instances; cur; cur = cur->next)
1224 if (cur != instance)
1225 set_one_value (cur, val, True);
1226
1227 updating = False;
1228 }
1229
1230
1231 \f/* get the id */
1232
1233 LWLIB_ID
1234 lw_get_widget_id (w)
1235 Widget w;
1236 {
1237 widget_instance* instance = get_widget_instance (w, False);
1238
1239 return instance ? instance->info->id : 0;
1240 }
1241
1242 \f/* set the keyboard focus */
1243 void
1244 lw_set_keyboard_focus (parent, w)
1245 Widget parent;
1246 Widget w;
1247 {
1248 #if defined (USE_MOTIF)
1249 xm_set_keyboard_focus (parent, w);
1250 #else
1251 XtSetKeyboardFocus (parent, w);
1252 #endif
1253 }
1254
1255 \f/* Show busy */
1256 static void
1257 show_one_widget_busy (w, flag)
1258 Widget w;
1259 Boolean flag;
1260 {
1261 Pixel foreground = 0;
1262 Pixel background = 1;
1263 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1264 if (!widget_to_invert)
1265 widget_to_invert = w;
1266
1267 XtVaGetValues (widget_to_invert,
1268 XtNforeground, &foreground,
1269 XtNbackground, &background,
1270 0);
1271 XtVaSetValues (widget_to_invert,
1272 XtNforeground, background,
1273 XtNbackground, foreground,
1274 0);
1275 }
1276
1277 void
1278 lw_show_busy (w, busy)
1279 Widget w;
1280 Boolean busy;
1281 {
1282 widget_instance* instance = get_widget_instance (w, False);
1283 widget_info* info;
1284 widget_instance* next;
1285
1286 if (instance)
1287 {
1288 info = instance->info;
1289 if (info->busy != busy)
1290 {
1291 for (next = info->instances; next; next = next->next)
1292 if (next->widget)
1293 show_one_widget_busy (next->widget, busy);
1294 info->busy = busy;
1295 }
1296 }
1297 }
1298
1299 /* This hack exists because Lucid/Athena need to execute the strange
1300 function below to support geometry management. */
1301 void
1302 lw_refigure_widget (w, doit)
1303 Widget w;
1304 Boolean doit;
1305 {
1306 #if defined (USE_XAW)
1307 XawPanedSetRefigureMode (w, doit);
1308 #endif
1309 #if defined (USE_MOTIF)
1310 if (doit)
1311 XtUnmanageChild (w);
1312 else
1313 XtManageChild (w);
1314 #endif
1315 }
1316
1317 /* Toolkit independent way of determining if an event window is in the
1318 menubar. */
1319 Boolean
1320 lw_window_is_in_menubar (win, menubar_widget)
1321 Window win;
1322 Widget menubar_widget;
1323 {
1324 return menubar_widget
1325 #if defined (USE_LUCID)
1326 && XtWindow (menubar_widget) == win;
1327 #endif
1328 #if defined (USE_MOTIF)
1329 && XtWindowToWidget (XtDisplay (menubar_widget), win)
1330 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
1331 == menubar_widget);
1332 #endif
1333 }
1334
1335 /* Motif hack to set the main window areas. */
1336 void
1337 lw_set_main_areas (parent, menubar, work_area)
1338 Widget parent;
1339 Widget menubar;
1340 Widget work_area;
1341 {
1342 #if defined (USE_MOTIF)
1343 xm_set_main_areas (parent, menubar, work_area);
1344 #endif
1345 }
1346
1347 /* Manage resizing for Motif. This disables resizing when the menubar
1348 is about to be modified. */
1349 void
1350 lw_allow_resizing (w, flag)
1351 Widget w;
1352 Boolean flag;
1353 {
1354 #if defined (USE_MOTIF)
1355 xm_manage_resizing (w, flag);
1356 #endif
1357 }