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, 2009, 2010 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. */
28 #include "../src/lisp.h"
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 char *lwlib_toolkit_type
= "motif";
71 char *lwlib_toolkit_type
= "lucid";
74 static widget_value
*merge_widget_value
P_ ((widget_value
*,
77 static void instantiate_widget_instance
P_ ((widget_instance
*));
78 static int my_strcasecmp
P_ ((char *, char *));
79 static void safe_free_str
P_ ((char *));
80 static void free_widget_value_tree
P_ ((widget_value
*));
81 static widget_value
*copy_widget_value_tree
P_ ((widget_value
*,
83 static widget_info
*allocate_widget_info
P_ ((char *, char *, LWLIB_ID
,
85 lw_callback
, lw_callback
,
86 lw_callback
, lw_callback
));
87 static void free_widget_info
P_ ((widget_info
*));
88 static void mark_widget_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
89 static widget_instance
*allocate_widget_instance
P_ ((widget_info
*,
91 static void free_widget_instance
P_ ((widget_instance
*));
92 static widget_info
*get_widget_info
P_ ((LWLIB_ID
, Boolean
));
93 static widget_instance
*get_widget_instance
P_ ((Widget
, Boolean
));
94 static widget_instance
*find_instance
P_ ((LWLIB_ID
, Widget
, Boolean
));
95 static Boolean safe_strcmp
P_ ((char *, char *));
96 static Widget name_to_widget
P_ ((widget_instance
*, char *));
97 static void set_one_value
P_ ((widget_instance
*, widget_value
*, Boolean
));
98 static void update_one_widget_instance
P_ ((widget_instance
*, Boolean
));
99 static void update_all_widget_values
P_ ((widget_info
*, Boolean
));
100 static void initialize_widget_instance
P_ ((widget_instance
*));
101 static widget_creation_function find_in_table
P_ ((char *, widget_creation_entry
*));
102 static Boolean dialog_spec_p
P_ ((char *));
103 static void destroy_one_instance
P_ ((widget_instance
*));
104 static void lw_pop_all_widgets
P_ ((LWLIB_ID
, Boolean
));
105 static Boolean get_one_value
P_ ((widget_instance
*, widget_value
*));
106 static void show_one_widget_busy
P_ ((Widget
, Boolean
));
109 lwlib_memset (address
, value
, length
)
116 for (i
= 0; i
< length
; i
++)
121 lwlib_bcopy (from
, to
, length
)
128 for (i
= 0; i
< length
; i
++)
131 \f/* utility functions for widget_instance and widget_info */
138 result
= (char *) malloc (strlen (s
) + 1);
145 /* Like strcmp but ignore differences in case. */
148 my_strcasecmp (s1
, s2
)
160 return (c1
> c2
? 1 : -1);
173 static widget_value
*widget_value_free_list
= 0;
174 static int malloc_cpt
= 0;
177 malloc_widget_value ()
180 if (widget_value_free_list
)
182 wv
= widget_value_free_list
;
183 widget_value_free_list
= wv
->free_list
;
188 wv
= (widget_value
*) malloc (sizeof (widget_value
));
191 lwlib_memset ((void*) wv
, 0, sizeof (widget_value
));
195 /* this is analogous to free(). It frees only what was allocated
196 by malloc_widget_value(), and no substructures.
199 free_widget_value (wv
)
207 /* When the number of already allocated cells is too big,
214 wv
->free_list
= widget_value_free_list
;
215 widget_value_free_list
= wv
;
220 free_widget_value_tree (wv
)
230 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
232 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
234 XtFree (wv
->toolkit_data
);
235 wv
->toolkit_data
= (void *) 0xDEADBEEF;
238 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
240 free_widget_value_tree (wv
->contents
);
241 wv
->contents
= (widget_value
*) 0xDEADBEEF;
245 free_widget_value_tree (wv
->next
);
246 wv
->next
= (widget_value
*) 0xDEADBEEF;
248 free_widget_value (wv
);
251 static widget_value
*
252 copy_widget_value_tree (val
, change
)
260 if (val
== (widget_value
*) 1)
263 copy
= malloc_widget_value ();
264 copy
->name
= safe_strdup (val
->name
);
265 copy
->value
= safe_strdup (val
->value
);
266 copy
->key
= safe_strdup (val
->key
);
267 copy
->help
= val
->help
;
268 copy
->enabled
= val
->enabled
;
269 copy
->button_type
= val
->button_type
;
270 copy
->selected
= val
->selected
;
271 copy
->edited
= False
;
272 copy
->change
= change
;
273 copy
->this_one_change
= change
;
274 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
275 copy
->call_data
= val
->call_data
;
276 copy
->next
= copy_widget_value_tree (val
->next
, change
);
277 copy
->toolkit_data
= NULL
;
278 copy
->free_toolkit_data
= False
;
283 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
284 selection_cb
, post_activate_cb
, highlight_cb
)
289 lw_callback pre_activate_cb
;
290 lw_callback selection_cb
;
291 lw_callback post_activate_cb
;
292 lw_callback highlight_cb
;
294 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
295 info
->type
= safe_strdup (type
);
296 info
->name
= safe_strdup (name
);
298 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
300 info
->pre_activate_cb
= pre_activate_cb
;
301 info
->selection_cb
= selection_cb
;
302 info
->post_activate_cb
= post_activate_cb
;
303 info
->highlight_cb
= highlight_cb
;
304 info
->instances
= NULL
;
306 info
->next
= all_widget_info
;
307 all_widget_info
= info
;
313 free_widget_info (info
)
316 safe_free_str (info
->type
);
317 safe_free_str (info
->name
);
318 free_widget_value_tree (info
->val
);
319 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
324 mark_widget_destroyed (widget
, closure
, call_data
)
329 widget_instance
* instance
= (widget_instance
*)closure
;
331 /* be very conservative */
332 if (instance
->widget
== widget
)
333 instance
->widget
= NULL
;
336 /* The messy #ifdef PROTOTYPES here and elsewhere are prompted by a
337 flood of warnings about argument promotion from proprietary ISO C
338 compilers. (etags still only makes one entry for each function.) */
339 static widget_instance
*
341 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
343 allocate_widget_instance (info
, parent
, pop_up_p
)
349 widget_instance
* instance
=
350 (widget_instance
*)malloc (sizeof (widget_instance
));
351 bzero (instance
, sizeof *instance
);
352 instance
->parent
= parent
;
353 instance
->pop_up_p
= pop_up_p
;
354 instance
->info
= info
;
355 instance
->next
= info
->instances
;
356 info
->instances
= instance
;
358 instantiate_widget_instance (instance
);
360 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
361 mark_widget_destroyed
, (XtPointer
)instance
);
366 free_widget_instance (instance
)
367 widget_instance
* instance
;
369 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
375 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
377 get_widget_info (id
, remove_p
)
384 for (prev
= NULL
, info
= all_widget_info
;
386 prev
= info
, info
= info
->next
)
392 prev
->next
= info
->next
;
394 all_widget_info
= info
->next
;
401 /* Internal function used by the library dependent implementation to get the
402 widget_value for a given widget in an instance */
404 lw_get_widget_info (id
)
407 return get_widget_info (id
, 0);
410 static widget_instance
*
412 get_widget_instance (Widget widget
, Boolean remove_p
)
414 get_widget_instance (widget
, remove_p
)
420 widget_instance
* instance
;
421 widget_instance
* prev
;
422 for (info
= all_widget_info
; info
; info
= info
->next
)
423 for (prev
= NULL
, instance
= info
->instances
;
425 prev
= instance
, instance
= instance
->next
)
426 if (instance
->widget
== widget
)
431 prev
->next
= instance
->next
;
433 info
->instances
= instance
->next
;
437 return (widget_instance
*) 0;
440 /* Value is a pointer to the widget_instance corresponding to
441 WIDGET, or null if WIDGET is not a lwlib widget. */
444 lw_get_widget_instance (widget
)
447 return get_widget_instance (widget
, False
);
450 static widget_instance
*
452 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
454 find_instance (id
, parent
, pop_up_p
)
460 widget_info
* info
= get_widget_info (id
, False
);
461 widget_instance
* instance
;
464 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
465 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
472 /* utility function for widget_value */
478 if (!!s1
^ !!s2
) return True
;
479 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
484 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
485 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
487 (oc == NO_CHANGE ? "none" : \
488 (oc == INVISIBLE_CHANGE ? "invisible" : \
489 (oc == VISIBLE_CHANGE ? "visible" : \
490 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
492 (nc == NO_CHANGE ? "none" : \
493 (nc == INVISIBLE_CHANGE ? "invisible" : \
494 (nc == VISIBLE_CHANGE ? "visible" : \
495 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
498 # define EXPLAIN(name, oc, nc, desc, a1, a2)
502 static widget_value
*
503 merge_widget_value (val1
, val2
, level
, change_p
)
509 change_type change
, this_one_change
;
510 widget_value
* merged_next
;
511 widget_value
* merged_contents
;
518 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
526 free_widget_value_tree (val1
);
532 if (safe_strcmp (val1
->name
, val2
->name
))
534 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
535 val1
->name
, val2
->name
);
536 change
= max (change
, STRUCTURAL_CHANGE
);
537 safe_free_str (val1
->name
);
538 val1
->name
= safe_strdup (val2
->name
);
540 if (safe_strcmp (val1
->value
, val2
->value
))
542 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
543 val1
->value
, val2
->value
);
544 change
= max (change
, VISIBLE_CHANGE
);
545 safe_free_str (val1
->value
);
546 val1
->value
= safe_strdup (val2
->value
);
548 if (safe_strcmp (val1
->key
, val2
->key
))
550 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
551 val1
->key
, val2
->key
);
552 change
= max (change
, VISIBLE_CHANGE
);
553 safe_free_str (val1
->key
);
554 val1
->key
= safe_strdup (val2
->key
);
556 if (! EQ (val1
->help
, val2
->help
))
558 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
559 val1
->help
, val2
->help
);
560 change
= max (change
, VISIBLE_CHANGE
);
561 val1
->help
= val2
->help
;
563 if (val1
->enabled
!= val2
->enabled
)
565 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
566 val1
->enabled
, val2
->enabled
);
567 change
= max (change
, VISIBLE_CHANGE
);
568 val1
->enabled
= val2
->enabled
;
570 if (val1
->button_type
!= val2
->button_type
)
572 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
573 val1
->button_type
, val2
->button_type
);
574 change
= max (change
, VISIBLE_CHANGE
);
575 val1
->button_type
= val2
->button_type
;
577 if (val1
->selected
!= val2
->selected
)
579 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
580 val1
->selected
, val2
->selected
);
581 change
= max (change
, VISIBLE_CHANGE
);
582 val1
->selected
= val2
->selected
;
584 if (val1
->call_data
!= val2
->call_data
)
586 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
587 val1
->call_data
, val2
->call_data
);
588 change
= max (change
, INVISIBLE_CHANGE
);
589 val1
->call_data
= val2
->call_data
;
595 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
598 if (val1
->contents
&& !merged_contents
)
600 /* This used to say INVISIBLE_CHANGE,
601 but it is visible and vitally important when
602 the contents of the menu bar itself are entirely deleted.
604 But maybe it doesn't matter. This fails to fix the bug. */
605 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
607 change
= max (change
, STRUCTURAL_CHANGE
);
609 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
611 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
613 change
= max (change
, INVISIBLE_CHANGE
);
614 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
616 change
= max (merged_contents
->change
, change
);
621 val1
->contents
= merged_contents
;
624 this_one_change
= change
;
626 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
628 if (val1
->next
&& !merged_next
)
630 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
632 change
= max (change
, STRUCTURAL_CHANGE
);
634 else if (merged_next
)
636 if (merged_next
->change
)
637 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
639 change
= max (change
, merged_next
->change
);
642 val1
->next
= merged_next
;
644 val1
->this_one_change
= this_one_change
;
645 val1
->change
= change
;
647 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
650 if (val1
->free_toolkit_data
)
651 XtFree (val1
->toolkit_data
);
652 val1
->toolkit_data
= NULL
;
659 /* modifying the widgets */
661 name_to_widget (instance
, name
)
662 widget_instance
* instance
;
665 Widget widget
= NULL
;
667 if (!instance
->widget
)
670 if (!strcmp (XtName (instance
->widget
), name
))
671 widget
= instance
->widget
;
674 int length
= strlen (name
) + 2;
675 char* real_name
= (char *) xmalloc (length
);
677 strcpy (real_name
+ 1, name
);
679 widget
= XtNameToWidget (instance
->widget
, real_name
);
688 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
690 set_one_value (instance
, val
, deep_p
)
691 widget_instance
* instance
;
696 Widget widget
= name_to_widget (instance
, val
->name
);
700 #if defined (USE_LUCID)
701 if (lw_lucid_widget_p (instance
->widget
))
702 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
704 #if defined (USE_MOTIF)
705 if (lw_motif_widget_p (instance
->widget
))
706 xm_update_one_widget (instance
, widget
, val
, deep_p
);
708 #if defined (USE_XAW)
709 if (lw_xaw_widget_p (instance
->widget
))
710 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
717 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
719 update_one_widget_instance (instance
, deep_p
)
720 widget_instance
* instance
;
726 if (!instance
->widget
)
727 /* the widget was destroyed */
730 for (val
= instance
->info
->val
; val
; val
= val
->next
)
731 if (val
->change
!= NO_CHANGE
)
732 set_one_value (instance
, val
, deep_p
);
737 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
739 update_all_widget_values (info
, deep_p
)
744 widget_instance
* instance
;
747 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
748 update_one_widget_instance (instance
, deep_p
);
750 for (val
= info
->val
; val
; val
= val
->next
)
751 val
->change
= NO_CHANGE
;
756 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
758 lw_modify_all_widgets (id
, val
, deep_p
)
764 widget_info
* info
= get_widget_info (id
, False
);
765 widget_value
* new_val
;
766 widget_value
* next_new_val
;
776 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
778 next_new_val
= new_val
->next
;
779 new_val
->next
= NULL
;
781 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
782 if (!strcmp (cur
->name
, new_val
->name
))
787 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
790 prev
->next
= cur
? cur
: next
;
792 info
->val
= cur
? cur
: next
;
799 /* Could not find it, add it */
801 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
803 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
806 new_val
->next
= next_new_val
;
809 update_all_widget_values (info
, deep_p
);
814 /* creating the widgets */
817 initialize_widget_instance (instance
)
818 widget_instance
* instance
;
822 for (val
= instance
->info
->val
; val
; val
= val
->next
)
823 val
->change
= STRUCTURAL_CHANGE
;
825 update_one_widget_instance (instance
, True
);
827 for (val
= instance
->info
->val
; val
; val
= val
->next
)
828 val
->change
= NO_CHANGE
;
832 static widget_creation_function
833 find_in_table (type
, table
)
835 widget_creation_entry
* table
;
837 widget_creation_entry
* cur
;
838 for (cur
= table
; cur
->type
; cur
++)
839 if (!my_strcasecmp (type
, cur
->type
))
840 return cur
->function
;
848 /* return True if name matches [EILPQeilpq][1-9][Bb] or
849 [EILPQeilpq][1-9][Bb][Rr][1-9] */
855 case 'E': case 'I': case 'L': case 'P': case 'Q':
856 case 'e': case 'i': case 'l': case 'p': case 'q':
857 if (name
[1] >= '0' && name
[1] <= '9')
859 if (name
[2] != 'B' && name
[2] != 'b')
863 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
865 if ((name
[3] == 'R' || name
[3] == 'r')
866 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
879 instantiate_widget_instance (instance
)
880 widget_instance
* instance
;
882 widget_creation_function function
= NULL
;
884 #if defined (USE_LUCID)
886 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
888 #if defined(USE_MOTIF)
890 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
892 #if defined (USE_XAW)
894 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
899 if (dialog_spec_p (instance
->info
->type
))
901 #if defined (USE_LUCID)
904 #if defined(USE_MOTIF)
906 function
= xm_create_dialog
;
908 #if defined (USE_XAW)
910 function
= xaw_create_dialog
;
917 printf ("No creation function for widget type %s\n",
918 instance
->info
->type
);
922 instance
->widget
= (*function
) (instance
);
924 if (!instance
->widget
)
927 /* XtRealizeWidget (instance->widget);*/
931 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
932 selection_cb
, post_activate_cb
, highlight_cb
)
937 lw_callback pre_activate_cb
;
938 lw_callback selection_cb
;
939 lw_callback post_activate_cb
;
940 lw_callback highlight_cb
;
942 if (!get_widget_info (id
, False
))
943 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
944 post_activate_cb
, highlight_cb
);
949 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
951 lw_get_widget (id
, parent
, pop_up_p
)
957 widget_instance
* instance
;
959 instance
= find_instance (id
, parent
, pop_up_p
);
960 return instance
? instance
->widget
: NULL
;
965 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
967 lw_make_widget (id
, parent
, pop_up_p
)
973 widget_instance
* instance
;
976 instance
= find_instance (id
, parent
, pop_up_p
);
979 info
= get_widget_info (id
, False
);
982 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
983 initialize_widget_instance (instance
);
985 if (!instance
->widget
)
987 return instance
->widget
;
992 lw_create_widget (char* type
, char* name
, LWLIB_ID id
, widget_value
* val
,
993 Widget parent
, Boolean pop_up_p
,
994 lw_callback pre_activate_cb
, lw_callback selection_cb
,
995 lw_callback post_activate_cb
, lw_callback highlight_cb
)
997 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
998 selection_cb
, post_activate_cb
, highlight_cb
)
1005 lw_callback pre_activate_cb
;
1006 lw_callback selection_cb
;
1007 lw_callback post_activate_cb
;
1008 lw_callback highlight_cb
;
1011 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
1012 post_activate_cb
, highlight_cb
);
1013 return lw_make_widget (id
, parent
, pop_up_p
);
1017 /* destroying the widgets */
1019 destroy_one_instance (instance
)
1020 widget_instance
* instance
;
1022 /* Remove the destroy callback on the widget; that callback will try to
1023 dereference the instance object (to set its widget slot to 0, since the
1024 widget is dead.) Since the instance is now dead, we don't have to worry
1025 about the fact that its widget is dead too.
1027 This happens in the Phase2Destroy of the widget, so this callback would
1028 not have been run until arbitrarily long after the instance was freed.
1030 if (instance
->widget
)
1031 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1032 mark_widget_destroyed
, (XtPointer
)instance
);
1034 if (instance
->widget
)
1036 /* The else are pretty tricky here, including the empty statement
1037 at the end because it would be very bad to destroy a widget
1039 #if defined (USE_LUCID)
1040 if (lw_lucid_widget_p (instance
->widget
))
1041 xlw_destroy_instance (instance
);
1044 #if defined (USE_MOTIF)
1045 if (lw_motif_widget_p (instance
->widget
))
1046 xm_destroy_instance (instance
);
1049 #if defined (USE_XAW)
1050 if (lw_xaw_widget_p (instance
->widget
))
1051 xaw_destroy_instance (instance
);
1054 /* do not remove the empty statement */
1058 free_widget_instance (instance
);
1062 lw_destroy_widget (w
)
1065 widget_instance
* instance
= get_widget_instance (w
, True
);
1069 widget_info
*info
= instance
->info
;
1070 /* instance has already been removed from the list; free it */
1071 destroy_one_instance (instance
);
1072 /* if there are no instances left, free the info too */
1073 if (!info
->instances
)
1074 lw_destroy_all_widgets (info
->id
);
1079 lw_destroy_all_widgets (id
)
1082 widget_info
* info
= get_widget_info (id
, True
);
1083 widget_instance
* instance
;
1084 widget_instance
* next
;
1088 for (instance
= info
->instances
; instance
; )
1090 next
= instance
->next
;
1091 destroy_one_instance (instance
);
1094 free_widget_info (info
);
1099 lw_destroy_everything ()
1101 while (all_widget_info
)
1102 lw_destroy_all_widgets (all_widget_info
->id
);
1106 lw_destroy_all_pop_ups ()
1110 widget_instance
* instance
;
1112 for (info
= all_widget_info
; info
; info
= next
)
1115 instance
= info
->instances
;
1116 if (instance
&& instance
->pop_up_p
)
1117 lw_destroy_all_widgets (info
->id
);
1122 extern Widget
first_child (/* Widget */); /* garbage */
1126 lw_raise_all_pop_up_widgets ()
1129 widget_instance
* instance
;
1130 Widget result
= NULL
;
1132 for (info
= all_widget_info
; info
; info
= info
->next
)
1133 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1134 if (instance
->pop_up_p
)
1136 Widget widget
= instance
->widget
;
1139 if (XtIsManaged (widget
)
1141 /* What a complete load of crap!!!!
1142 When a dialogShell is on the screen, it is not managed!
1144 || (lw_motif_widget_p (instance
->widget
) &&
1145 XtIsManaged (first_child (widget
)))
1151 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1160 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1162 lw_pop_all_widgets (id
, up
)
1167 widget_info
* info
= get_widget_info (id
, False
);
1168 widget_instance
* instance
;
1171 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1172 if (instance
->pop_up_p
&& instance
->widget
)
1174 #if defined (USE_LUCID)
1175 if (lw_lucid_widget_p (instance
->widget
))
1177 XtRealizeWidget (instance
->widget
);
1178 xlw_pop_instance (instance
, up
);
1181 #if defined (USE_MOTIF)
1182 if (lw_motif_widget_p (instance
->widget
))
1184 XtRealizeWidget (instance
->widget
);
1185 xm_pop_instance (instance
, up
);
1188 #if defined (USE_XAW)
1189 if (lw_xaw_widget_p (instance
->widget
))
1191 XtRealizeWidget (XtParent (instance
->widget
));
1192 XtRealizeWidget (instance
->widget
);
1193 xaw_pop_instance (instance
, up
);
1200 lw_pop_up_all_widgets (id
)
1203 lw_pop_all_widgets (id
, True
);
1207 lw_pop_down_all_widgets (id
)
1210 lw_pop_all_widgets (id
, False
);
1214 lw_popup_menu (widget
, event
)
1218 #if defined (USE_LUCID)
1219 if (lw_lucid_widget_p (widget
))
1220 xlw_popup_menu (widget
, event
);
1222 #if defined (USE_MOTIF)
1223 if (lw_motif_widget_p (widget
))
1224 xm_popup_menu (widget
, event
);
1226 #if defined (USE_XAW)
1227 if (lw_xaw_widget_p (widget
))
1228 xaw_popup_menu (widget
, event
);
1232 \f/* get the values back */
1234 get_one_value (instance
, val
)
1235 widget_instance
* instance
;
1238 Widget widget
= name_to_widget (instance
, val
->name
);
1242 #if defined (USE_LUCID)
1243 if (lw_lucid_widget_p (instance
->widget
))
1244 xlw_update_one_value (instance
, widget
, val
);
1246 #if defined (USE_MOTIF)
1247 if (lw_motif_widget_p (instance
->widget
))
1248 xm_update_one_value (instance
, widget
, val
);
1250 #if defined (USE_XAW)
1251 if (lw_xaw_widget_p (instance
->widget
))
1252 xaw_update_one_value (instance
, widget
, val
);
1261 lw_get_some_values (id
, val_out
)
1263 widget_value
* val_out
;
1265 widget_info
* info
= get_widget_info (id
, False
);
1266 widget_instance
* instance
;
1268 Boolean result
= False
;
1273 instance
= info
->instances
;
1277 for (val
= val_out
; val
; val
= val
->next
)
1278 if (get_one_value (instance
, val
))
1285 lw_get_all_values (id
)
1288 widget_info
* info
= get_widget_info (id
, False
);
1289 widget_value
* val
= info
->val
;
1290 if (lw_get_some_values (id
, val
))
1296 /* internal function used by the library dependent implementation to get the
1297 widget_value for a given widget in an instance */
1299 lw_get_widget_value_for_widget (instance
, w
)
1300 widget_instance
* instance
;
1303 char* name
= XtName (w
);
1305 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1306 if (!strcmp (cur
->name
, name
))
1311 \f/* update other instances value when one thing changed */
1313 /* To forbid recursive calls */
1314 static Boolean lwlib_updating
;
1316 /* This function can be used as a an XtCallback for the widgets that get
1317 modified to update other instances of the widgets. Closure should be the
1320 lw_internal_update_other_instances (widget
, closure
, call_data
)
1323 XtPointer call_data
;
1325 widget_instance
* instance
= (widget_instance
*)closure
;
1326 char* name
= XtName (widget
);
1328 widget_instance
* cur
;
1331 /* Avoid possibly infinite recursion. */
1335 /* protect against the widget being destroyed */
1336 if (XtWidgetBeingDestroyedP (widget
))
1339 /* Return immediately if there are no other instances */
1340 info
= instance
->info
;
1341 if (!info
->instances
->next
)
1344 lwlib_updating
= True
;
1346 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1348 if (val
&& get_one_value (instance
, val
))
1349 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1350 if (cur
!= instance
)
1351 set_one_value (cur
, val
, True
);
1353 lwlib_updating
= False
;
1360 lw_get_widget_id (w
)
1363 widget_instance
* instance
= get_widget_instance (w
, False
);
1365 return instance
? instance
->info
->id
: 0;
1368 \f/* set the keyboard focus */
1370 lw_set_keyboard_focus (parent
, w
)
1374 #if defined (USE_MOTIF)
1375 xm_set_keyboard_focus (parent
, w
);
1377 XtSetKeyboardFocus (parent
, w
);
1384 show_one_widget_busy (Widget w
, Boolean flag
)
1386 show_one_widget_busy (w
, flag
)
1391 Pixel foreground
= 0;
1392 Pixel background
= 1;
1393 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1394 if (!widget_to_invert
)
1395 widget_to_invert
= w
;
1397 XtVaGetValues (widget_to_invert
,
1398 XtNforeground
, &foreground
,
1399 XtNbackground
, &background
,
1401 XtVaSetValues (widget_to_invert
,
1402 XtNforeground
, background
,
1403 XtNbackground
, foreground
,
1409 lw_show_busy (Widget w
, Boolean busy
)
1411 lw_show_busy (w
, busy
)
1416 widget_instance
* instance
= get_widget_instance (w
, False
);
1418 widget_instance
* next
;
1422 info
= instance
->info
;
1423 if (info
->busy
!= busy
)
1425 for (next
= info
->instances
; next
; next
= next
->next
)
1427 show_one_widget_busy (next
->widget
, busy
);
1433 /* This hack exists because Lucid/Athena need to execute the strange
1434 function below to support geometry management. */
1437 lw_refigure_widget (Widget w
, Boolean doit
)
1439 lw_refigure_widget (w
, doit
)
1444 #if defined (USE_XAW)
1445 XawPanedSetRefigureMode (w
, doit
);
1447 #if defined (USE_MOTIF)
1451 XtUnmanageChild (w
);
1455 /* Toolkit independent way of determining if an event window is in the
1458 lw_window_is_in_menubar (win
, menubar_widget
)
1460 Widget menubar_widget
;
1462 return menubar_widget
1463 #if defined (USE_LUCID)
1464 && XtWindow (menubar_widget
) == win
;
1466 #if defined (USE_MOTIF)
1467 && ((XtWindow (menubar_widget
) == win
)
1468 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1469 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1470 == menubar_widget
)));
1474 /* Motif hack to set the main window areas. */
1476 lw_set_main_areas (parent
, menubar
, work_area
)
1481 #if defined (USE_MOTIF)
1482 xm_set_main_areas (parent
, menubar
, work_area
);
1486 /* Manage resizing for Motif. This disables resizing when the menubar
1487 is about to be modified. */
1490 lw_allow_resizing (Widget w
, Boolean flag
)
1492 lw_allow_resizing (w
, flag
)
1497 #if defined (USE_MOTIF)
1498 xm_manage_resizing (w
, flag
);
1503 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1504 set to an appropriate enumerator of type enum menu_separator.
1505 MOTIF_P non-zero means map separator types not supported by Motif
1506 to similar ones that are supported. */
1509 lw_separator_p (label
, type
, motif_p
)
1511 enum menu_separator
*type
;
1514 int separator_p
= 0;
1516 if (strlen (label
) >= 3
1517 && bcmp (label
, "--:", 3) == 0)
1519 static struct separator_table
1522 enum menu_separator type
;
1526 {"space", SEPARATOR_NO_LINE
},
1527 {"noLine", SEPARATOR_NO_LINE
},
1528 {"singleLine", SEPARATOR_SINGLE_LINE
},
1529 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1530 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1531 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1532 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1533 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1534 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1535 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1536 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1537 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1538 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1539 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1546 for (i
= 0; separator_names
[i
].name
; ++i
)
1547 if (strcmp (label
, separator_names
[i
].name
) == 0)
1550 *type
= separator_names
[i
].type
;
1552 /* If separator type is not supported under Motif,
1553 use a similar one. */
1554 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1559 else if (strlen (label
) > 3
1560 && bcmp (label
, "--", 2) == 0
1563 /* Alternative, more Emacs-style names. */
1564 static struct separator_table
1567 enum menu_separator type
;
1571 {"space", SEPARATOR_NO_LINE
},
1572 {"no-line", SEPARATOR_NO_LINE
},
1573 {"single-line", SEPARATOR_SINGLE_LINE
},
1574 {"double-line", SEPARATOR_DOUBLE_LINE
},
1575 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1576 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1577 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1578 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1579 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1580 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1581 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1582 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1583 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1584 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1591 for (i
= 0; separator_names
[i
].name
; ++i
)
1592 if (strcmp (label
, separator_names
[i
].name
) == 0)
1595 *type
= separator_names
[i
].type
;
1597 /* If separator type is not supported under Motif,
1598 use a similar one. */
1599 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1606 /* Old-style separator, maybe. It's a separator if it contains
1608 while (*label
== '-')
1610 separator_p
= *label
== 0;
1611 *type
= SEPARATOR_SHADOW_ETCHED_IN
;
1617 /* arch-tag: 3d730f36-a441-4a71-9971-48ef3b5a4d9f
1618 (do not change this comment) */