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., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, 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 */
48 #if defined (USE_OLIT)
49 #include "lwlib-Xol.h"
52 #include <X11/Xaw/Paned.h>
53 #include "lwlib-Xaw.h"
56 #if !defined (USE_LUCID) && !defined (USE_MOTIF) && !defined (USE_OLIT)
57 ERROR
! At least one of USE_LUCID
, USE_MOTIF
or USE_OLIT must be defined
.
60 #if defined (USE_MOTIF) && defined (USE_OLIT)
61 ERROR
! no more than one of USE_MOTIF
and USE_OLIT may be defined
.
65 #define max(x, y) ((x) > (y) ? (x) : (y))
68 /* List of all widgets managed by the library. */
70 all_widget_info
= NULL
;
73 char *lwlib_toolkit_type
= "motif";
75 char *lwlib_toolkit_type
= "lucid";
78 static widget_value
*merge_widget_value
P_ ((widget_value
*,
81 static void instantiate_widget_instance
P_ ((widget_instance
*));
82 static int my_strcasecmp
P_ ((char *, char *));
83 static void safe_free_str
P_ ((char *));
84 static void free_widget_value_tree
P_ ((widget_value
*));
85 static widget_value
*copy_widget_value_tree
P_ ((widget_value
*,
87 static widget_info
*allocate_widget_info
P_ ((char *, char *, LWLIB_ID
,
89 lw_callback
, lw_callback
,
90 lw_callback
, lw_callback
));
91 static void free_widget_info
P_ ((widget_info
*));
92 static void mark_widget_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
93 static widget_instance
*allocate_widget_instance
P_ ((widget_info
*,
95 static void free_widget_instance
P_ ((widget_instance
*));
96 static widget_info
*get_widget_info
P_ ((LWLIB_ID
, Boolean
));
97 static widget_instance
*get_widget_instance
P_ ((Widget
, Boolean
));
98 static widget_instance
*find_instance
P_ ((LWLIB_ID
, Widget
, Boolean
));
99 static Boolean safe_strcmp
P_ ((char *, char *));
100 static Widget name_to_widget
P_ ((widget_instance
*, char *));
101 static void set_one_value
P_ ((widget_instance
*, widget_value
*, Boolean
));
102 static void update_one_widget_instance
P_ ((widget_instance
*, Boolean
));
103 static void update_all_widget_values
P_ ((widget_info
*, Boolean
));
104 static void initialize_widget_instance
P_ ((widget_instance
*));
105 static widget_creation_function find_in_table
P_ ((char *, widget_creation_entry
*));
106 static Boolean dialog_spec_p
P_ ((char *));
107 static void instantiate_widget_instance
P_ ((widget_instance
*));
108 static void destroy_one_instance
P_ ((widget_instance
*));
109 static void lw_pop_all_widgets
P_ ((LWLIB_ID
, Boolean
));
110 static Boolean get_one_value
P_ ((widget_instance
*, widget_value
*));
111 static void show_one_widget_busy
P_ ((Widget
, Boolean
));
114 lwlib_memset (address
, value
, length
)
121 for (i
= 0; i
< length
; i
++)
126 lwlib_bcopy (from
, to
, length
)
133 for (i
= 0; i
< length
; i
++)
136 \f/* utility functions for widget_instance and widget_info */
143 result
= (char *) malloc (strlen (s
) + 1);
150 /* Like strcmp but ignore differences in case. */
153 my_strcasecmp (s1
, s2
)
165 return (c1
> c2
? 1 : -1);
178 static widget_value
*widget_value_free_list
= 0;
179 static int malloc_cpt
= 0;
182 malloc_widget_value ()
185 if (widget_value_free_list
)
187 wv
= widget_value_free_list
;
188 widget_value_free_list
= wv
->free_list
;
193 wv
= (widget_value
*) malloc (sizeof (widget_value
));
196 lwlib_memset (wv
, 0, sizeof (widget_value
));
200 /* this is analogous to free(). It frees only what was allocated
201 by malloc_widget_value(), and no substructures.
204 free_widget_value (wv
)
212 /* When the number of already allocated cells is too big,
219 wv
->free_list
= widget_value_free_list
;
220 widget_value_free_list
= wv
;
225 free_widget_value_tree (wv
)
231 if (wv
->name
) free (wv
->name
);
232 if (wv
->value
) free (wv
->value
);
233 if (wv
->key
) free (wv
->key
);
235 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
237 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
239 XtFree (wv
->toolkit_data
);
240 wv
->toolkit_data
= (void *) 0xDEADBEEF;
243 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
245 free_widget_value_tree (wv
->contents
);
246 wv
->contents
= (widget_value
*) 0xDEADBEEF;
250 free_widget_value_tree (wv
->next
);
251 wv
->next
= (widget_value
*) 0xDEADBEEF;
253 free_widget_value (wv
);
256 static widget_value
*
257 copy_widget_value_tree (val
, change
)
265 if (val
== (widget_value
*) 1)
268 copy
= malloc_widget_value ();
269 copy
->name
= safe_strdup (val
->name
);
270 copy
->value
= safe_strdup (val
->value
);
271 copy
->key
= safe_strdup (val
->key
);
272 copy
->help
= val
->help
;
273 copy
->enabled
= val
->enabled
;
274 copy
->button_type
= val
->button_type
;
275 copy
->selected
= val
->selected
;
276 copy
->edited
= False
;
277 copy
->change
= change
;
278 copy
->this_one_change
= change
;
279 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
280 copy
->call_data
= val
->call_data
;
281 copy
->next
= copy_widget_value_tree (val
->next
, change
);
282 copy
->toolkit_data
= NULL
;
283 copy
->free_toolkit_data
= False
;
288 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
289 selection_cb
, post_activate_cb
, highlight_cb
)
294 lw_callback pre_activate_cb
;
295 lw_callback selection_cb
;
296 lw_callback post_activate_cb
;
297 lw_callback highlight_cb
;
299 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
300 info
->type
= safe_strdup (type
);
301 info
->name
= safe_strdup (name
);
303 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
305 info
->pre_activate_cb
= pre_activate_cb
;
306 info
->selection_cb
= selection_cb
;
307 info
->post_activate_cb
= post_activate_cb
;
308 info
->highlight_cb
= highlight_cb
;
309 info
->instances
= NULL
;
311 info
->next
= all_widget_info
;
312 all_widget_info
= info
;
318 free_widget_info (info
)
321 safe_free_str (info
->type
);
322 safe_free_str (info
->name
);
323 free_widget_value_tree (info
->val
);
324 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
329 mark_widget_destroyed (widget
, closure
, call_data
)
334 widget_instance
* instance
= (widget_instance
*)closure
;
336 /* be very conservative */
337 if (instance
->widget
== widget
)
338 instance
->widget
= NULL
;
341 static widget_instance
*
342 allocate_widget_instance (info
, parent
, pop_up_p
)
347 widget_instance
* instance
=
348 (widget_instance
*)malloc (sizeof (widget_instance
));
349 bzero (instance
, sizeof *instance
);
350 instance
->parent
= parent
;
351 instance
->pop_up_p
= pop_up_p
;
352 instance
->info
= info
;
353 instance
->next
= info
->instances
;
354 info
->instances
= instance
;
356 instantiate_widget_instance (instance
);
358 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
359 mark_widget_destroyed
, (XtPointer
)instance
);
364 free_widget_instance (instance
)
365 widget_instance
* instance
;
367 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
372 get_widget_info (id
, remove_p
)
378 for (prev
= NULL
, info
= all_widget_info
;
380 prev
= info
, info
= info
->next
)
386 prev
->next
= info
->next
;
388 all_widget_info
= info
->next
;
395 /* Internal function used by the library dependent implementation to get the
396 widget_value for a given widget in an instance */
398 lw_get_widget_info (id
)
401 return get_widget_info (id
, 0);
404 static widget_instance
*
405 get_widget_instance (widget
, remove_p
)
410 widget_instance
* instance
;
411 widget_instance
* prev
;
412 for (info
= all_widget_info
; info
; info
= info
->next
)
413 for (prev
= NULL
, instance
= info
->instances
;
415 prev
= instance
, instance
= instance
->next
)
416 if (instance
->widget
== widget
)
421 prev
->next
= instance
->next
;
423 info
->instances
= instance
->next
;
427 return (widget_instance
*) 0;
430 /* Value is a pointer to the widget_instance corresponding to
431 WIDGET, or null if WIDGET is not a lwlib widget. */
434 lw_get_widget_instance (widget
)
437 return get_widget_instance (widget
, False
);
440 static widget_instance
*
441 find_instance (id
, parent
, pop_up_p
)
446 widget_info
* info
= get_widget_info (id
, False
);
447 widget_instance
* instance
;
450 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
451 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
458 /* utility function for widget_value */
464 if (!!s1
^ !!s2
) return True
;
465 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
470 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
471 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
473 (oc == NO_CHANGE ? "none" : \
474 (oc == INVISIBLE_CHANGE ? "invisible" : \
475 (oc == VISIBLE_CHANGE ? "visible" : \
476 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
478 (nc == NO_CHANGE ? "none" : \
479 (nc == INVISIBLE_CHANGE ? "invisible" : \
480 (nc == VISIBLE_CHANGE ? "visible" : \
481 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
484 # define EXPLAIN(name, oc, nc, desc, a1, a2)
488 static widget_value
*
489 merge_widget_value (val1
, val2
, level
, change_p
)
495 change_type change
, this_one_change
;
496 widget_value
* merged_next
;
497 widget_value
* merged_contents
;
504 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
512 free_widget_value_tree (val1
);
518 if (safe_strcmp (val1
->name
, val2
->name
))
520 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
521 val1
->name
, val2
->name
);
522 change
= max (change
, STRUCTURAL_CHANGE
);
523 safe_free_str (val1
->name
);
524 val1
->name
= safe_strdup (val2
->name
);
526 if (safe_strcmp (val1
->value
, val2
->value
))
528 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
529 val1
->value
, val2
->value
);
530 change
= max (change
, VISIBLE_CHANGE
);
531 safe_free_str (val1
->value
);
532 val1
->value
= safe_strdup (val2
->value
);
534 if (safe_strcmp (val1
->key
, val2
->key
))
536 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
537 val1
->key
, val2
->key
);
538 change
= max (change
, VISIBLE_CHANGE
);
539 safe_free_str (val1
->key
);
540 val1
->key
= safe_strdup (val2
->key
);
542 if (! EQ (val1
->help
, val2
->help
))
544 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
545 val1
->help
, val2
->help
);
546 change
= max (change
, VISIBLE_CHANGE
);
547 val1
->help
= val2
->help
;
549 if (val1
->enabled
!= val2
->enabled
)
551 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
552 val1
->enabled
, val2
->enabled
);
553 change
= max (change
, VISIBLE_CHANGE
);
554 val1
->enabled
= val2
->enabled
;
556 if (val1
->button_type
!= val2
->button_type
)
558 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
559 val1
->button_type
, val2
->button_type
);
560 change
= max (change
, VISIBLE_CHANGE
);
561 val1
->button_type
= val2
->button_type
;
563 if (val1
->selected
!= val2
->selected
)
565 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
566 val1
->selected
, val2
->selected
);
567 change
= max (change
, VISIBLE_CHANGE
);
568 val1
->selected
= val2
->selected
;
570 if (val1
->call_data
!= val2
->call_data
)
572 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
573 val1
->call_data
, val2
->call_data
);
574 change
= max (change
, INVISIBLE_CHANGE
);
575 val1
->call_data
= val2
->call_data
;
581 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
584 if (val1
->contents
&& !merged_contents
)
586 /* This used to say INVISIBLE_CHANGE,
587 but it is visible and vitally important when
588 the contents of the menu bar itself are entirely deleted.
590 But maybe it doesn't matter. This fails to fix the bug. */
591 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
593 change
= max (change
, STRUCTURAL_CHANGE
);
595 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
597 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
599 change
= max (change
, INVISIBLE_CHANGE
);
600 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
602 change
= max (merged_contents
->change
, change
);
607 val1
->contents
= merged_contents
;
610 this_one_change
= change
;
612 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
614 if (val1
->next
&& !merged_next
)
616 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
618 change
= max (change
, STRUCTURAL_CHANGE
);
620 else if (merged_next
)
622 if (merged_next
->change
)
623 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
625 change
= max (change
, merged_next
->change
);
628 val1
->next
= merged_next
;
630 val1
->this_one_change
= this_one_change
;
631 val1
->change
= change
;
633 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
636 if (val1
->free_toolkit_data
)
637 XtFree (val1
->toolkit_data
);
638 val1
->toolkit_data
= NULL
;
645 /* modifying the widgets */
647 name_to_widget (instance
, name
)
648 widget_instance
* instance
;
651 Widget widget
= NULL
;
653 if (!instance
->widget
)
656 if (!strcmp (XtName (instance
->widget
), name
))
657 widget
= instance
->widget
;
660 int length
= strlen (name
) + 2;
661 char* real_name
= (char *) xmalloc (length
);
663 strcpy (real_name
+ 1, name
);
665 widget
= XtNameToWidget (instance
->widget
, real_name
);
673 set_one_value (instance
, val
, deep_p
)
674 widget_instance
* instance
;
678 Widget widget
= name_to_widget (instance
, val
->name
);
682 #if defined (USE_LUCID)
683 if (lw_lucid_widget_p (instance
->widget
))
684 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
686 #if defined (USE_MOTIF)
687 if (lw_motif_widget_p (instance
->widget
))
688 xm_update_one_widget (instance
, widget
, val
, deep_p
);
690 #if defined (USE_OLIT)
691 if (lw_olit_widget_p (instance
->widget
))
692 xol_update_one_widget (instance
, widget
, val
, deep_p
);
694 #if defined (USE_XAW)
695 if (lw_xaw_widget_p (instance
->widget
))
696 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
702 update_one_widget_instance (instance
, deep_p
)
703 widget_instance
* instance
;
708 if (!instance
->widget
)
709 /* the widget was destroyed */
712 for (val
= instance
->info
->val
; val
; val
= val
->next
)
713 if (val
->change
!= NO_CHANGE
)
714 set_one_value (instance
, val
, deep_p
);
718 update_all_widget_values (info
, deep_p
)
722 widget_instance
* instance
;
725 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
726 update_one_widget_instance (instance
, deep_p
);
728 for (val
= info
->val
; val
; val
= val
->next
)
729 val
->change
= NO_CHANGE
;
733 lw_modify_all_widgets (id
, val
, deep_p
)
738 widget_info
* info
= get_widget_info (id
, False
);
739 widget_value
* new_val
;
740 widget_value
* next_new_val
;
750 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
752 next_new_val
= new_val
->next
;
753 new_val
->next
= NULL
;
755 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
756 if (!strcmp (cur
->name
, new_val
->name
))
761 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
764 prev
->next
= cur
? cur
: next
;
766 info
->val
= cur
? cur
: next
;
773 /* Could not find it, add it */
775 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
777 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
780 new_val
->next
= next_new_val
;
783 update_all_widget_values (info
, deep_p
);
788 /* creating the widgets */
791 initialize_widget_instance (instance
)
792 widget_instance
* instance
;
796 for (val
= instance
->info
->val
; val
; val
= val
->next
)
797 val
->change
= STRUCTURAL_CHANGE
;
799 update_one_widget_instance (instance
, True
);
801 for (val
= instance
->info
->val
; val
; val
= val
->next
)
802 val
->change
= NO_CHANGE
;
806 static widget_creation_function
807 find_in_table (type
, table
)
809 widget_creation_entry
* table
;
811 widget_creation_entry
* cur
;
812 for (cur
= table
; cur
->type
; cur
++)
813 if (!my_strcasecmp (type
, cur
->type
))
814 return cur
->function
;
822 /* return True if name matches [EILPQeilpq][1-9][Bb] or
823 [EILPQeilpq][1-9][Bb][Rr][1-9] */
829 case 'E': case 'I': case 'L': case 'P': case 'Q':
830 case 'e': case 'i': case 'l': case 'p': case 'q':
831 if (name
[1] >= '0' && name
[1] <= '9')
833 if (name
[2] != 'B' && name
[2] != 'b')
837 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
839 if ((name
[3] == 'R' || name
[3] == 'r')
840 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
853 instantiate_widget_instance (instance
)
854 widget_instance
* instance
;
856 widget_creation_function function
= NULL
;
858 #if defined (USE_LUCID)
860 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
862 #if defined(USE_MOTIF)
864 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
866 #if defined (USE_OLIT)
868 function
= find_in_table (instance
->info
->type
, xol_creation_table
);
870 #if defined (USE_XAW)
872 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
877 if (dialog_spec_p (instance
->info
->type
))
879 #if defined (USE_LUCID)
882 #if defined(USE_MOTIF)
884 function
= xm_create_dialog
;
886 #if defined (USE_XAW)
888 function
= xaw_create_dialog
;
890 #if defined (USE_OLIT)
898 printf ("No creation function for widget type %s\n",
899 instance
->info
->type
);
903 instance
->widget
= (*function
) (instance
);
905 if (!instance
->widget
)
908 /* XtRealizeWidget (instance->widget);*/
912 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
913 selection_cb
, post_activate_cb
, highlight_cb
)
918 lw_callback pre_activate_cb
;
919 lw_callback selection_cb
;
920 lw_callback post_activate_cb
;
921 lw_callback highlight_cb
;
923 if (!get_widget_info (id
, False
))
924 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
925 post_activate_cb
, highlight_cb
);
929 lw_get_widget (id
, parent
, pop_up_p
)
934 widget_instance
* instance
;
936 instance
= find_instance (id
, parent
, pop_up_p
);
937 return instance
? instance
->widget
: NULL
;
941 lw_make_widget (id
, parent
, pop_up_p
)
946 widget_instance
* instance
;
949 instance
= find_instance (id
, parent
, pop_up_p
);
952 info
= get_widget_info (id
, False
);
955 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
956 initialize_widget_instance (instance
);
958 if (!instance
->widget
)
960 return instance
->widget
;
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
;
977 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
978 post_activate_cb
, highlight_cb
);
979 return lw_make_widget (id
, parent
, pop_up_p
);
983 /* destroying the widgets */
985 destroy_one_instance (instance
)
986 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_OLIT)
1016 if (lw_olit_widget_p (instance
->widget
))
1017 xol_destroy_instance (instance
);
1020 #if defined (USE_XAW)
1021 if (lw_xaw_widget_p (instance
->widget
))
1022 xaw_destroy_instance (instance
);
1025 /* do not remove the empty statement */
1029 free_widget_instance (instance
);
1033 lw_destroy_widget (w
)
1036 widget_instance
* instance
= get_widget_instance (w
, True
);
1040 widget_info
*info
= instance
->info
;
1041 /* instance has already been removed from the list; free it */
1042 destroy_one_instance (instance
);
1043 /* if there are no instances left, free the info too */
1044 if (!info
->instances
)
1045 lw_destroy_all_widgets (info
->id
);
1050 lw_destroy_all_widgets (id
)
1053 widget_info
* info
= get_widget_info (id
, True
);
1054 widget_instance
* instance
;
1055 widget_instance
* next
;
1059 for (instance
= info
->instances
; instance
; )
1061 next
= instance
->next
;
1062 destroy_one_instance (instance
);
1065 free_widget_info (info
);
1070 lw_destroy_everything ()
1072 while (all_widget_info
)
1073 lw_destroy_all_widgets (all_widget_info
->id
);
1077 lw_destroy_all_pop_ups ()
1081 widget_instance
* instance
;
1083 for (info
= all_widget_info
; info
; info
= next
)
1086 instance
= info
->instances
;
1087 if (instance
&& instance
->pop_up_p
)
1088 lw_destroy_all_widgets (info
->id
);
1093 extern Widget
first_child (/* Widget */); /* garbage */
1097 lw_raise_all_pop_up_widgets ()
1100 widget_instance
* instance
;
1101 Widget result
= NULL
;
1103 for (info
= all_widget_info
; info
; info
= info
->next
)
1104 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1105 if (instance
->pop_up_p
)
1107 Widget widget
= instance
->widget
;
1110 if (XtIsManaged (widget
)
1112 /* What a complete load of crap!!!!
1113 When a dialogShell is on the screen, it is not managed!
1115 || (lw_motif_widget_p (instance
->widget
) &&
1116 XtIsManaged (first_child (widget
)))
1122 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1130 lw_pop_all_widgets (id
, up
)
1134 widget_info
* info
= get_widget_info (id
, False
);
1135 widget_instance
* instance
;
1138 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1139 if (instance
->pop_up_p
&& instance
->widget
)
1141 #if defined (USE_LUCID)
1142 if (lw_lucid_widget_p (instance
->widget
))
1144 XtRealizeWidget (instance
->widget
);
1145 xlw_pop_instance (instance
, up
);
1148 #if defined (USE_MOTIF)
1149 if (lw_motif_widget_p (instance
->widget
))
1151 XtRealizeWidget (instance
->widget
);
1152 xm_pop_instance (instance
, up
);
1155 #if defined (USE_OLIT)
1156 if (lw_olit_widget_p (instance
->widget
))
1158 XtRealizeWidget (instance
->widget
);
1159 xol_pop_instance (instance
, up
);
1162 #if defined (USE_XAW)
1163 if (lw_xaw_widget_p (instance
->widget
))
1165 XtRealizeWidget (XtParent (instance
->widget
));
1166 XtRealizeWidget (instance
->widget
);
1167 xaw_pop_instance (instance
, up
);
1174 lw_pop_up_all_widgets (id
)
1177 lw_pop_all_widgets (id
, True
);
1181 lw_pop_down_all_widgets (id
)
1184 lw_pop_all_widgets (id
, False
);
1188 lw_popup_menu (widget
, event
)
1192 #if defined (USE_LUCID)
1193 if (lw_lucid_widget_p (widget
))
1194 xlw_popup_menu (widget
, event
);
1196 #if defined (USE_MOTIF)
1197 if (lw_motif_widget_p (widget
))
1198 xm_popup_menu (widget
, event
);
1200 #if defined (USE_OLIT)
1201 if (lw_olit_widget_p (widget
))
1202 xol_popup_menu (widget
, event
);
1204 #if defined (USE_XAW)
1205 if (lw_xaw_widget_p (widget
))
1206 xaw_popup_menu (widget
, event
);
1210 \f/* get the values back */
1212 get_one_value (instance
, val
)
1213 widget_instance
* instance
;
1216 Widget widget
= name_to_widget (instance
, val
->name
);
1220 #if defined (USE_LUCID)
1221 if (lw_lucid_widget_p (instance
->widget
))
1222 xlw_update_one_value (instance
, widget
, val
);
1224 #if defined (USE_MOTIF)
1225 if (lw_motif_widget_p (instance
->widget
))
1226 xm_update_one_value (instance
, widget
, val
);
1228 #if defined (USE_OLIT)
1229 if (lw_olit_widget_p (instance
->widget
))
1230 xol_update_one_value (instance
, widget
, val
);
1232 #if defined (USE_XAW)
1233 if (lw_xaw_widget_p (instance
->widget
))
1234 xaw_update_one_value (instance
, widget
, val
);
1243 lw_get_some_values (id
, val_out
)
1245 widget_value
* val_out
;
1247 widget_info
* info
= get_widget_info (id
, False
);
1248 widget_instance
* instance
;
1250 Boolean result
= False
;
1255 instance
= info
->instances
;
1259 for (val
= val_out
; val
; val
= val
->next
)
1260 if (get_one_value (instance
, val
))
1267 lw_get_all_values (id
)
1270 widget_info
* info
= get_widget_info (id
, False
);
1271 widget_value
* val
= info
->val
;
1272 if (lw_get_some_values (id
, val
))
1278 /* internal function used by the library dependent implementation to get the
1279 widget_value for a given widget in an instance */
1281 lw_get_widget_value_for_widget (instance
, w
)
1282 widget_instance
* instance
;
1285 char* name
= XtName (w
);
1287 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1288 if (!strcmp (cur
->name
, name
))
1293 \f/* update other instances value when one thing changed */
1295 /* To forbid recursive calls */
1296 static Boolean lwlib_updating
;
1298 /* This function can be used as a an XtCallback for the widgets that get
1299 modified to update other instances of the widgets. Closure should be the
1302 lw_internal_update_other_instances (widget
, closure
, call_data
)
1305 XtPointer call_data
;
1307 widget_instance
* instance
= (widget_instance
*)closure
;
1308 char* name
= XtName (widget
);
1310 widget_instance
* cur
;
1313 /* Avoid possibly infinite recursion. */
1317 /* protect against the widget being destroyed */
1318 if (XtWidgetBeingDestroyedP (widget
))
1321 /* Return immediately if there are no other instances */
1322 info
= instance
->info
;
1323 if (!info
->instances
->next
)
1326 lwlib_updating
= True
;
1328 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1330 if (val
&& get_one_value (instance
, val
))
1331 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1332 if (cur
!= instance
)
1333 set_one_value (cur
, val
, True
);
1335 lwlib_updating
= False
;
1342 lw_get_widget_id (w
)
1345 widget_instance
* instance
= get_widget_instance (w
, False
);
1347 return instance
? instance
->info
->id
: 0;
1350 \f/* set the keyboard focus */
1352 lw_set_keyboard_focus (parent
, w
)
1356 #if defined (USE_MOTIF)
1357 xm_set_keyboard_focus (parent
, w
);
1359 XtSetKeyboardFocus (parent
, w
);
1365 show_one_widget_busy (w
, flag
)
1369 Pixel foreground
= 0;
1370 Pixel background
= 1;
1371 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1372 if (!widget_to_invert
)
1373 widget_to_invert
= w
;
1375 XtVaGetValues (widget_to_invert
,
1376 XtNforeground
, &foreground
,
1377 XtNbackground
, &background
,
1379 XtVaSetValues (widget_to_invert
,
1380 XtNforeground
, background
,
1381 XtNbackground
, foreground
,
1386 lw_show_busy (w
, busy
)
1390 widget_instance
* instance
= get_widget_instance (w
, False
);
1392 widget_instance
* next
;
1396 info
= instance
->info
;
1397 if (info
->busy
!= busy
)
1399 for (next
= info
->instances
; next
; next
= next
->next
)
1401 show_one_widget_busy (next
->widget
, busy
);
1407 /* This hack exists because Lucid/Athena need to execute the strange
1408 function below to support geometry management. */
1410 lw_refigure_widget (w
, doit
)
1414 #if defined (USE_XAW)
1415 XawPanedSetRefigureMode (w
, doit
);
1417 #if defined (USE_MOTIF)
1421 XtUnmanageChild (w
);
1425 /* Toolkit independent way of determining if an event window is in the
1428 lw_window_is_in_menubar (win
, menubar_widget
)
1430 Widget menubar_widget
;
1432 return menubar_widget
1433 #if defined (USE_LUCID)
1434 && XtWindow (menubar_widget
) == win
;
1436 #if defined (USE_MOTIF)
1437 && ((XtWindow (menubar_widget
) == win
)
1438 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1439 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1440 == menubar_widget
)));
1444 /* Motif hack to set the main window areas. */
1446 lw_set_main_areas (parent
, menubar
, work_area
)
1451 #if defined (USE_MOTIF)
1452 xm_set_main_areas (parent
, menubar
, work_area
);
1456 /* Manage resizing for Motif. This disables resizing when the menubar
1457 is about to be modified. */
1459 lw_allow_resizing (w
, flag
)
1463 #if defined (USE_MOTIF)
1464 xm_manage_resizing (w
, flag
);
1469 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1470 set to an appropriate enumerator of type enum menu_separator.
1471 MOTIF_P non-zero means map separator types not supported by Motif
1472 to similar ones that are supported. */
1475 lw_separator_p (label
, type
, motif_p
)
1477 enum menu_separator
*type
;
1480 int separator_p
= 0;
1482 if (strlen (label
) >= 3
1483 && bcmp (label
, "--:", 3) == 0)
1485 static struct separator_table
1488 enum menu_separator type
;
1492 {"space", SEPARATOR_NO_LINE
},
1493 {"noLine", SEPARATOR_NO_LINE
},
1494 {"singleLine", SEPARATOR_SINGLE_LINE
},
1495 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1496 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1497 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1498 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1499 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1500 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1501 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1502 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1503 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1504 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1505 {"shadowDoubleEtchedOutDash", 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
)
1525 else if (strlen (label
) > 3
1526 && bcmp (label
, "--", 2) == 0
1529 /* Alternative, more Emacs-style names. */
1530 static struct separator_table
1533 enum menu_separator type
;
1537 {"space", SEPARATOR_NO_LINE
},
1538 {"no-line", SEPARATOR_NO_LINE
},
1539 {"single-line", SEPARATOR_SINGLE_LINE
},
1540 {"double-line", SEPARATOR_DOUBLE_LINE
},
1541 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1542 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1543 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1544 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1545 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1546 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1547 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1548 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1549 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1550 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1557 for (i
= 0; separator_names
[i
].name
; ++i
)
1558 if (strcmp (label
, separator_names
[i
].name
) == 0)
1561 *type
= separator_names
[i
].type
;
1563 /* If separator type is not supported under Motif,
1564 use a similar one. */
1565 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1572 /* Old-style separator, maybe. It's a separator if it contains
1574 while (*label
== '-')
1576 separator_p
= *label
== 0;
1577 *type
= SEPARATOR_SHADOW_ETCHED_IN
;