1 /* A general interface to the widgets of different toolkits.
3 Copyright (C) 1992, 1993 Lucid, Inc.
4 Copyright (C) 1994-1996, 1999-2014 Free Software Foundation, Inc.
6 This file is part of the Lucid Widget Library.
8 The Lucid Widget Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 The Lucid Widget Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25 #include <c-strcase.h>
27 #include <sys/types.h>
29 #include "lwlib-int.h"
30 #include "lwlib-utils.h"
31 #include <X11/StringDefs.h>
33 #if defined (USE_LUCID)
34 #include "lwlib-Xlw.h"
36 #if defined (USE_MOTIF)
38 #else /* not USE_MOTIF */
39 #if defined (USE_LUCID)
41 #endif /* not USE_MOTIF && USE_LUCID */
45 #include <X11/Xaw3d/Paned.h>
46 #else /* !HAVE_XAW3D */
47 #include <X11/Xaw/Paned.h>
48 #endif /* HAVE_XAW3D */
49 #include "lwlib-Xaw.h"
52 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
53 #error At least one of USE_LUCID or USE_MOTIF must be defined.
57 #define max(x, y) ((x) > (y) ? (x) : (y))
60 /* List of all widgets managed by the library. */
62 all_widget_info
= NULL
;
65 const char *lwlib_toolkit_type
= "motif";
67 const char *lwlib_toolkit_type
= "lucid";
70 static widget_value
*merge_widget_value (widget_value
*,
73 static void instantiate_widget_instance (widget_instance
*);
74 static void free_widget_value_tree (widget_value
*);
75 static widget_value
*copy_widget_value_tree (widget_value
*,
77 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
79 lw_callback
, lw_callback
,
80 lw_callback
, lw_callback
);
81 static void free_widget_info (widget_info
*);
82 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
83 static widget_instance
*allocate_widget_instance (widget_info
*,
85 static void free_widget_instance (widget_instance
*);
86 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
87 static widget_instance
*get_widget_instance (Widget
, Boolean
);
88 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
89 static Boolean
safe_strcmp (const char *, const char *);
90 static Widget
name_to_widget (widget_instance
*, const char *);
91 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
92 static void update_one_widget_instance (widget_instance
*, Boolean
);
93 static void update_all_widget_values (widget_info
*, Boolean
);
94 static void initialize_widget_instance (widget_instance
*);
95 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
96 static Boolean
dialog_spec_p (const char *);
97 static void destroy_one_instance (widget_instance
*);
98 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
99 static Boolean
get_one_value (widget_instance
*, widget_value
*);
100 static void show_one_widget_busy (Widget
, Boolean
);
102 static widget_value
*widget_value_free_list
= 0;
103 static int malloc_cpt
= 0;
106 malloc_widget_value (void)
109 if (widget_value_free_list
)
111 wv
= widget_value_free_list
;
112 widget_value_free_list
= wv
->free_list
;
117 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
120 memset ((void*) wv
, 0, sizeof (widget_value
));
124 /* this is analogous to free(). It frees only what was allocated
125 by malloc_widget_value(), and no substructures.
128 free_widget_value (widget_value
*wv
)
135 /* When the number of already allocated cells is too big,
142 wv
->free_list
= widget_value_free_list
;
143 widget_value_free_list
= wv
;
148 free_widget_value_tree (widget_value
*wv
)
157 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
159 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
161 XtFree (wv
->toolkit_data
);
162 wv
->toolkit_data
= (void *) 0xDEADBEEF;
165 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
167 free_widget_value_tree (wv
->contents
);
168 wv
->contents
= (widget_value
*) 0xDEADBEEF;
172 free_widget_value_tree (wv
->next
);
173 wv
->next
= (widget_value
*) 0xDEADBEEF;
175 free_widget_value (wv
);
178 static widget_value
*
179 copy_widget_value_tree (widget_value
*val
, change_type change
)
185 if (val
== (widget_value
*) 1)
188 copy
= malloc_widget_value ();
189 copy
->name
= xstrdup (val
->name
);
190 copy
->value
= val
->value
? xstrdup (val
->value
) : NULL
;
191 copy
->key
= val
->key
? xstrdup (val
->key
) : NULL
;
192 copy
->help
= val
->help
;
193 copy
->enabled
= val
->enabled
;
194 copy
->button_type
= val
->button_type
;
195 copy
->selected
= val
->selected
;
196 copy
->edited
= False
;
197 copy
->change
= change
;
198 copy
->this_one_change
= change
;
199 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
200 copy
->call_data
= val
->call_data
;
201 copy
->next
= copy_widget_value_tree (val
->next
, change
);
202 copy
->toolkit_data
= NULL
;
203 copy
->free_toolkit_data
= False
;
208 allocate_widget_info (const char* type
,
212 lw_callback pre_activate_cb
,
213 lw_callback selection_cb
,
214 lw_callback post_activate_cb
,
215 lw_callback highlight_cb
)
217 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
218 info
->type
= xstrdup (type
);
219 info
->name
= xstrdup (name
);
221 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
223 info
->pre_activate_cb
= pre_activate_cb
;
224 info
->selection_cb
= selection_cb
;
225 info
->post_activate_cb
= post_activate_cb
;
226 info
->highlight_cb
= highlight_cb
;
227 info
->instances
= NULL
;
229 info
->next
= all_widget_info
;
230 all_widget_info
= info
;
236 free_widget_info (widget_info
*info
)
240 free_widget_value_tree (info
->val
);
241 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
246 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
248 widget_instance
* instance
= (widget_instance
*)closure
;
250 /* be very conservative */
251 if (instance
->widget
== widget
)
252 instance
->widget
= NULL
;
255 static widget_instance
*
256 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
258 widget_instance
* instance
=
259 (widget_instance
*) xmalloc (sizeof (widget_instance
));
260 memset (instance
, 0, sizeof *instance
);
261 instance
->parent
= parent
;
262 instance
->pop_up_p
= pop_up_p
;
263 instance
->info
= info
;
264 instance
->next
= info
->instances
;
265 info
->instances
= instance
;
267 instantiate_widget_instance (instance
);
269 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
270 mark_widget_destroyed
, (XtPointer
)instance
);
275 free_widget_instance (widget_instance
*instance
)
277 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
282 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
286 for (prev
= NULL
, info
= all_widget_info
;
288 prev
= info
, info
= info
->next
)
294 prev
->next
= info
->next
;
296 all_widget_info
= info
->next
;
303 /* Internal function used by the library dependent implementation to get the
304 widget_value for a given widget in an instance */
306 lw_get_widget_info (LWLIB_ID id
)
308 return get_widget_info (id
, 0);
311 static widget_instance
*
312 get_widget_instance (Widget widget
, Boolean remove_p
)
315 widget_instance
* instance
;
316 widget_instance
* prev
;
317 for (info
= all_widget_info
; info
; info
= info
->next
)
318 for (prev
= NULL
, instance
= info
->instances
;
320 prev
= instance
, instance
= instance
->next
)
321 if (instance
->widget
== widget
)
326 prev
->next
= instance
->next
;
328 info
->instances
= instance
->next
;
332 return (widget_instance
*) 0;
335 /* Value is a pointer to the widget_instance corresponding to
336 WIDGET, or null if WIDGET is not a lwlib widget. */
339 lw_get_widget_instance (Widget widget
)
341 return get_widget_instance (widget
, False
);
344 static widget_instance
*
345 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
347 widget_info
* info
= get_widget_info (id
, False
);
348 widget_instance
* instance
;
351 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
352 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
359 /* utility function for widget_value */
361 safe_strcmp (const char *s1
, const char *s2
)
363 if (!!s1
^ !!s2
) return True
;
364 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
369 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
370 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
372 (oc == NO_CHANGE ? "none" : \
373 (oc == INVISIBLE_CHANGE ? "invisible" : \
374 (oc == VISIBLE_CHANGE ? "visible" : \
375 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
377 (nc == NO_CHANGE ? "none" : \
378 (nc == INVISIBLE_CHANGE ? "invisible" : \
379 (nc == VISIBLE_CHANGE ? "visible" : \
380 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
383 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
387 static widget_value
*
388 merge_widget_value (widget_value
*val1
,
393 change_type change
, this_one_change
;
394 widget_value
* merged_next
;
395 widget_value
* merged_contents
;
402 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
410 free_widget_value_tree (val1
);
416 if (safe_strcmp (val1
->name
, val2
->name
))
418 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
419 val1
->name
, val2
->name
);
420 change
= max (change
, STRUCTURAL_CHANGE
);
421 dupstring (&val1
->name
, val2
->name
);
423 if (safe_strcmp (val1
->value
, val2
->value
))
425 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
426 val1
->value
, val2
->value
);
427 change
= max (change
, VISIBLE_CHANGE
);
428 dupstring (&val1
->value
, val2
->value
);
430 if (safe_strcmp (val1
->key
, val2
->key
))
432 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
433 val1
->key
, val2
->key
);
434 change
= max (change
, VISIBLE_CHANGE
);
435 dupstring (&val1
->key
, val2
->key
);
437 if (! EQ (val1
->help
, val2
->help
))
439 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
440 val1
->help
, val2
->help
);
441 change
= max (change
, VISIBLE_CHANGE
);
442 val1
->help
= val2
->help
;
444 if (val1
->enabled
!= val2
->enabled
)
446 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
447 val1
->enabled
, val2
->enabled
);
448 change
= max (change
, VISIBLE_CHANGE
);
449 val1
->enabled
= val2
->enabled
;
451 if (val1
->button_type
!= val2
->button_type
)
453 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
454 val1
->button_type
, val2
->button_type
);
455 change
= max (change
, VISIBLE_CHANGE
);
456 val1
->button_type
= val2
->button_type
;
458 if (val1
->selected
!= val2
->selected
)
460 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
461 val1
->selected
, val2
->selected
);
462 change
= max (change
, VISIBLE_CHANGE
);
463 val1
->selected
= val2
->selected
;
465 if (val1
->call_data
!= val2
->call_data
)
467 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
468 val1
->call_data
, val2
->call_data
);
469 change
= max (change
, INVISIBLE_CHANGE
);
470 val1
->call_data
= val2
->call_data
;
476 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
479 if (val1
->contents
&& !merged_contents
)
481 /* This used to say INVISIBLE_CHANGE,
482 but it is visible and vitally important when
483 the contents of the menu bar itself are entirely deleted.
485 But maybe it doesn't matter. This fails to fix the bug. */
486 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
488 change
= max (change
, STRUCTURAL_CHANGE
);
490 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
492 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
494 change
= max (change
, INVISIBLE_CHANGE
);
495 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
497 change
= max (merged_contents
->change
, change
);
502 val1
->contents
= merged_contents
;
505 this_one_change
= change
;
507 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
509 if (val1
->next
&& !merged_next
)
511 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
513 change
= max (change
, STRUCTURAL_CHANGE
);
515 else if (merged_next
)
517 if (merged_next
->change
)
518 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
520 change
= max (change
, merged_next
->change
);
523 val1
->next
= merged_next
;
525 val1
->this_one_change
= this_one_change
;
526 val1
->change
= change
;
528 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
531 if (val1
->free_toolkit_data
)
532 XtFree (val1
->toolkit_data
);
533 val1
->toolkit_data
= NULL
;
540 /* modifying the widgets */
542 name_to_widget (widget_instance
*instance
, const char *name
)
544 Widget widget
= NULL
;
546 if (!instance
->widget
)
549 if (!strcmp (XtName (instance
->widget
), name
))
550 widget
= instance
->widget
;
553 int length
= strlen (name
) + 2;
554 char* real_name
= (char *) xmalloc (length
);
556 strcpy (real_name
+ 1, name
);
558 widget
= XtNameToWidget (instance
->widget
, real_name
);
566 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
568 Widget widget
= name_to_widget (instance
, val
->name
);
572 #if defined (USE_LUCID)
573 if (lw_lucid_widget_p (instance
->widget
))
574 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
576 #if defined (USE_MOTIF)
577 if (lw_motif_widget_p (instance
->widget
))
578 xm_update_one_widget (instance
, widget
, val
, deep_p
);
580 #if defined (USE_XAW)
581 if (lw_xaw_widget_p (instance
->widget
))
582 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
588 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
592 if (!instance
->widget
)
593 /* the widget was destroyed */
596 for (val
= instance
->info
->val
; val
; val
= val
->next
)
597 if (val
->change
!= NO_CHANGE
)
598 set_one_value (instance
, val
, deep_p
);
602 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
604 widget_instance
* instance
;
607 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
608 update_one_widget_instance (instance
, deep_p
);
610 for (val
= info
->val
; val
; val
= val
->next
)
611 val
->change
= NO_CHANGE
;
615 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
617 widget_info
* info
= get_widget_info (id
, False
);
618 widget_value
* new_val
;
619 widget_value
* next_new_val
;
629 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
631 next_new_val
= new_val
->next
;
632 new_val
->next
= NULL
;
634 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
635 if (!strcmp (cur
->name
, new_val
->name
))
640 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
643 prev
->next
= cur
? cur
: next
;
645 info
->val
= cur
? cur
: next
;
652 /* Could not find it, add it */
654 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
656 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
659 new_val
->next
= next_new_val
;
662 update_all_widget_values (info
, deep_p
);
667 /* creating the widgets */
670 initialize_widget_instance (widget_instance
*instance
)
674 for (val
= instance
->info
->val
; val
; val
= val
->next
)
675 val
->change
= STRUCTURAL_CHANGE
;
677 update_one_widget_instance (instance
, True
);
679 for (val
= instance
->info
->val
; val
; val
= val
->next
)
680 val
->change
= NO_CHANGE
;
684 static widget_creation_function
685 find_in_table (const char *type
, const widget_creation_entry
*table
)
687 const widget_creation_entry
* cur
;
688 for (cur
= table
; cur
->type
; cur
++)
689 if (!c_strcasecmp (type
, cur
->type
))
690 return cur
->function
;
695 dialog_spec_p (const char *name
)
697 /* return True if name matches [EILPQeilpq][1-9][Bb] or
698 [EILPQeilpq][1-9][Bb][Rr][1-9] */
704 case 'E': case 'I': case 'L': case 'P': case 'Q':
705 case 'e': case 'i': case 'l': case 'p': case 'q':
706 if (name
[1] >= '0' && name
[1] <= '9')
708 if (name
[2] != 'B' && name
[2] != 'b')
712 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
714 if ((name
[3] == 'R' || name
[3] == 'r')
715 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
728 instantiate_widget_instance (widget_instance
*instance
)
730 widget_creation_function function
= NULL
;
732 #if defined (USE_LUCID)
734 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
736 #if defined(USE_MOTIF)
738 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
740 #if defined (USE_XAW)
742 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
747 if (dialog_spec_p (instance
->info
->type
))
749 #if defined (USE_LUCID)
752 #if defined(USE_MOTIF)
754 function
= xm_create_dialog
;
756 #if defined (USE_XAW)
758 function
= xaw_create_dialog
;
765 printf ("No creation function for widget type %s\n",
766 instance
->info
->type
);
770 instance
->widget
= (*function
) (instance
);
772 if (!instance
->widget
)
775 /* XtRealizeWidget (instance->widget);*/
779 lw_register_widget (const char* type
,
783 lw_callback pre_activate_cb
,
784 lw_callback selection_cb
,
785 lw_callback post_activate_cb
,
786 lw_callback highlight_cb
)
788 if (!get_widget_info (id
, False
))
789 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
790 post_activate_cb
, highlight_cb
);
794 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
796 widget_instance
* instance
;
798 instance
= find_instance (id
, parent
, pop_up_p
);
799 return instance
? instance
->widget
: NULL
;
803 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
805 widget_instance
* instance
;
808 instance
= find_instance (id
, parent
, pop_up_p
);
811 info
= get_widget_info (id
, False
);
814 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
815 initialize_widget_instance (instance
);
817 if (!instance
->widget
)
819 return instance
->widget
;
823 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
824 Widget parent
, Boolean pop_up_p
,
825 lw_callback pre_activate_cb
, lw_callback selection_cb
,
826 lw_callback post_activate_cb
, lw_callback highlight_cb
)
828 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
829 post_activate_cb
, highlight_cb
);
830 return lw_make_widget (id
, parent
, pop_up_p
);
834 /* destroying the widgets */
836 destroy_one_instance (widget_instance
*instance
)
838 /* Remove the destroy callback on the widget; that callback will try to
839 dereference the instance object (to set its widget slot to 0, since the
840 widget is dead.) Since the instance is now dead, we don't have to worry
841 about the fact that its widget is dead too.
843 This happens in the Phase2Destroy of the widget, so this callback would
844 not have been run until arbitrarily long after the instance was freed.
846 if (instance
->widget
)
847 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
848 mark_widget_destroyed
, (XtPointer
)instance
);
850 if (instance
->widget
)
852 /* The else are pretty tricky here, including the empty statement
853 at the end because it would be very bad to destroy a widget
855 #if defined (USE_LUCID)
856 if (lw_lucid_widget_p (instance
->widget
))
857 xlw_destroy_instance (instance
);
860 #if defined (USE_MOTIF)
861 if (lw_motif_widget_p (instance
->widget
))
862 xm_destroy_instance (instance
);
865 #if defined (USE_XAW)
866 if (lw_xaw_widget_p (instance
->widget
))
867 xaw_destroy_instance (instance
);
871 /* Empty compound statement to terminate if-then-else chain. */
875 free_widget_instance (instance
);
879 lw_destroy_widget (Widget w
)
881 widget_instance
* instance
= get_widget_instance (w
, True
);
885 widget_info
*info
= instance
->info
;
886 /* instance has already been removed from the list; free it */
887 destroy_one_instance (instance
);
888 /* if there are no instances left, free the info too */
889 if (!info
->instances
)
890 lw_destroy_all_widgets (info
->id
);
895 lw_destroy_all_widgets (LWLIB_ID id
)
897 widget_info
* info
= get_widget_info (id
, True
);
898 widget_instance
* instance
;
899 widget_instance
* next
;
903 for (instance
= info
->instances
; instance
; )
905 next
= instance
->next
;
906 destroy_one_instance (instance
);
909 free_widget_info (info
);
914 lw_destroy_everything (void)
916 while (all_widget_info
)
917 lw_destroy_all_widgets (all_widget_info
->id
);
921 lw_destroy_all_pop_ups (void)
925 widget_instance
* instance
;
927 for (info
= all_widget_info
; info
; info
= next
)
930 instance
= info
->instances
;
931 if (instance
&& instance
->pop_up_p
)
932 lw_destroy_all_widgets (info
->id
);
937 extern Widget
first_child (Widget
); /* garbage */
941 lw_raise_all_pop_up_widgets (void)
944 widget_instance
* instance
;
945 Widget result
= NULL
;
947 for (info
= all_widget_info
; info
; info
= info
->next
)
948 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
949 if (instance
->pop_up_p
)
951 Widget widget
= instance
->widget
;
954 if (XtIsManaged (widget
)
956 /* What a complete load of crap!!!!
957 When a dialogShell is on the screen, it is not managed!
959 || (lw_motif_widget_p (instance
->widget
) &&
960 XtIsManaged (first_child (widget
)))
966 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
974 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
976 widget_info
* info
= get_widget_info (id
, False
);
977 widget_instance
* instance
;
980 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
981 if (instance
->pop_up_p
&& instance
->widget
)
983 #if defined (USE_LUCID)
984 if (lw_lucid_widget_p (instance
->widget
))
986 XtRealizeWidget (instance
->widget
);
987 xlw_pop_instance (instance
, up
);
990 #if defined (USE_MOTIF)
991 if (lw_motif_widget_p (instance
->widget
))
993 XtRealizeWidget (instance
->widget
);
994 xm_pop_instance (instance
, up
);
997 #if defined (USE_XAW)
998 if (lw_xaw_widget_p (instance
->widget
))
1000 XtRealizeWidget (XtParent (instance
->widget
));
1001 XtRealizeWidget (instance
->widget
);
1002 xaw_pop_instance (instance
, up
);
1009 lw_pop_up_all_widgets (LWLIB_ID id
)
1011 lw_pop_all_widgets (id
, True
);
1015 lw_pop_down_all_widgets (LWLIB_ID id
)
1017 lw_pop_all_widgets (id
, False
);
1021 lw_popup_menu (Widget widget
, XEvent
*event
)
1023 #if defined (USE_LUCID)
1024 if (lw_lucid_widget_p (widget
))
1025 xlw_popup_menu (widget
, event
);
1027 #if defined (USE_MOTIF)
1028 if (lw_motif_widget_p (widget
))
1029 xm_popup_menu (widget
, event
);
1031 #if defined (USE_XAW)
1032 if (lw_xaw_widget_p (widget
))
1033 xaw_popup_menu (widget
, event
);
1037 \f/* get the values back */
1039 get_one_value (widget_instance
*instance
, widget_value
*val
)
1041 Widget widget
= name_to_widget (instance
, val
->name
);
1045 #if defined (USE_LUCID)
1046 if (lw_lucid_widget_p (instance
->widget
))
1047 xlw_update_one_value (instance
, widget
, val
);
1049 #if defined (USE_MOTIF)
1050 if (lw_motif_widget_p (instance
->widget
))
1051 xm_update_one_value (instance
, widget
, val
);
1053 #if defined (USE_XAW)
1054 if (lw_xaw_widget_p (instance
->widget
))
1055 xaw_update_one_value (instance
, widget
, val
);
1064 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1066 widget_info
* info
= get_widget_info (id
, False
);
1067 widget_instance
* instance
;
1069 Boolean result
= False
;
1074 instance
= info
->instances
;
1078 for (val
= val_out
; val
; val
= val
->next
)
1079 if (get_one_value (instance
, val
))
1086 lw_get_all_values (LWLIB_ID id
)
1088 widget_info
* info
= get_widget_info (id
, False
);
1089 widget_value
* val
= info
->val
;
1090 if (lw_get_some_values (id
, val
))
1096 /* internal function used by the library dependent implementation to get the
1097 widget_value for a given widget in an instance */
1099 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1101 char* name
= XtName (w
);
1103 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1104 if (!strcmp (cur
->name
, name
))
1109 \f/* update other instances value when one thing changed */
1111 /* To forbid recursive calls */
1112 static Boolean lwlib_updating
;
1114 /* This function can be used as an XtCallback for the widgets that get
1115 modified to update other instances of the widgets. Closure should be the
1118 lw_internal_update_other_instances (Widget widget
,
1120 XtPointer call_data
)
1122 widget_instance
* instance
= (widget_instance
*)closure
;
1123 char* name
= XtName (widget
);
1125 widget_instance
* cur
;
1128 /* Avoid possibly infinite recursion. */
1132 /* protect against the widget being destroyed */
1133 if (XtWidgetBeingDestroyedP (widget
))
1136 /* Return immediately if there are no other instances */
1137 info
= instance
->info
;
1138 if (!info
->instances
->next
)
1141 lwlib_updating
= True
;
1143 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1145 if (val
&& get_one_value (instance
, val
))
1146 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1147 if (cur
!= instance
)
1148 set_one_value (cur
, val
, True
);
1150 lwlib_updating
= False
;
1157 lw_get_widget_id (Widget w
)
1159 widget_instance
* instance
= get_widget_instance (w
, False
);
1161 return instance
? instance
->info
->id
: 0;
1164 \f/* set the keyboard focus */
1166 lw_set_keyboard_focus (Widget parent
, Widget w
)
1168 #if defined (USE_MOTIF)
1169 xm_set_keyboard_focus (parent
, w
);
1171 XtSetKeyboardFocus (parent
, w
);
1177 show_one_widget_busy (Widget w
, Boolean flag
)
1179 Pixel foreground
= 0;
1180 Pixel background
= 1;
1181 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1182 if (!widget_to_invert
)
1183 widget_to_invert
= w
;
1185 XtVaGetValues (widget_to_invert
,
1186 XtNforeground
, &foreground
,
1187 XtNbackground
, &background
,
1189 XtVaSetValues (widget_to_invert
,
1190 XtNforeground
, background
,
1191 XtNbackground
, foreground
,
1196 lw_show_busy (Widget w
, Boolean busy
)
1198 widget_instance
* instance
= get_widget_instance (w
, False
);
1200 widget_instance
* next
;
1204 info
= instance
->info
;
1205 if (info
->busy
!= busy
)
1207 for (next
= info
->instances
; next
; next
= next
->next
)
1209 show_one_widget_busy (next
->widget
, busy
);
1215 /* This hack exists because Lucid/Athena need to execute the strange
1216 function below to support geometry management. */
1218 lw_refigure_widget (Widget w
, Boolean doit
)
1220 #if defined (USE_XAW)
1221 XawPanedSetRefigureMode (w
, doit
);
1223 #if defined (USE_MOTIF)
1227 XtUnmanageChild (w
);
1231 /* Toolkit independent way of determining if an event window is in the
1234 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1236 return menubar_widget
1237 #if defined (USE_LUCID)
1238 && XtWindow (menubar_widget
) == win
;
1240 #if defined (USE_MOTIF)
1241 && ((XtWindow (menubar_widget
) == win
)
1242 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1243 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1244 == menubar_widget
)));
1248 /* Motif hack to set the main window areas. */
1250 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1252 #if defined (USE_MOTIF)
1253 xm_set_main_areas (parent
, menubar
, work_area
);
1257 /* Manage resizing for Motif. This disables resizing when the menubar
1258 is about to be modified. */
1260 lw_allow_resizing (Widget w
, Boolean flag
)
1262 #if defined (USE_MOTIF)
1263 xm_manage_resizing (w
, flag
);
1268 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1269 set to an appropriate enumerator of type enum menu_separator.
1270 MOTIF_P non-zero means map separator types not supported by Motif
1271 to similar ones that are supported. */
1274 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1276 int separator_p
= 0;
1278 if (strlen (label
) >= 3
1279 && memcmp (label
, "--:", 3) == 0)
1281 static struct separator_table
1284 enum menu_separator type
;
1288 {"space", SEPARATOR_NO_LINE
},
1289 {"noLine", SEPARATOR_NO_LINE
},
1290 {"singleLine", SEPARATOR_SINGLE_LINE
},
1291 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1292 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1293 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1294 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1295 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1296 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1297 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1298 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1299 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1300 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1301 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1308 for (i
= 0; separator_names
[i
].name
; ++i
)
1309 if (strcmp (label
, separator_names
[i
].name
) == 0)
1312 *type
= separator_names
[i
].type
;
1314 /* If separator type is not supported under Motif,
1315 use a similar one. */
1316 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1321 else if (strlen (label
) > 3
1322 && memcmp (label
, "--", 2) == 0
1325 /* Alternative, more Emacs-style names. */
1326 static struct separator_table
1329 enum menu_separator type
;
1333 {"space", SEPARATOR_NO_LINE
},
1334 {"no-line", SEPARATOR_NO_LINE
},
1335 {"single-line", SEPARATOR_SINGLE_LINE
},
1336 {"double-line", SEPARATOR_DOUBLE_LINE
},
1337 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1338 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1339 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1340 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1341 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1342 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1343 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1344 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1345 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1346 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1353 for (i
= 0; separator_names
[i
].name
; ++i
)
1354 if (strcmp (label
, separator_names
[i
].name
) == 0)
1357 *type
= separator_names
[i
].type
;
1359 /* If separator type is not supported under Motif,
1360 use a similar one. */
1361 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1368 /* Old-style separator, maybe. It's a separator if it contains
1370 while (*label
== '-')
1372 separator_p
= *label
== 0;
1373 *type
= SEPARATOR_SHADOW_ETCHED_IN
;