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