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 <sys/types.h>
32 #include "lwlib-int.h"
33 #include "lwlib-utils.h"
34 #include <X11/StringDefs.h>
36 extern long *xmalloc();
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 #if defined __STDC__ || defined PROTOTYPES
84 static widget_value
*merge_widget_value
P_ ((widget_value
*,
87 static void instantiate_widget_instance
P_ ((widget_instance
*));
88 static int my_strcasecmp
P_ ((char *, char *));
89 static void safe_free_str
P_ ((char *));
90 static void free_widget_value_tree
P_ ((widget_value
*));
91 static widget_value
*copy_widget_value_tree
P_ ((widget_value
*,
93 static widget_info
*allocate_widget_info
P_ ((char *, char *, LWLIB_ID
,
95 lw_callback
, lw_callback
,
96 lw_callback
, lw_callback
));
97 static void free_widget_info
P_ ((widget_info
*));
98 static void mark_widget_destroyed
P_ ((Widget
, XtPointer
, XtPointer
));
99 static widget_instance
*allocate_widget_instance
P_ ((widget_info
*,
101 static void free_widget_instance
P_ ((widget_instance
*));
102 static widget_info
*get_widget_info
P_ ((LWLIB_ID
, Boolean
));
103 static widget_instance
*get_widget_instance
P_ ((Widget
, Boolean
));
104 static widget_instance
*find_instance
P_ ((LWLIB_ID
, Widget
, Boolean
));
105 static Boolean safe_strcmp
P_ ((char *, char *));
106 static Widget name_to_widget
P_ ((widget_instance
*, char *));
107 static void set_one_value
P_ ((widget_instance
*, widget_value
*, Boolean
));
108 static void update_one_widget_instance
P_ ((widget_instance
*, Boolean
));
109 static void update_all_widget_values
P_ ((widget_info
*, Boolean
));
110 static void initialize_widget_instance
P_ ((widget_instance
*));
111 static widget_creation_function find_in_table
P_ ((char *, widget_creation_entry
*));
112 static Boolean dialog_spec_p
P_ ((char *));
113 static void instantiate_widget_instance
P_ ((widget_instance
*));
114 static void destroy_one_instance
P_ ((widget_instance
*));
115 static void lw_pop_all_widgets
P_ ((LWLIB_ID
, Boolean
));
116 static Boolean get_one_value
P_ ((widget_instance
*, widget_value
*));
117 static void show_one_widget_busy
P_ ((Widget
, Boolean
));
120 lwlib_memset (address
, value
, length
)
127 for (i
= 0; i
< length
; i
++)
132 lwlib_bcopy (from
, to
, length
)
139 for (i
= 0; i
< length
; i
++)
142 \f/* utility functions for widget_instance and widget_info */
149 result
= (char *) malloc (strlen (s
) + 1);
156 /* Like strcmp but ignore differences in case. */
159 my_strcasecmp (s1
, s2
)
171 return (c1
> c2
? 1 : -1);
184 static widget_value
*widget_value_free_list
= 0;
185 static int malloc_cpt
= 0;
188 malloc_widget_value ()
191 if (widget_value_free_list
)
193 wv
= widget_value_free_list
;
194 widget_value_free_list
= wv
->free_list
;
199 wv
= (widget_value
*) malloc (sizeof (widget_value
));
202 lwlib_memset (wv
, 0, sizeof (widget_value
));
206 /* this is analogous to free(). It frees only what was allocated
207 by malloc_widget_value(), and no substructures.
210 free_widget_value (wv
)
218 /* When the number of already allocated cells is too big,
225 wv
->free_list
= widget_value_free_list
;
226 widget_value_free_list
= wv
;
231 free_widget_value_tree (wv
)
237 if (wv
->name
) free (wv
->name
);
238 if (wv
->value
) free (wv
->value
);
239 if (wv
->key
) free (wv
->key
);
240 if (wv
->help
) free (wv
->help
);
242 wv
->name
= wv
->value
= wv
->key
= wv
->help
= (char *) 0xDEADBEEF;
244 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
246 XtFree (wv
->toolkit_data
);
247 wv
->toolkit_data
= (void *) 0xDEADBEEF;
250 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
252 free_widget_value_tree (wv
->contents
);
253 wv
->contents
= (widget_value
*) 0xDEADBEEF;
257 free_widget_value_tree (wv
->next
);
258 wv
->next
= (widget_value
*) 0xDEADBEEF;
260 free_widget_value (wv
);
263 static widget_value
*
264 copy_widget_value_tree (val
, change
)
272 if (val
== (widget_value
*) 1)
275 copy
= malloc_widget_value ();
276 copy
->name
= safe_strdup (val
->name
);
277 copy
->value
= safe_strdup (val
->value
);
278 copy
->key
= safe_strdup (val
->key
);
279 copy
->help
= safe_strdup (val
->help
);
280 copy
->enabled
= val
->enabled
;
281 copy
->button_type
= val
->button_type
;
282 copy
->selected
= val
->selected
;
283 copy
->edited
= False
;
284 copy
->change
= change
;
285 copy
->this_one_change
= change
;
286 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
287 copy
->call_data
= val
->call_data
;
288 copy
->next
= copy_widget_value_tree (val
->next
, change
);
289 copy
->toolkit_data
= NULL
;
290 copy
->free_toolkit_data
= False
;
295 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
296 selection_cb
, post_activate_cb
, highlight_cb
)
301 lw_callback pre_activate_cb
;
302 lw_callback selection_cb
;
303 lw_callback post_activate_cb
;
304 lw_callback highlight_cb
;
306 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
307 info
->type
= safe_strdup (type
);
308 info
->name
= safe_strdup (name
);
310 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
312 info
->pre_activate_cb
= pre_activate_cb
;
313 info
->selection_cb
= selection_cb
;
314 info
->post_activate_cb
= post_activate_cb
;
315 info
->highlight_cb
= highlight_cb
;
316 info
->instances
= NULL
;
318 info
->next
= all_widget_info
;
319 all_widget_info
= info
;
325 free_widget_info (info
)
328 safe_free_str (info
->type
);
329 safe_free_str (info
->name
);
330 free_widget_value_tree (info
->val
);
331 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
336 mark_widget_destroyed (widget
, closure
, call_data
)
341 widget_instance
* instance
= (widget_instance
*)closure
;
343 /* be very conservative */
344 if (instance
->widget
== widget
)
345 instance
->widget
= NULL
;
348 static widget_instance
*
349 allocate_widget_instance (info
, parent
, pop_up_p
)
354 widget_instance
* instance
=
355 (widget_instance
*)malloc (sizeof (widget_instance
));
356 bzero (instance
, sizeof *instance
);
357 instance
->parent
= parent
;
358 instance
->pop_up_p
= pop_up_p
;
359 instance
->info
= info
;
360 instance
->next
= info
->instances
;
361 info
->instances
= instance
;
363 instantiate_widget_instance (instance
);
365 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
366 mark_widget_destroyed
, (XtPointer
)instance
);
371 free_widget_instance (instance
)
372 widget_instance
* instance
;
374 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
379 get_widget_info (id
, remove_p
)
385 for (prev
= NULL
, info
= all_widget_info
;
387 prev
= info
, info
= info
->next
)
393 prev
->next
= info
->next
;
395 all_widget_info
= info
->next
;
402 /* Internal function used by the library dependent implementation to get the
403 widget_value for a given widget in an instance */
405 lw_get_widget_info (id
)
408 return get_widget_info (id
, 0);
411 static widget_instance
*
412 get_widget_instance (widget
, remove_p
)
417 widget_instance
* instance
;
418 widget_instance
* prev
;
419 for (info
= all_widget_info
; info
; info
= info
->next
)
420 for (prev
= NULL
, instance
= info
->instances
;
422 prev
= instance
, instance
= instance
->next
)
423 if (instance
->widget
== widget
)
428 prev
->next
= instance
->next
;
430 info
->instances
= instance
->next
;
434 return (widget_instance
*) 0;
437 /* Value is a pointer to the widget_instance corresponding to
438 WIDGET, or null if WIDGET is not a lwlib widget. */
441 lw_get_widget_instance (widget
)
444 return get_widget_instance (widget
, False
);
447 static widget_instance
*
448 find_instance (id
, parent
, pop_up_p
)
453 widget_info
* info
= get_widget_info (id
, False
);
454 widget_instance
* instance
;
457 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
458 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
465 /* utility function for widget_value */
471 if (!!s1
^ !!s2
) return True
;
472 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
477 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
478 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
480 (oc == NO_CHANGE ? "none" : \
481 (oc == INVISIBLE_CHANGE ? "invisible" : \
482 (oc == VISIBLE_CHANGE ? "visible" : \
483 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
485 (nc == NO_CHANGE ? "none" : \
486 (nc == INVISIBLE_CHANGE ? "invisible" : \
487 (nc == VISIBLE_CHANGE ? "visible" : \
488 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
491 # define EXPLAIN(name, oc, nc, desc, a1, a2)
495 static widget_value
*
496 merge_widget_value (val1
, val2
, level
, change_p
)
502 change_type change
, this_one_change
;
503 widget_value
* merged_next
;
504 widget_value
* merged_contents
;
511 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
519 free_widget_value_tree (val1
);
525 if (safe_strcmp (val1
->name
, val2
->name
))
527 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
528 val1
->name
, val2
->name
);
529 change
= max (change
, STRUCTURAL_CHANGE
);
530 safe_free_str (val1
->name
);
531 val1
->name
= safe_strdup (val2
->name
);
533 if (safe_strcmp (val1
->value
, val2
->value
))
535 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
536 val1
->value
, val2
->value
);
537 change
= max (change
, VISIBLE_CHANGE
);
538 safe_free_str (val1
->value
);
539 val1
->value
= safe_strdup (val2
->value
);
541 if (safe_strcmp (val1
->key
, val2
->key
))
543 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
544 val1
->key
, val2
->key
);
545 change
= max (change
, VISIBLE_CHANGE
);
546 safe_free_str (val1
->key
);
547 val1
->key
= safe_strdup (val2
->key
);
549 if (safe_strcmp (val1
->help
, val2
->help
))
551 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
552 val1
->help
, val2
->help
);
553 change
= max (change
, VISIBLE_CHANGE
);
554 safe_free_str (val1
->help
);
555 val1
->help
= safe_strdup (val2
->help
);
557 if (val1
->enabled
!= val2
->enabled
)
559 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
560 val1
->enabled
, val2
->enabled
);
561 change
= max (change
, VISIBLE_CHANGE
);
562 val1
->enabled
= val2
->enabled
;
564 if (val1
->button_type
!= val2
->button_type
)
566 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
567 val1
->button_type
, val2
->button_type
);
568 change
= max (change
, VISIBLE_CHANGE
);
569 val1
->button_type
= val2
->button_type
;
571 if (val1
->selected
!= val2
->selected
)
573 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
574 val1
->selected
, val2
->selected
);
575 change
= max (change
, VISIBLE_CHANGE
);
576 val1
->selected
= val2
->selected
;
578 if (val1
->call_data
!= val2
->call_data
)
580 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
581 val1
->call_data
, val2
->call_data
);
582 change
= max (change
, INVISIBLE_CHANGE
);
583 val1
->call_data
= val2
->call_data
;
589 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
592 if (val1
->contents
&& !merged_contents
)
594 /* This used to say INVISIBLE_CHANGE,
595 but it is visible and vitally important when
596 the contents of the menu bar itself are entirely deleted.
598 But maybe it doesn't matter. This fails to fix the bug. */
599 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
601 change
= max (change
, STRUCTURAL_CHANGE
);
603 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
605 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
607 change
= max (change
, INVISIBLE_CHANGE
);
608 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
610 change
= max (merged_contents
->change
, change
);
615 val1
->contents
= merged_contents
;
618 this_one_change
= change
;
620 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
622 if (val1
->next
&& !merged_next
)
624 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
626 change
= max (change
, STRUCTURAL_CHANGE
);
628 else if (merged_next
)
630 if (merged_next
->change
)
631 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
633 change
= max (change
, merged_next
->change
);
636 val1
->next
= merged_next
;
638 val1
->this_one_change
= this_one_change
;
639 val1
->change
= change
;
641 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
644 if (val1
->free_toolkit_data
)
645 XtFree (val1
->toolkit_data
);
646 val1
->toolkit_data
= NULL
;
653 /* modifying the widgets */
655 name_to_widget (instance
, name
)
656 widget_instance
* instance
;
659 Widget widget
= NULL
;
661 if (!instance
->widget
)
664 if (!strcmp (XtName (instance
->widget
), name
))
665 widget
= instance
->widget
;
668 int length
= strlen (name
) + 2;
669 char* real_name
= (char *) xmalloc (length
);
671 strcpy (real_name
+ 1, name
);
673 widget
= XtNameToWidget (instance
->widget
, real_name
);
681 set_one_value (instance
, val
, deep_p
)
682 widget_instance
* instance
;
686 Widget widget
= name_to_widget (instance
, val
->name
);
690 #if defined (USE_LUCID)
691 if (lw_lucid_widget_p (instance
->widget
))
692 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
694 #if defined (USE_MOTIF)
695 if (lw_motif_widget_p (instance
->widget
))
696 xm_update_one_widget (instance
, widget
, val
, deep_p
);
698 #if defined (USE_OLIT)
699 if (lw_olit_widget_p (instance
->widget
))
700 xol_update_one_widget (instance
, widget
, val
, deep_p
);
702 #if defined (USE_XAW)
703 if (lw_xaw_widget_p (instance
->widget
))
704 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
710 update_one_widget_instance (instance
, deep_p
)
711 widget_instance
* instance
;
716 if (!instance
->widget
)
717 /* the widget was destroyed */
720 for (val
= instance
->info
->val
; val
; val
= val
->next
)
721 if (val
->change
!= NO_CHANGE
)
722 set_one_value (instance
, val
, deep_p
);
726 update_all_widget_values (info
, deep_p
)
730 widget_instance
* instance
;
733 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
734 update_one_widget_instance (instance
, deep_p
);
736 for (val
= info
->val
; val
; val
= val
->next
)
737 val
->change
= NO_CHANGE
;
741 lw_modify_all_widgets (id
, val
, deep_p
)
746 widget_info
* info
= get_widget_info (id
, False
);
747 widget_value
* new_val
;
748 widget_value
* next_new_val
;
758 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
760 next_new_val
= new_val
->next
;
761 new_val
->next
= NULL
;
763 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
764 if (!strcmp (cur
->name
, new_val
->name
))
769 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
772 prev
->next
= cur
? cur
: next
;
774 info
->val
= cur
? cur
: next
;
781 /* Could not find it, add it */
783 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
785 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
788 new_val
->next
= next_new_val
;
791 update_all_widget_values (info
, deep_p
);
796 /* creating the widgets */
799 initialize_widget_instance (instance
)
800 widget_instance
* instance
;
804 for (val
= instance
->info
->val
; val
; val
= val
->next
)
805 val
->change
= STRUCTURAL_CHANGE
;
807 update_one_widget_instance (instance
, True
);
809 for (val
= instance
->info
->val
; val
; val
= val
->next
)
810 val
->change
= NO_CHANGE
;
814 static widget_creation_function
815 find_in_table (type
, table
)
817 widget_creation_entry
* table
;
819 widget_creation_entry
* cur
;
820 for (cur
= table
; cur
->type
; cur
++)
821 if (!my_strcasecmp (type
, cur
->type
))
822 return cur
->function
;
830 /* return True if name matches [EILPQeilpq][1-9][Bb] or
831 [EILPQeilpq][1-9][Bb][Rr][1-9] */
837 case 'E': case 'I': case 'L': case 'P': case 'Q':
838 case 'e': case 'i': case 'l': case 'p': case 'q':
839 if (name
[1] >= '0' && name
[1] <= '9')
841 if (name
[2] != 'B' && name
[2] != 'b')
845 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
847 if ((name
[3] == 'R' || name
[3] == 'r')
848 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
861 instantiate_widget_instance (instance
)
862 widget_instance
* instance
;
864 widget_creation_function function
= NULL
;
866 #if defined (USE_LUCID)
868 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
870 #if defined(USE_MOTIF)
872 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
874 #if defined (USE_OLIT)
876 function
= find_in_table (instance
->info
->type
, xol_creation_table
);
878 #if defined (USE_XAW)
880 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
885 if (dialog_spec_p (instance
->info
->type
))
887 #if defined (USE_LUCID)
890 #if defined(USE_MOTIF)
892 function
= xm_create_dialog
;
894 #if defined (USE_XAW)
896 function
= xaw_create_dialog
;
898 #if defined (USE_OLIT)
906 printf ("No creation function for widget type %s\n",
907 instance
->info
->type
);
911 instance
->widget
= (*function
) (instance
);
913 if (!instance
->widget
)
916 /* XtRealizeWidget (instance->widget);*/
920 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
921 selection_cb
, post_activate_cb
, highlight_cb
)
926 lw_callback pre_activate_cb
;
927 lw_callback selection_cb
;
928 lw_callback post_activate_cb
;
929 lw_callback highlight_cb
;
931 if (!get_widget_info (id
, False
))
932 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
933 post_activate_cb
, highlight_cb
);
937 lw_get_widget (id
, parent
, pop_up_p
)
942 widget_instance
* instance
;
944 instance
= find_instance (id
, parent
, pop_up_p
);
945 return instance
? instance
->widget
: NULL
;
949 lw_make_widget (id
, parent
, pop_up_p
)
954 widget_instance
* instance
;
957 instance
= find_instance (id
, parent
, pop_up_p
);
960 info
= get_widget_info (id
, False
);
963 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
964 initialize_widget_instance (instance
);
966 if (!instance
->widget
)
968 return instance
->widget
;
972 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
973 selection_cb
, post_activate_cb
, highlight_cb
)
980 lw_callback pre_activate_cb
;
981 lw_callback selection_cb
;
982 lw_callback post_activate_cb
;
983 lw_callback highlight_cb
;
985 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
986 post_activate_cb
, highlight_cb
);
987 return lw_make_widget (id
, parent
, pop_up_p
);
991 /* destroying the widgets */
993 destroy_one_instance (instance
)
994 widget_instance
* instance
;
996 /* Remove the destroy callback on the widget; that callback will try to
997 dereference the instance object (to set its widget slot to 0, since the
998 widget is dead.) Since the instance is now dead, we don't have to worry
999 about the fact that its widget is dead too.
1001 This happens in the Phase2Destroy of the widget, so this callback would
1002 not have been run until arbitrarily long after the instance was freed.
1004 if (instance
->widget
)
1005 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1006 mark_widget_destroyed
, (XtPointer
)instance
);
1008 if (instance
->widget
)
1010 /* The else are pretty tricky here, including the empty statement
1011 at the end because it would be very bad to destroy a widget
1013 #if defined (USE_LUCID)
1014 if (lw_lucid_widget_p (instance
->widget
))
1015 xlw_destroy_instance (instance
);
1018 #if defined (USE_MOTIF)
1019 if (lw_motif_widget_p (instance
->widget
))
1020 xm_destroy_instance (instance
);
1023 #if defined (USE_OLIT)
1024 if (lw_olit_widget_p (instance
->widget
))
1025 xol_destroy_instance (instance
);
1028 #if defined (USE_XAW)
1029 if (lw_xaw_widget_p (instance
->widget
))
1030 xaw_destroy_instance (instance
);
1033 /* do not remove the empty statement */
1037 free_widget_instance (instance
);
1041 lw_destroy_widget (w
)
1044 widget_instance
* instance
= get_widget_instance (w
, True
);
1048 widget_info
*info
= instance
->info
;
1049 /* instance has already been removed from the list; free it */
1050 destroy_one_instance (instance
);
1051 /* if there are no instances left, free the info too */
1052 if (!info
->instances
)
1053 lw_destroy_all_widgets (info
->id
);
1058 lw_destroy_all_widgets (id
)
1061 widget_info
* info
= get_widget_info (id
, True
);
1062 widget_instance
* instance
;
1063 widget_instance
* next
;
1067 for (instance
= info
->instances
; instance
; )
1069 next
= instance
->next
;
1070 destroy_one_instance (instance
);
1073 free_widget_info (info
);
1078 lw_destroy_everything ()
1080 while (all_widget_info
)
1081 lw_destroy_all_widgets (all_widget_info
->id
);
1085 lw_destroy_all_pop_ups ()
1089 widget_instance
* instance
;
1091 for (info
= all_widget_info
; info
; info
= next
)
1094 instance
= info
->instances
;
1095 if (instance
&& instance
->pop_up_p
)
1096 lw_destroy_all_widgets (info
->id
);
1101 extern Widget
first_child (/* Widget */); /* garbage */
1105 lw_raise_all_pop_up_widgets ()
1108 widget_instance
* instance
;
1109 Widget result
= NULL
;
1111 for (info
= all_widget_info
; info
; info
= info
->next
)
1112 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1113 if (instance
->pop_up_p
)
1115 Widget widget
= instance
->widget
;
1118 if (XtIsManaged (widget
)
1120 /* What a complete load of crap!!!!
1121 When a dialogShell is on the screen, it is not managed!
1123 || (lw_motif_widget_p (instance
->widget
) &&
1124 XtIsManaged (first_child (widget
)))
1130 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1138 lw_pop_all_widgets (id
, up
)
1142 widget_info
* info
= get_widget_info (id
, False
);
1143 widget_instance
* instance
;
1146 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1147 if (instance
->pop_up_p
&& instance
->widget
)
1149 #if defined (USE_LUCID)
1150 if (lw_lucid_widget_p (instance
->widget
))
1152 XtRealizeWidget (instance
->widget
);
1153 xlw_pop_instance (instance
, up
);
1156 #if defined (USE_MOTIF)
1157 if (lw_motif_widget_p (instance
->widget
))
1159 XtRealizeWidget (instance
->widget
);
1160 xm_pop_instance (instance
, up
);
1163 #if defined (USE_OLIT)
1164 if (lw_olit_widget_p (instance
->widget
))
1166 XtRealizeWidget (instance
->widget
);
1167 xol_pop_instance (instance
, up
);
1170 #if defined (USE_XAW)
1171 if (lw_xaw_widget_p (instance
->widget
))
1173 XtRealizeWidget (XtParent (instance
->widget
));
1174 XtRealizeWidget (instance
->widget
);
1175 xaw_pop_instance (instance
, up
);
1182 lw_pop_up_all_widgets (id
)
1185 lw_pop_all_widgets (id
, True
);
1189 lw_pop_down_all_widgets (id
)
1192 lw_pop_all_widgets (id
, False
);
1196 lw_popup_menu (widget
, event
)
1200 #if defined (USE_LUCID)
1201 if (lw_lucid_widget_p (widget
))
1202 xlw_popup_menu (widget
, event
);
1204 #if defined (USE_MOTIF)
1205 if (lw_motif_widget_p (widget
))
1206 xm_popup_menu (widget
, event
);
1208 #if defined (USE_OLIT)
1209 if (lw_olit_widget_p (widget
))
1210 xol_popup_menu (widget
, event
);
1212 #if defined (USE_XAW)
1213 if (lw_xaw_widget_p (widget
))
1214 xaw_popup_menu (widget
, event
);
1218 \f/* get the values back */
1220 get_one_value (instance
, val
)
1221 widget_instance
* instance
;
1224 Widget widget
= name_to_widget (instance
, val
->name
);
1228 #if defined (USE_LUCID)
1229 if (lw_lucid_widget_p (instance
->widget
))
1230 xlw_update_one_value (instance
, widget
, val
);
1232 #if defined (USE_MOTIF)
1233 if (lw_motif_widget_p (instance
->widget
))
1234 xm_update_one_value (instance
, widget
, val
);
1236 #if defined (USE_OLIT)
1237 if (lw_olit_widget_p (instance
->widget
))
1238 xol_update_one_value (instance
, widget
, val
);
1240 #if defined (USE_XAW)
1241 if (lw_xaw_widget_p (instance
->widget
))
1242 xaw_update_one_value (instance
, widget
, val
);
1251 lw_get_some_values (id
, val_out
)
1253 widget_value
* val_out
;
1255 widget_info
* info
= get_widget_info (id
, False
);
1256 widget_instance
* instance
;
1258 Boolean result
= False
;
1263 instance
= info
->instances
;
1267 for (val
= val_out
; val
; val
= val
->next
)
1268 if (get_one_value (instance
, val
))
1275 lw_get_all_values (id
)
1278 widget_info
* info
= get_widget_info (id
, False
);
1279 widget_value
* val
= info
->val
;
1280 if (lw_get_some_values (id
, val
))
1286 /* internal function used by the library dependent implementation to get the
1287 widget_value for a given widget in an instance */
1289 lw_get_widget_value_for_widget (instance
, w
)
1290 widget_instance
* instance
;
1293 char* name
= XtName (w
);
1295 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1296 if (!strcmp (cur
->name
, name
))
1301 \f/* update other instances value when one thing changed */
1303 /* To forbid recursive calls */
1304 static Boolean lwlib_updating
;
1306 /* This function can be used as a an XtCallback for the widgets that get
1307 modified to update other instances of the widgets. Closure should be the
1310 lw_internal_update_other_instances (widget
, closure
, call_data
)
1313 XtPointer call_data
;
1315 widget_instance
* instance
= (widget_instance
*)closure
;
1316 char* name
= XtName (widget
);
1318 widget_instance
* cur
;
1321 /* Avoid possibly infinite recursion. */
1325 /* protect against the widget being destroyed */
1326 if (XtWidgetBeingDestroyedP (widget
))
1329 /* Return immediately if there are no other instances */
1330 info
= instance
->info
;
1331 if (!info
->instances
->next
)
1334 lwlib_updating
= True
;
1336 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1338 if (val
&& get_one_value (instance
, val
))
1339 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1340 if (cur
!= instance
)
1341 set_one_value (cur
, val
, True
);
1343 lwlib_updating
= False
;
1350 lw_get_widget_id (w
)
1353 widget_instance
* instance
= get_widget_instance (w
, False
);
1355 return instance
? instance
->info
->id
: 0;
1358 \f/* set the keyboard focus */
1360 lw_set_keyboard_focus (parent
, w
)
1364 #if defined (USE_MOTIF)
1365 xm_set_keyboard_focus (parent
, w
);
1367 XtSetKeyboardFocus (parent
, w
);
1373 show_one_widget_busy (w
, flag
)
1377 Pixel foreground
= 0;
1378 Pixel background
= 1;
1379 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1380 if (!widget_to_invert
)
1381 widget_to_invert
= w
;
1383 XtVaGetValues (widget_to_invert
,
1384 XtNforeground
, &foreground
,
1385 XtNbackground
, &background
,
1387 XtVaSetValues (widget_to_invert
,
1388 XtNforeground
, background
,
1389 XtNbackground
, foreground
,
1394 lw_show_busy (w
, busy
)
1398 widget_instance
* instance
= get_widget_instance (w
, False
);
1400 widget_instance
* next
;
1404 info
= instance
->info
;
1405 if (info
->busy
!= busy
)
1407 for (next
= info
->instances
; next
; next
= next
->next
)
1409 show_one_widget_busy (next
->widget
, busy
);
1415 /* This hack exists because Lucid/Athena need to execute the strange
1416 function below to support geometry management. */
1418 lw_refigure_widget (w
, doit
)
1422 #if defined (USE_XAW)
1423 XawPanedSetRefigureMode (w
, doit
);
1425 #if defined (USE_MOTIF)
1429 XtUnmanageChild (w
);
1433 /* Toolkit independent way of determining if an event window is in the
1436 lw_window_is_in_menubar (win
, menubar_widget
)
1438 Widget menubar_widget
;
1440 return menubar_widget
1441 #if defined (USE_LUCID)
1442 && XtWindow (menubar_widget
) == win
;
1444 #if defined (USE_MOTIF)
1445 && ((XtWindow (menubar_widget
) == win
)
1446 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1447 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1448 == menubar_widget
)));
1452 /* Motif hack to set the main window areas. */
1454 lw_set_main_areas (parent
, menubar
, work_area
)
1459 #if defined (USE_MOTIF)
1460 xm_set_main_areas (parent
, menubar
, work_area
);
1464 /* Manage resizing for Motif. This disables resizing when the menubar
1465 is about to be modified. */
1467 lw_allow_resizing (w
, flag
)
1471 #if defined (USE_MOTIF)
1472 xm_manage_resizing (w
, flag
);
1477 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1478 set to an appropriate enumerator of type enum menu_separator.
1479 MOTIF_P non-zero means map separator types not supported by Motif
1480 to similar ones that are supported. */
1483 lw_separator_p (label
, type
, motif_p
)
1485 enum menu_separator
*type
;
1490 if (strlen (label
) >= 3
1491 && bcmp (label
, "--:", 3) == 0)
1493 static struct separator_table
1496 enum menu_separator type
;
1500 "space", SEPARATOR_NO_LINE
,
1501 "noLine", SEPARATOR_NO_LINE
,
1502 "singleLine", SEPARATOR_SINGLE_LINE
,
1503 "doubleLine", SEPARATOR_DOUBLE_LINE
,
1504 "singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
,
1505 "doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
,
1506 "shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
,
1507 "shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
,
1508 "shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
,
1509 "shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
,
1510 "shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
,
1511 "shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
,
1512 "shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
,
1513 "shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
,
1520 for (i
= 0; separator_names
[i
].name
; ++i
)
1521 if (strcmp (label
, separator_names
[i
].name
) == 0)
1524 *type
= separator_names
[i
].type
;
1526 /* If separator type is not supported under Motif,
1527 use a similar one. */
1528 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1533 else if (strlen (label
) > 3
1534 && bcmp (label
, "--", 2) == 0
1537 /* Alternative, more Emacs-style names. */
1538 static struct separator_table
1541 enum menu_separator type
;
1545 "space", SEPARATOR_NO_LINE
,
1546 "no-line", SEPARATOR_NO_LINE
,
1547 "single-line", SEPARATOR_SINGLE_LINE
,
1548 "double-line", SEPARATOR_DOUBLE_LINE
,
1549 "single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
,
1550 "double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
,
1551 "shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
,
1552 "shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
,
1553 "shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
,
1554 "shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
,
1555 "shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
,
1556 "shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
,
1557 "shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
,
1558 "shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
,
1565 for (i
= 0; separator_names
[i
].name
; ++i
)
1566 if (strcmp (label
, separator_names
[i
].name
) == 0)
1569 *type
= separator_names
[i
].type
;
1571 /* If separator type is not supported under Motif,
1572 use a similar one. */
1573 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1580 /* Old-style separator, maybe. It's a separator if it contains
1582 while (*label
== '-')
1584 separator_p
= *label
== 0;
1585 *type
= SEPARATOR_SHADOW_ETCHED_IN
;