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 */
25 #include <sys/types.h>
28 #include "lwlib-int.h"
29 #include "lwlib-utils.h"
30 #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";
77 \f/* Forward declarations */
79 instantiate_widget_instance (/* widget_instance* instance */);
82 lwlib_memset (address
, value
, length
)
89 for (i
= 0; i
< length
; i
++)
94 lwlib_bcopy (from
, to
, length
)
101 for (i
= 0; i
< length
; i
++)
104 \f/* utility functions for widget_instance and widget_info */
111 result
= (char *) malloc (strlen (s
) + 1);
118 /* Like strcmp but ignore differences in case. */
121 my_strcasecmp (s1
, s2
)
133 return (c1
> c2
? 1 : -1);
146 static widget_value
*widget_value_free_list
= 0;
147 static int malloc_cpt
= 0;
150 malloc_widget_value ()
153 if (widget_value_free_list
)
155 wv
= widget_value_free_list
;
156 widget_value_free_list
= wv
->free_list
;
161 wv
= (widget_value
*) malloc (sizeof (widget_value
));
164 lwlib_memset (wv
, 0, sizeof (widget_value
));
168 /* this is analogous to free(). It frees only what was allocated
169 by malloc_widget_value(), and no substructures.
172 free_widget_value (wv
)
180 /* When the number of already allocated cells is too big,
187 wv
->free_list
= widget_value_free_list
;
188 widget_value_free_list
= wv
;
193 free_widget_value_tree (wv
)
199 if (wv
->name
) free (wv
->name
);
200 if (wv
->value
) free (wv
->value
);
201 if (wv
->key
) free (wv
->key
);
203 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
205 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
207 XtFree (wv
->toolkit_data
);
208 wv
->toolkit_data
= (void *) 0xDEADBEEF;
211 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
213 free_widget_value_tree (wv
->contents
);
214 wv
->contents
= (widget_value
*) 0xDEADBEEF;
218 free_widget_value_tree (wv
->next
);
219 wv
->next
= (widget_value
*) 0xDEADBEEF;
221 free_widget_value (wv
);
224 static widget_value
*
225 copy_widget_value_tree (val
, change
)
233 if (val
== (widget_value
*) 1)
236 copy
= malloc_widget_value ();
237 copy
->name
= safe_strdup (val
->name
);
238 copy
->value
= safe_strdup (val
->value
);
239 copy
->key
= safe_strdup (val
->key
);
240 copy
->enabled
= val
->enabled
;
241 copy
->button_type
= val
->button_type
;
242 copy
->selected
= val
->selected
;
243 copy
->edited
= False
;
244 copy
->change
= change
;
245 copy
->this_one_change
= change
;
246 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
247 copy
->call_data
= val
->call_data
;
248 copy
->next
= copy_widget_value_tree (val
->next
, change
);
249 copy
->toolkit_data
= NULL
;
250 copy
->free_toolkit_data
= False
;
255 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
, post_activate_cb
)
260 lw_callback pre_activate_cb
;
261 lw_callback selection_cb
;
262 lw_callback post_activate_cb
;
264 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
265 info
->type
= safe_strdup (type
);
266 info
->name
= safe_strdup (name
);
268 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
270 info
->pre_activate_cb
= pre_activate_cb
;
271 info
->selection_cb
= selection_cb
;
272 info
->post_activate_cb
= post_activate_cb
;
273 info
->instances
= NULL
;
275 info
->next
= all_widget_info
;
276 all_widget_info
= info
;
282 free_widget_info (info
)
285 safe_free_str (info
->type
);
286 safe_free_str (info
->name
);
287 free_widget_value_tree (info
->val
);
288 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
293 mark_widget_destroyed (widget
, closure
, call_data
)
298 widget_instance
* instance
= (widget_instance
*)closure
;
300 /* be very conservative */
301 if (instance
->widget
== widget
)
302 instance
->widget
= NULL
;
305 static widget_instance
*
306 allocate_widget_instance (info
, parent
, pop_up_p
)
311 widget_instance
* instance
=
312 (widget_instance
*)malloc (sizeof (widget_instance
));
313 instance
->parent
= parent
;
314 instance
->pop_up_p
= pop_up_p
;
315 instance
->info
= info
;
316 instance
->next
= info
->instances
;
317 info
->instances
= instance
;
319 instantiate_widget_instance (instance
);
321 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
322 mark_widget_destroyed
, (XtPointer
)instance
);
327 free_widget_instance (instance
)
328 widget_instance
* instance
;
330 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
335 get_widget_info (id
, remove_p
)
341 for (prev
= NULL
, info
= all_widget_info
;
343 prev
= info
, info
= info
->next
)
349 prev
->next
= info
->next
;
351 all_widget_info
= info
->next
;
358 /* Internal function used by the library dependent implementation to get the
359 widget_value for a given widget in an instance */
361 lw_get_widget_info (id
)
364 return get_widget_info (id
, 0);
367 static widget_instance
*
368 get_widget_instance (widget
, remove_p
)
373 widget_instance
* instance
;
374 widget_instance
* prev
;
375 for (info
= all_widget_info
; info
; info
= info
->next
)
376 for (prev
= NULL
, instance
= info
->instances
;
378 prev
= instance
, instance
= instance
->next
)
379 if (instance
->widget
== widget
)
384 prev
->next
= instance
->next
;
386 info
->instances
= instance
->next
;
390 return (widget_instance
*) 0;
393 static widget_instance
*
394 find_instance (id
, parent
, pop_up_p
)
399 widget_info
* info
= get_widget_info (id
, False
);
400 widget_instance
* instance
;
403 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
404 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
411 /* utility function for widget_value */
417 if (!!s1
^ !!s2
) return True
;
418 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
423 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
424 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
426 (oc == NO_CHANGE ? "none" : \
427 (oc == INVISIBLE_CHANGE ? "invisible" : \
428 (oc == VISIBLE_CHANGE ? "visible" : \
429 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
431 (nc == NO_CHANGE ? "none" : \
432 (nc == INVISIBLE_CHANGE ? "invisible" : \
433 (nc == VISIBLE_CHANGE ? "visible" : \
434 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
437 # define EXPLAIN(name, oc, nc, desc, a1, a2)
441 static widget_value
*
442 merge_widget_value (val1
, val2
, level
)
447 change_type change
, this_one_change
;
448 widget_value
* merged_next
;
449 widget_value
* merged_contents
;
454 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
460 free_widget_value_tree (val1
);
466 if (safe_strcmp (val1
->name
, val2
->name
))
468 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
469 val1
->name
, val2
->name
);
470 change
= max (change
, STRUCTURAL_CHANGE
);
471 safe_free_str (val1
->name
);
472 val1
->name
= safe_strdup (val2
->name
);
474 if (safe_strcmp (val1
->value
, val2
->value
))
476 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
477 val1
->value
, val2
->value
);
478 change
= max (change
, VISIBLE_CHANGE
);
479 safe_free_str (val1
->value
);
480 val1
->value
= safe_strdup (val2
->value
);
482 if (safe_strcmp (val1
->key
, val2
->key
))
484 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
485 val1
->key
, val2
->key
);
486 change
= max (change
, VISIBLE_CHANGE
);
487 safe_free_str (val1
->key
);
488 val1
->key
= safe_strdup (val2
->key
);
490 if (val1
->enabled
!= val2
->enabled
)
492 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
493 val1
->enabled
, val2
->enabled
);
494 change
= max (change
, VISIBLE_CHANGE
);
495 val1
->enabled
= val2
->enabled
;
497 if (val1
->button_type
!= val2
->button_type
)
499 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
500 val1
->button_type
, val2
->button_type
);
501 change
= max (change
, VISIBLE_CHANGE
);
502 val1
->button_type
= val2
->button_type
;
504 if (val1
->selected
!= val2
->selected
)
506 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
507 val1
->selected
, val2
->selected
);
508 change
= max (change
, VISIBLE_CHANGE
);
509 val1
->selected
= val2
->selected
;
511 if (val1
->call_data
!= val2
->call_data
)
513 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
514 val1
->call_data
, val2
->call_data
);
515 change
= max (change
, INVISIBLE_CHANGE
);
516 val1
->call_data
= val2
->call_data
;
522 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1);
524 if (val1
->contents
&& !merged_contents
)
526 /* This used to say INVISIBLE_CHANGE,
527 but it is visible and vitally important when
528 the contents of the menu bar itself are entirely deleted.
530 But maybe it doesn't matter. This fails to fix the bug. */
531 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
533 change
= max (change
, STRUCTURAL_CHANGE
);
535 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
537 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
539 change
= max (change
, INVISIBLE_CHANGE
);
540 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
542 change
= max (merged_contents
->change
, change
);
547 val1
->contents
= merged_contents
;
550 this_one_change
= change
;
552 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
);
554 if (val1
->next
&& !merged_next
)
556 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
558 change
= max (change
, STRUCTURAL_CHANGE
);
560 else if (merged_next
)
562 if (merged_next
->change
)
563 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
565 change
= max (change
, merged_next
->change
);
568 val1
->next
= merged_next
;
570 val1
->this_one_change
= this_one_change
;
571 val1
->change
= change
;
573 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
575 if (val1
->free_toolkit_data
)
576 XtFree (val1
->toolkit_data
);
577 val1
->toolkit_data
= NULL
;
584 /* modifying the widgets */
586 name_to_widget (instance
, name
)
587 widget_instance
* instance
;
590 Widget widget
= NULL
;
592 if (!instance
->widget
)
595 if (!strcmp (XtName (instance
->widget
), name
))
596 widget
= instance
->widget
;
599 int length
= strlen (name
) + 2;
600 char* real_name
= (char *) xmalloc (length
);
602 strcpy (real_name
+ 1, name
);
604 widget
= XtNameToWidget (instance
->widget
, real_name
);
612 set_one_value (instance
, val
, deep_p
)
613 widget_instance
* instance
;
617 Widget widget
= name_to_widget (instance
, val
->name
);
621 #if defined (USE_LUCID)
622 if (lw_lucid_widget_p (instance
->widget
))
623 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
625 #if defined (USE_MOTIF)
626 if (lw_motif_widget_p (instance
->widget
))
627 xm_update_one_widget (instance
, widget
, val
, deep_p
);
629 #if defined (USE_OLIT)
630 if (lw_olit_widget_p (instance
->widget
))
631 xol_update_one_widget (instance
, widget
, val
, deep_p
);
633 #if defined (USE_XAW)
634 if (lw_xaw_widget_p (instance
->widget
))
635 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
641 update_one_widget_instance (instance
, deep_p
)
642 widget_instance
* instance
;
647 if (!instance
->widget
)
648 /* the widget was destroyed */
651 for (val
= instance
->info
->val
; val
; val
= val
->next
)
652 if (val
->change
!= NO_CHANGE
)
653 set_one_value (instance
, val
, deep_p
);
657 update_all_widget_values (info
, deep_p
)
661 widget_instance
* instance
;
664 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
665 update_one_widget_instance (instance
, deep_p
);
667 for (val
= info
->val
; val
; val
= val
->next
)
668 val
->change
= NO_CHANGE
;
672 lw_modify_all_widgets (id
, val
, deep_p
)
677 widget_info
* info
= get_widget_info (id
, False
);
678 widget_value
* new_val
;
679 widget_value
* next_new_val
;
688 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
690 next_new_val
= new_val
->next
;
691 new_val
->next
= NULL
;
693 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
694 if (!strcmp (cur
->name
, new_val
->name
))
699 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1);
701 prev
->next
= cur
? cur
: next
;
703 info
->val
= cur
? cur
: next
;
710 /* Could not find it, add it */
712 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
714 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
716 new_val
->next
= next_new_val
;
719 update_all_widget_values (info
, deep_p
);
723 /* creating the widgets */
726 initialize_widget_instance (instance
)
727 widget_instance
* instance
;
731 for (val
= instance
->info
->val
; val
; val
= val
->next
)
732 val
->change
= STRUCTURAL_CHANGE
;
734 update_one_widget_instance (instance
, True
);
736 for (val
= instance
->info
->val
; val
; val
= val
->next
)
737 val
->change
= NO_CHANGE
;
741 static widget_creation_function
742 find_in_table (type
, table
)
744 widget_creation_entry
* table
;
746 widget_creation_entry
* cur
;
747 for (cur
= table
; cur
->type
; cur
++)
748 if (!my_strcasecmp (type
, cur
->type
))
749 return cur
->function
;
757 /* return True if name matches [EILPQeilpq][1-9][Bb] or
758 [EILPQeilpq][1-9][Bb][Rr][1-9] */
764 case 'E': case 'I': case 'L': case 'P': case 'Q':
765 case 'e': case 'i': case 'l': case 'p': case 'q':
766 if (name
[1] >= '0' && name
[1] <= '9')
768 if (name
[2] != 'B' && name
[2] != 'b')
772 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
774 if ((name
[3] == 'R' || name
[3] == 'r')
775 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
788 instantiate_widget_instance (instance
)
789 widget_instance
* instance
;
791 widget_creation_function function
= NULL
;
793 #if defined (USE_LUCID)
795 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
797 #if defined(USE_MOTIF)
799 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
801 #if defined (USE_OLIT)
803 function
= find_in_table (instance
->info
->type
, xol_creation_table
);
805 #if defined (USE_XAW)
807 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
812 if (dialog_spec_p (instance
->info
->type
))
814 #if defined (USE_LUCID)
817 #if defined(USE_MOTIF)
819 function
= xm_create_dialog
;
821 #if defined (USE_XAW)
823 function
= xaw_create_dialog
;
825 #if defined (USE_OLIT)
833 printf ("No creation function for widget type %s\n",
834 instance
->info
->type
);
838 instance
->widget
= (*function
) (instance
);
840 if (!instance
->widget
)
843 /* XtRealizeWidget (instance->widget);*/
847 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
, post_activate_cb
)
852 lw_callback pre_activate_cb
;
853 lw_callback selection_cb
;
854 lw_callback post_activate_cb
;
856 if (!get_widget_info (id
, False
))
857 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
862 lw_get_widget (id
, parent
, pop_up_p
)
867 widget_instance
* instance
;
869 instance
= find_instance (id
, parent
, pop_up_p
);
870 return instance
? instance
->widget
: NULL
;
874 lw_make_widget (id
, parent
, pop_up_p
)
879 widget_instance
* instance
;
882 instance
= find_instance (id
, parent
, pop_up_p
);
885 info
= get_widget_info (id
, False
);
888 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
889 initialize_widget_instance (instance
);
891 if (!instance
->widget
)
893 return instance
->widget
;
897 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
, selection_cb
, post_activate_cb
)
904 lw_callback pre_activate_cb
;
905 lw_callback selection_cb
;
906 lw_callback post_activate_cb
;
908 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
910 return lw_make_widget (id
, parent
, pop_up_p
);
914 /* destroying the widgets */
916 destroy_one_instance (instance
)
917 widget_instance
* instance
;
919 /* Remove the destroy callback on the widget; that callback will try to
920 dereference the instance object (to set its widget slot to 0, since the
921 widget is dead.) Since the instance is now dead, we don't have to worry
922 about the fact that its widget is dead too.
924 This happens in the Phase2Destroy of the widget, so this callback would
925 not have been run until arbitrarily long after the instance was freed.
927 if (instance
->widget
)
928 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
929 mark_widget_destroyed
, (XtPointer
)instance
);
931 if (instance
->widget
)
933 /* The else are pretty tricky here, including the empty statement
934 at the end because it would be very bad to destroy a widget
936 #if defined (USE_LUCID)
937 if (lw_lucid_widget_p (instance
->widget
))
938 xlw_destroy_instance (instance
);
941 #if defined (USE_MOTIF)
942 if (lw_motif_widget_p (instance
->widget
))
943 xm_destroy_instance (instance
);
946 #if defined (USE_OLIT)
947 if (lw_olit_widget_p (instance
->widget
))
948 xol_destroy_instance (instance
);
951 #if defined (USE_XAW)
952 if (lw_xaw_widget_p (instance
->widget
))
953 xaw_destroy_instance (instance
);
956 /* do not remove the empty statement */
960 free_widget_instance (instance
);
964 lw_destroy_widget (w
)
967 widget_instance
* instance
= get_widget_instance (w
, True
);
971 widget_info
*info
= instance
->info
;
972 /* instance has already been removed from the list; free it */
973 destroy_one_instance (instance
);
974 /* if there are no instances left, free the info too */
975 if (!info
->instances
)
976 lw_destroy_all_widgets (info
->id
);
981 lw_destroy_all_widgets (id
)
984 widget_info
* info
= get_widget_info (id
, True
);
985 widget_instance
* instance
;
986 widget_instance
* next
;
990 for (instance
= info
->instances
; instance
; )
992 next
= instance
->next
;
993 destroy_one_instance (instance
);
996 free_widget_info (info
);
1001 lw_destroy_everything ()
1003 while (all_widget_info
)
1004 lw_destroy_all_widgets (all_widget_info
->id
);
1008 lw_destroy_all_pop_ups ()
1012 widget_instance
* instance
;
1014 for (info
= all_widget_info
; info
; info
= next
)
1017 instance
= info
->instances
;
1018 if (instance
&& instance
->pop_up_p
)
1019 lw_destroy_all_widgets (info
->id
);
1024 extern Widget
first_child (/* Widget */); /* garbage */
1028 lw_raise_all_pop_up_widgets ()
1031 widget_instance
* instance
;
1032 Widget result
= NULL
;
1034 for (info
= all_widget_info
; info
; info
= info
->next
)
1035 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1036 if (instance
->pop_up_p
)
1038 Widget widget
= instance
->widget
;
1041 if (XtIsManaged (widget
)
1043 /* What a complete load of crap!!!!
1044 When a dialogShell is on the screen, it is not managed!
1046 || (lw_motif_widget_p (instance
->widget
) &&
1047 XtIsManaged (first_child (widget
)))
1053 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1061 lw_pop_all_widgets (id
, up
)
1065 widget_info
* info
= get_widget_info (id
, False
);
1066 widget_instance
* instance
;
1069 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1070 if (instance
->pop_up_p
&& instance
->widget
)
1072 #if defined (USE_LUCID)
1073 if (lw_lucid_widget_p (instance
->widget
))
1075 XtRealizeWidget (instance
->widget
);
1076 xlw_pop_instance (instance
, up
);
1079 #if defined (USE_MOTIF)
1080 if (lw_motif_widget_p (instance
->widget
))
1082 XtRealizeWidget (instance
->widget
);
1083 xm_pop_instance (instance
, up
);
1086 #if defined (USE_OLIT)
1087 if (lw_olit_widget_p (instance
->widget
))
1089 XtRealizeWidget (instance
->widget
);
1090 xol_pop_instance (instance
, up
);
1093 #if defined (USE_XAW)
1094 if (lw_xaw_widget_p (instance
->widget
))
1096 XtRealizeWidget (XtParent (instance
->widget
));
1097 XtRealizeWidget (instance
->widget
);
1098 xaw_pop_instance (instance
, up
);
1105 lw_pop_up_all_widgets (id
)
1108 lw_pop_all_widgets (id
, True
);
1112 lw_pop_down_all_widgets (id
)
1115 lw_pop_all_widgets (id
, False
);
1119 lw_popup_menu (widget
, event
)
1123 #if defined (USE_LUCID)
1124 if (lw_lucid_widget_p (widget
))
1125 xlw_popup_menu (widget
, event
);
1127 #if defined (USE_MOTIF)
1128 if (lw_motif_widget_p (widget
))
1129 xm_popup_menu (widget
, event
);
1131 #if defined (USE_OLIT)
1132 if (lw_olit_widget_p (widget
))
1133 xol_popup_menu (widget
, event
);
1135 #if defined (USE_XAW)
1136 if (lw_xaw_widget_p (widget
))
1137 xaw_popup_menu (widget
, event
);
1141 \f/* get the values back */
1143 get_one_value (instance
, val
)
1144 widget_instance
* instance
;
1147 Widget widget
= name_to_widget (instance
, val
->name
);
1151 #if defined (USE_LUCID)
1152 if (lw_lucid_widget_p (instance
->widget
))
1153 xlw_update_one_value (instance
, widget
, val
);
1155 #if defined (USE_MOTIF)
1156 if (lw_motif_widget_p (instance
->widget
))
1157 xm_update_one_value (instance
, widget
, val
);
1159 #if defined (USE_OLIT)
1160 if (lw_olit_widget_p (instance
->widget
))
1161 xol_update_one_value (instance
, widget
, val
);
1163 #if defined (USE_XAW)
1164 if (lw_xaw_widget_p (instance
->widget
))
1165 xaw_update_one_value (instance
, widget
, val
);
1174 lw_get_some_values (id
, val_out
)
1176 widget_value
* val_out
;
1178 widget_info
* info
= get_widget_info (id
, False
);
1179 widget_instance
* instance
;
1181 Boolean result
= False
;
1186 instance
= info
->instances
;
1190 for (val
= val_out
; val
; val
= val
->next
)
1191 if (get_one_value (instance
, val
))
1198 lw_get_all_values (id
)
1201 widget_info
* info
= get_widget_info (id
, False
);
1202 widget_value
* val
= info
->val
;
1203 if (lw_get_some_values (id
, val
))
1209 /* internal function used by the library dependent implementation to get the
1210 widget_value for a given widget in an instance */
1212 lw_get_widget_value_for_widget (instance
, w
)
1213 widget_instance
* instance
;
1216 char* name
= XtName (w
);
1218 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1219 if (!strcmp (cur
->name
, name
))
1224 \f/* update other instances value when one thing changed */
1226 /* To forbid recursive calls */
1227 static Boolean lwlib_updating
;
1229 /* This function can be used as a an XtCallback for the widgets that get
1230 modified to update other instances of the widgets. Closure should be the
1233 lw_internal_update_other_instances (widget
, closure
, call_data
)
1236 XtPointer call_data
;
1238 widget_instance
* instance
= (widget_instance
*)closure
;
1239 char* name
= XtName (widget
);
1241 widget_instance
* cur
;
1244 /* Avoid possibly infinite recursion. */
1248 /* protect against the widget being destroyed */
1249 if (XtWidgetBeingDestroyedP (widget
))
1252 /* Return immediately if there are no other instances */
1253 info
= instance
->info
;
1254 if (!info
->instances
->next
)
1257 lwlib_updating
= True
;
1259 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1261 if (val
&& get_one_value (instance
, val
))
1262 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1263 if (cur
!= instance
)
1264 set_one_value (cur
, val
, True
);
1266 lwlib_updating
= False
;
1273 lw_get_widget_id (w
)
1276 widget_instance
* instance
= get_widget_instance (w
, False
);
1278 return instance
? instance
->info
->id
: 0;
1281 \f/* set the keyboard focus */
1283 lw_set_keyboard_focus (parent
, w
)
1287 #if defined (USE_MOTIF)
1288 xm_set_keyboard_focus (parent
, w
);
1290 XtSetKeyboardFocus (parent
, w
);
1296 show_one_widget_busy (w
, flag
)
1300 Pixel foreground
= 0;
1301 Pixel background
= 1;
1302 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1303 if (!widget_to_invert
)
1304 widget_to_invert
= w
;
1306 XtVaGetValues (widget_to_invert
,
1307 XtNforeground
, &foreground
,
1308 XtNbackground
, &background
,
1310 XtVaSetValues (widget_to_invert
,
1311 XtNforeground
, background
,
1312 XtNbackground
, foreground
,
1317 lw_show_busy (w
, busy
)
1321 widget_instance
* instance
= get_widget_instance (w
, False
);
1323 widget_instance
* next
;
1327 info
= instance
->info
;
1328 if (info
->busy
!= busy
)
1330 for (next
= info
->instances
; next
; next
= next
->next
)
1332 show_one_widget_busy (next
->widget
, busy
);
1338 /* This hack exists because Lucid/Athena need to execute the strange
1339 function below to support geometry management. */
1341 lw_refigure_widget (w
, doit
)
1345 #if defined (USE_XAW)
1346 XawPanedSetRefigureMode (w
, doit
);
1348 #if defined (USE_MOTIF)
1352 XtUnmanageChild (w
);
1356 /* Toolkit independent way of determining if an event window is in the
1359 lw_window_is_in_menubar (win
, menubar_widget
)
1361 Widget menubar_widget
;
1363 return menubar_widget
1364 #if defined (USE_LUCID)
1365 && XtWindow (menubar_widget
) == win
;
1367 #if defined (USE_MOTIF)
1368 && ((XtWindow (menubar_widget
) == win
)
1369 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1370 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1371 == menubar_widget
)));
1375 /* Motif hack to set the main window areas. */
1377 lw_set_main_areas (parent
, menubar
, work_area
)
1382 #if defined (USE_MOTIF)
1383 xm_set_main_areas (parent
, menubar
, work_area
);
1387 /* Manage resizing for Motif. This disables resizing when the menubar
1388 is about to be modified. */
1390 lw_allow_resizing (w
, flag
)
1394 #if defined (USE_MOTIF)
1395 xm_manage_resizing (w
, flag
);
1400 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1401 set to an appropriate enumerator of type enum menu_separator.
1402 MOTIF_P non-zero means map separator types not supported by Motif
1403 to similar ones that are supported. */
1406 lw_separator_p (label
, type
, motif_p
)
1408 enum menu_separator
*type
;
1413 if (strlen (label
) >= 3
1414 && bcmp (label
, "--:", 3) == 0)
1416 static struct separator_table
1419 enum menu_separator type
;
1423 "noLine", SEPARATOR_NO_LINE
,
1424 "singleLine", SEPARATOR_SINGLE_LINE
,
1425 "doubleLine", SEPARATOR_DOUBLE_LINE
,
1426 "singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
,
1427 "doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
,
1428 "shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
,
1429 "shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
,
1430 "shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
,
1431 "shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
,
1432 "shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
,
1433 "shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
,
1434 "shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
,
1435 "shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
,
1442 for (i
= 0; separator_names
[i
].name
; ++i
)
1443 if (strcmp (label
, separator_names
[i
].name
) == 0)
1446 *type
= separator_names
[i
].type
;
1448 /* If separator type is not supported under Motif,
1449 use a similar one. */
1450 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1457 /* Old-style separator, maybe. It's a separator if it contains
1459 while (*label
== '-')
1461 separator_p
= *label
== 0;
1462 *type
= SEPARATOR_SHADOW_ETCHED_IN
;