1 /* A general interface to the widgets of different toolkits.
3 Copyright (C) 1992, 1993 Lucid, Inc.
4 Copyright (C) 1994-1996, 1999-2013 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 safe_free_str (char *);
75 static void free_widget_value_tree (widget_value
*);
76 static widget_value
*copy_widget_value_tree (widget_value
*,
78 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
80 lw_callback
, lw_callback
,
81 lw_callback
, lw_callback
);
82 static void free_widget_info (widget_info
*);
83 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
84 static widget_instance
*allocate_widget_instance (widget_info
*,
86 static void free_widget_instance (widget_instance
*);
87 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
88 static widget_instance
*get_widget_instance (Widget
, Boolean
);
89 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
90 static Boolean
safe_strcmp (const char *, const char *);
91 static Widget
name_to_widget (widget_instance
*, const char *);
92 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
93 static void update_one_widget_instance (widget_instance
*, Boolean
);
94 static void update_all_widget_values (widget_info
*, Boolean
);
95 static void initialize_widget_instance (widget_instance
*);
96 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
97 static Boolean
dialog_spec_p (const char *);
98 static void destroy_one_instance (widget_instance
*);
99 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
100 static Boolean
get_one_value (widget_instance
*, widget_value
*);
101 static void show_one_widget_busy (Widget
, Boolean
);
102 \f/* utility functions for widget_instance and widget_info */
104 safe_strdup (const char *s
)
108 result
= (char *) xmalloc (strlen (s
) + 1);
114 safe_free_str (char *s
)
119 static widget_value
*widget_value_free_list
= 0;
120 static int malloc_cpt
= 0;
123 malloc_widget_value (void)
126 if (widget_value_free_list
)
128 wv
= widget_value_free_list
;
129 widget_value_free_list
= wv
->free_list
;
134 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
137 memset ((void*) wv
, 0, sizeof (widget_value
));
141 /* this is analogous to free(). It frees only what was allocated
142 by malloc_widget_value(), and no substructures.
145 free_widget_value (widget_value
*wv
)
152 /* When the number of already allocated cells is too big,
159 wv
->free_list
= widget_value_free_list
;
160 widget_value_free_list
= wv
;
165 free_widget_value_tree (widget_value
*wv
)
174 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
176 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
178 XtFree (wv
->toolkit_data
);
179 wv
->toolkit_data
= (void *) 0xDEADBEEF;
182 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
184 free_widget_value_tree (wv
->contents
);
185 wv
->contents
= (widget_value
*) 0xDEADBEEF;
189 free_widget_value_tree (wv
->next
);
190 wv
->next
= (widget_value
*) 0xDEADBEEF;
192 free_widget_value (wv
);
195 static widget_value
*
196 copy_widget_value_tree (widget_value
*val
, change_type change
)
202 if (val
== (widget_value
*) 1)
205 copy
= malloc_widget_value ();
206 copy
->name
= safe_strdup (val
->name
);
207 copy
->value
= safe_strdup (val
->value
);
208 copy
->key
= safe_strdup (val
->key
);
209 copy
->help
= val
->help
;
210 copy
->enabled
= val
->enabled
;
211 copy
->button_type
= val
->button_type
;
212 copy
->selected
= val
->selected
;
213 copy
->edited
= False
;
214 copy
->change
= change
;
215 copy
->this_one_change
= change
;
216 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
217 copy
->call_data
= val
->call_data
;
218 copy
->next
= copy_widget_value_tree (val
->next
, change
);
219 copy
->toolkit_data
= NULL
;
220 copy
->free_toolkit_data
= False
;
225 allocate_widget_info (const char* type
,
229 lw_callback pre_activate_cb
,
230 lw_callback selection_cb
,
231 lw_callback post_activate_cb
,
232 lw_callback highlight_cb
)
234 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
235 info
->type
= safe_strdup (type
);
236 info
->name
= safe_strdup (name
);
238 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
240 info
->pre_activate_cb
= pre_activate_cb
;
241 info
->selection_cb
= selection_cb
;
242 info
->post_activate_cb
= post_activate_cb
;
243 info
->highlight_cb
= highlight_cb
;
244 info
->instances
= NULL
;
246 info
->next
= all_widget_info
;
247 all_widget_info
= info
;
253 free_widget_info (widget_info
*info
)
255 safe_free_str (info
->type
);
256 safe_free_str (info
->name
);
257 free_widget_value_tree (info
->val
);
258 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
263 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
265 widget_instance
* instance
= (widget_instance
*)closure
;
267 /* be very conservative */
268 if (instance
->widget
== widget
)
269 instance
->widget
= NULL
;
272 static widget_instance
*
273 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
275 widget_instance
* instance
=
276 (widget_instance
*) xmalloc (sizeof (widget_instance
));
277 memset (instance
, 0, sizeof *instance
);
278 instance
->parent
= parent
;
279 instance
->pop_up_p
= pop_up_p
;
280 instance
->info
= info
;
281 instance
->next
= info
->instances
;
282 info
->instances
= instance
;
284 instantiate_widget_instance (instance
);
286 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
287 mark_widget_destroyed
, (XtPointer
)instance
);
292 free_widget_instance (widget_instance
*instance
)
294 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
299 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
303 for (prev
= NULL
, info
= all_widget_info
;
305 prev
= info
, info
= info
->next
)
311 prev
->next
= info
->next
;
313 all_widget_info
= info
->next
;
320 /* Internal function used by the library dependent implementation to get the
321 widget_value for a given widget in an instance */
323 lw_get_widget_info (LWLIB_ID id
)
325 return get_widget_info (id
, 0);
328 static widget_instance
*
329 get_widget_instance (Widget widget
, Boolean remove_p
)
332 widget_instance
* instance
;
333 widget_instance
* prev
;
334 for (info
= all_widget_info
; info
; info
= info
->next
)
335 for (prev
= NULL
, instance
= info
->instances
;
337 prev
= instance
, instance
= instance
->next
)
338 if (instance
->widget
== widget
)
343 prev
->next
= instance
->next
;
345 info
->instances
= instance
->next
;
349 return (widget_instance
*) 0;
352 /* Value is a pointer to the widget_instance corresponding to
353 WIDGET, or null if WIDGET is not a lwlib widget. */
356 lw_get_widget_instance (Widget widget
)
358 return get_widget_instance (widget
, False
);
361 static widget_instance
*
362 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
364 widget_info
* info
= get_widget_info (id
, False
);
365 widget_instance
* instance
;
368 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
369 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
376 /* utility function for widget_value */
378 safe_strcmp (const char *s1
, const char *s2
)
380 if (!!s1
^ !!s2
) return True
;
381 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
386 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
387 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
389 (oc == NO_CHANGE ? "none" : \
390 (oc == INVISIBLE_CHANGE ? "invisible" : \
391 (oc == VISIBLE_CHANGE ? "visible" : \
392 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
394 (nc == NO_CHANGE ? "none" : \
395 (nc == INVISIBLE_CHANGE ? "invisible" : \
396 (nc == VISIBLE_CHANGE ? "visible" : \
397 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
400 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
404 static widget_value
*
405 merge_widget_value (widget_value
*val1
,
410 change_type change
, this_one_change
;
411 widget_value
* merged_next
;
412 widget_value
* merged_contents
;
419 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
427 free_widget_value_tree (val1
);
433 if (safe_strcmp (val1
->name
, val2
->name
))
435 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
436 val1
->name
, val2
->name
);
437 change
= max (change
, STRUCTURAL_CHANGE
);
438 safe_free_str (val1
->name
);
439 val1
->name
= safe_strdup (val2
->name
);
441 if (safe_strcmp (val1
->value
, val2
->value
))
443 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
444 val1
->value
, val2
->value
);
445 change
= max (change
, VISIBLE_CHANGE
);
446 safe_free_str (val1
->value
);
447 val1
->value
= safe_strdup (val2
->value
);
449 if (safe_strcmp (val1
->key
, val2
->key
))
451 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
452 val1
->key
, val2
->key
);
453 change
= max (change
, VISIBLE_CHANGE
);
454 safe_free_str (val1
->key
);
455 val1
->key
= safe_strdup (val2
->key
);
457 if (! EQ (val1
->help
, val2
->help
))
459 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
460 val1
->help
, val2
->help
);
461 change
= max (change
, VISIBLE_CHANGE
);
462 val1
->help
= val2
->help
;
464 if (val1
->enabled
!= val2
->enabled
)
466 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
467 val1
->enabled
, val2
->enabled
);
468 change
= max (change
, VISIBLE_CHANGE
);
469 val1
->enabled
= val2
->enabled
;
471 if (val1
->button_type
!= val2
->button_type
)
473 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
474 val1
->button_type
, val2
->button_type
);
475 change
= max (change
, VISIBLE_CHANGE
);
476 val1
->button_type
= val2
->button_type
;
478 if (val1
->selected
!= val2
->selected
)
480 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
481 val1
->selected
, val2
->selected
);
482 change
= max (change
, VISIBLE_CHANGE
);
483 val1
->selected
= val2
->selected
;
485 if (val1
->call_data
!= val2
->call_data
)
487 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
488 val1
->call_data
, val2
->call_data
);
489 change
= max (change
, INVISIBLE_CHANGE
);
490 val1
->call_data
= val2
->call_data
;
496 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
499 if (val1
->contents
&& !merged_contents
)
501 /* This used to say INVISIBLE_CHANGE,
502 but it is visible and vitally important when
503 the contents of the menu bar itself are entirely deleted.
505 But maybe it doesn't matter. This fails to fix the bug. */
506 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
508 change
= max (change
, STRUCTURAL_CHANGE
);
510 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
512 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
514 change
= max (change
, INVISIBLE_CHANGE
);
515 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
517 change
= max (merged_contents
->change
, change
);
522 val1
->contents
= merged_contents
;
525 this_one_change
= change
;
527 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
529 if (val1
->next
&& !merged_next
)
531 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
533 change
= max (change
, STRUCTURAL_CHANGE
);
535 else if (merged_next
)
537 if (merged_next
->change
)
538 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
540 change
= max (change
, merged_next
->change
);
543 val1
->next
= merged_next
;
545 val1
->this_one_change
= this_one_change
;
546 val1
->change
= change
;
548 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
551 if (val1
->free_toolkit_data
)
552 XtFree (val1
->toolkit_data
);
553 val1
->toolkit_data
= NULL
;
560 /* modifying the widgets */
562 name_to_widget (widget_instance
*instance
, const char *name
)
564 Widget widget
= NULL
;
566 if (!instance
->widget
)
569 if (!strcmp (XtName (instance
->widget
), name
))
570 widget
= instance
->widget
;
573 int length
= strlen (name
) + 2;
574 char* real_name
= (char *) xmalloc (length
);
576 strcpy (real_name
+ 1, name
);
578 widget
= XtNameToWidget (instance
->widget
, real_name
);
586 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
588 Widget widget
= name_to_widget (instance
, val
->name
);
592 #if defined (USE_LUCID)
593 if (lw_lucid_widget_p (instance
->widget
))
594 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
596 #if defined (USE_MOTIF)
597 if (lw_motif_widget_p (instance
->widget
))
598 xm_update_one_widget (instance
, widget
, val
, deep_p
);
600 #if defined (USE_XAW)
601 if (lw_xaw_widget_p (instance
->widget
))
602 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
608 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
612 if (!instance
->widget
)
613 /* the widget was destroyed */
616 for (val
= instance
->info
->val
; val
; val
= val
->next
)
617 if (val
->change
!= NO_CHANGE
)
618 set_one_value (instance
, val
, deep_p
);
622 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
624 widget_instance
* instance
;
627 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
628 update_one_widget_instance (instance
, deep_p
);
630 for (val
= info
->val
; val
; val
= val
->next
)
631 val
->change
= NO_CHANGE
;
635 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
637 widget_info
* info
= get_widget_info (id
, False
);
638 widget_value
* new_val
;
639 widget_value
* next_new_val
;
649 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
651 next_new_val
= new_val
->next
;
652 new_val
->next
= NULL
;
654 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
655 if (!strcmp (cur
->name
, new_val
->name
))
660 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
663 prev
->next
= cur
? cur
: next
;
665 info
->val
= cur
? cur
: next
;
672 /* Could not find it, add it */
674 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
676 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
679 new_val
->next
= next_new_val
;
682 update_all_widget_values (info
, deep_p
);
687 /* creating the widgets */
690 initialize_widget_instance (widget_instance
*instance
)
694 for (val
= instance
->info
->val
; val
; val
= val
->next
)
695 val
->change
= STRUCTURAL_CHANGE
;
697 update_one_widget_instance (instance
, True
);
699 for (val
= instance
->info
->val
; val
; val
= val
->next
)
700 val
->change
= NO_CHANGE
;
704 static widget_creation_function
705 find_in_table (const char *type
, const widget_creation_entry
*table
)
707 const widget_creation_entry
* cur
;
708 for (cur
= table
; cur
->type
; cur
++)
709 if (!c_strcasecmp (type
, cur
->type
))
710 return cur
->function
;
715 dialog_spec_p (const char *name
)
717 /* return True if name matches [EILPQeilpq][1-9][Bb] or
718 [EILPQeilpq][1-9][Bb][Rr][1-9] */
724 case 'E': case 'I': case 'L': case 'P': case 'Q':
725 case 'e': case 'i': case 'l': case 'p': case 'q':
726 if (name
[1] >= '0' && name
[1] <= '9')
728 if (name
[2] != 'B' && name
[2] != 'b')
732 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
734 if ((name
[3] == 'R' || name
[3] == 'r')
735 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
748 instantiate_widget_instance (widget_instance
*instance
)
750 widget_creation_function function
= NULL
;
752 #if defined (USE_LUCID)
754 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
756 #if defined(USE_MOTIF)
758 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
760 #if defined (USE_XAW)
762 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
767 if (dialog_spec_p (instance
->info
->type
))
769 #if defined (USE_LUCID)
772 #if defined(USE_MOTIF)
774 function
= xm_create_dialog
;
776 #if defined (USE_XAW)
778 function
= xaw_create_dialog
;
785 printf ("No creation function for widget type %s\n",
786 instance
->info
->type
);
790 instance
->widget
= (*function
) (instance
);
792 if (!instance
->widget
)
795 /* XtRealizeWidget (instance->widget);*/
799 lw_register_widget (const char* type
,
803 lw_callback pre_activate_cb
,
804 lw_callback selection_cb
,
805 lw_callback post_activate_cb
,
806 lw_callback highlight_cb
)
808 if (!get_widget_info (id
, False
))
809 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
810 post_activate_cb
, highlight_cb
);
814 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
816 widget_instance
* instance
;
818 instance
= find_instance (id
, parent
, pop_up_p
);
819 return instance
? instance
->widget
: NULL
;
823 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
825 widget_instance
* instance
;
828 instance
= find_instance (id
, parent
, pop_up_p
);
831 info
= get_widget_info (id
, False
);
834 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
835 initialize_widget_instance (instance
);
837 if (!instance
->widget
)
839 return instance
->widget
;
843 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
844 Widget parent
, Boolean pop_up_p
,
845 lw_callback pre_activate_cb
, lw_callback selection_cb
,
846 lw_callback post_activate_cb
, lw_callback highlight_cb
)
848 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
849 post_activate_cb
, highlight_cb
);
850 return lw_make_widget (id
, parent
, pop_up_p
);
854 /* destroying the widgets */
856 destroy_one_instance (widget_instance
*instance
)
858 /* Remove the destroy callback on the widget; that callback will try to
859 dereference the instance object (to set its widget slot to 0, since the
860 widget is dead.) Since the instance is now dead, we don't have to worry
861 about the fact that its widget is dead too.
863 This happens in the Phase2Destroy of the widget, so this callback would
864 not have been run until arbitrarily long after the instance was freed.
866 if (instance
->widget
)
867 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
868 mark_widget_destroyed
, (XtPointer
)instance
);
870 if (instance
->widget
)
872 /* The else are pretty tricky here, including the empty statement
873 at the end because it would be very bad to destroy a widget
875 #if defined (USE_LUCID)
876 if (lw_lucid_widget_p (instance
->widget
))
877 xlw_destroy_instance (instance
);
880 #if defined (USE_MOTIF)
881 if (lw_motif_widget_p (instance
->widget
))
882 xm_destroy_instance (instance
);
885 #if defined (USE_XAW)
886 if (lw_xaw_widget_p (instance
->widget
))
887 xaw_destroy_instance (instance
);
891 /* Empty compound statement to terminate if-then-else chain. */
895 free_widget_instance (instance
);
899 lw_destroy_widget (Widget w
)
901 widget_instance
* instance
= get_widget_instance (w
, True
);
905 widget_info
*info
= instance
->info
;
906 /* instance has already been removed from the list; free it */
907 destroy_one_instance (instance
);
908 /* if there are no instances left, free the info too */
909 if (!info
->instances
)
910 lw_destroy_all_widgets (info
->id
);
915 lw_destroy_all_widgets (LWLIB_ID id
)
917 widget_info
* info
= get_widget_info (id
, True
);
918 widget_instance
* instance
;
919 widget_instance
* next
;
923 for (instance
= info
->instances
; instance
; )
925 next
= instance
->next
;
926 destroy_one_instance (instance
);
929 free_widget_info (info
);
934 lw_destroy_everything (void)
936 while (all_widget_info
)
937 lw_destroy_all_widgets (all_widget_info
->id
);
941 lw_destroy_all_pop_ups (void)
945 widget_instance
* instance
;
947 for (info
= all_widget_info
; info
; info
= next
)
950 instance
= info
->instances
;
951 if (instance
&& instance
->pop_up_p
)
952 lw_destroy_all_widgets (info
->id
);
957 extern Widget
first_child (Widget
); /* garbage */
961 lw_raise_all_pop_up_widgets (void)
964 widget_instance
* instance
;
965 Widget result
= NULL
;
967 for (info
= all_widget_info
; info
; info
= info
->next
)
968 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
969 if (instance
->pop_up_p
)
971 Widget widget
= instance
->widget
;
974 if (XtIsManaged (widget
)
976 /* What a complete load of crap!!!!
977 When a dialogShell is on the screen, it is not managed!
979 || (lw_motif_widget_p (instance
->widget
) &&
980 XtIsManaged (first_child (widget
)))
986 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
994 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
996 widget_info
* info
= get_widget_info (id
, False
);
997 widget_instance
* instance
;
1000 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1001 if (instance
->pop_up_p
&& instance
->widget
)
1003 #if defined (USE_LUCID)
1004 if (lw_lucid_widget_p (instance
->widget
))
1006 XtRealizeWidget (instance
->widget
);
1007 xlw_pop_instance (instance
, up
);
1010 #if defined (USE_MOTIF)
1011 if (lw_motif_widget_p (instance
->widget
))
1013 XtRealizeWidget (instance
->widget
);
1014 xm_pop_instance (instance
, up
);
1017 #if defined (USE_XAW)
1018 if (lw_xaw_widget_p (instance
->widget
))
1020 XtRealizeWidget (XtParent (instance
->widget
));
1021 XtRealizeWidget (instance
->widget
);
1022 xaw_pop_instance (instance
, up
);
1029 lw_pop_up_all_widgets (LWLIB_ID id
)
1031 lw_pop_all_widgets (id
, True
);
1035 lw_pop_down_all_widgets (LWLIB_ID id
)
1037 lw_pop_all_widgets (id
, False
);
1041 lw_popup_menu (Widget widget
, XEvent
*event
)
1043 #if defined (USE_LUCID)
1044 if (lw_lucid_widget_p (widget
))
1045 xlw_popup_menu (widget
, event
);
1047 #if defined (USE_MOTIF)
1048 if (lw_motif_widget_p (widget
))
1049 xm_popup_menu (widget
, event
);
1051 #if defined (USE_XAW)
1052 if (lw_xaw_widget_p (widget
))
1053 xaw_popup_menu (widget
, event
);
1057 \f/* get the values back */
1059 get_one_value (widget_instance
*instance
, widget_value
*val
)
1061 Widget widget
= name_to_widget (instance
, val
->name
);
1065 #if defined (USE_LUCID)
1066 if (lw_lucid_widget_p (instance
->widget
))
1067 xlw_update_one_value (instance
, widget
, val
);
1069 #if defined (USE_MOTIF)
1070 if (lw_motif_widget_p (instance
->widget
))
1071 xm_update_one_value (instance
, widget
, val
);
1073 #if defined (USE_XAW)
1074 if (lw_xaw_widget_p (instance
->widget
))
1075 xaw_update_one_value (instance
, widget
, val
);
1084 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1086 widget_info
* info
= get_widget_info (id
, False
);
1087 widget_instance
* instance
;
1089 Boolean result
= False
;
1094 instance
= info
->instances
;
1098 for (val
= val_out
; val
; val
= val
->next
)
1099 if (get_one_value (instance
, val
))
1106 lw_get_all_values (LWLIB_ID id
)
1108 widget_info
* info
= get_widget_info (id
, False
);
1109 widget_value
* val
= info
->val
;
1110 if (lw_get_some_values (id
, val
))
1116 /* internal function used by the library dependent implementation to get the
1117 widget_value for a given widget in an instance */
1119 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1121 char* name
= XtName (w
);
1123 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1124 if (!strcmp (cur
->name
, name
))
1129 \f/* update other instances value when one thing changed */
1131 /* To forbid recursive calls */
1132 static Boolean lwlib_updating
;
1134 /* This function can be used as an XtCallback for the widgets that get
1135 modified to update other instances of the widgets. Closure should be the
1138 lw_internal_update_other_instances (Widget widget
,
1140 XtPointer call_data
)
1142 widget_instance
* instance
= (widget_instance
*)closure
;
1143 char* name
= XtName (widget
);
1145 widget_instance
* cur
;
1148 /* Avoid possibly infinite recursion. */
1152 /* protect against the widget being destroyed */
1153 if (XtWidgetBeingDestroyedP (widget
))
1156 /* Return immediately if there are no other instances */
1157 info
= instance
->info
;
1158 if (!info
->instances
->next
)
1161 lwlib_updating
= True
;
1163 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1165 if (val
&& get_one_value (instance
, val
))
1166 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1167 if (cur
!= instance
)
1168 set_one_value (cur
, val
, True
);
1170 lwlib_updating
= False
;
1177 lw_get_widget_id (Widget w
)
1179 widget_instance
* instance
= get_widget_instance (w
, False
);
1181 return instance
? instance
->info
->id
: 0;
1184 \f/* set the keyboard focus */
1186 lw_set_keyboard_focus (Widget parent
, Widget w
)
1188 #if defined (USE_MOTIF)
1189 xm_set_keyboard_focus (parent
, w
);
1191 XtSetKeyboardFocus (parent
, w
);
1197 show_one_widget_busy (Widget w
, Boolean flag
)
1199 Pixel foreground
= 0;
1200 Pixel background
= 1;
1201 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1202 if (!widget_to_invert
)
1203 widget_to_invert
= w
;
1205 XtVaGetValues (widget_to_invert
,
1206 XtNforeground
, &foreground
,
1207 XtNbackground
, &background
,
1209 XtVaSetValues (widget_to_invert
,
1210 XtNforeground
, background
,
1211 XtNbackground
, foreground
,
1216 lw_show_busy (Widget w
, Boolean busy
)
1218 widget_instance
* instance
= get_widget_instance (w
, False
);
1220 widget_instance
* next
;
1224 info
= instance
->info
;
1225 if (info
->busy
!= busy
)
1227 for (next
= info
->instances
; next
; next
= next
->next
)
1229 show_one_widget_busy (next
->widget
, busy
);
1235 /* This hack exists because Lucid/Athena need to execute the strange
1236 function below to support geometry management. */
1238 lw_refigure_widget (Widget w
, Boolean doit
)
1240 #if defined (USE_XAW)
1241 XawPanedSetRefigureMode (w
, doit
);
1243 #if defined (USE_MOTIF)
1247 XtUnmanageChild (w
);
1251 /* Toolkit independent way of determining if an event window is in the
1254 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1256 return menubar_widget
1257 #if defined (USE_LUCID)
1258 && XtWindow (menubar_widget
) == win
;
1260 #if defined (USE_MOTIF)
1261 && ((XtWindow (menubar_widget
) == win
)
1262 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1263 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1264 == menubar_widget
)));
1268 /* Motif hack to set the main window areas. */
1270 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1272 #if defined (USE_MOTIF)
1273 xm_set_main_areas (parent
, menubar
, work_area
);
1277 /* Manage resizing for Motif. This disables resizing when the menubar
1278 is about to be modified. */
1280 lw_allow_resizing (Widget w
, Boolean flag
)
1282 #if defined (USE_MOTIF)
1283 xm_manage_resizing (w
, flag
);
1288 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1289 set to an appropriate enumerator of type enum menu_separator.
1290 MOTIF_P non-zero means map separator types not supported by Motif
1291 to similar ones that are supported. */
1294 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1296 int separator_p
= 0;
1298 if (strlen (label
) >= 3
1299 && memcmp (label
, "--:", 3) == 0)
1301 static struct separator_table
1304 enum menu_separator type
;
1308 {"space", SEPARATOR_NO_LINE
},
1309 {"noLine", SEPARATOR_NO_LINE
},
1310 {"singleLine", SEPARATOR_SINGLE_LINE
},
1311 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1312 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1313 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1314 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1315 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1316 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1317 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1318 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1319 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1320 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1321 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1328 for (i
= 0; separator_names
[i
].name
; ++i
)
1329 if (strcmp (label
, separator_names
[i
].name
) == 0)
1332 *type
= separator_names
[i
].type
;
1334 /* If separator type is not supported under Motif,
1335 use a similar one. */
1336 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1341 else if (strlen (label
) > 3
1342 && memcmp (label
, "--", 2) == 0
1345 /* Alternative, more Emacs-style names. */
1346 static struct separator_table
1349 enum menu_separator type
;
1353 {"space", SEPARATOR_NO_LINE
},
1354 {"no-line", SEPARATOR_NO_LINE
},
1355 {"single-line", SEPARATOR_SINGLE_LINE
},
1356 {"double-line", SEPARATOR_DOUBLE_LINE
},
1357 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1358 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1359 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1360 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1361 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1362 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1363 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1364 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1365 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1366 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1373 for (i
= 0; separator_names
[i
].name
; ++i
)
1374 if (strcmp (label
, separator_names
[i
].name
) == 0)
1377 *type
= separator_names
[i
].type
;
1379 /* If separator type is not supported under Motif,
1380 use a similar one. */
1381 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1388 /* Old-style separator, maybe. It's a separator if it contains
1390 while (*label
== '-')
1392 separator_p
= *label
== 0;
1393 *type
= SEPARATOR_SHADOW_ETCHED_IN
;