Fix prototypes.
[emacs.git] / lwlib / lwlib-Xaw.c
blob3ac72acdace076bf3ad7cace1f30fcf3f096b674
1 /* The lwlib interface to Athena widgets.
2 Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
3 Copyright (C) 1994, 2001, 2002, 2003, 2004, 2005, 2006,
4 2007, 2008, 2009, 2010 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 1, or (at your option)
11 any later version.
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. */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdio.h>
28 #include <setjmp.h>
30 #include "../src/lisp.h"
32 #include "lwlib-Xaw.h"
34 #include <X11/StringDefs.h>
35 #include <X11/IntrinsicP.h>
36 #include <X11/CoreP.h>
37 #include <X11/Shell.h>
39 #ifdef HAVE_XAW3D
40 #include <X11/Xaw3d/Scrollbar.h>
41 #include <X11/Xaw3d/Paned.h>
42 #include <X11/Xaw3d/Dialog.h>
43 #include <X11/Xaw3d/Form.h>
44 #include <X11/Xaw3d/Command.h>
45 #include <X11/Xaw3d/Label.h>
46 #else /* !HAVE_XAW3D */
47 #include <X11/Xaw/Scrollbar.h>
48 #include <X11/Xaw/Paned.h>
49 #include <X11/Xaw/Dialog.h>
50 #include <X11/Xaw/Form.h>
51 #include <X11/Xaw/Command.h>
52 #include <X11/Xaw/Label.h>
53 #endif /* HAVE_XAW3D */
55 #include <X11/Xatom.h>
57 #ifdef HAVE_XFT
58 #include <X11/Xft/Xft.h>
60 struct widget_xft_data
62 Widget widget;
63 XftFont *xft_font;
64 XftDraw *xft_draw;
65 XftColor xft_fg, xft_bg;
66 int p_width, p_height;
67 Pixmap p;
71 #endif
73 static void xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data);
76 Boolean
77 lw_xaw_widget_p (Widget widget)
79 return (XtIsSubclass (widget, scrollbarWidgetClass) ||
80 XtIsSubclass (widget, dialogWidgetClass));
83 #if 0
84 static void
85 xaw_update_scrollbar (instance, widget, val)
86 widget_instance *instance;
87 Widget widget;
88 widget_value *val;
90 if (val->scrollbar_data)
92 scrollbar_values *data = val->scrollbar_data;
93 Dimension height, width;
94 Dimension pos_x, pos_y;
95 int widget_shown, widget_topOfThumb;
96 float new_shown, new_topOfThumb;
98 XtVaGetValues (widget,
99 XtNheight, &height,
100 XtNwidth, &width,
101 XtNx, &pos_x,
102 XtNy, &pos_y,
103 XtNtopOfThumb, &widget_topOfThumb,
104 XtNshown, &widget_shown,
105 NULL);
108 * First size and position the scrollbar widget.
109 * We need to position it to second-guess the Paned widget's notion
110 * of what should happen when the WMShell gets resized.
112 if (height != data->scrollbar_height || pos_y != data->scrollbar_pos)
114 XtConfigureWidget (widget, pos_x, data->scrollbar_pos,
115 width, data->scrollbar_height, 0);
117 XtVaSetValues (widget,
118 XtNlength, data->scrollbar_height,
119 XtNthickness, width,
120 NULL);
124 * Now the size the scrollbar's slider.
126 new_shown = (float) data->slider_size /
127 (float) (data->maximum - data->minimum);
129 new_topOfThumb = (float) (data->slider_position - data->minimum) /
130 (float) (data->maximum - data->minimum);
132 if (new_shown > 1.0)
133 new_shown = 1.0;
134 if (new_shown < 0)
135 new_shown = 0;
137 if (new_topOfThumb > 1.0)
138 new_topOfThumb = 1.0;
139 if (new_topOfThumb < 0)
140 new_topOfThumb = 0;
142 if (new_shown != widget_shown || new_topOfThumb != widget_topOfThumb)
143 XawScrollbarSetThumb (widget, new_topOfThumb, new_shown);
146 #endif
148 #ifdef HAVE_XFT
149 static void
150 fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
152 Pixel bg, fg;
153 XColor colors[2];
154 int screen = XScreenNumberOfScreen (XtScreen (widget));
156 data->widget = widget;
157 data->xft_font = font;
158 XtVaGetValues (widget,
159 XtNbackground, &bg,
160 XtNforeground, &fg,
161 NULL);
163 colors[0].pixel = data->xft_fg.pixel = fg;
164 colors[1].pixel = data->xft_bg.pixel = bg;
165 XQueryColors (XtDisplay (widget),
166 DefaultColormapOfScreen (XtScreen (widget)),
167 colors, 2);
169 data->xft_fg.color.alpha = 0xFFFF;
170 data->xft_fg.color.red = colors[0].red;
171 data->xft_fg.color.green = colors[0].green;
172 data->xft_fg.color.blue = colors[0].blue;
173 data->xft_bg.color.alpha = 0xFFFF;
174 data->xft_bg.color.red = colors[1].red;
175 data->xft_bg.color.green = colors[1].green;
176 data->xft_bg.color.blue = colors[1].blue;
178 data->p = None;
179 data->xft_draw = 0;
180 data->p_width = data->p_height = 0;
183 static XftFont*
184 openFont (Widget widget, char *name)
186 char *fname = name;
187 int screen = XScreenNumberOfScreen (XtScreen (widget));
188 int len = strlen (fname), i = len-1;
189 XftFont *fn;
191 /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
192 while (i > 0 && isdigit (fname[i]))
193 --i;
194 if (fname[i] == ' ')
196 fname = xstrdup (name);
197 fname[i] = '-';
200 fn = XftFontOpenName (XtDisplay (widget), screen, fname);
201 if (fname != name) free (fname);
203 return fn;
206 static int
207 get_text_width_and_height (Widget widget, char *text,
208 XftFont *xft_font,
209 int *height)
211 int w = 0, h = 0;
212 char *bp = text;
214 while (bp && *bp != '\0')
216 XGlyphInfo gi;
217 char *cp = strchr (bp, '\n');
218 XftTextExtentsUtf8 (XtDisplay (widget), xft_font,
219 (FcChar8 *) bp,
220 cp ? cp - bp : strlen (bp),
221 &gi);
222 bp = cp ? cp + 1 : NULL;
223 h += xft_font->height;
224 if (w < gi.width) w = gi.width;
227 *height = h;
228 return w;
231 static void
232 draw_text (struct widget_xft_data *data, char *lbl, int inverse)
234 Screen *sc = XtScreen (data->widget);
235 int screen = XScreenNumberOfScreen (sc);
236 int y = data->xft_font->ascent;
237 int x = inverse ? 0 : 2;
238 char *bp = lbl;
240 data->xft_draw = XftDrawCreate (XtDisplay (data->widget),
241 data->p,
242 DefaultVisual (XtDisplay (data->widget),
243 screen),
244 DefaultColormapOfScreen (sc));
245 XftDrawRect (data->xft_draw,
246 inverse ? &data->xft_fg : &data->xft_bg,
247 0, 0, data->p_width, data->p_height);
249 if (!inverse) y += 2;
250 while (bp && *bp != '\0')
252 char *cp = strchr (bp, '\n');
253 XftDrawStringUtf8 (data->xft_draw,
254 inverse ? &data->xft_bg : &data->xft_fg,
255 data->xft_font, x, y, bp, cp ? cp - bp : strlen (bp));
256 bp = cp ? cp + 1 : NULL;
257 /* 1.2 gives reasonable line spacing. */
258 y += data->xft_font->height * 1.2;
264 static void
265 set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
267 int screen = XScreenNumberOfScreen (XtScreen (data->widget));
268 int width, height;
270 width = get_text_width_and_height (data->widget, lbl, data->xft_font,
271 &height);
272 data->p_width = width + margin;
273 data->p_height = height + margin;
275 data->p = XCreatePixmap (XtDisplay (data->widget),
276 XtWindow (toplevel),
277 data->p_width,
278 data->p_height,
279 DefaultDepthOfScreen (XtScreen (data->widget)));
280 draw_text (data, lbl, 0);
281 XtVaSetValues (data->widget, XtNbitmap, data->p, NULL);
284 static struct widget_xft_data *
285 find_xft_data (Widget widget)
287 widget_instance *inst = NULL;
288 Widget parent = XtParent (widget);
289 struct widget_xft_data *data = NULL;
290 int nr;
291 while (parent && !inst)
293 inst = lw_get_widget_instance (parent);
294 parent = XtParent (parent);
296 if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return;
298 for (nr = 0; data == NULL && nr < inst->nr_xft_data; ++nr)
300 if (inst->xft_data[nr].widget == widget)
301 data = &inst->xft_data[nr];
304 return data;
307 static void
308 command_press (Widget widget,
309 XEvent* event,
310 String *params,
311 Cardinal *num_params)
313 struct widget_xft_data *data = find_xft_data (widget);
314 if (data)
316 char *lbl;
317 /* Since this isn't used for rectangle buttons, use it to for armed. */
318 XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
320 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
321 draw_text (data, lbl, 1);
325 static void
326 command_reset (Widget widget,
327 XEvent* event,
328 String *params,
329 Cardinal *num_params)
331 struct widget_xft_data *data = find_xft_data (widget);
332 if (data)
334 Dimension cr;
335 XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
336 if (cr == 1)
338 char *lbl;
339 XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
340 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
341 draw_text (data, lbl, 0);
347 #endif
349 void
350 #ifdef PROTOTYPES
351 xaw_update_one_widget (widget_instance *instance, Widget widget,
352 widget_value *val, Boolean deep_p)
353 #else
354 xaw_update_one_widget (instance, widget, val, deep_p)
355 widget_instance *instance;
356 Widget widget;
357 widget_value *val;
358 Boolean deep_p;
359 #endif
361 #if 0
362 if (XtIsSubclass (widget, scrollbarWidgetClass))
364 xaw_update_scrollbar (instance, widget, val);
366 #endif
367 if (XtIsSubclass (widget, dialogWidgetClass))
370 #ifdef HAVE_XFT
371 if (instance->xft_data && instance->xft_data[0].xft_font)
373 set_text (&instance->xft_data[0], instance->parent,
374 val->contents->value, 10);
376 #endif
377 XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
379 else if (XtIsSubclass (widget, commandWidgetClass))
381 Dimension bw = 0;
382 Arg al[10];
383 int ac = 0;
385 XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
386 if (bw == 0)
387 /* Don't let buttons end up with 0 borderwidth, that's ugly...
388 Yeah, all this should really be done through app-defaults files
389 or fallback resources, but that's a whole different can of worms
390 that I don't feel like opening right now. Making Athena widgets
391 not look like shit is just entirely too much work.
394 XtSetArg (al[0], XtNborderWidth, 1);
395 XtSetValues (widget, al, 1);
398 XtSetSensitive (widget, val->enabled);
399 XtSetArg (al[ac], XtNlabel, val->value);ac++;
400 /* Force centered button text. Se above. */
401 XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
402 #ifdef HAVE_XFT
403 if (instance->xft_data && instance->xft_data[0].xft_font)
405 int th;
406 int nr;
407 for (nr = 0; nr < instance->nr_xft_data; ++nr)
408 if (instance->xft_data[nr].widget == widget)
409 break;
410 if (nr < instance->nr_xft_data)
412 set_text (&instance->xft_data[nr], instance->parent,
413 val->value, 6);
415 /* Must set internalHeight to twice the highlight thickness,
416 or else it gets overwritten by our pixmap. Probably a bug. */
417 XtVaGetValues (widget, XtNhighlightThickness, &th, NULL);
418 XtSetArg (al[ac], XtNinternalHeight, 2*th);ac++;
421 #endif
422 XtSetValues (widget, al, ac);
423 XtRemoveAllCallbacks (widget, XtNcallback);
424 XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
428 void
429 xaw_update_one_value (widget_instance *instance, Widget widget, widget_value *val)
431 /* This function is not used by the scrollbars and those are the only
432 Athena widget implemented at the moment so do nothing. */
433 return;
436 void
437 xaw_destroy_instance (widget_instance *instance)
439 #ifdef HAVE_XFT
440 if (instance->xft_data)
442 int i;
443 for (i = 0; i < instance->nr_xft_data; ++i)
445 if (instance->xft_data[i].xft_draw)
446 XftDrawDestroy (instance->xft_data[i].xft_draw);
447 if (instance->xft_data[i].p != None)
449 XtVaSetValues (instance->xft_data[i].widget, XtNbitmap, None,
450 NULL);
451 XFreePixmap (XtDisplay (instance->widget),
452 instance->xft_data[i].p);
455 if (instance->xft_data[0].xft_font)
456 XftFontClose (XtDisplay (instance->widget),
457 instance->xft_data[0].xft_font);
458 free (instance->xft_data);
460 #endif
461 if (XtIsSubclass (instance->widget, dialogWidgetClass))
462 /* Need to destroy the Shell too. */
463 XtDestroyWidget (XtParent (instance->widget));
464 else
465 XtDestroyWidget (instance->widget);
468 void
469 xaw_popup_menu (Widget widget, XEvent *event)
471 /* An Athena menubar has not been implemented. */
472 return;
475 void
476 #ifdef PROTOTYPES
477 xaw_pop_instance (widget_instance *instance, Boolean up)
478 #else
479 xaw_pop_instance (instance, up)
480 widget_instance *instance;
481 Boolean up;
482 #endif
484 Widget widget = instance->widget;
486 if (up)
488 if (XtIsSubclass (widget, dialogWidgetClass))
490 /* For dialogs, we need to call XtPopup on the parent instead
491 of calling XtManageChild on the widget.
492 Also we need to hack the shell's WM_PROTOCOLS to get it to
493 understand what the close box is supposed to do!!
495 Display *dpy = XtDisplay (widget);
496 Widget shell = XtParent (widget);
497 Atom props [2];
498 int i = 0;
499 props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
500 XChangeProperty (dpy, XtWindow (shell),
501 XInternAtom (dpy, "WM_PROTOCOLS", False),
502 XA_ATOM, 32, PropModeAppend,
503 (unsigned char *) props, i);
505 /* Center the widget in its parent. Why isn't this kind of crap
506 done automatically? I thought toolkits were supposed to make
507 life easier?
510 unsigned int x, y, w, h;
511 Widget topmost = instance->parent;
512 Arg args[2];
514 w = shell->core.width;
515 h = shell->core.height;
516 while (topmost->core.parent && XtIsRealized (topmost->core.parent))
517 topmost = topmost->core.parent;
518 if (topmost->core.width < w) x = topmost->core.x;
519 else x = topmost->core.x + ((topmost->core.width - w) / 2);
520 if (topmost->core.height < h) y = topmost->core.y;
521 else y = topmost->core.y + ((topmost->core.height - h) / 2);
522 /* Using XtMoveWidget caused the widget to come
523 out in the wrong place with vtwm.
524 Question of virtual vs real coords, perhaps. */
525 XtSetArg (args[0], XtNx, x);
526 XtSetArg (args[1], XtNy, y);
527 XtSetValues (shell, args, 2);
530 /* Finally, pop it up. */
531 XtPopup (shell, XtGrabNonexclusive);
533 else
534 XtManageChild (widget);
536 else
538 if (XtIsSubclass (widget, dialogWidgetClass))
539 XtUnmanageChild (XtParent (widget));
540 else
541 XtUnmanageChild (widget);
546 /* Dialog boxes */
548 static char overrideTrans[] =
549 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
550 /* Dialogs pop down on any key press */
551 static char dialogOverride[] =
552 "<KeyPress>Escape: lwlib_delete_dialog()";
553 static void wm_delete_window(Widget w, XtPointer closure, XtPointer call_data);
554 static XtActionsRec xaw_actions [] = {
555 {"lwlib_delete_dialog", wm_delete_window}
557 static Boolean actions_initted = False;
559 #ifdef HAVE_XFT
560 static XtActionsRec button_actions[] =
562 { "my_reset", command_reset },
563 { "my_press", command_press },
565 char buttonTrans[] =
566 "<Leave>: reset() my_reset()\n"
567 "<Btn1Down>: set() my_press()\n"
568 "<Btn1Up>: my_reset() notify() unset()\n";
569 #endif
571 static Widget
572 make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
573 radio_box, list, left_buttons, right_buttons, instance)
574 char* name;
575 Widget parent;
576 Boolean pop_up_p;
577 char* shell_title;
578 char* icon_name;
579 Boolean text_input_slot;
580 Boolean radio_box;
581 Boolean list;
582 int left_buttons;
583 int right_buttons;
584 widget_instance *instance;
586 Arg av [20];
587 int ac = 0;
588 int i, bc;
589 char button_name [255];
590 Widget shell;
591 Widget dialog;
592 Widget button;
593 XtTranslations override;
594 #ifdef HAVE_XFT
595 XftFont *xft_font = 0;
596 XtTranslations button_override;
597 #endif
599 if (! pop_up_p) abort (); /* not implemented */
600 if (text_input_slot) abort (); /* not implemented */
601 if (radio_box) abort (); /* not implemented */
602 if (list) abort (); /* not implemented */
604 if (! actions_initted)
606 XtAppContext app = XtWidgetToApplicationContext (parent);
607 XtAppAddActions (app, xaw_actions,
608 sizeof (xaw_actions) / sizeof (xaw_actions[0]));
609 #ifdef HAVE_XFT
610 XtAppAddActions (app, button_actions,
611 sizeof (button_actions) / sizeof (button_actions[0]));
612 #endif
613 actions_initted = True;
616 override = XtParseTranslationTable (overrideTrans);
618 ac = 0;
619 XtSetArg (av[ac], XtNtitle, shell_title); ac++;
620 XtSetArg (av[ac], XtNallowShellResize, True); ac++;
622 /* Don't allow any geometry request from the user. */
623 XtSetArg (av[ac], XtNgeometry, 0); ac++;
625 shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
626 parent, av, ac);
627 XtOverrideTranslations (shell, override);
629 ac = 0;
630 dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
631 override = XtParseTranslationTable (dialogOverride);
632 XtOverrideTranslations (dialog, override);
634 #ifdef HAVE_XFT
636 int num;
637 Widget *ch = NULL;
638 Widget w = 0;
639 XtVaGetValues (dialog,
640 XtNnumChildren, &num,
641 XtNchildren, &ch, NULL);
642 for (i = 0; i < num; ++i)
644 if (!XtIsSubclass (ch[i], commandWidgetClass)
645 && XtIsSubclass (ch[i], labelWidgetClass))
647 w = ch[i];
648 break;
651 instance->xft_data = 0;
652 instance->nr_xft_data = 0;
653 if (w)
655 XtResource rec[] =
656 { { "faceName", "FaceName", XtRString, sizeof(String), 0, XtRString,
657 (XtPointer)"Sans-14" }};
658 char *faceName;
659 XtVaGetSubresources (dialog, &faceName, "Dialog", "dialog",
660 rec, 1, (String)NULL);
661 if (strcmp ("none", faceName) != 0)
662 xft_font = openFont (dialog, faceName);
663 if (xft_font)
665 instance->nr_xft_data = left_buttons + right_buttons + 1;
666 instance->xft_data = calloc (instance->nr_xft_data,
667 sizeof(*instance->xft_data));
669 fill_xft_data (&instance->xft_data[0], w, xft_font);
673 button_override = XtParseTranslationTable (buttonTrans);
675 #endif
677 bc = 0;
678 button = 0;
679 for (i = 0; i < left_buttons; i++)
681 ac = 0;
682 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
683 XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
684 XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
685 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
686 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
687 XtSetArg (av [ac], XtNresizable, True); ac++;
688 #ifdef HAVE_XAW3D
689 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
691 /* Turn of dithered shadow if we can. Looks bad */
692 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
694 #endif
695 sprintf (button_name, "button%d", ++bc);
696 button = XtCreateManagedWidget (button_name, commandWidgetClass,
697 dialog, av, ac);
698 #ifdef HAVE_XFT
699 if (xft_font)
701 fill_xft_data (&instance->xft_data[bc], button, xft_font);
702 XtOverrideTranslations (button, button_override);
704 #endif
707 for (i = 0; i < right_buttons; i++)
709 ac = 0;
710 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
711 if (i == 0)
713 /* Separator to the other buttons. */
714 XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
716 XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
717 XtSetArg (av [ac], XtNright, XtChainRight); ac++;
718 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
719 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
720 XtSetArg (av [ac], XtNresizable, True); ac++;
721 #ifdef HAVE_XAW3D
722 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
724 /* Turn of dithered shadow if we can. Looks bad */
725 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
727 #endif
728 sprintf (button_name, "button%d", ++bc);
729 button = XtCreateManagedWidget (button_name, commandWidgetClass,
730 dialog, av, ac);
731 #ifdef HAVE_XFT
732 if (xft_font)
734 fill_xft_data (&instance->xft_data[bc], button, xft_font);
735 XtOverrideTranslations (button, button_override);
737 #endif
740 return dialog;
743 Widget
744 xaw_create_dialog (widget_instance *instance)
746 char *name = instance->info->type;
747 Widget parent = instance->parent;
748 Widget widget;
749 Boolean pop_up_p = instance->pop_up_p;
750 char *shell_name = 0;
751 char *icon_name = 0;
752 Boolean text_input_slot = False;
753 Boolean radio_box = False;
754 Boolean list = False;
755 int total_buttons;
756 int left_buttons = 0;
757 int right_buttons = 1;
759 switch (name [0]) {
760 case 'E': case 'e':
761 icon_name = "dbox-error";
762 shell_name = "Error";
763 break;
765 case 'I': case 'i':
766 icon_name = "dbox-info";
767 shell_name = "Information";
768 break;
770 case 'L': case 'l':
771 list = True;
772 icon_name = "dbox-question";
773 shell_name = "Prompt";
774 break;
776 case 'P': case 'p':
777 text_input_slot = True;
778 icon_name = "dbox-question";
779 shell_name = "Prompt";
780 break;
782 case 'Q': case 'q':
783 icon_name = "dbox-question";
784 shell_name = "Question";
785 break;
788 total_buttons = name [1] - '0';
790 if (name [3] == 'T' || name [3] == 't')
792 text_input_slot = False;
793 radio_box = True;
795 else if (name [3])
796 right_buttons = name [4] - '0';
798 left_buttons = total_buttons - right_buttons;
800 widget = make_dialog (name, parent, pop_up_p,
801 shell_name, icon_name, text_input_slot, radio_box,
802 list, left_buttons, right_buttons, instance);
803 return widget;
807 static void
808 xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
810 widget_instance *instance = (widget_instance *) closure;
811 Widget instance_widget;
812 LWLIB_ID id;
813 XtPointer user_data;
815 lw_internal_update_other_instances (widget, closure, call_data);
817 if (! instance)
818 return;
819 if (widget->core.being_destroyed)
820 return;
822 instance_widget = instance->widget;
823 if (!instance_widget)
824 return;
826 id = instance->info->id;
828 #if 0
829 user_data = NULL;
830 XtVaGetValues (widget, XtNuserData, &user_data, NULL);
831 #else
832 /* Damn! Athena doesn't give us a way to hang our own data on the
833 buttons, so we have to go find it... I guess this assumes that
834 all instances of a button have the same call data. */
836 widget_value *val = instance->info->val->contents;
837 char *name = XtName (widget);
838 while (val)
840 if (val->name && !strcmp (val->name, name))
841 break;
842 val = val->next;
844 if (! val) abort ();
845 user_data = val->call_data;
847 #endif
849 if (instance->info->selection_cb)
850 instance->info->selection_cb (widget, id, user_data);
853 static void
854 wm_delete_window (Widget w, XtPointer closure, XtPointer call_data)
856 LWLIB_ID id;
857 Cardinal nkids;
858 int i;
859 Widget *kids = 0;
860 Widget widget, shell;
862 if (XtIsSubclass (w, dialogWidgetClass))
863 shell = XtParent (w);
864 else
865 shell = w;
867 if (! XtIsSubclass (shell, shellWidgetClass))
868 abort ();
869 XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
870 XtVaGetValues (shell, XtNchildren, &kids, NULL);
871 if (!kids || !*kids)
872 abort ();
873 for (i = 0; i < nkids; i++)
875 widget = kids[i];
876 if (XtIsSubclass (widget, dialogWidgetClass))
877 break;
879 id = lw_get_widget_id (widget);
880 if (! id) abort ();
883 widget_info *info = lw_get_widget_info (id);
884 if (! info) abort ();
885 if (info->selection_cb)
886 info->selection_cb (widget, id, (XtPointer) -1);
889 lw_destroy_all_widgets (id);
893 /* Scrollbars */
895 #if 0
896 static void
897 xaw_scrollbar_scroll (widget, closure, call_data)
898 Widget widget;
899 XtPointer closure;
900 XtPointer call_data;
902 widget_instance *instance = (widget_instance *) closure;
903 LWLIB_ID id;
904 scroll_event event_data;
906 if (!instance || widget->core.being_destroyed)
907 return;
909 id = instance->info->id;
910 event_data.slider_value = 0;
911 event_data.time = 0;
913 if ((int) call_data > 0)
914 event_data.action = SCROLLBAR_PAGE_DOWN;
915 else
916 event_data.action = SCROLLBAR_PAGE_UP;
918 if (instance->info->pre_activate_cb)
919 instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
921 #endif
923 #if 0
924 static void
925 xaw_scrollbar_jump (widget, closure, call_data)
926 Widget widget;
927 XtPointer closure;
928 XtPointer call_data;
930 widget_instance *instance = (widget_instance *) closure;
931 LWLIB_ID id;
932 scroll_event event_data;
933 scrollbar_values *val =
934 (scrollbar_values *) instance->info->val->scrollbar_data;
935 float percent;
937 if (!instance || widget->core.being_destroyed)
938 return;
940 id = instance->info->id;
942 percent = * (float *) call_data;
943 event_data.slider_value =
944 (int) (percent * (float) (val->maximum - val->minimum)) + val->minimum;
946 event_data.time = 0;
947 event_data.action = SCROLLBAR_DRAG;
949 if (instance->info->pre_activate_cb)
950 instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
952 #endif
954 static Widget
955 xaw_create_scrollbar (widget_instance *instance)
957 #if 0
958 Arg av[20];
959 int ac = 0;
960 Dimension width;
961 Widget scrollbar;
963 XtVaGetValues (instance->parent, XtNwidth, &width, NULL);
965 XtSetArg (av[ac], XtNshowGrip, 0); ac++;
966 XtSetArg (av[ac], XtNresizeToPreferred, 1); ac++;
967 XtSetArg (av[ac], XtNallowResize, True); ac++;
968 XtSetArg (av[ac], XtNskipAdjust, True); ac++;
969 XtSetArg (av[ac], XtNwidth, width); ac++;
970 XtSetArg (av[ac], XtNmappedWhenManaged, True); ac++;
972 scrollbar =
973 XtCreateWidget (instance->info->name, scrollbarWidgetClass,
974 instance->parent, av, ac);
976 /* We have to force the border width to be 0 otherwise the
977 geometry manager likes to start looping for awhile... */
978 XtVaSetValues (scrollbar, XtNborderWidth, 0, NULL);
980 XtRemoveAllCallbacks (scrollbar, "jumpProc");
981 XtRemoveAllCallbacks (scrollbar, "scrollProc");
983 XtAddCallback (scrollbar, "jumpProc", xaw_scrollbar_jump,
984 (XtPointer) instance);
985 XtAddCallback (scrollbar, "scrollProc", xaw_scrollbar_scroll,
986 (XtPointer) instance);
988 return scrollbar;
989 #else
990 return NULL;
991 #endif
994 static Widget
995 xaw_create_main (widget_instance *instance)
997 Arg al[1];
998 int ac;
1000 /* Create a vertical Paned to hold menubar */
1001 ac = 0;
1002 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
1003 return XtCreateWidget (instance->info->name, panedWidgetClass,
1004 instance->parent, al, ac);
1007 widget_creation_entry
1008 xaw_creation_table [] =
1010 {"scrollbar", xaw_create_scrollbar},
1011 {"main", xaw_create_main},
1012 {NULL, NULL}
1015 /* arch-tag: fbbd3589-ae1c-41a0-9142-f628cfee6564
1016 (do not change this comment) */