1 /* A general interface to the widgets of different toolkits.
3 Copyright (C) 1992, 1993 Lucid, Inc.
4 Copyright (C) 1994-1996, 1999-2017 Free Software Foundation, Inc.
6 This file is part of the Lucid Widget Library.
8 The Lucid Widget Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 The Lucid Widget Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25 #include <c-strcase.h>
27 #include <sys/types.h>
29 #include "lwlib-int.h"
30 #include "lwlib-utils.h"
31 #include <X11/StringDefs.h>
33 #if defined (USE_LUCID)
34 #include "lwlib-Xlw.h"
36 #if defined (USE_MOTIF)
38 #else /* not USE_MOTIF */
39 #if defined (USE_LUCID)
41 #endif /* not USE_MOTIF && USE_LUCID */
45 #include <X11/Xaw3d/Paned.h>
46 #else /* !HAVE_XAW3D */
47 #include <X11/Xaw/Paned.h>
48 #endif /* HAVE_XAW3D */
49 #include "lwlib-Xaw.h"
52 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
53 #error At least one of USE_LUCID or USE_MOTIF must be defined.
57 #define max(x, y) ((x) > (y) ? (x) : (y))
60 /* List of all widgets managed by the library. */
62 all_widget_info
= NULL
;
65 const char *lwlib_toolkit_type
= "motif";
67 const char *lwlib_toolkit_type
= "lucid";
70 static widget_value
*merge_widget_value (widget_value
*,
73 static void instantiate_widget_instance (widget_instance
*);
74 static void free_widget_value_tree (widget_value
*);
75 static widget_value
*copy_widget_value_tree (widget_value
*,
77 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
79 lw_callback
, lw_callback
,
80 lw_callback
, lw_callback
);
81 static void free_widget_info (widget_info
*);
82 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
83 static widget_instance
*allocate_widget_instance (widget_info
*,
85 static void free_widget_instance (widget_instance
*);
86 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
87 static widget_instance
*get_widget_instance (Widget
, Boolean
);
88 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
89 static Boolean
safe_strcmp (const char *, const char *);
90 static Widget
name_to_widget (widget_instance
*, const char *);
91 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
92 static void update_one_widget_instance (widget_instance
*, Boolean
);
93 static void update_all_widget_values (widget_info
*, Boolean
);
94 static void initialize_widget_instance (widget_instance
*);
95 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
96 static Boolean
dialog_spec_p (const char *);
97 static void destroy_one_instance (widget_instance
*);
98 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
99 static Boolean
get_one_value (widget_instance
*, widget_value
*);
100 static void show_one_widget_busy (Widget
, Boolean
);
103 free_widget_value_tree (widget_value
*wv
)
112 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
114 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
116 XtFree (wv
->toolkit_data
);
117 wv
->toolkit_data
= (void *) 0xDEADBEEF;
120 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
122 free_widget_value_tree (wv
->contents
);
123 wv
->contents
= (widget_value
*) 0xDEADBEEF;
127 free_widget_value_tree (wv
->next
);
128 wv
->next
= (widget_value
*) 0xDEADBEEF;
133 static widget_value
*
134 copy_widget_value_tree (widget_value
*val
, change_type change
)
140 if (val
== (widget_value
*) 1)
143 copy
= xmalloc (sizeof (widget_value
));
144 copy
->lname
= copy
->lkey
= Qnil
;
145 copy
->name
= xstrdup (val
->name
);
146 copy
->value
= val
->value
? xstrdup (val
->value
) : NULL
;
147 copy
->key
= val
->key
? xstrdup (val
->key
) : NULL
;
148 copy
->help
= val
->help
;
149 copy
->enabled
= val
->enabled
;
150 copy
->button_type
= val
->button_type
;
151 copy
->selected
= val
->selected
;
152 copy
->edited
= False
;
153 copy
->change
= change
;
154 copy
->this_one_change
= change
;
155 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
156 copy
->call_data
= val
->call_data
;
157 copy
->next
= copy_widget_value_tree (val
->next
, change
);
158 copy
->toolkit_data
= NULL
;
159 copy
->free_toolkit_data
= False
;
164 allocate_widget_info (const char* type
,
168 lw_callback pre_activate_cb
,
169 lw_callback selection_cb
,
170 lw_callback post_activate_cb
,
171 lw_callback highlight_cb
)
173 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
174 info
->type
= xstrdup (type
);
175 info
->name
= xstrdup (name
);
177 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
179 info
->pre_activate_cb
= pre_activate_cb
;
180 info
->selection_cb
= selection_cb
;
181 info
->post_activate_cb
= post_activate_cb
;
182 info
->highlight_cb
= highlight_cb
;
183 info
->instances
= NULL
;
185 info
->next
= all_widget_info
;
186 all_widget_info
= info
;
192 free_widget_info (widget_info
*info
)
196 free_widget_value_tree (info
->val
);
197 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
202 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
204 widget_instance
* instance
= (widget_instance
*)closure
;
206 /* be very conservative */
207 if (instance
->widget
== widget
)
208 instance
->widget
= NULL
;
211 static widget_instance
*
212 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
214 widget_instance
* instance
=
215 (widget_instance
*) xmalloc (sizeof (widget_instance
));
216 memset (instance
, 0, sizeof *instance
);
217 instance
->parent
= parent
;
218 instance
->pop_up_p
= pop_up_p
;
219 instance
->info
= info
;
220 instance
->next
= info
->instances
;
221 info
->instances
= instance
;
223 instantiate_widget_instance (instance
);
225 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
226 mark_widget_destroyed
, (XtPointer
)instance
);
231 free_widget_instance (widget_instance
*instance
)
233 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
238 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
242 for (prev
= NULL
, info
= all_widget_info
;
244 prev
= info
, info
= info
->next
)
250 prev
->next
= info
->next
;
252 all_widget_info
= info
->next
;
259 /* Internal function used by the library dependent implementation to get the
260 widget_value for a given widget in an instance */
262 lw_get_widget_info (LWLIB_ID id
)
264 return get_widget_info (id
, 0);
267 static widget_instance
*
268 get_widget_instance (Widget widget
, Boolean remove_p
)
271 widget_instance
* instance
;
272 widget_instance
* prev
;
273 for (info
= all_widget_info
; info
; info
= info
->next
)
274 for (prev
= NULL
, instance
= info
->instances
;
276 prev
= instance
, instance
= instance
->next
)
277 if (instance
->widget
== widget
)
282 prev
->next
= instance
->next
;
284 info
->instances
= instance
->next
;
288 return (widget_instance
*) 0;
291 /* Value is a pointer to the widget_instance corresponding to
292 WIDGET, or null if WIDGET is not a lwlib widget. */
295 lw_get_widget_instance (Widget widget
)
297 return get_widget_instance (widget
, False
);
300 static widget_instance
*
301 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
303 widget_info
* info
= get_widget_info (id
, False
);
304 widget_instance
* instance
;
307 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
308 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
315 /* utility function for widget_value */
317 safe_strcmp (const char *s1
, const char *s2
)
319 if (!!s1
^ !!s2
) return True
;
320 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
325 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
326 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
328 (oc == NO_CHANGE ? "none" : \
329 (oc == INVISIBLE_CHANGE ? "invisible" : \
330 (oc == VISIBLE_CHANGE ? "visible" : \
331 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
333 (nc == NO_CHANGE ? "none" : \
334 (nc == INVISIBLE_CHANGE ? "invisible" : \
335 (nc == VISIBLE_CHANGE ? "visible" : \
336 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
339 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
343 static widget_value
*
344 merge_widget_value (widget_value
*val1
,
349 change_type change
, this_one_change
;
350 widget_value
* merged_next
;
351 widget_value
* merged_contents
;
358 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
366 free_widget_value_tree (val1
);
372 if (safe_strcmp (val1
->name
, val2
->name
))
374 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
375 val1
->name
, val2
->name
);
376 change
= max (change
, STRUCTURAL_CHANGE
);
377 dupstring (&val1
->name
, val2
->name
);
379 if (safe_strcmp (val1
->value
, val2
->value
))
381 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
382 val1
->value
, val2
->value
);
383 change
= max (change
, VISIBLE_CHANGE
);
384 dupstring (&val1
->value
, val2
->value
);
386 if (safe_strcmp (val1
->key
, val2
->key
))
388 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
389 val1
->key
, val2
->key
);
390 change
= max (change
, VISIBLE_CHANGE
);
391 dupstring (&val1
->key
, val2
->key
);
393 if (! EQ (val1
->help
, val2
->help
))
395 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
396 val1
->help
, val2
->help
);
397 change
= max (change
, VISIBLE_CHANGE
);
398 val1
->help
= val2
->help
;
400 if (val1
->enabled
!= val2
->enabled
)
402 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
403 val1
->enabled
, val2
->enabled
);
404 change
= max (change
, VISIBLE_CHANGE
);
405 val1
->enabled
= val2
->enabled
;
407 if (val1
->button_type
!= val2
->button_type
)
409 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
410 val1
->button_type
, val2
->button_type
);
411 change
= max (change
, VISIBLE_CHANGE
);
412 val1
->button_type
= val2
->button_type
;
414 if (val1
->selected
!= val2
->selected
)
416 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
417 val1
->selected
, val2
->selected
);
418 change
= max (change
, VISIBLE_CHANGE
);
419 val1
->selected
= val2
->selected
;
421 if (val1
->call_data
!= val2
->call_data
)
423 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
424 val1
->call_data
, val2
->call_data
);
425 change
= max (change
, INVISIBLE_CHANGE
);
426 val1
->call_data
= val2
->call_data
;
432 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
435 if (val1
->contents
&& !merged_contents
)
437 /* This used to say INVISIBLE_CHANGE,
438 but it is visible and vitally important when
439 the contents of the menu bar itself are entirely deleted.
441 But maybe it doesn't matter. This fails to fix the bug. */
442 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
444 change
= max (change
, STRUCTURAL_CHANGE
);
446 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
448 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
450 change
= max (change
, INVISIBLE_CHANGE
);
451 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
453 change
= max (merged_contents
->change
, change
);
458 val1
->contents
= merged_contents
;
461 this_one_change
= change
;
463 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
465 if (val1
->next
&& !merged_next
)
467 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
469 change
= max (change
, STRUCTURAL_CHANGE
);
471 else if (merged_next
)
473 if (merged_next
->change
)
474 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
476 change
= max (change
, merged_next
->change
);
479 val1
->next
= merged_next
;
481 val1
->this_one_change
= this_one_change
;
482 val1
->change
= change
;
484 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
487 if (val1
->free_toolkit_data
)
488 XtFree (val1
->toolkit_data
);
489 val1
->toolkit_data
= NULL
;
496 /* modifying the widgets */
498 name_to_widget (widget_instance
*instance
, const char *name
)
500 Widget widget
= NULL
;
502 if (!instance
->widget
)
505 if (!strcmp (XtName (instance
->widget
), name
))
506 widget
= instance
->widget
;
509 int length
= strlen (name
) + 2;
510 char* real_name
= (char *) xmalloc (length
);
512 strcpy (real_name
+ 1, name
);
514 widget
= XtNameToWidget (instance
->widget
, real_name
);
522 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
524 Widget widget
= name_to_widget (instance
, val
->name
);
528 #if defined (USE_LUCID)
529 if (lw_lucid_widget_p (instance
->widget
))
530 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
532 #if defined (USE_MOTIF)
533 if (lw_motif_widget_p (instance
->widget
))
534 xm_update_one_widget (instance
, widget
, val
, deep_p
);
536 #if defined (USE_XAW)
537 if (lw_xaw_widget_p (instance
->widget
))
538 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
544 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
548 if (!instance
->widget
)
549 /* the widget was destroyed */
552 for (val
= instance
->info
->val
; val
; val
= val
->next
)
553 if (val
->change
!= NO_CHANGE
)
554 set_one_value (instance
, val
, deep_p
);
558 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
560 widget_instance
* instance
;
563 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
564 update_one_widget_instance (instance
, deep_p
);
566 for (val
= info
->val
; val
; val
= val
->next
)
567 val
->change
= NO_CHANGE
;
571 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
573 widget_info
* info
= get_widget_info (id
, False
);
574 widget_value
* new_val
;
575 widget_value
* next_new_val
;
585 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
587 next_new_val
= new_val
->next
;
588 new_val
->next
= NULL
;
590 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
591 if (!strcmp (cur
->name
, new_val
->name
))
596 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
599 prev
->next
= cur
? cur
: next
;
601 info
->val
= cur
? cur
: next
;
608 /* Could not find it, add it */
610 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
612 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
615 new_val
->next
= next_new_val
;
618 update_all_widget_values (info
, deep_p
);
623 /* creating the widgets */
626 initialize_widget_instance (widget_instance
*instance
)
630 for (val
= instance
->info
->val
; val
; val
= val
->next
)
631 val
->change
= STRUCTURAL_CHANGE
;
633 update_one_widget_instance (instance
, True
);
635 for (val
= instance
->info
->val
; val
; val
= val
->next
)
636 val
->change
= NO_CHANGE
;
640 static widget_creation_function
641 find_in_table (const char *type
, const widget_creation_entry
*table
)
643 const widget_creation_entry
* cur
;
644 for (cur
= table
; cur
->type
; cur
++)
645 if (!c_strcasecmp (type
, cur
->type
))
646 return cur
->function
;
651 dialog_spec_p (const char *name
)
653 /* return True if name matches [EILPQeilpq][1-9][Bb] or
654 [EILPQeilpq][1-9][Bb][Rr][1-9] */
660 case 'E': case 'I': case 'L': case 'P': case 'Q':
661 case 'e': case 'i': case 'l': case 'p': case 'q':
662 if (name
[1] >= '0' && name
[1] <= '9')
664 if (name
[2] != 'B' && name
[2] != 'b')
668 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
670 if ((name
[3] == 'R' || name
[3] == 'r')
671 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
684 instantiate_widget_instance (widget_instance
*instance
)
686 widget_creation_function function
= NULL
;
688 #if defined (USE_LUCID)
690 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
692 #if defined(USE_MOTIF)
694 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
696 #if defined (USE_XAW)
698 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
703 if (dialog_spec_p (instance
->info
->type
))
705 #if defined (USE_LUCID)
708 #if defined(USE_MOTIF)
710 function
= xm_create_dialog
;
712 #if defined (USE_XAW)
714 function
= xaw_create_dialog
;
721 printf ("No creation function for widget type %s\n",
722 instance
->info
->type
);
726 instance
->widget
= (*function
) (instance
);
728 if (!instance
->widget
)
731 /* XtRealizeWidget (instance->widget);*/
735 lw_register_widget (const char* type
,
739 lw_callback pre_activate_cb
,
740 lw_callback selection_cb
,
741 lw_callback post_activate_cb
,
742 lw_callback highlight_cb
)
744 if (!get_widget_info (id
, False
))
745 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
746 post_activate_cb
, highlight_cb
);
750 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
752 widget_instance
* instance
;
754 instance
= find_instance (id
, parent
, pop_up_p
);
755 return instance
? instance
->widget
: NULL
;
759 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
761 widget_instance
* instance
;
764 instance
= find_instance (id
, parent
, pop_up_p
);
767 info
= get_widget_info (id
, False
);
770 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
771 initialize_widget_instance (instance
);
773 if (!instance
->widget
)
775 return instance
->widget
;
779 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
780 Widget parent
, Boolean pop_up_p
,
781 lw_callback pre_activate_cb
, lw_callback selection_cb
,
782 lw_callback post_activate_cb
, lw_callback highlight_cb
)
784 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
785 post_activate_cb
, highlight_cb
);
786 return lw_make_widget (id
, parent
, pop_up_p
);
790 /* destroying the widgets */
792 destroy_one_instance (widget_instance
*instance
)
794 /* Remove the destroy callback on the widget; that callback will try to
795 dereference the instance object (to set its widget slot to 0, since the
796 widget is dead.) Since the instance is now dead, we don't have to worry
797 about the fact that its widget is dead too.
799 This happens in the Phase2Destroy of the widget, so this callback would
800 not have been run until arbitrarily long after the instance was freed.
802 if (instance
->widget
)
803 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
804 mark_widget_destroyed
, (XtPointer
)instance
);
806 if (instance
->widget
)
808 /* The else are pretty tricky here, including the empty statement
809 at the end because it would be very bad to destroy a widget
811 #if defined (USE_LUCID)
812 if (lw_lucid_widget_p (instance
->widget
))
813 xlw_destroy_instance (instance
);
816 #if defined (USE_MOTIF)
817 if (lw_motif_widget_p (instance
->widget
))
818 xm_destroy_instance (instance
);
821 #if defined (USE_XAW)
822 if (lw_xaw_widget_p (instance
->widget
))
823 xaw_destroy_instance (instance
);
827 /* Empty compound statement to terminate if-then-else chain. */
831 free_widget_instance (instance
);
835 lw_destroy_widget (Widget w
)
837 widget_instance
* instance
= get_widget_instance (w
, True
);
841 widget_info
*info
= instance
->info
;
842 /* instance has already been removed from the list; free it */
843 destroy_one_instance (instance
);
844 /* if there are no instances left, free the info too */
845 if (!info
->instances
)
846 lw_destroy_all_widgets (info
->id
);
851 lw_destroy_all_widgets (LWLIB_ID id
)
853 widget_info
* info
= get_widget_info (id
, True
);
854 widget_instance
* instance
;
855 widget_instance
* next
;
859 for (instance
= info
->instances
; instance
; )
861 next
= instance
->next
;
862 destroy_one_instance (instance
);
865 free_widget_info (info
);
870 lw_destroy_everything (void)
872 while (all_widget_info
)
873 lw_destroy_all_widgets (all_widget_info
->id
);
877 lw_destroy_all_pop_ups (void)
881 widget_instance
* instance
;
883 for (info
= all_widget_info
; info
; info
= next
)
886 instance
= info
->instances
;
887 if (instance
&& instance
->pop_up_p
)
888 lw_destroy_all_widgets (info
->id
);
893 extern Widget
first_child (Widget
); /* garbage */
897 lw_raise_all_pop_up_widgets (void)
900 widget_instance
* instance
;
901 Widget result
= NULL
;
903 for (info
= all_widget_info
; info
; info
= info
->next
)
904 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
905 if (instance
->pop_up_p
)
907 Widget widget
= instance
->widget
;
910 if (XtIsManaged (widget
)
912 /* What a complete load of crap!!!!
913 When a dialogShell is on the screen, it is not managed!
915 || (lw_motif_widget_p (instance
->widget
) &&
916 XtIsManaged (first_child (widget
)))
922 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
930 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
932 widget_info
* info
= get_widget_info (id
, False
);
933 widget_instance
* instance
;
936 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
937 if (instance
->pop_up_p
&& instance
->widget
)
939 #if defined (USE_LUCID)
940 if (lw_lucid_widget_p (instance
->widget
))
942 XtRealizeWidget (instance
->widget
);
943 xlw_pop_instance (instance
, up
);
946 #if defined (USE_MOTIF)
947 if (lw_motif_widget_p (instance
->widget
))
949 XtRealizeWidget (instance
->widget
);
950 xm_pop_instance (instance
, up
);
953 #if defined (USE_XAW)
954 if (lw_xaw_widget_p (instance
->widget
))
956 XtRealizeWidget (XtParent (instance
->widget
));
957 XtRealizeWidget (instance
->widget
);
958 xaw_pop_instance (instance
, up
);
965 lw_pop_up_all_widgets (LWLIB_ID id
)
967 lw_pop_all_widgets (id
, True
);
971 lw_pop_down_all_widgets (LWLIB_ID id
)
973 lw_pop_all_widgets (id
, False
);
977 lw_popup_menu (Widget widget
, XEvent
*event
)
979 #if defined (USE_LUCID)
980 if (lw_lucid_widget_p (widget
))
981 xlw_popup_menu (widget
, event
);
983 #if defined (USE_MOTIF)
984 if (lw_motif_widget_p (widget
))
985 xm_popup_menu (widget
, event
);
987 #if defined (USE_XAW)
988 if (lw_xaw_widget_p (widget
))
989 xaw_popup_menu (widget
, event
);
993 \f/* get the values back */
995 get_one_value (widget_instance
*instance
, widget_value
*val
)
997 Widget widget
= name_to_widget (instance
, val
->name
);
1001 #if defined (USE_LUCID)
1002 if (lw_lucid_widget_p (instance
->widget
))
1003 xlw_update_one_value (instance
, widget
, val
);
1005 #if defined (USE_MOTIF)
1006 if (lw_motif_widget_p (instance
->widget
))
1007 xm_update_one_value (instance
, widget
, val
);
1009 #if defined (USE_XAW)
1010 if (lw_xaw_widget_p (instance
->widget
))
1011 xaw_update_one_value (instance
, widget
, val
);
1020 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1022 widget_info
* info
= get_widget_info (id
, False
);
1023 widget_instance
* instance
;
1025 Boolean result
= False
;
1030 instance
= info
->instances
;
1034 for (val
= val_out
; val
; val
= val
->next
)
1035 if (get_one_value (instance
, val
))
1042 lw_get_all_values (LWLIB_ID id
)
1044 widget_info
* info
= get_widget_info (id
, False
);
1045 widget_value
* val
= info
->val
;
1046 if (lw_get_some_values (id
, val
))
1052 /* internal function used by the library dependent implementation to get the
1053 widget_value for a given widget in an instance */
1055 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1057 char* name
= XtName (w
);
1059 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1060 if (!strcmp (cur
->name
, name
))
1065 \f/* update other instances value when one thing changed */
1067 /* To forbid recursive calls */
1068 static Boolean lwlib_updating
;
1070 /* This function can be used as an XtCallback for the widgets that get
1071 modified to update other instances of the widgets. Closure should be the
1074 lw_internal_update_other_instances (Widget widget
,
1076 XtPointer call_data
)
1078 widget_instance
* instance
= (widget_instance
*)closure
;
1079 char* name
= XtName (widget
);
1081 widget_instance
* cur
;
1084 /* Avoid possibly infinite recursion. */
1088 /* protect against the widget being destroyed */
1089 if (XtWidgetBeingDestroyedP (widget
))
1092 /* Return immediately if there are no other instances */
1093 info
= instance
->info
;
1094 if (!info
->instances
->next
)
1097 lwlib_updating
= True
;
1099 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1101 if (val
&& get_one_value (instance
, val
))
1102 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1103 if (cur
!= instance
)
1104 set_one_value (cur
, val
, True
);
1106 lwlib_updating
= False
;
1113 lw_get_widget_id (Widget w
)
1115 widget_instance
* instance
= get_widget_instance (w
, False
);
1117 return instance
? instance
->info
->id
: 0;
1120 \f/* set the keyboard focus */
1122 lw_set_keyboard_focus (Widget parent
, Widget w
)
1124 #if defined (USE_MOTIF)
1125 xm_set_keyboard_focus (parent
, w
);
1127 XtSetKeyboardFocus (parent
, w
);
1133 show_one_widget_busy (Widget w
, Boolean flag
)
1135 Pixel foreground
= 0;
1136 Pixel background
= 1;
1137 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1138 if (!widget_to_invert
)
1139 widget_to_invert
= w
;
1141 XtVaGetValues (widget_to_invert
,
1142 XtNforeground
, &foreground
,
1143 XtNbackground
, &background
,
1145 XtVaSetValues (widget_to_invert
,
1146 XtNforeground
, background
,
1147 XtNbackground
, foreground
,
1152 lw_show_busy (Widget w
, Boolean busy
)
1154 widget_instance
* instance
= get_widget_instance (w
, False
);
1156 widget_instance
* next
;
1160 info
= instance
->info
;
1161 if (info
->busy
!= busy
)
1163 for (next
= info
->instances
; next
; next
= next
->next
)
1165 show_one_widget_busy (next
->widget
, busy
);
1171 /* This hack exists because Lucid/Athena need to execute the strange
1172 function below to support geometry management. */
1174 lw_refigure_widget (Widget w
, Boolean doit
)
1176 #if defined (USE_XAW)
1177 XawPanedSetRefigureMode (w
, doit
);
1179 #if defined (USE_MOTIF)
1183 XtUnmanageChild (w
);
1187 /* Toolkit independent way of determining if an event window is in the
1190 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1192 return menubar_widget
1193 #if defined (USE_LUCID)
1194 && XtWindow (menubar_widget
) == win
;
1196 #if defined (USE_MOTIF)
1197 && ((XtWindow (menubar_widget
) == win
)
1198 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1199 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1200 == menubar_widget
)));
1204 /* Motif hack to set the main window areas. */
1206 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1208 #if defined (USE_MOTIF)
1209 xm_set_main_areas (parent
, menubar
, work_area
);
1213 /* Manage resizing for Motif. This disables resizing when the menubar
1214 is about to be modified. */
1216 lw_allow_resizing (Widget w
, Boolean flag
)
1218 #if defined (USE_MOTIF)
1219 xm_manage_resizing (w
, flag
);
1224 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1225 set to an appropriate enumerator of type enum menu_separator.
1226 MOTIF_P non-zero means map separator types not supported by Motif
1227 to similar ones that are supported. */
1230 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1232 int separator_p
= 0;
1234 if (strlen (label
) >= 3
1235 && memcmp (label
, "--:", 3) == 0)
1237 static struct separator_table
1240 enum menu_separator type
;
1244 {"space", SEPARATOR_NO_LINE
},
1245 {"noLine", SEPARATOR_NO_LINE
},
1246 {"singleLine", SEPARATOR_SINGLE_LINE
},
1247 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1248 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1249 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1250 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1251 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1252 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1253 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1254 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1255 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1256 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1257 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1264 for (i
= 0; separator_names
[i
].name
; ++i
)
1265 if (strcmp (label
, separator_names
[i
].name
) == 0)
1268 *type
= separator_names
[i
].type
;
1270 /* If separator type is not supported under Motif,
1271 use a similar one. */
1272 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1277 else if (strlen (label
) > 3
1278 && memcmp (label
, "--", 2) == 0
1281 /* Alternative, more Emacs-style names. */
1282 static struct separator_table
1285 enum menu_separator type
;
1289 {"space", SEPARATOR_NO_LINE
},
1290 {"no-line", SEPARATOR_NO_LINE
},
1291 {"single-line", SEPARATOR_SINGLE_LINE
},
1292 {"double-line", SEPARATOR_DOUBLE_LINE
},
1293 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1294 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1295 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1296 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1297 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1298 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1299 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1300 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1301 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1302 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1309 for (i
= 0; separator_names
[i
].name
; ++i
)
1310 if (strcmp (label
, separator_names
[i
].name
) == 0)
1313 *type
= separator_names
[i
].type
;
1315 /* If separator type is not supported under Motif,
1316 use a similar one. */
1317 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1324 /* Old-style separator, maybe. It's a separator if it contains
1326 while (*label
== '-')
1328 separator_p
= *label
== 0;
1329 *type
= SEPARATOR_SHADOW_ETCHED_IN
;