Merge from emacs-24; up to 2012-04-30T11:57:47Z!sdl.web@gmail.com
[bpt/emacs.git] / lwlib / lwlib-Xaw.c
CommitLineData
b70cfce2 1/* The lwlib interface to Athena widgets.
67f02b82 2
4424d48a 3Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
acaf905b 4Copyright (C) 1994, 2001-2012 Free Software Foundation, Inc.
b70cfce2
FP
5
6This file is part of the Lucid Widget Library.
7
177c0ea7 8The Lucid Widget Library is free software; you can redistribute it and/or
b70cfce2
FP
9modify it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 1, or (at your option)
11any later version.
12
13The Lucid Widget Library is distributed in the hope that it will be useful,
177c0ea7 14but WITHOUT ANY WARRANTY; without even the implied warranty of
b70cfce2
FP
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs; see the file COPYING. If not, write to
364c38d3
LK
20the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21Boston, MA 02110-1301, USA. */
b70cfce2 22
0f0912e6 23#include <config.h>
0f0912e6 24
b70cfce2 25#include <stdio.h>
d7306fe6 26#include <setjmp.h>
e4c8d29a 27#include <ctype.h>
b70cfce2 28
67f02b82 29#include <lisp.h>
2f96293d 30
b70cfce2
FP
31#include "lwlib-Xaw.h"
32
33#include <X11/StringDefs.h>
34#include <X11/IntrinsicP.h>
35#include <X11/CoreP.h>
36#include <X11/Shell.h>
37
5262c5c7
CY
38#ifdef HAVE_XAW3D
39#include <X11/Xaw3d/Scrollbar.h>
40#include <X11/Xaw3d/Paned.h>
41#include <X11/Xaw3d/Dialog.h>
42#include <X11/Xaw3d/Form.h>
43#include <X11/Xaw3d/Command.h>
44#include <X11/Xaw3d/Label.h>
45#else /* !HAVE_XAW3D */
b70cfce2
FP
46#include <X11/Xaw/Scrollbar.h>
47#include <X11/Xaw/Paned.h>
48#include <X11/Xaw/Dialog.h>
49#include <X11/Xaw/Form.h>
50#include <X11/Xaw/Command.h>
51#include <X11/Xaw/Label.h>
5262c5c7 52#endif /* HAVE_XAW3D */
b70cfce2
FP
53
54#include <X11/Xatom.h>
55
1ecb2d3f
JD
56#ifdef HAVE_XFT
57#include <X11/Xft/Xft.h>
58
59struct widget_xft_data
60{
61 Widget widget;
62 XftFont *xft_font;
63 XftDraw *xft_draw;
64 XftColor xft_fg, xft_bg;
65 int p_width, p_height;
66 Pixmap p;
67};
68
69
70#endif
71
c825c0b6
J
72static void xaw_generic_callback (Widget widget,
73 XtPointer closure,
74 XtPointer call_data);
b70cfce2
FP
75
76
77Boolean
c3174d16 78lw_xaw_widget_p (Widget widget)
b70cfce2
FP
79{
80 return (XtIsSubclass (widget, scrollbarWidgetClass) ||
81 XtIsSubclass (widget, dialogWidgetClass));
82}
83
b70cfce2 84
1ecb2d3f
JD
85#ifdef HAVE_XFT
86static void
87fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
88{
1ecb2d3f
JD
89 Pixel bg, fg;
90 XColor colors[2];
1ecb2d3f 91
c632dfda
JD
92 data->widget = widget;
93 data->xft_font = font;
1ecb2d3f
JD
94 XtVaGetValues (widget,
95 XtNbackground, &bg,
96 XtNforeground, &fg,
97 NULL);
98
99 colors[0].pixel = data->xft_fg.pixel = fg;
100 colors[1].pixel = data->xft_bg.pixel = bg;
101 XQueryColors (XtDisplay (widget),
102 DefaultColormapOfScreen (XtScreen (widget)),
103 colors, 2);
104
105 data->xft_fg.color.alpha = 0xFFFF;
106 data->xft_fg.color.red = colors[0].red;
107 data->xft_fg.color.green = colors[0].green;
108 data->xft_fg.color.blue = colors[0].blue;
109 data->xft_bg.color.alpha = 0xFFFF;
110 data->xft_bg.color.red = colors[1].red;
111 data->xft_bg.color.green = colors[1].green;
112 data->xft_bg.color.blue = colors[1].blue;
113
114 data->p = None;
115 data->xft_draw = 0;
116 data->p_width = data->p_height = 0;
117}
118
119static XftFont*
120openFont (Widget widget, char *name)
121{
122 char *fname = name;
123 int screen = XScreenNumberOfScreen (XtScreen (widget));
124 int len = strlen (fname), i = len-1;
125 XftFont *fn;
126
127 /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
128 while (i > 0 && isdigit (fname[i]))
129 --i;
130 if (fname[i] == ' ')
131 {
132 fname = xstrdup (name);
133 fname[i] = '-';
134 }
135
136 fn = XftFontOpenName (XtDisplay (widget), screen, fname);
81d40c92 137 if (fname != name) xfree (fname);
1ecb2d3f
JD
138
139 return fn;
140}
141
142static int
143get_text_width_and_height (Widget widget, char *text,
144 XftFont *xft_font,
145 int *height)
146{
147 int w = 0, h = 0;
148 char *bp = text;
cf38a720 149
1ecb2d3f
JD
150 while (bp && *bp != '\0')
151 {
152 XGlyphInfo gi;
153 char *cp = strchr (bp, '\n');
154 XftTextExtentsUtf8 (XtDisplay (widget), xft_font,
155 (FcChar8 *) bp,
156 cp ? cp - bp : strlen (bp),
157 &gi);
158 bp = cp ? cp + 1 : NULL;
159 h += xft_font->height;
160 if (w < gi.width) w = gi.width;
161 }
162
163 *height = h;
164 return w;
165}
166
167static void
168draw_text (struct widget_xft_data *data, char *lbl, int inverse)
169{
170 Screen *sc = XtScreen (data->widget);
171 int screen = XScreenNumberOfScreen (sc);
172 int y = data->xft_font->ascent;
173 int x = inverse ? 0 : 2;
174 char *bp = lbl;
175
176 data->xft_draw = XftDrawCreate (XtDisplay (data->widget),
177 data->p,
178 DefaultVisual (XtDisplay (data->widget),
179 screen),
180 DefaultColormapOfScreen (sc));
181 XftDrawRect (data->xft_draw,
182 inverse ? &data->xft_fg : &data->xft_bg,
183 0, 0, data->p_width, data->p_height);
184
185 if (!inverse) y += 2;
186 while (bp && *bp != '\0')
187 {
188 char *cp = strchr (bp, '\n');
189 XftDrawStringUtf8 (data->xft_draw,
190 inverse ? &data->xft_bg : &data->xft_fg,
e4c8d29a
J
191 data->xft_font, x, y,
192 (FcChar8 *) bp,
193 cp ? cp - bp : strlen (bp));
1ecb2d3f
JD
194 bp = cp ? cp + 1 : NULL;
195 /* 1.2 gives reasonable line spacing. */
196 y += data->xft_font->height * 1.2;
197 }
198
199}
200
201
202static void
203set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
204{
1ecb2d3f
JD
205 int width, height;
206
207 width = get_text_width_and_height (data->widget, lbl, data->xft_font,
208 &height);
209 data->p_width = width + margin;
210 data->p_height = height + margin;
211
212 data->p = XCreatePixmap (XtDisplay (data->widget),
213 XtWindow (toplevel),
214 data->p_width,
215 data->p_height,
216 DefaultDepthOfScreen (XtScreen (data->widget)));
217 draw_text (data, lbl, 0);
218 XtVaSetValues (data->widget, XtNbitmap, data->p, NULL);
219}
220
221static struct widget_xft_data *
222find_xft_data (Widget widget)
223{
224 widget_instance *inst = NULL;
225 Widget parent = XtParent (widget);
226 struct widget_xft_data *data = NULL;
227 int nr;
cf38a720 228 while (parent && !inst)
1ecb2d3f
JD
229 {
230 inst = lw_get_widget_instance (parent);
231 parent = XtParent (parent);
232 }
e4c8d29a 233 if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return 0;
1ecb2d3f 234
cf38a720 235 for (nr = 0; data == NULL && nr < inst->nr_xft_data; ++nr)
1ecb2d3f 236 {
cf38a720 237 if (inst->xft_data[nr].widget == widget)
1ecb2d3f
JD
238 data = &inst->xft_data[nr];
239 }
240
241 return data;
242}
243
244static void
245command_press (Widget widget,
246 XEvent* event,
247 String *params,
248 Cardinal *num_params)
249{
250 struct widget_xft_data *data = find_xft_data (widget);
cf38a720 251 if (data)
1ecb2d3f
JD
252 {
253 char *lbl;
254 /* Since this isn't used for rectangle buttons, use it to for armed. */
255 XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
256
257 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
258 draw_text (data, lbl, 1);
259 }
260}
261
262static void
263command_reset (Widget widget,
c825c0b6
J
264 XEvent* event,
265 String *params,
266 Cardinal *num_params)
1ecb2d3f
JD
267{
268 struct widget_xft_data *data = find_xft_data (widget);
cf38a720 269 if (data)
1ecb2d3f
JD
270 {
271 Dimension cr;
272 XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
cf38a720 273 if (cr == 1)
1ecb2d3f
JD
274 {
275 char *lbl;
276 XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
277 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
278 draw_text (data, lbl, 0);
279 }
280 }
281}
282
283
284#endif
285
b70cfce2 286void
c825c0b6
J
287xaw_update_one_widget (widget_instance *instance,
288 Widget widget,
289 widget_value *val,
290 Boolean deep_p)
b70cfce2 291{
13162c0e 292 if (XtIsSubclass (widget, dialogWidgetClass))
b70cfce2 293 {
1ecb2d3f
JD
294
295#ifdef HAVE_XFT
296 if (instance->xft_data && instance->xft_data[0].xft_font)
297 {
298 set_text (&instance->xft_data[0], instance->parent,
299 val->contents->value, 10);
300 }
301#endif
302 XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
b70cfce2
FP
303 }
304 else if (XtIsSubclass (widget, commandWidgetClass))
305 {
306 Dimension bw = 0;
1ecb2d3f
JD
307 Arg al[10];
308 int ac = 0;
13162c0e 309
8dd095ee 310 XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
b70cfce2
FP
311 if (bw == 0)
312 /* Don't let buttons end up with 0 borderwidth, that's ugly...
313 Yeah, all this should really be done through app-defaults files
314 or fallback resources, but that's a whole different can of worms
315 that I don't feel like opening right now. Making Athena widgets
316 not look like shit is just entirely too much work.
317 */
13162c0e
RS
318 {
319 XtSetArg (al[0], XtNborderWidth, 1);
320 XtSetValues (widget, al, 1);
321 }
b70cfce2 322
2a73ab60 323 XtSetSensitive (widget, val->enabled);
1ecb2d3f 324 XtSetArg (al[ac], XtNlabel, val->value);ac++;
13162c0e 325 /* Force centered button text. Se above. */
1ecb2d3f
JD
326 XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
327#ifdef HAVE_XFT
328 if (instance->xft_data && instance->xft_data[0].xft_font)
329 {
330 int th;
331 int nr;
332 for (nr = 0; nr < instance->nr_xft_data; ++nr)
333 if (instance->xft_data[nr].widget == widget)
334 break;
335 if (nr < instance->nr_xft_data)
336 {
337 set_text (&instance->xft_data[nr], instance->parent,
338 val->value, 6);
339
340 /* Must set internalHeight to twice the highlight thickness,
341 or else it gets overwritten by our pixmap. Probably a bug. */
342 XtVaGetValues (widget, XtNhighlightThickness, &th, NULL);
343 XtSetArg (al[ac], XtNinternalHeight, 2*th);ac++;
344 }
345 }
346#endif
347 XtSetValues (widget, al, ac);
b70cfce2
FP
348 XtRemoveAllCallbacks (widget, XtNcallback);
349 XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
350 }
351}
352
353void
c825c0b6
J
354xaw_update_one_value (widget_instance *instance,
355 Widget widget,
356 widget_value *val)
b70cfce2
FP
357{
358 /* This function is not used by the scrollbars and those are the only
359 Athena widget implemented at the moment so do nothing. */
360 return;
361}
362
363void
c3174d16 364xaw_destroy_instance (widget_instance *instance)
b70cfce2 365{
1ecb2d3f 366#ifdef HAVE_XFT
cf38a720 367 if (instance->xft_data)
1ecb2d3f
JD
368 {
369 int i;
cf38a720 370 for (i = 0; i < instance->nr_xft_data; ++i)
1ecb2d3f
JD
371 {
372 if (instance->xft_data[i].xft_draw)
373 XftDrawDestroy (instance->xft_data[i].xft_draw);
cf38a720 374 if (instance->xft_data[i].p != None)
1ecb2d3f
JD
375 {
376 XtVaSetValues (instance->xft_data[i].widget, XtNbitmap, None,
377 NULL);
378 XFreePixmap (XtDisplay (instance->widget),
379 instance->xft_data[i].p);
380 }
381 }
382 if (instance->xft_data[0].xft_font)
383 XftFontClose (XtDisplay (instance->widget),
384 instance->xft_data[0].xft_font);
81d40c92 385 xfree (instance->xft_data);
1ecb2d3f
JD
386 }
387#endif
b70cfce2
FP
388 if (XtIsSubclass (instance->widget, dialogWidgetClass))
389 /* Need to destroy the Shell too. */
390 XtDestroyWidget (XtParent (instance->widget));
391 else
392 XtDestroyWidget (instance->widget);
393}
394
395void
c3174d16 396xaw_popup_menu (Widget widget, XEvent *event)
b70cfce2
FP
397{
398 /* An Athena menubar has not been implemented. */
399 return;
400}
401
402void
207c13a7 403xaw_pop_instance (widget_instance *instance, Boolean up)
b70cfce2
FP
404{
405 Widget widget = instance->widget;
406
407 if (up)
408 {
409 if (XtIsSubclass (widget, dialogWidgetClass))
410 {
411 /* For dialogs, we need to call XtPopup on the parent instead
412 of calling XtManageChild on the widget.
413 Also we need to hack the shell's WM_PROTOCOLS to get it to
414 understand what the close box is supposed to do!!
415 */
416 Display *dpy = XtDisplay (widget);
417 Widget shell = XtParent (widget);
418 Atom props [2];
419 int i = 0;
420 props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
421 XChangeProperty (dpy, XtWindow (shell),
422 XInternAtom (dpy, "WM_PROTOCOLS", False),
423 XA_ATOM, 32, PropModeAppend,
424 (unsigned char *) props, i);
425
426 /* Center the widget in its parent. Why isn't this kind of crap
427 done automatically? I thought toolkits were supposed to make
428 life easier?
429 */
430 {
e363091e 431 unsigned int x, y, w, h;
b70cfce2 432 Widget topmost = instance->parent;
2af91681
PR
433 Arg args[2];
434
b70cfce2
FP
435 w = shell->core.width;
436 h = shell->core.height;
437 while (topmost->core.parent && XtIsRealized (topmost->core.parent))
438 topmost = topmost->core.parent;
439 if (topmost->core.width < w) x = topmost->core.x;
440 else x = topmost->core.x + ((topmost->core.width - w) / 2);
441 if (topmost->core.height < h) y = topmost->core.y;
442 else y = topmost->core.y + ((topmost->core.height - h) / 2);
2af91681
PR
443 /* Using XtMoveWidget caused the widget to come
444 out in the wrong place with vtwm.
445 Question of virtual vs real coords, perhaps. */
446 XtSetArg (args[0], XtNx, x);
447 XtSetArg (args[1], XtNy, y);
448 XtSetValues (shell, args, 2);
b70cfce2
FP
449 }
450
451 /* Finally, pop it up. */
452 XtPopup (shell, XtGrabNonexclusive);
453 }
454 else
455 XtManageChild (widget);
456 }
457 else
458 {
459 if (XtIsSubclass (widget, dialogWidgetClass))
460 XtUnmanageChild (XtParent (widget));
461 else
462 XtUnmanageChild (widget);
463 }
464}
465
466\f
467/* Dialog boxes */
468
469static char overrideTrans[] =
470 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
244c93fe
JD
471/* Dialogs pop down on any key press */
472static char dialogOverride[] =
4e6e2184 473 "<KeyPress>Escape: lwlib_delete_dialog()";
e4c8d29a
J
474static void wm_delete_window (Widget w,
475 XEvent *event,
476 String *params,
477 Cardinal *num_params);
b70cfce2
FP
478static XtActionsRec xaw_actions [] = {
479 {"lwlib_delete_dialog", wm_delete_window}
480};
481static Boolean actions_initted = False;
482
1ecb2d3f 483#ifdef HAVE_XFT
cf38a720 484static XtActionsRec button_actions[] =
1ecb2d3f
JD
485 {
486 { "my_reset", command_reset },
487 { "my_press", command_press },
488 };
489char buttonTrans[] =
490 "<Leave>: reset() my_reset()\n"
491 "<Btn1Down>: set() my_press()\n"
492 "<Btn1Up>: my_reset() notify() unset()\n";
493#endif
494
b70cfce2 495static Widget
c825c0b6
J
496make_dialog (char* name,
497 Widget parent,
498 Boolean pop_up_p,
499 char* shell_title,
500 char* icon_name,
501 Boolean text_input_slot,
502 Boolean radio_box,
503 Boolean list,
504 int left_buttons,
505 int right_buttons,
506 widget_instance *instance)
b70cfce2
FP
507{
508 Arg av [20];
509 int ac = 0;
510 int i, bc;
511 char button_name [255];
512 Widget shell;
513 Widget dialog;
514 Widget button;
515 XtTranslations override;
1ecb2d3f
JD
516#ifdef HAVE_XFT
517 XftFont *xft_font = 0;
518 XtTranslations button_override;
519#endif
b70cfce2
FP
520
521 if (! pop_up_p) abort (); /* not implemented */
522 if (text_input_slot) abort (); /* not implemented */
523 if (radio_box) abort (); /* not implemented */
524 if (list) abort (); /* not implemented */
525
526 if (! actions_initted)
527 {
528 XtAppContext app = XtWidgetToApplicationContext (parent);
529 XtAppAddActions (app, xaw_actions,
530 sizeof (xaw_actions) / sizeof (xaw_actions[0]));
1ecb2d3f
JD
531#ifdef HAVE_XFT
532 XtAppAddActions (app, button_actions,
533 sizeof (button_actions) / sizeof (button_actions[0]));
534#endif
b70cfce2
FP
535 actions_initted = True;
536 }
537
538 override = XtParseTranslationTable (overrideTrans);
539
540 ac = 0;
541 XtSetArg (av[ac], XtNtitle, shell_title); ac++;
542 XtSetArg (av[ac], XtNallowShellResize, True); ac++;
dc49df96
FP
543
544 /* Don't allow any geometry request from the user. */
545 XtSetArg (av[ac], XtNgeometry, 0); ac++;
546
b70cfce2
FP
547 shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
548 parent, av, ac);
549 XtOverrideTranslations (shell, override);
550
551 ac = 0;
552 dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
244c93fe
JD
553 override = XtParseTranslationTable (dialogOverride);
554 XtOverrideTranslations (dialog, override);
b70cfce2 555
1ecb2d3f
JD
556#ifdef HAVE_XFT
557 {
558 int num;
559 Widget *ch = NULL;
560 Widget w = 0;
561 XtVaGetValues (dialog,
562 XtNnumChildren, &num,
563 XtNchildren, &ch, NULL);
cf38a720 564 for (i = 0; i < num; ++i)
1ecb2d3f
JD
565 {
566 if (!XtIsSubclass (ch[i], commandWidgetClass)
567 && XtIsSubclass (ch[i], labelWidgetClass))
568 {
569 w = ch[i];
570 break;
571 }
572 }
573 instance->xft_data = 0;
574 instance->nr_xft_data = 0;
cf38a720 575 if (w)
1ecb2d3f 576 {
cf38a720 577 XtResource rec[] =
3928f2b6
JD
578 { { "font", "Font", XtRString, sizeof(String), 0, XtRString,
579 (XtPointer)"Sans-10" }};
580 char *fontName = NULL;
581 XtVaGetSubresources (dialog, &fontName, "Dialog", "dialog",
41d81b80 582 rec, 1, (String)NULL);
3928f2b6
JD
583 if (fontName)
584 {
585 XFontStruct *xfn = XLoadQueryFont (XtDisplay (dialog), fontName);
586 if (!xfn)
587 xft_font = openFont (dialog, fontName);
588 else
589 XFreeFont (XtDisplay (dialog), xfn);
590 }
cf38a720
PE
591
592 if (xft_font)
1ecb2d3f
JD
593 {
594 instance->nr_xft_data = left_buttons + right_buttons + 1;
595 instance->xft_data = calloc (instance->nr_xft_data,
596 sizeof(*instance->xft_data));
597
598 fill_xft_data (&instance->xft_data[0], w, xft_font);
599 }
600 }
601
602 button_override = XtParseTranslationTable (buttonTrans);
603 }
604#endif
605
b70cfce2
FP
606 bc = 0;
607 button = 0;
608 for (i = 0; i < left_buttons; i++)
609 {
610 ac = 0;
611 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
612 XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
613 XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
614 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
615 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
616 XtSetArg (av [ac], XtNresizable, True); ac++;
1ecb2d3f
JD
617#ifdef HAVE_XAW3D
618 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
619 {
620 /* Turn of dithered shadow if we can. Looks bad */
621 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
622 }
623#endif
b70cfce2
FP
624 sprintf (button_name, "button%d", ++bc);
625 button = XtCreateManagedWidget (button_name, commandWidgetClass,
626 dialog, av, ac);
1ecb2d3f
JD
627#ifdef HAVE_XFT
628 if (xft_font)
629 {
630 fill_xft_data (&instance->xft_data[bc], button, xft_font);
631 XtOverrideTranslations (button, button_override);
632 }
633#endif
b70cfce2 634 }
b70cfce2 635
b70cfce2
FP
636 for (i = 0; i < right_buttons; i++)
637 {
638 ac = 0;
639 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
cf38a720 640 if (i == 0)
1ecb2d3f
JD
641 {
642 /* Separator to the other buttons. */
643 XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
644 }
b70cfce2
FP
645 XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
646 XtSetArg (av [ac], XtNright, XtChainRight); ac++;
647 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
648 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
649 XtSetArg (av [ac], XtNresizable, True); ac++;
1ecb2d3f
JD
650#ifdef HAVE_XAW3D
651 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
652 {
653 /* Turn of dithered shadow if we can. Looks bad */
654 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
655 }
656#endif
b70cfce2
FP
657 sprintf (button_name, "button%d", ++bc);
658 button = XtCreateManagedWidget (button_name, commandWidgetClass,
659 dialog, av, ac);
1ecb2d3f
JD
660#ifdef HAVE_XFT
661 if (xft_font)
662 {
663 fill_xft_data (&instance->xft_data[bc], button, xft_font);
664 XtOverrideTranslations (button, button_override);
665 }
666#endif
b70cfce2
FP
667 }
668
669 return dialog;
670}
671
672Widget
c3174d16 673xaw_create_dialog (widget_instance *instance)
b70cfce2
FP
674{
675 char *name = instance->info->type;
676 Widget parent = instance->parent;
677 Widget widget;
678 Boolean pop_up_p = instance->pop_up_p;
679 char *shell_name = 0;
ca79970e 680 char *icon_name = 0;
b70cfce2
FP
681 Boolean text_input_slot = False;
682 Boolean radio_box = False;
683 Boolean list = False;
684 int total_buttons;
685 int left_buttons = 0;
686 int right_buttons = 1;
687
688 switch (name [0]) {
689 case 'E': case 'e':
690 icon_name = "dbox-error";
691 shell_name = "Error";
692 break;
693
694 case 'I': case 'i':
695 icon_name = "dbox-info";
696 shell_name = "Information";
697 break;
698
699 case 'L': case 'l':
700 list = True;
701 icon_name = "dbox-question";
702 shell_name = "Prompt";
703 break;
704
705 case 'P': case 'p':
706 text_input_slot = True;
707 icon_name = "dbox-question";
708 shell_name = "Prompt";
709 break;
710
711 case 'Q': case 'q':
712 icon_name = "dbox-question";
713 shell_name = "Question";
714 break;
715 }
177c0ea7 716
b70cfce2
FP
717 total_buttons = name [1] - '0';
718
719 if (name [3] == 'T' || name [3] == 't')
720 {
721 text_input_slot = False;
722 radio_box = True;
723 }
724 else if (name [3])
725 right_buttons = name [4] - '0';
177c0ea7 726
b70cfce2 727 left_buttons = total_buttons - right_buttons;
177c0ea7 728
b70cfce2
FP
729 widget = make_dialog (name, parent, pop_up_p,
730 shell_name, icon_name, text_input_slot, radio_box,
1ecb2d3f 731 list, left_buttons, right_buttons, instance);
b70cfce2
FP
732 return widget;
733}
734
735
736static void
c3174d16 737xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
b70cfce2
FP
738{
739 widget_instance *instance = (widget_instance *) closure;
740 Widget instance_widget;
741 LWLIB_ID id;
742 XtPointer user_data;
743
744 lw_internal_update_other_instances (widget, closure, call_data);
745
746 if (! instance)
747 return;
748 if (widget->core.being_destroyed)
749 return;
750
751 instance_widget = instance->widget;
752 if (!instance_widget)
753 return;
754
755 id = instance->info->id;
756
b70cfce2
FP
757 /* Damn! Athena doesn't give us a way to hang our own data on the
758 buttons, so we have to go find it... I guess this assumes that
759 all instances of a button have the same call data. */
760 {
761 widget_value *val = instance->info->val->contents;
762 char *name = XtName (widget);
763 while (val)
764 {
765 if (val->name && !strcmp (val->name, name))
766 break;
767 val = val->next;
768 }
769 if (! val) abort ();
770 user_data = val->call_data;
771 }
b70cfce2
FP
772
773 if (instance->info->selection_cb)
774 instance->info->selection_cb (widget, id, user_data);
775}
776
777static void
e4c8d29a
J
778wm_delete_window (Widget w,
779 XEvent *event,
780 String *params,
781 Cardinal *num_params)
b70cfce2
FP
782{
783 LWLIB_ID id;
8dce2ddc
RS
784 Cardinal nkids;
785 int i;
b70cfce2 786 Widget *kids = 0;
e4c8d29a 787 Widget widget = 0, shell;
244c93fe
JD
788
789 if (XtIsSubclass (w, dialogWidgetClass))
790 shell = XtParent (w);
791 else
792 shell = w;
793
b70cfce2
FP
794 if (! XtIsSubclass (shell, shellWidgetClass))
795 abort ();
8dd095ee
GM
796 XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
797 XtVaGetValues (shell, XtNchildren, &kids, NULL);
b70cfce2
FP
798 if (!kids || !*kids)
799 abort ();
8dce2ddc
RS
800 for (i = 0; i < nkids; i++)
801 {
802 widget = kids[i];
803 if (XtIsSubclass (widget, dialogWidgetClass))
804 break;
805 }
e4c8d29a
J
806 if (! widget) return;
807
b70cfce2
FP
808 id = lw_get_widget_id (widget);
809 if (! id) abort ();
810
811 {
812 widget_info *info = lw_get_widget_info (id);
813 if (! info) abort ();
814 if (info->selection_cb)
815 info->selection_cb (widget, id, (XtPointer) -1);
816 }
817
818 lw_destroy_all_widgets (id);
819}
820
821\f
b70cfce2 822
2af91681 823static Widget
c3174d16 824xaw_create_main (widget_instance *instance)
2af91681
PR
825{
826 Arg al[1];
827 int ac;
828
829 /* Create a vertical Paned to hold menubar */
830 ac = 0;
831 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
832 return XtCreateWidget (instance->info->name, panedWidgetClass,
833 instance->parent, al, ac);
834}
835
b70cfce2
FP
836widget_creation_entry
837xaw_creation_table [] =
838{
2af91681 839 {"main", xaw_create_main},
b70cfce2
FP
840 {NULL, NULL}
841};