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
);
107 \f/* utility functions for widget_instance and widget_info */
109 safe_strdup (const char *s
)
113 result
= (char *) malloc (strlen (s
) + 1);
120 /* Like strcmp but ignore differences in case. */
123 my_strcasecmp (char *s1
, char *s2
)
134 return (c1
> c2
? 1 : -1);
141 safe_free_str (char *s
)
146 static widget_value
*widget_value_free_list
= 0;
147 static int malloc_cpt
= 0;
150 malloc_widget_value (void)
153 if (widget_value_free_list
)
155 wv
= widget_value_free_list
;
156 widget_value_free_list
= wv
->free_list
;
161 wv
= (widget_value
*) malloc (sizeof (widget_value
));
164 memset ((void*) wv
, 0, sizeof (widget_value
));
168 /* this is analogous to free(). It frees only what was allocated
169 by malloc_widget_value(), and no substructures.
172 free_widget_value (widget_value
*wv
)
179 /* When the number of already allocated cells is too big,
186 wv
->free_list
= widget_value_free_list
;
187 widget_value_free_list
= wv
;
192 free_widget_value_tree (widget_value
*wv
)
201 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
203 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
205 XtFree (wv
->toolkit_data
);
206 wv
->toolkit_data
= (void *) 0xDEADBEEF;
209 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
211 free_widget_value_tree (wv
->contents
);
212 wv
->contents
= (widget_value
*) 0xDEADBEEF;
216 free_widget_value_tree (wv
->next
);
217 wv
->next
= (widget_value
*) 0xDEADBEEF;
219 free_widget_value (wv
);
222 static widget_value
*
223 copy_widget_value_tree (widget_value
*val
, change_type change
)
229 if (val
== (widget_value
*) 1)
232 copy
= malloc_widget_value ();
233 copy
->name
= safe_strdup (val
->name
);
234 copy
->value
= safe_strdup (val
->value
);
235 copy
->key
= safe_strdup (val
->key
);
236 copy
->help
= val
->help
;
237 copy
->enabled
= val
->enabled
;
238 copy
->button_type
= val
->button_type
;
239 copy
->selected
= val
->selected
;
240 copy
->edited
= False
;
241 copy
->change
= change
;
242 copy
->this_one_change
= change
;
243 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
244 copy
->call_data
= val
->call_data
;
245 copy
->next
= copy_widget_value_tree (val
->next
, change
);
246 copy
->toolkit_data
= NULL
;
247 copy
->free_toolkit_data
= False
;
252 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
253 selection_cb
, post_activate_cb
, highlight_cb
)
258 lw_callback pre_activate_cb
;
259 lw_callback selection_cb
;
260 lw_callback post_activate_cb
;
261 lw_callback highlight_cb
;
263 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
264 info
->type
= safe_strdup (type
);
265 info
->name
= safe_strdup (name
);
267 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
269 info
->pre_activate_cb
= pre_activate_cb
;
270 info
->selection_cb
= selection_cb
;
271 info
->post_activate_cb
= post_activate_cb
;
272 info
->highlight_cb
= highlight_cb
;
273 info
->instances
= NULL
;
275 info
->next
= all_widget_info
;
276 all_widget_info
= info
;
282 free_widget_info (widget_info
*info
)
284 safe_free_str (info
->type
);
285 safe_free_str (info
->name
);
286 free_widget_value_tree (info
->val
);
287 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
292 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
294 widget_instance
* instance
= (widget_instance
*)closure
;
296 /* be very conservative */
297 if (instance
->widget
== widget
)
298 instance
->widget
= NULL
;
301 /* The messy #ifdef PROTOTYPES here and elsewhere are prompted by a
302 flood of warnings about argument promotion from proprietary ISO C
303 compilers. (etags still only makes one entry for each function.) */
304 static widget_instance
*
306 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
308 allocate_widget_instance (info
, parent
, pop_up_p
)
314 widget_instance
* instance
=
315 (widget_instance
*)malloc (sizeof (widget_instance
));
316 memset (instance
, 0, sizeof *instance
);
317 instance
->parent
= parent
;
318 instance
->pop_up_p
= pop_up_p
;
319 instance
->info
= info
;
320 instance
->next
= info
->instances
;
321 info
->instances
= instance
;
323 instantiate_widget_instance (instance
);
325 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
326 mark_widget_destroyed
, (XtPointer
)instance
);
331 free_widget_instance (widget_instance
*instance
)
333 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
339 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
341 get_widget_info (id
, remove_p
)
348 for (prev
= NULL
, info
= all_widget_info
;
350 prev
= info
, info
= info
->next
)
356 prev
->next
= info
->next
;
358 all_widget_info
= info
->next
;
365 /* Internal function used by the library dependent implementation to get the
366 widget_value for a given widget in an instance */
368 lw_get_widget_info (LWLIB_ID id
)
370 return get_widget_info (id
, 0);
373 static widget_instance
*
375 get_widget_instance (Widget widget
, Boolean remove_p
)
377 get_widget_instance (widget
, remove_p
)
383 widget_instance
* instance
;
384 widget_instance
* prev
;
385 for (info
= all_widget_info
; info
; info
= info
->next
)
386 for (prev
= NULL
, instance
= info
->instances
;
388 prev
= instance
, instance
= instance
->next
)
389 if (instance
->widget
== widget
)
394 prev
->next
= instance
->next
;
396 info
->instances
= instance
->next
;
400 return (widget_instance
*) 0;
403 /* Value is a pointer to the widget_instance corresponding to
404 WIDGET, or null if WIDGET is not a lwlib widget. */
407 lw_get_widget_instance (Widget widget
)
409 return get_widget_instance (widget
, False
);
412 static widget_instance
*
414 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
416 find_instance (id
, parent
, pop_up_p
)
422 widget_info
* info
= get_widget_info (id
, False
);
423 widget_instance
* instance
;
426 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
427 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
434 /* utility function for widget_value */
436 safe_strcmp (char *s1
, char *s2
)
438 if (!!s1
^ !!s2
) return True
;
439 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
444 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
445 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
447 (oc == NO_CHANGE ? "none" : \
448 (oc == INVISIBLE_CHANGE ? "invisible" : \
449 (oc == VISIBLE_CHANGE ? "visible" : \
450 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
452 (nc == NO_CHANGE ? "none" : \
453 (nc == INVISIBLE_CHANGE ? "invisible" : \
454 (nc == VISIBLE_CHANGE ? "visible" : \
455 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
458 # define EXPLAIN(name, oc, nc, desc, a1, a2)
462 static widget_value
*
463 merge_widget_value (widget_value
*val1
, widget_value
*val2
, int level
, int *change_p
)
465 change_type change
, this_one_change
;
466 widget_value
* merged_next
;
467 widget_value
* merged_contents
;
474 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
482 free_widget_value_tree (val1
);
488 if (safe_strcmp (val1
->name
, val2
->name
))
490 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
491 val1
->name
, val2
->name
);
492 change
= max (change
, STRUCTURAL_CHANGE
);
493 safe_free_str (val1
->name
);
494 val1
->name
= safe_strdup (val2
->name
);
496 if (safe_strcmp (val1
->value
, val2
->value
))
498 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
499 val1
->value
, val2
->value
);
500 change
= max (change
, VISIBLE_CHANGE
);
501 safe_free_str (val1
->value
);
502 val1
->value
= safe_strdup (val2
->value
);
504 if (safe_strcmp (val1
->key
, val2
->key
))
506 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
507 val1
->key
, val2
->key
);
508 change
= max (change
, VISIBLE_CHANGE
);
509 safe_free_str (val1
->key
);
510 val1
->key
= safe_strdup (val2
->key
);
512 if (! EQ (val1
->help
, val2
->help
))
514 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
515 val1
->help
, val2
->help
);
516 change
= max (change
, VISIBLE_CHANGE
);
517 val1
->help
= val2
->help
;
519 if (val1
->enabled
!= val2
->enabled
)
521 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
522 val1
->enabled
, val2
->enabled
);
523 change
= max (change
, VISIBLE_CHANGE
);
524 val1
->enabled
= val2
->enabled
;
526 if (val1
->button_type
!= val2
->button_type
)
528 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
529 val1
->button_type
, val2
->button_type
);
530 change
= max (change
, VISIBLE_CHANGE
);
531 val1
->button_type
= val2
->button_type
;
533 if (val1
->selected
!= val2
->selected
)
535 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
536 val1
->selected
, val2
->selected
);
537 change
= max (change
, VISIBLE_CHANGE
);
538 val1
->selected
= val2
->selected
;
540 if (val1
->call_data
!= val2
->call_data
)
542 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
543 val1
->call_data
, val2
->call_data
);
544 change
= max (change
, INVISIBLE_CHANGE
);
545 val1
->call_data
= val2
->call_data
;
551 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
554 if (val1
->contents
&& !merged_contents
)
556 /* This used to say INVISIBLE_CHANGE,
557 but it is visible and vitally important when
558 the contents of the menu bar itself are entirely deleted.
560 But maybe it doesn't matter. This fails to fix the bug. */
561 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
563 change
= max (change
, STRUCTURAL_CHANGE
);
565 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
567 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
569 change
= max (change
, INVISIBLE_CHANGE
);
570 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
572 change
= max (merged_contents
->change
, change
);
577 val1
->contents
= merged_contents
;
580 this_one_change
= change
;
582 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
584 if (val1
->next
&& !merged_next
)
586 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
588 change
= max (change
, STRUCTURAL_CHANGE
);
590 else if (merged_next
)
592 if (merged_next
->change
)
593 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
595 change
= max (change
, merged_next
->change
);
598 val1
->next
= merged_next
;
600 val1
->this_one_change
= this_one_change
;
601 val1
->change
= change
;
603 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
606 if (val1
->free_toolkit_data
)
607 XtFree (val1
->toolkit_data
);
608 val1
->toolkit_data
= NULL
;
615 /* modifying the widgets */
617 name_to_widget (widget_instance
*instance
, char *name
)
619 Widget widget
= NULL
;
621 if (!instance
->widget
)
624 if (!strcmp (XtName (instance
->widget
), name
))
625 widget
= instance
->widget
;
628 int length
= strlen (name
) + 2;
629 char* real_name
= (char *) xmalloc (length
);
631 strcpy (real_name
+ 1, name
);
633 widget
= XtNameToWidget (instance
->widget
, real_name
);
642 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
644 set_one_value (instance
, val
, deep_p
)
645 widget_instance
* instance
;
650 Widget widget
= name_to_widget (instance
, val
->name
);
654 #if defined (USE_LUCID)
655 if (lw_lucid_widget_p (instance
->widget
))
656 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
658 #if defined (USE_MOTIF)
659 if (lw_motif_widget_p (instance
->widget
))
660 xm_update_one_widget (instance
, widget
, val
, deep_p
);
662 #if defined (USE_XAW)
663 if (lw_xaw_widget_p (instance
->widget
))
664 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
671 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
673 update_one_widget_instance (instance
, deep_p
)
674 widget_instance
* instance
;
680 if (!instance
->widget
)
681 /* the widget was destroyed */
684 for (val
= instance
->info
->val
; val
; val
= val
->next
)
685 if (val
->change
!= NO_CHANGE
)
686 set_one_value (instance
, val
, deep_p
);
691 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
693 update_all_widget_values (info
, deep_p
)
698 widget_instance
* instance
;
701 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
702 update_one_widget_instance (instance
, deep_p
);
704 for (val
= info
->val
; val
; val
= val
->next
)
705 val
->change
= NO_CHANGE
;
710 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
712 lw_modify_all_widgets (id
, val
, deep_p
)
718 widget_info
* info
= get_widget_info (id
, False
);
719 widget_value
* new_val
;
720 widget_value
* next_new_val
;
730 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
732 next_new_val
= new_val
->next
;
733 new_val
->next
= NULL
;
735 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
736 if (!strcmp (cur
->name
, new_val
->name
))
741 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
744 prev
->next
= cur
? cur
: next
;
746 info
->val
= cur
? cur
: next
;
753 /* Could not find it, add it */
755 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
757 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
760 new_val
->next
= next_new_val
;
763 update_all_widget_values (info
, deep_p
);
768 /* creating the widgets */
771 initialize_widget_instance (widget_instance
*instance
)
775 for (val
= instance
->info
->val
; val
; val
= val
->next
)
776 val
->change
= STRUCTURAL_CHANGE
;
778 update_one_widget_instance (instance
, True
);
780 for (val
= instance
->info
->val
; val
; val
= val
->next
)
781 val
->change
= NO_CHANGE
;
785 static widget_creation_function
786 find_in_table (char *type
, widget_creation_entry
*table
)
788 widget_creation_entry
* cur
;
789 for (cur
= table
; cur
->type
; cur
++)
790 if (!my_strcasecmp (type
, cur
->type
))
791 return cur
->function
;
796 dialog_spec_p (char *name
)
798 /* return True if name matches [EILPQeilpq][1-9][Bb] or
799 [EILPQeilpq][1-9][Bb][Rr][1-9] */
805 case 'E': case 'I': case 'L': case 'P': case 'Q':
806 case 'e': case 'i': case 'l': case 'p': case 'q':
807 if (name
[1] >= '0' && name
[1] <= '9')
809 if (name
[2] != 'B' && name
[2] != 'b')
813 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
815 if ((name
[3] == 'R' || name
[3] == 'r')
816 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
829 instantiate_widget_instance (widget_instance
*instance
)
831 widget_creation_function function
= NULL
;
833 #if defined (USE_LUCID)
835 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
837 #if defined(USE_MOTIF)
839 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
841 #if defined (USE_XAW)
843 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
848 if (dialog_spec_p (instance
->info
->type
))
850 #if defined (USE_LUCID)
853 #if defined(USE_MOTIF)
855 function
= xm_create_dialog
;
857 #if defined (USE_XAW)
859 function
= xaw_create_dialog
;
866 printf ("No creation function for widget type %s\n",
867 instance
->info
->type
);
871 instance
->widget
= (*function
) (instance
);
873 if (!instance
->widget
)
876 /* XtRealizeWidget (instance->widget);*/
880 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
881 selection_cb
, post_activate_cb
, highlight_cb
)
886 lw_callback pre_activate_cb
;
887 lw_callback selection_cb
;
888 lw_callback post_activate_cb
;
889 lw_callback highlight_cb
;
891 if (!get_widget_info (id
, False
))
892 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
893 post_activate_cb
, highlight_cb
);
898 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
900 lw_get_widget (id
, parent
, pop_up_p
)
906 widget_instance
* instance
;
908 instance
= find_instance (id
, parent
, pop_up_p
);
909 return instance
? instance
->widget
: NULL
;
914 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
916 lw_make_widget (id
, parent
, pop_up_p
)
922 widget_instance
* instance
;
925 instance
= find_instance (id
, parent
, pop_up_p
);
928 info
= get_widget_info (id
, False
);
931 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
932 initialize_widget_instance (instance
);
934 if (!instance
->widget
)
936 return instance
->widget
;
941 lw_create_widget (char* type
, char* name
, LWLIB_ID id
, widget_value
* val
,
942 Widget parent
, Boolean pop_up_p
,
943 lw_callback pre_activate_cb
, lw_callback selection_cb
,
944 lw_callback post_activate_cb
, lw_callback highlight_cb
)
946 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
947 selection_cb
, post_activate_cb
, highlight_cb
)
954 lw_callback pre_activate_cb
;
955 lw_callback selection_cb
;
956 lw_callback post_activate_cb
;
957 lw_callback highlight_cb
;
960 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
961 post_activate_cb
, highlight_cb
);
962 return lw_make_widget (id
, parent
, pop_up_p
);
966 /* destroying the widgets */
968 destroy_one_instance (widget_instance
*instance
)
970 /* Remove the destroy callback on the widget; that callback will try to
971 dereference the instance object (to set its widget slot to 0, since the
972 widget is dead.) Since the instance is now dead, we don't have to worry
973 about the fact that its widget is dead too.
975 This happens in the Phase2Destroy of the widget, so this callback would
976 not have been run until arbitrarily long after the instance was freed.
978 if (instance
->widget
)
979 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
980 mark_widget_destroyed
, (XtPointer
)instance
);
982 if (instance
->widget
)
984 /* The else are pretty tricky here, including the empty statement
985 at the end because it would be very bad to destroy a widget
987 #if defined (USE_LUCID)
988 if (lw_lucid_widget_p (instance
->widget
))
989 xlw_destroy_instance (instance
);
992 #if defined (USE_MOTIF)
993 if (lw_motif_widget_p (instance
->widget
))
994 xm_destroy_instance (instance
);
997 #if defined (USE_XAW)
998 if (lw_xaw_widget_p (instance
->widget
))
999 xaw_destroy_instance (instance
);
1002 /* do not remove the empty statement */
1006 free_widget_instance (instance
);
1010 lw_destroy_widget (Widget w
)
1012 widget_instance
* instance
= get_widget_instance (w
, True
);
1016 widget_info
*info
= instance
->info
;
1017 /* instance has already been removed from the list; free it */
1018 destroy_one_instance (instance
);
1019 /* if there are no instances left, free the info too */
1020 if (!info
->instances
)
1021 lw_destroy_all_widgets (info
->id
);
1026 lw_destroy_all_widgets (LWLIB_ID id
)
1028 widget_info
* info
= get_widget_info (id
, True
);
1029 widget_instance
* instance
;
1030 widget_instance
* next
;
1034 for (instance
= info
->instances
; instance
; )
1036 next
= instance
->next
;
1037 destroy_one_instance (instance
);
1040 free_widget_info (info
);
1045 lw_destroy_everything (void)
1047 while (all_widget_info
)
1048 lw_destroy_all_widgets (all_widget_info
->id
);
1052 lw_destroy_all_pop_ups (void)
1056 widget_instance
* instance
;
1058 for (info
= all_widget_info
; info
; info
= next
)
1061 instance
= info
->instances
;
1062 if (instance
&& instance
->pop_up_p
)
1063 lw_destroy_all_widgets (info
->id
);
1068 extern Widget
first_child (/* Widget */); /* garbage */
1072 lw_raise_all_pop_up_widgets (void)
1075 widget_instance
* instance
;
1076 Widget result
= NULL
;
1078 for (info
= all_widget_info
; info
; info
= info
->next
)
1079 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1080 if (instance
->pop_up_p
)
1082 Widget widget
= instance
->widget
;
1085 if (XtIsManaged (widget
)
1087 /* What a complete load of crap!!!!
1088 When a dialogShell is on the screen, it is not managed!
1090 || (lw_motif_widget_p (instance
->widget
) &&
1091 XtIsManaged (first_child (widget
)))
1097 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1106 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1108 lw_pop_all_widgets (id
, up
)
1113 widget_info
* info
= get_widget_info (id
, False
);
1114 widget_instance
* instance
;
1117 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1118 if (instance
->pop_up_p
&& instance
->widget
)
1120 #if defined (USE_LUCID)
1121 if (lw_lucid_widget_p (instance
->widget
))
1123 XtRealizeWidget (instance
->widget
);
1124 xlw_pop_instance (instance
, up
);
1127 #if defined (USE_MOTIF)
1128 if (lw_motif_widget_p (instance
->widget
))
1130 XtRealizeWidget (instance
->widget
);
1131 xm_pop_instance (instance
, up
);
1134 #if defined (USE_XAW)
1135 if (lw_xaw_widget_p (instance
->widget
))
1137 XtRealizeWidget (XtParent (instance
->widget
));
1138 XtRealizeWidget (instance
->widget
);
1139 xaw_pop_instance (instance
, up
);
1146 lw_pop_up_all_widgets (LWLIB_ID id
)
1148 lw_pop_all_widgets (id
, True
);
1152 lw_pop_down_all_widgets (LWLIB_ID id
)
1154 lw_pop_all_widgets (id
, False
);
1158 lw_popup_menu (Widget widget
, XEvent
*event
)
1160 #if defined (USE_LUCID)
1161 if (lw_lucid_widget_p (widget
))
1162 xlw_popup_menu (widget
, event
);
1164 #if defined (USE_MOTIF)
1165 if (lw_motif_widget_p (widget
))
1166 xm_popup_menu (widget
, event
);
1168 #if defined (USE_XAW)
1169 if (lw_xaw_widget_p (widget
))
1170 xaw_popup_menu (widget
, event
);
1174 \f/* get the values back */
1176 get_one_value (widget_instance
*instance
, widget_value
*val
)
1178 Widget widget
= name_to_widget (instance
, val
->name
);
1182 #if defined (USE_LUCID)
1183 if (lw_lucid_widget_p (instance
->widget
))
1184 xlw_update_one_value (instance
, widget
, val
);
1186 #if defined (USE_MOTIF)
1187 if (lw_motif_widget_p (instance
->widget
))
1188 xm_update_one_value (instance
, widget
, val
);
1190 #if defined (USE_XAW)
1191 if (lw_xaw_widget_p (instance
->widget
))
1192 xaw_update_one_value (instance
, widget
, val
);
1201 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1203 widget_info
* info
= get_widget_info (id
, False
);
1204 widget_instance
* instance
;
1206 Boolean result
= False
;
1211 instance
= info
->instances
;
1215 for (val
= val_out
; val
; val
= val
->next
)
1216 if (get_one_value (instance
, val
))
1223 lw_get_all_values (LWLIB_ID id
)
1225 widget_info
* info
= get_widget_info (id
, False
);
1226 widget_value
* val
= info
->val
;
1227 if (lw_get_some_values (id
, val
))
1233 /* internal function used by the library dependent implementation to get the
1234 widget_value for a given widget in an instance */
1236 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1238 char* name
= XtName (w
);
1240 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1241 if (!strcmp (cur
->name
, name
))
1246 \f/* update other instances value when one thing changed */
1248 /* To forbid recursive calls */
1249 static Boolean lwlib_updating
;
1251 /* This function can be used as a an XtCallback for the widgets that get
1252 modified to update other instances of the widgets. Closure should be the
1255 lw_internal_update_other_instances (Widget widget
, XtPointer closure
, XtPointer call_data
)
1257 widget_instance
* instance
= (widget_instance
*)closure
;
1258 char* name
= XtName (widget
);
1260 widget_instance
* cur
;
1263 /* Avoid possibly infinite recursion. */
1267 /* protect against the widget being destroyed */
1268 if (XtWidgetBeingDestroyedP (widget
))
1271 /* Return immediately if there are no other instances */
1272 info
= instance
->info
;
1273 if (!info
->instances
->next
)
1276 lwlib_updating
= True
;
1278 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1280 if (val
&& get_one_value (instance
, val
))
1281 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1282 if (cur
!= instance
)
1283 set_one_value (cur
, val
, True
);
1285 lwlib_updating
= False
;
1292 lw_get_widget_id (Widget w
)
1294 widget_instance
* instance
= get_widget_instance (w
, False
);
1296 return instance
? instance
->info
->id
: 0;
1299 \f/* set the keyboard focus */
1301 lw_set_keyboard_focus (Widget parent
, Widget w
)
1303 #if defined (USE_MOTIF)
1304 xm_set_keyboard_focus (parent
, w
);
1306 XtSetKeyboardFocus (parent
, w
);
1313 show_one_widget_busy (Widget w
, Boolean flag
)
1315 show_one_widget_busy (w
, flag
)
1320 Pixel foreground
= 0;
1321 Pixel background
= 1;
1322 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1323 if (!widget_to_invert
)
1324 widget_to_invert
= w
;
1326 XtVaGetValues (widget_to_invert
,
1327 XtNforeground
, &foreground
,
1328 XtNbackground
, &background
,
1330 XtVaSetValues (widget_to_invert
,
1331 XtNforeground
, background
,
1332 XtNbackground
, foreground
,
1338 lw_show_busy (Widget w
, Boolean busy
)
1340 lw_show_busy (w
, busy
)
1345 widget_instance
* instance
= get_widget_instance (w
, False
);
1347 widget_instance
* next
;
1351 info
= instance
->info
;
1352 if (info
->busy
!= busy
)
1354 for (next
= info
->instances
; next
; next
= next
->next
)
1356 show_one_widget_busy (next
->widget
, busy
);
1362 /* This hack exists because Lucid/Athena need to execute the strange
1363 function below to support geometry management. */
1366 lw_refigure_widget (Widget w
, Boolean doit
)
1368 lw_refigure_widget (w
, doit
)
1373 #if defined (USE_XAW)
1374 XawPanedSetRefigureMode (w
, doit
);
1376 #if defined (USE_MOTIF)
1380 XtUnmanageChild (w
);
1384 /* Toolkit independent way of determining if an event window is in the
1387 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1389 return menubar_widget
1390 #if defined (USE_LUCID)
1391 && XtWindow (menubar_widget
) == win
;
1393 #if defined (USE_MOTIF)
1394 && ((XtWindow (menubar_widget
) == win
)
1395 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1396 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1397 == menubar_widget
)));
1401 /* Motif hack to set the main window areas. */
1403 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1405 #if defined (USE_MOTIF)
1406 xm_set_main_areas (parent
, menubar
, work_area
);
1410 /* Manage resizing for Motif. This disables resizing when the menubar
1411 is about to be modified. */
1414 lw_allow_resizing (Widget w
, Boolean flag
)
1416 lw_allow_resizing (w
, flag
)
1421 #if defined (USE_MOTIF)
1422 xm_manage_resizing (w
, flag
);
1427 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1428 set to an appropriate enumerator of type enum menu_separator.
1429 MOTIF_P non-zero means map separator types not supported by Motif
1430 to similar ones that are supported. */
1433 lw_separator_p (char *label
, enum menu_separator
*type
, int motif_p
)
1435 int separator_p
= 0;
1437 if (strlen (label
) >= 3
1438 && memcmp (label
, "--:", 3) == 0)
1440 static struct separator_table
1443 enum menu_separator type
;
1447 {"space", SEPARATOR_NO_LINE
},
1448 {"noLine", SEPARATOR_NO_LINE
},
1449 {"singleLine", SEPARATOR_SINGLE_LINE
},
1450 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1451 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1452 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1453 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1454 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1455 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1456 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1457 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1458 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1459 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1460 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1467 for (i
= 0; separator_names
[i
].name
; ++i
)
1468 if (strcmp (label
, separator_names
[i
].name
) == 0)
1471 *type
= separator_names
[i
].type
;
1473 /* If separator type is not supported under Motif,
1474 use a similar one. */
1475 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1480 else if (strlen (label
) > 3
1481 && memcmp (label
, "--", 2) == 0
1484 /* Alternative, more Emacs-style names. */
1485 static struct separator_table
1488 enum menu_separator type
;
1492 {"space", SEPARATOR_NO_LINE
},
1493 {"no-line", SEPARATOR_NO_LINE
},
1494 {"single-line", SEPARATOR_SINGLE_LINE
},
1495 {"double-line", SEPARATOR_DOUBLE_LINE
},
1496 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1497 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1498 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1499 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1500 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1501 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1502 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1503 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1504 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1505 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1512 for (i
= 0; separator_names
[i
].name
; ++i
)
1513 if (strcmp (label
, separator_names
[i
].name
) == 0)
1516 *type
= separator_names
[i
].type
;
1518 /* If separator type is not supported under Motif,
1519 use a similar one. */
1520 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1527 /* Old-style separator, maybe. It's a separator if it contains
1529 while (*label
== '-')
1531 separator_p
= *label
== 0;
1532 *type
= SEPARATOR_SHADOW_ETCHED_IN
;
1538 /* arch-tag: 3d730f36-a441-4a71-9971-48ef3b5a4d9f
1539 (do not change this comment) */