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 destroy_one_instance
P_ ((widget_instance
*));
108 static void lw_pop_all_widgets
P_ ((LWLIB_ID
, Boolean
));
109 static Boolean get_one_value
P_ ((widget_instance
*, widget_value
*));
110 static void show_one_widget_busy
P_ ((Widget
, Boolean
));
113 lwlib_memset (address
, value
, length
)
120 for (i
= 0; i
< length
; i
++)
125 lwlib_bcopy (from
, to
, length
)
132 for (i
= 0; i
< length
; i
++)
135 \f/* utility functions for widget_instance and widget_info */
142 result
= (char *) malloc (strlen (s
) + 1);
149 /* Like strcmp but ignore differences in case. */
152 my_strcasecmp (s1
, s2
)
164 return (c1
> c2
? 1 : -1);
177 static widget_value
*widget_value_free_list
= 0;
178 static int malloc_cpt
= 0;
181 malloc_widget_value ()
184 if (widget_value_free_list
)
186 wv
= widget_value_free_list
;
187 widget_value_free_list
= wv
->free_list
;
192 wv
= (widget_value
*) malloc (sizeof (widget_value
));
195 lwlib_memset (wv
, 0, sizeof (widget_value
));
199 /* this is analogous to free(). It frees only what was allocated
200 by malloc_widget_value(), and no substructures.
203 free_widget_value (wv
)
211 /* When the number of already allocated cells is too big,
218 wv
->free_list
= widget_value_free_list
;
219 widget_value_free_list
= wv
;
224 free_widget_value_tree (wv
)
230 if (wv
->name
) free (wv
->name
);
231 if (wv
->value
) free (wv
->value
);
232 if (wv
->key
) free (wv
->key
);
234 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
236 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
238 XtFree (wv
->toolkit_data
);
239 wv
->toolkit_data
= (void *) 0xDEADBEEF;
242 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
244 free_widget_value_tree (wv
->contents
);
245 wv
->contents
= (widget_value
*) 0xDEADBEEF;
249 free_widget_value_tree (wv
->next
);
250 wv
->next
= (widget_value
*) 0xDEADBEEF;
252 free_widget_value (wv
);
255 static widget_value
*
256 copy_widget_value_tree (val
, change
)
264 if (val
== (widget_value
*) 1)
267 copy
= malloc_widget_value ();
268 copy
->name
= safe_strdup (val
->name
);
269 copy
->value
= safe_strdup (val
->value
);
270 copy
->key
= safe_strdup (val
->key
);
271 copy
->help
= val
->help
;
272 copy
->enabled
= val
->enabled
;
273 copy
->button_type
= val
->button_type
;
274 copy
->selected
= val
->selected
;
275 copy
->edited
= False
;
276 copy
->change
= change
;
277 copy
->this_one_change
= change
;
278 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
279 copy
->call_data
= val
->call_data
;
280 copy
->next
= copy_widget_value_tree (val
->next
, change
);
281 copy
->toolkit_data
= NULL
;
282 copy
->free_toolkit_data
= False
;
287 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
288 selection_cb
, post_activate_cb
, highlight_cb
)
293 lw_callback pre_activate_cb
;
294 lw_callback selection_cb
;
295 lw_callback post_activate_cb
;
296 lw_callback highlight_cb
;
298 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
299 info
->type
= safe_strdup (type
);
300 info
->name
= safe_strdup (name
);
302 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
304 info
->pre_activate_cb
= pre_activate_cb
;
305 info
->selection_cb
= selection_cb
;
306 info
->post_activate_cb
= post_activate_cb
;
307 info
->highlight_cb
= highlight_cb
;
308 info
->instances
= NULL
;
310 info
->next
= all_widget_info
;
311 all_widget_info
= info
;
317 free_widget_info (info
)
320 safe_free_str (info
->type
);
321 safe_free_str (info
->name
);
322 free_widget_value_tree (info
->val
);
323 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
328 mark_widget_destroyed (widget
, closure
, call_data
)
333 widget_instance
* instance
= (widget_instance
*)closure
;
335 /* be very conservative */
336 if (instance
->widget
== widget
)
337 instance
->widget
= NULL
;
340 static widget_instance
*
341 allocate_widget_instance (info
, parent
, pop_up_p
)
346 widget_instance
* instance
=
347 (widget_instance
*)malloc (sizeof (widget_instance
));
348 bzero (instance
, sizeof *instance
);
349 instance
->parent
= parent
;
350 instance
->pop_up_p
= pop_up_p
;
351 instance
->info
= info
;
352 instance
->next
= info
->instances
;
353 info
->instances
= instance
;
355 instantiate_widget_instance (instance
);
357 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
358 mark_widget_destroyed
, (XtPointer
)instance
);
363 free_widget_instance (instance
)
364 widget_instance
* instance
;
366 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
371 get_widget_info (id
, remove_p
)
377 for (prev
= NULL
, info
= all_widget_info
;
379 prev
= info
, info
= info
->next
)
385 prev
->next
= info
->next
;
387 all_widget_info
= info
->next
;
394 /* Internal function used by the library dependent implementation to get the
395 widget_value for a given widget in an instance */
397 lw_get_widget_info (id
)
400 return get_widget_info (id
, 0);
403 static widget_instance
*
404 get_widget_instance (widget
, remove_p
)
409 widget_instance
* instance
;
410 widget_instance
* prev
;
411 for (info
= all_widget_info
; info
; info
= info
->next
)
412 for (prev
= NULL
, instance
= info
->instances
;
414 prev
= instance
, instance
= instance
->next
)
415 if (instance
->widget
== widget
)
420 prev
->next
= instance
->next
;
422 info
->instances
= instance
->next
;
426 return (widget_instance
*) 0;
429 /* Value is a pointer to the widget_instance corresponding to
430 WIDGET, or null if WIDGET is not a lwlib widget. */
433 lw_get_widget_instance (widget
)
436 return get_widget_instance (widget
, False
);
439 static widget_instance
*
440 find_instance (id
, parent
, pop_up_p
)
445 widget_info
* info
= get_widget_info (id
, False
);
446 widget_instance
* instance
;
449 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
450 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
457 /* utility function for widget_value */
463 if (!!s1
^ !!s2
) return True
;
464 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
469 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
470 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
472 (oc == NO_CHANGE ? "none" : \
473 (oc == INVISIBLE_CHANGE ? "invisible" : \
474 (oc == VISIBLE_CHANGE ? "visible" : \
475 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
477 (nc == NO_CHANGE ? "none" : \
478 (nc == INVISIBLE_CHANGE ? "invisible" : \
479 (nc == VISIBLE_CHANGE ? "visible" : \
480 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
483 # define EXPLAIN(name, oc, nc, desc, a1, a2)
487 static widget_value
*
488 merge_widget_value (val1
, val2
, level
, change_p
)
494 change_type change
, this_one_change
;
495 widget_value
* merged_next
;
496 widget_value
* merged_contents
;
503 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
511 free_widget_value_tree (val1
);
517 if (safe_strcmp (val1
->name
, val2
->name
))
519 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
520 val1
->name
, val2
->name
);
521 change
= max (change
, STRUCTURAL_CHANGE
);
522 safe_free_str (val1
->name
);
523 val1
->name
= safe_strdup (val2
->name
);
525 if (safe_strcmp (val1
->value
, val2
->value
))
527 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
528 val1
->value
, val2
->value
);
529 change
= max (change
, VISIBLE_CHANGE
);
530 safe_free_str (val1
->value
);
531 val1
->value
= safe_strdup (val2
->value
);
533 if (safe_strcmp (val1
->key
, val2
->key
))
535 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
536 val1
->key
, val2
->key
);
537 change
= max (change
, VISIBLE_CHANGE
);
538 safe_free_str (val1
->key
);
539 val1
->key
= safe_strdup (val2
->key
);
541 if (! EQ (val1
->help
, val2
->help
))
543 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
544 val1
->help
, val2
->help
);
545 change
= max (change
, VISIBLE_CHANGE
);
546 val1
->help
= val2
->help
;
548 if (val1
->enabled
!= val2
->enabled
)
550 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
551 val1
->enabled
, val2
->enabled
);
552 change
= max (change
, VISIBLE_CHANGE
);
553 val1
->enabled
= val2
->enabled
;
555 if (val1
->button_type
!= val2
->button_type
)
557 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
558 val1
->button_type
, val2
->button_type
);
559 change
= max (change
, VISIBLE_CHANGE
);
560 val1
->button_type
= val2
->button_type
;
562 if (val1
->selected
!= val2
->selected
)
564 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
565 val1
->selected
, val2
->selected
);
566 change
= max (change
, VISIBLE_CHANGE
);
567 val1
->selected
= val2
->selected
;
569 if (val1
->call_data
!= val2
->call_data
)
571 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
572 val1
->call_data
, val2
->call_data
);
573 change
= max (change
, INVISIBLE_CHANGE
);
574 val1
->call_data
= val2
->call_data
;
580 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
583 if (val1
->contents
&& !merged_contents
)
585 /* This used to say INVISIBLE_CHANGE,
586 but it is visible and vitally important when
587 the contents of the menu bar itself are entirely deleted.
589 But maybe it doesn't matter. This fails to fix the bug. */
590 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
592 change
= max (change
, STRUCTURAL_CHANGE
);
594 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
596 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
598 change
= max (change
, INVISIBLE_CHANGE
);
599 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
601 change
= max (merged_contents
->change
, change
);
606 val1
->contents
= merged_contents
;
609 this_one_change
= change
;
611 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
613 if (val1
->next
&& !merged_next
)
615 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
617 change
= max (change
, STRUCTURAL_CHANGE
);
619 else if (merged_next
)
621 if (merged_next
->change
)
622 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
624 change
= max (change
, merged_next
->change
);
627 val1
->next
= merged_next
;
629 val1
->this_one_change
= this_one_change
;
630 val1
->change
= change
;
632 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
635 if (val1
->free_toolkit_data
)
636 XtFree (val1
->toolkit_data
);
637 val1
->toolkit_data
= NULL
;
644 /* modifying the widgets */
646 name_to_widget (instance
, name
)
647 widget_instance
* instance
;
650 Widget widget
= NULL
;
652 if (!instance
->widget
)
655 if (!strcmp (XtName (instance
->widget
), name
))
656 widget
= instance
->widget
;
659 int length
= strlen (name
) + 2;
660 char* real_name
= (char *) xmalloc (length
);
662 strcpy (real_name
+ 1, name
);
664 widget
= XtNameToWidget (instance
->widget
, real_name
);
672 set_one_value (instance
, val
, deep_p
)
673 widget_instance
* instance
;
677 Widget widget
= name_to_widget (instance
, val
->name
);
681 #if defined (USE_LUCID)
682 if (lw_lucid_widget_p (instance
->widget
))
683 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
685 #if defined (USE_MOTIF)
686 if (lw_motif_widget_p (instance
->widget
))
687 xm_update_one_widget (instance
, widget
, val
, deep_p
);
689 #if defined (USE_OLIT)
690 if (lw_olit_widget_p (instance
->widget
))
691 xol_update_one_widget (instance
, widget
, val
, deep_p
);
693 #if defined (USE_XAW)
694 if (lw_xaw_widget_p (instance
->widget
))
695 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
701 update_one_widget_instance (instance
, deep_p
)
702 widget_instance
* instance
;
707 if (!instance
->widget
)
708 /* the widget was destroyed */
711 for (val
= instance
->info
->val
; val
; val
= val
->next
)
712 if (val
->change
!= NO_CHANGE
)
713 set_one_value (instance
, val
, deep_p
);
717 update_all_widget_values (info
, deep_p
)
721 widget_instance
* instance
;
724 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
725 update_one_widget_instance (instance
, deep_p
);
727 for (val
= info
->val
; val
; val
= val
->next
)
728 val
->change
= NO_CHANGE
;
732 lw_modify_all_widgets (id
, val
, deep_p
)
737 widget_info
* info
= get_widget_info (id
, False
);
738 widget_value
* new_val
;
739 widget_value
* next_new_val
;
749 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
751 next_new_val
= new_val
->next
;
752 new_val
->next
= NULL
;
754 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
755 if (!strcmp (cur
->name
, new_val
->name
))
760 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
763 prev
->next
= cur
? cur
: next
;
765 info
->val
= cur
? cur
: next
;
772 /* Could not find it, add it */
774 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
776 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
779 new_val
->next
= next_new_val
;
782 update_all_widget_values (info
, deep_p
);
787 /* creating the widgets */
790 initialize_widget_instance (instance
)
791 widget_instance
* instance
;
795 for (val
= instance
->info
->val
; val
; val
= val
->next
)
796 val
->change
= STRUCTURAL_CHANGE
;
798 update_one_widget_instance (instance
, True
);
800 for (val
= instance
->info
->val
; val
; val
= val
->next
)
801 val
->change
= NO_CHANGE
;
805 static widget_creation_function
806 find_in_table (type
, table
)
808 widget_creation_entry
* table
;
810 widget_creation_entry
* cur
;
811 for (cur
= table
; cur
->type
; cur
++)
812 if (!my_strcasecmp (type
, cur
->type
))
813 return cur
->function
;
821 /* return True if name matches [EILPQeilpq][1-9][Bb] or
822 [EILPQeilpq][1-9][Bb][Rr][1-9] */
828 case 'E': case 'I': case 'L': case 'P': case 'Q':
829 case 'e': case 'i': case 'l': case 'p': case 'q':
830 if (name
[1] >= '0' && name
[1] <= '9')
832 if (name
[2] != 'B' && name
[2] != 'b')
836 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
838 if ((name
[3] == 'R' || name
[3] == 'r')
839 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
852 instantiate_widget_instance (instance
)
853 widget_instance
* instance
;
855 widget_creation_function function
= NULL
;
857 #if defined (USE_LUCID)
859 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
861 #if defined(USE_MOTIF)
863 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
865 #if defined (USE_OLIT)
867 function
= find_in_table (instance
->info
->type
, xol_creation_table
);
869 #if defined (USE_XAW)
871 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
876 if (dialog_spec_p (instance
->info
->type
))
878 #if defined (USE_LUCID)
881 #if defined(USE_MOTIF)
883 function
= xm_create_dialog
;
885 #if defined (USE_XAW)
887 function
= xaw_create_dialog
;
889 #if defined (USE_OLIT)
897 printf ("No creation function for widget type %s\n",
898 instance
->info
->type
);
902 instance
->widget
= (*function
) (instance
);
904 if (!instance
->widget
)
907 /* XtRealizeWidget (instance->widget);*/
911 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
912 selection_cb
, post_activate_cb
, highlight_cb
)
917 lw_callback pre_activate_cb
;
918 lw_callback selection_cb
;
919 lw_callback post_activate_cb
;
920 lw_callback highlight_cb
;
922 if (!get_widget_info (id
, False
))
923 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
924 post_activate_cb
, highlight_cb
);
928 lw_get_widget (id
, parent
, pop_up_p
)
933 widget_instance
* instance
;
935 instance
= find_instance (id
, parent
, pop_up_p
);
936 return instance
? instance
->widget
: NULL
;
940 lw_make_widget (id
, parent
, pop_up_p
)
945 widget_instance
* instance
;
948 instance
= find_instance (id
, parent
, pop_up_p
);
951 info
= get_widget_info (id
, False
);
954 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
955 initialize_widget_instance (instance
);
957 if (!instance
->widget
)
959 return instance
->widget
;
963 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
964 selection_cb
, post_activate_cb
, highlight_cb
)
971 lw_callback pre_activate_cb
;
972 lw_callback selection_cb
;
973 lw_callback post_activate_cb
;
974 lw_callback highlight_cb
;
976 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
977 post_activate_cb
, highlight_cb
);
978 return lw_make_widget (id
, parent
, pop_up_p
);
982 /* destroying the widgets */
984 destroy_one_instance (instance
)
985 widget_instance
* instance
;
987 /* Remove the destroy callback on the widget; that callback will try to
988 dereference the instance object (to set its widget slot to 0, since the
989 widget is dead.) Since the instance is now dead, we don't have to worry
990 about the fact that its widget is dead too.
992 This happens in the Phase2Destroy of the widget, so this callback would
993 not have been run until arbitrarily long after the instance was freed.
995 if (instance
->widget
)
996 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
997 mark_widget_destroyed
, (XtPointer
)instance
);
999 if (instance
->widget
)
1001 /* The else are pretty tricky here, including the empty statement
1002 at the end because it would be very bad to destroy a widget
1004 #if defined (USE_LUCID)
1005 if (lw_lucid_widget_p (instance
->widget
))
1006 xlw_destroy_instance (instance
);
1009 #if defined (USE_MOTIF)
1010 if (lw_motif_widget_p (instance
->widget
))
1011 xm_destroy_instance (instance
);
1014 #if defined (USE_OLIT)
1015 if (lw_olit_widget_p (instance
->widget
))
1016 xol_destroy_instance (instance
);
1019 #if defined (USE_XAW)
1020 if (lw_xaw_widget_p (instance
->widget
))
1021 xaw_destroy_instance (instance
);
1024 /* do not remove the empty statement */
1028 free_widget_instance (instance
);
1032 lw_destroy_widget (w
)
1035 widget_instance
* instance
= get_widget_instance (w
, True
);
1039 widget_info
*info
= instance
->info
;
1040 /* instance has already been removed from the list; free it */
1041 destroy_one_instance (instance
);
1042 /* if there are no instances left, free the info too */
1043 if (!info
->instances
)
1044 lw_destroy_all_widgets (info
->id
);
1049 lw_destroy_all_widgets (id
)
1052 widget_info
* info
= get_widget_info (id
, True
);
1053 widget_instance
* instance
;
1054 widget_instance
* next
;
1058 for (instance
= info
->instances
; instance
; )
1060 next
= instance
->next
;
1061 destroy_one_instance (instance
);
1064 free_widget_info (info
);
1069 lw_destroy_everything ()
1071 while (all_widget_info
)
1072 lw_destroy_all_widgets (all_widget_info
->id
);
1076 lw_destroy_all_pop_ups ()
1080 widget_instance
* instance
;
1082 for (info
= all_widget_info
; info
; info
= next
)
1085 instance
= info
->instances
;
1086 if (instance
&& instance
->pop_up_p
)
1087 lw_destroy_all_widgets (info
->id
);
1092 extern Widget
first_child (/* Widget */); /* garbage */
1096 lw_raise_all_pop_up_widgets ()
1099 widget_instance
* instance
;
1100 Widget result
= NULL
;
1102 for (info
= all_widget_info
; info
; info
= info
->next
)
1103 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1104 if (instance
->pop_up_p
)
1106 Widget widget
= instance
->widget
;
1109 if (XtIsManaged (widget
)
1111 /* What a complete load of crap!!!!
1112 When a dialogShell is on the screen, it is not managed!
1114 || (lw_motif_widget_p (instance
->widget
) &&
1115 XtIsManaged (first_child (widget
)))
1121 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1129 lw_pop_all_widgets (id
, up
)
1133 widget_info
* info
= get_widget_info (id
, False
);
1134 widget_instance
* instance
;
1137 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1138 if (instance
->pop_up_p
&& instance
->widget
)
1140 #if defined (USE_LUCID)
1141 if (lw_lucid_widget_p (instance
->widget
))
1143 XtRealizeWidget (instance
->widget
);
1144 xlw_pop_instance (instance
, up
);
1147 #if defined (USE_MOTIF)
1148 if (lw_motif_widget_p (instance
->widget
))
1150 XtRealizeWidget (instance
->widget
);
1151 xm_pop_instance (instance
, up
);
1154 #if defined (USE_OLIT)
1155 if (lw_olit_widget_p (instance
->widget
))
1157 XtRealizeWidget (instance
->widget
);
1158 xol_pop_instance (instance
, up
);
1161 #if defined (USE_XAW)
1162 if (lw_xaw_widget_p (instance
->widget
))
1164 XtRealizeWidget (XtParent (instance
->widget
));
1165 XtRealizeWidget (instance
->widget
);
1166 xaw_pop_instance (instance
, up
);
1173 lw_pop_up_all_widgets (id
)
1176 lw_pop_all_widgets (id
, True
);
1180 lw_pop_down_all_widgets (id
)
1183 lw_pop_all_widgets (id
, False
);
1187 lw_popup_menu (widget
, event
)
1191 #if defined (USE_LUCID)
1192 if (lw_lucid_widget_p (widget
))
1193 xlw_popup_menu (widget
, event
);
1195 #if defined (USE_MOTIF)
1196 if (lw_motif_widget_p (widget
))
1197 xm_popup_menu (widget
, event
);
1199 #if defined (USE_OLIT)
1200 if (lw_olit_widget_p (widget
))
1201 xol_popup_menu (widget
, event
);
1203 #if defined (USE_XAW)
1204 if (lw_xaw_widget_p (widget
))
1205 xaw_popup_menu (widget
, event
);
1209 \f/* get the values back */
1211 get_one_value (instance
, val
)
1212 widget_instance
* instance
;
1215 Widget widget
= name_to_widget (instance
, val
->name
);
1219 #if defined (USE_LUCID)
1220 if (lw_lucid_widget_p (instance
->widget
))
1221 xlw_update_one_value (instance
, widget
, val
);
1223 #if defined (USE_MOTIF)
1224 if (lw_motif_widget_p (instance
->widget
))
1225 xm_update_one_value (instance
, widget
, val
);
1227 #if defined (USE_OLIT)
1228 if (lw_olit_widget_p (instance
->widget
))
1229 xol_update_one_value (instance
, widget
, val
);
1231 #if defined (USE_XAW)
1232 if (lw_xaw_widget_p (instance
->widget
))
1233 xaw_update_one_value (instance
, widget
, val
);
1242 lw_get_some_values (id
, val_out
)
1244 widget_value
* val_out
;
1246 widget_info
* info
= get_widget_info (id
, False
);
1247 widget_instance
* instance
;
1249 Boolean result
= False
;
1254 instance
= info
->instances
;
1258 for (val
= val_out
; val
; val
= val
->next
)
1259 if (get_one_value (instance
, val
))
1266 lw_get_all_values (id
)
1269 widget_info
* info
= get_widget_info (id
, False
);
1270 widget_value
* val
= info
->val
;
1271 if (lw_get_some_values (id
, val
))
1277 /* internal function used by the library dependent implementation to get the
1278 widget_value for a given widget in an instance */
1280 lw_get_widget_value_for_widget (instance
, w
)
1281 widget_instance
* instance
;
1284 char* name
= XtName (w
);
1286 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1287 if (!strcmp (cur
->name
, name
))
1292 \f/* update other instances value when one thing changed */
1294 /* To forbid recursive calls */
1295 static Boolean lwlib_updating
;
1297 /* This function can be used as a an XtCallback for the widgets that get
1298 modified to update other instances of the widgets. Closure should be the
1301 lw_internal_update_other_instances (widget
, closure
, call_data
)
1304 XtPointer call_data
;
1306 widget_instance
* instance
= (widget_instance
*)closure
;
1307 char* name
= XtName (widget
);
1309 widget_instance
* cur
;
1312 /* Avoid possibly infinite recursion. */
1316 /* protect against the widget being destroyed */
1317 if (XtWidgetBeingDestroyedP (widget
))
1320 /* Return immediately if there are no other instances */
1321 info
= instance
->info
;
1322 if (!info
->instances
->next
)
1325 lwlib_updating
= True
;
1327 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1329 if (val
&& get_one_value (instance
, val
))
1330 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1331 if (cur
!= instance
)
1332 set_one_value (cur
, val
, True
);
1334 lwlib_updating
= False
;
1341 lw_get_widget_id (w
)
1344 widget_instance
* instance
= get_widget_instance (w
, False
);
1346 return instance
? instance
->info
->id
: 0;
1349 \f/* set the keyboard focus */
1351 lw_set_keyboard_focus (parent
, w
)
1355 #if defined (USE_MOTIF)
1356 xm_set_keyboard_focus (parent
, w
);
1358 XtSetKeyboardFocus (parent
, w
);
1364 show_one_widget_busy (w
, flag
)
1368 Pixel foreground
= 0;
1369 Pixel background
= 1;
1370 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1371 if (!widget_to_invert
)
1372 widget_to_invert
= w
;
1374 XtVaGetValues (widget_to_invert
,
1375 XtNforeground
, &foreground
,
1376 XtNbackground
, &background
,
1378 XtVaSetValues (widget_to_invert
,
1379 XtNforeground
, background
,
1380 XtNbackground
, foreground
,
1385 lw_show_busy (w
, busy
)
1389 widget_instance
* instance
= get_widget_instance (w
, False
);
1391 widget_instance
* next
;
1395 info
= instance
->info
;
1396 if (info
->busy
!= busy
)
1398 for (next
= info
->instances
; next
; next
= next
->next
)
1400 show_one_widget_busy (next
->widget
, busy
);
1406 /* This hack exists because Lucid/Athena need to execute the strange
1407 function below to support geometry management. */
1409 lw_refigure_widget (w
, doit
)
1413 #if defined (USE_XAW)
1414 XawPanedSetRefigureMode (w
, doit
);
1416 #if defined (USE_MOTIF)
1420 XtUnmanageChild (w
);
1424 /* Toolkit independent way of determining if an event window is in the
1427 lw_window_is_in_menubar (win
, menubar_widget
)
1429 Widget menubar_widget
;
1431 return menubar_widget
1432 #if defined (USE_LUCID)
1433 && XtWindow (menubar_widget
) == win
;
1435 #if defined (USE_MOTIF)
1436 && ((XtWindow (menubar_widget
) == win
)
1437 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1438 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1439 == menubar_widget
)));
1443 /* Motif hack to set the main window areas. */
1445 lw_set_main_areas (parent
, menubar
, work_area
)
1450 #if defined (USE_MOTIF)
1451 xm_set_main_areas (parent
, menubar
, work_area
);
1455 /* Manage resizing for Motif. This disables resizing when the menubar
1456 is about to be modified. */
1458 lw_allow_resizing (w
, flag
)
1462 #if defined (USE_MOTIF)
1463 xm_manage_resizing (w
, flag
);
1468 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1469 set to an appropriate enumerator of type enum menu_separator.
1470 MOTIF_P non-zero means map separator types not supported by Motif
1471 to similar ones that are supported. */
1474 lw_separator_p (label
, type
, motif_p
)
1476 enum menu_separator
*type
;
1479 int separator_p
= 0;
1481 if (strlen (label
) >= 3
1482 && bcmp (label
, "--:", 3) == 0)
1484 static struct separator_table
1487 enum menu_separator type
;
1491 {"space", SEPARATOR_NO_LINE
},
1492 {"noLine", SEPARATOR_NO_LINE
},
1493 {"singleLine", SEPARATOR_SINGLE_LINE
},
1494 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1495 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1496 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1497 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1498 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1499 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1500 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1501 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1502 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1503 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1504 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1511 for (i
= 0; separator_names
[i
].name
; ++i
)
1512 if (strcmp (label
, separator_names
[i
].name
) == 0)
1515 *type
= separator_names
[i
].type
;
1517 /* If separator type is not supported under Motif,
1518 use a similar one. */
1519 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1524 else if (strlen (label
) > 3
1525 && bcmp (label
, "--", 2) == 0
1528 /* Alternative, more Emacs-style names. */
1529 static struct separator_table
1532 enum menu_separator type
;
1536 {"space", SEPARATOR_NO_LINE
},
1537 {"no-line", SEPARATOR_NO_LINE
},
1538 {"single-line", SEPARATOR_SINGLE_LINE
},
1539 {"double-line", SEPARATOR_DOUBLE_LINE
},
1540 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1541 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1542 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1543 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1544 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1545 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1546 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1547 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1548 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1549 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1556 for (i
= 0; separator_names
[i
].name
; ++i
)
1557 if (strcmp (label
, separator_names
[i
].name
) == 0)
1560 *type
= separator_names
[i
].type
;
1562 /* If separator type is not supported under Motif,
1563 use a similar one. */
1564 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1571 /* Old-style separator, maybe. It's a separator if it contains
1573 while (*label
== '-')
1575 separator_p
= *label
== 0;
1576 *type
= SEPARATOR_SHADOW_ETCHED_IN
;