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. */
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 char *lwlib_toolkit_type
= "motif";
70 char *lwlib_toolkit_type
= "lucid";
73 static widget_value
*merge_widget_value
P_ ((widget_value
*,
76 static void instantiate_widget_instance
P_ ((widget_instance
*));
77 static int my_strcasecmp
P_ ((char *, char *));
78 static void safe_free_str
P_ ((char *));
79 static void free_widget_value_tree
P_ ((widget_value
*));
80 static widget_value
*copy_widget_value_tree
P_ ((widget_value
*,
82 static widget_info
*allocate_widget_info
P_ ((char *, char *, LWLIB_ID
,
84 lw_callback
, lw_callback
,
85 lw_callback
, lw_callback
));
86 static void free_widget_info
P_ ((widget_info
*));
87 static void mark_widget_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
88 static widget_instance
*allocate_widget_instance
P_ ((widget_info
*,
90 static void free_widget_instance
P_ ((widget_instance
*));
91 static widget_info
*get_widget_info
P_ ((LWLIB_ID
, Boolean
));
92 static widget_instance
*get_widget_instance
P_ ((Widget
, Boolean
));
93 static widget_instance
*find_instance
P_ ((LWLIB_ID
, Widget
, Boolean
));
94 static Boolean safe_strcmp
P_ ((char *, char *));
95 static Widget name_to_widget
P_ ((widget_instance
*, char *));
96 static void set_one_value
P_ ((widget_instance
*, widget_value
*, Boolean
));
97 static void update_one_widget_instance
P_ ((widget_instance
*, Boolean
));
98 static void update_all_widget_values
P_ ((widget_info
*, Boolean
));
99 static void initialize_widget_instance
P_ ((widget_instance
*));
100 static widget_creation_function find_in_table
P_ ((char *, widget_creation_entry
*));
101 static Boolean dialog_spec_p
P_ ((char *));
102 static void destroy_one_instance
P_ ((widget_instance
*));
103 static void lw_pop_all_widgets
P_ ((LWLIB_ID
, Boolean
));
104 static Boolean get_one_value
P_ ((widget_instance
*, widget_value
*));
105 static void show_one_widget_busy
P_ ((Widget
, Boolean
));
108 lwlib_memset (address
, value
, length
)
115 for (i
= 0; i
< length
; i
++)
120 lwlib_bcopy (from
, to
, length
)
127 for (i
= 0; i
< length
; i
++)
130 \f/* utility functions for widget_instance and widget_info */
137 result
= (char *) malloc (strlen (s
) + 1);
144 /* Like strcmp but ignore differences in case. */
147 my_strcasecmp (s1
, s2
)
159 return (c1
> c2
? 1 : -1);
172 static widget_value
*widget_value_free_list
= 0;
173 static int malloc_cpt
= 0;
176 malloc_widget_value ()
179 if (widget_value_free_list
)
181 wv
= widget_value_free_list
;
182 widget_value_free_list
= wv
->free_list
;
187 wv
= (widget_value
*) malloc (sizeof (widget_value
));
190 lwlib_memset ((void*) wv
, 0, sizeof (widget_value
));
194 /* this is analogous to free(). It frees only what was allocated
195 by malloc_widget_value(), and no substructures.
198 free_widget_value (wv
)
206 /* When the number of already allocated cells is too big,
213 wv
->free_list
= widget_value_free_list
;
214 widget_value_free_list
= wv
;
219 free_widget_value_tree (wv
)
229 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
231 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
233 XtFree (wv
->toolkit_data
);
234 wv
->toolkit_data
= (void *) 0xDEADBEEF;
237 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
239 free_widget_value_tree (wv
->contents
);
240 wv
->contents
= (widget_value
*) 0xDEADBEEF;
244 free_widget_value_tree (wv
->next
);
245 wv
->next
= (widget_value
*) 0xDEADBEEF;
247 free_widget_value (wv
);
250 static widget_value
*
251 copy_widget_value_tree (val
, change
)
259 if (val
== (widget_value
*) 1)
262 copy
= malloc_widget_value ();
263 copy
->name
= safe_strdup (val
->name
);
264 copy
->value
= safe_strdup (val
->value
);
265 copy
->key
= safe_strdup (val
->key
);
266 copy
->help
= val
->help
;
267 copy
->enabled
= val
->enabled
;
268 copy
->button_type
= val
->button_type
;
269 copy
->selected
= val
->selected
;
270 copy
->edited
= False
;
271 copy
->change
= change
;
272 copy
->this_one_change
= change
;
273 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
274 copy
->call_data
= val
->call_data
;
275 copy
->next
= copy_widget_value_tree (val
->next
, change
);
276 copy
->toolkit_data
= NULL
;
277 copy
->free_toolkit_data
= False
;
282 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
283 selection_cb
, post_activate_cb
, highlight_cb
)
288 lw_callback pre_activate_cb
;
289 lw_callback selection_cb
;
290 lw_callback post_activate_cb
;
291 lw_callback highlight_cb
;
293 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
294 info
->type
= safe_strdup (type
);
295 info
->name
= safe_strdup (name
);
297 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
299 info
->pre_activate_cb
= pre_activate_cb
;
300 info
->selection_cb
= selection_cb
;
301 info
->post_activate_cb
= post_activate_cb
;
302 info
->highlight_cb
= highlight_cb
;
303 info
->instances
= NULL
;
305 info
->next
= all_widget_info
;
306 all_widget_info
= info
;
312 free_widget_info (info
)
315 safe_free_str (info
->type
);
316 safe_free_str (info
->name
);
317 free_widget_value_tree (info
->val
);
318 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
323 mark_widget_destroyed (widget
, closure
, call_data
)
328 widget_instance
* instance
= (widget_instance
*)closure
;
330 /* be very conservative */
331 if (instance
->widget
== widget
)
332 instance
->widget
= NULL
;
335 /* The messy #ifdef PROTOTYPES here and elsewhere are prompted by a
336 flood of warnings about argument promotion from proprietary ISO C
337 compilers. (etags still only makes one entry for each function.) */
338 static widget_instance
*
340 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
342 allocate_widget_instance (info
, parent
, pop_up_p
)
348 widget_instance
* instance
=
349 (widget_instance
*)malloc (sizeof (widget_instance
));
350 bzero (instance
, sizeof *instance
);
351 instance
->parent
= parent
;
352 instance
->pop_up_p
= pop_up_p
;
353 instance
->info
= info
;
354 instance
->next
= info
->instances
;
355 info
->instances
= instance
;
357 instantiate_widget_instance (instance
);
359 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
360 mark_widget_destroyed
, (XtPointer
)instance
);
365 free_widget_instance (instance
)
366 widget_instance
* instance
;
368 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
374 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
376 get_widget_info (id
, remove_p
)
383 for (prev
= NULL
, info
= all_widget_info
;
385 prev
= info
, info
= info
->next
)
391 prev
->next
= info
->next
;
393 all_widget_info
= info
->next
;
400 /* Internal function used by the library dependent implementation to get the
401 widget_value for a given widget in an instance */
403 lw_get_widget_info (id
)
406 return get_widget_info (id
, 0);
409 static widget_instance
*
411 get_widget_instance (Widget widget
, Boolean remove_p
)
413 get_widget_instance (widget
, remove_p
)
419 widget_instance
* instance
;
420 widget_instance
* prev
;
421 for (info
= all_widget_info
; info
; info
= info
->next
)
422 for (prev
= NULL
, instance
= info
->instances
;
424 prev
= instance
, instance
= instance
->next
)
425 if (instance
->widget
== widget
)
430 prev
->next
= instance
->next
;
432 info
->instances
= instance
->next
;
436 return (widget_instance
*) 0;
439 /* Value is a pointer to the widget_instance corresponding to
440 WIDGET, or null if WIDGET is not a lwlib widget. */
443 lw_get_widget_instance (widget
)
446 return get_widget_instance (widget
, False
);
449 static widget_instance
*
451 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
453 find_instance (id
, parent
, pop_up_p
)
459 widget_info
* info
= get_widget_info (id
, False
);
460 widget_instance
* instance
;
463 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
464 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
471 /* utility function for widget_value */
477 if (!!s1
^ !!s2
) return True
;
478 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
483 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
484 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
486 (oc == NO_CHANGE ? "none" : \
487 (oc == INVISIBLE_CHANGE ? "invisible" : \
488 (oc == VISIBLE_CHANGE ? "visible" : \
489 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
491 (nc == NO_CHANGE ? "none" : \
492 (nc == INVISIBLE_CHANGE ? "invisible" : \
493 (nc == VISIBLE_CHANGE ? "visible" : \
494 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
497 # define EXPLAIN(name, oc, nc, desc, a1, a2)
501 static widget_value
*
502 merge_widget_value (val1
, val2
, level
, change_p
)
508 change_type change
, this_one_change
;
509 widget_value
* merged_next
;
510 widget_value
* merged_contents
;
517 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
525 free_widget_value_tree (val1
);
531 if (safe_strcmp (val1
->name
, val2
->name
))
533 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
534 val1
->name
, val2
->name
);
535 change
= max (change
, STRUCTURAL_CHANGE
);
536 safe_free_str (val1
->name
);
537 val1
->name
= safe_strdup (val2
->name
);
539 if (safe_strcmp (val1
->value
, val2
->value
))
541 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
542 val1
->value
, val2
->value
);
543 change
= max (change
, VISIBLE_CHANGE
);
544 safe_free_str (val1
->value
);
545 val1
->value
= safe_strdup (val2
->value
);
547 if (safe_strcmp (val1
->key
, val2
->key
))
549 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
550 val1
->key
, val2
->key
);
551 change
= max (change
, VISIBLE_CHANGE
);
552 safe_free_str (val1
->key
);
553 val1
->key
= safe_strdup (val2
->key
);
555 if (! EQ (val1
->help
, val2
->help
))
557 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
558 val1
->help
, val2
->help
);
559 change
= max (change
, VISIBLE_CHANGE
);
560 val1
->help
= val2
->help
;
562 if (val1
->enabled
!= val2
->enabled
)
564 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
565 val1
->enabled
, val2
->enabled
);
566 change
= max (change
, VISIBLE_CHANGE
);
567 val1
->enabled
= val2
->enabled
;
569 if (val1
->button_type
!= val2
->button_type
)
571 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
572 val1
->button_type
, val2
->button_type
);
573 change
= max (change
, VISIBLE_CHANGE
);
574 val1
->button_type
= val2
->button_type
;
576 if (val1
->selected
!= val2
->selected
)
578 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
579 val1
->selected
, val2
->selected
);
580 change
= max (change
, VISIBLE_CHANGE
);
581 val1
->selected
= val2
->selected
;
583 if (val1
->call_data
!= val2
->call_data
)
585 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
586 val1
->call_data
, val2
->call_data
);
587 change
= max (change
, INVISIBLE_CHANGE
);
588 val1
->call_data
= val2
->call_data
;
594 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
597 if (val1
->contents
&& !merged_contents
)
599 /* This used to say INVISIBLE_CHANGE,
600 but it is visible and vitally important when
601 the contents of the menu bar itself are entirely deleted.
603 But maybe it doesn't matter. This fails to fix the bug. */
604 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
606 change
= max (change
, STRUCTURAL_CHANGE
);
608 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
610 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
612 change
= max (change
, INVISIBLE_CHANGE
);
613 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
615 change
= max (merged_contents
->change
, change
);
620 val1
->contents
= merged_contents
;
623 this_one_change
= change
;
625 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
627 if (val1
->next
&& !merged_next
)
629 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
631 change
= max (change
, STRUCTURAL_CHANGE
);
633 else if (merged_next
)
635 if (merged_next
->change
)
636 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
638 change
= max (change
, merged_next
->change
);
641 val1
->next
= merged_next
;
643 val1
->this_one_change
= this_one_change
;
644 val1
->change
= change
;
646 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
649 if (val1
->free_toolkit_data
)
650 XtFree (val1
->toolkit_data
);
651 val1
->toolkit_data
= NULL
;
658 /* modifying the widgets */
660 name_to_widget (instance
, name
)
661 widget_instance
* instance
;
664 Widget widget
= NULL
;
666 if (!instance
->widget
)
669 if (!strcmp (XtName (instance
->widget
), name
))
670 widget
= instance
->widget
;
673 int length
= strlen (name
) + 2;
674 char* real_name
= (char *) xmalloc (length
);
676 strcpy (real_name
+ 1, name
);
678 widget
= XtNameToWidget (instance
->widget
, real_name
);
687 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
689 set_one_value (instance
, val
, deep_p
)
690 widget_instance
* instance
;
695 Widget widget
= name_to_widget (instance
, val
->name
);
699 #if defined (USE_LUCID)
700 if (lw_lucid_widget_p (instance
->widget
))
701 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
703 #if defined (USE_MOTIF)
704 if (lw_motif_widget_p (instance
->widget
))
705 xm_update_one_widget (instance
, widget
, val
, deep_p
);
707 #if defined (USE_XAW)
708 if (lw_xaw_widget_p (instance
->widget
))
709 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
716 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
718 update_one_widget_instance (instance
, deep_p
)
719 widget_instance
* instance
;
725 if (!instance
->widget
)
726 /* the widget was destroyed */
729 for (val
= instance
->info
->val
; val
; val
= val
->next
)
730 if (val
->change
!= NO_CHANGE
)
731 set_one_value (instance
, val
, deep_p
);
736 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
738 update_all_widget_values (info
, deep_p
)
743 widget_instance
* instance
;
746 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
747 update_one_widget_instance (instance
, deep_p
);
749 for (val
= info
->val
; val
; val
= val
->next
)
750 val
->change
= NO_CHANGE
;
755 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
757 lw_modify_all_widgets (id
, val
, deep_p
)
763 widget_info
* info
= get_widget_info (id
, False
);
764 widget_value
* new_val
;
765 widget_value
* next_new_val
;
775 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
777 next_new_val
= new_val
->next
;
778 new_val
->next
= NULL
;
780 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
781 if (!strcmp (cur
->name
, new_val
->name
))
786 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
789 prev
->next
= cur
? cur
: next
;
791 info
->val
= cur
? cur
: next
;
798 /* Could not find it, add it */
800 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
802 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
805 new_val
->next
= next_new_val
;
808 update_all_widget_values (info
, deep_p
);
813 /* creating the widgets */
816 initialize_widget_instance (instance
)
817 widget_instance
* instance
;
821 for (val
= instance
->info
->val
; val
; val
= val
->next
)
822 val
->change
= STRUCTURAL_CHANGE
;
824 update_one_widget_instance (instance
, True
);
826 for (val
= instance
->info
->val
; val
; val
= val
->next
)
827 val
->change
= NO_CHANGE
;
831 static widget_creation_function
832 find_in_table (type
, table
)
834 widget_creation_entry
* table
;
836 widget_creation_entry
* cur
;
837 for (cur
= table
; cur
->type
; cur
++)
838 if (!my_strcasecmp (type
, cur
->type
))
839 return cur
->function
;
847 /* return True if name matches [EILPQeilpq][1-9][Bb] or
848 [EILPQeilpq][1-9][Bb][Rr][1-9] */
854 case 'E': case 'I': case 'L': case 'P': case 'Q':
855 case 'e': case 'i': case 'l': case 'p': case 'q':
856 if (name
[1] >= '0' && name
[1] <= '9')
858 if (name
[2] != 'B' && name
[2] != 'b')
862 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
864 if ((name
[3] == 'R' || name
[3] == 'r')
865 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
878 instantiate_widget_instance (instance
)
879 widget_instance
* instance
;
881 widget_creation_function function
= NULL
;
883 #if defined (USE_LUCID)
885 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
887 #if defined(USE_MOTIF)
889 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
891 #if defined (USE_XAW)
893 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
898 if (dialog_spec_p (instance
->info
->type
))
900 #if defined (USE_LUCID)
903 #if defined(USE_MOTIF)
905 function
= xm_create_dialog
;
907 #if defined (USE_XAW)
909 function
= xaw_create_dialog
;
916 printf ("No creation function for widget type %s\n",
917 instance
->info
->type
);
921 instance
->widget
= (*function
) (instance
);
923 if (!instance
->widget
)
926 /* XtRealizeWidget (instance->widget);*/
930 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
931 selection_cb
, post_activate_cb
, highlight_cb
)
936 lw_callback pre_activate_cb
;
937 lw_callback selection_cb
;
938 lw_callback post_activate_cb
;
939 lw_callback highlight_cb
;
941 if (!get_widget_info (id
, False
))
942 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
943 post_activate_cb
, highlight_cb
);
948 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
950 lw_get_widget (id
, parent
, pop_up_p
)
956 widget_instance
* instance
;
958 instance
= find_instance (id
, parent
, pop_up_p
);
959 return instance
? instance
->widget
: NULL
;
964 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
966 lw_make_widget (id
, parent
, pop_up_p
)
972 widget_instance
* instance
;
975 instance
= find_instance (id
, parent
, pop_up_p
);
978 info
= get_widget_info (id
, False
);
981 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
982 initialize_widget_instance (instance
);
984 if (!instance
->widget
)
986 return instance
->widget
;
991 lw_create_widget (char* type
, char* name
, LWLIB_ID id
, widget_value
* val
,
992 Widget parent
, Boolean pop_up_p
,
993 lw_callback pre_activate_cb
, lw_callback selection_cb
,
994 lw_callback post_activate_cb
, lw_callback highlight_cb
)
996 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
997 selection_cb
, post_activate_cb
, highlight_cb
)
1004 lw_callback pre_activate_cb
;
1005 lw_callback selection_cb
;
1006 lw_callback post_activate_cb
;
1007 lw_callback highlight_cb
;
1010 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
1011 post_activate_cb
, highlight_cb
);
1012 return lw_make_widget (id
, parent
, pop_up_p
);
1016 /* destroying the widgets */
1018 destroy_one_instance (instance
)
1019 widget_instance
* instance
;
1021 /* Remove the destroy callback on the widget; that callback will try to
1022 dereference the instance object (to set its widget slot to 0, since the
1023 widget is dead.) Since the instance is now dead, we don't have to worry
1024 about the fact that its widget is dead too.
1026 This happens in the Phase2Destroy of the widget, so this callback would
1027 not have been run until arbitrarily long after the instance was freed.
1029 if (instance
->widget
)
1030 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1031 mark_widget_destroyed
, (XtPointer
)instance
);
1033 if (instance
->widget
)
1035 /* The else are pretty tricky here, including the empty statement
1036 at the end because it would be very bad to destroy a widget
1038 #if defined (USE_LUCID)
1039 if (lw_lucid_widget_p (instance
->widget
))
1040 xlw_destroy_instance (instance
);
1043 #if defined (USE_MOTIF)
1044 if (lw_motif_widget_p (instance
->widget
))
1045 xm_destroy_instance (instance
);
1048 #if defined (USE_XAW)
1049 if (lw_xaw_widget_p (instance
->widget
))
1050 xaw_destroy_instance (instance
);
1053 /* do not remove the empty statement */
1057 free_widget_instance (instance
);
1061 lw_destroy_widget (w
)
1064 widget_instance
* instance
= get_widget_instance (w
, True
);
1068 widget_info
*info
= instance
->info
;
1069 /* instance has already been removed from the list; free it */
1070 destroy_one_instance (instance
);
1071 /* if there are no instances left, free the info too */
1072 if (!info
->instances
)
1073 lw_destroy_all_widgets (info
->id
);
1078 lw_destroy_all_widgets (id
)
1081 widget_info
* info
= get_widget_info (id
, True
);
1082 widget_instance
* instance
;
1083 widget_instance
* next
;
1087 for (instance
= info
->instances
; instance
; )
1089 next
= instance
->next
;
1090 destroy_one_instance (instance
);
1093 free_widget_info (info
);
1098 lw_destroy_everything ()
1100 while (all_widget_info
)
1101 lw_destroy_all_widgets (all_widget_info
->id
);
1105 lw_destroy_all_pop_ups ()
1109 widget_instance
* instance
;
1111 for (info
= all_widget_info
; info
; info
= next
)
1114 instance
= info
->instances
;
1115 if (instance
&& instance
->pop_up_p
)
1116 lw_destroy_all_widgets (info
->id
);
1121 extern Widget
first_child (/* Widget */); /* garbage */
1125 lw_raise_all_pop_up_widgets ()
1128 widget_instance
* instance
;
1129 Widget result
= NULL
;
1131 for (info
= all_widget_info
; info
; info
= info
->next
)
1132 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1133 if (instance
->pop_up_p
)
1135 Widget widget
= instance
->widget
;
1138 if (XtIsManaged (widget
)
1140 /* What a complete load of crap!!!!
1141 When a dialogShell is on the screen, it is not managed!
1143 || (lw_motif_widget_p (instance
->widget
) &&
1144 XtIsManaged (first_child (widget
)))
1150 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1159 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1161 lw_pop_all_widgets (id
, up
)
1166 widget_info
* info
= get_widget_info (id
, False
);
1167 widget_instance
* instance
;
1170 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1171 if (instance
->pop_up_p
&& instance
->widget
)
1173 #if defined (USE_LUCID)
1174 if (lw_lucid_widget_p (instance
->widget
))
1176 XtRealizeWidget (instance
->widget
);
1177 xlw_pop_instance (instance
, up
);
1180 #if defined (USE_MOTIF)
1181 if (lw_motif_widget_p (instance
->widget
))
1183 XtRealizeWidget (instance
->widget
);
1184 xm_pop_instance (instance
, up
);
1187 #if defined (USE_XAW)
1188 if (lw_xaw_widget_p (instance
->widget
))
1190 XtRealizeWidget (XtParent (instance
->widget
));
1191 XtRealizeWidget (instance
->widget
);
1192 xaw_pop_instance (instance
, up
);
1199 lw_pop_up_all_widgets (id
)
1202 lw_pop_all_widgets (id
, True
);
1206 lw_pop_down_all_widgets (id
)
1209 lw_pop_all_widgets (id
, False
);
1213 lw_popup_menu (widget
, event
)
1217 #if defined (USE_LUCID)
1218 if (lw_lucid_widget_p (widget
))
1219 xlw_popup_menu (widget
, event
);
1221 #if defined (USE_MOTIF)
1222 if (lw_motif_widget_p (widget
))
1223 xm_popup_menu (widget
, event
);
1225 #if defined (USE_XAW)
1226 if (lw_xaw_widget_p (widget
))
1227 xaw_popup_menu (widget
, event
);
1231 \f/* get the values back */
1233 get_one_value (instance
, val
)
1234 widget_instance
* instance
;
1237 Widget widget
= name_to_widget (instance
, val
->name
);
1241 #if defined (USE_LUCID)
1242 if (lw_lucid_widget_p (instance
->widget
))
1243 xlw_update_one_value (instance
, widget
, val
);
1245 #if defined (USE_MOTIF)
1246 if (lw_motif_widget_p (instance
->widget
))
1247 xm_update_one_value (instance
, widget
, val
);
1249 #if defined (USE_XAW)
1250 if (lw_xaw_widget_p (instance
->widget
))
1251 xaw_update_one_value (instance
, widget
, val
);
1260 lw_get_some_values (id
, val_out
)
1262 widget_value
* val_out
;
1264 widget_info
* info
= get_widget_info (id
, False
);
1265 widget_instance
* instance
;
1267 Boolean result
= False
;
1272 instance
= info
->instances
;
1276 for (val
= val_out
; val
; val
= val
->next
)
1277 if (get_one_value (instance
, val
))
1284 lw_get_all_values (id
)
1287 widget_info
* info
= get_widget_info (id
, False
);
1288 widget_value
* val
= info
->val
;
1289 if (lw_get_some_values (id
, val
))
1295 /* internal function used by the library dependent implementation to get the
1296 widget_value for a given widget in an instance */
1298 lw_get_widget_value_for_widget (instance
, w
)
1299 widget_instance
* instance
;
1302 char* name
= XtName (w
);
1304 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1305 if (!strcmp (cur
->name
, name
))
1310 \f/* update other instances value when one thing changed */
1312 /* To forbid recursive calls */
1313 static Boolean lwlib_updating
;
1315 /* This function can be used as a an XtCallback for the widgets that get
1316 modified to update other instances of the widgets. Closure should be the
1319 lw_internal_update_other_instances (widget
, closure
, call_data
)
1322 XtPointer call_data
;
1324 widget_instance
* instance
= (widget_instance
*)closure
;
1325 char* name
= XtName (widget
);
1327 widget_instance
* cur
;
1330 /* Avoid possibly infinite recursion. */
1334 /* protect against the widget being destroyed */
1335 if (XtWidgetBeingDestroyedP (widget
))
1338 /* Return immediately if there are no other instances */
1339 info
= instance
->info
;
1340 if (!info
->instances
->next
)
1343 lwlib_updating
= True
;
1345 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1347 if (val
&& get_one_value (instance
, val
))
1348 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1349 if (cur
!= instance
)
1350 set_one_value (cur
, val
, True
);
1352 lwlib_updating
= False
;
1359 lw_get_widget_id (w
)
1362 widget_instance
* instance
= get_widget_instance (w
, False
);
1364 return instance
? instance
->info
->id
: 0;
1367 \f/* set the keyboard focus */
1369 lw_set_keyboard_focus (parent
, w
)
1373 #if defined (USE_MOTIF)
1374 xm_set_keyboard_focus (parent
, w
);
1376 XtSetKeyboardFocus (parent
, w
);
1383 show_one_widget_busy (Widget w
, Boolean flag
)
1385 show_one_widget_busy (w
, flag
)
1390 Pixel foreground
= 0;
1391 Pixel background
= 1;
1392 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1393 if (!widget_to_invert
)
1394 widget_to_invert
= w
;
1396 XtVaGetValues (widget_to_invert
,
1397 XtNforeground
, &foreground
,
1398 XtNbackground
, &background
,
1400 XtVaSetValues (widget_to_invert
,
1401 XtNforeground
, background
,
1402 XtNbackground
, foreground
,
1408 lw_show_busy (Widget w
, Boolean busy
)
1410 lw_show_busy (w
, busy
)
1415 widget_instance
* instance
= get_widget_instance (w
, False
);
1417 widget_instance
* next
;
1421 info
= instance
->info
;
1422 if (info
->busy
!= busy
)
1424 for (next
= info
->instances
; next
; next
= next
->next
)
1426 show_one_widget_busy (next
->widget
, busy
);
1432 /* This hack exists because Lucid/Athena need to execute the strange
1433 function below to support geometry management. */
1436 lw_refigure_widget (Widget w
, Boolean doit
)
1438 lw_refigure_widget (w
, doit
)
1443 #if defined (USE_XAW)
1444 XawPanedSetRefigureMode (w
, doit
);
1446 #if defined (USE_MOTIF)
1450 XtUnmanageChild (w
);
1454 /* Toolkit independent way of determining if an event window is in the
1457 lw_window_is_in_menubar (win
, menubar_widget
)
1459 Widget menubar_widget
;
1461 return menubar_widget
1462 #if defined (USE_LUCID)
1463 && XtWindow (menubar_widget
) == win
;
1465 #if defined (USE_MOTIF)
1466 && ((XtWindow (menubar_widget
) == win
)
1467 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1468 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1469 == menubar_widget
)));
1473 /* Motif hack to set the main window areas. */
1475 lw_set_main_areas (parent
, menubar
, work_area
)
1480 #if defined (USE_MOTIF)
1481 xm_set_main_areas (parent
, menubar
, work_area
);
1485 /* Manage resizing for Motif. This disables resizing when the menubar
1486 is about to be modified. */
1489 lw_allow_resizing (Widget w
, Boolean flag
)
1491 lw_allow_resizing (w
, flag
)
1496 #if defined (USE_MOTIF)
1497 xm_manage_resizing (w
, flag
);
1502 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1503 set to an appropriate enumerator of type enum menu_separator.
1504 MOTIF_P non-zero means map separator types not supported by Motif
1505 to similar ones that are supported. */
1508 lw_separator_p (label
, type
, motif_p
)
1510 enum menu_separator
*type
;
1513 int separator_p
= 0;
1515 if (strlen (label
) >= 3
1516 && bcmp (label
, "--:", 3) == 0)
1518 static struct separator_table
1521 enum menu_separator type
;
1525 {"space", SEPARATOR_NO_LINE
},
1526 {"noLine", SEPARATOR_NO_LINE
},
1527 {"singleLine", SEPARATOR_SINGLE_LINE
},
1528 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1529 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1530 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1531 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1532 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1533 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1534 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1535 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1536 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1537 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1538 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1545 for (i
= 0; separator_names
[i
].name
; ++i
)
1546 if (strcmp (label
, separator_names
[i
].name
) == 0)
1549 *type
= separator_names
[i
].type
;
1551 /* If separator type is not supported under Motif,
1552 use a similar one. */
1553 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1558 else if (strlen (label
) > 3
1559 && bcmp (label
, "--", 2) == 0
1562 /* Alternative, more Emacs-style names. */
1563 static struct separator_table
1566 enum menu_separator type
;
1570 {"space", SEPARATOR_NO_LINE
},
1571 {"no-line", SEPARATOR_NO_LINE
},
1572 {"single-line", SEPARATOR_SINGLE_LINE
},
1573 {"double-line", SEPARATOR_DOUBLE_LINE
},
1574 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1575 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1576 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1577 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1578 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1579 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1580 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1581 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1582 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1583 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1590 for (i
= 0; separator_names
[i
].name
; ++i
)
1591 if (strcmp (label
, separator_names
[i
].name
) == 0)
1594 *type
= separator_names
[i
].type
;
1596 /* If separator type is not supported under Motif,
1597 use a similar one. */
1598 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1605 /* Old-style separator, maybe. It's a separator if it contains
1607 while (*label
== '-')
1609 separator_p
= *label
== 0;
1610 *type
= SEPARATOR_SHADOW_ETCHED_IN
;
1616 /* arch-tag: 3d730f36-a441-4a71-9971-48ef3b5a4d9f
1617 (do not change this comment) */