1 /* A general interface to the widgets of different toolkits.
3 Copyright (C) 1992, 1993 Lucid, Inc.
4 Copyright (C) 1994-1996, 1999-2011 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. */
30 #include <sys/types.h>
33 #include "lwlib-int.h"
34 #include "lwlib-utils.h"
35 #include <X11/StringDefs.h>
37 #if defined (USE_LUCID)
38 #include "lwlib-Xlw.h"
40 #if defined (USE_MOTIF)
42 #else /* not USE_MOTIF */
43 #if defined (USE_LUCID)
45 #endif /* not USE_MOTIF && USE_LUCID */
49 #include <X11/Xaw3d/Paned.h>
50 #else /* !HAVE_XAW3D */
51 #include <X11/Xaw/Paned.h>
52 #endif /* HAVE_XAW3D */
53 #include "lwlib-Xaw.h"
56 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
57 #error At least one of USE_LUCID or USE_MOTIF must be defined.
61 #define max(x, y) ((x) > (y) ? (x) : (y))
64 /* List of all widgets managed by the library. */
66 all_widget_info
= NULL
;
69 const char *lwlib_toolkit_type
= "motif";
71 const char *lwlib_toolkit_type
= "lucid";
74 static widget_value
*merge_widget_value (widget_value
*,
77 static void instantiate_widget_instance (widget_instance
*);
78 static int my_strcasecmp (const char *, const char *);
79 static void safe_free_str (char *);
80 static void free_widget_value_tree (widget_value
*);
81 static widget_value
*copy_widget_value_tree (widget_value
*,
83 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
85 lw_callback
, lw_callback
,
86 lw_callback
, lw_callback
);
87 static void free_widget_info (widget_info
*);
88 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
89 static widget_instance
*allocate_widget_instance (widget_info
*,
91 static void free_widget_instance (widget_instance
*);
92 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
93 static widget_instance
*get_widget_instance (Widget
, Boolean
);
94 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
95 static Boolean
safe_strcmp (const char *, const char *);
96 static Widget
name_to_widget (widget_instance
*, const char *);
97 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
98 static void update_one_widget_instance (widget_instance
*, Boolean
);
99 static void update_all_widget_values (widget_info
*, Boolean
);
100 static void initialize_widget_instance (widget_instance
*);
101 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
102 static Boolean
dialog_spec_p (const char *);
103 static void destroy_one_instance (widget_instance
*);
104 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
105 static Boolean
get_one_value (widget_instance
*, widget_value
*);
106 static void show_one_widget_busy (Widget
, Boolean
);
107 \f/* utility functions for widget_instance and widget_info */
109 safe_strdup (const char *s
)
113 result
= (char *) xmalloc (strlen (s
) + 1);
118 /* Like strcmp but ignore differences in case. */
121 my_strcasecmp (const char *s1
, const char *s2
)
132 return (c1
> c2
? 1 : -1);
139 safe_free_str (char *s
)
144 static widget_value
*widget_value_free_list
= 0;
145 static int malloc_cpt
= 0;
148 malloc_widget_value (void)
151 if (widget_value_free_list
)
153 wv
= widget_value_free_list
;
154 widget_value_free_list
= wv
->free_list
;
159 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
162 memset ((void*) wv
, 0, sizeof (widget_value
));
166 /* this is analogous to free(). It frees only what was allocated
167 by malloc_widget_value(), and no substructures.
170 free_widget_value (widget_value
*wv
)
177 /* When the number of already allocated cells is too big,
184 wv
->free_list
= widget_value_free_list
;
185 widget_value_free_list
= wv
;
190 free_widget_value_tree (widget_value
*wv
)
199 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
201 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
203 XtFree (wv
->toolkit_data
);
204 wv
->toolkit_data
= (void *) 0xDEADBEEF;
207 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
209 free_widget_value_tree (wv
->contents
);
210 wv
->contents
= (widget_value
*) 0xDEADBEEF;
214 free_widget_value_tree (wv
->next
);
215 wv
->next
= (widget_value
*) 0xDEADBEEF;
217 free_widget_value (wv
);
220 static widget_value
*
221 copy_widget_value_tree (widget_value
*val
, change_type change
)
227 if (val
== (widget_value
*) 1)
230 copy
= malloc_widget_value ();
231 copy
->name
= safe_strdup (val
->name
);
232 copy
->value
= safe_strdup (val
->value
);
233 copy
->key
= safe_strdup (val
->key
);
234 copy
->help
= val
->help
;
235 copy
->enabled
= val
->enabled
;
236 copy
->button_type
= val
->button_type
;
237 copy
->selected
= val
->selected
;
238 copy
->edited
= False
;
239 copy
->change
= change
;
240 copy
->this_one_change
= change
;
241 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
242 copy
->call_data
= val
->call_data
;
243 copy
->next
= copy_widget_value_tree (val
->next
, change
);
244 copy
->toolkit_data
= NULL
;
245 copy
->free_toolkit_data
= False
;
250 allocate_widget_info (const char* type
,
254 lw_callback pre_activate_cb
,
255 lw_callback selection_cb
,
256 lw_callback post_activate_cb
,
257 lw_callback highlight_cb
)
259 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
260 info
->type
= safe_strdup (type
);
261 info
->name
= safe_strdup (name
);
263 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
265 info
->pre_activate_cb
= pre_activate_cb
;
266 info
->selection_cb
= selection_cb
;
267 info
->post_activate_cb
= post_activate_cb
;
268 info
->highlight_cb
= highlight_cb
;
269 info
->instances
= NULL
;
271 info
->next
= all_widget_info
;
272 all_widget_info
= info
;
278 free_widget_info (widget_info
*info
)
280 safe_free_str (info
->type
);
281 safe_free_str (info
->name
);
282 free_widget_value_tree (info
->val
);
283 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
288 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
290 widget_instance
* instance
= (widget_instance
*)closure
;
292 /* be very conservative */
293 if (instance
->widget
== widget
)
294 instance
->widget
= NULL
;
297 static widget_instance
*
298 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
300 widget_instance
* instance
=
301 (widget_instance
*) xmalloc (sizeof (widget_instance
));
302 memset (instance
, 0, sizeof *instance
);
303 instance
->parent
= parent
;
304 instance
->pop_up_p
= pop_up_p
;
305 instance
->info
= info
;
306 instance
->next
= info
->instances
;
307 info
->instances
= instance
;
309 instantiate_widget_instance (instance
);
311 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
312 mark_widget_destroyed
, (XtPointer
)instance
);
317 free_widget_instance (widget_instance
*instance
)
319 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
324 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
328 for (prev
= NULL
, info
= all_widget_info
;
330 prev
= info
, info
= info
->next
)
336 prev
->next
= info
->next
;
338 all_widget_info
= info
->next
;
345 /* Internal function used by the library dependent implementation to get the
346 widget_value for a given widget in an instance */
348 lw_get_widget_info (LWLIB_ID id
)
350 return get_widget_info (id
, 0);
353 static widget_instance
*
354 get_widget_instance (Widget widget
, Boolean remove_p
)
357 widget_instance
* instance
;
358 widget_instance
* prev
;
359 for (info
= all_widget_info
; info
; info
= info
->next
)
360 for (prev
= NULL
, instance
= info
->instances
;
362 prev
= instance
, instance
= instance
->next
)
363 if (instance
->widget
== widget
)
368 prev
->next
= instance
->next
;
370 info
->instances
= instance
->next
;
374 return (widget_instance
*) 0;
377 /* Value is a pointer to the widget_instance corresponding to
378 WIDGET, or null if WIDGET is not a lwlib widget. */
381 lw_get_widget_instance (Widget widget
)
383 return get_widget_instance (widget
, False
);
386 static widget_instance
*
387 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
389 widget_info
* info
= get_widget_info (id
, False
);
390 widget_instance
* instance
;
393 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
394 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
401 /* utility function for widget_value */
403 safe_strcmp (const char *s1
, const char *s2
)
405 if (!!s1
^ !!s2
) return True
;
406 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
411 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
412 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
414 (oc == NO_CHANGE ? "none" : \
415 (oc == INVISIBLE_CHANGE ? "invisible" : \
416 (oc == VISIBLE_CHANGE ? "visible" : \
417 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
419 (nc == NO_CHANGE ? "none" : \
420 (nc == INVISIBLE_CHANGE ? "invisible" : \
421 (nc == VISIBLE_CHANGE ? "visible" : \
422 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
425 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
429 static widget_value
*
430 merge_widget_value (widget_value
*val1
,
435 change_type change
, this_one_change
;
436 widget_value
* merged_next
;
437 widget_value
* merged_contents
;
444 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
452 free_widget_value_tree (val1
);
458 if (safe_strcmp (val1
->name
, val2
->name
))
460 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
461 val1
->name
, val2
->name
);
462 change
= max (change
, STRUCTURAL_CHANGE
);
463 safe_free_str (val1
->name
);
464 val1
->name
= safe_strdup (val2
->name
);
466 if (safe_strcmp (val1
->value
, val2
->value
))
468 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
469 val1
->value
, val2
->value
);
470 change
= max (change
, VISIBLE_CHANGE
);
471 safe_free_str (val1
->value
);
472 val1
->value
= safe_strdup (val2
->value
);
474 if (safe_strcmp (val1
->key
, val2
->key
))
476 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
477 val1
->key
, val2
->key
);
478 change
= max (change
, VISIBLE_CHANGE
);
479 safe_free_str (val1
->key
);
480 val1
->key
= safe_strdup (val2
->key
);
482 if (! EQ (val1
->help
, val2
->help
))
484 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
485 val1
->help
, val2
->help
);
486 change
= max (change
, VISIBLE_CHANGE
);
487 val1
->help
= val2
->help
;
489 if (val1
->enabled
!= val2
->enabled
)
491 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
492 val1
->enabled
, val2
->enabled
);
493 change
= max (change
, VISIBLE_CHANGE
);
494 val1
->enabled
= val2
->enabled
;
496 if (val1
->button_type
!= val2
->button_type
)
498 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
499 val1
->button_type
, val2
->button_type
);
500 change
= max (change
, VISIBLE_CHANGE
);
501 val1
->button_type
= val2
->button_type
;
503 if (val1
->selected
!= val2
->selected
)
505 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
506 val1
->selected
, val2
->selected
);
507 change
= max (change
, VISIBLE_CHANGE
);
508 val1
->selected
= val2
->selected
;
510 if (val1
->call_data
!= val2
->call_data
)
512 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
513 val1
->call_data
, val2
->call_data
);
514 change
= max (change
, INVISIBLE_CHANGE
);
515 val1
->call_data
= val2
->call_data
;
521 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
524 if (val1
->contents
&& !merged_contents
)
526 /* This used to say INVISIBLE_CHANGE,
527 but it is visible and vitally important when
528 the contents of the menu bar itself are entirely deleted.
530 But maybe it doesn't matter. This fails to fix the bug. */
531 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
533 change
= max (change
, STRUCTURAL_CHANGE
);
535 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
537 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
539 change
= max (change
, INVISIBLE_CHANGE
);
540 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
542 change
= max (merged_contents
->change
, change
);
547 val1
->contents
= merged_contents
;
550 this_one_change
= change
;
552 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
554 if (val1
->next
&& !merged_next
)
556 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
558 change
= max (change
, STRUCTURAL_CHANGE
);
560 else if (merged_next
)
562 if (merged_next
->change
)
563 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
565 change
= max (change
, merged_next
->change
);
568 val1
->next
= merged_next
;
570 val1
->this_one_change
= this_one_change
;
571 val1
->change
= change
;
573 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
576 if (val1
->free_toolkit_data
)
577 XtFree (val1
->toolkit_data
);
578 val1
->toolkit_data
= NULL
;
585 /* modifying the widgets */
587 name_to_widget (widget_instance
*instance
, const char *name
)
589 Widget widget
= NULL
;
591 if (!instance
->widget
)
594 if (!strcmp (XtName (instance
->widget
), name
))
595 widget
= instance
->widget
;
598 int length
= strlen (name
) + 2;
599 char* real_name
= (char *) xmalloc (length
);
601 strcpy (real_name
+ 1, name
);
603 widget
= XtNameToWidget (instance
->widget
, real_name
);
611 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
613 Widget widget
= name_to_widget (instance
, val
->name
);
617 #if defined (USE_LUCID)
618 if (lw_lucid_widget_p (instance
->widget
))
619 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
621 #if defined (USE_MOTIF)
622 if (lw_motif_widget_p (instance
->widget
))
623 xm_update_one_widget (instance
, widget
, val
, deep_p
);
625 #if defined (USE_XAW)
626 if (lw_xaw_widget_p (instance
->widget
))
627 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
633 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
637 if (!instance
->widget
)
638 /* the widget was destroyed */
641 for (val
= instance
->info
->val
; val
; val
= val
->next
)
642 if (val
->change
!= NO_CHANGE
)
643 set_one_value (instance
, val
, deep_p
);
647 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
649 widget_instance
* instance
;
652 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
653 update_one_widget_instance (instance
, deep_p
);
655 for (val
= info
->val
; val
; val
= val
->next
)
656 val
->change
= NO_CHANGE
;
660 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
662 widget_info
* info
= get_widget_info (id
, False
);
663 widget_value
* new_val
;
664 widget_value
* next_new_val
;
674 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
676 next_new_val
= new_val
->next
;
677 new_val
->next
= NULL
;
679 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
680 if (!strcmp (cur
->name
, new_val
->name
))
685 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
688 prev
->next
= cur
? cur
: next
;
690 info
->val
= cur
? cur
: next
;
697 /* Could not find it, add it */
699 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
701 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
704 new_val
->next
= next_new_val
;
707 update_all_widget_values (info
, deep_p
);
712 /* creating the widgets */
715 initialize_widget_instance (widget_instance
*instance
)
719 for (val
= instance
->info
->val
; val
; val
= val
->next
)
720 val
->change
= STRUCTURAL_CHANGE
;
722 update_one_widget_instance (instance
, True
);
724 for (val
= instance
->info
->val
; val
; val
= val
->next
)
725 val
->change
= NO_CHANGE
;
729 static widget_creation_function
730 find_in_table (const char *type
, const widget_creation_entry
*table
)
732 const widget_creation_entry
* cur
;
733 for (cur
= table
; cur
->type
; cur
++)
734 if (!my_strcasecmp (type
, cur
->type
))
735 return cur
->function
;
740 dialog_spec_p (const char *name
)
742 /* return True if name matches [EILPQeilpq][1-9][Bb] or
743 [EILPQeilpq][1-9][Bb][Rr][1-9] */
749 case 'E': case 'I': case 'L': case 'P': case 'Q':
750 case 'e': case 'i': case 'l': case 'p': case 'q':
751 if (name
[1] >= '0' && name
[1] <= '9')
753 if (name
[2] != 'B' && name
[2] != 'b')
757 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
759 if ((name
[3] == 'R' || name
[3] == 'r')
760 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
773 instantiate_widget_instance (widget_instance
*instance
)
775 widget_creation_function function
= NULL
;
777 #if defined (USE_LUCID)
779 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
781 #if defined(USE_MOTIF)
783 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
785 #if defined (USE_XAW)
787 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
792 if (dialog_spec_p (instance
->info
->type
))
794 #if defined (USE_LUCID)
797 #if defined(USE_MOTIF)
799 function
= xm_create_dialog
;
801 #if defined (USE_XAW)
803 function
= xaw_create_dialog
;
810 printf ("No creation function for widget type %s\n",
811 instance
->info
->type
);
815 instance
->widget
= (*function
) (instance
);
817 if (!instance
->widget
)
820 /* XtRealizeWidget (instance->widget);*/
824 lw_register_widget (const char* type
,
828 lw_callback pre_activate_cb
,
829 lw_callback selection_cb
,
830 lw_callback post_activate_cb
,
831 lw_callback highlight_cb
)
833 if (!get_widget_info (id
, False
))
834 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
835 post_activate_cb
, highlight_cb
);
839 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
841 widget_instance
* instance
;
843 instance
= find_instance (id
, parent
, pop_up_p
);
844 return instance
? instance
->widget
: NULL
;
848 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
850 widget_instance
* instance
;
853 instance
= find_instance (id
, parent
, pop_up_p
);
856 info
= get_widget_info (id
, False
);
859 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
860 initialize_widget_instance (instance
);
862 if (!instance
->widget
)
864 return instance
->widget
;
868 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
869 Widget parent
, Boolean pop_up_p
,
870 lw_callback pre_activate_cb
, lw_callback selection_cb
,
871 lw_callback post_activate_cb
, lw_callback highlight_cb
)
873 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
874 post_activate_cb
, highlight_cb
);
875 return lw_make_widget (id
, parent
, pop_up_p
);
879 /* destroying the widgets */
881 destroy_one_instance (widget_instance
*instance
)
883 /* Remove the destroy callback on the widget; that callback will try to
884 dereference the instance object (to set its widget slot to 0, since the
885 widget is dead.) Since the instance is now dead, we don't have to worry
886 about the fact that its widget is dead too.
888 This happens in the Phase2Destroy of the widget, so this callback would
889 not have been run until arbitrarily long after the instance was freed.
891 if (instance
->widget
)
892 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
893 mark_widget_destroyed
, (XtPointer
)instance
);
895 if (instance
->widget
)
897 /* The else are pretty tricky here, including the empty statement
898 at the end because it would be very bad to destroy a widget
900 #if defined (USE_LUCID)
901 if (lw_lucid_widget_p (instance
->widget
))
902 xlw_destroy_instance (instance
);
905 #if defined (USE_MOTIF)
906 if (lw_motif_widget_p (instance
->widget
))
907 xm_destroy_instance (instance
);
910 #if defined (USE_XAW)
911 if (lw_xaw_widget_p (instance
->widget
))
912 xaw_destroy_instance (instance
);
916 /* Empty compound statement to terminate if-then-else chain. */
920 free_widget_instance (instance
);
924 lw_destroy_widget (Widget w
)
926 widget_instance
* instance
= get_widget_instance (w
, True
);
930 widget_info
*info
= instance
->info
;
931 /* instance has already been removed from the list; free it */
932 destroy_one_instance (instance
);
933 /* if there are no instances left, free the info too */
934 if (!info
->instances
)
935 lw_destroy_all_widgets (info
->id
);
940 lw_destroy_all_widgets (LWLIB_ID id
)
942 widget_info
* info
= get_widget_info (id
, True
);
943 widget_instance
* instance
;
944 widget_instance
* next
;
948 for (instance
= info
->instances
; instance
; )
950 next
= instance
->next
;
951 destroy_one_instance (instance
);
954 free_widget_info (info
);
959 lw_destroy_everything (void)
961 while (all_widget_info
)
962 lw_destroy_all_widgets (all_widget_info
->id
);
966 lw_destroy_all_pop_ups (void)
970 widget_instance
* instance
;
972 for (info
= all_widget_info
; info
; info
= next
)
975 instance
= info
->instances
;
976 if (instance
&& instance
->pop_up_p
)
977 lw_destroy_all_widgets (info
->id
);
982 extern Widget
first_child (Widget
); /* garbage */
986 lw_raise_all_pop_up_widgets (void)
989 widget_instance
* instance
;
990 Widget result
= NULL
;
992 for (info
= all_widget_info
; info
; info
= info
->next
)
993 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
994 if (instance
->pop_up_p
)
996 Widget widget
= instance
->widget
;
999 if (XtIsManaged (widget
)
1001 /* What a complete load of crap!!!!
1002 When a dialogShell is on the screen, it is not managed!
1004 || (lw_motif_widget_p (instance
->widget
) &&
1005 XtIsManaged (first_child (widget
)))
1011 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1019 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1021 widget_info
* info
= get_widget_info (id
, False
);
1022 widget_instance
* instance
;
1025 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1026 if (instance
->pop_up_p
&& instance
->widget
)
1028 #if defined (USE_LUCID)
1029 if (lw_lucid_widget_p (instance
->widget
))
1031 XtRealizeWidget (instance
->widget
);
1032 xlw_pop_instance (instance
, up
);
1035 #if defined (USE_MOTIF)
1036 if (lw_motif_widget_p (instance
->widget
))
1038 XtRealizeWidget (instance
->widget
);
1039 xm_pop_instance (instance
, up
);
1042 #if defined (USE_XAW)
1043 if (lw_xaw_widget_p (instance
->widget
))
1045 XtRealizeWidget (XtParent (instance
->widget
));
1046 XtRealizeWidget (instance
->widget
);
1047 xaw_pop_instance (instance
, up
);
1054 lw_pop_up_all_widgets (LWLIB_ID id
)
1056 lw_pop_all_widgets (id
, True
);
1060 lw_pop_down_all_widgets (LWLIB_ID id
)
1062 lw_pop_all_widgets (id
, False
);
1066 lw_popup_menu (Widget widget
, XEvent
*event
)
1068 #if defined (USE_LUCID)
1069 if (lw_lucid_widget_p (widget
))
1070 xlw_popup_menu (widget
, event
);
1072 #if defined (USE_MOTIF)
1073 if (lw_motif_widget_p (widget
))
1074 xm_popup_menu (widget
, event
);
1076 #if defined (USE_XAW)
1077 if (lw_xaw_widget_p (widget
))
1078 xaw_popup_menu (widget
, event
);
1082 \f/* get the values back */
1084 get_one_value (widget_instance
*instance
, widget_value
*val
)
1086 Widget widget
= name_to_widget (instance
, val
->name
);
1090 #if defined (USE_LUCID)
1091 if (lw_lucid_widget_p (instance
->widget
))
1092 xlw_update_one_value (instance
, widget
, val
);
1094 #if defined (USE_MOTIF)
1095 if (lw_motif_widget_p (instance
->widget
))
1096 xm_update_one_value (instance
, widget
, val
);
1098 #if defined (USE_XAW)
1099 if (lw_xaw_widget_p (instance
->widget
))
1100 xaw_update_one_value (instance
, widget
, val
);
1109 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1111 widget_info
* info
= get_widget_info (id
, False
);
1112 widget_instance
* instance
;
1114 Boolean result
= False
;
1119 instance
= info
->instances
;
1123 for (val
= val_out
; val
; val
= val
->next
)
1124 if (get_one_value (instance
, val
))
1131 lw_get_all_values (LWLIB_ID id
)
1133 widget_info
* info
= get_widget_info (id
, False
);
1134 widget_value
* val
= info
->val
;
1135 if (lw_get_some_values (id
, val
))
1141 /* internal function used by the library dependent implementation to get the
1142 widget_value for a given widget in an instance */
1144 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1146 char* name
= XtName (w
);
1148 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1149 if (!strcmp (cur
->name
, name
))
1154 \f/* update other instances value when one thing changed */
1156 /* To forbid recursive calls */
1157 static Boolean lwlib_updating
;
1159 /* This function can be used as a an XtCallback for the widgets that get
1160 modified to update other instances of the widgets. Closure should be the
1163 lw_internal_update_other_instances (Widget widget
,
1165 XtPointer call_data
)
1167 widget_instance
* instance
= (widget_instance
*)closure
;
1168 char* name
= XtName (widget
);
1170 widget_instance
* cur
;
1173 /* Avoid possibly infinite recursion. */
1177 /* protect against the widget being destroyed */
1178 if (XtWidgetBeingDestroyedP (widget
))
1181 /* Return immediately if there are no other instances */
1182 info
= instance
->info
;
1183 if (!info
->instances
->next
)
1186 lwlib_updating
= True
;
1188 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1190 if (val
&& get_one_value (instance
, val
))
1191 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1192 if (cur
!= instance
)
1193 set_one_value (cur
, val
, True
);
1195 lwlib_updating
= False
;
1202 lw_get_widget_id (Widget w
)
1204 widget_instance
* instance
= get_widget_instance (w
, False
);
1206 return instance
? instance
->info
->id
: 0;
1209 \f/* set the keyboard focus */
1211 lw_set_keyboard_focus (Widget parent
, Widget w
)
1213 #if defined (USE_MOTIF)
1214 xm_set_keyboard_focus (parent
, w
);
1216 XtSetKeyboardFocus (parent
, w
);
1222 show_one_widget_busy (Widget w
, Boolean flag
)
1224 Pixel foreground
= 0;
1225 Pixel background
= 1;
1226 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1227 if (!widget_to_invert
)
1228 widget_to_invert
= w
;
1230 XtVaGetValues (widget_to_invert
,
1231 XtNforeground
, &foreground
,
1232 XtNbackground
, &background
,
1234 XtVaSetValues (widget_to_invert
,
1235 XtNforeground
, background
,
1236 XtNbackground
, foreground
,
1241 lw_show_busy (Widget w
, Boolean busy
)
1243 widget_instance
* instance
= get_widget_instance (w
, False
);
1245 widget_instance
* next
;
1249 info
= instance
->info
;
1250 if (info
->busy
!= busy
)
1252 for (next
= info
->instances
; next
; next
= next
->next
)
1254 show_one_widget_busy (next
->widget
, busy
);
1260 /* This hack exists because Lucid/Athena need to execute the strange
1261 function below to support geometry management. */
1263 lw_refigure_widget (Widget w
, Boolean doit
)
1265 #if defined (USE_XAW)
1266 XawPanedSetRefigureMode (w
, doit
);
1268 #if defined (USE_MOTIF)
1272 XtUnmanageChild (w
);
1276 /* Toolkit independent way of determining if an event window is in the
1279 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1281 return menubar_widget
1282 #if defined (USE_LUCID)
1283 && XtWindow (menubar_widget
) == win
;
1285 #if defined (USE_MOTIF)
1286 && ((XtWindow (menubar_widget
) == win
)
1287 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1288 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1289 == menubar_widget
)));
1293 /* Motif hack to set the main window areas. */
1295 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1297 #if defined (USE_MOTIF)
1298 xm_set_main_areas (parent
, menubar
, work_area
);
1302 /* Manage resizing for Motif. This disables resizing when the menubar
1303 is about to be modified. */
1305 lw_allow_resizing (Widget w
, Boolean flag
)
1307 #if defined (USE_MOTIF)
1308 xm_manage_resizing (w
, flag
);
1313 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1314 set to an appropriate enumerator of type enum menu_separator.
1315 MOTIF_P non-zero means map separator types not supported by Motif
1316 to similar ones that are supported. */
1319 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1321 int separator_p
= 0;
1323 if (strlen (label
) >= 3
1324 && memcmp (label
, "--:", 3) == 0)
1326 static struct separator_table
1329 enum menu_separator type
;
1333 {"space", SEPARATOR_NO_LINE
},
1334 {"noLine", SEPARATOR_NO_LINE
},
1335 {"singleLine", SEPARATOR_SINGLE_LINE
},
1336 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1337 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1338 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1339 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1340 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1341 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1342 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1343 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1344 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1345 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1346 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1353 for (i
= 0; separator_names
[i
].name
; ++i
)
1354 if (strcmp (label
, separator_names
[i
].name
) == 0)
1357 *type
= separator_names
[i
].type
;
1359 /* If separator type is not supported under Motif,
1360 use a similar one. */
1361 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1366 else if (strlen (label
) > 3
1367 && memcmp (label
, "--", 2) == 0
1370 /* Alternative, more Emacs-style names. */
1371 static struct separator_table
1374 enum menu_separator type
;
1378 {"space", SEPARATOR_NO_LINE
},
1379 {"no-line", SEPARATOR_NO_LINE
},
1380 {"single-line", SEPARATOR_SINGLE_LINE
},
1381 {"double-line", SEPARATOR_DOUBLE_LINE
},
1382 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1383 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1384 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1385 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1386 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1387 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1388 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1389 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1390 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1391 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1398 for (i
= 0; separator_names
[i
].name
; ++i
)
1399 if (strcmp (label
, separator_names
[i
].name
) == 0)
1402 *type
= separator_names
[i
].type
;
1404 /* If separator type is not supported under Motif,
1405 use a similar one. */
1406 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1413 /* Old-style separator, maybe. It's a separator if it contains
1415 while (*label
== '-')
1417 separator_p
= *label
== 0;
1418 *type
= SEPARATOR_SHADOW_ETCHED_IN
;