1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
3 Copyright (C) 1994-1996, 1999-2011 Free Software Foundation, Inc.
5 This file is part of the Lucid Widget Library.
7 The Lucid Widget Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 The Lucid Widget Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
27 #include "../src/lisp.h"
29 #include <sys/types.h>
32 #include "lwlib-int.h"
33 #include "lwlib-utils.h"
34 #include <X11/StringDefs.h>
36 #if defined (USE_LUCID)
37 #include "lwlib-Xlw.h"
39 #if defined (USE_MOTIF)
41 #else /* not USE_MOTIF */
42 #if defined (USE_LUCID)
44 #endif /* not USE_MOTIF && USE_LUCID */
48 #include <X11/Xaw3d/Paned.h>
49 #else /* !HAVE_XAW3D */
50 #include <X11/Xaw/Paned.h>
51 #endif /* HAVE_XAW3D */
52 #include "lwlib-Xaw.h"
55 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
56 #error At least one of USE_LUCID or USE_MOTIF must be defined.
60 #define max(x, y) ((x) > (y) ? (x) : (y))
63 /* List of all widgets managed by the library. */
65 all_widget_info
= NULL
;
68 const char *lwlib_toolkit_type
= "motif";
70 const char *lwlib_toolkit_type
= "lucid";
73 static widget_value
*merge_widget_value (widget_value
*,
76 static void instantiate_widget_instance (widget_instance
*);
77 static int my_strcasecmp (const char *, const char *);
78 static void safe_free_str (char *);
79 static void free_widget_value_tree (widget_value
*);
80 static widget_value
*copy_widget_value_tree (widget_value
*,
82 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
84 lw_callback
, lw_callback
,
85 lw_callback
, lw_callback
);
86 static void free_widget_info (widget_info
*);
87 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
88 static widget_instance
*allocate_widget_instance (widget_info
*,
90 static void free_widget_instance (widget_instance
*);
91 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
92 static widget_instance
*get_widget_instance (Widget
, Boolean
);
93 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
94 static Boolean
safe_strcmp (const char *, const char *);
95 static Widget
name_to_widget (widget_instance
*, const char *);
96 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
97 static void update_one_widget_instance (widget_instance
*, Boolean
);
98 static void update_all_widget_values (widget_info
*, Boolean
);
99 static void initialize_widget_instance (widget_instance
*);
100 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
101 static Boolean
dialog_spec_p (const char *);
102 static void destroy_one_instance (widget_instance
*);
103 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
104 static Boolean
get_one_value (widget_instance
*, widget_value
*);
105 static void show_one_widget_busy (Widget
, Boolean
);
106 \f/* utility functions for widget_instance and widget_info */
108 safe_strdup (const char *s
)
112 result
= (char *) xmalloc (strlen (s
) + 1);
117 /* Like strcmp but ignore differences in case. */
120 my_strcasecmp (const char *s1
, const char *s2
)
131 return (c1
> c2
? 1 : -1);
138 safe_free_str (char *s
)
143 static widget_value
*widget_value_free_list
= 0;
144 static int malloc_cpt
= 0;
147 malloc_widget_value (void)
150 if (widget_value_free_list
)
152 wv
= widget_value_free_list
;
153 widget_value_free_list
= wv
->free_list
;
158 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
161 memset ((void*) wv
, 0, sizeof (widget_value
));
165 /* this is analogous to free(). It frees only what was allocated
166 by malloc_widget_value(), and no substructures.
169 free_widget_value (widget_value
*wv
)
176 /* When the number of already allocated cells is too big,
183 wv
->free_list
= widget_value_free_list
;
184 widget_value_free_list
= wv
;
189 free_widget_value_tree (widget_value
*wv
)
198 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
200 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
202 XtFree (wv
->toolkit_data
);
203 wv
->toolkit_data
= (void *) 0xDEADBEEF;
206 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
208 free_widget_value_tree (wv
->contents
);
209 wv
->contents
= (widget_value
*) 0xDEADBEEF;
213 free_widget_value_tree (wv
->next
);
214 wv
->next
= (widget_value
*) 0xDEADBEEF;
216 free_widget_value (wv
);
219 static widget_value
*
220 copy_widget_value_tree (widget_value
*val
, change_type change
)
226 if (val
== (widget_value
*) 1)
229 copy
= malloc_widget_value ();
230 copy
->name
= safe_strdup (val
->name
);
231 copy
->value
= safe_strdup (val
->value
);
232 copy
->key
= safe_strdup (val
->key
);
233 copy
->help
= val
->help
;
234 copy
->enabled
= val
->enabled
;
235 copy
->button_type
= val
->button_type
;
236 copy
->selected
= val
->selected
;
237 copy
->edited
= False
;
238 copy
->change
= change
;
239 copy
->this_one_change
= change
;
240 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
241 copy
->call_data
= val
->call_data
;
242 copy
->next
= copy_widget_value_tree (val
->next
, change
);
243 copy
->toolkit_data
= NULL
;
244 copy
->free_toolkit_data
= False
;
249 allocate_widget_info (const char* type
,
253 lw_callback pre_activate_cb
,
254 lw_callback selection_cb
,
255 lw_callback post_activate_cb
,
256 lw_callback highlight_cb
)
258 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
259 info
->type
= safe_strdup (type
);
260 info
->name
= safe_strdup (name
);
262 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
264 info
->pre_activate_cb
= pre_activate_cb
;
265 info
->selection_cb
= selection_cb
;
266 info
->post_activate_cb
= post_activate_cb
;
267 info
->highlight_cb
= highlight_cb
;
268 info
->instances
= NULL
;
270 info
->next
= all_widget_info
;
271 all_widget_info
= info
;
277 free_widget_info (widget_info
*info
)
279 safe_free_str (info
->type
);
280 safe_free_str (info
->name
);
281 free_widget_value_tree (info
->val
);
282 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
287 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
289 widget_instance
* instance
= (widget_instance
*)closure
;
291 /* be very conservative */
292 if (instance
->widget
== widget
)
293 instance
->widget
= NULL
;
296 static widget_instance
*
297 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
299 widget_instance
* instance
=
300 (widget_instance
*) xmalloc (sizeof (widget_instance
));
301 memset (instance
, 0, sizeof *instance
);
302 instance
->parent
= parent
;
303 instance
->pop_up_p
= pop_up_p
;
304 instance
->info
= info
;
305 instance
->next
= info
->instances
;
306 info
->instances
= instance
;
308 instantiate_widget_instance (instance
);
310 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
311 mark_widget_destroyed
, (XtPointer
)instance
);
316 free_widget_instance (widget_instance
*instance
)
318 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
323 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
327 for (prev
= NULL
, info
= all_widget_info
;
329 prev
= info
, info
= info
->next
)
335 prev
->next
= info
->next
;
337 all_widget_info
= info
->next
;
344 /* Internal function used by the library dependent implementation to get the
345 widget_value for a given widget in an instance */
347 lw_get_widget_info (LWLIB_ID id
)
349 return get_widget_info (id
, 0);
352 static widget_instance
*
353 get_widget_instance (Widget widget
, Boolean remove_p
)
356 widget_instance
* instance
;
357 widget_instance
* prev
;
358 for (info
= all_widget_info
; info
; info
= info
->next
)
359 for (prev
= NULL
, instance
= info
->instances
;
361 prev
= instance
, instance
= instance
->next
)
362 if (instance
->widget
== widget
)
367 prev
->next
= instance
->next
;
369 info
->instances
= instance
->next
;
373 return (widget_instance
*) 0;
376 /* Value is a pointer to the widget_instance corresponding to
377 WIDGET, or null if WIDGET is not a lwlib widget. */
380 lw_get_widget_instance (Widget widget
)
382 return get_widget_instance (widget
, False
);
385 static widget_instance
*
386 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
388 widget_info
* info
= get_widget_info (id
, False
);
389 widget_instance
* instance
;
392 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
393 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
400 /* utility function for widget_value */
402 safe_strcmp (const char *s1
, const char *s2
)
404 if (!!s1
^ !!s2
) return True
;
405 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
410 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
411 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
413 (oc == NO_CHANGE ? "none" : \
414 (oc == INVISIBLE_CHANGE ? "invisible" : \
415 (oc == VISIBLE_CHANGE ? "visible" : \
416 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
418 (nc == NO_CHANGE ? "none" : \
419 (nc == INVISIBLE_CHANGE ? "invisible" : \
420 (nc == VISIBLE_CHANGE ? "visible" : \
421 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
424 # define EXPLAIN(name, oc, nc, desc, a1, a2)
428 static widget_value
*
429 merge_widget_value (widget_value
*val1
,
434 change_type change
, this_one_change
;
435 widget_value
* merged_next
;
436 widget_value
* merged_contents
;
443 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
451 free_widget_value_tree (val1
);
457 if (safe_strcmp (val1
->name
, val2
->name
))
459 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
460 val1
->name
, val2
->name
);
461 change
= max (change
, STRUCTURAL_CHANGE
);
462 safe_free_str (val1
->name
);
463 val1
->name
= safe_strdup (val2
->name
);
465 if (safe_strcmp (val1
->value
, val2
->value
))
467 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
468 val1
->value
, val2
->value
);
469 change
= max (change
, VISIBLE_CHANGE
);
470 safe_free_str (val1
->value
);
471 val1
->value
= safe_strdup (val2
->value
);
473 if (safe_strcmp (val1
->key
, val2
->key
))
475 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
476 val1
->key
, val2
->key
);
477 change
= max (change
, VISIBLE_CHANGE
);
478 safe_free_str (val1
->key
);
479 val1
->key
= safe_strdup (val2
->key
);
481 if (! EQ (val1
->help
, val2
->help
))
483 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
484 val1
->help
, val2
->help
);
485 change
= max (change
, VISIBLE_CHANGE
);
486 val1
->help
= val2
->help
;
488 if (val1
->enabled
!= val2
->enabled
)
490 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
491 val1
->enabled
, val2
->enabled
);
492 change
= max (change
, VISIBLE_CHANGE
);
493 val1
->enabled
= val2
->enabled
;
495 if (val1
->button_type
!= val2
->button_type
)
497 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
498 val1
->button_type
, val2
->button_type
);
499 change
= max (change
, VISIBLE_CHANGE
);
500 val1
->button_type
= val2
->button_type
;
502 if (val1
->selected
!= val2
->selected
)
504 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
505 val1
->selected
, val2
->selected
);
506 change
= max (change
, VISIBLE_CHANGE
);
507 val1
->selected
= val2
->selected
;
509 if (val1
->call_data
!= val2
->call_data
)
511 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
512 val1
->call_data
, val2
->call_data
);
513 change
= max (change
, INVISIBLE_CHANGE
);
514 val1
->call_data
= val2
->call_data
;
520 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
523 if (val1
->contents
&& !merged_contents
)
525 /* This used to say INVISIBLE_CHANGE,
526 but it is visible and vitally important when
527 the contents of the menu bar itself are entirely deleted.
529 But maybe it doesn't matter. This fails to fix the bug. */
530 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
532 change
= max (change
, STRUCTURAL_CHANGE
);
534 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
536 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
538 change
= max (change
, INVISIBLE_CHANGE
);
539 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
541 change
= max (merged_contents
->change
, change
);
546 val1
->contents
= merged_contents
;
549 this_one_change
= change
;
551 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
553 if (val1
->next
&& !merged_next
)
555 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
557 change
= max (change
, STRUCTURAL_CHANGE
);
559 else if (merged_next
)
561 if (merged_next
->change
)
562 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
564 change
= max (change
, merged_next
->change
);
567 val1
->next
= merged_next
;
569 val1
->this_one_change
= this_one_change
;
570 val1
->change
= change
;
572 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
575 if (val1
->free_toolkit_data
)
576 XtFree (val1
->toolkit_data
);
577 val1
->toolkit_data
= NULL
;
584 /* modifying the widgets */
586 name_to_widget (widget_instance
*instance
, const char *name
)
588 Widget widget
= NULL
;
590 if (!instance
->widget
)
593 if (!strcmp (XtName (instance
->widget
), name
))
594 widget
= instance
->widget
;
597 int length
= strlen (name
) + 2;
598 char* real_name
= (char *) xmalloc (length
);
600 strcpy (real_name
+ 1, name
);
602 widget
= XtNameToWidget (instance
->widget
, real_name
);
610 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
612 Widget widget
= name_to_widget (instance
, val
->name
);
616 #if defined (USE_LUCID)
617 if (lw_lucid_widget_p (instance
->widget
))
618 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
620 #if defined (USE_MOTIF)
621 if (lw_motif_widget_p (instance
->widget
))
622 xm_update_one_widget (instance
, widget
, val
, deep_p
);
624 #if defined (USE_XAW)
625 if (lw_xaw_widget_p (instance
->widget
))
626 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
632 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
636 if (!instance
->widget
)
637 /* the widget was destroyed */
640 for (val
= instance
->info
->val
; val
; val
= val
->next
)
641 if (val
->change
!= NO_CHANGE
)
642 set_one_value (instance
, val
, deep_p
);
646 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
648 widget_instance
* instance
;
651 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
652 update_one_widget_instance (instance
, deep_p
);
654 for (val
= info
->val
; val
; val
= val
->next
)
655 val
->change
= NO_CHANGE
;
659 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
661 widget_info
* info
= get_widget_info (id
, False
);
662 widget_value
* new_val
;
663 widget_value
* next_new_val
;
673 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
675 next_new_val
= new_val
->next
;
676 new_val
->next
= NULL
;
678 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
679 if (!strcmp (cur
->name
, new_val
->name
))
684 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
687 prev
->next
= cur
? cur
: next
;
689 info
->val
= cur
? cur
: next
;
696 /* Could not find it, add it */
698 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
700 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
703 new_val
->next
= next_new_val
;
706 update_all_widget_values (info
, deep_p
);
711 /* creating the widgets */
714 initialize_widget_instance (widget_instance
*instance
)
718 for (val
= instance
->info
->val
; val
; val
= val
->next
)
719 val
->change
= STRUCTURAL_CHANGE
;
721 update_one_widget_instance (instance
, True
);
723 for (val
= instance
->info
->val
; val
; val
= val
->next
)
724 val
->change
= NO_CHANGE
;
728 static widget_creation_function
729 find_in_table (const char *type
, const widget_creation_entry
*table
)
731 const widget_creation_entry
* cur
;
732 for (cur
= table
; cur
->type
; cur
++)
733 if (!my_strcasecmp (type
, cur
->type
))
734 return cur
->function
;
739 dialog_spec_p (const char *name
)
741 /* return True if name matches [EILPQeilpq][1-9][Bb] or
742 [EILPQeilpq][1-9][Bb][Rr][1-9] */
748 case 'E': case 'I': case 'L': case 'P': case 'Q':
749 case 'e': case 'i': case 'l': case 'p': case 'q':
750 if (name
[1] >= '0' && name
[1] <= '9')
752 if (name
[2] != 'B' && name
[2] != 'b')
756 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
758 if ((name
[3] == 'R' || name
[3] == 'r')
759 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
772 instantiate_widget_instance (widget_instance
*instance
)
774 widget_creation_function function
= NULL
;
776 #if defined (USE_LUCID)
778 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
780 #if defined(USE_MOTIF)
782 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
784 #if defined (USE_XAW)
786 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
791 if (dialog_spec_p (instance
->info
->type
))
793 #if defined (USE_LUCID)
796 #if defined(USE_MOTIF)
798 function
= xm_create_dialog
;
800 #if defined (USE_XAW)
802 function
= xaw_create_dialog
;
809 printf ("No creation function for widget type %s\n",
810 instance
->info
->type
);
814 instance
->widget
= (*function
) (instance
);
816 if (!instance
->widget
)
819 /* XtRealizeWidget (instance->widget);*/
823 lw_register_widget (const char* type
,
827 lw_callback pre_activate_cb
,
828 lw_callback selection_cb
,
829 lw_callback post_activate_cb
,
830 lw_callback highlight_cb
)
832 if (!get_widget_info (id
, False
))
833 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
834 post_activate_cb
, highlight_cb
);
838 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
840 widget_instance
* instance
;
842 instance
= find_instance (id
, parent
, pop_up_p
);
843 return instance
? instance
->widget
: NULL
;
847 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
849 widget_instance
* instance
;
852 instance
= find_instance (id
, parent
, pop_up_p
);
855 info
= get_widget_info (id
, False
);
858 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
859 initialize_widget_instance (instance
);
861 if (!instance
->widget
)
863 return instance
->widget
;
867 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
868 Widget parent
, Boolean pop_up_p
,
869 lw_callback pre_activate_cb
, lw_callback selection_cb
,
870 lw_callback post_activate_cb
, lw_callback highlight_cb
)
872 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
873 post_activate_cb
, highlight_cb
);
874 return lw_make_widget (id
, parent
, pop_up_p
);
878 /* destroying the widgets */
880 destroy_one_instance (widget_instance
*instance
)
882 /* Remove the destroy callback on the widget; that callback will try to
883 dereference the instance object (to set its widget slot to 0, since the
884 widget is dead.) Since the instance is now dead, we don't have to worry
885 about the fact that its widget is dead too.
887 This happens in the Phase2Destroy of the widget, so this callback would
888 not have been run until arbitrarily long after the instance was freed.
890 if (instance
->widget
)
891 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
892 mark_widget_destroyed
, (XtPointer
)instance
);
894 if (instance
->widget
)
896 /* The else are pretty tricky here, including the empty statement
897 at the end because it would be very bad to destroy a widget
899 #if defined (USE_LUCID)
900 if (lw_lucid_widget_p (instance
->widget
))
901 xlw_destroy_instance (instance
);
904 #if defined (USE_MOTIF)
905 if (lw_motif_widget_p (instance
->widget
))
906 xm_destroy_instance (instance
);
909 #if defined (USE_XAW)
910 if (lw_xaw_widget_p (instance
->widget
))
911 xaw_destroy_instance (instance
);
914 /* do not remove the empty statement */
918 free_widget_instance (instance
);
922 lw_destroy_widget (Widget w
)
924 widget_instance
* instance
= get_widget_instance (w
, True
);
928 widget_info
*info
= instance
->info
;
929 /* instance has already been removed from the list; free it */
930 destroy_one_instance (instance
);
931 /* if there are no instances left, free the info too */
932 if (!info
->instances
)
933 lw_destroy_all_widgets (info
->id
);
938 lw_destroy_all_widgets (LWLIB_ID id
)
940 widget_info
* info
= get_widget_info (id
, True
);
941 widget_instance
* instance
;
942 widget_instance
* next
;
946 for (instance
= info
->instances
; instance
; )
948 next
= instance
->next
;
949 destroy_one_instance (instance
);
952 free_widget_info (info
);
957 lw_destroy_everything (void)
959 while (all_widget_info
)
960 lw_destroy_all_widgets (all_widget_info
->id
);
964 lw_destroy_all_pop_ups (void)
968 widget_instance
* instance
;
970 for (info
= all_widget_info
; info
; info
= next
)
973 instance
= info
->instances
;
974 if (instance
&& instance
->pop_up_p
)
975 lw_destroy_all_widgets (info
->id
);
980 extern Widget
first_child (/* Widget */); /* garbage */
984 lw_raise_all_pop_up_widgets (void)
987 widget_instance
* instance
;
988 Widget result
= NULL
;
990 for (info
= all_widget_info
; info
; info
= info
->next
)
991 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
992 if (instance
->pop_up_p
)
994 Widget widget
= instance
->widget
;
997 if (XtIsManaged (widget
)
999 /* What a complete load of crap!!!!
1000 When a dialogShell is on the screen, it is not managed!
1002 || (lw_motif_widget_p (instance
->widget
) &&
1003 XtIsManaged (first_child (widget
)))
1009 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1017 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1019 widget_info
* info
= get_widget_info (id
, False
);
1020 widget_instance
* instance
;
1023 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1024 if (instance
->pop_up_p
&& instance
->widget
)
1026 #if defined (USE_LUCID)
1027 if (lw_lucid_widget_p (instance
->widget
))
1029 XtRealizeWidget (instance
->widget
);
1030 xlw_pop_instance (instance
, up
);
1033 #if defined (USE_MOTIF)
1034 if (lw_motif_widget_p (instance
->widget
))
1036 XtRealizeWidget (instance
->widget
);
1037 xm_pop_instance (instance
, up
);
1040 #if defined (USE_XAW)
1041 if (lw_xaw_widget_p (instance
->widget
))
1043 XtRealizeWidget (XtParent (instance
->widget
));
1044 XtRealizeWidget (instance
->widget
);
1045 xaw_pop_instance (instance
, up
);
1052 lw_pop_up_all_widgets (LWLIB_ID id
)
1054 lw_pop_all_widgets (id
, True
);
1058 lw_pop_down_all_widgets (LWLIB_ID id
)
1060 lw_pop_all_widgets (id
, False
);
1064 lw_popup_menu (Widget widget
, XEvent
*event
)
1066 #if defined (USE_LUCID)
1067 if (lw_lucid_widget_p (widget
))
1068 xlw_popup_menu (widget
, event
);
1070 #if defined (USE_MOTIF)
1071 if (lw_motif_widget_p (widget
))
1072 xm_popup_menu (widget
, event
);
1074 #if defined (USE_XAW)
1075 if (lw_xaw_widget_p (widget
))
1076 xaw_popup_menu (widget
, event
);
1080 \f/* get the values back */
1082 get_one_value (widget_instance
*instance
, widget_value
*val
)
1084 Widget widget
= name_to_widget (instance
, val
->name
);
1088 #if defined (USE_LUCID)
1089 if (lw_lucid_widget_p (instance
->widget
))
1090 xlw_update_one_value (instance
, widget
, val
);
1092 #if defined (USE_MOTIF)
1093 if (lw_motif_widget_p (instance
->widget
))
1094 xm_update_one_value (instance
, widget
, val
);
1096 #if defined (USE_XAW)
1097 if (lw_xaw_widget_p (instance
->widget
))
1098 xaw_update_one_value (instance
, widget
, val
);
1107 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1109 widget_info
* info
= get_widget_info (id
, False
);
1110 widget_instance
* instance
;
1112 Boolean result
= False
;
1117 instance
= info
->instances
;
1121 for (val
= val_out
; val
; val
= val
->next
)
1122 if (get_one_value (instance
, val
))
1129 lw_get_all_values (LWLIB_ID id
)
1131 widget_info
* info
= get_widget_info (id
, False
);
1132 widget_value
* val
= info
->val
;
1133 if (lw_get_some_values (id
, val
))
1139 /* internal function used by the library dependent implementation to get the
1140 widget_value for a given widget in an instance */
1142 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1144 char* name
= XtName (w
);
1146 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1147 if (!strcmp (cur
->name
, name
))
1152 \f/* update other instances value when one thing changed */
1154 /* To forbid recursive calls */
1155 static Boolean lwlib_updating
;
1157 /* This function can be used as a an XtCallback for the widgets that get
1158 modified to update other instances of the widgets. Closure should be the
1161 lw_internal_update_other_instances (Widget widget
,
1163 XtPointer call_data
)
1165 widget_instance
* instance
= (widget_instance
*)closure
;
1166 char* name
= XtName (widget
);
1168 widget_instance
* cur
;
1171 /* Avoid possibly infinite recursion. */
1175 /* protect against the widget being destroyed */
1176 if (XtWidgetBeingDestroyedP (widget
))
1179 /* Return immediately if there are no other instances */
1180 info
= instance
->info
;
1181 if (!info
->instances
->next
)
1184 lwlib_updating
= True
;
1186 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1188 if (val
&& get_one_value (instance
, val
))
1189 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1190 if (cur
!= instance
)
1191 set_one_value (cur
, val
, True
);
1193 lwlib_updating
= False
;
1200 lw_get_widget_id (Widget w
)
1202 widget_instance
* instance
= get_widget_instance (w
, False
);
1204 return instance
? instance
->info
->id
: 0;
1207 \f/* set the keyboard focus */
1209 lw_set_keyboard_focus (Widget parent
, Widget w
)
1211 #if defined (USE_MOTIF)
1212 xm_set_keyboard_focus (parent
, w
);
1214 XtSetKeyboardFocus (parent
, w
);
1220 show_one_widget_busy (Widget w
, Boolean flag
)
1222 Pixel foreground
= 0;
1223 Pixel background
= 1;
1224 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1225 if (!widget_to_invert
)
1226 widget_to_invert
= w
;
1228 XtVaGetValues (widget_to_invert
,
1229 XtNforeground
, &foreground
,
1230 XtNbackground
, &background
,
1232 XtVaSetValues (widget_to_invert
,
1233 XtNforeground
, background
,
1234 XtNbackground
, foreground
,
1239 lw_show_busy (Widget w
, Boolean busy
)
1241 widget_instance
* instance
= get_widget_instance (w
, False
);
1243 widget_instance
* next
;
1247 info
= instance
->info
;
1248 if (info
->busy
!= busy
)
1250 for (next
= info
->instances
; next
; next
= next
->next
)
1252 show_one_widget_busy (next
->widget
, busy
);
1258 /* This hack exists because Lucid/Athena need to execute the strange
1259 function below to support geometry management. */
1261 lw_refigure_widget (Widget w
, Boolean doit
)
1263 #if defined (USE_XAW)
1264 XawPanedSetRefigureMode (w
, doit
);
1266 #if defined (USE_MOTIF)
1270 XtUnmanageChild (w
);
1274 /* Toolkit independent way of determining if an event window is in the
1277 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1279 return menubar_widget
1280 #if defined (USE_LUCID)
1281 && XtWindow (menubar_widget
) == win
;
1283 #if defined (USE_MOTIF)
1284 && ((XtWindow (menubar_widget
) == win
)
1285 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1286 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1287 == menubar_widget
)));
1291 /* Motif hack to set the main window areas. */
1293 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1295 #if defined (USE_MOTIF)
1296 xm_set_main_areas (parent
, menubar
, work_area
);
1300 /* Manage resizing for Motif. This disables resizing when the menubar
1301 is about to be modified. */
1303 lw_allow_resizing (Widget w
, Boolean flag
)
1305 #if defined (USE_MOTIF)
1306 xm_manage_resizing (w
, flag
);
1311 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1312 set to an appropriate enumerator of type enum menu_separator.
1313 MOTIF_P non-zero means map separator types not supported by Motif
1314 to similar ones that are supported. */
1317 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1319 int separator_p
= 0;
1321 if (strlen (label
) >= 3
1322 && memcmp (label
, "--:", 3) == 0)
1324 static struct separator_table
1327 enum menu_separator type
;
1331 {"space", SEPARATOR_NO_LINE
},
1332 {"noLine", SEPARATOR_NO_LINE
},
1333 {"singleLine", SEPARATOR_SINGLE_LINE
},
1334 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1335 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1336 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1337 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1338 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1339 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1340 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1341 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1342 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1343 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1344 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1351 for (i
= 0; separator_names
[i
].name
; ++i
)
1352 if (strcmp (label
, separator_names
[i
].name
) == 0)
1355 *type
= separator_names
[i
].type
;
1357 /* If separator type is not supported under Motif,
1358 use a similar one. */
1359 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1364 else if (strlen (label
) > 3
1365 && memcmp (label
, "--", 2) == 0
1368 /* Alternative, more Emacs-style names. */
1369 static struct separator_table
1372 enum menu_separator type
;
1376 {"space", SEPARATOR_NO_LINE
},
1377 {"no-line", SEPARATOR_NO_LINE
},
1378 {"single-line", SEPARATOR_SINGLE_LINE
},
1379 {"double-line", SEPARATOR_DOUBLE_LINE
},
1380 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1381 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1382 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1383 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1384 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1385 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1386 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1387 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1388 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1389 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1396 for (i
= 0; separator_names
[i
].name
; ++i
)
1397 if (strcmp (label
, separator_names
[i
].name
) == 0)
1400 *type
= separator_names
[i
].type
;
1402 /* If separator type is not supported under Motif,
1403 use a similar one. */
1404 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1411 /* Old-style separator, maybe. It's a separator if it contains
1413 while (*label
== '-')
1415 separator_p
= *label
== 0;
1416 *type
= SEPARATOR_SHADOW_ETCHED_IN
;