entered into RCS
[bpt/emacs.git] / lwlib / lwlib.c
CommitLineData
07bf635f
RS
1/* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
3
4This file is part of the Lucid Widget Library.
5
6The Lucid Widget Library is free software; you can redistribute it and/or
7modify it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11The Lucid Widget Library is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#ifdef NeXT
21#undef __STRICT_BSD__ /* ick */
22#endif
23
24#include <stdlib.h>
25#include <unistd.h>
26#include <sys/types.h>
27#include <string.h>
28#include <stdio.h>
29#include <X11/StringDefs.h>
e7818b5a 30#include "lwlib-int.h"
07bf635f
RS
31#include "lwlib-utils.h"
32
33#if defined(__GNUC__) && !defined(alloca)
34#define alloca __builtin_alloca
35#endif
36
37#if ((!__GNUC__) && !defined(__hpux)) && !defined(AIXV3)
38#include <alloca.h>
39#endif
40
41#if defined(AIXV3)
42#pragma alloca
43#endif
44
45#if defined (USE_LUCID)
46#include "lwlib-Xlw.h"
47#endif
48#if defined (USE_MOTIF)
49#include "lwlib-Xm.h"
50#endif
51#if defined (USE_OLIT)
52#include "lwlib-Xol.h"
53#endif
54
55#if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
56ERROR! At least one of USE_LUCID, USE_MOTIF or USE_OLIT must be defined.
57#endif
58
59#if defined (USE_MOTIF) && defined (USE_OLIT)
60ERROR! no more than one of USE_MOTIF and USE_OLIT may be defined.
61#endif
62
63/* List of all widgets managed by the library. */
64static widget_info*
65all_widget_info = NULL;
66
67\f/* Forward declarations */
68static void
69instanciate_widget_instance (widget_instance* instance);
70
71\f/* utility functions for widget_instance and widget_info */
72static char *
73safe_strdup (char* s)
74{
75 char *result;
76 if (! s) return 0;
77 result = (char *) malloc (strlen (s) + 1);
78 if (! result)
79 return 0;
80 strcpy (result, s);
81 return result;
82}
83
84static void
85safe_free_str (char* s)
86{
87 if (s) free (s);
88}
89
90static widget_value *widget_value_free_list = 0;
91
92widget_value *
93malloc_widget_value ()
94{
95 widget_value *wv;
96 if (widget_value_free_list)
97 {
98 wv = widget_value_free_list;
99 widget_value_free_list = wv->free_list;
100 wv->free_list = 0;
101 }
102 else
103 {
104 wv = (widget_value *) malloc (sizeof (widget_value));
105 }
106 memset (wv, 0, sizeof (widget_value));
107 return wv;
108}
109
110/* this is analagous to free(). It frees only what was allocated
111 by malloc_widget_value(), and no substructures.
112 */
113void
114free_widget_value (wv)
115 widget_value *wv;
116{
117 if (wv->free_list)
118 abort ();
119 wv->free_list = widget_value_free_list;
120 widget_value_free_list = wv;
121}
122
123static void
124free_widget_value_tree (widget_value* wv)
125{
126 if (!wv)
127 return;
128
129 if (wv->name) free (wv->name);
130 if (wv->value) free (wv->value);
131 if (wv->key) free (wv->key);
132
133 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
134
135 if (wv->toolkit_data && wv->free_toolkit_data)
136 {
137 free (wv->toolkit_data);
138 wv->toolkit_data = (void *) 0xDEADBEEF;
139 }
140
141 if (wv->contents && (wv->contents != (widget_value*)1))
142 {
143 free_widget_value_tree (wv->contents);
144 wv->contents = (widget_value *) 0xDEADBEEF;
145 }
146 if (wv->next)
147 {
148 free_widget_value_tree (wv->next);
149 wv->next = (widget_value *) 0xDEADBEEF;
150 }
151 free_widget_value (wv);
152}
153
154static widget_value *
155copy_widget_value_tree (widget_value* val, change_type change)
156{
157 widget_value* copy;
158
159 if (!val)
160 return NULL;
161 if (val == (widget_value *) 1)
162 return val;
163
164 copy = malloc_widget_value ();
165 copy->name = safe_strdup (val->name);
166 copy->value = safe_strdup (val->value);
167 copy->key = safe_strdup (val->key);
168 copy->enabled = val->enabled;
169 copy->selected = val->selected;
170 copy->edited = False;
171 copy->change = change;
172 copy->contents = copy_widget_value_tree (val->contents, change);
173 copy->call_data = val->call_data;
174 copy->next = copy_widget_value_tree (val->next, change);
175 copy->toolkit_data = NULL;
176 copy->free_toolkit_data = False;
177 return copy;
178}
179
180static widget_info *
181allocate_widget_info (char* type, char* name, LWLIB_ID id, widget_value* val,
182 lw_callback pre_activate_cb, lw_callback selection_cb,
183 lw_callback post_activate_cb)
184{
185 widget_info* info = (widget_info*)malloc (sizeof (widget_info));
186 info->type = safe_strdup (type);
187 info->name = safe_strdup (name);
188 info->id = id;
189 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
190 info->busy = False;
191 info->pre_activate_cb = pre_activate_cb;
192 info->selection_cb = selection_cb;
193 info->post_activate_cb = post_activate_cb;
194 info->instances = NULL;
195
196 info->next = all_widget_info;
197 all_widget_info = info;
198
199 return info;
200}
201
202static void
203free_widget_info (widget_info* info)
204{
205 safe_free_str (info->type);
206 safe_free_str (info->name);
207 free_widget_value_tree (info->val);
208 memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
209 free (info);
210}
211
212static void
213mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
214{
215 widget_instance* instance = (widget_instance*)closure;
216
217 /* be very conservative */
218 if (instance->widget == widget)
219 instance->widget = NULL;
220}
221
222static widget_instance *
223allocate_widget_instance (widget_info* info, Widget parent, Boolean pop_up_p)
224{
225 widget_instance* instance =
226 (widget_instance*)malloc (sizeof (widget_instance));
227 instance->parent = parent;
228 instance->pop_up_p = pop_up_p;
229 instance->info = info;
230 instance->next = info->instances;
231 info->instances = instance;
232
233 instanciate_widget_instance (instance);
234
235 XtAddCallback (instance->widget, XtNdestroyCallback,
236 mark_widget_destroyed, (XtPointer)instance);
237 return instance;
238}
239
240static void
241free_widget_instance (widget_instance* instance)
242{
243 memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
244 free (instance);
245}
246
247static widget_info *
248get_widget_info (LWLIB_ID id, Boolean remove_p)
249{
250 widget_info* info;
251 widget_info* prev;
252 for (prev = NULL, info = all_widget_info;
253 info;
254 prev = info, info = info->next)
255 if (info->id == id)
256 {
257 if (remove_p)
258 {
259 if (prev)
260 prev->next = info->next;
261 else
262 all_widget_info = info->next;
263 }
264 return info;
265 }
266 return NULL;
267}
268
269static widget_instance *
270get_widget_instance (Widget widget, Boolean remove_p)
271{
272 widget_info* info;
273 widget_instance* instance;
274 widget_instance* prev;
275 for (info = all_widget_info; info; info = info->next)
276 for (prev = NULL, instance = info->instances;
277 instance;
278 prev = instance, instance = instance->next)
279 if (instance->widget == widget)
280 {
281 if (remove_p)
282 {
283 if (prev)
284 prev->next = instance->next;
285 else
286 info->instances = instance->next;
287 }
288 return instance;
289 }
290 return (widget_instance *) 0;
291}
292
293static widget_instance*
294find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
295{
296 widget_info* info = get_widget_info (id, False);
297 widget_instance* instance;
298
299 if (info)
300 for (instance = info->instances; instance; instance = instance->next)
301 if (instance->parent == parent && instance->pop_up_p == pop_up_p)
302 return instance;
303
304 return NULL;
305}
306
307\f
308/* utility function for widget_value */
309static Boolean
310safe_strcmp (char* s1, char* s2)
311{
312 if (!!s1 ^ !!s2) return True;
313 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
314}
315
316static int
317max (int i1, int i2)
318{
319 return i1 > i2 ? i1 : i2;
320}
321
322
323#if 0
324# define EXPLAIN(name, oc, nc, desc, a1, a2) \
325 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
326 name, \
327 (oc == NO_CHANGE ? "none" : \
328 (oc == INVISIBLE_CHANGE ? "invisible" : \
329 (oc == VISIBLE_CHANGE ? "visible" : \
330 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
331 oc, \
332 (nc == NO_CHANGE ? "none" : \
333 (nc == INVISIBLE_CHANGE ? "invisible" : \
334 (nc == VISIBLE_CHANGE ? "visible" : \
335 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
336 nc, desc, a1, a2)
337#else
338# define EXPLAIN(name, oc, nc, desc, a1, a2)
339#endif
340
341
342static widget_value *
343merge_widget_value (widget_value* val1, widget_value* val2, int level)
344{
345 change_type change;
346 widget_value* merged_next;
347 widget_value* merged_contents;
348
349 if (!val1)
350 {
351 if (val2)
352 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
353 else
354 return NULL;
355 }
356 if (!val2)
357 {
358 free_widget_value_tree (val1);
359 return NULL;
360 }
361
362 change = NO_CHANGE;
363
364 if (safe_strcmp (val1->name, val2->name))
365 {
366 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
367 val1->name, val2->name);
368 change = max (change, STRUCTURAL_CHANGE);
369 safe_free_str (val1->name);
370 val1->name = safe_strdup (val2->name);
371 }
372 if (safe_strcmp (val1->value, val2->value))
373 {
374 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
375 val1->value, val2->value);
376 change = max (change, VISIBLE_CHANGE);
377 safe_free_str (val1->value);
378 val1->value = safe_strdup (val2->value);
379 }
380 if (safe_strcmp (val1->key, val2->key))
381 {
382 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
383 val1->key, val2->key);
384 change = max (change, VISIBLE_CHANGE);
385 safe_free_str (val1->key);
386 val1->key = safe_strdup (val2->key);
387 }
388 if (val1->enabled != val2->enabled)
389 {
390 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
391 val1->enabled, val2->enabled);
392 change = max (change, VISIBLE_CHANGE);
393 val1->enabled = val2->enabled;
394 }
395 if (val1->selected != val2->selected)
396 {
397 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
398 val1->selected, val2->selected);
399 change = max (change, VISIBLE_CHANGE);
400 val1->selected = val2->selected;
401 }
402 if (val1->call_data != val2->call_data)
403 {
404 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
405 val1->call_data, val2->call_data);
406 change = max (change, INVISIBLE_CHANGE);
407 val1->call_data = val2->call_data;
408 }
409
410 if (level > 0)
411 {
412 merged_contents =
413 merge_widget_value (val1->contents, val2->contents, level - 1);
414
415 if (val1->contents && !merged_contents)
416 {
417 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)",
418 0, 0);
419 change = max (change, INVISIBLE_CHANGE);
420 }
421 else if (merged_contents && merged_contents->change != NO_CHANGE)
422 {
423 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
424 0, 0);
425 change = max (change, INVISIBLE_CHANGE);
426 }
427
428 val1->contents = merged_contents;
429 }
430
431 merged_next = merge_widget_value (val1->next, val2->next, level);
432
433 if (val1->next && !merged_next)
434 {
435 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
436 0, 0);
437 change = max (change, STRUCTURAL_CHANGE);
438 }
439 else if (merged_next)
440 {
441 if (merged_next->change)
442 EXPLAIN (val1->name, change, merged_next->change, "(following change)",
443 0, 0);
444 change = max (change, merged_next->change);
445 }
446
447 val1->next = merged_next;
448
449 val1->change = change;
450
451 if (change > NO_CHANGE && val1->toolkit_data)
452 {
453 if (val1->free_toolkit_data)
454 free (val1->toolkit_data);
455 val1->toolkit_data = NULL;
456 }
457
458 return val1;
459}
460
461\f
462/* modifying the widgets */
463static Widget
464name_to_widget (widget_instance* instance, char* name)
465{
466 Widget widget = NULL;
467
468 if (!instance->widget)
469 return NULL;
470
471 if (!strcmp (XtName (instance->widget), name))
472 widget = instance->widget;
473 else
474 {
475 int length = strlen (name) + 2;
476 char* real_name = (char *) alloca (length);
477 real_name [0] = '*';
478 strcpy (real_name + 1, name);
479
480 widget = XtNameToWidget (instance->widget, real_name);
481 }
482 return widget;
483}
484
485static void
486set_one_value (widget_instance* instance, widget_value* val, Boolean deep_p)
487{
488 Widget widget = name_to_widget (instance, val->name);
489
490 if (widget)
491 {
492#if defined (USE_LUCID)
493 if (lw_lucid_widget_p (instance->widget))
494 xlw_update_one_widget (instance, widget, val, deep_p);
495#endif
496#if defined (USE_MOTIF)
497 if (lw_motif_widget_p (instance->widget))
498 xm_update_one_widget (instance, widget, val, deep_p);
499#endif
500#if defined (USE_OLIT)
501 if (lw_olit_widget_p (instance->widget))
502 xol_update_one_widget (instance, widget, val, deep_p);
503#endif
504 }
505}
506
507static void
508update_one_widget_instance (widget_instance* instance, Boolean deep_p)
509{
510 widget_value *val;
511
512 if (!instance->widget)
513 /* the widget was destroyed */
514 return;
515
516 for (val = instance->info->val; val; val = val->next)
517 if (val->change != NO_CHANGE)
518 set_one_value (instance, val, deep_p);
519}
520
521static void
522update_all_widget_values (widget_info* info, Boolean deep_p)
523{
524 widget_instance* instance;
525 widget_value* val;
526
527 for (instance = info->instances; instance; instance = instance->next)
528 update_one_widget_instance (instance, deep_p);
529
530 for (val = info->val; val; val = val->next)
531 val->change = NO_CHANGE;
532}
533
534void
535lw_modify_all_widgets (LWLIB_ID id, widget_value* val, Boolean deep_p)
536{
537 widget_info* info = get_widget_info (id, False);
538 widget_value* new_val;
539 widget_value* next_new_val;
540 widget_value* cur;
541 widget_value* prev;
542 widget_value* next;
543 int found;
544
545 if (!info)
546 return;
547
548 for (new_val = val; new_val; new_val = new_val->next)
549 {
550 next_new_val = new_val->next;
551 new_val->next = NULL;
552 found = False;
553 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
554 if (!strcmp (cur->name, new_val->name))
555 {
556 found = True;
557 next = cur->next;
558 cur->next = NULL;
559 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1);
560 if (prev)
561 prev->next = cur ? cur : next;
562 else
563 info->val = cur ? cur : next;
564 if (cur)
565 cur->next = next;
566 break;
567 }
568 if (!found)
569 {
570 /* Could not find it, add it */
571 if (prev)
572 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
573 else
574 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
575 }
576 new_val->next = next_new_val;
577 }
578
579 update_all_widget_values (info, deep_p);
580}
581
582\f
583/* creating the widgets */
584
585static void
586initialize_widget_instance (widget_instance* instance)
587{
588 widget_value* val;
589
590 for (val = instance->info->val; val; val = val->next)
591 val->change = STRUCTURAL_CHANGE;
592
593 update_one_widget_instance (instance, True);
594
595 for (val = instance->info->val; val; val = val->next)
596 val->change = NO_CHANGE;
597}
598
599
600static widget_creation_function
601find_in_table (char* type, widget_creation_entry* table)
602{
603 widget_creation_entry* cur;
604 for (cur = table; cur->type; cur++)
605 if (!strcasecmp (type, cur->type))
606 return cur->function;
607 return NULL;
608}
609
610static Boolean
611dialog_spec_p (char* name)
612{
613 /* return True if name matches [EILPQeilpq][1-9][Bb] or
614 [EILPQeilpq][1-9][Bb][Rr][1-9] */
615 if (!name)
616 return False;
617
618 switch (name [0])
619 {
620 case 'E': case 'I': case 'L': case 'P': case 'Q':
621 case 'e': case 'i': case 'l': case 'p': case 'q':
622 if (name [1] >= '0' && name [1] <= '9')
623 {
624 if (name [2] != 'B' && name [2] != 'b')
625 return False;
626 if (!name [3])
627 return True;
628 if ((name [3] == 'T' || name [3] == 't') && !name [4])
629 return True;
630 if ((name [3] == 'R' || name [3] == 'r')
631 && name [4] >= '0' && name [4] <= '9' && !name [5])
632 return True;
633 return False;
634 }
635 else
636 return False;
637
638 default:
639 return False;
640 }
641}
642
643static void
644instanciate_widget_instance (widget_instance* instance)
645{
646 widget_creation_function function = NULL;
647
648#if defined (USE_LUCID)
649 if (!function)
650 function = find_in_table (instance->info->type, xlw_creation_table);
651#endif
652#if defined(USE_MOTIF)
653 if (!function)
654 function = find_in_table (instance->info->type, xm_creation_table);
655#endif
656#if defined (USE_OLIT)
657 if (!function)
658 function = find_in_table (instance->info->type, xol_creation_table);
659#endif
660
661 if (!function)
662 {
663 if (dialog_spec_p (instance->info->type))
664 {
665#if defined (USE_LUCID)
666 /* not yet */
667#endif
668#if defined(USE_MOTIF)
669 if (!function)
670 function = xm_create_dialog;
671#endif
672#if defined (USE_OLIT)
673 /* not yet */
674#endif
675 }
676 }
677
678 if (!function)
679 {
680 printf ("No creation function for widget type %s\n",
681 instance->info->type);
682 abort ();
683 }
684
685 instance->widget = (*function) (instance);
686
687 if (!instance->widget)
688 abort ();
689
690 /* XtRealizeWidget (instance->widget);*/
691}
692
693void
694lw_register_widget (char* type, char* name, LWLIB_ID id, widget_value* val,
695 lw_callback pre_activate_cb, lw_callback selection_cb,
696 lw_callback post_activate_cb)
697{
698 if (!get_widget_info (id, False))
699 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
700 post_activate_cb);
701}
702
703Widget
704lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
705{
706 widget_instance* instance;
707
708 instance = find_instance (id, parent, pop_up_p);
709 return instance ? instance->widget : NULL;
710}
711
712Widget
713lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
714{
715 widget_instance* instance;
716 widget_info* info;
717
718 instance = find_instance (id, parent, pop_up_p);
719 if (!instance)
720 {
721 info = get_widget_info (id, False);
722 if (!info)
723 return NULL;
724 instance = allocate_widget_instance (info, parent, pop_up_p);
725 initialize_widget_instance (instance);
726 }
727 if (!instance->widget)
728 abort ();
729 return instance->widget;
730}
731
732Widget
733lw_create_widget (char* type, char* name, LWLIB_ID id, widget_value* val,
734 Widget parent, Boolean pop_up_p, lw_callback pre_activate_cb,
735 lw_callback selection_cb, lw_callback post_activate_cb)
736{
737 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
738 post_activate_cb);
739 return lw_make_widget (id, parent, pop_up_p);
740}
741
742\f
743/* destroying the widgets */
744static void
745destroy_one_instance (widget_instance* instance)
746{
747 /* Remove the destroy callback on the widget; that callback will try to
748 dereference the instance object (to set its widget slot to 0, since the
749 widget is dead.) Since the instance is now dead, we don't have to worry
750 about the fact that its widget is dead too.
751
752 This happens in the Phase2Destroy of the widget, so this callback would
753 not have been run until arbitrarily long after the instance was freed.
754 */
755 if (instance->widget)
756 XtRemoveCallback (instance->widget, XtNdestroyCallback,
757 mark_widget_destroyed, (XtPointer)instance);
758
759 if (instance->widget)
760 {
761 /* The else are pretty tricky here, including the empty statement
762 at the end because it would be very bad to destroy a widget
763 twice. */
764#if defined (USE_LUCID)
765 if (lw_lucid_widget_p (instance->widget))
766 xlw_destroy_instance (instance);
767 else
768#endif
769#if defined (USE_MOTIF)
770 if (lw_motif_widget_p (instance->widget))
771 xm_destroy_instance (instance);
772 else
773#endif
774#if defined (USE_OLIT)
775 if (lw_olit_widget_p (instance->widget))
776 xol_destroy_instance (instance);
777 else
778#endif
779 /* do not remove the empty statement */
780 ;
781 }
782
783 free_widget_instance (instance);
784}
785
786void
787lw_destroy_widget (Widget w)
788{
789 widget_instance* instance = get_widget_instance (w, True);
790
791 if (instance)
792 {
793 widget_info *info = instance->info;
794 /* instance has already been removed from the list; free it */
795 destroy_one_instance (instance);
796 /* if there are no instances left, free the info too */
797 if (!info->instances)
798 lw_destroy_all_widgets (info->id);
799 }
800}
801
802void
803lw_destroy_all_widgets (LWLIB_ID id)
804{
805 widget_info* info = get_widget_info (id, True);
806 widget_instance* instance;
807 widget_instance* next;
808
809 if (info)
810 {
811 for (instance = info->instances; instance; )
812 {
813 next = instance->next;
814 destroy_one_instance (instance);
815 instance = next;
816 }
817 free_widget_info (info);
818 }
819}
820
821void
822lw_destroy_everything ()
823{
824 while (all_widget_info)
825 lw_destroy_all_widgets (all_widget_info->id);
826}
827
828void
829lw_destroy_all_pop_ups ()
830{
831 widget_info* info;
832 widget_info* next;
833 widget_instance* instance;
834
835 for (info = all_widget_info; info; info = next)
836 {
837 next = info->next;
838 instance = info->instances;
839 if (instance && instance->pop_up_p)
840 lw_destroy_all_widgets (info->id);
841 }
842}
843
844#ifdef USE_MOTIF
845extern Widget first_child (Widget); /* garbage */
846#endif
847
848Widget
849lw_raise_all_pop_up_widgets ()
850{
851 widget_info* info;
852 widget_instance* instance;
853 Widget result = NULL;
854
855 for (info = all_widget_info; info; info = info->next)
856 for (instance = info->instances; instance; instance = instance->next)
857 if (instance->pop_up_p)
858 {
859 Widget widget = instance->widget;
860 if (widget)
861 {
862 if (XtIsManaged (widget)
863#ifdef USE_MOTIF
864 /* What a complete load of crap!!!!
865 When a dialogShell is on the screen, it is not managed!
866 */
867 || (lw_motif_widget_p (instance->widget) &&
868 XtIsManaged (first_child (widget)))
869#endif
870 )
871 {
872 if (!result)
873 result = widget;
874 XMapRaised (XtDisplay (widget), XtWindow (widget));
875 }
876 }
877 }
878 return result;
879}
880
881static void
882lw_pop_all_widgets (LWLIB_ID id, Boolean up)
883{
884 widget_info* info = get_widget_info (id, False);
885 widget_instance* instance;
886
887 if (info)
888 for (instance = info->instances; instance; instance = instance->next)
889 if (instance->pop_up_p && instance->widget)
890 {
891 if (!XtIsRealized (instance->widget))
892 XtRealizeWidget (instance->widget);
893#if defined (USE_LUCID)
894 if (lw_lucid_widget_p (instance->widget))
895 xlw_pop_instance (instance, up);
896#endif
897#if defined (USE_MOTIF)
898 if (lw_motif_widget_p (instance->widget))
899 xm_pop_instance (instance, up);
900#endif
901#if defined (USE_OLIT)
902 if (lw_olit_widget_p (instance->widget))
903 xol_pop_instance (instance, up);
904#endif
905 }
906}
907
908void
909lw_pop_up_all_widgets (LWLIB_ID id)
910{
911 lw_pop_all_widgets (id, True);
912}
913
914void
915lw_pop_down_all_widgets (LWLIB_ID id)
916{
917 lw_pop_all_widgets (id, False);
918}
919
920void
921lw_popup_menu (Widget widget)
922{
923#if defined (USE_LUCID)
924 if (lw_lucid_widget_p (widget))
925 xlw_popup_menu (widget);
926#endif
927#if defined (USE_MOTIF)
928 if (lw_motif_widget_p (widget))
929 xm_popup_menu (widget);
930#endif
931#if defined (USE_OLIT)
932 if (lw_olit_widget_p (widget))
933 xol_popup_menu (widget);
934#endif
935}
936
937\f/* get the values back */
938static Boolean
939get_one_value (widget_instance* instance, widget_value* val)
940{
941 Widget widget = name_to_widget (instance, val->name);
942
943 if (widget)
944 {
945#if defined (USE_LUCID)
946 if (lw_lucid_widget_p (instance->widget))
947 xlw_update_one_value (instance, widget, val);
948#endif
949#if defined (USE_MOTIF)
950 if (lw_motif_widget_p (instance->widget))
951 xm_update_one_value (instance, widget, val);
952#endif
953#if defined (USE_OLIT)
954 if (lw_olit_widget_p (instance->widget))
955 xol_update_one_value (instance, widget, val);
956#endif
957 return True;
958 }
959 else
960 return False;
961}
962
963Boolean
964lw_get_some_values (LWLIB_ID id, widget_value* val_out)
965{
966 widget_info* info = get_widget_info (id, False);
967 widget_instance* instance;
968 widget_value* val;
969 Boolean result = False;
970
971 if (!info)
972 return False;
973
974 instance = info->instances;
975 if (!instance)
976 return False;
977
978 for (val = val_out; val; val = val->next)
979 if (get_one_value (instance, val))
980 result = True;
981
982 return result;
983}
984
985widget_value*
986lw_get_all_values (LWLIB_ID id)
987{
988 widget_info* info = get_widget_info (id, False);
989 widget_value* val = info->val;
990 if (lw_get_some_values (id, val))
991 return val;
992 else
993 return NULL;
994}
995
996/* internal function used by the library dependent implementation to get the
997 widget_value for a given widget in an instance */
998widget_value*
999lw_get_widget_value_for_widget (widget_instance* instance, Widget w)
1000{
1001 char* name = XtName (w);
1002 widget_value* cur;
1003 for (cur = instance->info->val; cur; cur = cur->next)
1004 if (!strcmp (cur->name, name))
1005 return cur;
1006 return NULL;
1007}
1008
1009\f/* update other instances value when one thing changed */
1010/* This function can be used as a an XtCallback for the widgets that get
1011 modified to update other instances of the widgets. Closure should be the
1012 widget_instance. */
1013void
1014lw_internal_update_other_instances (Widget widget, XtPointer closure,
1015 XtPointer call_data)
1016{
1017 /* To forbid recursive calls */
1018 static Boolean updating;
1019
1020 widget_instance* instance = (widget_instance*)closure;
1021 char* name = XtName (widget);
1022 widget_info* info;
1023 widget_instance* cur;
1024 widget_value* val;
1025
1026 /* never recurse as this could cause infinite recursions. */
1027 if (updating)
1028 return;
1029
1030 /* protect against the widget being destroyed */
1031 if (XtWidgetBeingDestroyedP (widget))
1032 return;
1033
1034 /* Return immediately if there are no other instances */
1035 info = instance->info;
1036 if (!info->instances->next)
1037 return;
1038
1039 updating = True;
1040
1041 for (val = info->val; val && strcmp (val->name, name); val = val->next);
1042
1043 if (val && get_one_value (instance, val))
1044 for (cur = info->instances; cur; cur = cur->next)
1045 if (cur != instance)
1046 set_one_value (cur, val, True);
1047
1048 updating = False;
1049}
1050
1051
1052\f/* get the id */
1053
1054LWLIB_ID
1055lw_get_widget_id (Widget w)
1056{
1057 widget_instance* instance = get_widget_instance (w, False);
1058
1059 return instance ? instance->info->id : 0;
1060}
1061
1062\f/* set the keyboard focus */
1063void
1064lw_set_keyboard_focus (Widget parent, Widget w)
1065{
1066#if defined (USE_MOTIF)
1067 xm_set_keyboard_focus (parent, w);
1068#else
1069 XtSetKeyboardFocus (parent, w);
1070#endif
1071}
1072
1073\f/* Show busy */
1074static void
1075show_one_widget_busy (Widget w, Boolean flag)
1076{
1077 Pixel foreground = 0;
1078 Pixel background = 1;
1079 Widget widget_to_invert = XtNameToWidget (w, "*sheet");
1080 if (!widget_to_invert)
1081 widget_to_invert = w;
1082
1083 XtVaGetValues (widget_to_invert,
1084 XtNforeground, &foreground,
1085 XtNbackground, &background,
1086 0);
1087 XtVaSetValues (widget_to_invert,
1088 XtNforeground, background,
1089 XtNbackground, foreground,
1090 0);
1091}
1092
1093void
1094lw_show_busy (Widget w, Boolean busy)
1095{
1096 widget_instance* instance = get_widget_instance (w, False);
1097 widget_info* info;
1098 widget_instance* next;
1099
1100 if (instance)
1101 {
1102 info = instance->info;
1103 if (info->busy != busy)
1104 {
1105 for (next = info->instances; next; next = next->next)
1106 if (next->widget)
1107 show_one_widget_busy (next->widget, busy);
1108 info->busy = busy;
1109 }
1110 }
1111}