1 /* A general interface to the widgets of different toolkits.
3 Copyright (C) 1992, 1993 Lucid, Inc.
4 Copyright (C) 1994-1996, 1999-2012 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; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
27 #include <c-strcase.h>
29 #include <sys/types.h>
32 #include "lwlib-int.h"
33 #include "lwlib-utils.h"
34 #include <X11/StringDefs.h>
36 #if defined (USE_LUCID)
37 #include "lwlib-Xlw.h"
39 #if defined (USE_MOTIF)
41 #else /* not USE_MOTIF */
42 #if defined (USE_LUCID)
44 #endif /* not USE_MOTIF && USE_LUCID */
48 #include <X11/Xaw3d/Paned.h>
49 #else /* !HAVE_XAW3D */
50 #include <X11/Xaw/Paned.h>
51 #endif /* HAVE_XAW3D */
52 #include "lwlib-Xaw.h"
55 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
56 #error At least one of USE_LUCID or USE_MOTIF must be defined.
60 #define max(x, y) ((x) > (y) ? (x) : (y))
63 /* List of all widgets managed by the library. */
65 all_widget_info
= NULL
;
68 const char *lwlib_toolkit_type
= "motif";
70 const char *lwlib_toolkit_type
= "lucid";
73 static widget_value
*merge_widget_value (widget_value
*,
76 static void instantiate_widget_instance (widget_instance
*);
77 static void safe_free_str (char *);
78 static void free_widget_value_tree (widget_value
*);
79 static widget_value
*copy_widget_value_tree (widget_value
*,
81 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
83 lw_callback
, lw_callback
,
84 lw_callback
, lw_callback
);
85 static void free_widget_info (widget_info
*);
86 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
87 static widget_instance
*allocate_widget_instance (widget_info
*,
89 static void free_widget_instance (widget_instance
*);
90 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
91 static widget_instance
*get_widget_instance (Widget
, Boolean
);
92 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
93 static Boolean
safe_strcmp (const char *, const char *);
94 static Widget
name_to_widget (widget_instance
*, const char *);
95 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
96 static void update_one_widget_instance (widget_instance
*, Boolean
);
97 static void update_all_widget_values (widget_info
*, Boolean
);
98 static void initialize_widget_instance (widget_instance
*);
99 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
100 static Boolean
dialog_spec_p (const char *);
101 static void destroy_one_instance (widget_instance
*);
102 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
103 static Boolean
get_one_value (widget_instance
*, widget_value
*);
104 static void show_one_widget_busy (Widget
, Boolean
);
105 \f/* utility functions for widget_instance and widget_info */
107 safe_strdup (const char *s
)
111 result
= (char *) xmalloc (strlen (s
) + 1);
117 safe_free_str (char *s
)
122 static widget_value
*widget_value_free_list
= 0;
123 static int malloc_cpt
= 0;
126 malloc_widget_value (void)
129 if (widget_value_free_list
)
131 wv
= widget_value_free_list
;
132 widget_value_free_list
= wv
->free_list
;
137 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
140 memset ((void*) wv
, 0, sizeof (widget_value
));
144 /* this is analogous to free(). It frees only what was allocated
145 by malloc_widget_value(), and no substructures.
148 free_widget_value (widget_value
*wv
)
155 /* When the number of already allocated cells is too big,
162 wv
->free_list
= widget_value_free_list
;
163 widget_value_free_list
= wv
;
168 free_widget_value_tree (widget_value
*wv
)
177 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
179 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
181 XtFree (wv
->toolkit_data
);
182 wv
->toolkit_data
= (void *) 0xDEADBEEF;
185 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
187 free_widget_value_tree (wv
->contents
);
188 wv
->contents
= (widget_value
*) 0xDEADBEEF;
192 free_widget_value_tree (wv
->next
);
193 wv
->next
= (widget_value
*) 0xDEADBEEF;
195 free_widget_value (wv
);
198 static widget_value
*
199 copy_widget_value_tree (widget_value
*val
, change_type change
)
205 if (val
== (widget_value
*) 1)
208 copy
= malloc_widget_value ();
209 copy
->name
= safe_strdup (val
->name
);
210 copy
->value
= safe_strdup (val
->value
);
211 copy
->key
= safe_strdup (val
->key
);
212 copy
->help
= val
->help
;
213 copy
->enabled
= val
->enabled
;
214 copy
->button_type
= val
->button_type
;
215 copy
->selected
= val
->selected
;
216 copy
->edited
= False
;
217 copy
->change
= change
;
218 copy
->this_one_change
= change
;
219 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
220 copy
->call_data
= val
->call_data
;
221 copy
->next
= copy_widget_value_tree (val
->next
, change
);
222 copy
->toolkit_data
= NULL
;
223 copy
->free_toolkit_data
= False
;
228 allocate_widget_info (const char* type
,
232 lw_callback pre_activate_cb
,
233 lw_callback selection_cb
,
234 lw_callback post_activate_cb
,
235 lw_callback highlight_cb
)
237 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
238 info
->type
= safe_strdup (type
);
239 info
->name
= safe_strdup (name
);
241 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
243 info
->pre_activate_cb
= pre_activate_cb
;
244 info
->selection_cb
= selection_cb
;
245 info
->post_activate_cb
= post_activate_cb
;
246 info
->highlight_cb
= highlight_cb
;
247 info
->instances
= NULL
;
249 info
->next
= all_widget_info
;
250 all_widget_info
= info
;
256 free_widget_info (widget_info
*info
)
258 safe_free_str (info
->type
);
259 safe_free_str (info
->name
);
260 free_widget_value_tree (info
->val
);
261 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
266 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
268 widget_instance
* instance
= (widget_instance
*)closure
;
270 /* be very conservative */
271 if (instance
->widget
== widget
)
272 instance
->widget
= NULL
;
275 static widget_instance
*
276 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
278 widget_instance
* instance
=
279 (widget_instance
*) xmalloc (sizeof (widget_instance
));
280 memset (instance
, 0, sizeof *instance
);
281 instance
->parent
= parent
;
282 instance
->pop_up_p
= pop_up_p
;
283 instance
->info
= info
;
284 instance
->next
= info
->instances
;
285 info
->instances
= instance
;
287 instantiate_widget_instance (instance
);
289 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
290 mark_widget_destroyed
, (XtPointer
)instance
);
295 free_widget_instance (widget_instance
*instance
)
297 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
302 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
306 for (prev
= NULL
, info
= all_widget_info
;
308 prev
= info
, info
= info
->next
)
314 prev
->next
= info
->next
;
316 all_widget_info
= info
->next
;
323 /* Internal function used by the library dependent implementation to get the
324 widget_value for a given widget in an instance */
326 lw_get_widget_info (LWLIB_ID id
)
328 return get_widget_info (id
, 0);
331 static widget_instance
*
332 get_widget_instance (Widget widget
, Boolean remove_p
)
335 widget_instance
* instance
;
336 widget_instance
* prev
;
337 for (info
= all_widget_info
; info
; info
= info
->next
)
338 for (prev
= NULL
, instance
= info
->instances
;
340 prev
= instance
, instance
= instance
->next
)
341 if (instance
->widget
== widget
)
346 prev
->next
= instance
->next
;
348 info
->instances
= instance
->next
;
352 return (widget_instance
*) 0;
355 /* Value is a pointer to the widget_instance corresponding to
356 WIDGET, or null if WIDGET is not a lwlib widget. */
359 lw_get_widget_instance (Widget widget
)
361 return get_widget_instance (widget
, False
);
364 static widget_instance
*
365 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
367 widget_info
* info
= get_widget_info (id
, False
);
368 widget_instance
* instance
;
371 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
372 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
379 /* utility function for widget_value */
381 safe_strcmp (const char *s1
, const char *s2
)
383 if (!!s1
^ !!s2
) return True
;
384 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
389 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
390 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
392 (oc == NO_CHANGE ? "none" : \
393 (oc == INVISIBLE_CHANGE ? "invisible" : \
394 (oc == VISIBLE_CHANGE ? "visible" : \
395 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
397 (nc == NO_CHANGE ? "none" : \
398 (nc == INVISIBLE_CHANGE ? "invisible" : \
399 (nc == VISIBLE_CHANGE ? "visible" : \
400 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
403 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
407 static widget_value
*
408 merge_widget_value (widget_value
*val1
,
413 change_type change
, this_one_change
;
414 widget_value
* merged_next
;
415 widget_value
* merged_contents
;
422 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
430 free_widget_value_tree (val1
);
436 if (safe_strcmp (val1
->name
, val2
->name
))
438 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
439 val1
->name
, val2
->name
);
440 change
= max (change
, STRUCTURAL_CHANGE
);
441 safe_free_str (val1
->name
);
442 val1
->name
= safe_strdup (val2
->name
);
444 if (safe_strcmp (val1
->value
, val2
->value
))
446 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
447 val1
->value
, val2
->value
);
448 change
= max (change
, VISIBLE_CHANGE
);
449 safe_free_str (val1
->value
);
450 val1
->value
= safe_strdup (val2
->value
);
452 if (safe_strcmp (val1
->key
, val2
->key
))
454 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
455 val1
->key
, val2
->key
);
456 change
= max (change
, VISIBLE_CHANGE
);
457 safe_free_str (val1
->key
);
458 val1
->key
= safe_strdup (val2
->key
);
460 if (! EQ (val1
->help
, val2
->help
))
462 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
463 val1
->help
, val2
->help
);
464 change
= max (change
, VISIBLE_CHANGE
);
465 val1
->help
= val2
->help
;
467 if (val1
->enabled
!= val2
->enabled
)
469 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
470 val1
->enabled
, val2
->enabled
);
471 change
= max (change
, VISIBLE_CHANGE
);
472 val1
->enabled
= val2
->enabled
;
474 if (val1
->button_type
!= val2
->button_type
)
476 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
477 val1
->button_type
, val2
->button_type
);
478 change
= max (change
, VISIBLE_CHANGE
);
479 val1
->button_type
= val2
->button_type
;
481 if (val1
->selected
!= val2
->selected
)
483 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
484 val1
->selected
, val2
->selected
);
485 change
= max (change
, VISIBLE_CHANGE
);
486 val1
->selected
= val2
->selected
;
488 if (val1
->call_data
!= val2
->call_data
)
490 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
491 val1
->call_data
, val2
->call_data
);
492 change
= max (change
, INVISIBLE_CHANGE
);
493 val1
->call_data
= val2
->call_data
;
499 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
502 if (val1
->contents
&& !merged_contents
)
504 /* This used to say INVISIBLE_CHANGE,
505 but it is visible and vitally important when
506 the contents of the menu bar itself are entirely deleted.
508 But maybe it doesn't matter. This fails to fix the bug. */
509 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
511 change
= max (change
, STRUCTURAL_CHANGE
);
513 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
515 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
517 change
= max (change
, INVISIBLE_CHANGE
);
518 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
520 change
= max (merged_contents
->change
, change
);
525 val1
->contents
= merged_contents
;
528 this_one_change
= change
;
530 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
532 if (val1
->next
&& !merged_next
)
534 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
536 change
= max (change
, STRUCTURAL_CHANGE
);
538 else if (merged_next
)
540 if (merged_next
->change
)
541 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
543 change
= max (change
, merged_next
->change
);
546 val1
->next
= merged_next
;
548 val1
->this_one_change
= this_one_change
;
549 val1
->change
= change
;
551 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
554 if (val1
->free_toolkit_data
)
555 XtFree (val1
->toolkit_data
);
556 val1
->toolkit_data
= NULL
;
563 /* modifying the widgets */
565 name_to_widget (widget_instance
*instance
, const char *name
)
567 Widget widget
= NULL
;
569 if (!instance
->widget
)
572 if (!strcmp (XtName (instance
->widget
), name
))
573 widget
= instance
->widget
;
576 int length
= strlen (name
) + 2;
577 char* real_name
= (char *) xmalloc (length
);
579 strcpy (real_name
+ 1, name
);
581 widget
= XtNameToWidget (instance
->widget
, real_name
);
589 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
591 Widget widget
= name_to_widget (instance
, val
->name
);
595 #if defined (USE_LUCID)
596 if (lw_lucid_widget_p (instance
->widget
))
597 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
599 #if defined (USE_MOTIF)
600 if (lw_motif_widget_p (instance
->widget
))
601 xm_update_one_widget (instance
, widget
, val
, deep_p
);
603 #if defined (USE_XAW)
604 if (lw_xaw_widget_p (instance
->widget
))
605 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
611 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
615 if (!instance
->widget
)
616 /* the widget was destroyed */
619 for (val
= instance
->info
->val
; val
; val
= val
->next
)
620 if (val
->change
!= NO_CHANGE
)
621 set_one_value (instance
, val
, deep_p
);
625 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
627 widget_instance
* instance
;
630 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
631 update_one_widget_instance (instance
, deep_p
);
633 for (val
= info
->val
; val
; val
= val
->next
)
634 val
->change
= NO_CHANGE
;
638 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
640 widget_info
* info
= get_widget_info (id
, False
);
641 widget_value
* new_val
;
642 widget_value
* next_new_val
;
652 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
654 next_new_val
= new_val
->next
;
655 new_val
->next
= NULL
;
657 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
658 if (!strcmp (cur
->name
, new_val
->name
))
663 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
666 prev
->next
= cur
? cur
: next
;
668 info
->val
= cur
? cur
: next
;
675 /* Could not find it, add it */
677 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
679 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
682 new_val
->next
= next_new_val
;
685 update_all_widget_values (info
, deep_p
);
690 /* creating the widgets */
693 initialize_widget_instance (widget_instance
*instance
)
697 for (val
= instance
->info
->val
; val
; val
= val
->next
)
698 val
->change
= STRUCTURAL_CHANGE
;
700 update_one_widget_instance (instance
, True
);
702 for (val
= instance
->info
->val
; val
; val
= val
->next
)
703 val
->change
= NO_CHANGE
;
707 static widget_creation_function
708 find_in_table (const char *type
, const widget_creation_entry
*table
)
710 const widget_creation_entry
* cur
;
711 for (cur
= table
; cur
->type
; cur
++)
712 if (!c_strcasecmp (type
, cur
->type
))
713 return cur
->function
;
718 dialog_spec_p (const char *name
)
720 /* return True if name matches [EILPQeilpq][1-9][Bb] or
721 [EILPQeilpq][1-9][Bb][Rr][1-9] */
727 case 'E': case 'I': case 'L': case 'P': case 'Q':
728 case 'e': case 'i': case 'l': case 'p': case 'q':
729 if (name
[1] >= '0' && name
[1] <= '9')
731 if (name
[2] != 'B' && name
[2] != 'b')
735 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
737 if ((name
[3] == 'R' || name
[3] == 'r')
738 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
751 instantiate_widget_instance (widget_instance
*instance
)
753 widget_creation_function function
= NULL
;
755 #if defined (USE_LUCID)
757 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
759 #if defined(USE_MOTIF)
761 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
763 #if defined (USE_XAW)
765 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
770 if (dialog_spec_p (instance
->info
->type
))
772 #if defined (USE_LUCID)
775 #if defined(USE_MOTIF)
777 function
= xm_create_dialog
;
779 #if defined (USE_XAW)
781 function
= xaw_create_dialog
;
788 printf ("No creation function for widget type %s\n",
789 instance
->info
->type
);
793 instance
->widget
= (*function
) (instance
);
795 if (!instance
->widget
)
798 /* XtRealizeWidget (instance->widget);*/
802 lw_register_widget (const char* type
,
806 lw_callback pre_activate_cb
,
807 lw_callback selection_cb
,
808 lw_callback post_activate_cb
,
809 lw_callback highlight_cb
)
811 if (!get_widget_info (id
, False
))
812 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
813 post_activate_cb
, highlight_cb
);
817 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
819 widget_instance
* instance
;
821 instance
= find_instance (id
, parent
, pop_up_p
);
822 return instance
? instance
->widget
: NULL
;
826 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
828 widget_instance
* instance
;
831 instance
= find_instance (id
, parent
, pop_up_p
);
834 info
= get_widget_info (id
, False
);
837 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
838 initialize_widget_instance (instance
);
840 if (!instance
->widget
)
842 return instance
->widget
;
846 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
847 Widget parent
, Boolean pop_up_p
,
848 lw_callback pre_activate_cb
, lw_callback selection_cb
,
849 lw_callback post_activate_cb
, lw_callback highlight_cb
)
851 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
852 post_activate_cb
, highlight_cb
);
853 return lw_make_widget (id
, parent
, pop_up_p
);
857 /* destroying the widgets */
859 destroy_one_instance (widget_instance
*instance
)
861 /* Remove the destroy callback on the widget; that callback will try to
862 dereference the instance object (to set its widget slot to 0, since the
863 widget is dead.) Since the instance is now dead, we don't have to worry
864 about the fact that its widget is dead too.
866 This happens in the Phase2Destroy of the widget, so this callback would
867 not have been run until arbitrarily long after the instance was freed.
869 if (instance
->widget
)
870 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
871 mark_widget_destroyed
, (XtPointer
)instance
);
873 if (instance
->widget
)
875 /* The else are pretty tricky here, including the empty statement
876 at the end because it would be very bad to destroy a widget
878 #if defined (USE_LUCID)
879 if (lw_lucid_widget_p (instance
->widget
))
880 xlw_destroy_instance (instance
);
883 #if defined (USE_MOTIF)
884 if (lw_motif_widget_p (instance
->widget
))
885 xm_destroy_instance (instance
);
888 #if defined (USE_XAW)
889 if (lw_xaw_widget_p (instance
->widget
))
890 xaw_destroy_instance (instance
);
894 /* Empty compound statement to terminate if-then-else chain. */
898 free_widget_instance (instance
);
902 lw_destroy_widget (Widget w
)
904 widget_instance
* instance
= get_widget_instance (w
, True
);
908 widget_info
*info
= instance
->info
;
909 /* instance has already been removed from the list; free it */
910 destroy_one_instance (instance
);
911 /* if there are no instances left, free the info too */
912 if (!info
->instances
)
913 lw_destroy_all_widgets (info
->id
);
918 lw_destroy_all_widgets (LWLIB_ID id
)
920 widget_info
* info
= get_widget_info (id
, True
);
921 widget_instance
* instance
;
922 widget_instance
* next
;
926 for (instance
= info
->instances
; instance
; )
928 next
= instance
->next
;
929 destroy_one_instance (instance
);
932 free_widget_info (info
);
937 lw_destroy_everything (void)
939 while (all_widget_info
)
940 lw_destroy_all_widgets (all_widget_info
->id
);
944 lw_destroy_all_pop_ups (void)
948 widget_instance
* instance
;
950 for (info
= all_widget_info
; info
; info
= next
)
953 instance
= info
->instances
;
954 if (instance
&& instance
->pop_up_p
)
955 lw_destroy_all_widgets (info
->id
);
960 extern Widget
first_child (Widget
); /* garbage */
964 lw_raise_all_pop_up_widgets (void)
967 widget_instance
* instance
;
968 Widget result
= NULL
;
970 for (info
= all_widget_info
; info
; info
= info
->next
)
971 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
972 if (instance
->pop_up_p
)
974 Widget widget
= instance
->widget
;
977 if (XtIsManaged (widget
)
979 /* What a complete load of crap!!!!
980 When a dialogShell is on the screen, it is not managed!
982 || (lw_motif_widget_p (instance
->widget
) &&
983 XtIsManaged (first_child (widget
)))
989 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
997 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
999 widget_info
* info
= get_widget_info (id
, False
);
1000 widget_instance
* instance
;
1003 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1004 if (instance
->pop_up_p
&& instance
->widget
)
1006 #if defined (USE_LUCID)
1007 if (lw_lucid_widget_p (instance
->widget
))
1009 XtRealizeWidget (instance
->widget
);
1010 xlw_pop_instance (instance
, up
);
1013 #if defined (USE_MOTIF)
1014 if (lw_motif_widget_p (instance
->widget
))
1016 XtRealizeWidget (instance
->widget
);
1017 xm_pop_instance (instance
, up
);
1020 #if defined (USE_XAW)
1021 if (lw_xaw_widget_p (instance
->widget
))
1023 XtRealizeWidget (XtParent (instance
->widget
));
1024 XtRealizeWidget (instance
->widget
);
1025 xaw_pop_instance (instance
, up
);
1032 lw_pop_up_all_widgets (LWLIB_ID id
)
1034 lw_pop_all_widgets (id
, True
);
1038 lw_pop_down_all_widgets (LWLIB_ID id
)
1040 lw_pop_all_widgets (id
, False
);
1044 lw_popup_menu (Widget widget
, XEvent
*event
)
1046 #if defined (USE_LUCID)
1047 if (lw_lucid_widget_p (widget
))
1048 xlw_popup_menu (widget
, event
);
1050 #if defined (USE_MOTIF)
1051 if (lw_motif_widget_p (widget
))
1052 xm_popup_menu (widget
, event
);
1054 #if defined (USE_XAW)
1055 if (lw_xaw_widget_p (widget
))
1056 xaw_popup_menu (widget
, event
);
1060 \f/* get the values back */
1062 get_one_value (widget_instance
*instance
, widget_value
*val
)
1064 Widget widget
= name_to_widget (instance
, val
->name
);
1068 #if defined (USE_LUCID)
1069 if (lw_lucid_widget_p (instance
->widget
))
1070 xlw_update_one_value (instance
, widget
, val
);
1072 #if defined (USE_MOTIF)
1073 if (lw_motif_widget_p (instance
->widget
))
1074 xm_update_one_value (instance
, widget
, val
);
1076 #if defined (USE_XAW)
1077 if (lw_xaw_widget_p (instance
->widget
))
1078 xaw_update_one_value (instance
, widget
, val
);
1087 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1089 widget_info
* info
= get_widget_info (id
, False
);
1090 widget_instance
* instance
;
1092 Boolean result
= False
;
1097 instance
= info
->instances
;
1101 for (val
= val_out
; val
; val
= val
->next
)
1102 if (get_one_value (instance
, val
))
1109 lw_get_all_values (LWLIB_ID id
)
1111 widget_info
* info
= get_widget_info (id
, False
);
1112 widget_value
* val
= info
->val
;
1113 if (lw_get_some_values (id
, val
))
1119 /* internal function used by the library dependent implementation to get the
1120 widget_value for a given widget in an instance */
1122 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1124 char* name
= XtName (w
);
1126 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1127 if (!strcmp (cur
->name
, name
))
1132 \f/* update other instances value when one thing changed */
1134 /* To forbid recursive calls */
1135 static Boolean lwlib_updating
;
1137 /* This function can be used as an XtCallback for the widgets that get
1138 modified to update other instances of the widgets. Closure should be the
1141 lw_internal_update_other_instances (Widget widget
,
1143 XtPointer call_data
)
1145 widget_instance
* instance
= (widget_instance
*)closure
;
1146 char* name
= XtName (widget
);
1148 widget_instance
* cur
;
1151 /* Avoid possibly infinite recursion. */
1155 /* protect against the widget being destroyed */
1156 if (XtWidgetBeingDestroyedP (widget
))
1159 /* Return immediately if there are no other instances */
1160 info
= instance
->info
;
1161 if (!info
->instances
->next
)
1164 lwlib_updating
= True
;
1166 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1168 if (val
&& get_one_value (instance
, val
))
1169 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1170 if (cur
!= instance
)
1171 set_one_value (cur
, val
, True
);
1173 lwlib_updating
= False
;
1180 lw_get_widget_id (Widget w
)
1182 widget_instance
* instance
= get_widget_instance (w
, False
);
1184 return instance
? instance
->info
->id
: 0;
1187 \f/* set the keyboard focus */
1189 lw_set_keyboard_focus (Widget parent
, Widget w
)
1191 #if defined (USE_MOTIF)
1192 xm_set_keyboard_focus (parent
, w
);
1194 XtSetKeyboardFocus (parent
, w
);
1200 show_one_widget_busy (Widget w
, Boolean flag
)
1202 Pixel foreground
= 0;
1203 Pixel background
= 1;
1204 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1205 if (!widget_to_invert
)
1206 widget_to_invert
= w
;
1208 XtVaGetValues (widget_to_invert
,
1209 XtNforeground
, &foreground
,
1210 XtNbackground
, &background
,
1212 XtVaSetValues (widget_to_invert
,
1213 XtNforeground
, background
,
1214 XtNbackground
, foreground
,
1219 lw_show_busy (Widget w
, Boolean busy
)
1221 widget_instance
* instance
= get_widget_instance (w
, False
);
1223 widget_instance
* next
;
1227 info
= instance
->info
;
1228 if (info
->busy
!= busy
)
1230 for (next
= info
->instances
; next
; next
= next
->next
)
1232 show_one_widget_busy (next
->widget
, busy
);
1238 /* This hack exists because Lucid/Athena need to execute the strange
1239 function below to support geometry management. */
1241 lw_refigure_widget (Widget w
, Boolean doit
)
1243 #if defined (USE_XAW)
1244 XawPanedSetRefigureMode (w
, doit
);
1246 #if defined (USE_MOTIF)
1250 XtUnmanageChild (w
);
1254 /* Toolkit independent way of determining if an event window is in the
1257 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1259 return menubar_widget
1260 #if defined (USE_LUCID)
1261 && XtWindow (menubar_widget
) == win
;
1263 #if defined (USE_MOTIF)
1264 && ((XtWindow (menubar_widget
) == win
)
1265 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1266 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1267 == menubar_widget
)));
1271 /* Motif hack to set the main window areas. */
1273 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1275 #if defined (USE_MOTIF)
1276 xm_set_main_areas (parent
, menubar
, work_area
);
1280 /* Manage resizing for Motif. This disables resizing when the menubar
1281 is about to be modified. */
1283 lw_allow_resizing (Widget w
, Boolean flag
)
1285 #if defined (USE_MOTIF)
1286 xm_manage_resizing (w
, flag
);
1291 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1292 set to an appropriate enumerator of type enum menu_separator.
1293 MOTIF_P non-zero means map separator types not supported by Motif
1294 to similar ones that are supported. */
1297 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1299 int separator_p
= 0;
1301 if (strlen (label
) >= 3
1302 && memcmp (label
, "--:", 3) == 0)
1304 static struct separator_table
1307 enum menu_separator type
;
1311 {"space", SEPARATOR_NO_LINE
},
1312 {"noLine", SEPARATOR_NO_LINE
},
1313 {"singleLine", SEPARATOR_SINGLE_LINE
},
1314 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1315 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1316 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1317 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1318 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1319 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1320 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1321 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1322 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1323 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1324 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1331 for (i
= 0; separator_names
[i
].name
; ++i
)
1332 if (strcmp (label
, separator_names
[i
].name
) == 0)
1335 *type
= separator_names
[i
].type
;
1337 /* If separator type is not supported under Motif,
1338 use a similar one. */
1339 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1344 else if (strlen (label
) > 3
1345 && memcmp (label
, "--", 2) == 0
1348 /* Alternative, more Emacs-style names. */
1349 static struct separator_table
1352 enum menu_separator type
;
1356 {"space", SEPARATOR_NO_LINE
},
1357 {"no-line", SEPARATOR_NO_LINE
},
1358 {"single-line", SEPARATOR_SINGLE_LINE
},
1359 {"double-line", SEPARATOR_DOUBLE_LINE
},
1360 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1361 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1362 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1363 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1364 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1365 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1366 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1367 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1368 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1369 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1376 for (i
= 0; separator_names
[i
].name
; ++i
)
1377 if (strcmp (label
, separator_names
[i
].name
) == 0)
1380 *type
= separator_names
[i
].type
;
1382 /* If separator type is not supported under Motif,
1383 use a similar one. */
1384 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1391 /* Old-style separator, maybe. It's a separator if it contains
1393 while (*label
== '-')
1395 separator_p
= *label
== 0;
1396 *type
= SEPARATOR_SHADOW_ETCHED_IN
;