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 #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
);
241 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
243 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
245 XtFree (wv
->toolkit_data
);
246 wv
->toolkit_data
= (void *) 0xDEADBEEF;
249 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
251 free_widget_value_tree (wv
->contents
);
252 wv
->contents
= (widget_value
*) 0xDEADBEEF;
256 free_widget_value_tree (wv
->next
);
257 wv
->next
= (widget_value
*) 0xDEADBEEF;
259 free_widget_value (wv
);
262 static widget_value
*
263 copy_widget_value_tree (val
, change
)
271 if (val
== (widget_value
*) 1)
274 copy
= malloc_widget_value ();
275 copy
->name
= safe_strdup (val
->name
);
276 copy
->value
= safe_strdup (val
->value
);
277 copy
->key
= safe_strdup (val
->key
);
278 copy
->help
= val
->help
;
279 copy
->enabled
= val
->enabled
;
280 copy
->button_type
= val
->button_type
;
281 copy
->selected
= val
->selected
;
282 copy
->edited
= False
;
283 copy
->change
= change
;
284 copy
->this_one_change
= change
;
285 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
286 copy
->call_data
= val
->call_data
;
287 copy
->next
= copy_widget_value_tree (val
->next
, change
);
288 copy
->toolkit_data
= NULL
;
289 copy
->free_toolkit_data
= False
;
294 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
,
295 selection_cb
, post_activate_cb
, highlight_cb
)
300 lw_callback pre_activate_cb
;
301 lw_callback selection_cb
;
302 lw_callback post_activate_cb
;
303 lw_callback highlight_cb
;
305 widget_info
* info
= (widget_info
*)malloc (sizeof (widget_info
));
306 info
->type
= safe_strdup (type
);
307 info
->name
= safe_strdup (name
);
309 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
311 info
->pre_activate_cb
= pre_activate_cb
;
312 info
->selection_cb
= selection_cb
;
313 info
->post_activate_cb
= post_activate_cb
;
314 info
->highlight_cb
= highlight_cb
;
315 info
->instances
= NULL
;
317 info
->next
= all_widget_info
;
318 all_widget_info
= info
;
324 free_widget_info (info
)
327 safe_free_str (info
->type
);
328 safe_free_str (info
->name
);
329 free_widget_value_tree (info
->val
);
330 lwlib_memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
335 mark_widget_destroyed (widget
, closure
, call_data
)
340 widget_instance
* instance
= (widget_instance
*)closure
;
342 /* be very conservative */
343 if (instance
->widget
== widget
)
344 instance
->widget
= NULL
;
347 static widget_instance
*
348 allocate_widget_instance (info
, parent
, pop_up_p
)
353 widget_instance
* instance
=
354 (widget_instance
*)malloc (sizeof (widget_instance
));
355 bzero (instance
, sizeof *instance
);
356 instance
->parent
= parent
;
357 instance
->pop_up_p
= pop_up_p
;
358 instance
->info
= info
;
359 instance
->next
= info
->instances
;
360 info
->instances
= instance
;
362 instantiate_widget_instance (instance
);
364 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
365 mark_widget_destroyed
, (XtPointer
)instance
);
370 free_widget_instance (instance
)
371 widget_instance
* instance
;
373 lwlib_memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
378 get_widget_info (id
, remove_p
)
384 for (prev
= NULL
, info
= all_widget_info
;
386 prev
= info
, info
= info
->next
)
392 prev
->next
= info
->next
;
394 all_widget_info
= info
->next
;
401 /* Internal function used by the library dependent implementation to get the
402 widget_value for a given widget in an instance */
404 lw_get_widget_info (id
)
407 return get_widget_info (id
, 0);
410 static widget_instance
*
411 get_widget_instance (widget
, remove_p
)
416 widget_instance
* instance
;
417 widget_instance
* prev
;
418 for (info
= all_widget_info
; info
; info
= info
->next
)
419 for (prev
= NULL
, instance
= info
->instances
;
421 prev
= instance
, instance
= instance
->next
)
422 if (instance
->widget
== widget
)
427 prev
->next
= instance
->next
;
429 info
->instances
= instance
->next
;
433 return (widget_instance
*) 0;
436 /* Value is a pointer to the widget_instance corresponding to
437 WIDGET, or null if WIDGET is not a lwlib widget. */
440 lw_get_widget_instance (widget
)
443 return get_widget_instance (widget
, False
);
446 static widget_instance
*
447 find_instance (id
, parent
, pop_up_p
)
452 widget_info
* info
= get_widget_info (id
, False
);
453 widget_instance
* instance
;
456 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
457 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
464 /* utility function for widget_value */
470 if (!!s1
^ !!s2
) return True
;
471 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
476 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
477 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
479 (oc == NO_CHANGE ? "none" : \
480 (oc == INVISIBLE_CHANGE ? "invisible" : \
481 (oc == VISIBLE_CHANGE ? "visible" : \
482 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
484 (nc == NO_CHANGE ? "none" : \
485 (nc == INVISIBLE_CHANGE ? "invisible" : \
486 (nc == VISIBLE_CHANGE ? "visible" : \
487 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
490 # define EXPLAIN(name, oc, nc, desc, a1, a2)
494 static widget_value
*
495 merge_widget_value (val1
, val2
, level
, change_p
)
501 change_type change
, this_one_change
;
502 widget_value
* merged_next
;
503 widget_value
* merged_contents
;
510 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
518 free_widget_value_tree (val1
);
524 if (safe_strcmp (val1
->name
, val2
->name
))
526 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
527 val1
->name
, val2
->name
);
528 change
= max (change
, STRUCTURAL_CHANGE
);
529 safe_free_str (val1
->name
);
530 val1
->name
= safe_strdup (val2
->name
);
532 if (safe_strcmp (val1
->value
, val2
->value
))
534 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
535 val1
->value
, val2
->value
);
536 change
= max (change
, VISIBLE_CHANGE
);
537 safe_free_str (val1
->value
);
538 val1
->value
= safe_strdup (val2
->value
);
540 if (safe_strcmp (val1
->key
, val2
->key
))
542 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
543 val1
->key
, val2
->key
);
544 change
= max (change
, VISIBLE_CHANGE
);
545 safe_free_str (val1
->key
);
546 val1
->key
= safe_strdup (val2
->key
);
548 if (! EQ (val1
->help
, val2
->help
))
550 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
551 val1
->help
, val2
->help
);
552 change
= max (change
, VISIBLE_CHANGE
);
553 val1
->help
= val2
->help
;
555 if (val1
->enabled
!= val2
->enabled
)
557 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
558 val1
->enabled
, val2
->enabled
);
559 change
= max (change
, VISIBLE_CHANGE
);
560 val1
->enabled
= val2
->enabled
;
562 if (val1
->button_type
!= val2
->button_type
)
564 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
565 val1
->button_type
, val2
->button_type
);
566 change
= max (change
, VISIBLE_CHANGE
);
567 val1
->button_type
= val2
->button_type
;
569 if (val1
->selected
!= val2
->selected
)
571 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
572 val1
->selected
, val2
->selected
);
573 change
= max (change
, VISIBLE_CHANGE
);
574 val1
->selected
= val2
->selected
;
576 if (val1
->call_data
!= val2
->call_data
)
578 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
579 val1
->call_data
, val2
->call_data
);
580 change
= max (change
, INVISIBLE_CHANGE
);
581 val1
->call_data
= val2
->call_data
;
587 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
590 if (val1
->contents
&& !merged_contents
)
592 /* This used to say INVISIBLE_CHANGE,
593 but it is visible and vitally important when
594 the contents of the menu bar itself are entirely deleted.
596 But maybe it doesn't matter. This fails to fix the bug. */
597 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
599 change
= max (change
, STRUCTURAL_CHANGE
);
601 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
603 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
605 change
= max (change
, INVISIBLE_CHANGE
);
606 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
608 change
= max (merged_contents
->change
, change
);
613 val1
->contents
= merged_contents
;
616 this_one_change
= change
;
618 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
620 if (val1
->next
&& !merged_next
)
622 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
624 change
= max (change
, STRUCTURAL_CHANGE
);
626 else if (merged_next
)
628 if (merged_next
->change
)
629 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
631 change
= max (change
, merged_next
->change
);
634 val1
->next
= merged_next
;
636 val1
->this_one_change
= this_one_change
;
637 val1
->change
= change
;
639 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
642 if (val1
->free_toolkit_data
)
643 XtFree (val1
->toolkit_data
);
644 val1
->toolkit_data
= NULL
;
651 /* modifying the widgets */
653 name_to_widget (instance
, name
)
654 widget_instance
* instance
;
657 Widget widget
= NULL
;
659 if (!instance
->widget
)
662 if (!strcmp (XtName (instance
->widget
), name
))
663 widget
= instance
->widget
;
666 int length
= strlen (name
) + 2;
667 char* real_name
= (char *) xmalloc (length
);
669 strcpy (real_name
+ 1, name
);
671 widget
= XtNameToWidget (instance
->widget
, real_name
);
679 set_one_value (instance
, val
, deep_p
)
680 widget_instance
* instance
;
684 Widget widget
= name_to_widget (instance
, val
->name
);
688 #if defined (USE_LUCID)
689 if (lw_lucid_widget_p (instance
->widget
))
690 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
692 #if defined (USE_MOTIF)
693 if (lw_motif_widget_p (instance
->widget
))
694 xm_update_one_widget (instance
, widget
, val
, deep_p
);
696 #if defined (USE_OLIT)
697 if (lw_olit_widget_p (instance
->widget
))
698 xol_update_one_widget (instance
, widget
, val
, deep_p
);
700 #if defined (USE_XAW)
701 if (lw_xaw_widget_p (instance
->widget
))
702 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
708 update_one_widget_instance (instance
, deep_p
)
709 widget_instance
* instance
;
714 if (!instance
->widget
)
715 /* the widget was destroyed */
718 for (val
= instance
->info
->val
; val
; val
= val
->next
)
719 if (val
->change
!= NO_CHANGE
)
720 set_one_value (instance
, val
, deep_p
);
724 update_all_widget_values (info
, deep_p
)
728 widget_instance
* instance
;
731 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
732 update_one_widget_instance (instance
, deep_p
);
734 for (val
= info
->val
; val
; val
= val
->next
)
735 val
->change
= NO_CHANGE
;
739 lw_modify_all_widgets (id
, val
, deep_p
)
744 widget_info
* info
= get_widget_info (id
, False
);
745 widget_value
* new_val
;
746 widget_value
* next_new_val
;
756 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
758 next_new_val
= new_val
->next
;
759 new_val
->next
= NULL
;
761 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
762 if (!strcmp (cur
->name
, new_val
->name
))
767 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
770 prev
->next
= cur
? cur
: next
;
772 info
->val
= cur
? cur
: next
;
779 /* Could not find it, add it */
781 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
783 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
786 new_val
->next
= next_new_val
;
789 update_all_widget_values (info
, deep_p
);
794 /* creating the widgets */
797 initialize_widget_instance (instance
)
798 widget_instance
* instance
;
802 for (val
= instance
->info
->val
; val
; val
= val
->next
)
803 val
->change
= STRUCTURAL_CHANGE
;
805 update_one_widget_instance (instance
, True
);
807 for (val
= instance
->info
->val
; val
; val
= val
->next
)
808 val
->change
= NO_CHANGE
;
812 static widget_creation_function
813 find_in_table (type
, table
)
815 widget_creation_entry
* table
;
817 widget_creation_entry
* cur
;
818 for (cur
= table
; cur
->type
; cur
++)
819 if (!my_strcasecmp (type
, cur
->type
))
820 return cur
->function
;
828 /* return True if name matches [EILPQeilpq][1-9][Bb] or
829 [EILPQeilpq][1-9][Bb][Rr][1-9] */
835 case 'E': case 'I': case 'L': case 'P': case 'Q':
836 case 'e': case 'i': case 'l': case 'p': case 'q':
837 if (name
[1] >= '0' && name
[1] <= '9')
839 if (name
[2] != 'B' && name
[2] != 'b')
843 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
845 if ((name
[3] == 'R' || name
[3] == 'r')
846 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
859 instantiate_widget_instance (instance
)
860 widget_instance
* instance
;
862 widget_creation_function function
= NULL
;
864 #if defined (USE_LUCID)
866 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
868 #if defined(USE_MOTIF)
870 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
872 #if defined (USE_OLIT)
874 function
= find_in_table (instance
->info
->type
, xol_creation_table
);
876 #if defined (USE_XAW)
878 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
883 if (dialog_spec_p (instance
->info
->type
))
885 #if defined (USE_LUCID)
888 #if defined(USE_MOTIF)
890 function
= xm_create_dialog
;
892 #if defined (USE_XAW)
894 function
= xaw_create_dialog
;
896 #if defined (USE_OLIT)
904 printf ("No creation function for widget type %s\n",
905 instance
->info
->type
);
909 instance
->widget
= (*function
) (instance
);
911 if (!instance
->widget
)
914 /* XtRealizeWidget (instance->widget);*/
918 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
,
919 selection_cb
, post_activate_cb
, highlight_cb
)
924 lw_callback pre_activate_cb
;
925 lw_callback selection_cb
;
926 lw_callback post_activate_cb
;
927 lw_callback highlight_cb
;
929 if (!get_widget_info (id
, False
))
930 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
931 post_activate_cb
, highlight_cb
);
935 lw_get_widget (id
, parent
, pop_up_p
)
940 widget_instance
* instance
;
942 instance
= find_instance (id
, parent
, pop_up_p
);
943 return instance
? instance
->widget
: NULL
;
947 lw_make_widget (id
, parent
, pop_up_p
)
952 widget_instance
* instance
;
955 instance
= find_instance (id
, parent
, pop_up_p
);
958 info
= get_widget_info (id
, False
);
961 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
962 initialize_widget_instance (instance
);
964 if (!instance
->widget
)
966 return instance
->widget
;
970 lw_create_widget (type
, name
, id
, val
, parent
, pop_up_p
, pre_activate_cb
,
971 selection_cb
, post_activate_cb
, highlight_cb
)
978 lw_callback pre_activate_cb
;
979 lw_callback selection_cb
;
980 lw_callback post_activate_cb
;
981 lw_callback highlight_cb
;
983 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
984 post_activate_cb
, highlight_cb
);
985 return lw_make_widget (id
, parent
, pop_up_p
);
989 /* destroying the widgets */
991 destroy_one_instance (instance
)
992 widget_instance
* instance
;
994 /* Remove the destroy callback on the widget; that callback will try to
995 dereference the instance object (to set its widget slot to 0, since the
996 widget is dead.) Since the instance is now dead, we don't have to worry
997 about the fact that its widget is dead too.
999 This happens in the Phase2Destroy of the widget, so this callback would
1000 not have been run until arbitrarily long after the instance was freed.
1002 if (instance
->widget
)
1003 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
1004 mark_widget_destroyed
, (XtPointer
)instance
);
1006 if (instance
->widget
)
1008 /* The else are pretty tricky here, including the empty statement
1009 at the end because it would be very bad to destroy a widget
1011 #if defined (USE_LUCID)
1012 if (lw_lucid_widget_p (instance
->widget
))
1013 xlw_destroy_instance (instance
);
1016 #if defined (USE_MOTIF)
1017 if (lw_motif_widget_p (instance
->widget
))
1018 xm_destroy_instance (instance
);
1021 #if defined (USE_OLIT)
1022 if (lw_olit_widget_p (instance
->widget
))
1023 xol_destroy_instance (instance
);
1026 #if defined (USE_XAW)
1027 if (lw_xaw_widget_p (instance
->widget
))
1028 xaw_destroy_instance (instance
);
1031 /* do not remove the empty statement */
1035 free_widget_instance (instance
);
1039 lw_destroy_widget (w
)
1042 widget_instance
* instance
= get_widget_instance (w
, True
);
1046 widget_info
*info
= instance
->info
;
1047 /* instance has already been removed from the list; free it */
1048 destroy_one_instance (instance
);
1049 /* if there are no instances left, free the info too */
1050 if (!info
->instances
)
1051 lw_destroy_all_widgets (info
->id
);
1056 lw_destroy_all_widgets (id
)
1059 widget_info
* info
= get_widget_info (id
, True
);
1060 widget_instance
* instance
;
1061 widget_instance
* next
;
1065 for (instance
= info
->instances
; instance
; )
1067 next
= instance
->next
;
1068 destroy_one_instance (instance
);
1071 free_widget_info (info
);
1076 lw_destroy_everything ()
1078 while (all_widget_info
)
1079 lw_destroy_all_widgets (all_widget_info
->id
);
1083 lw_destroy_all_pop_ups ()
1087 widget_instance
* instance
;
1089 for (info
= all_widget_info
; info
; info
= next
)
1092 instance
= info
->instances
;
1093 if (instance
&& instance
->pop_up_p
)
1094 lw_destroy_all_widgets (info
->id
);
1099 extern Widget
first_child (/* Widget */); /* garbage */
1103 lw_raise_all_pop_up_widgets ()
1106 widget_instance
* instance
;
1107 Widget result
= NULL
;
1109 for (info
= all_widget_info
; info
; info
= info
->next
)
1110 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1111 if (instance
->pop_up_p
)
1113 Widget widget
= instance
->widget
;
1116 if (XtIsManaged (widget
)
1118 /* What a complete load of crap!!!!
1119 When a dialogShell is on the screen, it is not managed!
1121 || (lw_motif_widget_p (instance
->widget
) &&
1122 XtIsManaged (first_child (widget
)))
1128 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1136 lw_pop_all_widgets (id
, up
)
1140 widget_info
* info
= get_widget_info (id
, False
);
1141 widget_instance
* instance
;
1144 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1145 if (instance
->pop_up_p
&& instance
->widget
)
1147 #if defined (USE_LUCID)
1148 if (lw_lucid_widget_p (instance
->widget
))
1150 XtRealizeWidget (instance
->widget
);
1151 xlw_pop_instance (instance
, up
);
1154 #if defined (USE_MOTIF)
1155 if (lw_motif_widget_p (instance
->widget
))
1157 XtRealizeWidget (instance
->widget
);
1158 xm_pop_instance (instance
, up
);
1161 #if defined (USE_OLIT)
1162 if (lw_olit_widget_p (instance
->widget
))
1164 XtRealizeWidget (instance
->widget
);
1165 xol_pop_instance (instance
, up
);
1168 #if defined (USE_XAW)
1169 if (lw_xaw_widget_p (instance
->widget
))
1171 XtRealizeWidget (XtParent (instance
->widget
));
1172 XtRealizeWidget (instance
->widget
);
1173 xaw_pop_instance (instance
, up
);
1180 lw_pop_up_all_widgets (id
)
1183 lw_pop_all_widgets (id
, True
);
1187 lw_pop_down_all_widgets (id
)
1190 lw_pop_all_widgets (id
, False
);
1194 lw_popup_menu (widget
, event
)
1198 #if defined (USE_LUCID)
1199 if (lw_lucid_widget_p (widget
))
1200 xlw_popup_menu (widget
, event
);
1202 #if defined (USE_MOTIF)
1203 if (lw_motif_widget_p (widget
))
1204 xm_popup_menu (widget
, event
);
1206 #if defined (USE_OLIT)
1207 if (lw_olit_widget_p (widget
))
1208 xol_popup_menu (widget
, event
);
1210 #if defined (USE_XAW)
1211 if (lw_xaw_widget_p (widget
))
1212 xaw_popup_menu (widget
, event
);
1216 \f/* get the values back */
1218 get_one_value (instance
, val
)
1219 widget_instance
* instance
;
1222 Widget widget
= name_to_widget (instance
, val
->name
);
1226 #if defined (USE_LUCID)
1227 if (lw_lucid_widget_p (instance
->widget
))
1228 xlw_update_one_value (instance
, widget
, val
);
1230 #if defined (USE_MOTIF)
1231 if (lw_motif_widget_p (instance
->widget
))
1232 xm_update_one_value (instance
, widget
, val
);
1234 #if defined (USE_OLIT)
1235 if (lw_olit_widget_p (instance
->widget
))
1236 xol_update_one_value (instance
, widget
, val
);
1238 #if defined (USE_XAW)
1239 if (lw_xaw_widget_p (instance
->widget
))
1240 xaw_update_one_value (instance
, widget
, val
);
1249 lw_get_some_values (id
, val_out
)
1251 widget_value
* val_out
;
1253 widget_info
* info
= get_widget_info (id
, False
);
1254 widget_instance
* instance
;
1256 Boolean result
= False
;
1261 instance
= info
->instances
;
1265 for (val
= val_out
; val
; val
= val
->next
)
1266 if (get_one_value (instance
, val
))
1273 lw_get_all_values (id
)
1276 widget_info
* info
= get_widget_info (id
, False
);
1277 widget_value
* val
= info
->val
;
1278 if (lw_get_some_values (id
, val
))
1284 /* internal function used by the library dependent implementation to get the
1285 widget_value for a given widget in an instance */
1287 lw_get_widget_value_for_widget (instance
, w
)
1288 widget_instance
* instance
;
1291 char* name
= XtName (w
);
1293 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1294 if (!strcmp (cur
->name
, name
))
1299 \f/* update other instances value when one thing changed */
1301 /* To forbid recursive calls */
1302 static Boolean lwlib_updating
;
1304 /* This function can be used as a an XtCallback for the widgets that get
1305 modified to update other instances of the widgets. Closure should be the
1308 lw_internal_update_other_instances (widget
, closure
, call_data
)
1311 XtPointer call_data
;
1313 widget_instance
* instance
= (widget_instance
*)closure
;
1314 char* name
= XtName (widget
);
1316 widget_instance
* cur
;
1319 /* Avoid possibly infinite recursion. */
1323 /* protect against the widget being destroyed */
1324 if (XtWidgetBeingDestroyedP (widget
))
1327 /* Return immediately if there are no other instances */
1328 info
= instance
->info
;
1329 if (!info
->instances
->next
)
1332 lwlib_updating
= True
;
1334 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1336 if (val
&& get_one_value (instance
, val
))
1337 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1338 if (cur
!= instance
)
1339 set_one_value (cur
, val
, True
);
1341 lwlib_updating
= False
;
1348 lw_get_widget_id (w
)
1351 widget_instance
* instance
= get_widget_instance (w
, False
);
1353 return instance
? instance
->info
->id
: 0;
1356 \f/* set the keyboard focus */
1358 lw_set_keyboard_focus (parent
, w
)
1362 #if defined (USE_MOTIF)
1363 xm_set_keyboard_focus (parent
, w
);
1365 XtSetKeyboardFocus (parent
, w
);
1371 show_one_widget_busy (w
, flag
)
1375 Pixel foreground
= 0;
1376 Pixel background
= 1;
1377 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1378 if (!widget_to_invert
)
1379 widget_to_invert
= w
;
1381 XtVaGetValues (widget_to_invert
,
1382 XtNforeground
, &foreground
,
1383 XtNbackground
, &background
,
1385 XtVaSetValues (widget_to_invert
,
1386 XtNforeground
, background
,
1387 XtNbackground
, foreground
,
1392 lw_show_busy (w
, busy
)
1396 widget_instance
* instance
= get_widget_instance (w
, False
);
1398 widget_instance
* next
;
1402 info
= instance
->info
;
1403 if (info
->busy
!= busy
)
1405 for (next
= info
->instances
; next
; next
= next
->next
)
1407 show_one_widget_busy (next
->widget
, busy
);
1413 /* This hack exists because Lucid/Athena need to execute the strange
1414 function below to support geometry management. */
1416 lw_refigure_widget (w
, doit
)
1420 #if defined (USE_XAW)
1421 XawPanedSetRefigureMode (w
, doit
);
1423 #if defined (USE_MOTIF)
1427 XtUnmanageChild (w
);
1431 /* Toolkit independent way of determining if an event window is in the
1434 lw_window_is_in_menubar (win
, menubar_widget
)
1436 Widget menubar_widget
;
1438 return menubar_widget
1439 #if defined (USE_LUCID)
1440 && XtWindow (menubar_widget
) == win
;
1442 #if defined (USE_MOTIF)
1443 && ((XtWindow (menubar_widget
) == win
)
1444 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1445 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1446 == menubar_widget
)));
1450 /* Motif hack to set the main window areas. */
1452 lw_set_main_areas (parent
, menubar
, work_area
)
1457 #if defined (USE_MOTIF)
1458 xm_set_main_areas (parent
, menubar
, work_area
);
1462 /* Manage resizing for Motif. This disables resizing when the menubar
1463 is about to be modified. */
1465 lw_allow_resizing (w
, flag
)
1469 #if defined (USE_MOTIF)
1470 xm_manage_resizing (w
, flag
);
1475 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1476 set to an appropriate enumerator of type enum menu_separator.
1477 MOTIF_P non-zero means map separator types not supported by Motif
1478 to similar ones that are supported. */
1481 lw_separator_p (label
, type
, motif_p
)
1483 enum menu_separator
*type
;
1486 int separator_p
= 0;
1488 if (strlen (label
) >= 3
1489 && bcmp (label
, "--:", 3) == 0)
1491 static struct separator_table
1494 enum menu_separator type
;
1498 {"space", SEPARATOR_NO_LINE
},
1499 {"noLine", SEPARATOR_NO_LINE
},
1500 {"singleLine", SEPARATOR_SINGLE_LINE
},
1501 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1502 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1503 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1504 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1505 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1506 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1507 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1508 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1509 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1510 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1511 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1518 for (i
= 0; separator_names
[i
].name
; ++i
)
1519 if (strcmp (label
, separator_names
[i
].name
) == 0)
1522 *type
= separator_names
[i
].type
;
1524 /* If separator type is not supported under Motif,
1525 use a similar one. */
1526 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1531 else if (strlen (label
) > 3
1532 && bcmp (label
, "--", 2) == 0
1535 /* Alternative, more Emacs-style names. */
1536 static struct separator_table
1539 enum menu_separator type
;
1543 {"space", SEPARATOR_NO_LINE
},
1544 {"no-line", SEPARATOR_NO_LINE
},
1545 {"single-line", SEPARATOR_SINGLE_LINE
},
1546 {"double-line", SEPARATOR_DOUBLE_LINE
},
1547 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1548 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1549 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1550 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1551 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1552 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1553 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1554 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1555 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1556 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1563 for (i
= 0; separator_names
[i
].name
; ++i
)
1564 if (strcmp (label
, separator_names
[i
].name
) == 0)
1567 *type
= separator_names
[i
].type
;
1569 /* If separator type is not supported under Motif,
1570 use a similar one. */
1571 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1578 /* Old-style separator, maybe. It's a separator if it contains
1580 while (*label
== '-')
1582 separator_p
= *label
== 0;
1583 *type
= SEPARATOR_SHADOW_ETCHED_IN
;