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>
31 #include "lwlib-int.h"
32 #include "lwlib-utils.h"
33 #include <X11/StringDefs.h>
35 #if defined (USE_LUCID)
36 #include "lwlib-Xlw.h"
38 #if defined (USE_MOTIF)
40 #else /* not USE_MOTIF */
41 #if defined (USE_LUCID)
43 #endif /* not USE_MOTIF && USE_LUCID */
47 #include <X11/Xaw3d/Paned.h>
48 #else /* !HAVE_XAW3D */
49 #include <X11/Xaw/Paned.h>
50 #endif /* HAVE_XAW3D */
51 #include "lwlib-Xaw.h"
54 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
55 #error At least one of USE_LUCID or USE_MOTIF must be defined.
59 #define max(x, y) ((x) > (y) ? (x) : (y))
62 /* List of all widgets managed by the library. */
64 all_widget_info
= NULL
;
67 const char *lwlib_toolkit_type
= "motif";
69 const char *lwlib_toolkit_type
= "lucid";
72 static widget_value
*merge_widget_value (widget_value
*,
75 static void instantiate_widget_instance (widget_instance
*);
76 static void safe_free_str (char *);
77 static void free_widget_value_tree (widget_value
*);
78 static widget_value
*copy_widget_value_tree (widget_value
*,
80 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
82 lw_callback
, lw_callback
,
83 lw_callback
, lw_callback
);
84 static void free_widget_info (widget_info
*);
85 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
86 static widget_instance
*allocate_widget_instance (widget_info
*,
88 static void free_widget_instance (widget_instance
*);
89 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
90 static widget_instance
*get_widget_instance (Widget
, Boolean
);
91 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
92 static Boolean
safe_strcmp (const char *, const char *);
93 static Widget
name_to_widget (widget_instance
*, const char *);
94 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
95 static void update_one_widget_instance (widget_instance
*, Boolean
);
96 static void update_all_widget_values (widget_info
*, Boolean
);
97 static void initialize_widget_instance (widget_instance
*);
98 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
99 static Boolean
dialog_spec_p (const char *);
100 static void destroy_one_instance (widget_instance
*);
101 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
102 static Boolean
get_one_value (widget_instance
*, widget_value
*);
103 static void show_one_widget_busy (Widget
, Boolean
);
104 \f/* utility functions for widget_instance and widget_info */
106 safe_strdup (const char *s
)
110 result
= (char *) xmalloc (strlen (s
) + 1);
116 safe_free_str (char *s
)
121 static widget_value
*widget_value_free_list
= 0;
122 static int malloc_cpt
= 0;
125 malloc_widget_value (void)
128 if (widget_value_free_list
)
130 wv
= widget_value_free_list
;
131 widget_value_free_list
= wv
->free_list
;
136 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
139 memset ((void*) wv
, 0, sizeof (widget_value
));
143 /* this is analogous to free(). It frees only what was allocated
144 by malloc_widget_value(), and no substructures.
147 free_widget_value (widget_value
*wv
)
154 /* When the number of already allocated cells is too big,
161 wv
->free_list
= widget_value_free_list
;
162 widget_value_free_list
= wv
;
167 free_widget_value_tree (widget_value
*wv
)
176 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
178 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
180 XtFree (wv
->toolkit_data
);
181 wv
->toolkit_data
= (void *) 0xDEADBEEF;
184 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
186 free_widget_value_tree (wv
->contents
);
187 wv
->contents
= (widget_value
*) 0xDEADBEEF;
191 free_widget_value_tree (wv
->next
);
192 wv
->next
= (widget_value
*) 0xDEADBEEF;
194 free_widget_value (wv
);
197 static widget_value
*
198 copy_widget_value_tree (widget_value
*val
, change_type change
)
204 if (val
== (widget_value
*) 1)
207 copy
= malloc_widget_value ();
208 copy
->name
= safe_strdup (val
->name
);
209 copy
->value
= safe_strdup (val
->value
);
210 copy
->key
= safe_strdup (val
->key
);
211 copy
->help
= val
->help
;
212 copy
->enabled
= val
->enabled
;
213 copy
->button_type
= val
->button_type
;
214 copy
->selected
= val
->selected
;
215 copy
->edited
= False
;
216 copy
->change
= change
;
217 copy
->this_one_change
= change
;
218 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
219 copy
->call_data
= val
->call_data
;
220 copy
->next
= copy_widget_value_tree (val
->next
, change
);
221 copy
->toolkit_data
= NULL
;
222 copy
->free_toolkit_data
= False
;
227 allocate_widget_info (const char* type
,
231 lw_callback pre_activate_cb
,
232 lw_callback selection_cb
,
233 lw_callback post_activate_cb
,
234 lw_callback highlight_cb
)
236 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
237 info
->type
= safe_strdup (type
);
238 info
->name
= safe_strdup (name
);
240 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
242 info
->pre_activate_cb
= pre_activate_cb
;
243 info
->selection_cb
= selection_cb
;
244 info
->post_activate_cb
= post_activate_cb
;
245 info
->highlight_cb
= highlight_cb
;
246 info
->instances
= NULL
;
248 info
->next
= all_widget_info
;
249 all_widget_info
= info
;
255 free_widget_info (widget_info
*info
)
257 safe_free_str (info
->type
);
258 safe_free_str (info
->name
);
259 free_widget_value_tree (info
->val
);
260 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
265 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
267 widget_instance
* instance
= (widget_instance
*)closure
;
269 /* be very conservative */
270 if (instance
->widget
== widget
)
271 instance
->widget
= NULL
;
274 static widget_instance
*
275 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
277 widget_instance
* instance
=
278 (widget_instance
*) xmalloc (sizeof (widget_instance
));
279 memset (instance
, 0, sizeof *instance
);
280 instance
->parent
= parent
;
281 instance
->pop_up_p
= pop_up_p
;
282 instance
->info
= info
;
283 instance
->next
= info
->instances
;
284 info
->instances
= instance
;
286 instantiate_widget_instance (instance
);
288 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
289 mark_widget_destroyed
, (XtPointer
)instance
);
294 free_widget_instance (widget_instance
*instance
)
296 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
301 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
305 for (prev
= NULL
, info
= all_widget_info
;
307 prev
= info
, info
= info
->next
)
313 prev
->next
= info
->next
;
315 all_widget_info
= info
->next
;
322 /* Internal function used by the library dependent implementation to get the
323 widget_value for a given widget in an instance */
325 lw_get_widget_info (LWLIB_ID id
)
327 return get_widget_info (id
, 0);
330 static widget_instance
*
331 get_widget_instance (Widget widget
, Boolean remove_p
)
334 widget_instance
* instance
;
335 widget_instance
* prev
;
336 for (info
= all_widget_info
; info
; info
= info
->next
)
337 for (prev
= NULL
, instance
= info
->instances
;
339 prev
= instance
, instance
= instance
->next
)
340 if (instance
->widget
== widget
)
345 prev
->next
= instance
->next
;
347 info
->instances
= instance
->next
;
351 return (widget_instance
*) 0;
354 /* Value is a pointer to the widget_instance corresponding to
355 WIDGET, or null if WIDGET is not a lwlib widget. */
358 lw_get_widget_instance (Widget widget
)
360 return get_widget_instance (widget
, False
);
363 static widget_instance
*
364 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
366 widget_info
* info
= get_widget_info (id
, False
);
367 widget_instance
* instance
;
370 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
371 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
378 /* utility function for widget_value */
380 safe_strcmp (const char *s1
, const char *s2
)
382 if (!!s1
^ !!s2
) return True
;
383 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
388 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
389 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
391 (oc == NO_CHANGE ? "none" : \
392 (oc == INVISIBLE_CHANGE ? "invisible" : \
393 (oc == VISIBLE_CHANGE ? "visible" : \
394 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
396 (nc == NO_CHANGE ? "none" : \
397 (nc == INVISIBLE_CHANGE ? "invisible" : \
398 (nc == VISIBLE_CHANGE ? "visible" : \
399 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
402 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
406 static widget_value
*
407 merge_widget_value (widget_value
*val1
,
412 change_type change
, this_one_change
;
413 widget_value
* merged_next
;
414 widget_value
* merged_contents
;
421 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
429 free_widget_value_tree (val1
);
435 if (safe_strcmp (val1
->name
, val2
->name
))
437 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
438 val1
->name
, val2
->name
);
439 change
= max (change
, STRUCTURAL_CHANGE
);
440 safe_free_str (val1
->name
);
441 val1
->name
= safe_strdup (val2
->name
);
443 if (safe_strcmp (val1
->value
, val2
->value
))
445 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
446 val1
->value
, val2
->value
);
447 change
= max (change
, VISIBLE_CHANGE
);
448 safe_free_str (val1
->value
);
449 val1
->value
= safe_strdup (val2
->value
);
451 if (safe_strcmp (val1
->key
, val2
->key
))
453 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
454 val1
->key
, val2
->key
);
455 change
= max (change
, VISIBLE_CHANGE
);
456 safe_free_str (val1
->key
);
457 val1
->key
= safe_strdup (val2
->key
);
459 if (! EQ (val1
->help
, val2
->help
))
461 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
462 val1
->help
, val2
->help
);
463 change
= max (change
, VISIBLE_CHANGE
);
464 val1
->help
= val2
->help
;
466 if (val1
->enabled
!= val2
->enabled
)
468 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
469 val1
->enabled
, val2
->enabled
);
470 change
= max (change
, VISIBLE_CHANGE
);
471 val1
->enabled
= val2
->enabled
;
473 if (val1
->button_type
!= val2
->button_type
)
475 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
476 val1
->button_type
, val2
->button_type
);
477 change
= max (change
, VISIBLE_CHANGE
);
478 val1
->button_type
= val2
->button_type
;
480 if (val1
->selected
!= val2
->selected
)
482 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
483 val1
->selected
, val2
->selected
);
484 change
= max (change
, VISIBLE_CHANGE
);
485 val1
->selected
= val2
->selected
;
487 if (val1
->call_data
!= val2
->call_data
)
489 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
490 val1
->call_data
, val2
->call_data
);
491 change
= max (change
, INVISIBLE_CHANGE
);
492 val1
->call_data
= val2
->call_data
;
498 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
501 if (val1
->contents
&& !merged_contents
)
503 /* This used to say INVISIBLE_CHANGE,
504 but it is visible and vitally important when
505 the contents of the menu bar itself are entirely deleted.
507 But maybe it doesn't matter. This fails to fix the bug. */
508 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
510 change
= max (change
, STRUCTURAL_CHANGE
);
512 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
514 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
516 change
= max (change
, INVISIBLE_CHANGE
);
517 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
519 change
= max (merged_contents
->change
, change
);
524 val1
->contents
= merged_contents
;
527 this_one_change
= change
;
529 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
531 if (val1
->next
&& !merged_next
)
533 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
535 change
= max (change
, STRUCTURAL_CHANGE
);
537 else if (merged_next
)
539 if (merged_next
->change
)
540 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
542 change
= max (change
, merged_next
->change
);
545 val1
->next
= merged_next
;
547 val1
->this_one_change
= this_one_change
;
548 val1
->change
= change
;
550 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
553 if (val1
->free_toolkit_data
)
554 XtFree (val1
->toolkit_data
);
555 val1
->toolkit_data
= NULL
;
562 /* modifying the widgets */
564 name_to_widget (widget_instance
*instance
, const char *name
)
566 Widget widget
= NULL
;
568 if (!instance
->widget
)
571 if (!strcmp (XtName (instance
->widget
), name
))
572 widget
= instance
->widget
;
575 int length
= strlen (name
) + 2;
576 char* real_name
= (char *) xmalloc (length
);
578 strcpy (real_name
+ 1, name
);
580 widget
= XtNameToWidget (instance
->widget
, real_name
);
588 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
590 Widget widget
= name_to_widget (instance
, val
->name
);
594 #if defined (USE_LUCID)
595 if (lw_lucid_widget_p (instance
->widget
))
596 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
598 #if defined (USE_MOTIF)
599 if (lw_motif_widget_p (instance
->widget
))
600 xm_update_one_widget (instance
, widget
, val
, deep_p
);
602 #if defined (USE_XAW)
603 if (lw_xaw_widget_p (instance
->widget
))
604 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
610 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
614 if (!instance
->widget
)
615 /* the widget was destroyed */
618 for (val
= instance
->info
->val
; val
; val
= val
->next
)
619 if (val
->change
!= NO_CHANGE
)
620 set_one_value (instance
, val
, deep_p
);
624 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
626 widget_instance
* instance
;
629 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
630 update_one_widget_instance (instance
, deep_p
);
632 for (val
= info
->val
; val
; val
= val
->next
)
633 val
->change
= NO_CHANGE
;
637 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
639 widget_info
* info
= get_widget_info (id
, False
);
640 widget_value
* new_val
;
641 widget_value
* next_new_val
;
651 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
653 next_new_val
= new_val
->next
;
654 new_val
->next
= NULL
;
656 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
657 if (!strcmp (cur
->name
, new_val
->name
))
662 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
665 prev
->next
= cur
? cur
: next
;
667 info
->val
= cur
? cur
: next
;
674 /* Could not find it, add it */
676 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
678 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
681 new_val
->next
= next_new_val
;
684 update_all_widget_values (info
, deep_p
);
689 /* creating the widgets */
692 initialize_widget_instance (widget_instance
*instance
)
696 for (val
= instance
->info
->val
; val
; val
= val
->next
)
697 val
->change
= STRUCTURAL_CHANGE
;
699 update_one_widget_instance (instance
, True
);
701 for (val
= instance
->info
->val
; val
; val
= val
->next
)
702 val
->change
= NO_CHANGE
;
706 static widget_creation_function
707 find_in_table (const char *type
, const widget_creation_entry
*table
)
709 const widget_creation_entry
* cur
;
710 for (cur
= table
; cur
->type
; cur
++)
711 if (!c_strcasecmp (type
, cur
->type
))
712 return cur
->function
;
717 dialog_spec_p (const char *name
)
719 /* return True if name matches [EILPQeilpq][1-9][Bb] or
720 [EILPQeilpq][1-9][Bb][Rr][1-9] */
726 case 'E': case 'I': case 'L': case 'P': case 'Q':
727 case 'e': case 'i': case 'l': case 'p': case 'q':
728 if (name
[1] >= '0' && name
[1] <= '9')
730 if (name
[2] != 'B' && name
[2] != 'b')
734 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
736 if ((name
[3] == 'R' || name
[3] == 'r')
737 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
750 instantiate_widget_instance (widget_instance
*instance
)
752 widget_creation_function function
= NULL
;
754 #if defined (USE_LUCID)
756 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
758 #if defined(USE_MOTIF)
760 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
762 #if defined (USE_XAW)
764 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
769 if (dialog_spec_p (instance
->info
->type
))
771 #if defined (USE_LUCID)
774 #if defined(USE_MOTIF)
776 function
= xm_create_dialog
;
778 #if defined (USE_XAW)
780 function
= xaw_create_dialog
;
787 printf ("No creation function for widget type %s\n",
788 instance
->info
->type
);
792 instance
->widget
= (*function
) (instance
);
794 if (!instance
->widget
)
797 /* XtRealizeWidget (instance->widget);*/
801 lw_register_widget (const char* type
,
805 lw_callback pre_activate_cb
,
806 lw_callback selection_cb
,
807 lw_callback post_activate_cb
,
808 lw_callback highlight_cb
)
810 if (!get_widget_info (id
, False
))
811 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
812 post_activate_cb
, highlight_cb
);
816 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
818 widget_instance
* instance
;
820 instance
= find_instance (id
, parent
, pop_up_p
);
821 return instance
? instance
->widget
: NULL
;
825 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
827 widget_instance
* instance
;
830 instance
= find_instance (id
, parent
, pop_up_p
);
833 info
= get_widget_info (id
, False
);
836 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
837 initialize_widget_instance (instance
);
839 if (!instance
->widget
)
841 return instance
->widget
;
845 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
846 Widget parent
, Boolean pop_up_p
,
847 lw_callback pre_activate_cb
, lw_callback selection_cb
,
848 lw_callback post_activate_cb
, lw_callback highlight_cb
)
850 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
851 post_activate_cb
, highlight_cb
);
852 return lw_make_widget (id
, parent
, pop_up_p
);
856 /* destroying the widgets */
858 destroy_one_instance (widget_instance
*instance
)
860 /* Remove the destroy callback on the widget; that callback will try to
861 dereference the instance object (to set its widget slot to 0, since the
862 widget is dead.) Since the instance is now dead, we don't have to worry
863 about the fact that its widget is dead too.
865 This happens in the Phase2Destroy of the widget, so this callback would
866 not have been run until arbitrarily long after the instance was freed.
868 if (instance
->widget
)
869 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
870 mark_widget_destroyed
, (XtPointer
)instance
);
872 if (instance
->widget
)
874 /* The else are pretty tricky here, including the empty statement
875 at the end because it would be very bad to destroy a widget
877 #if defined (USE_LUCID)
878 if (lw_lucid_widget_p (instance
->widget
))
879 xlw_destroy_instance (instance
);
882 #if defined (USE_MOTIF)
883 if (lw_motif_widget_p (instance
->widget
))
884 xm_destroy_instance (instance
);
887 #if defined (USE_XAW)
888 if (lw_xaw_widget_p (instance
->widget
))
889 xaw_destroy_instance (instance
);
893 /* Empty compound statement to terminate if-then-else chain. */
897 free_widget_instance (instance
);
901 lw_destroy_widget (Widget w
)
903 widget_instance
* instance
= get_widget_instance (w
, True
);
907 widget_info
*info
= instance
->info
;
908 /* instance has already been removed from the list; free it */
909 destroy_one_instance (instance
);
910 /* if there are no instances left, free the info too */
911 if (!info
->instances
)
912 lw_destroy_all_widgets (info
->id
);
917 lw_destroy_all_widgets (LWLIB_ID id
)
919 widget_info
* info
= get_widget_info (id
, True
);
920 widget_instance
* instance
;
921 widget_instance
* next
;
925 for (instance
= info
->instances
; instance
; )
927 next
= instance
->next
;
928 destroy_one_instance (instance
);
931 free_widget_info (info
);
936 lw_destroy_everything (void)
938 while (all_widget_info
)
939 lw_destroy_all_widgets (all_widget_info
->id
);
943 lw_destroy_all_pop_ups (void)
947 widget_instance
* instance
;
949 for (info
= all_widget_info
; info
; info
= next
)
952 instance
= info
->instances
;
953 if (instance
&& instance
->pop_up_p
)
954 lw_destroy_all_widgets (info
->id
);
959 extern Widget
first_child (Widget
); /* garbage */
963 lw_raise_all_pop_up_widgets (void)
966 widget_instance
* instance
;
967 Widget result
= NULL
;
969 for (info
= all_widget_info
; info
; info
= info
->next
)
970 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
971 if (instance
->pop_up_p
)
973 Widget widget
= instance
->widget
;
976 if (XtIsManaged (widget
)
978 /* What a complete load of crap!!!!
979 When a dialogShell is on the screen, it is not managed!
981 || (lw_motif_widget_p (instance
->widget
) &&
982 XtIsManaged (first_child (widget
)))
988 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
996 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
998 widget_info
* info
= get_widget_info (id
, False
);
999 widget_instance
* instance
;
1002 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1003 if (instance
->pop_up_p
&& instance
->widget
)
1005 #if defined (USE_LUCID)
1006 if (lw_lucid_widget_p (instance
->widget
))
1008 XtRealizeWidget (instance
->widget
);
1009 xlw_pop_instance (instance
, up
);
1012 #if defined (USE_MOTIF)
1013 if (lw_motif_widget_p (instance
->widget
))
1015 XtRealizeWidget (instance
->widget
);
1016 xm_pop_instance (instance
, up
);
1019 #if defined (USE_XAW)
1020 if (lw_xaw_widget_p (instance
->widget
))
1022 XtRealizeWidget (XtParent (instance
->widget
));
1023 XtRealizeWidget (instance
->widget
);
1024 xaw_pop_instance (instance
, up
);
1031 lw_pop_up_all_widgets (LWLIB_ID id
)
1033 lw_pop_all_widgets (id
, True
);
1037 lw_pop_down_all_widgets (LWLIB_ID id
)
1039 lw_pop_all_widgets (id
, False
);
1043 lw_popup_menu (Widget widget
, XEvent
*event
)
1045 #if defined (USE_LUCID)
1046 if (lw_lucid_widget_p (widget
))
1047 xlw_popup_menu (widget
, event
);
1049 #if defined (USE_MOTIF)
1050 if (lw_motif_widget_p (widget
))
1051 xm_popup_menu (widget
, event
);
1053 #if defined (USE_XAW)
1054 if (lw_xaw_widget_p (widget
))
1055 xaw_popup_menu (widget
, event
);
1059 \f/* get the values back */
1061 get_one_value (widget_instance
*instance
, widget_value
*val
)
1063 Widget widget
= name_to_widget (instance
, val
->name
);
1067 #if defined (USE_LUCID)
1068 if (lw_lucid_widget_p (instance
->widget
))
1069 xlw_update_one_value (instance
, widget
, val
);
1071 #if defined (USE_MOTIF)
1072 if (lw_motif_widget_p (instance
->widget
))
1073 xm_update_one_value (instance
, widget
, val
);
1075 #if defined (USE_XAW)
1076 if (lw_xaw_widget_p (instance
->widget
))
1077 xaw_update_one_value (instance
, widget
, val
);
1086 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1088 widget_info
* info
= get_widget_info (id
, False
);
1089 widget_instance
* instance
;
1091 Boolean result
= False
;
1096 instance
= info
->instances
;
1100 for (val
= val_out
; val
; val
= val
->next
)
1101 if (get_one_value (instance
, val
))
1108 lw_get_all_values (LWLIB_ID id
)
1110 widget_info
* info
= get_widget_info (id
, False
);
1111 widget_value
* val
= info
->val
;
1112 if (lw_get_some_values (id
, val
))
1118 /* internal function used by the library dependent implementation to get the
1119 widget_value for a given widget in an instance */
1121 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1123 char* name
= XtName (w
);
1125 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1126 if (!strcmp (cur
->name
, name
))
1131 \f/* update other instances value when one thing changed */
1133 /* To forbid recursive calls */
1134 static Boolean lwlib_updating
;
1136 /* This function can be used as an XtCallback for the widgets that get
1137 modified to update other instances of the widgets. Closure should be the
1140 lw_internal_update_other_instances (Widget widget
,
1142 XtPointer call_data
)
1144 widget_instance
* instance
= (widget_instance
*)closure
;
1145 char* name
= XtName (widget
);
1147 widget_instance
* cur
;
1150 /* Avoid possibly infinite recursion. */
1154 /* protect against the widget being destroyed */
1155 if (XtWidgetBeingDestroyedP (widget
))
1158 /* Return immediately if there are no other instances */
1159 info
= instance
->info
;
1160 if (!info
->instances
->next
)
1163 lwlib_updating
= True
;
1165 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1167 if (val
&& get_one_value (instance
, val
))
1168 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1169 if (cur
!= instance
)
1170 set_one_value (cur
, val
, True
);
1172 lwlib_updating
= False
;
1179 lw_get_widget_id (Widget w
)
1181 widget_instance
* instance
= get_widget_instance (w
, False
);
1183 return instance
? instance
->info
->id
: 0;
1186 \f/* set the keyboard focus */
1188 lw_set_keyboard_focus (Widget parent
, Widget w
)
1190 #if defined (USE_MOTIF)
1191 xm_set_keyboard_focus (parent
, w
);
1193 XtSetKeyboardFocus (parent
, w
);
1199 show_one_widget_busy (Widget w
, Boolean flag
)
1201 Pixel foreground
= 0;
1202 Pixel background
= 1;
1203 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1204 if (!widget_to_invert
)
1205 widget_to_invert
= w
;
1207 XtVaGetValues (widget_to_invert
,
1208 XtNforeground
, &foreground
,
1209 XtNbackground
, &background
,
1211 XtVaSetValues (widget_to_invert
,
1212 XtNforeground
, background
,
1213 XtNbackground
, foreground
,
1218 lw_show_busy (Widget w
, Boolean busy
)
1220 widget_instance
* instance
= get_widget_instance (w
, False
);
1222 widget_instance
* next
;
1226 info
= instance
->info
;
1227 if (info
->busy
!= busy
)
1229 for (next
= info
->instances
; next
; next
= next
->next
)
1231 show_one_widget_busy (next
->widget
, busy
);
1237 /* This hack exists because Lucid/Athena need to execute the strange
1238 function below to support geometry management. */
1240 lw_refigure_widget (Widget w
, Boolean doit
)
1242 #if defined (USE_XAW)
1243 XawPanedSetRefigureMode (w
, doit
);
1245 #if defined (USE_MOTIF)
1249 XtUnmanageChild (w
);
1253 /* Toolkit independent way of determining if an event window is in the
1256 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1258 return menubar_widget
1259 #if defined (USE_LUCID)
1260 && XtWindow (menubar_widget
) == win
;
1262 #if defined (USE_MOTIF)
1263 && ((XtWindow (menubar_widget
) == win
)
1264 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1265 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1266 == menubar_widget
)));
1270 /* Motif hack to set the main window areas. */
1272 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1274 #if defined (USE_MOTIF)
1275 xm_set_main_areas (parent
, menubar
, work_area
);
1279 /* Manage resizing for Motif. This disables resizing when the menubar
1280 is about to be modified. */
1282 lw_allow_resizing (Widget w
, Boolean flag
)
1284 #if defined (USE_MOTIF)
1285 xm_manage_resizing (w
, flag
);
1290 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1291 set to an appropriate enumerator of type enum menu_separator.
1292 MOTIF_P non-zero means map separator types not supported by Motif
1293 to similar ones that are supported. */
1296 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1298 int separator_p
= 0;
1300 if (strlen (label
) >= 3
1301 && memcmp (label
, "--:", 3) == 0)
1303 static struct separator_table
1306 enum menu_separator type
;
1310 {"space", SEPARATOR_NO_LINE
},
1311 {"noLine", SEPARATOR_NO_LINE
},
1312 {"singleLine", SEPARATOR_SINGLE_LINE
},
1313 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1314 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1315 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1316 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1317 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1318 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1319 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1320 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1321 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1322 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1323 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1330 for (i
= 0; separator_names
[i
].name
; ++i
)
1331 if (strcmp (label
, separator_names
[i
].name
) == 0)
1334 *type
= separator_names
[i
].type
;
1336 /* If separator type is not supported under Motif,
1337 use a similar one. */
1338 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1343 else if (strlen (label
) > 3
1344 && memcmp (label
, "--", 2) == 0
1347 /* Alternative, more Emacs-style names. */
1348 static struct separator_table
1351 enum menu_separator type
;
1355 {"space", SEPARATOR_NO_LINE
},
1356 {"no-line", SEPARATOR_NO_LINE
},
1357 {"single-line", SEPARATOR_SINGLE_LINE
},
1358 {"double-line", SEPARATOR_DOUBLE_LINE
},
1359 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1360 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1361 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1362 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1363 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1364 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1365 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1366 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1367 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1368 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1375 for (i
= 0; separator_names
[i
].name
; ++i
)
1376 if (strcmp (label
, separator_names
[i
].name
) == 0)
1379 *type
= separator_names
[i
].type
;
1381 /* If separator type is not supported under Motif,
1382 use a similar one. */
1383 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1390 /* Old-style separator, maybe. It's a separator if it contains
1392 while (*label
== '-')
1394 separator_p
= *label
== 0;
1395 *type
= SEPARATOR_SHADOW_ETCHED_IN
;