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>
30 #include "lwlib-int.h"
31 #include "lwlib-utils.h"
32 #include <X11/StringDefs.h>
34 #if defined (USE_LUCID)
35 #include "lwlib-Xlw.h"
37 #if defined (USE_MOTIF)
39 #else /* not USE_MOTIF */
40 #if defined (USE_LUCID)
42 #endif /* not USE_MOTIF && USE_LUCID */
46 #include <X11/Xaw3d/Paned.h>
47 #else /* !HAVE_XAW3D */
48 #include <X11/Xaw/Paned.h>
49 #endif /* HAVE_XAW3D */
50 #include "lwlib-Xaw.h"
53 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
54 #error At least one of USE_LUCID or USE_MOTIF must be defined.
58 #define max(x, y) ((x) > (y) ? (x) : (y))
61 /* List of all widgets managed by the library. */
63 all_widget_info
= NULL
;
66 const char *lwlib_toolkit_type
= "motif";
68 const char *lwlib_toolkit_type
= "lucid";
71 static widget_value
*merge_widget_value (widget_value
*,
74 static void instantiate_widget_instance (widget_instance
*);
75 static void free_widget_value_tree (widget_value
*);
76 static widget_value
*copy_widget_value_tree (widget_value
*,
78 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
80 lw_callback
, lw_callback
,
81 lw_callback
, lw_callback
);
82 static void free_widget_info (widget_info
*);
83 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
84 static widget_instance
*allocate_widget_instance (widget_info
*,
86 static void free_widget_instance (widget_instance
*);
87 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
88 static widget_instance
*get_widget_instance (Widget
, Boolean
);
89 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
90 static Boolean
safe_strcmp (const char *, const char *);
91 static Widget
name_to_widget (widget_instance
*, const char *);
92 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
93 static void update_one_widget_instance (widget_instance
*, Boolean
);
94 static void update_all_widget_values (widget_info
*, Boolean
);
95 static void initialize_widget_instance (widget_instance
*);
96 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
97 static Boolean
dialog_spec_p (const char *);
98 static void destroy_one_instance (widget_instance
*);
99 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
100 static Boolean
get_one_value (widget_instance
*, widget_value
*);
101 static void show_one_widget_busy (Widget
, Boolean
);
104 free_widget_value_tree (widget_value
*wv
)
113 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
115 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
117 XtFree (wv
->toolkit_data
);
118 wv
->toolkit_data
= (void *) 0xDEADBEEF;
121 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
123 free_widget_value_tree (wv
->contents
);
124 wv
->contents
= (widget_value
*) 0xDEADBEEF;
128 free_widget_value_tree (wv
->next
);
129 wv
->next
= (widget_value
*) 0xDEADBEEF;
134 static widget_value
*
135 copy_widget_value_tree (widget_value
*val
, change_type change
)
141 if (val
== (widget_value
*) 1)
144 copy
= xmalloc (sizeof (widget_value
));
145 copy
->lname
= copy
->lkey
= Qnil
;
146 copy
->name
= xstrdup (val
->name
);
147 copy
->value
= val
->value
? xstrdup (val
->value
) : NULL
;
148 copy
->key
= val
->key
? xstrdup (val
->key
) : NULL
;
149 copy
->help
= val
->help
;
150 copy
->enabled
= val
->enabled
;
151 copy
->button_type
= val
->button_type
;
152 copy
->selected
= val
->selected
;
153 copy
->edited
= False
;
154 copy
->change
= change
;
155 copy
->this_one_change
= change
;
156 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
157 copy
->call_data
= val
->call_data
;
158 copy
->next
= copy_widget_value_tree (val
->next
, change
);
159 copy
->toolkit_data
= NULL
;
160 copy
->free_toolkit_data
= False
;
165 allocate_widget_info (const char* type
,
169 lw_callback pre_activate_cb
,
170 lw_callback selection_cb
,
171 lw_callback post_activate_cb
,
172 lw_callback highlight_cb
)
174 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
175 info
->type
= xstrdup (type
);
176 info
->name
= xstrdup (name
);
178 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
180 info
->pre_activate_cb
= pre_activate_cb
;
181 info
->selection_cb
= selection_cb
;
182 info
->post_activate_cb
= post_activate_cb
;
183 info
->highlight_cb
= highlight_cb
;
184 info
->instances
= NULL
;
186 info
->next
= all_widget_info
;
187 all_widget_info
= info
;
193 free_widget_info (widget_info
*info
)
197 free_widget_value_tree (info
->val
);
198 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
203 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
205 widget_instance
* instance
= (widget_instance
*)closure
;
207 /* be very conservative */
208 if (instance
->widget
== widget
)
209 instance
->widget
= NULL
;
212 static widget_instance
*
213 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
215 widget_instance
* instance
=
216 (widget_instance
*) xmalloc (sizeof (widget_instance
));
217 memset (instance
, 0, sizeof *instance
);
218 instance
->parent
= parent
;
219 instance
->pop_up_p
= pop_up_p
;
220 instance
->info
= info
;
221 instance
->next
= info
->instances
;
222 info
->instances
= instance
;
224 instantiate_widget_instance (instance
);
226 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
227 mark_widget_destroyed
, (XtPointer
)instance
);
232 free_widget_instance (widget_instance
*instance
)
234 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
239 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
243 for (prev
= NULL
, info
= all_widget_info
;
245 prev
= info
, info
= info
->next
)
251 prev
->next
= info
->next
;
253 all_widget_info
= info
->next
;
260 /* Internal function used by the library dependent implementation to get the
261 widget_value for a given widget in an instance */
263 lw_get_widget_info (LWLIB_ID id
)
265 return get_widget_info (id
, 0);
268 static widget_instance
*
269 get_widget_instance (Widget widget
, Boolean remove_p
)
272 widget_instance
* instance
;
273 widget_instance
* prev
;
274 for (info
= all_widget_info
; info
; info
= info
->next
)
275 for (prev
= NULL
, instance
= info
->instances
;
277 prev
= instance
, instance
= instance
->next
)
278 if (instance
->widget
== widget
)
283 prev
->next
= instance
->next
;
285 info
->instances
= instance
->next
;
289 return (widget_instance
*) 0;
292 /* Value is a pointer to the widget_instance corresponding to
293 WIDGET, or null if WIDGET is not a lwlib widget. */
296 lw_get_widget_instance (Widget widget
)
298 return get_widget_instance (widget
, False
);
301 static widget_instance
*
302 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
304 widget_info
* info
= get_widget_info (id
, False
);
305 widget_instance
* instance
;
308 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
309 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
316 /* utility function for widget_value */
318 safe_strcmp (const char *s1
, const char *s2
)
320 if (!!s1
^ !!s2
) return True
;
321 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
326 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
327 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
329 (oc == NO_CHANGE ? "none" : \
330 (oc == INVISIBLE_CHANGE ? "invisible" : \
331 (oc == VISIBLE_CHANGE ? "visible" : \
332 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
334 (nc == NO_CHANGE ? "none" : \
335 (nc == INVISIBLE_CHANGE ? "invisible" : \
336 (nc == VISIBLE_CHANGE ? "visible" : \
337 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
340 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
344 static widget_value
*
345 merge_widget_value (widget_value
*val1
,
350 change_type change
, this_one_change
;
351 widget_value
* merged_next
;
352 widget_value
* merged_contents
;
359 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
367 free_widget_value_tree (val1
);
373 if (safe_strcmp (val1
->name
, val2
->name
))
375 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
376 val1
->name
, val2
->name
);
377 change
= max (change
, STRUCTURAL_CHANGE
);
378 dupstring (&val1
->name
, val2
->name
);
380 if (safe_strcmp (val1
->value
, val2
->value
))
382 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
383 val1
->value
, val2
->value
);
384 change
= max (change
, VISIBLE_CHANGE
);
385 dupstring (&val1
->value
, val2
->value
);
387 if (safe_strcmp (val1
->key
, val2
->key
))
389 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
390 val1
->key
, val2
->key
);
391 change
= max (change
, VISIBLE_CHANGE
);
392 dupstring (&val1
->key
, val2
->key
);
394 if (! EQ (val1
->help
, val2
->help
))
396 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
397 val1
->help
, val2
->help
);
398 change
= max (change
, VISIBLE_CHANGE
);
399 val1
->help
= val2
->help
;
401 if (val1
->enabled
!= val2
->enabled
)
403 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
404 val1
->enabled
, val2
->enabled
);
405 change
= max (change
, VISIBLE_CHANGE
);
406 val1
->enabled
= val2
->enabled
;
408 if (val1
->button_type
!= val2
->button_type
)
410 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
411 val1
->button_type
, val2
->button_type
);
412 change
= max (change
, VISIBLE_CHANGE
);
413 val1
->button_type
= val2
->button_type
;
415 if (val1
->selected
!= val2
->selected
)
417 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
418 val1
->selected
, val2
->selected
);
419 change
= max (change
, VISIBLE_CHANGE
);
420 val1
->selected
= val2
->selected
;
422 if (val1
->call_data
!= val2
->call_data
)
424 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
425 val1
->call_data
, val2
->call_data
);
426 change
= max (change
, INVISIBLE_CHANGE
);
427 val1
->call_data
= val2
->call_data
;
433 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
436 if (val1
->contents
&& !merged_contents
)
438 /* This used to say INVISIBLE_CHANGE,
439 but it is visible and vitally important when
440 the contents of the menu bar itself are entirely deleted.
442 But maybe it doesn't matter. This fails to fix the bug. */
443 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
445 change
= max (change
, STRUCTURAL_CHANGE
);
447 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
449 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
451 change
= max (change
, INVISIBLE_CHANGE
);
452 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
454 change
= max (merged_contents
->change
, change
);
459 val1
->contents
= merged_contents
;
462 this_one_change
= change
;
464 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
466 if (val1
->next
&& !merged_next
)
468 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
470 change
= max (change
, STRUCTURAL_CHANGE
);
472 else if (merged_next
)
474 if (merged_next
->change
)
475 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
477 change
= max (change
, merged_next
->change
);
480 val1
->next
= merged_next
;
482 val1
->this_one_change
= this_one_change
;
483 val1
->change
= change
;
485 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
488 if (val1
->free_toolkit_data
)
489 XtFree (val1
->toolkit_data
);
490 val1
->toolkit_data
= NULL
;
497 /* modifying the widgets */
499 name_to_widget (widget_instance
*instance
, const char *name
)
501 Widget widget
= NULL
;
503 if (!instance
->widget
)
506 if (!strcmp (XtName (instance
->widget
), name
))
507 widget
= instance
->widget
;
510 int length
= strlen (name
) + 2;
511 char* real_name
= (char *) xmalloc (length
);
513 strcpy (real_name
+ 1, name
);
515 widget
= XtNameToWidget (instance
->widget
, real_name
);
523 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
525 Widget widget
= name_to_widget (instance
, val
->name
);
529 #if defined (USE_LUCID)
530 if (lw_lucid_widget_p (instance
->widget
))
531 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
533 #if defined (USE_MOTIF)
534 if (lw_motif_widget_p (instance
->widget
))
535 xm_update_one_widget (instance
, widget
, val
, deep_p
);
537 #if defined (USE_XAW)
538 if (lw_xaw_widget_p (instance
->widget
))
539 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
545 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
549 if (!instance
->widget
)
550 /* the widget was destroyed */
553 for (val
= instance
->info
->val
; val
; val
= val
->next
)
554 if (val
->change
!= NO_CHANGE
)
555 set_one_value (instance
, val
, deep_p
);
559 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
561 widget_instance
* instance
;
564 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
565 update_one_widget_instance (instance
, deep_p
);
567 for (val
= info
->val
; val
; val
= val
->next
)
568 val
->change
= NO_CHANGE
;
572 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
574 widget_info
* info
= get_widget_info (id
, False
);
575 widget_value
* new_val
;
576 widget_value
* next_new_val
;
586 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
588 next_new_val
= new_val
->next
;
589 new_val
->next
= NULL
;
591 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
592 if (!strcmp (cur
->name
, new_val
->name
))
597 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
600 prev
->next
= cur
? cur
: next
;
602 info
->val
= cur
? cur
: next
;
609 /* Could not find it, add it */
611 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
613 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
616 new_val
->next
= next_new_val
;
619 update_all_widget_values (info
, deep_p
);
624 /* creating the widgets */
627 initialize_widget_instance (widget_instance
*instance
)
631 for (val
= instance
->info
->val
; val
; val
= val
->next
)
632 val
->change
= STRUCTURAL_CHANGE
;
634 update_one_widget_instance (instance
, True
);
636 for (val
= instance
->info
->val
; val
; val
= val
->next
)
637 val
->change
= NO_CHANGE
;
641 static widget_creation_function
642 find_in_table (const char *type
, const widget_creation_entry
*table
)
644 const widget_creation_entry
* cur
;
645 for (cur
= table
; cur
->type
; cur
++)
646 if (!c_strcasecmp (type
, cur
->type
))
647 return cur
->function
;
652 dialog_spec_p (const char *name
)
654 /* return True if name matches [EILPQeilpq][1-9][Bb] or
655 [EILPQeilpq][1-9][Bb][Rr][1-9] */
661 case 'E': case 'I': case 'L': case 'P': case 'Q':
662 case 'e': case 'i': case 'l': case 'p': case 'q':
663 if (name
[1] >= '0' && name
[1] <= '9')
665 if (name
[2] != 'B' && name
[2] != 'b')
669 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
671 if ((name
[3] == 'R' || name
[3] == 'r')
672 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
685 instantiate_widget_instance (widget_instance
*instance
)
687 widget_creation_function function
= NULL
;
689 #if defined (USE_LUCID)
691 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
693 #if defined(USE_MOTIF)
695 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
697 #if defined (USE_XAW)
699 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
704 if (dialog_spec_p (instance
->info
->type
))
706 #if defined (USE_LUCID)
709 #if defined(USE_MOTIF)
711 function
= xm_create_dialog
;
713 #if defined (USE_XAW)
715 function
= xaw_create_dialog
;
722 printf ("No creation function for widget type %s\n",
723 instance
->info
->type
);
727 instance
->widget
= (*function
) (instance
);
729 if (!instance
->widget
)
732 /* XtRealizeWidget (instance->widget);*/
736 lw_register_widget (const char* type
,
740 lw_callback pre_activate_cb
,
741 lw_callback selection_cb
,
742 lw_callback post_activate_cb
,
743 lw_callback highlight_cb
)
745 if (!get_widget_info (id
, False
))
746 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
747 post_activate_cb
, highlight_cb
);
751 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
753 widget_instance
* instance
;
755 instance
= find_instance (id
, parent
, pop_up_p
);
756 return instance
? instance
->widget
: NULL
;
760 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
762 widget_instance
* instance
;
765 instance
= find_instance (id
, parent
, pop_up_p
);
768 info
= get_widget_info (id
, False
);
771 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
772 initialize_widget_instance (instance
);
774 if (!instance
->widget
)
776 return instance
->widget
;
780 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
781 Widget parent
, Boolean pop_up_p
,
782 lw_callback pre_activate_cb
, lw_callback selection_cb
,
783 lw_callback post_activate_cb
, lw_callback highlight_cb
)
785 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
786 post_activate_cb
, highlight_cb
);
787 return lw_make_widget (id
, parent
, pop_up_p
);
791 /* destroying the widgets */
793 destroy_one_instance (widget_instance
*instance
)
795 /* Remove the destroy callback on the widget; that callback will try to
796 dereference the instance object (to set its widget slot to 0, since the
797 widget is dead.) Since the instance is now dead, we don't have to worry
798 about the fact that its widget is dead too.
800 This happens in the Phase2Destroy of the widget, so this callback would
801 not have been run until arbitrarily long after the instance was freed.
803 if (instance
->widget
)
804 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
805 mark_widget_destroyed
, (XtPointer
)instance
);
807 if (instance
->widget
)
809 /* The else are pretty tricky here, including the empty statement
810 at the end because it would be very bad to destroy a widget
812 #if defined (USE_LUCID)
813 if (lw_lucid_widget_p (instance
->widget
))
814 xlw_destroy_instance (instance
);
817 #if defined (USE_MOTIF)
818 if (lw_motif_widget_p (instance
->widget
))
819 xm_destroy_instance (instance
);
822 #if defined (USE_XAW)
823 if (lw_xaw_widget_p (instance
->widget
))
824 xaw_destroy_instance (instance
);
828 /* Empty compound statement to terminate if-then-else chain. */
832 free_widget_instance (instance
);
836 lw_destroy_widget (Widget w
)
838 widget_instance
* instance
= get_widget_instance (w
, True
);
842 widget_info
*info
= instance
->info
;
843 /* instance has already been removed from the list; free it */
844 destroy_one_instance (instance
);
845 /* if there are no instances left, free the info too */
846 if (!info
->instances
)
847 lw_destroy_all_widgets (info
->id
);
852 lw_destroy_all_widgets (LWLIB_ID id
)
854 widget_info
* info
= get_widget_info (id
, True
);
855 widget_instance
* instance
;
856 widget_instance
* next
;
860 for (instance
= info
->instances
; instance
; )
862 next
= instance
->next
;
863 destroy_one_instance (instance
);
866 free_widget_info (info
);
871 lw_destroy_everything (void)
873 while (all_widget_info
)
874 lw_destroy_all_widgets (all_widget_info
->id
);
878 lw_destroy_all_pop_ups (void)
882 widget_instance
* instance
;
884 for (info
= all_widget_info
; info
; info
= next
)
887 instance
= info
->instances
;
888 if (instance
&& instance
->pop_up_p
)
889 lw_destroy_all_widgets (info
->id
);
894 extern Widget
first_child (Widget
); /* garbage */
898 lw_raise_all_pop_up_widgets (void)
901 widget_instance
* instance
;
902 Widget result
= NULL
;
904 for (info
= all_widget_info
; info
; info
= info
->next
)
905 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
906 if (instance
->pop_up_p
)
908 Widget widget
= instance
->widget
;
911 if (XtIsManaged (widget
)
913 /* What a complete load of crap!!!!
914 When a dialogShell is on the screen, it is not managed!
916 || (lw_motif_widget_p (instance
->widget
) &&
917 XtIsManaged (first_child (widget
)))
923 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
931 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
933 widget_info
* info
= get_widget_info (id
, False
);
934 widget_instance
* instance
;
937 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
938 if (instance
->pop_up_p
&& instance
->widget
)
940 #if defined (USE_LUCID)
941 if (lw_lucid_widget_p (instance
->widget
))
943 XtRealizeWidget (instance
->widget
);
944 xlw_pop_instance (instance
, up
);
947 #if defined (USE_MOTIF)
948 if (lw_motif_widget_p (instance
->widget
))
950 XtRealizeWidget (instance
->widget
);
951 xm_pop_instance (instance
, up
);
954 #if defined (USE_XAW)
955 if (lw_xaw_widget_p (instance
->widget
))
957 XtRealizeWidget (XtParent (instance
->widget
));
958 XtRealizeWidget (instance
->widget
);
959 xaw_pop_instance (instance
, up
);
966 lw_pop_up_all_widgets (LWLIB_ID id
)
968 lw_pop_all_widgets (id
, True
);
972 lw_pop_down_all_widgets (LWLIB_ID id
)
974 lw_pop_all_widgets (id
, False
);
978 lw_popup_menu (Widget widget
, XEvent
*event
)
980 #if defined (USE_LUCID)
981 if (lw_lucid_widget_p (widget
))
982 xlw_popup_menu (widget
, event
);
984 #if defined (USE_MOTIF)
985 if (lw_motif_widget_p (widget
))
986 xm_popup_menu (widget
, event
);
988 #if defined (USE_XAW)
989 if (lw_xaw_widget_p (widget
))
990 xaw_popup_menu (widget
, event
);
994 \f/* get the values back */
996 get_one_value (widget_instance
*instance
, widget_value
*val
)
998 Widget widget
= name_to_widget (instance
, val
->name
);
1002 #if defined (USE_LUCID)
1003 if (lw_lucid_widget_p (instance
->widget
))
1004 xlw_update_one_value (instance
, widget
, val
);
1006 #if defined (USE_MOTIF)
1007 if (lw_motif_widget_p (instance
->widget
))
1008 xm_update_one_value (instance
, widget
, val
);
1010 #if defined (USE_XAW)
1011 if (lw_xaw_widget_p (instance
->widget
))
1012 xaw_update_one_value (instance
, widget
, val
);
1021 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1023 widget_info
* info
= get_widget_info (id
, False
);
1024 widget_instance
* instance
;
1026 Boolean result
= False
;
1031 instance
= info
->instances
;
1035 for (val
= val_out
; val
; val
= val
->next
)
1036 if (get_one_value (instance
, val
))
1043 lw_get_all_values (LWLIB_ID id
)
1045 widget_info
* info
= get_widget_info (id
, False
);
1048 widget_value
* val
= info
->val
;
1049 if (lw_get_some_values (id
, val
))
1055 /* internal function used by the library dependent implementation to get the
1056 widget_value for a given widget in an instance */
1058 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1060 char* name
= XtName (w
);
1062 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1063 if (!strcmp (cur
->name
, name
))
1068 \f/* update other instances value when one thing changed */
1070 /* To forbid recursive calls */
1071 static Boolean lwlib_updating
;
1073 /* This function can be used as an XtCallback for the widgets that get
1074 modified to update other instances of the widgets. Closure should be the
1077 lw_internal_update_other_instances (Widget widget
,
1079 XtPointer call_data
)
1081 widget_instance
* instance
= (widget_instance
*)closure
;
1082 char* name
= XtName (widget
);
1084 widget_instance
* cur
;
1087 /* Avoid possibly infinite recursion. */
1091 /* protect against the widget being destroyed */
1092 if (XtWidgetBeingDestroyedP (widget
))
1095 /* Return immediately if there are no other instances */
1096 info
= instance
->info
;
1097 if (!info
->instances
->next
)
1100 lwlib_updating
= True
;
1102 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1104 if (val
&& get_one_value (instance
, val
))
1105 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1106 if (cur
!= instance
)
1107 set_one_value (cur
, val
, True
);
1109 lwlib_updating
= False
;
1116 lw_get_widget_id (Widget w
)
1118 widget_instance
* instance
= get_widget_instance (w
, False
);
1120 return instance
? instance
->info
->id
: 0;
1123 \f/* set the keyboard focus */
1125 lw_set_keyboard_focus (Widget parent
, Widget w
)
1127 #if defined (USE_MOTIF)
1128 xm_set_keyboard_focus (parent
, w
);
1130 XtSetKeyboardFocus (parent
, w
);
1136 show_one_widget_busy (Widget w
, Boolean flag
)
1138 Pixel foreground
= 0;
1139 Pixel background
= 1;
1140 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1141 if (!widget_to_invert
)
1142 widget_to_invert
= w
;
1144 XtVaGetValues (widget_to_invert
,
1145 XtNforeground
, &foreground
,
1146 XtNbackground
, &background
,
1148 XtVaSetValues (widget_to_invert
,
1149 XtNforeground
, background
,
1150 XtNbackground
, foreground
,
1155 lw_show_busy (Widget w
, Boolean busy
)
1157 widget_instance
* instance
= get_widget_instance (w
, False
);
1159 widget_instance
* next
;
1163 info
= instance
->info
;
1164 if (info
->busy
!= busy
)
1166 for (next
= info
->instances
; next
; next
= next
->next
)
1168 show_one_widget_busy (next
->widget
, busy
);
1174 /* This hack exists because Lucid/Athena need to execute the strange
1175 function below to support geometry management. */
1177 lw_refigure_widget (Widget w
, Boolean doit
)
1179 #if defined (USE_XAW)
1180 XawPanedSetRefigureMode (w
, doit
);
1182 #if defined (USE_MOTIF)
1186 XtUnmanageChild (w
);
1190 /* Toolkit independent way of determining if an event window is in the
1193 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1195 return menubar_widget
1196 #if defined (USE_LUCID)
1197 && XtWindow (menubar_widget
) == win
;
1199 #if defined (USE_MOTIF)
1200 && ((XtWindow (menubar_widget
) == win
)
1201 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1202 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1203 == menubar_widget
)));
1207 /* Motif hack to set the main window areas. */
1209 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1211 #if defined (USE_MOTIF)
1212 xm_set_main_areas (parent
, menubar
, work_area
);
1216 /* Manage resizing for Motif. This disables resizing when the menubar
1217 is about to be modified. */
1219 lw_allow_resizing (Widget w
, Boolean flag
)
1221 #if defined (USE_MOTIF)
1222 xm_manage_resizing (w
, flag
);
1227 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1228 set to an appropriate enumerator of type enum menu_separator.
1229 MOTIF_P non-zero means map separator types not supported by Motif
1230 to similar ones that are supported. */
1233 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1235 int separator_p
= 0;
1237 if (strlen (label
) >= 3
1238 && memcmp (label
, "--:", 3) == 0)
1240 static struct separator_table
1243 enum menu_separator type
;
1247 {"space", SEPARATOR_NO_LINE
},
1248 {"noLine", SEPARATOR_NO_LINE
},
1249 {"singleLine", SEPARATOR_SINGLE_LINE
},
1250 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1251 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1252 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1253 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1254 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1255 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1256 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1257 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1258 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1259 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1260 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1267 for (i
= 0; separator_names
[i
].name
; ++i
)
1268 if (strcmp (label
, separator_names
[i
].name
) == 0)
1271 *type
= separator_names
[i
].type
;
1273 /* If separator type is not supported under Motif,
1274 use a similar one. */
1275 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1280 else if (strlen (label
) > 3
1281 && memcmp (label
, "--", 2) == 0
1284 /* Alternative, more Emacs-style names. */
1285 static struct separator_table
1288 enum menu_separator type
;
1292 {"space", SEPARATOR_NO_LINE
},
1293 {"no-line", SEPARATOR_NO_LINE
},
1294 {"single-line", SEPARATOR_SINGLE_LINE
},
1295 {"double-line", SEPARATOR_DOUBLE_LINE
},
1296 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1297 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1298 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1299 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1300 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1301 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1302 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1303 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1304 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1305 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1312 for (i
= 0; separator_names
[i
].name
; ++i
)
1313 if (strcmp (label
, separator_names
[i
].name
) == 0)
1316 *type
= separator_names
[i
].type
;
1318 /* If separator type is not supported under Motif,
1319 use a similar one. */
1320 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1327 /* Old-style separator, maybe. It's a separator if it contains
1329 while (*label
== '-')
1331 separator_p
= *label
== 0;
1332 *type
= SEPARATOR_SHADOW_ETCHED_IN
;