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