1 /* A general interface to the widgets of different toolkits.
3 Copyright (C) 1992, 1993 Lucid, Inc.
4 Copyright (C) 1994-1996, 1999-2012 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; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
28 #include <sys/types.h>
31 #include "lwlib-int.h"
32 #include "lwlib-utils.h"
33 #include <X11/StringDefs.h>
35 #if defined (USE_LUCID)
36 #include "lwlib-Xlw.h"
38 #if defined (USE_MOTIF)
40 #else /* not USE_MOTIF */
41 #if defined (USE_LUCID)
43 #endif /* not USE_MOTIF && USE_LUCID */
47 #include <X11/Xaw3d/Paned.h>
48 #else /* !HAVE_XAW3D */
49 #include <X11/Xaw/Paned.h>
50 #endif /* HAVE_XAW3D */
51 #include "lwlib-Xaw.h"
54 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
55 #error At least one of USE_LUCID or USE_MOTIF must be defined.
59 #define max(x, y) ((x) > (y) ? (x) : (y))
62 /* List of all widgets managed by the library. */
64 all_widget_info
= NULL
;
67 const char *lwlib_toolkit_type
= "motif";
69 const char *lwlib_toolkit_type
= "lucid";
72 static widget_value
*merge_widget_value (widget_value
*,
75 static void instantiate_widget_instance (widget_instance
*);
76 static void safe_free_str (char *);
77 static void free_widget_value_tree (widget_value
*);
78 static widget_value
*copy_widget_value_tree (widget_value
*,
80 static widget_info
*allocate_widget_info (const char *, const char *, LWLIB_ID
,
82 lw_callback
, lw_callback
,
83 lw_callback
, lw_callback
);
84 static void free_widget_info (widget_info
*);
85 static void mark_widget_destroyed (Widget
, XtPointer
, XtPointer
);
86 static widget_instance
*allocate_widget_instance (widget_info
*,
88 static void free_widget_instance (widget_instance
*);
89 static widget_info
*get_widget_info (LWLIB_ID
, Boolean
);
90 static widget_instance
*get_widget_instance (Widget
, Boolean
);
91 static widget_instance
*find_instance (LWLIB_ID
, Widget
, Boolean
);
92 static Boolean
safe_strcmp (const char *, const char *);
93 static Widget
name_to_widget (widget_instance
*, const char *);
94 static void set_one_value (widget_instance
*, widget_value
*, Boolean
);
95 static void update_one_widget_instance (widget_instance
*, Boolean
);
96 static void update_all_widget_values (widget_info
*, Boolean
);
97 static void initialize_widget_instance (widget_instance
*);
98 static widget_creation_function
find_in_table (const char *, const widget_creation_entry
*);
99 static Boolean
dialog_spec_p (const char *);
100 static void destroy_one_instance (widget_instance
*);
101 static void lw_pop_all_widgets (LWLIB_ID
, Boolean
);
102 static Boolean
get_one_value (widget_instance
*, widget_value
*);
103 static void show_one_widget_busy (Widget
, Boolean
);
104 \f/* utility functions for widget_instance and widget_info */
106 safe_strdup (const char *s
)
110 result
= (char *) xmalloc (strlen (s
) + 1);
115 #ifdef HAVE_STRCASECMP
116 #define lwlib_strcasecmp(x,y) strcasecmp ((x), (y))
119 /* Like strcmp but ignore differences in case. */
122 lwlib_strcasecmp (const char *s1
, const char *s2
)
133 return (c1
> c2
? 1 : -1);
138 #endif /* HAVE_STRCASECMP */
141 safe_free_str (char *s
)
146 static widget_value
*widget_value_free_list
= 0;
147 static int malloc_cpt
= 0;
150 malloc_widget_value (void)
153 if (widget_value_free_list
)
155 wv
= widget_value_free_list
;
156 widget_value_free_list
= wv
->free_list
;
161 wv
= (widget_value
*) xmalloc (sizeof (widget_value
));
164 memset ((void*) wv
, 0, sizeof (widget_value
));
168 /* this is analogous to free(). It frees only what was allocated
169 by malloc_widget_value(), and no substructures.
172 free_widget_value (widget_value
*wv
)
179 /* When the number of already allocated cells is too big,
186 wv
->free_list
= widget_value_free_list
;
187 widget_value_free_list
= wv
;
192 free_widget_value_tree (widget_value
*wv
)
201 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
203 if (wv
->toolkit_data
&& wv
->free_toolkit_data
)
205 XtFree (wv
->toolkit_data
);
206 wv
->toolkit_data
= (void *) 0xDEADBEEF;
209 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
211 free_widget_value_tree (wv
->contents
);
212 wv
->contents
= (widget_value
*) 0xDEADBEEF;
216 free_widget_value_tree (wv
->next
);
217 wv
->next
= (widget_value
*) 0xDEADBEEF;
219 free_widget_value (wv
);
222 static widget_value
*
223 copy_widget_value_tree (widget_value
*val
, change_type change
)
229 if (val
== (widget_value
*) 1)
232 copy
= malloc_widget_value ();
233 copy
->name
= safe_strdup (val
->name
);
234 copy
->value
= safe_strdup (val
->value
);
235 copy
->key
= safe_strdup (val
->key
);
236 copy
->help
= val
->help
;
237 copy
->enabled
= val
->enabled
;
238 copy
->button_type
= val
->button_type
;
239 copy
->selected
= val
->selected
;
240 copy
->edited
= False
;
241 copy
->change
= change
;
242 copy
->this_one_change
= change
;
243 copy
->contents
= copy_widget_value_tree (val
->contents
, change
);
244 copy
->call_data
= val
->call_data
;
245 copy
->next
= copy_widget_value_tree (val
->next
, change
);
246 copy
->toolkit_data
= NULL
;
247 copy
->free_toolkit_data
= False
;
252 allocate_widget_info (const char* type
,
256 lw_callback pre_activate_cb
,
257 lw_callback selection_cb
,
258 lw_callback post_activate_cb
,
259 lw_callback highlight_cb
)
261 widget_info
* info
= (widget_info
*) xmalloc (sizeof (widget_info
));
262 info
->type
= safe_strdup (type
);
263 info
->name
= safe_strdup (name
);
265 info
->val
= copy_widget_value_tree (val
, STRUCTURAL_CHANGE
);
267 info
->pre_activate_cb
= pre_activate_cb
;
268 info
->selection_cb
= selection_cb
;
269 info
->post_activate_cb
= post_activate_cb
;
270 info
->highlight_cb
= highlight_cb
;
271 info
->instances
= NULL
;
273 info
->next
= all_widget_info
;
274 all_widget_info
= info
;
280 free_widget_info (widget_info
*info
)
282 safe_free_str (info
->type
);
283 safe_free_str (info
->name
);
284 free_widget_value_tree (info
->val
);
285 memset ((void*)info
, 0xDEADBEEF, sizeof (widget_info
));
290 mark_widget_destroyed (Widget widget
, XtPointer closure
, XtPointer call_data
)
292 widget_instance
* instance
= (widget_instance
*)closure
;
294 /* be very conservative */
295 if (instance
->widget
== widget
)
296 instance
->widget
= NULL
;
299 static widget_instance
*
300 allocate_widget_instance (widget_info
* info
, Widget parent
, Boolean pop_up_p
)
302 widget_instance
* instance
=
303 (widget_instance
*) xmalloc (sizeof (widget_instance
));
304 memset (instance
, 0, sizeof *instance
);
305 instance
->parent
= parent
;
306 instance
->pop_up_p
= pop_up_p
;
307 instance
->info
= info
;
308 instance
->next
= info
->instances
;
309 info
->instances
= instance
;
311 instantiate_widget_instance (instance
);
313 XtAddCallback (instance
->widget
, XtNdestroyCallback
,
314 mark_widget_destroyed
, (XtPointer
)instance
);
319 free_widget_instance (widget_instance
*instance
)
321 memset ((void*)instance
, 0xDEADBEEF, sizeof (widget_instance
));
326 get_widget_info (LWLIB_ID id
, Boolean remove_p
)
330 for (prev
= NULL
, info
= all_widget_info
;
332 prev
= info
, info
= info
->next
)
338 prev
->next
= info
->next
;
340 all_widget_info
= info
->next
;
347 /* Internal function used by the library dependent implementation to get the
348 widget_value for a given widget in an instance */
350 lw_get_widget_info (LWLIB_ID id
)
352 return get_widget_info (id
, 0);
355 static widget_instance
*
356 get_widget_instance (Widget widget
, Boolean remove_p
)
359 widget_instance
* instance
;
360 widget_instance
* prev
;
361 for (info
= all_widget_info
; info
; info
= info
->next
)
362 for (prev
= NULL
, instance
= info
->instances
;
364 prev
= instance
, instance
= instance
->next
)
365 if (instance
->widget
== widget
)
370 prev
->next
= instance
->next
;
372 info
->instances
= instance
->next
;
376 return (widget_instance
*) 0;
379 /* Value is a pointer to the widget_instance corresponding to
380 WIDGET, or null if WIDGET is not a lwlib widget. */
383 lw_get_widget_instance (Widget widget
)
385 return get_widget_instance (widget
, False
);
388 static widget_instance
*
389 find_instance (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
391 widget_info
* info
= get_widget_info (id
, False
);
392 widget_instance
* instance
;
395 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
396 if (instance
->parent
== parent
&& instance
->pop_up_p
== pop_up_p
)
403 /* utility function for widget_value */
405 safe_strcmp (const char *s1
, const char *s2
)
407 if (!!s1
^ !!s2
) return True
;
408 return (s1
&& s2
) ? strcmp (s1
, s2
) : s1
? False
: !!s2
;
413 # define EXPLAIN(name, oc, nc, desc, a1, a2) \
414 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
416 (oc == NO_CHANGE ? "none" : \
417 (oc == INVISIBLE_CHANGE ? "invisible" : \
418 (oc == VISIBLE_CHANGE ? "visible" : \
419 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
421 (nc == NO_CHANGE ? "none" : \
422 (nc == INVISIBLE_CHANGE ? "invisible" : \
423 (nc == VISIBLE_CHANGE ? "visible" : \
424 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
427 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
431 static widget_value
*
432 merge_widget_value (widget_value
*val1
,
437 change_type change
, this_one_change
;
438 widget_value
* merged_next
;
439 widget_value
* merged_contents
;
446 return copy_widget_value_tree (val2
, STRUCTURAL_CHANGE
);
454 free_widget_value_tree (val1
);
460 if (safe_strcmp (val1
->name
, val2
->name
))
462 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "name change",
463 val1
->name
, val2
->name
);
464 change
= max (change
, STRUCTURAL_CHANGE
);
465 safe_free_str (val1
->name
);
466 val1
->name
= safe_strdup (val2
->name
);
468 if (safe_strcmp (val1
->value
, val2
->value
))
470 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "value change",
471 val1
->value
, val2
->value
);
472 change
= max (change
, VISIBLE_CHANGE
);
473 safe_free_str (val1
->value
);
474 val1
->value
= safe_strdup (val2
->value
);
476 if (safe_strcmp (val1
->key
, val2
->key
))
478 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "key change",
479 val1
->key
, val2
->key
);
480 change
= max (change
, VISIBLE_CHANGE
);
481 safe_free_str (val1
->key
);
482 val1
->key
= safe_strdup (val2
->key
);
484 if (! EQ (val1
->help
, val2
->help
))
486 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "help change",
487 val1
->help
, val2
->help
);
488 change
= max (change
, VISIBLE_CHANGE
);
489 val1
->help
= val2
->help
;
491 if (val1
->enabled
!= val2
->enabled
)
493 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "enablement change",
494 val1
->enabled
, val2
->enabled
);
495 change
= max (change
, VISIBLE_CHANGE
);
496 val1
->enabled
= val2
->enabled
;
498 if (val1
->button_type
!= val2
->button_type
)
500 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "button type change",
501 val1
->button_type
, val2
->button_type
);
502 change
= max (change
, VISIBLE_CHANGE
);
503 val1
->button_type
= val2
->button_type
;
505 if (val1
->selected
!= val2
->selected
)
507 EXPLAIN (val1
->name
, change
, VISIBLE_CHANGE
, "selection change",
508 val1
->selected
, val2
->selected
);
509 change
= max (change
, VISIBLE_CHANGE
);
510 val1
->selected
= val2
->selected
;
512 if (val1
->call_data
!= val2
->call_data
)
514 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "call-data change",
515 val1
->call_data
, val2
->call_data
);
516 change
= max (change
, INVISIBLE_CHANGE
);
517 val1
->call_data
= val2
->call_data
;
523 merge_widget_value (val1
->contents
, val2
->contents
, level
- 1,
526 if (val1
->contents
&& !merged_contents
)
528 /* This used to say INVISIBLE_CHANGE,
529 but it is visible and vitally important when
530 the contents of the menu bar itself are entirely deleted.
532 But maybe it doesn't matter. This fails to fix the bug. */
533 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(contents gone)",
535 change
= max (change
, STRUCTURAL_CHANGE
);
537 else if (merged_contents
&& merged_contents
->change
!= NO_CHANGE
)
539 EXPLAIN (val1
->name
, change
, INVISIBLE_CHANGE
, "(contents change)",
541 change
= max (change
, INVISIBLE_CHANGE
);
542 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
544 change
= max (merged_contents
->change
, change
);
549 val1
->contents
= merged_contents
;
552 this_one_change
= change
;
554 merged_next
= merge_widget_value (val1
->next
, val2
->next
, level
, change_p
);
556 if (val1
->next
&& !merged_next
)
558 EXPLAIN (val1
->name
, change
, STRUCTURAL_CHANGE
, "(following gone)",
560 change
= max (change
, STRUCTURAL_CHANGE
);
562 else if (merged_next
)
564 if (merged_next
->change
)
565 EXPLAIN (val1
->name
, change
, merged_next
->change
, "(following change)",
567 change
= max (change
, merged_next
->change
);
570 val1
->next
= merged_next
;
572 val1
->this_one_change
= this_one_change
;
573 val1
->change
= change
;
575 if (change
> NO_CHANGE
&& val1
->toolkit_data
)
578 if (val1
->free_toolkit_data
)
579 XtFree (val1
->toolkit_data
);
580 val1
->toolkit_data
= NULL
;
587 /* modifying the widgets */
589 name_to_widget (widget_instance
*instance
, const char *name
)
591 Widget widget
= NULL
;
593 if (!instance
->widget
)
596 if (!strcmp (XtName (instance
->widget
), name
))
597 widget
= instance
->widget
;
600 int length
= strlen (name
) + 2;
601 char* real_name
= (char *) xmalloc (length
);
603 strcpy (real_name
+ 1, name
);
605 widget
= XtNameToWidget (instance
->widget
, real_name
);
613 set_one_value (widget_instance
* instance
, widget_value
* val
, Boolean deep_p
)
615 Widget widget
= name_to_widget (instance
, val
->name
);
619 #if defined (USE_LUCID)
620 if (lw_lucid_widget_p (instance
->widget
))
621 xlw_update_one_widget (instance
, widget
, val
, deep_p
);
623 #if defined (USE_MOTIF)
624 if (lw_motif_widget_p (instance
->widget
))
625 xm_update_one_widget (instance
, widget
, val
, deep_p
);
627 #if defined (USE_XAW)
628 if (lw_xaw_widget_p (instance
->widget
))
629 xaw_update_one_widget (instance
, widget
, val
, deep_p
);
635 update_one_widget_instance (widget_instance
* instance
, Boolean deep_p
)
639 if (!instance
->widget
)
640 /* the widget was destroyed */
643 for (val
= instance
->info
->val
; val
; val
= val
->next
)
644 if (val
->change
!= NO_CHANGE
)
645 set_one_value (instance
, val
, deep_p
);
649 update_all_widget_values (widget_info
* info
, Boolean deep_p
)
651 widget_instance
* instance
;
654 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
655 update_one_widget_instance (instance
, deep_p
);
657 for (val
= info
->val
; val
; val
= val
->next
)
658 val
->change
= NO_CHANGE
;
662 lw_modify_all_widgets (LWLIB_ID id
, widget_value
* val
, Boolean deep_p
)
664 widget_info
* info
= get_widget_info (id
, False
);
665 widget_value
* new_val
;
666 widget_value
* next_new_val
;
676 for (new_val
= val
; new_val
; new_val
= new_val
->next
)
678 next_new_val
= new_val
->next
;
679 new_val
->next
= NULL
;
681 for (prev
= NULL
, cur
= info
->val
; cur
; prev
= cur
, cur
= cur
->next
)
682 if (!strcmp (cur
->name
, new_val
->name
))
687 cur
= merge_widget_value (cur
, new_val
, deep_p
? 1000 : 1,
690 prev
->next
= cur
? cur
: next
;
692 info
->val
= cur
? cur
: next
;
699 /* Could not find it, add it */
701 prev
->next
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
703 info
->val
= copy_widget_value_tree (new_val
, STRUCTURAL_CHANGE
);
706 new_val
->next
= next_new_val
;
709 update_all_widget_values (info
, deep_p
);
714 /* creating the widgets */
717 initialize_widget_instance (widget_instance
*instance
)
721 for (val
= instance
->info
->val
; val
; val
= val
->next
)
722 val
->change
= STRUCTURAL_CHANGE
;
724 update_one_widget_instance (instance
, True
);
726 for (val
= instance
->info
->val
; val
; val
= val
->next
)
727 val
->change
= NO_CHANGE
;
731 static widget_creation_function
732 find_in_table (const char *type
, const widget_creation_entry
*table
)
734 const widget_creation_entry
* cur
;
735 for (cur
= table
; cur
->type
; cur
++)
736 if (!lwlib_strcasecmp (type
, cur
->type
))
737 return cur
->function
;
742 dialog_spec_p (const char *name
)
744 /* return True if name matches [EILPQeilpq][1-9][Bb] or
745 [EILPQeilpq][1-9][Bb][Rr][1-9] */
751 case 'E': case 'I': case 'L': case 'P': case 'Q':
752 case 'e': case 'i': case 'l': case 'p': case 'q':
753 if (name
[1] >= '0' && name
[1] <= '9')
755 if (name
[2] != 'B' && name
[2] != 'b')
759 if ((name
[3] == 'T' || name
[3] == 't') && !name
[4])
761 if ((name
[3] == 'R' || name
[3] == 'r')
762 && name
[4] >= '0' && name
[4] <= '9' && !name
[5])
775 instantiate_widget_instance (widget_instance
*instance
)
777 widget_creation_function function
= NULL
;
779 #if defined (USE_LUCID)
781 function
= find_in_table (instance
->info
->type
, xlw_creation_table
);
783 #if defined(USE_MOTIF)
785 function
= find_in_table (instance
->info
->type
, xm_creation_table
);
787 #if defined (USE_XAW)
789 function
= find_in_table (instance
->info
->type
, xaw_creation_table
);
794 if (dialog_spec_p (instance
->info
->type
))
796 #if defined (USE_LUCID)
799 #if defined(USE_MOTIF)
801 function
= xm_create_dialog
;
803 #if defined (USE_XAW)
805 function
= xaw_create_dialog
;
812 printf ("No creation function for widget type %s\n",
813 instance
->info
->type
);
817 instance
->widget
= (*function
) (instance
);
819 if (!instance
->widget
)
822 /* XtRealizeWidget (instance->widget);*/
826 lw_register_widget (const char* type
,
830 lw_callback pre_activate_cb
,
831 lw_callback selection_cb
,
832 lw_callback post_activate_cb
,
833 lw_callback highlight_cb
)
835 if (!get_widget_info (id
, False
))
836 allocate_widget_info (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
837 post_activate_cb
, highlight_cb
);
841 lw_get_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
843 widget_instance
* instance
;
845 instance
= find_instance (id
, parent
, pop_up_p
);
846 return instance
? instance
->widget
: NULL
;
850 lw_make_widget (LWLIB_ID id
, Widget parent
, Boolean pop_up_p
)
852 widget_instance
* instance
;
855 instance
= find_instance (id
, parent
, pop_up_p
);
858 info
= get_widget_info (id
, False
);
861 instance
= allocate_widget_instance (info
, parent
, pop_up_p
);
862 initialize_widget_instance (instance
);
864 if (!instance
->widget
)
866 return instance
->widget
;
870 lw_create_widget (const char* type
, const char* name
, LWLIB_ID id
, widget_value
* val
,
871 Widget parent
, Boolean pop_up_p
,
872 lw_callback pre_activate_cb
, lw_callback selection_cb
,
873 lw_callback post_activate_cb
, lw_callback highlight_cb
)
875 lw_register_widget (type
, name
, id
, val
, pre_activate_cb
, selection_cb
,
876 post_activate_cb
, highlight_cb
);
877 return lw_make_widget (id
, parent
, pop_up_p
);
881 /* destroying the widgets */
883 destroy_one_instance (widget_instance
*instance
)
885 /* Remove the destroy callback on the widget; that callback will try to
886 dereference the instance object (to set its widget slot to 0, since the
887 widget is dead.) Since the instance is now dead, we don't have to worry
888 about the fact that its widget is dead too.
890 This happens in the Phase2Destroy of the widget, so this callback would
891 not have been run until arbitrarily long after the instance was freed.
893 if (instance
->widget
)
894 XtRemoveCallback (instance
->widget
, XtNdestroyCallback
,
895 mark_widget_destroyed
, (XtPointer
)instance
);
897 if (instance
->widget
)
899 /* The else are pretty tricky here, including the empty statement
900 at the end because it would be very bad to destroy a widget
902 #if defined (USE_LUCID)
903 if (lw_lucid_widget_p (instance
->widget
))
904 xlw_destroy_instance (instance
);
907 #if defined (USE_MOTIF)
908 if (lw_motif_widget_p (instance
->widget
))
909 xm_destroy_instance (instance
);
912 #if defined (USE_XAW)
913 if (lw_xaw_widget_p (instance
->widget
))
914 xaw_destroy_instance (instance
);
918 /* Empty compound statement to terminate if-then-else chain. */
922 free_widget_instance (instance
);
926 lw_destroy_widget (Widget w
)
928 widget_instance
* instance
= get_widget_instance (w
, True
);
932 widget_info
*info
= instance
->info
;
933 /* instance has already been removed from the list; free it */
934 destroy_one_instance (instance
);
935 /* if there are no instances left, free the info too */
936 if (!info
->instances
)
937 lw_destroy_all_widgets (info
->id
);
942 lw_destroy_all_widgets (LWLIB_ID id
)
944 widget_info
* info
= get_widget_info (id
, True
);
945 widget_instance
* instance
;
946 widget_instance
* next
;
950 for (instance
= info
->instances
; instance
; )
952 next
= instance
->next
;
953 destroy_one_instance (instance
);
956 free_widget_info (info
);
961 lw_destroy_everything (void)
963 while (all_widget_info
)
964 lw_destroy_all_widgets (all_widget_info
->id
);
968 lw_destroy_all_pop_ups (void)
972 widget_instance
* instance
;
974 for (info
= all_widget_info
; info
; info
= next
)
977 instance
= info
->instances
;
978 if (instance
&& instance
->pop_up_p
)
979 lw_destroy_all_widgets (info
->id
);
984 extern Widget
first_child (Widget
); /* garbage */
988 lw_raise_all_pop_up_widgets (void)
991 widget_instance
* instance
;
992 Widget result
= NULL
;
994 for (info
= all_widget_info
; info
; info
= info
->next
)
995 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
996 if (instance
->pop_up_p
)
998 Widget widget
= instance
->widget
;
1001 if (XtIsManaged (widget
)
1003 /* What a complete load of crap!!!!
1004 When a dialogShell is on the screen, it is not managed!
1006 || (lw_motif_widget_p (instance
->widget
) &&
1007 XtIsManaged (first_child (widget
)))
1013 XMapRaised (XtDisplay (widget
), XtWindow (widget
));
1021 lw_pop_all_widgets (LWLIB_ID id
, Boolean up
)
1023 widget_info
* info
= get_widget_info (id
, False
);
1024 widget_instance
* instance
;
1027 for (instance
= info
->instances
; instance
; instance
= instance
->next
)
1028 if (instance
->pop_up_p
&& instance
->widget
)
1030 #if defined (USE_LUCID)
1031 if (lw_lucid_widget_p (instance
->widget
))
1033 XtRealizeWidget (instance
->widget
);
1034 xlw_pop_instance (instance
, up
);
1037 #if defined (USE_MOTIF)
1038 if (lw_motif_widget_p (instance
->widget
))
1040 XtRealizeWidget (instance
->widget
);
1041 xm_pop_instance (instance
, up
);
1044 #if defined (USE_XAW)
1045 if (lw_xaw_widget_p (instance
->widget
))
1047 XtRealizeWidget (XtParent (instance
->widget
));
1048 XtRealizeWidget (instance
->widget
);
1049 xaw_pop_instance (instance
, up
);
1056 lw_pop_up_all_widgets (LWLIB_ID id
)
1058 lw_pop_all_widgets (id
, True
);
1062 lw_pop_down_all_widgets (LWLIB_ID id
)
1064 lw_pop_all_widgets (id
, False
);
1068 lw_popup_menu (Widget widget
, XEvent
*event
)
1070 #if defined (USE_LUCID)
1071 if (lw_lucid_widget_p (widget
))
1072 xlw_popup_menu (widget
, event
);
1074 #if defined (USE_MOTIF)
1075 if (lw_motif_widget_p (widget
))
1076 xm_popup_menu (widget
, event
);
1078 #if defined (USE_XAW)
1079 if (lw_xaw_widget_p (widget
))
1080 xaw_popup_menu (widget
, event
);
1084 \f/* get the values back */
1086 get_one_value (widget_instance
*instance
, widget_value
*val
)
1088 Widget widget
= name_to_widget (instance
, val
->name
);
1092 #if defined (USE_LUCID)
1093 if (lw_lucid_widget_p (instance
->widget
))
1094 xlw_update_one_value (instance
, widget
, val
);
1096 #if defined (USE_MOTIF)
1097 if (lw_motif_widget_p (instance
->widget
))
1098 xm_update_one_value (instance
, widget
, val
);
1100 #if defined (USE_XAW)
1101 if (lw_xaw_widget_p (instance
->widget
))
1102 xaw_update_one_value (instance
, widget
, val
);
1111 lw_get_some_values (LWLIB_ID id
, widget_value
*val_out
)
1113 widget_info
* info
= get_widget_info (id
, False
);
1114 widget_instance
* instance
;
1116 Boolean result
= False
;
1121 instance
= info
->instances
;
1125 for (val
= val_out
; val
; val
= val
->next
)
1126 if (get_one_value (instance
, val
))
1133 lw_get_all_values (LWLIB_ID id
)
1135 widget_info
* info
= get_widget_info (id
, False
);
1136 widget_value
* val
= info
->val
;
1137 if (lw_get_some_values (id
, val
))
1143 /* internal function used by the library dependent implementation to get the
1144 widget_value for a given widget in an instance */
1146 lw_get_widget_value_for_widget (widget_instance
*instance
, Widget w
)
1148 char* name
= XtName (w
);
1150 for (cur
= instance
->info
->val
; cur
; cur
= cur
->next
)
1151 if (!strcmp (cur
->name
, name
))
1156 \f/* update other instances value when one thing changed */
1158 /* To forbid recursive calls */
1159 static Boolean lwlib_updating
;
1161 /* This function can be used as an XtCallback for the widgets that get
1162 modified to update other instances of the widgets. Closure should be the
1165 lw_internal_update_other_instances (Widget widget
,
1167 XtPointer call_data
)
1169 widget_instance
* instance
= (widget_instance
*)closure
;
1170 char* name
= XtName (widget
);
1172 widget_instance
* cur
;
1175 /* Avoid possibly infinite recursion. */
1179 /* protect against the widget being destroyed */
1180 if (XtWidgetBeingDestroyedP (widget
))
1183 /* Return immediately if there are no other instances */
1184 info
= instance
->info
;
1185 if (!info
->instances
->next
)
1188 lwlib_updating
= True
;
1190 for (val
= info
->val
; val
&& strcmp (val
->name
, name
); val
= val
->next
);
1192 if (val
&& get_one_value (instance
, val
))
1193 for (cur
= info
->instances
; cur
; cur
= cur
->next
)
1194 if (cur
!= instance
)
1195 set_one_value (cur
, val
, True
);
1197 lwlib_updating
= False
;
1204 lw_get_widget_id (Widget w
)
1206 widget_instance
* instance
= get_widget_instance (w
, False
);
1208 return instance
? instance
->info
->id
: 0;
1211 \f/* set the keyboard focus */
1213 lw_set_keyboard_focus (Widget parent
, Widget w
)
1215 #if defined (USE_MOTIF)
1216 xm_set_keyboard_focus (parent
, w
);
1218 XtSetKeyboardFocus (parent
, w
);
1224 show_one_widget_busy (Widget w
, Boolean flag
)
1226 Pixel foreground
= 0;
1227 Pixel background
= 1;
1228 Widget widget_to_invert
= XtNameToWidget (w
, "*sheet");
1229 if (!widget_to_invert
)
1230 widget_to_invert
= w
;
1232 XtVaGetValues (widget_to_invert
,
1233 XtNforeground
, &foreground
,
1234 XtNbackground
, &background
,
1236 XtVaSetValues (widget_to_invert
,
1237 XtNforeground
, background
,
1238 XtNbackground
, foreground
,
1243 lw_show_busy (Widget w
, Boolean busy
)
1245 widget_instance
* instance
= get_widget_instance (w
, False
);
1247 widget_instance
* next
;
1251 info
= instance
->info
;
1252 if (info
->busy
!= busy
)
1254 for (next
= info
->instances
; next
; next
= next
->next
)
1256 show_one_widget_busy (next
->widget
, busy
);
1262 /* This hack exists because Lucid/Athena need to execute the strange
1263 function below to support geometry management. */
1265 lw_refigure_widget (Widget w
, Boolean doit
)
1267 #if defined (USE_XAW)
1268 XawPanedSetRefigureMode (w
, doit
);
1270 #if defined (USE_MOTIF)
1274 XtUnmanageChild (w
);
1278 /* Toolkit independent way of determining if an event window is in the
1281 lw_window_is_in_menubar (Window win
, Widget menubar_widget
)
1283 return menubar_widget
1284 #if defined (USE_LUCID)
1285 && XtWindow (menubar_widget
) == win
;
1287 #if defined (USE_MOTIF)
1288 && ((XtWindow (menubar_widget
) == win
)
1289 || (XtWindowToWidget (XtDisplay (menubar_widget
), win
)
1290 && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget
), win
))
1291 == menubar_widget
)));
1295 /* Motif hack to set the main window areas. */
1297 lw_set_main_areas (Widget parent
, Widget menubar
, Widget work_area
)
1299 #if defined (USE_MOTIF)
1300 xm_set_main_areas (parent
, menubar
, work_area
);
1304 /* Manage resizing for Motif. This disables resizing when the menubar
1305 is about to be modified. */
1307 lw_allow_resizing (Widget w
, Boolean flag
)
1309 #if defined (USE_MOTIF)
1310 xm_manage_resizing (w
, flag
);
1315 /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
1316 set to an appropriate enumerator of type enum menu_separator.
1317 MOTIF_P non-zero means map separator types not supported by Motif
1318 to similar ones that are supported. */
1321 lw_separator_p (const char *label
, enum menu_separator
*type
, int motif_p
)
1323 int separator_p
= 0;
1325 if (strlen (label
) >= 3
1326 && memcmp (label
, "--:", 3) == 0)
1328 static struct separator_table
1331 enum menu_separator type
;
1335 {"space", SEPARATOR_NO_LINE
},
1336 {"noLine", SEPARATOR_NO_LINE
},
1337 {"singleLine", SEPARATOR_SINGLE_LINE
},
1338 {"doubleLine", SEPARATOR_DOUBLE_LINE
},
1339 {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE
},
1340 {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE
},
1341 {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN
},
1342 {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT
},
1343 {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1344 {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1345 {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1346 {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1347 {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1348 {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1355 for (i
= 0; separator_names
[i
].name
; ++i
)
1356 if (strcmp (label
, separator_names
[i
].name
) == 0)
1359 *type
= separator_names
[i
].type
;
1361 /* If separator type is not supported under Motif,
1362 use a similar one. */
1363 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1368 else if (strlen (label
) > 3
1369 && memcmp (label
, "--", 2) == 0
1372 /* Alternative, more Emacs-style names. */
1373 static struct separator_table
1376 enum menu_separator type
;
1380 {"space", SEPARATOR_NO_LINE
},
1381 {"no-line", SEPARATOR_NO_LINE
},
1382 {"single-line", SEPARATOR_SINGLE_LINE
},
1383 {"double-line", SEPARATOR_DOUBLE_LINE
},
1384 {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE
},
1385 {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE
},
1386 {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN
},
1387 {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT
},
1388 {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH
},
1389 {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH
},
1390 {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
},
1391 {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT
},
1392 {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH
},
1393 {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH
},
1400 for (i
= 0; separator_names
[i
].name
; ++i
)
1401 if (strcmp (label
, separator_names
[i
].name
) == 0)
1404 *type
= separator_names
[i
].type
;
1406 /* If separator type is not supported under Motif,
1407 use a similar one. */
1408 if (motif_p
&& *type
>= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN
)
1415 /* Old-style separator, maybe. It's a separator if it contains
1417 while (*label
== '-')
1419 separator_p
= *label
== 0;
1420 *type
= SEPARATOR_SHADOW_ETCHED_IN
;