comparison lwlib/lwlib-Xlw.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 3a7e78e1142d
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
1 /* The lwlib interface to "xlwmenu" menus.
2 Copyright (C) 1992, 1994 Lucid, Inc.
3
4 This file is part of the Lucid Widget Library.
5
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)
9 any later version.
10
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.
15
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. */
20
21 #include <config.h>
22 #include <stdlib.h> /* for abort () */
23 #include <stdio.h> /* for abort () */
24 #include <limits.h>
25
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>
33 #ifdef HAVE_WIDGETS
34 #include "../src/EmacsManager.h"
35 #endif
36 #ifdef LWLIB_MENUBARS_LUCID
37 #include "xlwmenu.h"
38 #endif
39 #ifdef LWLIB_SCROLLBARS_LUCID
40 #include "xlwscrollbar.h"
41 #endif
42 #ifdef LWLIB_TABS_LUCID
43 #ifdef NEED_MOTIF
44 #include "lwlib-Xm.h"
45 #endif
46 #ifdef NEED_ATHENA
47 #include "lwlib-Xaw.h"
48 #endif
49 #include "../src/xmu.h"
50 #include "xlwtabs.h"
51 #endif
52
53
54
55 #ifdef LWLIB_MENUBARS_LUCID
56
57 /* Menu callbacks */
58
59 static void
60 pre_hook (Widget w, XtPointer client_data, XtPointer call_data)
61 {
62 widget_instance* instance = (widget_instance*)client_data;
63 widget_value* val;
64
65 if (w->core.being_destroyed)
66 return;
67
68 val = lw_get_widget_value_for_widget (instance, w);
69 #if 0
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);
75 #endif
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. */
80
81 if (instance->info->pre_activate_cb)
82 instance->info->pre_activate_cb (w, instance->info->id, call_data);
83 }
84
85 static void
86 pick_hook (Widget w, XtPointer client_data, XtPointer call_data)
87 {
88 widget_instance* instance = (widget_instance*)client_data;
89 widget_value* contents_val = (widget_value*)call_data;
90 widget_value* widget_val;
91 XtPointer widget_arg;
92 LWLIB_ID id;
93 lw_callback post_activate_cb;
94
95 if (w->core.being_destroyed)
96 return;
97
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;
102
103 widget_val = lw_get_widget_value_for_widget (instance, w);
104 widget_arg = widget_val ? widget_val->call_data : NULL;
105
106 if (instance->info->selection_cb &&
107 contents_val &&
108 contents_val->enabled &&
109 !contents_val->contents)
110 instance->info->selection_cb (w, id, contents_val->call_data);
111
112 if (post_activate_cb)
113 post_activate_cb (w, id, widget_arg);
114 }
115
116
117
118 /* creation functions */
119 static Widget
120 xlw_create_menubar (widget_instance* instance)
121 {
122 Arg al [1];
123 Widget widget;
124
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);
130 return widget;
131 }
132
133 static Widget
134 xlw_create_popup_menu (widget_instance* instance)
135 {
136 Arg al [2];
137 Widget popup_shell, widget;
138
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,
145 popup_shell, al, 2);
146 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
147
148 return popup_shell;
149 }
150 #endif /* LWLIB_MENUBARS_LUCID */
151
152 #ifdef LWLIB_SCROLLBARS_LUCID
153 static void
154 xlw_scrollbar_callback (Widget widget, XtPointer closure, XtPointer call_data)
155 {
156 widget_instance *instance = (widget_instance *) closure;
157 LWLIB_ID id;
158 XlwScrollBarCallbackStruct *data =
159 (XlwScrollBarCallbackStruct *) call_data;
160 scroll_event event_data;
161 scrollbar_values *val =
162 (scrollbar_values *) instance->info->val->scrollbar_data;
163 double percent;
164
165 if (!instance || widget->core.being_destroyed)
166 return;
167
168 id = instance->info->id;
169
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;
173
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;
178
179 if (data->event)
180 {
181 switch (data->event->type)
182 {
183 case KeyPress:
184 case KeyRelease:
185 event_data.time = data->event->xkey.time;
186 break;
187 case ButtonPress:
188 case ButtonRelease:
189 event_data.time = data->event->xbutton.time;
190 break;
191 case MotionNotify:
192 event_data.time = data->event->xmotion.time;
193 break;
194 case EnterNotify:
195 case LeaveNotify:
196 event_data.time = data->event->xcrossing.time;
197 break;
198 default:
199 event_data.time = 0;
200 break;
201 }
202 }
203 else
204 event_data.time = 0;
205
206 switch (data->reason)
207 {
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;
217 }
218
219 if (instance->info->pre_activate_cb)
220 instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
221 }
222
223 #define add_scrollbar_callback(resource) \
224 XtAddCallback (scrollbar, resource, xlw_scrollbar_callback, (XtPointer) instance)
225
226 /* #### Does not yet support horizontal scrollbars. */
227 static Widget
228 xlw_create_scrollbar (widget_instance *instance, int vertical)
229 {
230 Arg al[20];
231 int ac = 0;
232 static XtCallbackRec callbacks[2] =
233 { {xlw_scrollbar_callback, NULL}, {NULL, NULL} };
234
235 callbacks[0].closure = (XtPointer) instance;
236
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++;
242
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++;
251
252 return XtCreateWidget (instance->info->name, xlwScrollBarWidgetClass,
253 instance->parent, al, ac);
254 }
255
256 static Widget
257 xlw_create_vertical_scrollbar (widget_instance *instance)
258 {
259 return xlw_create_scrollbar (instance, 1);
260 }
261
262 static Widget
263 xlw_create_horizontal_scrollbar (widget_instance *instance)
264 {
265 return xlw_create_scrollbar (instance, 0);
266 }
267
268 static void
269 xlw_update_scrollbar (widget_instance *instance, Widget widget,
270 widget_value *val)
271 {
272 if (val->scrollbar_data)
273 {
274 scrollbar_values *data = val->scrollbar_data;
275 int widget_sliderSize, widget_val;
276 int new_sliderSize, new_value;
277 double percent;
278 Arg al [4];
279
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);
286
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);
291
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);
296
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);
301
302 if (new_sliderSize > INT_MAX - 1)
303 new_sliderSize = INT_MAX - 1;
304 else if (new_sliderSize < 1)
305 new_sliderSize = 1;
306
307 if (new_value > (INT_MAX - new_sliderSize))
308 new_value = INT_MAX - new_sliderSize;
309 else if (new_value < 1)
310 new_value = 1;
311
312 if (new_sliderSize != widget_sliderSize || new_value != widget_val)
313 XlwScrollBarSetValues (widget, new_value, new_sliderSize, 1, 1, False);
314 }
315 }
316
317 #endif /* LWLIB_SCROLLBARS_LUCID */
318
319 #ifdef LWLIB_TABS_LUCID
320 /* tab control
321
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. */
329 static void
330 xlw_tab_control_callback (Widget w, XtPointer client_data, XtPointer call_data)
331 {
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;
338 LWLIB_ID id;
339 lw_callback post_activate_cb;
340
341 if (w->core.being_destroyed)
342 return;
343
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;
348
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)
352 {
353 if (!strcmp (widget_val->name, name))
354 break;
355 }
356
357 widget_arg = widget_val ? widget_val->call_data : NULL;
358
359 if (instance->info->selection_cb &&
360 widget_val &&
361 widget_val->enabled &&
362 !widget_val->contents)
363 instance->info->selection_cb (w, id, widget_arg);
364
365 if (post_activate_cb)
366 post_activate_cb (w, id, widget_arg);
367 }
368
369 static Widget
370 xlw_create_tab_control (widget_instance *instance)
371 {
372 Arg al[20];
373 int ac = 0;
374 Widget tab = 0;
375 widget_value* val = instance->info->val;
376
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++;
381
382 /* add any args the user supplied for creation time */
383 lw_add_value_args_to_args (val, al, &ac);
384
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);
389
390 XtManageChild (tab);
391
392 return tab;
393 }
394
395 static void build_tabs_in_widget (widget_instance* instance, Widget widget,
396 widget_value* val)
397 {
398 widget_value* cur = val;
399 for (cur = val; cur; cur = cur->next)
400 {
401 if (cur->value)
402 {
403 #ifdef LWLIB_WIDGETS_MOTIF
404 xm_create_label (widget, cur);
405 #else
406 xaw_create_label (widget, cur);
407 #endif
408 }
409 cur->change = NO_CHANGE;
410 }
411 }
412
413 static void
414 xlw_update_tab_control (widget_instance* instance, Widget widget, widget_value* val)
415 {
416 Widget* children;
417 unsigned int num_children;
418 int i;
419 widget_value *cur = 0;
420
421 XtRemoveAllCallbacks (widget, XtNcallback);
422 XtAddCallback (widget, XtNcallback, xlw_tab_control_callback, (XtPointer)instance);
423
424 if (val->change == STRUCTURAL_CHANGE
425 ||
426 (val->contents && val->contents->change == STRUCTURAL_CHANGE))
427 {
428 destroy_all_children (widget);
429 build_tabs_in_widget (instance, widget, val->contents);
430 }
431
432 children = XtCompositeChildren (widget, &num_children);
433 if (children)
434 {
435 for (i = 0, cur = val->contents; i < num_children; i++)
436 {
437 if (!cur)
438 abort ();
439 if (children [i]->core.being_destroyed
440 || strcmp (XtName (children [i]), cur->name))
441 continue;
442 #ifdef NEED_MOTIF
443 if (lw_motif_widget_p (children [i]))
444 xm_update_one_widget (instance, children [i], cur, False);
445 #endif
446 #ifdef NEED_ATHENA
447 if (lw_xaw_widget_p (children [i]))
448 xaw_update_one_widget (instance, children [i], cur, False);
449 #endif
450 cur = cur->next;
451 }
452 XtFree ((char *) children);
453 }
454 if (cur)
455 abort ();
456 }
457 #endif /* LWLIB_TABS_LUCID */
458
459 #ifdef HAVE_WIDGETS
460 static Widget
461 xlw_create_clip_window (widget_instance *instance)
462 {
463 Arg al[20];
464 int ac = 0;
465 Widget clip = 0;
466 widget_value* val = instance->info->val;
467
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);
472
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
476 required. */
477 clip = XtCreateManagedWidget (val->name,
478 emacsManagerWidgetClass,
479 instance->parent, al, ac);
480
481 return clip;
482 }
483 #endif
484
485 widget_creation_entry
486 xlw_creation_table [] =
487 {
488 #ifdef LWLIB_MENUBARS_LUCID
489 {"menubar", xlw_create_menubar},
490 {"popup", xlw_create_popup_menu},
491 #endif
492 #ifdef LWLIB_SCROLLBARS_LUCID
493 {"vertical-scrollbar", xlw_create_vertical_scrollbar},
494 {"horizontal-scrollbar", xlw_create_horizontal_scrollbar},
495 #endif
496 #ifdef LWLIB_TABS_LUCID
497 {"tab-control", xlw_create_tab_control},
498 #endif
499 #ifdef HAVE_WIDGETS
500 {"clip-window", xlw_create_clip_window},
501 #endif
502 {NULL, NULL}
503 };
504
505 Boolean
506 lw_lucid_widget_p (Widget widget)
507 {
508 WidgetClass the_class = XtClass (widget);
509 #ifdef LWLIB_MENUBARS_LUCID
510 if (the_class == xlwMenuWidgetClass)
511 return True;
512 #endif
513 #ifdef LWLIB_SCROLLBARS_LUCID
514 if (the_class == xlwScrollBarWidgetClass)
515 return True;
516 #endif
517 #ifdef LWLIB_TABS_LUCID
518 if (the_class == tabsWidgetClass)
519 return True;
520 #endif
521 #ifdef LWLIB_MENUBARS_LUCID
522 if (the_class == overrideShellWidgetClass)
523 return
524 XtClass (((CompositeWidget)widget)->composite.children [0])
525 == xlwMenuWidgetClass;
526 #endif
527 return False;
528 }
529
530 void
531 xlw_update_one_widget (widget_instance* instance, Widget widget,
532 widget_value* val, Boolean deep_p)
533 {
534 WidgetClass class = XtClass (widget);
535
536 if (0)
537 ;
538 #ifdef LWLIB_MENUBARS_LUCID
539 else if (class == xlwMenuWidgetClass)
540 {
541 XlwMenuWidget mw;
542 Arg al [1];
543 if (XtIsShell (widget))
544 mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
545 else
546 mw = (XlwMenuWidget)widget;
547 XtSetArg (al [0], XtNmenu, val);
548 XtSetValues (widget, al, 1);
549 }
550 #endif
551 #ifdef LWLIB_SCROLLBARS_LUCID
552 else if (class == xlwScrollBarWidgetClass)
553 {
554 xlw_update_scrollbar (instance, widget, val);
555 }
556 #endif
557 #ifdef LWLIB_TABS_LUCID
558 else if (class == tabsWidgetClass)
559 {
560 xlw_update_tab_control (instance, widget, val);
561 }
562 #endif
563 }
564
565 void
566 xlw_update_one_value (widget_instance* instance, Widget widget,
567 widget_value* val)
568 {
569 return;
570 }
571
572 void
573 xlw_pop_instance (widget_instance* instance, Boolean up)
574 {
575 }
576
577 #ifdef LWLIB_MENUBARS_LUCID
578 void
579 xlw_popup_menu (Widget widget, XEvent *event)
580 {
581 XlwMenuWidget mw;
582
583 if (!XtIsShell (widget))
584 return;
585
586 if (event->type == ButtonPress || event->type == ButtonRelease)
587 {
588 mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
589 xlw_pop_up_menu (mw, (XButtonPressedEvent *)event);
590 }
591 else
592 abort ();
593 }
594 #endif /* LWLIB_MENUBARS_LUCID */
595
596 /* Destruction of instances */
597 void
598 xlw_destroy_instance (widget_instance* instance)
599 {
600 if (instance->widget)
601 XtDestroyWidget (instance->widget);
602 }