1 /* The lwlib interface to "xlwmenu" menus.
2 Copyright (C) 1992, 1994 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 The Lucid Widget Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 #include <stdlib.h> /* for abort () */
23 #include <stdio.h> /* for abort () */
26 #include "lwlib-Xlw.h"
27 #include "lwlib-utils.h"
28 #include <X11/StringDefs.h>
29 #include <X11/IntrinsicP.h>
30 #include <X11/ObjectP.h>
31 #include <X11/CompositeP.h>
32 #include <X11/Shell.h>
34 #include "../src/EmacsManager.h"
36 #ifdef LWLIB_MENUBARS_LUCID
39 #ifdef LWLIB_SCROLLBARS_LUCID
40 #include "xlwscrollbar.h"
42 #ifdef LWLIB_TABS_LUCID
47 #include "lwlib-Xaw.h"
49 #include "../src/xmu.h"
54 #include <X11/Intrinsic.h>
55 #include <X11/StringDefs.h>
56 #include <X11/Shell.h>
57 #include <X11/Xaw/Form.h>
58 #include <X11/Xaw/Command.h>
61 #ifdef LWLIB_MENUBARS_LUCID
66 pre_hook (Widget w, XtPointer client_data, XtPointer call_data)
68 widget_instance* instance = (widget_instance*)client_data;
71 if (w->core.being_destroyed)
74 val = lw_get_widget_value_for_widget (instance, w);
76 /* #### - this code used to (for some random back_asswards reason) pass
77 the expression below in the call_data slot. For incremental menu
78 construction, this needs to go. I can't even figure out why it was done
79 this way in the first place...it's just a historical weirdism. --Stig */
80 call_data = (val ? val->call_data : NULL);
82 if (val && val->call_data)
83 abort(); /* #### - the call_data for the top_level
84 "menubar" widget_value used to be passed
85 back to the pre_hook. */
87 if (instance->info->pre_activate_cb)
88 instance->info->pre_activate_cb (w, instance->info->id, call_data);
92 pick_hook (Widget w, XtPointer client_data, XtPointer call_data)
94 widget_instance* instance = (widget_instance*)client_data;
95 widget_value* contents_val = (widget_value*)call_data;
96 widget_value* widget_val;
99 lw_callback post_activate_cb;
101 if (w->core.being_destroyed)
104 /* Grab these values before running any functions, in case running
105 the selection_cb causes the widget to be destroyed. */
106 id = instance->info->id;
107 post_activate_cb = instance->info->post_activate_cb;
109 widget_val = lw_get_widget_value_for_widget (instance, w);
110 widget_arg = widget_val ? widget_val->call_data : NULL;
112 if (instance->info->selection_cb &&
114 contents_val->enabled &&
115 !contents_val->contents)
116 instance->info->selection_cb (w, id, contents_val->call_data);
118 if (post_activate_cb)
119 post_activate_cb (w, id, widget_arg);
124 /* creation functions */
126 xlw_create_menubar (widget_instance* instance)
131 XtSetArg (al [0], XtNmenu, instance->info->val);
132 widget = XtCreateWidget (instance->info->name, xlwMenuWidgetClass,
133 instance->parent, al, 1);
134 XtAddCallback (widget, XtNopen, pre_hook, (XtPointer)instance);
135 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
140 xlw_create_popup_menu (widget_instance* instance)
143 Widget popup_shell, widget;
145 popup_shell = XtCreatePopupShell (instance->info->name,
146 overrideShellWidgetClass,
147 instance->parent, NULL, 0);
148 XtSetArg (al [0], XtNmenu, instance->info->val);
149 XtSetArg (al [1], XtNhorizontal, False);
150 widget = XtCreateManagedWidget ("popup", xlwMenuWidgetClass,
152 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
155 #endif /* LWLIB_MENUBARS_LUCID */
157 #ifdef LWLIB_SCROLLBARS_LUCID
159 xlw_scrollbar_callback (Widget widget, XtPointer closure, XtPointer call_data)
161 widget_instance *instance = (widget_instance *) closure;
163 XlwScrollBarCallbackStruct *data =
164 (XlwScrollBarCallbackStruct *) call_data;
165 scroll_event event_data;
166 scrollbar_values *val =
167 (scrollbar_values *) instance->info->val->scrollbar_data;
170 if (!instance || widget->core.being_destroyed)
173 id = instance->info->id;
175 percent = (double) (data->value - 1) / (double) (INT_MAX - 1);
176 event_data.slider_value =
177 (int) (percent * (double) (val->maximum - val->minimum)) + val->minimum;
179 if (event_data.slider_value > val->maximum - val->slider_size)
180 event_data.slider_value = val->maximum - val->slider_size;
181 else if (event_data.slider_value < val->minimum)
182 event_data.slider_value = val->minimum;
186 switch (data->event->type)
190 event_data.time = data->event->xkey.time;
194 event_data.time = data->event->xbutton.time;
197 event_data.time = data->event->xmotion.time;
201 event_data.time = data->event->xcrossing.time;
211 switch (data->reason)
213 case XmCR_DECREMENT: event_data.action = SCROLLBAR_LINE_UP; break;
214 case XmCR_INCREMENT: event_data.action = SCROLLBAR_LINE_DOWN; break;
215 case XmCR_PAGE_DECREMENT: event_data.action = SCROLLBAR_PAGE_UP; break;
216 case XmCR_PAGE_INCREMENT: event_data.action = SCROLLBAR_PAGE_DOWN; break;
217 case XmCR_TO_TOP: event_data.action = SCROLLBAR_TOP; break;
218 case XmCR_TO_BOTTOM: event_data.action = SCROLLBAR_BOTTOM; break;
219 case XmCR_DRAG: event_data.action = SCROLLBAR_DRAG; break;
220 case XmCR_VALUE_CHANGED: event_data.action = SCROLLBAR_CHANGE; break;
221 default: event_data.action = SCROLLBAR_CHANGE; break;
224 if (instance->info->pre_activate_cb)
225 instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
228 #define add_scrollbar_callback(resource) \
229 XtAddCallback (scrollbar, resource, xlw_scrollbar_callback, (XtPointer) instance)
231 /* #### Does not yet support horizontal scrollbars. */
233 xlw_create_scrollbar (widget_instance *instance, int vertical)
237 static XtCallbackRec callbacks[2] =
238 { {xlw_scrollbar_callback, NULL}, {NULL, NULL} };
240 callbacks[0].closure = (XtPointer) instance;
242 XtSetArg (al[ac], XmNminimum, 1); ac++;
243 XtSetArg (al[ac], XmNmaximum, INT_MAX); ac++;
244 XtSetArg (al[ac], XmNincrement, 1); ac++;
245 XtSetArg (al[ac], XmNpageIncrement, 1); ac++;
246 XtSetArg (al[ac], XmNorientation, (vertical ? XmVERTICAL : XmHORIZONTAL)); ac++;
248 XtSetArg (al[ac], XmNdecrementCallback, callbacks); ac++;
249 XtSetArg (al[ac], XmNdragCallback, callbacks); ac++;
250 XtSetArg (al[ac], XmNincrementCallback, callbacks); ac++;
251 XtSetArg (al[ac], XmNpageDecrementCallback, callbacks); ac++;
252 XtSetArg (al[ac], XmNpageIncrementCallback, callbacks); ac++;
253 XtSetArg (al[ac], XmNtoBottomCallback, callbacks); ac++;
254 XtSetArg (al[ac], XmNtoTopCallback, callbacks); ac++;
255 XtSetArg (al[ac], XmNvalueChangedCallback, callbacks); ac++;
257 return XtCreateWidget (instance->info->name, xlwScrollBarWidgetClass,
258 instance->parent, al, ac);
262 xlw_create_vertical_scrollbar (widget_instance *instance)
264 return xlw_create_scrollbar (instance, 1);
268 xlw_create_horizontal_scrollbar (widget_instance *instance)
270 return xlw_create_scrollbar (instance, 0);
274 xlw_update_scrollbar (widget_instance *instance, Widget widget,
277 if (val->scrollbar_data)
279 scrollbar_values *data = val->scrollbar_data;
280 int widget_sliderSize, widget_val;
281 int new_sliderSize, new_value;
285 /* First size and position the scrollbar widget. */
286 XtSetArg (al [0], XtNx, data->scrollbar_x);
287 XtSetArg (al [1], XtNy, data->scrollbar_y);
288 XtSetArg (al [2], XtNwidth, data->scrollbar_width);
289 XtSetArg (al [3], XtNheight, data->scrollbar_height);
290 XtSetValues (widget, al, 4);
292 /* Now size the scrollbar's slider. */
293 XtSetArg (al [0], XmNsliderSize, &widget_sliderSize);
294 XtSetArg (al [1], XmNvalue, &widget_val);
295 XtGetValues (widget, al, 2);
297 percent = (double) data->slider_size /
298 (double) (data->maximum - data->minimum);
299 percent = (percent > 1.0 ? 1.0 : percent);
300 new_sliderSize = (int) ((double) (INT_MAX - 1) * percent);
302 percent = (double) (data->slider_position - data->minimum) /
303 (double) (data->maximum - data->minimum);
304 percent = (percent > 1.0 ? 1.0 : percent);
305 new_value = (int) ((double) (INT_MAX - 1) * percent);
307 if (new_sliderSize > INT_MAX - 1)
308 new_sliderSize = INT_MAX - 1;
309 else if (new_sliderSize < 1)
312 if (new_value > (INT_MAX - new_sliderSize))
313 new_value = INT_MAX - new_sliderSize;
314 else if (new_value < 1)
317 if (new_sliderSize != widget_sliderSize || new_value != widget_val)
318 XlwScrollBarSetValues (widget, new_value, new_sliderSize, 1, 1, False);
322 #endif /* LWLIB_SCROLLBARS_LUCID */
324 #ifdef LWLIB_TABS_LUCID
327 lwlib is such an incredible hairy crock. I just cannot believe
328 it! There are random dependencies between functions, there is a
329 total lack of genericity, even though it initially appears to be
330 generic. It should all be junked and begun again. Building tabs are
331 an example - in theory we should be able to reuse a lot of the
332 general stuff because we want to put labels of whatever toolkit we
333 are using in the tab. Instead we have to hack it by hand. */
335 xlw_tab_control_callback (Widget w, XtPointer client_data, XtPointer call_data)
337 /* call data is the topmost widget */
338 widget_instance* instance = (widget_instance*)client_data;
339 Widget top = (Widget)call_data;
340 char *name = XtName (top);
341 widget_value* widget_val;
342 XtPointer widget_arg;
344 lw_callback post_activate_cb;
346 if (w->core.being_destroyed)
349 /* Grab these values before running any functions, in case running
350 the selection_cb causes the widget to be destroyed. */
351 id = instance->info->id;
352 post_activate_cb = instance->info->post_activate_cb;
354 /* search for the widget_val for the selected tab */
355 for (widget_val = instance->info->val->contents; widget_val;
356 widget_val = widget_val->next)
358 if (!strcmp (widget_val->name, name))
362 widget_arg = widget_val ? widget_val->call_data : NULL;
364 if (instance->info->selection_cb &&
366 widget_val->enabled &&
367 !widget_val->contents)
368 instance->info->selection_cb (w, id, widget_arg);
370 if (post_activate_cb)
371 post_activate_cb (w, id, widget_arg);
375 xlw_create_tab_control (widget_instance *instance)
380 widget_value* val = instance->info->val;
382 XtSetArg (al [ac], XtNsensitive, val->enabled); ac++;
383 XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++;
384 XtSetArg (al [ac], XtNorientation, XtorientHorizontal); ac++;
385 XtSetArg (al [ac], XtNresizable, False); ac++;
387 /* add any args the user supplied for creation time */
388 lw_add_value_args_to_args (val, al, &ac);
390 tab = XtCreateManagedWidget (val->name, tabsWidgetClass,
391 instance->parent, al, ac);
392 XtRemoveAllCallbacks (tab, XtNcallback);
393 XtAddCallback (tab, XtNcallback, xlw_tab_control_callback, (XtPointer)instance);
400 static void build_tabs_in_widget (widget_instance* instance, Widget widget,
403 widget_value* cur = val;
404 for (cur = val; cur; cur = cur->next)
408 #ifdef LWLIB_WIDGETS_MOTIF
409 xm_create_label (widget, cur);
411 xaw_create_label (widget, cur);
414 cur->change = NO_CHANGE;
419 xlw_update_tab_control (widget_instance* instance, Widget widget, widget_value* val)
422 unsigned int num_children;
424 widget_value *cur = 0;
426 XtRemoveAllCallbacks (widget, XtNcallback);
427 XtAddCallback (widget, XtNcallback, xlw_tab_control_callback, (XtPointer)instance);
429 if (val->change == STRUCTURAL_CHANGE
431 (val->contents && val->contents->change == STRUCTURAL_CHANGE))
433 destroy_all_children (widget);
434 build_tabs_in_widget (instance, widget, val->contents);
437 children = XtCompositeChildren (widget, &num_children);
440 for (i = 0, cur = val->contents; i < num_children; i++)
444 if (children [i]->core.being_destroyed
445 || strcmp (XtName (children [i]), cur->name))
448 if (lw_motif_widget_p (children [i]))
449 xm_update_one_widget (instance, children [i], cur, False);
452 if (lw_xaw_widget_p (children [i]))
453 xaw_update_one_widget (instance, children [i], cur, False);
457 XtFree ((char *) children);
462 #endif /* LWLIB_TABS_LUCID */
466 xlw_create_clip_window (widget_instance *instance)
471 widget_value* val = instance->info->val;
473 XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++;
474 XtSetArg (al [ac], XtNsensitive, TRUE); ac++;
475 /* add any args the user supplied for creation time */
476 lw_add_value_args_to_args (val, al, &ac);
478 /* Create a clip window to contain the subwidget. Incredibly the
479 XEmacs manager seems to be the most appropriate widget for
480 this. Nothing else is simple enough and yet does what is
482 clip = XtCreateManagedWidget (val->name,
483 emacsManagerWidgetClass,
484 instance->parent, al, ac);
490 const widget_creation_entry
491 xlw_creation_table [] =
493 #ifdef LWLIB_MENUBARS_LUCID
494 {"menubar", xlw_create_menubar},
495 {"popup", xlw_create_popup_menu},
497 #ifdef LWLIB_SCROLLBARS_LUCID
498 {"vertical-scrollbar", xlw_create_vertical_scrollbar},
499 {"horizontal-scrollbar", xlw_create_horizontal_scrollbar},
501 #ifdef LWLIB_TABS_LUCID
502 {"tab-control", xlw_create_tab_control},
505 {"clip-window", xlw_create_clip_window},
511 lw_lucid_widget_p (Widget widget)
513 WidgetClass the_class = XtClass (widget);
514 #ifdef LWLIB_MENUBARS_LUCID
515 if (the_class == xlwMenuWidgetClass)
518 #ifdef LWLIB_SCROLLBARS_LUCID
519 if (the_class == xlwScrollBarWidgetClass)
522 #ifdef LWLIB_TABS_LUCID
523 if (the_class == tabsWidgetClass)
526 #ifdef LWLIB_MENUBARS_LUCID
527 if (the_class == overrideShellWidgetClass)
529 XtClass (((CompositeWidget)widget)->composite.children [0])
530 == xlwMenuWidgetClass;
533 if (the_class == emacsManagerWidgetClass)
540 xlw_update_one_widget (widget_instance* instance, Widget widget,
541 widget_value* val, Boolean deep_p)
543 WidgetClass class = XtClass (widget);
547 #ifdef LWLIB_MENUBARS_LUCID
548 else if (class == xlwMenuWidgetClass)
552 if (XtIsShell (widget))
553 mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
555 mw = (XlwMenuWidget)widget;
556 XtSetArg (al [0], XtNmenu, val);
557 XtSetValues (widget, al, 1); /* #### mw unused! */
560 #ifdef LWLIB_SCROLLBARS_LUCID
561 else if (class == xlwScrollBarWidgetClass)
563 xlw_update_scrollbar (instance, widget, val);
566 #ifdef LWLIB_TABS_LUCID
567 else if (class == tabsWidgetClass)
569 xlw_update_tab_control (instance, widget, val);
572 /* Lastly update our global arg values. */
573 if (val->args && val->args->nargs)
574 XtSetValues (widget, val->args->args, val->args->nargs);
578 xlw_update_one_value (widget_instance* instance, Widget widget,
585 xlw_pop_instance (widget_instance* instance, Boolean up)
589 #ifdef LWLIB_MENUBARS_LUCID
591 xlw_popup_menu (Widget widget, XEvent *event)
595 if (!XtIsShell (widget))
598 if (event->type == ButtonPress || event->type == ButtonRelease)
600 mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
601 xlw_pop_up_menu (mw, (XButtonPressedEvent *)event);
606 #endif /* LWLIB_MENUBARS_LUCID */
608 \f/* Destruction of instances */
610 xlw_destroy_instance (widget_instance* instance)
612 if (instance->widget)
613 XtDestroyWidget (instance->widget);