1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
3 Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007, 2008 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. */
24 #undef __STRICT_BSD__ /* ick */
31 #include "../src/lisp.h"
33 #include <sys/types.h>
36 #include "lwlib-int.h"
37 #include "lwlib-utils.h"
38 #include <X11/StringDefs.h>
40 #if defined (USE_LUCID)
41 #include "lwlib-Xlw.h"
43 #if defined (USE_MOTIF)
45 #else /* not USE_MOTIF */
46 #if defined (USE_LUCID)
48 #endif /* not USE_MOTIF && USE_LUCID */
52 #include <X11/Xaw3d/Paned.h>
53 #else /* !HAVE_XAW3D */
54 #include <X11/Xaw/Paned.h>
55 #endif /* HAVE_XAW3D */
56 #include "lwlib-Xaw.h"
59 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
60 #error At least one of USE_LUCID or USE_MOTIF must be defined.
64 #define max(x, y) ((x) > (y) ? (x) : (y))
67 /* List of all widgets managed by the library. */
69 all_widget_info
= NULL
;
72 char *lwlib_toolkit_type
= "motif";
74 char *lwlib_toolkit_type
= "lucid";
77 static widget_value
*merge_widget_value
P_ ((widget_value
*,
80 static void instantiate_widget_instance
P_ ((widget_instance
*));
81 static int my_strcasecmp
P_ ((char *, char *));
82 static void safe_free_str
P_ ((char *));
83 static void free_widget_value_tree
P_ ((widget_value
*));
84 static widget_value
*copy_widget_value_tree
P_ ((widget_value
*,
86 static widget_info
*allocate_widget_info
P_ ((char *, char *, LWLIB_ID
,
88 lw_callback
, lw_callback
,
89 lw_callback
, lw_callback
));
90 static void free_widget_info
P_ ((widget_info
*));
91 static void mark_widget_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
92 static widget_instance
*allocate_widget_instance
P_ ((widget_info
*,
94 static void free_widget_instance
P_ ((widget_instance
*));
95 static widget_info
*get_widget_info
P_ ((LWLIB_ID
, Boolean
));
96 static widget_instance
*get_widget_instance
P_ ((Widget
, Boolean
));
97 static widget_instance
*find_instance
P_ ((LWLIB_ID
, Widget
, Boolean
));
98 static Boolean safe_strcmp
P_ ((char *, char *));
99 static Widget name_to_widget
P_ ((widget_instance
*, char *));
100 static void set_one_value
P_ ((widget_instance
*, widget_value
*, Boolean
));
101 static void update_one_widget_instance
P_ ((widget_instance
*, Boolean
));
102 static void update_all_widget_values
P_ ((widget_info
*, Boolean
));
103 static void initialize_widget_instance
P_ ((widget_instance
*));
104 static widget_creation_function find_in_table
P_ ((char *, widget_creation_entry
*));
105 static Boolean dialog_spec_p
P_ ((char *));
106 static void destroy_one_instance
P_ ((widget_instance
*));
107 static void lw_pop_all_widgets
P_ ((LWLIB_ID
, Boolean
));
108 static Boolean get_one_value
P_ ((widget_instance
*, widget_value
*));
109 static void show_one_widget_busy
P_ ((Widget
, Boolean
));
112 lwlib_memset (address
, value
, length
)
119 for (i
= 0; i
< length
; i
++)
124 lwlib_bcopy (from
, to
, length
)
131 for (i
= 0; i
< length
; i
++)
134 \f/* utility functions for widget_instance and widget_info */
141 result
= (char *) malloc (strlen (s
) + 1);
148 /* Like strcmp but ignore differences in case. */
151 my_strcasecmp (s1
, s2
)
163 return (c1
> c2
? 1 : -1);
176 static widget_value
*widget_value_free_list
= 0;
177 static int malloc_cpt
= 0;
180 malloc_widget_value ()
183 if (widget_value_free_list
)
185 wv
= widget_value_free_list
;
186 widget_value_free_list
= wv
->free_list
;
191 wv
= (widget_value
*) malloc (sizeof (widget_value
));
194 lwlib_memset ((void*) wv
, 0, sizeof (widget_value
));
198 /* this is analogous to free(). It frees only what was allocated
199 by malloc_widget_value(), and no substructures.
202 free_widget_value (wv
)
210 /* When the number of already allocated cells is too big,
217 wv
->free_list
= widget_value_free_list
;
218 widget_value_free_list
= wv
;
223 free_widget_value_tree (wv
)
233 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
235 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
237 XtFree (wv
->toolkit_data
);
238 wv
->toolkit_data
= (void *) 0xDEADBEEF;
241 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
243 free_widget_value_tree (wv
->contents
);
244 wv
->contents
= (widget_value
*) 0xDEADBEEF;
248 free_widget_value_tree (wv
->next
);
249 wv
->next
= (widget_value
*) 0xDEADBEEF;
251 free_widget_value (wv
);
254 static widget_value
*
255 copy_widget_value_tree (val
, change
)
263 if (val
== (widget_value
*) 1)
266 copy
= malloc_widget_value ();
267 copy
->name
= safe_strdup (val
->name
);
268 copy
->value
= safe_strdup (val
->value
);
269 copy
->key
= safe_strdup (val
->key
);
270 copy
->help
= val
->help
;
271 copy
->enabled
= val
->enabled
;
272 copy
->button_type
= val
->button_type
;
273 copy
->selected
= val
->selected
;
274 copy
->edited
= False
;
275 copy
->change
= change
;
276 copy
->this_one_change
= change
;
277 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
278 copy
->call_data
= val
->call_data
;
279 copy
->next
= copy_widget_value_tree (val
->next
, change
);
280 copy
->toolkit_data
= NULL
;
281 copy
->free_toolkit_data
= False
;
286 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
287 selection_cb
, post_activate_cb
, highlight_cb
)
292 lw_callback pre_activate_cb
;
293 lw_callback selection_cb
;
294 lw_callback post_activate_cb
;
295 lw_callback highlight_cb
;
297 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
298 info
->type
= safe_strdup (type
);
299 info
->name
= safe_strdup (name
);
301 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
303 info
->pre_activate_cb
= pre_activate_cb
;
304 info
->selection_cb
= selection_cb
;
305 info
->post_activate_cb
= post_activate_cb
;
306 info
->highlight_cb
= highlight_cb
;
307 info
->instances
= NULL
;
309 info
->next
= all_widget_info
;
310 all_widget_info
= info
;
316 free_widget_info (info
)
319 safe_free_str (info
->type
);
320 safe_free_str (info
->name
);
321 free_widget_value_tree (info
->val
);
322 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
327 mark_widget_destroyed (widget
, closure
, call_data
)
332 widget_instance
* instance
= (widget_instance
*)closure
;
334 /* be very conservative */
335 if (instance
->widget
== widget
)
336 instance
->widget
= NULL
;
339 /* The messy #ifdef PROTOTYPES here and elsewhere are prompted by a
340 flood of warnings about argument promotion from proprietary ISO C
341 compilers. (etags still only makes one entry for each function.) */
342 static widget_instance
*
344 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
346 allocate_widget_instance (info
, parent
, pop_up_p
)
352 widget_instance
* instance
=
353 (widget_instance
*)malloc (sizeof (widget_instance
));
354 bzero (instance
, sizeof *instance
);
355 instance
->parent
= parent
;
356 instance
->pop_up_p
= pop_up_p
;
357 instance
->info
= info
;
358 instance
->next
= info
->instances
;
359 info
->instances
= instance
;
361 instantiate_widget_instance (instance
);
363 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
364 mark_widget_destroyed
, (XtPointer
)instance
);
369 free_widget_instance (instance
)
370 widget_instance
* instance
;
372 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
378 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
380 get_widget_info (id
, remove_p
)
387 for (prev
= NULL
, info
= all_widget_info
;
389 prev
= info
, info
= info
->next
)
395 prev
->next
= info
->next
;
397 all_widget_info
= info
->next
;
404 /* Internal function used by the library dependent implementation to get the
405 widget_value for a given widget in an instance */
407 lw_get_widget_info (id
)
410 return get_widget_info (id
, 0);
413 static widget_instance
*
415 get_widget_instance (Widget widget
, Boolean remove_p
)
417 get_widget_instance (widget
, remove_p
)
423 widget_instance
* instance
;
424 widget_instance
* prev
;
425 for (info
= all_widget_info
; info
; info
= info
->next
)
426 for (prev
= NULL
, instance
= info
->instances
;
428 prev
= instance
, instance
= instance
->next
)
429 if (instance
->widget
== widget
)
434 prev
->next
= instance
->next
;
436 info
->instances
= instance
->next
;
440 return (widget_instance
*) 0;
443 /* Value is a pointer to the widget_instance corresponding to
444 WIDGET, or null if WIDGET is not a lwlib widget. */
447 lw_get_widget_instance (widget
)
450 return get_widget_instance (widget
, False
);
453 static widget_instance
*
455 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
457 find_instance (id
, parent
, pop_up_p
)
463 widget_info
* info
= get_widget_info (id
, False
);
464 widget_instance
* instance
;
467 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
468 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
475 /* utility function for widget_value */
481 if (!!s1
^ !!s2
) return True
;
482 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
487 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
488 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
490 (oc == NO_CHANGE ? "none" : \
491 (oc == INVISIBLE_CHANGE ? "invisible" : \
492 (oc == VISIBLE_CHANGE ? "visible" : \
493 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
495 (nc == NO_CHANGE ? "none" : \
496 (nc == INVISIBLE_CHANGE ? "invisible" : \
497 (nc == VISIBLE_CHANGE ? "visible" : \
498 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
501 # define EXPLAIN(name, oc, nc, desc, a1, a2)
505 static widget_value
*
506 merge_widget_value (val1
, val2
, level
, change_p
)
512 change_type change
, this_one_change
;
513 widget_value
* merged_next
;
514 widget_value
* merged_contents
;
521 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
529 free_widget_value_tree (val1
);
535 if (safe_strcmp (val1
->name
, val2
->name
))
537 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
538 val1
->name
, val2
->name
);
539 change
= max (change
, STRUCTURAL_CHANGE
);
540 safe_free_str (val1
->name
);
541 val1
->name
= safe_strdup (val2
->name
);
543 if (safe_strcmp (val1
->value
, val2
->value
))
545 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
546 val1
->value
, val2
->value
);
547 change
= max (change
, VISIBLE_CHANGE
);
548 safe_free_str (val1
->value
);
549 val1
->value
= safe_strdup (val2
->value
);
551 if (safe_strcmp (val1
->key
, val2
->key
))
553 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
554 val1
->key
, val2
->key
);
555 change
= max (change
, VISIBLE_CHANGE
);
556 safe_free_str (val1
->key
);
557 val1
->key
= safe_strdup (val2
->key
);
559 if (! EQ (val1
->help
, val2
->help
))
561 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
562 val1
->help
, val2
->help
);
563 change
= max (change
, VISIBLE_CHANGE
);
564 val1
->help
= val2
->help
;
566 if (val1
->enabled
!= val2
->enabled
)
568 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
569 val1
->enabled
, val2
->enabled
);
570 change
= max (change
, VISIBLE_CHANGE
);
571 val1
->enabled
= val2
->enabled
;
573 if (val1
->button_type
!= val2
->button_type
)
575 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
576 val1
->button_type
, val2
->button_type
);
577 change
= max (change
, VISIBLE_CHANGE
);
578 val1
->button_type
= val2
->button_type
;
580 if (val1
->selected
!= val2
->selected
)
582 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
583 val1
->selected
, val2
->selected
);
584 change
= max (change
, VISIBLE_CHANGE
);
585 val1
->selected
= val2
->selected
;
587 if (val1
->call_data
!= val2
->call_data
)
589 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
590 val1
->call_data
, val2
->call_data
);
591 change
= max (change
, INVISIBLE_CHANGE
);
592 val1
->call_data
= val2
->call_data
;
598 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
601 if (val1
->contents
&& !merged_contents
)
603 /* This used to say INVISIBLE_CHANGE,
604 but it is visible and vitally important when
605 the contents of the menu bar itself are entirely deleted.
607 But maybe it doesn't matter. This fails to fix the bug. */
608 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
610 change
= max (change
, STRUCTURAL_CHANGE
);
612 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
614 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
616 change
= max (change
, INVISIBLE_CHANGE
);
617 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
619 change
= max (merged_contents
->change
, change
);
624 val1
->contents
= merged_contents
;
627 this_one_change
= change
;
629 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
631 if (val1
->next
&& !merged_next
)
633 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
635 change
= max (change
, STRUCTURAL_CHANGE
);
637 else if (merged_next
)
639 if (merged_next
->change
)
640 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
642 change
= max (change
, merged_next
->change
);
645 val1
->next
= merged_next
;
647 val1
->this_one_change
= this_one_change
;
648 val1
->change
= change
;
650 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
653 if (val1
->free_toolkit_data
)
654 XtFree (val1
->toolkit_data
);
655 val1
->toolkit_data
= NULL
;
662 /* modifying the widgets */
664 name_to_widget (instance
, name
)
665 widget_instance
* instance
;
668 Widget widget
= NULL
;
670 if (!instance
->widget
)
673 if (!strcmp (XtName (instance
->widget
), name
))
674 widget
= instance
->widget
;
677 int length
= strlen (name
) + 2;
678 char* real_name
= (char *) xmalloc (length
);
680 strcpy (real_name
+ 1, name
);
682 widget
= XtNameToWidget (instance
->widget
, real_name
);
691 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
693 set_one_value (instance
, val
, deep_p
)
694 widget_instance
* instance
;
699 Widget widget
= name_to_widget (instance
, val
->name
);
703 #if defined (USE_LUCID)
704 if (lw_lucid_widget_p (instance
->widget
))
705 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
707 #if defined (USE_MOTIF)
708 if (lw_motif_widget_p (instance
->widget
))
709 xm_update_one_widget (instance
, widget
, val
, deep_p
);
711 #if defined (USE_XAW)
712 if (lw_xaw_widget_p (instance
->widget
))
713 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
720 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
722 update_one_widget_instance (instance
, deep_p
)
723 widget_instance
* instance
;
729 if (!instance
->widget
)
730 /* the widget was destroyed */
733 for (val
= instance
->info
->val
; val
; val
= val
->next
)
734 if (val
->change
!= NO_CHANGE
)
735 set_one_value (instance
, val
, deep_p
);
740 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
742 update_all_widget_values (info
, deep_p
)
747 widget_instance
* instance
;
750 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
751 update_one_widget_instance (instance
, deep_p
);
753 for (val
= info
->val
; val
; val
= val
->next
)
754 val
->change
= NO_CHANGE
;
759 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
761 lw_modify_all_widgets (id
, val
, deep_p
)
767 widget_info
* info
= get_widget_info (id
, False
);
768 widget_value
* new_val
;
769 widget_value
* next_new_val
;
779 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
781 next_new_val
= new_val
->next
;
782 new_val
->next
= NULL
;
784 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
785 if (!strcmp (cur
->name
, new_val
->name
))
790 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
793 prev
->next
= cur
? cur
: next
;
795 info
->val
= cur
? cur
: next
;
802 /* Could not find it, add it */
804 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
806 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
809 new_val
->next
= next_new_val
;
812 update_all_widget_values (info
, deep_p
);
817 /* creating the widgets */
820 initialize_widget_instance (instance
)
821 widget_instance
* instance
;
825 for (val
= instance
->info
->val
; val
; val
= val
->next
)
826 val
->change
= STRUCTURAL_CHANGE
;
828 update_one_widget_instance (instance
, True
);
830 for (val
= instance
->info
->val
; val
; val
= val
->next
)
831 val
->change
= NO_CHANGE
;
835 static widget_creation_function
836 find_in_table (type
, table
)
838 widget_creation_entry
* table
;
840 widget_creation_entry
* cur
;
841 for (cur
= table
; cur
->type
; cur
++)
842 if (!my_strcasecmp (type
, cur
->type
))
843 return cur
->function
;
851 /* return True if name matches [EILPQeilpq][1-9][Bb] or
852 [EILPQeilpq][1-9][Bb][Rr][1-9] */
858 case 'E': case 'I': case 'L': case 'P': case 'Q':
859 case 'e': case 'i': case 'l': case 'p': case 'q':
860 if (name
[1] >= '0' && name
[1] <= '9')
862 if (name
[2] != 'B' && name
[2] != 'b')
866 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
868 if ((name
[3] == 'R' || name
[3] == 'r')
869 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
882 instantiate_widget_instance (instance
)
883 widget_instance
* instance
;
885 widget_creation_function function
= NULL
;
887 #if defined (USE_LUCID)
889 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
891 #if defined(USE_MOTIF)
893 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
895 #if defined (USE_XAW)
897 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
902 if (dialog_spec_p (instance
->info
->type
))
904 #if defined (USE_LUCID)
907 #if defined(USE_MOTIF)
909 function
= xm_create_dialog
;
911 #if defined (USE_XAW)
913 function
= xaw_create_dialog
;
920 printf ("No creation function for widget type %s\n",
921 instance
->info
->type
);
925 instance
->widget
= (*function
) (instance
);
927 if (!instance
->widget
)
930 /* XtRealizeWidget (instance->widget);*/
934 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
935 selection_cb
, post_activate_cb
, highlight_cb
)
940 lw_callback pre_activate_cb
;
941 lw_callback selection_cb
;
942 lw_callback post_activate_cb
;
943 lw_callback highlight_cb
;
945 if (!get_widget_info (id
, False
))
946 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
947 post_activate_cb
, highlight_cb
);
952 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
954 lw_get_widget (id
, parent
, pop_up_p
)
960 widget_instance
* instance
;
962 instance
= find_instance (id
, parent
, pop_up_p
);
963 return instance
? instance
->widget
: NULL
;
968 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
970 lw_make_widget (id
, parent
, pop_up_p
)
976 widget_instance
* instance
;
979 instance
= find_instance (id
, parent
, pop_up_p
);
982 info
= get_widget_info (id
, False
);
985 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
986 initialize_widget_instance (instance
);
988 if (!instance
->widget
)
990 return instance
->widget
;
995 lw_create_widget (char* type
, char* name
, LWLIB_ID id
, widget_value
* val
,
996 Widget parent
, Boolean pop_up_p
,
997 lw_callback pre_activate_cb
, lw_callback selection_cb
,
998 lw_callback post_activate_cb
, lw_callback highlight_cb
)
1000 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
1001 selection_cb
, post_activate_cb
, highlight_cb
)
1008 lw_callback pre_activate_cb
;
1009 lw_callback selection_cb
;
1010 lw_callback post_activate_cb
;
1011 lw_callback highlight_cb
;
1014 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
1015 post_activate_cb
, highlight_cb
);
1016 return lw_make_widget (id
, parent
, pop_up_p
);
1020 /* destroying the widgets */
1022 destroy_one_instance (instance
)
1023 widget_instance
* instance
;
1025 /* Remove the destroy callback on the widget; that callback will try to
1026 dereference the instance object (to set its widget slot to 0, since the
1027 widget is dead.) Since the instance is now dead, we don't have to worry
1028 about the fact that its widget is dead too.
1030 This happens in the Phase2Destroy of the widget, so this callback would
1031 not have been run until arbitrarily long after the instance was freed.
1033 if (instance
->widget
)
1034 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1035 mark_widget_destroyed
, (XtPointer
)instance
);
1037 if (instance
->widget
)
1039 /* The else are pretty tricky here, including the empty statement
1040 at the end because it would be very bad to destroy a widget
1042 #if defined (USE_LUCID)
1043 if (lw_lucid_widget_p (instance
->widget
))
1044 xlw_destroy_instance (instance
);
1047 #if defined (USE_MOTIF)
1048 if (lw_motif_widget_p (instance
->widget
))
1049 xm_destroy_instance (instance
);
1052 #if defined (USE_XAW)
1053 if (lw_xaw_widget_p (instance
->widget
))
1054 xaw_destroy_instance (instance
);
1057 /* do not remove the empty statement */
1061 free_widget_instance (instance
);
1065 lw_destroy_widget (w
)
1068 widget_instance
* instance
= get_widget_instance (w
, True
);
1072 widget_info
*info
= instance
->info
;
1073 /* instance has already been removed from the list; free it */
1074 destroy_one_instance (instance
);
1075 /* if there are no instances left, free the info too */
1076 if (!info
->instances
)
1077 lw_destroy_all_widgets (info
->id
);
1082 lw_destroy_all_widgets (id
)
1085 widget_info
* info
= get_widget_info (id
, True
);
1086 widget_instance
* instance
;
1087 widget_instance
* next
;
1091 for (instance
= info
->instances
; instance
; )
1093 next
= instance
->next
;
1094 destroy_one_instance (instance
);
1097 free_widget_info (info
);
1102 lw_destroy_everything ()
1104 while (all_widget_info
)
1105 lw_destroy_all_widgets (all_widget_info
->id
);
1109 lw_destroy_all_pop_ups ()
1113 widget_instance
* instance
;
1115 for (info
= all_widget_info
; info
; info
= next
)
1118 instance
= info
->instances
;
1119 if (instance
&& instance
->pop_up_p
)
1120 lw_destroy_all_widgets (info
->id
);
1125 extern Widget
first_child (/* Widget */); /* garbage */
1129 lw_raise_all_pop_up_widgets ()
1132 widget_instance
* instance
;
1133 Widget result
= NULL
;
1135 for (info
= all_widget_info
; info
; info
= info
->next
)
1136 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1137 if (instance
->pop_up_p
)
1139 Widget widget
= instance
->widget
;
1142 if (XtIsManaged (widget
)
1144 /* What a complete load of crap!!!!
1145 When a dialogShell is on the screen, it is not managed!
1147 || (lw_motif_widget_p (instance
->widget
) &&
1148 XtIsManaged (first_child (widget
)))
1154 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1163 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1165 lw_pop_all_widgets (id
, up
)
1170 widget_info
* info
= get_widget_info (id
, False
);
1171 widget_instance
* instance
;
1174 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1175 if (instance
->pop_up_p
&& instance
->widget
)
1177 #if defined (USE_LUCID)
1178 if (lw_lucid_widget_p (instance
->widget
))
1180 XtRealizeWidget (instance
->widget
);
1181 xlw_pop_instance (instance
, up
);
1184 #if defined (USE_MOTIF)
1185 if (lw_motif_widget_p (instance
->widget
))
1187 XtRealizeWidget (instance
->widget
);
1188 xm_pop_instance (instance
, up
);
1191 #if defined (USE_XAW)
1192 if (lw_xaw_widget_p (instance
->widget
))
1194 XtRealizeWidget (XtParent (instance
->widget
));
1195 XtRealizeWidget (instance
->widget
);
1196 xaw_pop_instance (instance
, up
);
1203 lw_pop_up_all_widgets (id
)
1206 lw_pop_all_widgets (id
, True
);
1210 lw_pop_down_all_widgets (id
)
1213 lw_pop_all_widgets (id
, False
);
1217 lw_popup_menu (widget
, event
)
1221 #if defined (USE_LUCID)
1222 if (lw_lucid_widget_p (widget
))
1223 xlw_popup_menu (widget
, event
);
1225 #if defined (USE_MOTIF)
1226 if (lw_motif_widget_p (widget
))
1227 xm_popup_menu (widget
, event
);
1229 #if defined (USE_XAW)
1230 if (lw_xaw_widget_p (widget
))
1231 xaw_popup_menu (widget
, event
);
1235 \f/* get the values back */
1237 get_one_value (instance
, val
)
1238 widget_instance
* instance
;
1241 Widget widget
= name_to_widget (instance
, val
->name
);
1245 #if defined (USE_LUCID)
1246 if (lw_lucid_widget_p (instance
->widget
))
1247 xlw_update_one_value (instance
, widget
, val
);
1249 #if defined (USE_MOTIF)
1250 if (lw_motif_widget_p (instance
->widget
))
1251 xm_update_one_value (instance
, widget
, val
);
1253 #if defined (USE_XAW)
1254 if (lw_xaw_widget_p (instance
->widget
))
1255 xaw_update_one_value (instance
, widget
, val
);
1264 lw_get_some_values (id
, val_out
)
1266 widget_value
* val_out
;
1268 widget_info
* info
= get_widget_info (id
, False
);
1269 widget_instance
* instance
;
1271 Boolean result
= False
;
1276 instance
= info
->instances
;
1280 for (val
= val_out
; val
; val
= val
->next
)
1281 if (get_one_value (instance
, val
))
1288 lw_get_all_values (id
)
1291 widget_info
* info
= get_widget_info (id
, False
);
1292 widget_value
* val
= info
->val
;
1293 if (lw_get_some_values (id
, val
))
1299 /* internal function used by the library dependent implementation to get the
1300 widget_value for a given widget in an instance */
1302 lw_get_widget_value_for_widget (instance
, w
)
1303 widget_instance
* instance
;
1306 char* name
= XtName (w
);
1308 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1309 if (!strcmp (cur
->name
, name
))
1314 \f/* update other instances value when one thing changed */
1316 /* To forbid recursive calls */
1317 static Boolean lwlib_updating
;
1319 /* This function can be used as a an XtCallback for the widgets that get
1320 modified to update other instances of the widgets. Closure should be the
1323 lw_internal_update_other_instances (widget
, closure
, call_data
)
1326 XtPointer call_data
;
1328 widget_instance
* instance
= (widget_instance
*)closure
;
1329 char* name
= XtName (widget
);
1331 widget_instance
* cur
;
1334 /* Avoid possibly infinite recursion. */
1338 /* protect against the widget being destroyed */
1339 if (XtWidgetBeingDestroyedP (widget
))
1342 /* Return immediately if there are no other instances */
1343 info
= instance
->info
;
1344 if (!info
->instances
->next
)
1347 lwlib_updating
= True
;
1349 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1351 if (val
&& get_one_value (instance
, val
))
1352 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1353 if (cur
!= instance
)
1354 set_one_value (cur
, val
, True
);
1356 lwlib_updating
= False
;
1363 lw_get_widget_id (w
)
1366 widget_instance
* instance
= get_widget_instance (w
, False
);
1368 return instance
? instance
->info
->id
: 0;
1371 \f/* set the keyboard focus */
1373 lw_set_keyboard_focus (parent
, w
)
1377 #if defined (USE_MOTIF)
1378 xm_set_keyboard_focus (parent
, w
);
1380 XtSetKeyboardFocus (parent
, w
);
1387 show_one_widget_busy (Widget w
, Boolean flag
)
1389 show_one_widget_busy (w
, flag
)
1394 Pixel foreground
= 0;
1395 Pixel background
= 1;
1396 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1397 if (!widget_to_invert
)
1398 widget_to_invert
= w
;
1400 XtVaGetValues (widget_to_invert
,
1401 XtNforeground
, &foreground
,
1402 XtNbackground
, &background
,
1404 XtVaSetValues (widget_to_invert
,
1405 XtNforeground
, background
,
1406 XtNbackground
, foreground
,
1412 lw_show_busy (Widget w
, Boolean busy
)
1414 lw_show_busy (w
, busy
)
1419 widget_instance
* instance
= get_widget_instance (w
, False
);
1421 widget_instance
* next
;
1425 info
= instance
->info
;
1426 if (info
->busy
!= busy
)
1428 for (next
= info
->instances
; next
; next
= next
->next
)
1430 show_one_widget_busy (next
->widget
, busy
);
1436 /* This hack exists because Lucid/Athena need to execute the strange
1437 function below to support geometry management. */
1440 lw_refigure_widget (Widget w
, Boolean doit
)
1442 lw_refigure_widget (w
, doit
)
1447 #if defined (USE_XAW)
1448 XawPanedSetRefigureMode (w
, doit
);
1450 #if defined (USE_MOTIF)
1454 XtUnmanageChild (w
);
1458 /* Toolkit independent way of determining if an event window is in the
1461 lw_window_is_in_menubar (win
, menubar_widget
)
1463 Widget menubar_widget
;
1465 return menubar_widget
1466 #if defined (USE_LUCID)
1467 && XtWindow (menubar_widget
) == win
;
1469 #if defined (USE_MOTIF)
1470 && ((XtWindow (menubar_widget
) == win
)
1471 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1472 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1473 == menubar_widget
)));
1477 /* Motif hack to set the main window areas. */
1479 lw_set_main_areas (parent
, menubar
, work_area
)
1484 #if defined (USE_MOTIF)
1485 xm_set_main_areas (parent
, menubar
, work_area
);
1489 /* Manage resizing for Motif. This disables resizing when the menubar
1490 is about to be modified. */
1493 lw_allow_resizing (Widget w
, Boolean flag
)
1495 lw_allow_resizing (w
, flag
)
1500 #if defined (USE_MOTIF)
1501 xm_manage_resizing (w
, flag
);
1506 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1507 set to an appropriate enumerator of type enum menu_separator.
1508 MOTIF_P non-zero means map separator types not supported by Motif
1509 to similar ones that are supported. */
1512 lw_separator_p (label
, type
, motif_p
)
1514 enum menu_separator
*type
;
1517 int separator_p
= 0;
1519 if (strlen (label
) >= 3
1520 && bcmp (label
, "--:", 3) == 0)
1522 static struct separator_table
1525 enum menu_separator type
;
1529 {"space", SEPARATOR_NO_LINE
},
1530 {"noLine", SEPARATOR_NO_LINE
},
1531 {"singleLine", SEPARATOR_SINGLE_LINE
},
1532 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1533 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1534 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1535 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1536 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1537 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1538 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1539 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1540 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1541 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1542 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1549 for (i
= 0; separator_names
[i
].name
; ++i
)
1550 if (strcmp (label
, separator_names
[i
].name
) == 0)
1553 *type
= separator_names
[i
].type
;
1555 /* If separator type is not supported under Motif,
1556 use a similar one. */
1557 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1562 else if (strlen (label
) > 3
1563 && bcmp (label
, "--", 2) == 0
1566 /* Alternative, more Emacs-style names. */
1567 static struct separator_table
1570 enum menu_separator type
;
1574 {"space", SEPARATOR_NO_LINE
},
1575 {"no-line", SEPARATOR_NO_LINE
},
1576 {"single-line", SEPARATOR_SINGLE_LINE
},
1577 {"double-line", SEPARATOR_DOUBLE_LINE
},
1578 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1579 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1580 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1581 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1582 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1583 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1584 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1585 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1586 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1587 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1594 for (i
= 0; separator_names
[i
].name
; ++i
)
1595 if (strcmp (label
, separator_names
[i
].name
) == 0)
1598 *type
= separator_names
[i
].type
;
1600 /* If separator type is not supported under Motif,
1601 use a similar one. */
1602 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1609 /* Old-style separator, maybe. It's a separator if it contains
1611 while (*label
== '-')
1613 separator_p
= *label
== 0;
1614 *type
= SEPARATOR_SHADOW_ETCHED_IN
;
1620 /* arch-tag: 3d730f36-a441-4a71-9971-48ef3b5a4d9f
1621 (do not change this comment) */