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 (widget_value
*,
77 static void instantiate_widget_instance (widget_instance
*);
78 static int my_strcasecmp (char *, char *);
79 static void safe_free_str (char *);
80 static void free_widget_value_tree (widget_value
*);
81 static widget_value
*copy_widget_value_tree (widget_value
*,
83 static widget_info
*allocate_widget_info (char *, char *, LWLIB_ID
,
85 lw_callback
, lw_callback
,
86 lw_callback
, lw_callback
);
87 static void free_widget_info (widget_info
*);
88 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
89 static widget_instance
*allocate_widget_instance (widget_info
*,
91 static void free_widget_instance (widget_instance
*);
92 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
93 static widget_instance
*get_widget_instance (Widget
, Boolean
);
94 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
95 static Boolean
safe_strcmp (char *, char *);
96 static Widget
name_to_widget (widget_instance
*, char *);
97 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
98 static void update_one_widget_instance (widget_instance
*, Boolean
);
99 static void update_all_widget_values (widget_info
*, Boolean
);
100 static void initialize_widget_instance (widget_instance
*);
101 static widget_creation_function
find_in_table (char *, widget_creation_entry
*);
102 static Boolean
dialog_spec_p (char *);
103 static void destroy_one_instance (widget_instance
*);
104 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
105 static Boolean
get_one_value (widget_instance
*, widget_value
*);
106 static void show_one_widget_busy (Widget
, Boolean
);
109 lwlib_memset (char *address
, int value
, size_t length
)
113 for (i
= 0; i
< length
; i
++)
118 lwlib_bcopy (char *from
, char *to
, int length
)
122 for (i
= 0; i
< length
; i
++)
125 \f/* utility functions for widget_instance and widget_info */
127 safe_strdup (const char *s
)
131 result
= (char *) malloc (strlen (s
) + 1);
138 /* Like strcmp but ignore differences in case. */
141 my_strcasecmp (char *s1
, char *s2
)
152 return (c1
> c2
? 1 : -1);
159 safe_free_str (char *s
)
164 static widget_value
*widget_value_free_list
= 0;
165 static int malloc_cpt
= 0;
168 malloc_widget_value (void)
171 if (widget_value_free_list
)
173 wv
= widget_value_free_list
;
174 widget_value_free_list
= wv
->free_list
;
179 wv
= (widget_value
*) malloc (sizeof (widget_value
));
182 lwlib_memset ((void*) wv
, 0, sizeof (widget_value
));
186 /* this is analogous to free(). It frees only what was allocated
187 by malloc_widget_value(), and no substructures.
190 free_widget_value (widget_value
*wv
)
197 /* When the number of already allocated cells is too big,
204 wv
->free_list
= widget_value_free_list
;
205 widget_value_free_list
= wv
;
210 free_widget_value_tree (widget_value
*wv
)
219 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
221 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
223 XtFree (wv
->toolkit_data
);
224 wv
->toolkit_data
= (void *) 0xDEADBEEF;
227 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
229 free_widget_value_tree (wv
->contents
);
230 wv
->contents
= (widget_value
*) 0xDEADBEEF;
234 free_widget_value_tree (wv
->next
);
235 wv
->next
= (widget_value
*) 0xDEADBEEF;
237 free_widget_value (wv
);
240 static widget_value
*
241 copy_widget_value_tree (widget_value
*val
, change_type change
)
247 if (val
== (widget_value
*) 1)
250 copy
= malloc_widget_value ();
251 copy
->name
= safe_strdup (val
->name
);
252 copy
->value
= safe_strdup (val
->value
);
253 copy
->key
= safe_strdup (val
->key
);
254 copy
->help
= val
->help
;
255 copy
->enabled
= val
->enabled
;
256 copy
->button_type
= val
->button_type
;
257 copy
->selected
= val
->selected
;
258 copy
->edited
= False
;
259 copy
->change
= change
;
260 copy
->this_one_change
= change
;
261 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
262 copy
->call_data
= val
->call_data
;
263 copy
->next
= copy_widget_value_tree (val
->next
, change
);
264 copy
->toolkit_data
= NULL
;
265 copy
->free_toolkit_data
= False
;
270 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
271 selection_cb
, post_activate_cb
, highlight_cb
)
276 lw_callback pre_activate_cb
;
277 lw_callback selection_cb
;
278 lw_callback post_activate_cb
;
279 lw_callback highlight_cb
;
281 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
282 info
->type
= safe_strdup (type
);
283 info
->name
= safe_strdup (name
);
285 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
287 info
->pre_activate_cb
= pre_activate_cb
;
288 info
->selection_cb
= selection_cb
;
289 info
->post_activate_cb
= post_activate_cb
;
290 info
->highlight_cb
= highlight_cb
;
291 info
->instances
= NULL
;
293 info
->next
= all_widget_info
;
294 all_widget_info
= info
;
300 free_widget_info (widget_info
*info
)
302 safe_free_str (info
->type
);
303 safe_free_str (info
->name
);
304 free_widget_value_tree (info
->val
);
305 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
310 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
312 widget_instance
* instance
= (widget_instance
*)closure
;
314 /* be very conservative */
315 if (instance
->widget
== widget
)
316 instance
->widget
= NULL
;
319 /* The messy #ifdef PROTOTYPES here and elsewhere are prompted by a
320 flood of warnings about argument promotion from proprietary ISO C
321 compilers. (etags still only makes one entry for each function.) */
322 static widget_instance
*
324 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
326 allocate_widget_instance (info
, parent
, pop_up_p
)
332 widget_instance
* instance
=
333 (widget_instance
*)malloc (sizeof (widget_instance
));
334 bzero (instance
, sizeof *instance
);
335 instance
->parent
= parent
;
336 instance
->pop_up_p
= pop_up_p
;
337 instance
->info
= info
;
338 instance
->next
= info
->instances
;
339 info
->instances
= instance
;
341 instantiate_widget_instance (instance
);
343 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
344 mark_widget_destroyed
, (XtPointer
)instance
);
349 free_widget_instance (widget_instance
*instance
)
351 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
357 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
359 get_widget_info (id
, remove_p
)
366 for (prev
= NULL
, info
= all_widget_info
;
368 prev
= info
, info
= info
->next
)
374 prev
->next
= info
->next
;
376 all_widget_info
= info
->next
;
383 /* Internal function used by the library dependent implementation to get the
384 widget_value for a given widget in an instance */
386 lw_get_widget_info (LWLIB_ID id
)
388 return get_widget_info (id
, 0);
391 static widget_instance
*
393 get_widget_instance (Widget widget
, Boolean remove_p
)
395 get_widget_instance (widget
, remove_p
)
401 widget_instance
* instance
;
402 widget_instance
* prev
;
403 for (info
= all_widget_info
; info
; info
= info
->next
)
404 for (prev
= NULL
, instance
= info
->instances
;
406 prev
= instance
, instance
= instance
->next
)
407 if (instance
->widget
== widget
)
412 prev
->next
= instance
->next
;
414 info
->instances
= instance
->next
;
418 return (widget_instance
*) 0;
421 /* Value is a pointer to the widget_instance corresponding to
422 WIDGET, or null if WIDGET is not a lwlib widget. */
425 lw_get_widget_instance (Widget widget
)
427 return get_widget_instance (widget
, False
);
430 static widget_instance
*
432 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
434 find_instance (id
, parent
, pop_up_p
)
440 widget_info
* info
= get_widget_info (id
, False
);
441 widget_instance
* instance
;
444 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
445 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
452 /* utility function for widget_value */
454 safe_strcmp (char *s1
, char *s2
)
456 if (!!s1
^ !!s2
) return True
;
457 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
462 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
463 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
465 (oc == NO_CHANGE ? "none" : \
466 (oc == INVISIBLE_CHANGE ? "invisible" : \
467 (oc == VISIBLE_CHANGE ? "visible" : \
468 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
470 (nc == NO_CHANGE ? "none" : \
471 (nc == INVISIBLE_CHANGE ? "invisible" : \
472 (nc == VISIBLE_CHANGE ? "visible" : \
473 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
476 # define EXPLAIN(name, oc, nc, desc, a1, a2)
480 static widget_value
*
481 merge_widget_value (widget_value
*val1
, widget_value
*val2
, int level
, int *change_p
)
483 change_type change
, this_one_change
;
484 widget_value
* merged_next
;
485 widget_value
* merged_contents
;
492 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
500 free_widget_value_tree (val1
);
506 if (safe_strcmp (val1
->name
, val2
->name
))
508 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
509 val1
->name
, val2
->name
);
510 change
= max (change
, STRUCTURAL_CHANGE
);
511 safe_free_str (val1
->name
);
512 val1
->name
= safe_strdup (val2
->name
);
514 if (safe_strcmp (val1
->value
, val2
->value
))
516 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
517 val1
->value
, val2
->value
);
518 change
= max (change
, VISIBLE_CHANGE
);
519 safe_free_str (val1
->value
);
520 val1
->value
= safe_strdup (val2
->value
);
522 if (safe_strcmp (val1
->key
, val2
->key
))
524 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
525 val1
->key
, val2
->key
);
526 change
= max (change
, VISIBLE_CHANGE
);
527 safe_free_str (val1
->key
);
528 val1
->key
= safe_strdup (val2
->key
);
530 if (! EQ (val1
->help
, val2
->help
))
532 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
533 val1
->help
, val2
->help
);
534 change
= max (change
, VISIBLE_CHANGE
);
535 val1
->help
= val2
->help
;
537 if (val1
->enabled
!= val2
->enabled
)
539 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
540 val1
->enabled
, val2
->enabled
);
541 change
= max (change
, VISIBLE_CHANGE
);
542 val1
->enabled
= val2
->enabled
;
544 if (val1
->button_type
!= val2
->button_type
)
546 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
547 val1
->button_type
, val2
->button_type
);
548 change
= max (change
, VISIBLE_CHANGE
);
549 val1
->button_type
= val2
->button_type
;
551 if (val1
->selected
!= val2
->selected
)
553 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
554 val1
->selected
, val2
->selected
);
555 change
= max (change
, VISIBLE_CHANGE
);
556 val1
->selected
= val2
->selected
;
558 if (val1
->call_data
!= val2
->call_data
)
560 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
561 val1
->call_data
, val2
->call_data
);
562 change
= max (change
, INVISIBLE_CHANGE
);
563 val1
->call_data
= val2
->call_data
;
569 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
572 if (val1
->contents
&& !merged_contents
)
574 /* This used to say INVISIBLE_CHANGE,
575 but it is visible and vitally important when
576 the contents of the menu bar itself are entirely deleted.
578 But maybe it doesn't matter. This fails to fix the bug. */
579 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
581 change
= max (change
, STRUCTURAL_CHANGE
);
583 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
585 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
587 change
= max (change
, INVISIBLE_CHANGE
);
588 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
590 change
= max (merged_contents
->change
, change
);
595 val1
->contents
= merged_contents
;
598 this_one_change
= change
;
600 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
602 if (val1
->next
&& !merged_next
)
604 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
606 change
= max (change
, STRUCTURAL_CHANGE
);
608 else if (merged_next
)
610 if (merged_next
->change
)
611 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
613 change
= max (change
, merged_next
->change
);
616 val1
->next
= merged_next
;
618 val1
->this_one_change
= this_one_change
;
619 val1
->change
= change
;
621 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
624 if (val1
->free_toolkit_data
)
625 XtFree (val1
->toolkit_data
);
626 val1
->toolkit_data
= NULL
;
633 /* modifying the widgets */
635 name_to_widget (widget_instance
*instance
, char *name
)
637 Widget widget
= NULL
;
639 if (!instance
->widget
)
642 if (!strcmp (XtName (instance
->widget
), name
))
643 widget
= instance
->widget
;
646 int length
= strlen (name
) + 2;
647 char* real_name
= (char *) xmalloc (length
);
649 strcpy (real_name
+ 1, name
);
651 widget
= XtNameToWidget (instance
->widget
, real_name
);
660 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
662 set_one_value (instance
, val
, deep_p
)
663 widget_instance
* instance
;
668 Widget widget
= name_to_widget (instance
, val
->name
);
672 #if defined (USE_LUCID)
673 if (lw_lucid_widget_p (instance
->widget
))
674 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
676 #if defined (USE_MOTIF)
677 if (lw_motif_widget_p (instance
->widget
))
678 xm_update_one_widget (instance
, widget
, val
, deep_p
);
680 #if defined (USE_XAW)
681 if (lw_xaw_widget_p (instance
->widget
))
682 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
689 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
691 update_one_widget_instance (instance
, deep_p
)
692 widget_instance
* instance
;
698 if (!instance
->widget
)
699 /* the widget was destroyed */
702 for (val
= instance
->info
->val
; val
; val
= val
->next
)
703 if (val
->change
!= NO_CHANGE
)
704 set_one_value (instance
, val
, deep_p
);
709 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
711 update_all_widget_values (info
, deep_p
)
716 widget_instance
* instance
;
719 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
720 update_one_widget_instance (instance
, deep_p
);
722 for (val
= info
->val
; val
; val
= val
->next
)
723 val
->change
= NO_CHANGE
;
728 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
730 lw_modify_all_widgets (id
, val
, deep_p
)
736 widget_info
* info
= get_widget_info (id
, False
);
737 widget_value
* new_val
;
738 widget_value
* next_new_val
;
748 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
750 next_new_val
= new_val
->next
;
751 new_val
->next
= NULL
;
753 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
754 if (!strcmp (cur
->name
, new_val
->name
))
759 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
762 prev
->next
= cur
? cur
: next
;
764 info
->val
= cur
? cur
: next
;
771 /* Could not find it, add it */
773 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
775 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
778 new_val
->next
= next_new_val
;
781 update_all_widget_values (info
, deep_p
);
786 /* creating the widgets */
789 initialize_widget_instance (widget_instance
*instance
)
793 for (val
= instance
->info
->val
; val
; val
= val
->next
)
794 val
->change
= STRUCTURAL_CHANGE
;
796 update_one_widget_instance (instance
, True
);
798 for (val
= instance
->info
->val
; val
; val
= val
->next
)
799 val
->change
= NO_CHANGE
;
803 static widget_creation_function
804 find_in_table (char *type
, widget_creation_entry
*table
)
806 widget_creation_entry
* cur
;
807 for (cur
= table
; cur
->type
; cur
++)
808 if (!my_strcasecmp (type
, cur
->type
))
809 return cur
->function
;
814 dialog_spec_p (char *name
)
816 /* return True if name matches [EILPQeilpq][1-9][Bb] or
817 [EILPQeilpq][1-9][Bb][Rr][1-9] */
823 case 'E': case 'I': case 'L': case 'P': case 'Q':
824 case 'e': case 'i': case 'l': case 'p': case 'q':
825 if (name
[1] >= '0' && name
[1] <= '9')
827 if (name
[2] != 'B' && name
[2] != 'b')
831 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
833 if ((name
[3] == 'R' || name
[3] == 'r')
834 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
847 instantiate_widget_instance (widget_instance
*instance
)
849 widget_creation_function function
= NULL
;
851 #if defined (USE_LUCID)
853 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
855 #if defined(USE_MOTIF)
857 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
859 #if defined (USE_XAW)
861 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
866 if (dialog_spec_p (instance
->info
->type
))
868 #if defined (USE_LUCID)
871 #if defined(USE_MOTIF)
873 function
= xm_create_dialog
;
875 #if defined (USE_XAW)
877 function
= xaw_create_dialog
;
884 printf ("No creation function for widget type %s\n",
885 instance
->info
->type
);
889 instance
->widget
= (*function
) (instance
);
891 if (!instance
->widget
)
894 /* XtRealizeWidget (instance->widget);*/
898 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
899 selection_cb
, post_activate_cb
, highlight_cb
)
904 lw_callback pre_activate_cb
;
905 lw_callback selection_cb
;
906 lw_callback post_activate_cb
;
907 lw_callback highlight_cb
;
909 if (!get_widget_info (id
, False
))
910 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
911 post_activate_cb
, highlight_cb
);
916 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
918 lw_get_widget (id
, parent
, pop_up_p
)
924 widget_instance
* instance
;
926 instance
= find_instance (id
, parent
, pop_up_p
);
927 return instance
? instance
->widget
: NULL
;
932 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
934 lw_make_widget (id
, parent
, pop_up_p
)
940 widget_instance
* instance
;
943 instance
= find_instance (id
, parent
, pop_up_p
);
946 info
= get_widget_info (id
, False
);
949 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
950 initialize_widget_instance (instance
);
952 if (!instance
->widget
)
954 return instance
->widget
;
959 lw_create_widget (char* type
, char* name
, LWLIB_ID id
, widget_value
* val
,
960 Widget parent
, Boolean pop_up_p
,
961 lw_callback pre_activate_cb
, lw_callback selection_cb
,
962 lw_callback post_activate_cb
, lw_callback highlight_cb
)
964 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
965 selection_cb
, post_activate_cb
, highlight_cb
)
972 lw_callback pre_activate_cb
;
973 lw_callback selection_cb
;
974 lw_callback post_activate_cb
;
975 lw_callback highlight_cb
;
978 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
979 post_activate_cb
, highlight_cb
);
980 return lw_make_widget (id
, parent
, pop_up_p
);
984 /* destroying the widgets */
986 destroy_one_instance (widget_instance
*instance
)
988 /* Remove the destroy callback on the widget; that callback will try to
989 dereference the instance object (to set its widget slot to 0, since the
990 widget is dead.) Since the instance is now dead, we don't have to worry
991 about the fact that its widget is dead too.
993 This happens in the Phase2Destroy of the widget, so this callback would
994 not have been run until arbitrarily long after the instance was freed.
996 if (instance
->widget
)
997 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
998 mark_widget_destroyed
, (XtPointer
)instance
);
1000 if (instance
->widget
)
1002 /* The else are pretty tricky here, including the empty statement
1003 at the end because it would be very bad to destroy a widget
1005 #if defined (USE_LUCID)
1006 if (lw_lucid_widget_p (instance
->widget
))
1007 xlw_destroy_instance (instance
);
1010 #if defined (USE_MOTIF)
1011 if (lw_motif_widget_p (instance
->widget
))
1012 xm_destroy_instance (instance
);
1015 #if defined (USE_XAW)
1016 if (lw_xaw_widget_p (instance
->widget
))
1017 xaw_destroy_instance (instance
);
1020 /* do not remove the empty statement */
1024 free_widget_instance (instance
);
1028 lw_destroy_widget (Widget w
)
1030 widget_instance
* instance
= get_widget_instance (w
, True
);
1034 widget_info
*info
= instance
->info
;
1035 /* instance has already been removed from the list; free it */
1036 destroy_one_instance (instance
);
1037 /* if there are no instances left, free the info too */
1038 if (!info
->instances
)
1039 lw_destroy_all_widgets (info
->id
);
1044 lw_destroy_all_widgets (LWLIB_ID id
)
1046 widget_info
* info
= get_widget_info (id
, True
);
1047 widget_instance
* instance
;
1048 widget_instance
* next
;
1052 for (instance
= info
->instances
; instance
; )
1054 next
= instance
->next
;
1055 destroy_one_instance (instance
);
1058 free_widget_info (info
);
1063 lw_destroy_everything (void)
1065 while (all_widget_info
)
1066 lw_destroy_all_widgets (all_widget_info
->id
);
1070 lw_destroy_all_pop_ups (void)
1074 widget_instance
* instance
;
1076 for (info
= all_widget_info
; info
; info
= next
)
1079 instance
= info
->instances
;
1080 if (instance
&& instance
->pop_up_p
)
1081 lw_destroy_all_widgets (info
->id
);
1086 extern Widget
first_child (/* Widget */); /* garbage */
1090 lw_raise_all_pop_up_widgets (void)
1093 widget_instance
* instance
;
1094 Widget result
= NULL
;
1096 for (info
= all_widget_info
; info
; info
= info
->next
)
1097 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1098 if (instance
->pop_up_p
)
1100 Widget widget
= instance
->widget
;
1103 if (XtIsManaged (widget
)
1105 /* What a complete load of crap!!!!
1106 When a dialogShell is on the screen, it is not managed!
1108 || (lw_motif_widget_p (instance
->widget
) &&
1109 XtIsManaged (first_child (widget
)))
1115 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1124 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1126 lw_pop_all_widgets (id
, up
)
1131 widget_info
* info
= get_widget_info (id
, False
);
1132 widget_instance
* instance
;
1135 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1136 if (instance
->pop_up_p
&& instance
->widget
)
1138 #if defined (USE_LUCID)
1139 if (lw_lucid_widget_p (instance
->widget
))
1141 XtRealizeWidget (instance
->widget
);
1142 xlw_pop_instance (instance
, up
);
1145 #if defined (USE_MOTIF)
1146 if (lw_motif_widget_p (instance
->widget
))
1148 XtRealizeWidget (instance
->widget
);
1149 xm_pop_instance (instance
, up
);
1152 #if defined (USE_XAW)
1153 if (lw_xaw_widget_p (instance
->widget
))
1155 XtRealizeWidget (XtParent (instance
->widget
));
1156 XtRealizeWidget (instance
->widget
);
1157 xaw_pop_instance (instance
, up
);
1164 lw_pop_up_all_widgets (LWLIB_ID id
)
1166 lw_pop_all_widgets (id
, True
);
1170 lw_pop_down_all_widgets (LWLIB_ID id
)
1172 lw_pop_all_widgets (id
, False
);
1176 lw_popup_menu (Widget widget
, XEvent
*event
)
1178 #if defined (USE_LUCID)
1179 if (lw_lucid_widget_p (widget
))
1180 xlw_popup_menu (widget
, event
);
1182 #if defined (USE_MOTIF)
1183 if (lw_motif_widget_p (widget
))
1184 xm_popup_menu (widget
, event
);
1186 #if defined (USE_XAW)
1187 if (lw_xaw_widget_p (widget
))
1188 xaw_popup_menu (widget
, event
);
1192 \f/* get the values back */
1194 get_one_value (widget_instance
*instance
, widget_value
*val
)
1196 Widget widget
= name_to_widget (instance
, val
->name
);
1200 #if defined (USE_LUCID)
1201 if (lw_lucid_widget_p (instance
->widget
))
1202 xlw_update_one_value (instance
, widget
, val
);
1204 #if defined (USE_MOTIF)
1205 if (lw_motif_widget_p (instance
->widget
))
1206 xm_update_one_value (instance
, widget
, val
);
1208 #if defined (USE_XAW)
1209 if (lw_xaw_widget_p (instance
->widget
))
1210 xaw_update_one_value (instance
, widget
, val
);
1219 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1221 widget_info
* info
= get_widget_info (id
, False
);
1222 widget_instance
* instance
;
1224 Boolean result
= False
;
1229 instance
= info
->instances
;
1233 for (val
= val_out
; val
; val
= val
->next
)
1234 if (get_one_value (instance
, val
))
1241 lw_get_all_values (LWLIB_ID id
)
1243 widget_info
* info
= get_widget_info (id
, False
);
1244 widget_value
* val
= info
->val
;
1245 if (lw_get_some_values (id
, val
))
1251 /* internal function used by the library dependent implementation to get the
1252 widget_value for a given widget in an instance */
1254 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1256 char* name
= XtName (w
);
1258 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1259 if (!strcmp (cur
->name
, name
))
1264 \f/* update other instances value when one thing changed */
1266 /* To forbid recursive calls */
1267 static Boolean lwlib_updating
;
1269 /* This function can be used as a an XtCallback for the widgets that get
1270 modified to update other instances of the widgets. Closure should be the
1273 lw_internal_update_other_instances (Widget widget
, XtPointer closure
, XtPointer call_data
)
1275 widget_instance
* instance
= (widget_instance
*)closure
;
1276 char* name
= XtName (widget
);
1278 widget_instance
* cur
;
1281 /* Avoid possibly infinite recursion. */
1285 /* protect against the widget being destroyed */
1286 if (XtWidgetBeingDestroyedP (widget
))
1289 /* Return immediately if there are no other instances */
1290 info
= instance
->info
;
1291 if (!info
->instances
->next
)
1294 lwlib_updating
= True
;
1296 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1298 if (val
&& get_one_value (instance
, val
))
1299 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1300 if (cur
!= instance
)
1301 set_one_value (cur
, val
, True
);
1303 lwlib_updating
= False
;
1310 lw_get_widget_id (Widget w
)
1312 widget_instance
* instance
= get_widget_instance (w
, False
);
1314 return instance
? instance
->info
->id
: 0;
1317 \f/* set the keyboard focus */
1319 lw_set_keyboard_focus (Widget parent
, Widget w
)
1321 #if defined (USE_MOTIF)
1322 xm_set_keyboard_focus (parent
, w
);
1324 XtSetKeyboardFocus (parent
, w
);
1331 show_one_widget_busy (Widget w
, Boolean flag
)
1333 show_one_widget_busy (w
, flag
)
1338 Pixel foreground
= 0;
1339 Pixel background
= 1;
1340 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1341 if (!widget_to_invert
)
1342 widget_to_invert
= w
;
1344 XtVaGetValues (widget_to_invert
,
1345 XtNforeground
, &foreground
,
1346 XtNbackground
, &background
,
1348 XtVaSetValues (widget_to_invert
,
1349 XtNforeground
, background
,
1350 XtNbackground
, foreground
,
1356 lw_show_busy (Widget w
, Boolean busy
)
1358 lw_show_busy (w
, busy
)
1363 widget_instance
* instance
= get_widget_instance (w
, False
);
1365 widget_instance
* next
;
1369 info
= instance
->info
;
1370 if (info
->busy
!= busy
)
1372 for (next
= info
->instances
; next
; next
= next
->next
)
1374 show_one_widget_busy (next
->widget
, busy
);
1380 /* This hack exists because Lucid/Athena need to execute the strange
1381 function below to support geometry management. */
1384 lw_refigure_widget (Widget w
, Boolean doit
)
1386 lw_refigure_widget (w
, doit
)
1391 #if defined (USE_XAW)
1392 XawPanedSetRefigureMode (w
, doit
);
1394 #if defined (USE_MOTIF)
1398 XtUnmanageChild (w
);
1402 /* Toolkit independent way of determining if an event window is in the
1405 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1407 return menubar_widget
1408 #if defined (USE_LUCID)
1409 && XtWindow (menubar_widget
) == win
;
1411 #if defined (USE_MOTIF)
1412 && ((XtWindow (menubar_widget
) == win
)
1413 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1414 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1415 == menubar_widget
)));
1419 /* Motif hack to set the main window areas. */
1421 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1423 #if defined (USE_MOTIF)
1424 xm_set_main_areas (parent
, menubar
, work_area
);
1428 /* Manage resizing for Motif. This disables resizing when the menubar
1429 is about to be modified. */
1432 lw_allow_resizing (Widget w
, Boolean flag
)
1434 lw_allow_resizing (w
, flag
)
1439 #if defined (USE_MOTIF)
1440 xm_manage_resizing (w
, flag
);
1445 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1446 set to an appropriate enumerator of type enum menu_separator.
1447 MOTIF_P non-zero means map separator types not supported by Motif
1448 to similar ones that are supported. */
1451 lw_separator_p (char *label
, enum menu_separator
*type
, int motif_p
)
1453 int separator_p
= 0;
1455 if (strlen (label
) >= 3
1456 && bcmp (label
, "--:", 3) == 0)
1458 static struct separator_table
1461 enum menu_separator type
;
1465 {"space", SEPARATOR_NO_LINE
},
1466 {"noLine", SEPARATOR_NO_LINE
},
1467 {"singleLine", SEPARATOR_SINGLE_LINE
},
1468 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1469 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1470 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1471 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1472 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1473 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1474 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1475 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1476 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1477 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1478 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1485 for (i
= 0; separator_names
[i
].name
; ++i
)
1486 if (strcmp (label
, separator_names
[i
].name
) == 0)
1489 *type
= separator_names
[i
].type
;
1491 /* If separator type is not supported under Motif,
1492 use a similar one. */
1493 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1498 else if (strlen (label
) > 3
1499 && bcmp (label
, "--", 2) == 0
1502 /* Alternative, more Emacs-style names. */
1503 static struct separator_table
1506 enum menu_separator type
;
1510 {"space", SEPARATOR_NO_LINE
},
1511 {"no-line", SEPARATOR_NO_LINE
},
1512 {"single-line", SEPARATOR_SINGLE_LINE
},
1513 {"double-line", SEPARATOR_DOUBLE_LINE
},
1514 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1515 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1516 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1517 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1518 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1519 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1520 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1521 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1522 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1523 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1530 for (i
= 0; separator_names
[i
].name
; ++i
)
1531 if (strcmp (label
, separator_names
[i
].name
) == 0)
1534 *type
= separator_names
[i
].type
;
1536 /* If separator type is not supported under Motif,
1537 use a similar one. */
1538 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1545 /* Old-style separator, maybe. It's a separator if it contains
1547 while (*label
== '-')
1549 separator_p
= *label
== 0;
1550 *type
= SEPARATOR_SHADOW_ETCHED_IN
;
1556 /* arch-tag: 3d730f36-a441-4a71-9971-48ef3b5a4d9f
1557 (do not change this comment) */