1 /* A general interface to the widgets of different toolkits.
2 Copyright (C) 1992, 1993 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
22 #undef __STRICT_BSD__ /* ick */
29 #include "../src/lisp.h"
31 #include <sys/types.h>
34 #include "lwlib-int.h"
35 #include "lwlib-utils.h"
36 #include <X11/StringDefs.h>
38 #if defined (USE_LUCID)
39 #include "lwlib-Xlw.h"
41 #if defined (USE_MOTIF)
43 #else /* not USE_MOTIF */
44 #if defined (USE_LUCID)
46 #endif /* not USE_MOTIF && USE_LUCID */
49 #include <X11/Xaw/Paned.h>
50 #include "lwlib-Xaw.h"
53 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
54 #error At least one of USE_LUCID or USE_MOTIF must be defined.
58 #define max(x, y) ((x) > (y) ? (x) : (y))
61 /* List of all widgets managed by the library. */
63 all_widget_info
= NULL
;
66 char *lwlib_toolkit_type
= "motif";
68 char *lwlib_toolkit_type
= "lucid";
71 static widget_value
*merge_widget_value
P_ ((widget_value
*,
74 static void instantiate_widget_instance
P_ ((widget_instance
*));
75 static int my_strcasecmp
P_ ((char *, char *));
76 static void safe_free_str
P_ ((char *));
77 static void free_widget_value_tree
P_ ((widget_value
*));
78 static widget_value
*copy_widget_value_tree
P_ ((widget_value
*,
80 static widget_info
*allocate_widget_info
P_ ((char *, char *, LWLIB_ID
,
82 lw_callback
, lw_callback
,
83 lw_callback
, lw_callback
));
84 static void free_widget_info
P_ ((widget_info
*));
85 static void mark_widget_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
86 static widget_instance
*allocate_widget_instance
P_ ((widget_info
*,
88 static void free_widget_instance
P_ ((widget_instance
*));
89 static widget_info
*get_widget_info
P_ ((LWLIB_ID
, Boolean
));
90 static widget_instance
*get_widget_instance
P_ ((Widget
, Boolean
));
91 static widget_instance
*find_instance
P_ ((LWLIB_ID
, Widget
, Boolean
));
92 static Boolean safe_strcmp
P_ ((char *, char *));
93 static Widget name_to_widget
P_ ((widget_instance
*, char *));
94 static void set_one_value
P_ ((widget_instance
*, widget_value
*, Boolean
));
95 static void update_one_widget_instance
P_ ((widget_instance
*, Boolean
));
96 static void update_all_widget_values
P_ ((widget_info
*, Boolean
));
97 static void initialize_widget_instance
P_ ((widget_instance
*));
98 static widget_creation_function find_in_table
P_ ((char *, widget_creation_entry
*));
99 static Boolean dialog_spec_p
P_ ((char *));
100 static void destroy_one_instance
P_ ((widget_instance
*));
101 static void lw_pop_all_widgets
P_ ((LWLIB_ID
, Boolean
));
102 static Boolean get_one_value
P_ ((widget_instance
*, widget_value
*));
103 static void show_one_widget_busy
P_ ((Widget
, Boolean
));
106 lwlib_memset (address
, value
, length
)
113 for (i
= 0; i
< length
; i
++)
118 lwlib_bcopy (from
, to
, length
)
125 for (i
= 0; i
< length
; i
++)
128 \f/* utility functions for widget_instance and widget_info */
135 result
= (char *) malloc (strlen (s
) + 1);
142 /* Like strcmp but ignore differences in case. */
145 my_strcasecmp (s1
, s2
)
157 return (c1
> c2
? 1 : -1);
170 static widget_value
*widget_value_free_list
= 0;
171 static int malloc_cpt
= 0;
174 malloc_widget_value ()
177 if (widget_value_free_list
)
179 wv
= widget_value_free_list
;
180 widget_value_free_list
= wv
->free_list
;
185 wv
= (widget_value
*) malloc (sizeof (widget_value
));
188 lwlib_memset ((void*) wv
, 0, sizeof (widget_value
));
192 /* this is analogous to free(). It frees only what was allocated
193 by malloc_widget_value(), and no substructures.
196 free_widget_value (wv
)
204 /* When the number of already allocated cells is too big,
211 wv
->free_list
= widget_value_free_list
;
212 widget_value_free_list
= wv
;
217 free_widget_value_tree (wv
)
223 if (wv
->name
) free (wv
->name
);
224 if (wv
->value
) free (wv
->value
);
225 if (wv
->key
) free (wv
->key
);
227 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
229 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
231 XtFree (wv
->toolkit_data
);
232 wv
->toolkit_data
= (void *) 0xDEADBEEF;
235 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
237 free_widget_value_tree (wv
->contents
);
238 wv
->contents
= (widget_value
*) 0xDEADBEEF;
242 free_widget_value_tree (wv
->next
);
243 wv
->next
= (widget_value
*) 0xDEADBEEF;
245 free_widget_value (wv
);
248 static widget_value
*
249 copy_widget_value_tree (val
, change
)
257 if (val
== (widget_value
*) 1)
260 copy
= malloc_widget_value ();
261 copy
->name
= safe_strdup (val
->name
);
262 copy
->value
= safe_strdup (val
->value
);
263 copy
->key
= safe_strdup (val
->key
);
264 copy
->help
= val
->help
;
265 copy
->enabled
= val
->enabled
;
266 copy
->button_type
= val
->button_type
;
267 copy
->selected
= val
->selected
;
268 copy
->edited
= False
;
269 copy
->change
= change
;
270 copy
->this_one_change
= change
;
271 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
272 copy
->call_data
= val
->call_data
;
273 copy
->next
= copy_widget_value_tree (val
->next
, change
);
274 copy
->toolkit_data
= NULL
;
275 copy
->free_toolkit_data
= False
;
280 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
281 selection_cb
, post_activate_cb
, highlight_cb
)
286 lw_callback pre_activate_cb
;
287 lw_callback selection_cb
;
288 lw_callback post_activate_cb
;
289 lw_callback highlight_cb
;
291 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
292 info
->type
= safe_strdup (type
);
293 info
->name
= safe_strdup (name
);
295 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
297 info
->pre_activate_cb
= pre_activate_cb
;
298 info
->selection_cb
= selection_cb
;
299 info
->post_activate_cb
= post_activate_cb
;
300 info
->highlight_cb
= highlight_cb
;
301 info
->instances
= NULL
;
303 info
->next
= all_widget_info
;
304 all_widget_info
= info
;
310 free_widget_info (info
)
313 safe_free_str (info
->type
);
314 safe_free_str (info
->name
);
315 free_widget_value_tree (info
->val
);
316 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
321 mark_widget_destroyed (widget
, closure
, call_data
)
326 widget_instance
* instance
= (widget_instance
*)closure
;
328 /* be very conservative */
329 if (instance
->widget
== widget
)
330 instance
->widget
= NULL
;
333 /* The messy #ifdef PROTOTYPES here and elsewhere are prompted by a
334 flood of warnings about argument promotion from proprietary ISO C
335 compilers. (etags still only makes one entry for each function.) */
336 static widget_instance
*
338 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
340 allocate_widget_instance (info
, parent
, pop_up_p
)
346 widget_instance
* instance
=
347 (widget_instance
*)malloc (sizeof (widget_instance
));
348 bzero (instance
, sizeof *instance
);
349 instance
->parent
= parent
;
350 instance
->pop_up_p
= pop_up_p
;
351 instance
->info
= info
;
352 instance
->next
= info
->instances
;
353 info
->instances
= instance
;
355 instantiate_widget_instance (instance
);
357 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
358 mark_widget_destroyed
, (XtPointer
)instance
);
363 free_widget_instance (instance
)
364 widget_instance
* instance
;
366 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
372 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
374 get_widget_info (id
, remove_p
)
381 for (prev
= NULL
, info
= all_widget_info
;
383 prev
= info
, info
= info
->next
)
389 prev
->next
= info
->next
;
391 all_widget_info
= info
->next
;
398 /* Internal function used by the library dependent implementation to get the
399 widget_value for a given widget in an instance */
401 lw_get_widget_info (id
)
404 return get_widget_info (id
, 0);
407 static widget_instance
*
409 get_widget_instance (Widget widget
, Boolean remove_p
)
411 get_widget_instance (widget
, remove_p
)
417 widget_instance
* instance
;
418 widget_instance
* prev
;
419 for (info
= all_widget_info
; info
; info
= info
->next
)
420 for (prev
= NULL
, instance
= info
->instances
;
422 prev
= instance
, instance
= instance
->next
)
423 if (instance
->widget
== widget
)
428 prev
->next
= instance
->next
;
430 info
->instances
= instance
->next
;
434 return (widget_instance
*) 0;
437 /* Value is a pointer to the widget_instance corresponding to
438 WIDGET, or null if WIDGET is not a lwlib widget. */
441 lw_get_widget_instance (widget
)
444 return get_widget_instance (widget
, False
);
447 static widget_instance
*
449 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
451 find_instance (id
, parent
, pop_up_p
)
457 widget_info
* info
= get_widget_info (id
, False
);
458 widget_instance
* instance
;
461 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
462 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
469 /* utility function for widget_value */
475 if (!!s1
^ !!s2
) return True
;
476 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
481 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
482 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
484 (oc == NO_CHANGE ? "none" : \
485 (oc == INVISIBLE_CHANGE ? "invisible" : \
486 (oc == VISIBLE_CHANGE ? "visible" : \
487 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
489 (nc == NO_CHANGE ? "none" : \
490 (nc == INVISIBLE_CHANGE ? "invisible" : \
491 (nc == VISIBLE_CHANGE ? "visible" : \
492 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
495 # define EXPLAIN(name, oc, nc, desc, a1, a2)
499 static widget_value
*
500 merge_widget_value (val1
, val2
, level
, change_p
)
506 change_type change
, this_one_change
;
507 widget_value
* merged_next
;
508 widget_value
* merged_contents
;
515 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
523 free_widget_value_tree (val1
);
529 if (safe_strcmp (val1
->name
, val2
->name
))
531 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
532 val1
->name
, val2
->name
);
533 change
= max (change
, STRUCTURAL_CHANGE
);
534 safe_free_str (val1
->name
);
535 val1
->name
= safe_strdup (val2
->name
);
537 if (safe_strcmp (val1
->value
, val2
->value
))
539 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
540 val1
->value
, val2
->value
);
541 change
= max (change
, VISIBLE_CHANGE
);
542 safe_free_str (val1
->value
);
543 val1
->value
= safe_strdup (val2
->value
);
545 if (safe_strcmp (val1
->key
, val2
->key
))
547 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
548 val1
->key
, val2
->key
);
549 change
= max (change
, VISIBLE_CHANGE
);
550 safe_free_str (val1
->key
);
551 val1
->key
= safe_strdup (val2
->key
);
553 if (! EQ (val1
->help
, val2
->help
))
555 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
556 val1
->help
, val2
->help
);
557 change
= max (change
, VISIBLE_CHANGE
);
558 val1
->help
= val2
->help
;
560 if (val1
->enabled
!= val2
->enabled
)
562 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
563 val1
->enabled
, val2
->enabled
);
564 change
= max (change
, VISIBLE_CHANGE
);
565 val1
->enabled
= val2
->enabled
;
567 if (val1
->button_type
!= val2
->button_type
)
569 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
570 val1
->button_type
, val2
->button_type
);
571 change
= max (change
, VISIBLE_CHANGE
);
572 val1
->button_type
= val2
->button_type
;
574 if (val1
->selected
!= val2
->selected
)
576 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
577 val1
->selected
, val2
->selected
);
578 change
= max (change
, VISIBLE_CHANGE
);
579 val1
->selected
= val2
->selected
;
581 if (val1
->call_data
!= val2
->call_data
)
583 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
584 val1
->call_data
, val2
->call_data
);
585 change
= max (change
, INVISIBLE_CHANGE
);
586 val1
->call_data
= val2
->call_data
;
592 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
595 if (val1
->contents
&& !merged_contents
)
597 /* This used to say INVISIBLE_CHANGE,
598 but it is visible and vitally important when
599 the contents of the menu bar itself are entirely deleted.
601 But maybe it doesn't matter. This fails to fix the bug. */
602 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
604 change
= max (change
, STRUCTURAL_CHANGE
);
606 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
608 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
610 change
= max (change
, INVISIBLE_CHANGE
);
611 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
613 change
= max (merged_contents
->change
, change
);
618 val1
->contents
= merged_contents
;
621 this_one_change
= change
;
623 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
625 if (val1
->next
&& !merged_next
)
627 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
629 change
= max (change
, STRUCTURAL_CHANGE
);
631 else if (merged_next
)
633 if (merged_next
->change
)
634 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
636 change
= max (change
, merged_next
->change
);
639 val1
->next
= merged_next
;
641 val1
->this_one_change
= this_one_change
;
642 val1
->change
= change
;
644 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
647 if (val1
->free_toolkit_data
)
648 XtFree (val1
->toolkit_data
);
649 val1
->toolkit_data
= NULL
;
656 /* modifying the widgets */
658 name_to_widget (instance
, name
)
659 widget_instance
* instance
;
662 Widget widget
= NULL
;
664 if (!instance
->widget
)
667 if (!strcmp (XtName (instance
->widget
), name
))
668 widget
= instance
->widget
;
671 int length
= strlen (name
) + 2;
672 char* real_name
= (char *) xmalloc (length
);
674 strcpy (real_name
+ 1, name
);
676 widget
= XtNameToWidget (instance
->widget
, real_name
);
685 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
687 set_one_value (instance
, val
, deep_p
)
688 widget_instance
* instance
;
693 Widget widget
= name_to_widget (instance
, val
->name
);
697 #if defined (USE_LUCID)
698 if (lw_lucid_widget_p (instance
->widget
))
699 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
701 #if defined (USE_MOTIF)
702 if (lw_motif_widget_p (instance
->widget
))
703 xm_update_one_widget (instance
, widget
, val
, deep_p
);
705 #if defined (USE_XAW)
706 if (lw_xaw_widget_p (instance
->widget
))
707 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
714 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
716 update_one_widget_instance (instance
, deep_p
)
717 widget_instance
* instance
;
723 if (!instance
->widget
)
724 /* the widget was destroyed */
727 for (val
= instance
->info
->val
; val
; val
= val
->next
)
728 if (val
->change
!= NO_CHANGE
)
729 set_one_value (instance
, val
, deep_p
);
734 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
736 update_all_widget_values (info
, deep_p
)
741 widget_instance
* instance
;
744 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
745 update_one_widget_instance (instance
, deep_p
);
747 for (val
= info
->val
; val
; val
= val
->next
)
748 val
->change
= NO_CHANGE
;
753 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
755 lw_modify_all_widgets (id
, val
, deep_p
)
761 widget_info
* info
= get_widget_info (id
, False
);
762 widget_value
* new_val
;
763 widget_value
* next_new_val
;
773 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
775 next_new_val
= new_val
->next
;
776 new_val
->next
= NULL
;
778 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
779 if (!strcmp (cur
->name
, new_val
->name
))
784 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
787 prev
->next
= cur
? cur
: next
;
789 info
->val
= cur
? cur
: next
;
796 /* Could not find it, add it */
798 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
800 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
803 new_val
->next
= next_new_val
;
806 update_all_widget_values (info
, deep_p
);
811 /* creating the widgets */
814 initialize_widget_instance (instance
)
815 widget_instance
* instance
;
819 for (val
= instance
->info
->val
; val
; val
= val
->next
)
820 val
->change
= STRUCTURAL_CHANGE
;
822 update_one_widget_instance (instance
, True
);
824 for (val
= instance
->info
->val
; val
; val
= val
->next
)
825 val
->change
= NO_CHANGE
;
829 static widget_creation_function
830 find_in_table (type
, table
)
832 widget_creation_entry
* table
;
834 widget_creation_entry
* cur
;
835 for (cur
= table
; cur
->type
; cur
++)
836 if (!my_strcasecmp (type
, cur
->type
))
837 return cur
->function
;
845 /* return True if name matches [EILPQeilpq][1-9][Bb] or
846 [EILPQeilpq][1-9][Bb][Rr][1-9] */
852 case 'E': case 'I': case 'L': case 'P': case 'Q':
853 case 'e': case 'i': case 'l': case 'p': case 'q':
854 if (name
[1] >= '0' && name
[1] <= '9')
856 if (name
[2] != 'B' && name
[2] != 'b')
860 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
862 if ((name
[3] == 'R' || name
[3] == 'r')
863 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
876 instantiate_widget_instance (instance
)
877 widget_instance
* instance
;
879 widget_creation_function function
= NULL
;
881 #if defined (USE_LUCID)
883 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
885 #if defined(USE_MOTIF)
887 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
889 #if defined (USE_XAW)
891 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
896 if (dialog_spec_p (instance
->info
->type
))
898 #if defined (USE_LUCID)
901 #if defined(USE_MOTIF)
903 function
= xm_create_dialog
;
905 #if defined (USE_XAW)
907 function
= xaw_create_dialog
;
914 printf ("No creation function for widget type %s\n",
915 instance
->info
->type
);
919 instance
->widget
= (*function
) (instance
);
921 if (!instance
->widget
)
924 /* XtRealizeWidget (instance->widget);*/
928 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
929 selection_cb
, post_activate_cb
, highlight_cb
)
934 lw_callback pre_activate_cb
;
935 lw_callback selection_cb
;
936 lw_callback post_activate_cb
;
937 lw_callback highlight_cb
;
939 if (!get_widget_info (id
, False
))
940 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
941 post_activate_cb
, highlight_cb
);
946 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
948 lw_get_widget (id
, parent
, pop_up_p
)
954 widget_instance
* instance
;
956 instance
= find_instance (id
, parent
, pop_up_p
);
957 return instance
? instance
->widget
: NULL
;
962 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
964 lw_make_widget (id
, parent
, pop_up_p
)
970 widget_instance
* instance
;
973 instance
= find_instance (id
, parent
, pop_up_p
);
976 info
= get_widget_info (id
, False
);
979 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
980 initialize_widget_instance (instance
);
982 if (!instance
->widget
)
984 return instance
->widget
;
989 lw_create_widget (char* type
, char* name
, LWLIB_ID id
, widget_value
* val
,
990 Widget parent
, Boolean pop_up_p
,
991 lw_callback pre_activate_cb
, lw_callback selection_cb
,
992 lw_callback post_activate_cb
, lw_callback highlight_cb
)
994 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
995 selection_cb
, post_activate_cb
, highlight_cb
)
1002 lw_callback pre_activate_cb
;
1003 lw_callback selection_cb
;
1004 lw_callback post_activate_cb
;
1005 lw_callback highlight_cb
;
1008 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
1009 post_activate_cb
, highlight_cb
);
1010 return lw_make_widget (id
, parent
, pop_up_p
);
1014 /* destroying the widgets */
1016 destroy_one_instance (instance
)
1017 widget_instance
* instance
;
1019 /* Remove the destroy callback on the widget; that callback will try to
1020 dereference the instance object (to set its widget slot to 0, since the
1021 widget is dead.) Since the instance is now dead, we don't have to worry
1022 about the fact that its widget is dead too.
1024 This happens in the Phase2Destroy of the widget, so this callback would
1025 not have been run until arbitrarily long after the instance was freed.
1027 if (instance
->widget
)
1028 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1029 mark_widget_destroyed
, (XtPointer
)instance
);
1031 if (instance
->widget
)
1033 /* The else are pretty tricky here, including the empty statement
1034 at the end because it would be very bad to destroy a widget
1036 #if defined (USE_LUCID)
1037 if (lw_lucid_widget_p (instance
->widget
))
1038 xlw_destroy_instance (instance
);
1041 #if defined (USE_MOTIF)
1042 if (lw_motif_widget_p (instance
->widget
))
1043 xm_destroy_instance (instance
);
1046 #if defined (USE_XAW)
1047 if (lw_xaw_widget_p (instance
->widget
))
1048 xaw_destroy_instance (instance
);
1051 /* do not remove the empty statement */
1055 free_widget_instance (instance
);
1059 lw_destroy_widget (w
)
1062 widget_instance
* instance
= get_widget_instance (w
, True
);
1066 widget_info
*info
= instance
->info
;
1067 /* instance has already been removed from the list; free it */
1068 destroy_one_instance (instance
);
1069 /* if there are no instances left, free the info too */
1070 if (!info
->instances
)
1071 lw_destroy_all_widgets (info
->id
);
1076 lw_destroy_all_widgets (id
)
1079 widget_info
* info
= get_widget_info (id
, True
);
1080 widget_instance
* instance
;
1081 widget_instance
* next
;
1085 for (instance
= info
->instances
; instance
; )
1087 next
= instance
->next
;
1088 destroy_one_instance (instance
);
1091 free_widget_info (info
);
1096 lw_destroy_everything ()
1098 while (all_widget_info
)
1099 lw_destroy_all_widgets (all_widget_info
->id
);
1103 lw_destroy_all_pop_ups ()
1107 widget_instance
* instance
;
1109 for (info
= all_widget_info
; info
; info
= next
)
1112 instance
= info
->instances
;
1113 if (instance
&& instance
->pop_up_p
)
1114 lw_destroy_all_widgets (info
->id
);
1119 extern Widget
first_child (/* Widget */); /* garbage */
1123 lw_raise_all_pop_up_widgets ()
1126 widget_instance
* instance
;
1127 Widget result
= NULL
;
1129 for (info
= all_widget_info
; info
; info
= info
->next
)
1130 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1131 if (instance
->pop_up_p
)
1133 Widget widget
= instance
->widget
;
1136 if (XtIsManaged (widget
)
1138 /* What a complete load of crap!!!!
1139 When a dialogShell is on the screen, it is not managed!
1141 || (lw_motif_widget_p (instance
->widget
) &&
1142 XtIsManaged (first_child (widget
)))
1148 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1157 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1159 lw_pop_all_widgets (id
, up
)
1164 widget_info
* info
= get_widget_info (id
, False
);
1165 widget_instance
* instance
;
1168 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1169 if (instance
->pop_up_p
&& instance
->widget
)
1171 #if defined (USE_LUCID)
1172 if (lw_lucid_widget_p (instance
->widget
))
1174 XtRealizeWidget (instance
->widget
);
1175 xlw_pop_instance (instance
, up
);
1178 #if defined (USE_MOTIF)
1179 if (lw_motif_widget_p (instance
->widget
))
1181 XtRealizeWidget (instance
->widget
);
1182 xm_pop_instance (instance
, up
);
1185 #if defined (USE_XAW)
1186 if (lw_xaw_widget_p (instance
->widget
))
1188 XtRealizeWidget (XtParent (instance
->widget
));
1189 XtRealizeWidget (instance
->widget
);
1190 xaw_pop_instance (instance
, up
);
1197 lw_pop_up_all_widgets (id
)
1200 lw_pop_all_widgets (id
, True
);
1204 lw_pop_down_all_widgets (id
)
1207 lw_pop_all_widgets (id
, False
);
1211 lw_popup_menu (widget
, event
)
1215 #if defined (USE_LUCID)
1216 if (lw_lucid_widget_p (widget
))
1217 xlw_popup_menu (widget
, event
);
1219 #if defined (USE_MOTIF)
1220 if (lw_motif_widget_p (widget
))
1221 xm_popup_menu (widget
, event
);
1223 #if defined (USE_XAW)
1224 if (lw_xaw_widget_p (widget
))
1225 xaw_popup_menu (widget
, event
);
1229 \f/* get the values back */
1231 get_one_value (instance
, val
)
1232 widget_instance
* instance
;
1235 Widget widget
= name_to_widget (instance
, val
->name
);
1239 #if defined (USE_LUCID)
1240 if (lw_lucid_widget_p (instance
->widget
))
1241 xlw_update_one_value (instance
, widget
, val
);
1243 #if defined (USE_MOTIF)
1244 if (lw_motif_widget_p (instance
->widget
))
1245 xm_update_one_value (instance
, widget
, val
);
1247 #if defined (USE_XAW)
1248 if (lw_xaw_widget_p (instance
->widget
))
1249 xaw_update_one_value (instance
, widget
, val
);
1258 lw_get_some_values (id
, val_out
)
1260 widget_value
* val_out
;
1262 widget_info
* info
= get_widget_info (id
, False
);
1263 widget_instance
* instance
;
1265 Boolean result
= False
;
1270 instance
= info
->instances
;
1274 for (val
= val_out
; val
; val
= val
->next
)
1275 if (get_one_value (instance
, val
))
1282 lw_get_all_values (id
)
1285 widget_info
* info
= get_widget_info (id
, False
);
1286 widget_value
* val
= info
->val
;
1287 if (lw_get_some_values (id
, val
))
1293 /* internal function used by the library dependent implementation to get the
1294 widget_value for a given widget in an instance */
1296 lw_get_widget_value_for_widget (instance
, w
)
1297 widget_instance
* instance
;
1300 char* name
= XtName (w
);
1302 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1303 if (!strcmp (cur
->name
, name
))
1308 \f/* update other instances value when one thing changed */
1310 /* To forbid recursive calls */
1311 static Boolean lwlib_updating
;
1313 /* This function can be used as a an XtCallback for the widgets that get
1314 modified to update other instances of the widgets. Closure should be the
1317 lw_internal_update_other_instances (widget
, closure
, call_data
)
1320 XtPointer call_data
;
1322 widget_instance
* instance
= (widget_instance
*)closure
;
1323 char* name
= XtName (widget
);
1325 widget_instance
* cur
;
1328 /* Avoid possibly infinite recursion. */
1332 /* protect against the widget being destroyed */
1333 if (XtWidgetBeingDestroyedP (widget
))
1336 /* Return immediately if there are no other instances */
1337 info
= instance
->info
;
1338 if (!info
->instances
->next
)
1341 lwlib_updating
= True
;
1343 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1345 if (val
&& get_one_value (instance
, val
))
1346 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1347 if (cur
!= instance
)
1348 set_one_value (cur
, val
, True
);
1350 lwlib_updating
= False
;
1357 lw_get_widget_id (w
)
1360 widget_instance
* instance
= get_widget_instance (w
, False
);
1362 return instance
? instance
->info
->id
: 0;
1365 \f/* set the keyboard focus */
1367 lw_set_keyboard_focus (parent
, w
)
1371 #if defined (USE_MOTIF)
1372 xm_set_keyboard_focus (parent
, w
);
1374 XtSetKeyboardFocus (parent
, w
);
1381 show_one_widget_busy (Widget w
, Boolean flag
)
1383 show_one_widget_busy (w
, flag
)
1388 Pixel foreground
= 0;
1389 Pixel background
= 1;
1390 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1391 if (!widget_to_invert
)
1392 widget_to_invert
= w
;
1394 XtVaGetValues (widget_to_invert
,
1395 XtNforeground
, &foreground
,
1396 XtNbackground
, &background
,
1398 XtVaSetValues (widget_to_invert
,
1399 XtNforeground
, background
,
1400 XtNbackground
, foreground
,
1406 lw_show_busy (Widget w
, Boolean busy
)
1408 lw_show_busy (w
, busy
)
1413 widget_instance
* instance
= get_widget_instance (w
, False
);
1415 widget_instance
* next
;
1419 info
= instance
->info
;
1420 if (info
->busy
!= busy
)
1422 for (next
= info
->instances
; next
; next
= next
->next
)
1424 show_one_widget_busy (next
->widget
, busy
);
1430 /* This hack exists because Lucid/Athena need to execute the strange
1431 function below to support geometry management. */
1434 lw_refigure_widget (Widget w
, Boolean doit
)
1436 lw_refigure_widget (w
, doit
)
1441 #if defined (USE_XAW)
1442 XawPanedSetRefigureMode (w
, doit
);
1444 #if defined (USE_MOTIF)
1448 XtUnmanageChild (w
);
1452 /* Toolkit independent way of determining if an event window is in the
1455 lw_window_is_in_menubar (win
, menubar_widget
)
1457 Widget menubar_widget
;
1459 return menubar_widget
1460 #if defined (USE_LUCID)
1461 && XtWindow (menubar_widget
) == win
;
1463 #if defined (USE_MOTIF)
1464 && ((XtWindow (menubar_widget
) == win
)
1465 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1466 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1467 == menubar_widget
)));
1471 /* Motif hack to set the main window areas. */
1473 lw_set_main_areas (parent
, menubar
, work_area
)
1478 #if defined (USE_MOTIF)
1479 xm_set_main_areas (parent
, menubar
, work_area
);
1483 /* Manage resizing for Motif. This disables resizing when the menubar
1484 is about to be modified. */
1487 lw_allow_resizing (Widget w
, Boolean flag
)
1489 lw_allow_resizing (w
, flag
)
1494 #if defined (USE_MOTIF)
1495 xm_manage_resizing (w
, flag
);
1500 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1501 set to an appropriate enumerator of type enum menu_separator.
1502 MOTIF_P non-zero means map separator types not supported by Motif
1503 to similar ones that are supported. */
1506 lw_separator_p (label
, type
, motif_p
)
1508 enum menu_separator
*type
;
1511 int separator_p
= 0;
1513 if (strlen (label
) >= 3
1514 && bcmp (label
, "--:", 3) == 0)
1516 static struct separator_table
1519 enum menu_separator type
;
1523 {"space", SEPARATOR_NO_LINE
},
1524 {"noLine", SEPARATOR_NO_LINE
},
1525 {"singleLine", SEPARATOR_SINGLE_LINE
},
1526 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1527 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1528 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1529 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1530 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1531 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1532 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1533 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1534 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1535 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1536 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1543 for (i
= 0; separator_names
[i
].name
; ++i
)
1544 if (strcmp (label
, separator_names
[i
].name
) == 0)
1547 *type
= separator_names
[i
].type
;
1549 /* If separator type is not supported under Motif,
1550 use a similar one. */
1551 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1556 else if (strlen (label
) > 3
1557 && bcmp (label
, "--", 2) == 0
1560 /* Alternative, more Emacs-style names. */
1561 static struct separator_table
1564 enum menu_separator type
;
1568 {"space", SEPARATOR_NO_LINE
},
1569 {"no-line", SEPARATOR_NO_LINE
},
1570 {"single-line", SEPARATOR_SINGLE_LINE
},
1571 {"double-line", SEPARATOR_DOUBLE_LINE
},
1572 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1573 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1574 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1575 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1576 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1577 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1578 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1579 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1580 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1581 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1588 for (i
= 0; separator_names
[i
].name
; ++i
)
1589 if (strcmp (label
, separator_names
[i
].name
) == 0)
1592 *type
= separator_names
[i
].type
;
1594 /* If separator type is not supported under Motif,
1595 use a similar one. */
1596 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1603 /* Old-style separator, maybe. It's a separator if it contains
1605 while (*label
== '-')
1607 separator_p
= *label
== 0;
1608 *type
= SEPARATOR_SHADOW_ETCHED_IN
;
1614 /* arch-tag: 3d730f36-a441-4a71-9971-48ef3b5a4d9f
1615 (do not change this comment) */