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"
55 #ifdef LWLIB_MENUBARS_LUCID
60 pre_hook (Widget w, XtPointer client_data, XtPointer call_data)
62 widget_instance* instance = (widget_instance*)client_data;
65 if (w->core.being_destroyed)
68 val = lw_get_widget_value_for_widget (instance, w);
70 /* #### - this code used to (for some random back_asswards reason) pass
71 the expression below in the call_data slot. For incremental menu
72 construction, this needs to go. I can't even figure out why it was done
73 this way in the first place...it's just a historical weirdism. --Stig */
74 call_data = (val ? val->call_data : NULL);
76 if (val && val->call_data)
77 abort(); /* #### - the call_data for the top_level
78 "menubar" widget_value used to be passed
79 back to the pre_hook. */
81 if (instance->info->pre_activate_cb)
82 instance->info->pre_activate_cb (w, instance->info->id, call_data);
86 pick_hook (Widget w, XtPointer client_data, XtPointer call_data)
88 widget_instance* instance = (widget_instance*)client_data;
89 widget_value* contents_val = (widget_value*)call_data;
90 widget_value* widget_val;
93 lw_callback post_activate_cb;
95 if (w->core.being_destroyed)
98 /* Grab these values before running any functions, in case running
99 the selection_cb causes the widget to be destroyed. */
100 id = instance->info->id;
101 post_activate_cb = instance->info->post_activate_cb;
103 widget_val = lw_get_widget_value_for_widget (instance, w);
104 widget_arg = widget_val ? widget_val->call_data : NULL;
106 if (instance->info->selection_cb &&
108 contents_val->enabled &&
109 !contents_val->contents)
110 instance->info->selection_cb (w, id, contents_val->call_data);
112 if (post_activate_cb)
113 post_activate_cb (w, id, widget_arg);
118 /* creation functions */
120 xlw_create_menubar (widget_instance* instance)
125 XtSetArg (al [0], XtNmenu, instance->info->val);
126 widget = XtCreateWidget (instance->info->name, xlwMenuWidgetClass,
127 instance->parent, al, 1);
128 XtAddCallback (widget, XtNopen, pre_hook, (XtPointer)instance);
129 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
134 xlw_create_popup_menu (widget_instance* instance)
137 Widget popup_shell, widget;
139 popup_shell = XtCreatePopupShell (instance->info->name,
140 overrideShellWidgetClass,
141 instance->parent, NULL, 0);
142 XtSetArg (al [0], XtNmenu, instance->info->val);
143 XtSetArg (al [1], XtNhorizontal, False);
144 widget = XtCreateManagedWidget ("popup", xlwMenuWidgetClass,
146 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
150 #endif /* LWLIB_MENUBARS_LUCID */
152 #ifdef LWLIB_SCROLLBARS_LUCID
154 xlw_scrollbar_callback (Widget widget, XtPointer closure, XtPointer call_data)
156 widget_instance *instance = (widget_instance *) closure;
158 XlwScrollBarCallbackStruct *data =
159 (XlwScrollBarCallbackStruct *) call_data;
160 scroll_event event_data;
161 scrollbar_values *val =
162 (scrollbar_values *) instance->info->val->scrollbar_data;
165 if (!instance || widget->core.being_destroyed)
168 id = instance->info->id;
170 percent = (double) (data->value - 1) / (double) (INT_MAX - 1);
171 event_data.slider_value =
172 (int) (percent * (double) (val->maximum - val->minimum)) + val->minimum;
174 if (event_data.slider_value > val->maximum - val->slider_size)
175 event_data.slider_value = val->maximum - val->slider_size;
176 else if (event_data.slider_value < val->minimum)
177 event_data.slider_value = val->minimum;
181 switch (data->event->type)
185 event_data.time = data->event->xkey.time;
189 event_data.time = data->event->xbutton.time;
192 event_data.time = data->event->xmotion.time;
196 event_data.time = data->event->xcrossing.time;
206 switch (data->reason)
208 case XmCR_DECREMENT: event_data.action = SCROLLBAR_LINE_UP; break;
209 case XmCR_INCREMENT: event_data.action = SCROLLBAR_LINE_DOWN; break;
210 case XmCR_PAGE_DECREMENT: event_data.action = SCROLLBAR_PAGE_UP; break;
211 case XmCR_PAGE_INCREMENT: event_data.action = SCROLLBAR_PAGE_DOWN; break;
212 case XmCR_TO_TOP: event_data.action = SCROLLBAR_TOP; break;
213 case XmCR_TO_BOTTOM: event_data.action = SCROLLBAR_BOTTOM; break;
214 case XmCR_DRAG: event_data.action = SCROLLBAR_DRAG; break;
215 case XmCR_VALUE_CHANGED: event_data.action = SCROLLBAR_CHANGE; break;
216 default: event_data.action = SCROLLBAR_CHANGE; break;
219 if (instance->info->pre_activate_cb)
220 instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
223 #define add_scrollbar_callback(resource) \
224 XtAddCallback (scrollbar, resource, xlw_scrollbar_callback, (XtPointer) instance)
226 /* #### Does not yet support horizontal scrollbars. */
228 xlw_create_scrollbar (widget_instance *instance, int vertical)
232 static XtCallbackRec callbacks[2] =
233 { {xlw_scrollbar_callback, NULL}, {NULL, NULL} };
235 callbacks[0].closure = (XtPointer) instance;
237 XtSetArg (al[ac], XmNminimum, 1); ac++;
238 XtSetArg (al[ac], XmNmaximum, INT_MAX); ac++;
239 XtSetArg (al[ac], XmNincrement, 1); ac++;
240 XtSetArg (al[ac], XmNpageIncrement, 1); ac++;
241 XtSetArg (al[ac], XmNorientation, (vertical ? XmVERTICAL : XmHORIZONTAL)); ac++;
243 XtSetArg (al[ac], XmNdecrementCallback, callbacks); ac++;
244 XtSetArg (al[ac], XmNdragCallback, callbacks); ac++;
245 XtSetArg (al[ac], XmNincrementCallback, callbacks); ac++;
246 XtSetArg (al[ac], XmNpageDecrementCallback, callbacks); ac++;
247 XtSetArg (al[ac], XmNpageIncrementCallback, callbacks); ac++;
248 XtSetArg (al[ac], XmNtoBottomCallback, callbacks); ac++;
249 XtSetArg (al[ac], XmNtoTopCallback, callbacks); ac++;
250 XtSetArg (al[ac], XmNvalueChangedCallback, callbacks); ac++;
252 return XtCreateWidget (instance->info->name, xlwScrollBarWidgetClass,
253 instance->parent, al, ac);
257 xlw_create_vertical_scrollbar (widget_instance *instance)
259 return xlw_create_scrollbar (instance, 1);
263 xlw_create_horizontal_scrollbar (widget_instance *instance)
265 return xlw_create_scrollbar (instance, 0);
269 xlw_update_scrollbar (widget_instance *instance, Widget widget,
272 if (val->scrollbar_data)
274 scrollbar_values *data = val->scrollbar_data;
275 int widget_sliderSize, widget_val;
276 int new_sliderSize, new_value;
280 /* First size and position the scrollbar widget. */
281 XtSetArg (al [0], XtNx, data->scrollbar_x);
282 XtSetArg (al [1], XtNy, data->scrollbar_y);
283 XtSetArg (al [2], XtNwidth, data->scrollbar_width);
284 XtSetArg (al [3], XtNheight, data->scrollbar_height);
285 XtSetValues (widget, al, 4);
287 /* Now size the scrollbar's slider. */
288 XtSetArg (al [0], XmNsliderSize, &widget_sliderSize);
289 XtSetArg (al [1], XmNvalue, &widget_val);
290 XtGetValues (widget, al, 2);
292 percent = (double) data->slider_size /
293 (double) (data->maximum - data->minimum);
294 percent = (percent > 1.0 ? 1.0 : percent);
295 new_sliderSize = (int) ((double) (INT_MAX - 1) * percent);
297 percent = (double) (data->slider_position - data->minimum) /
298 (double) (data->maximum - data->minimum);
299 percent = (percent > 1.0 ? 1.0 : percent);
300 new_value = (int) ((double) (INT_MAX - 1) * percent);
302 if (new_sliderSize > INT_MAX - 1)
303 new_sliderSize = INT_MAX - 1;
304 else if (new_sliderSize < 1)
307 if (new_value > (INT_MAX - new_sliderSize))
308 new_value = INT_MAX - new_sliderSize;
309 else if (new_value < 1)
312 if (new_sliderSize != widget_sliderSize || new_value != widget_val)
313 XlwScrollBarSetValues (widget, new_value, new_sliderSize, 1, 1, False);
317 #endif /* LWLIB_SCROLLBARS_LUCID */
319 #ifdef LWLIB_TABS_LUCID
322 lwlib is such an incredible hairy crock. I just cannot believe
323 it! There are random dependencies between functions, there is a
324 total lack of genericity, even though it initially appears to be
325 generic. It should all be junked and begun again. Building tabs are
326 an example - in theory we should be able to reuse a lot of the
327 general stuff because we want to put labels of whatever toolkit we
328 are using in the tab. Instead we have to hack it by hand. */
330 xlw_tab_control_callback (Widget w, XtPointer client_data, XtPointer call_data)
332 /* call data is the topmost widget */
333 widget_instance* instance = (widget_instance*)client_data;
334 Widget top = (Widget)call_data;
335 char *name = XtName (top);
336 widget_value* widget_val;
337 XtPointer widget_arg;
339 lw_callback post_activate_cb;
341 if (w->core.being_destroyed)
344 /* Grab these values before running any functions, in case running
345 the selection_cb causes the widget to be destroyed. */
346 id = instance->info->id;
347 post_activate_cb = instance->info->post_activate_cb;
349 /* search for the widget_val for the selected tab */
350 for (widget_val = instance->info->val->contents; widget_val;
351 widget_val = widget_val->next)
353 if (!strcmp (widget_val->name, name))
357 widget_arg = widget_val ? widget_val->call_data : NULL;
359 if (instance->info->selection_cb &&
361 widget_val->enabled &&
362 !widget_val->contents)
363 instance->info->selection_cb (w, id, widget_arg);
365 if (post_activate_cb)
366 post_activate_cb (w, id, widget_arg);
370 xlw_create_tab_control (widget_instance *instance)
375 widget_value* val = instance->info->val;
377 XtSetArg (al [ac], XtNsensitive, val->enabled); ac++;
378 XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++;
379 XtSetArg (al [ac], XtNorientation, XtorientHorizontal); ac++;
380 XtSetArg (al [ac], XtNresizable, False); ac++;
382 /* add any args the user supplied for creation time */
383 lw_add_value_args_to_args (val, al, &ac);
385 tab = XtCreateManagedWidget (val->name, tabsWidgetClass,
386 instance->parent, al, ac);
387 XtRemoveAllCallbacks (tab, XtNcallback);
388 XtAddCallback (tab, XtNcallback, xlw_tab_control_callback, (XtPointer)instance);
395 static void build_tabs_in_widget (widget_instance* instance, Widget widget,
398 widget_value* cur = val;
399 for (cur = val; cur; cur = cur->next)
403 #ifdef LWLIB_WIDGETS_MOTIF
404 xm_create_label (widget, cur);
406 xaw_create_label (widget, cur);
409 cur->change = NO_CHANGE;
414 xlw_update_tab_control (widget_instance* instance, Widget widget, widget_value* val)
417 unsigned int num_children;
419 widget_value *cur = 0;
421 XtRemoveAllCallbacks (widget, XtNcallback);
422 XtAddCallback (widget, XtNcallback, xlw_tab_control_callback, (XtPointer)instance);
424 if (val->change == STRUCTURAL_CHANGE
426 (val->contents && val->contents->change == STRUCTURAL_CHANGE))
428 destroy_all_children (widget);
429 build_tabs_in_widget (instance, widget, val->contents);
432 children = XtCompositeChildren (widget, &num_children);
435 for (i = 0, cur = val->contents; i < num_children; i++)
439 if (children [i]->core.being_destroyed
440 || strcmp (XtName (children [i]), cur->name))
443 if (lw_motif_widget_p (children [i]))
444 xm_update_one_widget (instance, children [i], cur, False);
447 if (lw_xaw_widget_p (children [i]))
448 xaw_update_one_widget (instance, children [i], cur, False);
452 XtFree ((char *) children);
457 #endif /* LWLIB_TABS_LUCID */
461 xlw_create_clip_window (widget_instance *instance)
466 widget_value* val = instance->info->val;
468 XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++;
469 XtSetArg (al [ac], XtNsensitive, TRUE); ac++;
470 /* add any args the user supplied for creation time */
471 lw_add_value_args_to_args (val, al, &ac);
473 /* Create a clip window to contain the subwidget. Incredibly the
474 XEmacs manager seems to be the most appropriate widget for
475 this. Nothing else is simple enough and yet does what is
477 clip = XtCreateManagedWidget (val->name,
478 emacsManagerWidgetClass,
479 instance->parent, al, ac);
485 const widget_creation_entry
486 xlw_creation_table [] =
488 #ifdef LWLIB_MENUBARS_LUCID
489 {"menubar", xlw_create_menubar},
490 {"popup", xlw_create_popup_menu},
492 #ifdef LWLIB_SCROLLBARS_LUCID
493 {"vertical-scrollbar", xlw_create_vertical_scrollbar},
494 {"horizontal-scrollbar", xlw_create_horizontal_scrollbar},
496 #ifdef LWLIB_TABS_LUCID
497 {"tab-control", xlw_create_tab_control},
500 {"clip-window", xlw_create_clip_window},
506 lw_lucid_widget_p (Widget widget)
508 WidgetClass the_class = XtClass (widget);
509 #ifdef LWLIB_MENUBARS_LUCID
510 if (the_class == xlwMenuWidgetClass)
513 #ifdef LWLIB_SCROLLBARS_LUCID
514 if (the_class == xlwScrollBarWidgetClass)
517 #ifdef LWLIB_TABS_LUCID
518 if (the_class == tabsWidgetClass)
521 #ifdef LWLIB_MENUBARS_LUCID
522 if (the_class == overrideShellWidgetClass)
524 XtClass (((CompositeWidget)widget)->composite.children [0])
525 == xlwMenuWidgetClass;
528 if (the_class == emacsManagerWidgetClass)
535 xlw_update_one_widget (widget_instance* instance, Widget widget,
536 widget_value* val, Boolean deep_p)
538 WidgetClass class = XtClass (widget);
542 #ifdef LWLIB_MENUBARS_LUCID
543 else if (class == xlwMenuWidgetClass)
547 if (XtIsShell (widget))
548 mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
550 mw = (XlwMenuWidget)widget;
551 XtSetArg (al [0], XtNmenu, val);
552 XtSetValues (widget, al, 1); /* #### mw unused! */
555 #ifdef LWLIB_SCROLLBARS_LUCID
556 else if (class == xlwScrollBarWidgetClass)
558 xlw_update_scrollbar (instance, widget, val);
561 #ifdef LWLIB_TABS_LUCID
562 else if (class == tabsWidgetClass)
564 xlw_update_tab_control (instance, widget, val);
567 /* Lastly update our global arg values. */
568 if (val->args && val->args->nargs)
569 XtSetValues (widget, val->args->args, val->args->nargs);
573 xlw_update_one_value (widget_instance* instance, Widget widget,
580 xlw_pop_instance (widget_instance* instance, Boolean up)
584 #ifdef LWLIB_MENUBARS_LUCID
586 xlw_popup_menu (Widget widget, XEvent *event)
590 if (!XtIsShell (widget))
593 if (event->type == ButtonPress || event->type == ButtonRelease)
595 mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
596 xlw_pop_up_menu (mw, (XButtonPressedEvent *)event);
601 #endif /* LWLIB_MENUBARS_LUCID */
603 \f/* Destruction of instances */
605 xlw_destroy_instance (widget_instance* instance)
607 if (instance->widget)
608 XtDestroyWidget (instance->widget);