1 /* A general interface to the widgets of different toolkits.
3 Copyright (C) 1992, 1993 Lucid, Inc.
4 Copyright (C) 1994-1996, 1999-2013 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 safe_free_str (char *);
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
);
102 \f/* utility functions for widget_instance and widget_info */
104 safe_strdup (const char *s
)
106 return s
? xstrdup (s
) : 0;
110 safe_free_str (char *s
)
115 static widget_value
*widget_value_free_list
= 0;
116 static int malloc_cpt
= 0;
119 malloc_widget_value (void)
122 if (widget_value_free_list
)
124 wv
= widget_value_free_list
;
125 widget_value_free_list
= wv
->free_list
;
130 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
133 memset ((void*) wv
, 0, sizeof (widget_value
));
137 /* this is analogous to free(). It frees only what was allocated
138 by malloc_widget_value(), and no substructures.
141 free_widget_value (widget_value
*wv
)
148 /* When the number of already allocated cells is too big,
155 wv
->free_list
= widget_value_free_list
;
156 widget_value_free_list
= wv
;
161 free_widget_value_tree (widget_value
*wv
)
170 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
172 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
174 XtFree (wv
->toolkit_data
);
175 wv
->toolkit_data
= (void *) 0xDEADBEEF;
178 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
180 free_widget_value_tree (wv
->contents
);
181 wv
->contents
= (widget_value
*) 0xDEADBEEF;
185 free_widget_value_tree (wv
->next
);
186 wv
->next
= (widget_value
*) 0xDEADBEEF;
188 free_widget_value (wv
);
191 static widget_value
*
192 copy_widget_value_tree (widget_value
*val
, change_type change
)
198 if (val
== (widget_value
*) 1)
201 copy
= malloc_widget_value ();
202 copy
->name
= safe_strdup (val
->name
);
203 copy
->value
= safe_strdup (val
->value
);
204 copy
->key
= safe_strdup (val
->key
);
205 copy
->help
= val
->help
;
206 copy
->enabled
= val
->enabled
;
207 copy
->button_type
= val
->button_type
;
208 copy
->selected
= val
->selected
;
209 copy
->edited
= False
;
210 copy
->change
= change
;
211 copy
->this_one_change
= change
;
212 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
213 copy
->call_data
= val
->call_data
;
214 copy
->next
= copy_widget_value_tree (val
->next
, change
);
215 copy
->toolkit_data
= NULL
;
216 copy
->free_toolkit_data
= False
;
221 allocate_widget_info (const char* type
,
225 lw_callback pre_activate_cb
,
226 lw_callback selection_cb
,
227 lw_callback post_activate_cb
,
228 lw_callback highlight_cb
)
230 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
231 info
->type
= safe_strdup (type
);
232 info
->name
= safe_strdup (name
);
234 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
236 info
->pre_activate_cb
= pre_activate_cb
;
237 info
->selection_cb
= selection_cb
;
238 info
->post_activate_cb
= post_activate_cb
;
239 info
->highlight_cb
= highlight_cb
;
240 info
->instances
= NULL
;
242 info
->next
= all_widget_info
;
243 all_widget_info
= info
;
249 free_widget_info (widget_info
*info
)
251 safe_free_str (info
->type
);
252 safe_free_str (info
->name
);
253 free_widget_value_tree (info
->val
);
254 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
259 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
261 widget_instance
* instance
= (widget_instance
*)closure
;
263 /* be very conservative */
264 if (instance
->widget
== widget
)
265 instance
->widget
= NULL
;
268 static widget_instance
*
269 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
271 widget_instance
* instance
=
272 (widget_instance
*) xmalloc (sizeof (widget_instance
));
273 memset (instance
, 0, sizeof *instance
);
274 instance
->parent
= parent
;
275 instance
->pop_up_p
= pop_up_p
;
276 instance
->info
= info
;
277 instance
->next
= info
->instances
;
278 info
->instances
= instance
;
280 instantiate_widget_instance (instance
);
282 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
283 mark_widget_destroyed
, (XtPointer
)instance
);
288 free_widget_instance (widget_instance
*instance
)
290 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
295 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
299 for (prev
= NULL
, info
= all_widget_info
;
301 prev
= info
, info
= info
->next
)
307 prev
->next
= info
->next
;
309 all_widget_info
= info
->next
;
316 /* Internal function used by the library dependent implementation to get the
317 widget_value for a given widget in an instance */
319 lw_get_widget_info (LWLIB_ID id
)
321 return get_widget_info (id
, 0);
324 static widget_instance
*
325 get_widget_instance (Widget widget
, Boolean remove_p
)
328 widget_instance
* instance
;
329 widget_instance
* prev
;
330 for (info
= all_widget_info
; info
; info
= info
->next
)
331 for (prev
= NULL
, instance
= info
->instances
;
333 prev
= instance
, instance
= instance
->next
)
334 if (instance
->widget
== widget
)
339 prev
->next
= instance
->next
;
341 info
->instances
= instance
->next
;
345 return (widget_instance
*) 0;
348 /* Value is a pointer to the widget_instance corresponding to
349 WIDGET, or null if WIDGET is not a lwlib widget. */
352 lw_get_widget_instance (Widget widget
)
354 return get_widget_instance (widget
, False
);
357 static widget_instance
*
358 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
360 widget_info
* info
= get_widget_info (id
, False
);
361 widget_instance
* instance
;
364 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
365 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
372 /* utility function for widget_value */
374 safe_strcmp (const char *s1
, const char *s2
)
376 if (!!s1
^ !!s2
) return True
;
377 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
382 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
383 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
385 (oc == NO_CHANGE ? "none" : \
386 (oc == INVISIBLE_CHANGE ? "invisible" : \
387 (oc == VISIBLE_CHANGE ? "visible" : \
388 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
390 (nc == NO_CHANGE ? "none" : \
391 (nc == INVISIBLE_CHANGE ? "invisible" : \
392 (nc == VISIBLE_CHANGE ? "visible" : \
393 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
396 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
400 static widget_value
*
401 merge_widget_value (widget_value
*val1
,
406 change_type change
, this_one_change
;
407 widget_value
* merged_next
;
408 widget_value
* merged_contents
;
415 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
423 free_widget_value_tree (val1
);
429 if (safe_strcmp (val1
->name
, val2
->name
))
431 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
432 val1
->name
, val2
->name
);
433 change
= max (change
, STRUCTURAL_CHANGE
);
434 safe_free_str (val1
->name
);
435 val1
->name
= safe_strdup (val2
->name
);
437 if (safe_strcmp (val1
->value
, val2
->value
))
439 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
440 val1
->value
, val2
->value
);
441 change
= max (change
, VISIBLE_CHANGE
);
442 safe_free_str (val1
->value
);
443 val1
->value
= safe_strdup (val2
->value
);
445 if (safe_strcmp (val1
->key
, val2
->key
))
447 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
448 val1
->key
, val2
->key
);
449 change
= max (change
, VISIBLE_CHANGE
);
450 safe_free_str (val1
->key
);
451 val1
->key
= safe_strdup (val2
->key
);
453 if (! EQ (val1
->help
, val2
->help
))
455 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
456 val1
->help
, val2
->help
);
457 change
= max (change
, VISIBLE_CHANGE
);
458 val1
->help
= val2
->help
;
460 if (val1
->enabled
!= val2
->enabled
)
462 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
463 val1
->enabled
, val2
->enabled
);
464 change
= max (change
, VISIBLE_CHANGE
);
465 val1
->enabled
= val2
->enabled
;
467 if (val1
->button_type
!= val2
->button_type
)
469 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
470 val1
->button_type
, val2
->button_type
);
471 change
= max (change
, VISIBLE_CHANGE
);
472 val1
->button_type
= val2
->button_type
;
474 if (val1
->selected
!= val2
->selected
)
476 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
477 val1
->selected
, val2
->selected
);
478 change
= max (change
, VISIBLE_CHANGE
);
479 val1
->selected
= val2
->selected
;
481 if (val1
->call_data
!= val2
->call_data
)
483 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
484 val1
->call_data
, val2
->call_data
);
485 change
= max (change
, INVISIBLE_CHANGE
);
486 val1
->call_data
= val2
->call_data
;
492 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
495 if (val1
->contents
&& !merged_contents
)
497 /* This used to say INVISIBLE_CHANGE,
498 but it is visible and vitally important when
499 the contents of the menu bar itself are entirely deleted.
501 But maybe it doesn't matter. This fails to fix the bug. */
502 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
504 change
= max (change
, STRUCTURAL_CHANGE
);
506 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
508 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
510 change
= max (change
, INVISIBLE_CHANGE
);
511 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
513 change
= max (merged_contents
->change
, change
);
518 val1
->contents
= merged_contents
;
521 this_one_change
= change
;
523 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
525 if (val1
->next
&& !merged_next
)
527 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
529 change
= max (change
, STRUCTURAL_CHANGE
);
531 else if (merged_next
)
533 if (merged_next
->change
)
534 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
536 change
= max (change
, merged_next
->change
);
539 val1
->next
= merged_next
;
541 val1
->this_one_change
= this_one_change
;
542 val1
->change
= change
;
544 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
547 if (val1
->free_toolkit_data
)
548 XtFree (val1
->toolkit_data
);
549 val1
->toolkit_data
= NULL
;
556 /* modifying the widgets */
558 name_to_widget (widget_instance
*instance
, const char *name
)
560 Widget widget
= NULL
;
562 if (!instance
->widget
)
565 if (!strcmp (XtName (instance
->widget
), name
))
566 widget
= instance
->widget
;
569 int length
= strlen (name
) + 2;
570 char* real_name
= (char *) xmalloc (length
);
572 strcpy (real_name
+ 1, name
);
574 widget
= XtNameToWidget (instance
->widget
, real_name
);
582 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
584 Widget widget
= name_to_widget (instance
, val
->name
);
588 #if defined (USE_LUCID)
589 if (lw_lucid_widget_p (instance
->widget
))
590 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
592 #if defined (USE_MOTIF)
593 if (lw_motif_widget_p (instance
->widget
))
594 xm_update_one_widget (instance
, widget
, val
, deep_p
);
596 #if defined (USE_XAW)
597 if (lw_xaw_widget_p (instance
->widget
))
598 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
604 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
608 if (!instance
->widget
)
609 /* the widget was destroyed */
612 for (val
= instance
->info
->val
; val
; val
= val
->next
)
613 if (val
->change
!= NO_CHANGE
)
614 set_one_value (instance
, val
, deep_p
);
618 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
620 widget_instance
* instance
;
623 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
624 update_one_widget_instance (instance
, deep_p
);
626 for (val
= info
->val
; val
; val
= val
->next
)
627 val
->change
= NO_CHANGE
;
631 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
633 widget_info
* info
= get_widget_info (id
, False
);
634 widget_value
* new_val
;
635 widget_value
* next_new_val
;
645 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
647 next_new_val
= new_val
->next
;
648 new_val
->next
= NULL
;
650 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
651 if (!strcmp (cur
->name
, new_val
->name
))
656 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
659 prev
->next
= cur
? cur
: next
;
661 info
->val
= cur
? cur
: next
;
668 /* Could not find it, add it */
670 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
672 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
675 new_val
->next
= next_new_val
;
678 update_all_widget_values (info
, deep_p
);
683 /* creating the widgets */
686 initialize_widget_instance (widget_instance
*instance
)
690 for (val
= instance
->info
->val
; val
; val
= val
->next
)
691 val
->change
= STRUCTURAL_CHANGE
;
693 update_one_widget_instance (instance
, True
);
695 for (val
= instance
->info
->val
; val
; val
= val
->next
)
696 val
->change
= NO_CHANGE
;
700 static widget_creation_function
701 find_in_table (const char *type
, const widget_creation_entry
*table
)
703 const widget_creation_entry
* cur
;
704 for (cur
= table
; cur
->type
; cur
++)
705 if (!c_strcasecmp (type
, cur
->type
))
706 return cur
->function
;
711 dialog_spec_p (const char *name
)
713 /* return True if name matches [EILPQeilpq][1-9][Bb] or
714 [EILPQeilpq][1-9][Bb][Rr][1-9] */
720 case 'E': case 'I': case 'L': case 'P': case 'Q':
721 case 'e': case 'i': case 'l': case 'p': case 'q':
722 if (name
[1] >= '0' && name
[1] <= '9')
724 if (name
[2] != 'B' && name
[2] != 'b')
728 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
730 if ((name
[3] == 'R' || name
[3] == 'r')
731 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
744 instantiate_widget_instance (widget_instance
*instance
)
746 widget_creation_function function
= NULL
;
748 #if defined (USE_LUCID)
750 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
752 #if defined(USE_MOTIF)
754 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
756 #if defined (USE_XAW)
758 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
763 if (dialog_spec_p (instance
->info
->type
))
765 #if defined (USE_LUCID)
768 #if defined(USE_MOTIF)
770 function
= xm_create_dialog
;
772 #if defined (USE_XAW)
774 function
= xaw_create_dialog
;
781 printf ("No creation function for widget type %s\n",
782 instance
->info
->type
);
786 instance
->widget
= (*function
) (instance
);
788 if (!instance
->widget
)
791 /* XtRealizeWidget (instance->widget);*/
795 lw_register_widget (const char* type
,
799 lw_callback pre_activate_cb
,
800 lw_callback selection_cb
,
801 lw_callback post_activate_cb
,
802 lw_callback highlight_cb
)
804 if (!get_widget_info (id
, False
))
805 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
806 post_activate_cb
, highlight_cb
);
810 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
812 widget_instance
* instance
;
814 instance
= find_instance (id
, parent
, pop_up_p
);
815 return instance
? instance
->widget
: NULL
;
819 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
821 widget_instance
* instance
;
824 instance
= find_instance (id
, parent
, pop_up_p
);
827 info
= get_widget_info (id
, False
);
830 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
831 initialize_widget_instance (instance
);
833 if (!instance
->widget
)
835 return instance
->widget
;
839 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
840 Widget parent
, Boolean pop_up_p
,
841 lw_callback pre_activate_cb
, lw_callback selection_cb
,
842 lw_callback post_activate_cb
, lw_callback highlight_cb
)
844 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
845 post_activate_cb
, highlight_cb
);
846 return lw_make_widget (id
, parent
, pop_up_p
);
850 /* destroying the widgets */
852 destroy_one_instance (widget_instance
*instance
)
854 /* Remove the destroy callback on the widget; that callback will try to
855 dereference the instance object (to set its widget slot to 0, since the
856 widget is dead.) Since the instance is now dead, we don't have to worry
857 about the fact that its widget is dead too.
859 This happens in the Phase2Destroy of the widget, so this callback would
860 not have been run until arbitrarily long after the instance was freed.
862 if (instance
->widget
)
863 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
864 mark_widget_destroyed
, (XtPointer
)instance
);
866 if (instance
->widget
)
868 /* The else are pretty tricky here, including the empty statement
869 at the end because it would be very bad to destroy a widget
871 #if defined (USE_LUCID)
872 if (lw_lucid_widget_p (instance
->widget
))
873 xlw_destroy_instance (instance
);
876 #if defined (USE_MOTIF)
877 if (lw_motif_widget_p (instance
->widget
))
878 xm_destroy_instance (instance
);
881 #if defined (USE_XAW)
882 if (lw_xaw_widget_p (instance
->widget
))
883 xaw_destroy_instance (instance
);
887 /* Empty compound statement to terminate if-then-else chain. */
891 free_widget_instance (instance
);
895 lw_destroy_widget (Widget w
)
897 widget_instance
* instance
= get_widget_instance (w
, True
);
901 widget_info
*info
= instance
->info
;
902 /* instance has already been removed from the list; free it */
903 destroy_one_instance (instance
);
904 /* if there are no instances left, free the info too */
905 if (!info
->instances
)
906 lw_destroy_all_widgets (info
->id
);
911 lw_destroy_all_widgets (LWLIB_ID id
)
913 widget_info
* info
= get_widget_info (id
, True
);
914 widget_instance
* instance
;
915 widget_instance
* next
;
919 for (instance
= info
->instances
; instance
; )
921 next
= instance
->next
;
922 destroy_one_instance (instance
);
925 free_widget_info (info
);
930 lw_destroy_everything (void)
932 while (all_widget_info
)
933 lw_destroy_all_widgets (all_widget_info
->id
);
937 lw_destroy_all_pop_ups (void)
941 widget_instance
* instance
;
943 for (info
= all_widget_info
; info
; info
= next
)
946 instance
= info
->instances
;
947 if (instance
&& instance
->pop_up_p
)
948 lw_destroy_all_widgets (info
->id
);
953 extern Widget
first_child (Widget
); /* garbage */
957 lw_raise_all_pop_up_widgets (void)
960 widget_instance
* instance
;
961 Widget result
= NULL
;
963 for (info
= all_widget_info
; info
; info
= info
->next
)
964 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
965 if (instance
->pop_up_p
)
967 Widget widget
= instance
->widget
;
970 if (XtIsManaged (widget
)
972 /* What a complete load of crap!!!!
973 When a dialogShell is on the screen, it is not managed!
975 || (lw_motif_widget_p (instance
->widget
) &&
976 XtIsManaged (first_child (widget
)))
982 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
990 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
992 widget_info
* info
= get_widget_info (id
, False
);
993 widget_instance
* instance
;
996 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
997 if (instance
->pop_up_p
&& instance
->widget
)
999 #if defined (USE_LUCID)
1000 if (lw_lucid_widget_p (instance
->widget
))
1002 XtRealizeWidget (instance
->widget
);
1003 xlw_pop_instance (instance
, up
);
1006 #if defined (USE_MOTIF)
1007 if (lw_motif_widget_p (instance
->widget
))
1009 XtRealizeWidget (instance
->widget
);
1010 xm_pop_instance (instance
, up
);
1013 #if defined (USE_XAW)
1014 if (lw_xaw_widget_p (instance
->widget
))
1016 XtRealizeWidget (XtParent (instance
->widget
));
1017 XtRealizeWidget (instance
->widget
);
1018 xaw_pop_instance (instance
, up
);
1025 lw_pop_up_all_widgets (LWLIB_ID id
)
1027 lw_pop_all_widgets (id
, True
);
1031 lw_pop_down_all_widgets (LWLIB_ID id
)
1033 lw_pop_all_widgets (id
, False
);
1037 lw_popup_menu (Widget widget
, XEvent
*event
)
1039 #if defined (USE_LUCID)
1040 if (lw_lucid_widget_p (widget
))
1041 xlw_popup_menu (widget
, event
);
1043 #if defined (USE_MOTIF)
1044 if (lw_motif_widget_p (widget
))
1045 xm_popup_menu (widget
, event
);
1047 #if defined (USE_XAW)
1048 if (lw_xaw_widget_p (widget
))
1049 xaw_popup_menu (widget
, event
);
1053 \f/* get the values back */
1055 get_one_value (widget_instance
*instance
, widget_value
*val
)
1057 Widget widget
= name_to_widget (instance
, val
->name
);
1061 #if defined (USE_LUCID)
1062 if (lw_lucid_widget_p (instance
->widget
))
1063 xlw_update_one_value (instance
, widget
, val
);
1065 #if defined (USE_MOTIF)
1066 if (lw_motif_widget_p (instance
->widget
))
1067 xm_update_one_value (instance
, widget
, val
);
1069 #if defined (USE_XAW)
1070 if (lw_xaw_widget_p (instance
->widget
))
1071 xaw_update_one_value (instance
, widget
, val
);
1080 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1082 widget_info
* info
= get_widget_info (id
, False
);
1083 widget_instance
* instance
;
1085 Boolean result
= False
;
1090 instance
= info
->instances
;
1094 for (val
= val_out
; val
; val
= val
->next
)
1095 if (get_one_value (instance
, val
))
1102 lw_get_all_values (LWLIB_ID id
)
1104 widget_info
* info
= get_widget_info (id
, False
);
1105 widget_value
* val
= info
->val
;
1106 if (lw_get_some_values (id
, val
))
1112 /* internal function used by the library dependent implementation to get the
1113 widget_value for a given widget in an instance */
1115 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1117 char* name
= XtName (w
);
1119 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1120 if (!strcmp (cur
->name
, name
))
1125 \f/* update other instances value when one thing changed */
1127 /* To forbid recursive calls */
1128 static Boolean lwlib_updating
;
1130 /* This function can be used as an XtCallback for the widgets that get
1131 modified to update other instances of the widgets. Closure should be the
1134 lw_internal_update_other_instances (Widget widget
,
1136 XtPointer call_data
)
1138 widget_instance
* instance
= (widget_instance
*)closure
;
1139 char* name
= XtName (widget
);
1141 widget_instance
* cur
;
1144 /* Avoid possibly infinite recursion. */
1148 /* protect against the widget being destroyed */
1149 if (XtWidgetBeingDestroyedP (widget
))
1152 /* Return immediately if there are no other instances */
1153 info
= instance
->info
;
1154 if (!info
->instances
->next
)
1157 lwlib_updating
= True
;
1159 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1161 if (val
&& get_one_value (instance
, val
))
1162 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1163 if (cur
!= instance
)
1164 set_one_value (cur
, val
, True
);
1166 lwlib_updating
= False
;
1173 lw_get_widget_id (Widget w
)
1175 widget_instance
* instance
= get_widget_instance (w
, False
);
1177 return instance
? instance
->info
->id
: 0;
1180 \f/* set the keyboard focus */
1182 lw_set_keyboard_focus (Widget parent
, Widget w
)
1184 #if defined (USE_MOTIF)
1185 xm_set_keyboard_focus (parent
, w
);
1187 XtSetKeyboardFocus (parent
, w
);
1193 show_one_widget_busy (Widget w
, Boolean flag
)
1195 Pixel foreground
= 0;
1196 Pixel background
= 1;
1197 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1198 if (!widget_to_invert
)
1199 widget_to_invert
= w
;
1201 XtVaGetValues (widget_to_invert
,
1202 XtNforeground
, &foreground
,
1203 XtNbackground
, &background
,
1205 XtVaSetValues (widget_to_invert
,
1206 XtNforeground
, background
,
1207 XtNbackground
, foreground
,
1212 lw_show_busy (Widget w
, Boolean busy
)
1214 widget_instance
* instance
= get_widget_instance (w
, False
);
1216 widget_instance
* next
;
1220 info
= instance
->info
;
1221 if (info
->busy
!= busy
)
1223 for (next
= info
->instances
; next
; next
= next
->next
)
1225 show_one_widget_busy (next
->widget
, busy
);
1231 /* This hack exists because Lucid/Athena need to execute the strange
1232 function below to support geometry management. */
1234 lw_refigure_widget (Widget w
, Boolean doit
)
1236 #if defined (USE_XAW)
1237 XawPanedSetRefigureMode (w
, doit
);
1239 #if defined (USE_MOTIF)
1243 XtUnmanageChild (w
);
1247 /* Toolkit independent way of determining if an event window is in the
1250 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1252 return menubar_widget
1253 #if defined (USE_LUCID)
1254 && XtWindow (menubar_widget
) == win
;
1256 #if defined (USE_MOTIF)
1257 && ((XtWindow (menubar_widget
) == win
)
1258 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1259 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1260 == menubar_widget
)));
1264 /* Motif hack to set the main window areas. */
1266 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1268 #if defined (USE_MOTIF)
1269 xm_set_main_areas (parent
, menubar
, work_area
);
1273 /* Manage resizing for Motif. This disables resizing when the menubar
1274 is about to be modified. */
1276 lw_allow_resizing (Widget w
, Boolean flag
)
1278 #if defined (USE_MOTIF)
1279 xm_manage_resizing (w
, flag
);
1284 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1285 set to an appropriate enumerator of type enum menu_separator.
1286 MOTIF_P non-zero means map separator types not supported by Motif
1287 to similar ones that are supported. */
1290 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1292 int separator_p
= 0;
1294 if (strlen (label
) >= 3
1295 && memcmp (label
, "--:", 3) == 0)
1297 static struct separator_table
1300 enum menu_separator type
;
1304 {"space", SEPARATOR_NO_LINE
},
1305 {"noLine", SEPARATOR_NO_LINE
},
1306 {"singleLine", SEPARATOR_SINGLE_LINE
},
1307 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1308 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1309 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1310 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1311 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1312 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1313 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1314 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1315 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1316 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1317 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1324 for (i
= 0; separator_names
[i
].name
; ++i
)
1325 if (strcmp (label
, separator_names
[i
].name
) == 0)
1328 *type
= separator_names
[i
].type
;
1330 /* If separator type is not supported under Motif,
1331 use a similar one. */
1332 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1337 else if (strlen (label
) > 3
1338 && memcmp (label
, "--", 2) == 0
1341 /* Alternative, more Emacs-style names. */
1342 static struct separator_table
1345 enum menu_separator type
;
1349 {"space", SEPARATOR_NO_LINE
},
1350 {"no-line", SEPARATOR_NO_LINE
},
1351 {"single-line", SEPARATOR_SINGLE_LINE
},
1352 {"double-line", SEPARATOR_DOUBLE_LINE
},
1353 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1354 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1355 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1356 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1357 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1358 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1359 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1360 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1361 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1362 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1369 for (i
= 0; separator_names
[i
].name
; ++i
)
1370 if (strcmp (label
, separator_names
[i
].name
) == 0)
1373 *type
= separator_names
[i
].type
;
1375 /* If separator type is not supported under Motif,
1376 use a similar one. */
1377 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1384 /* Old-style separator, maybe. It's a separator if it contains
1386 while (*label
== '-')
1388 separator_p
= *label
== 0;
1389 *type
= SEPARATOR_SHADOW_ETCHED_IN
;