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