merge trunk
[bpt/emacs.git] / lwlib / lwlib-Xaw.c
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.
5
6 This file is part of the Lucid Widget Library.
7
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.
12
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.
17
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. */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <setjmp.h>
29 #include <ctype.h>
30
31 #include "../src/lisp.h"
32
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
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 */
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>
54 #endif /* HAVE_XAW3D */
55
56 #include <X11/Xatom.h>
57
58 #ifdef HAVE_XFT
59 #include <X11/Xft/Xft.h>
60
61 struct 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
74 static void xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data);
75
76
77 Boolean
78 lw_xaw_widget_p (Widget widget)
79 {
80 return (XtIsSubclass (widget, scrollbarWidgetClass) ||
81 XtIsSubclass (widget, dialogWidgetClass));
82 }
83
84 #if 0
85 static void
86 xaw_update_scrollbar (instance, widget, val)
87 widget_instance *instance;
88 Widget widget;
89 widget_value *val;
90 {
91 if (val->scrollbar_data)
92 {
93 scrollbar_values *data = val->scrollbar_data;
94 Dimension height, width;
95 Dimension pos_x, pos_y;
96 int widget_shown, widget_topOfThumb;
97 float new_shown, new_topOfThumb;
98
99 XtVaGetValues (widget,
100 XtNheight, &height,
101 XtNwidth, &width,
102 XtNx, &pos_x,
103 XtNy, &pos_y,
104 XtNtopOfThumb, &widget_topOfThumb,
105 XtNshown, &widget_shown,
106 NULL);
107
108 /*
109 * First size and position the scrollbar widget.
110 * We need to position it to second-guess the Paned widget's notion
111 * of what should happen when the WMShell gets resized.
112 */
113 if (height != data->scrollbar_height || pos_y != data->scrollbar_pos)
114 {
115 XtConfigureWidget (widget, pos_x, data->scrollbar_pos,
116 width, data->scrollbar_height, 0);
117
118 XtVaSetValues (widget,
119 XtNlength, data->scrollbar_height,
120 XtNthickness, width,
121 NULL);
122 }
123
124 /*
125 * Now the size the scrollbar's slider.
126 */
127 new_shown = (float) data->slider_size /
128 (float) (data->maximum - data->minimum);
129
130 new_topOfThumb = (float) (data->slider_position - data->minimum) /
131 (float) (data->maximum - data->minimum);
132
133 if (new_shown > 1.0)
134 new_shown = 1.0;
135 if (new_shown < 0)
136 new_shown = 0;
137
138 if (new_topOfThumb > 1.0)
139 new_topOfThumb = 1.0;
140 if (new_topOfThumb < 0)
141 new_topOfThumb = 0;
142
143 if (new_shown != widget_shown || new_topOfThumb != widget_topOfThumb)
144 XawScrollbarSetThumb (widget, new_topOfThumb, new_shown);
145 }
146 }
147 #endif
148
149 #ifdef HAVE_XFT
150 static void
151 fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
152 {
153 Pixel bg, fg;
154 XColor colors[2];
155
156 data->widget = widget;
157 data->xft_font = font;
158 XtVaGetValues (widget,
159 XtNbackground, &bg,
160 XtNforeground, &fg,
161 NULL);
162
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);
168
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;
177
178 data->p = None;
179 data->xft_draw = 0;
180 data->p_width = data->p_height = 0;
181 }
182
183 static XftFont*
184 openFont (Widget widget, char *name)
185 {
186 char *fname = name;
187 int screen = XScreenNumberOfScreen (XtScreen (widget));
188 int len = strlen (fname), i = len-1;
189 XftFont *fn;
190
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] == ' ')
195 {
196 fname = xstrdup (name);
197 fname[i] = '-';
198 }
199
200 fn = XftFontOpenName (XtDisplay (widget), screen, fname);
201 if (fname != name) free (fname);
202
203 return fn;
204 }
205
206 static int
207 get_text_width_and_height (Widget widget, char *text,
208 XftFont *xft_font,
209 int *height)
210 {
211 int w = 0, h = 0;
212 char *bp = text;
213
214 while (bp && *bp != '\0')
215 {
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;
225 }
226
227 *height = h;
228 return w;
229 }
230
231 static void
232 draw_text (struct widget_xft_data *data, char *lbl, int inverse)
233 {
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;
239
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);
248
249 if (!inverse) y += 2;
250 while (bp && *bp != '\0')
251 {
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,
256 (FcChar8 *) bp,
257 cp ? cp - bp : strlen (bp));
258 bp = cp ? cp + 1 : NULL;
259 /* 1.2 gives reasonable line spacing. */
260 y += data->xft_font->height * 1.2;
261 }
262
263 }
264
265
266 static void
267 set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
268 {
269 int width, height;
270
271 width = get_text_width_and_height (data->widget, lbl, data->xft_font,
272 &height);
273 data->p_width = width + margin;
274 data->p_height = height + margin;
275
276 data->p = XCreatePixmap (XtDisplay (data->widget),
277 XtWindow (toplevel),
278 data->p_width,
279 data->p_height,
280 DefaultDepthOfScreen (XtScreen (data->widget)));
281 draw_text (data, lbl, 0);
282 XtVaSetValues (data->widget, XtNbitmap, data->p, NULL);
283 }
284
285 static struct widget_xft_data *
286 find_xft_data (Widget widget)
287 {
288 widget_instance *inst = NULL;
289 Widget parent = XtParent (widget);
290 struct widget_xft_data *data = NULL;
291 int nr;
292 while (parent && !inst)
293 {
294 inst = lw_get_widget_instance (parent);
295 parent = XtParent (parent);
296 }
297 if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return 0;
298
299 for (nr = 0; data == NULL && nr < inst->nr_xft_data; ++nr)
300 {
301 if (inst->xft_data[nr].widget == widget)
302 data = &inst->xft_data[nr];
303 }
304
305 return data;
306 }
307
308 static void
309 command_press (Widget widget,
310 XEvent* event,
311 String *params,
312 Cardinal *num_params)
313 {
314 struct widget_xft_data *data = find_xft_data (widget);
315 if (data)
316 {
317 char *lbl;
318 /* Since this isn't used for rectangle buttons, use it to for armed. */
319 XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
320
321 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
322 draw_text (data, lbl, 1);
323 }
324 }
325
326 static void
327 command_reset (Widget widget,
328 XEvent* event,
329 String *params,
330 Cardinal *num_params)
331 {
332 struct widget_xft_data *data = find_xft_data (widget);
333 if (data)
334 {
335 Dimension cr;
336 XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
337 if (cr == 1)
338 {
339 char *lbl;
340 XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
341 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
342 draw_text (data, lbl, 0);
343 }
344 }
345 }
346
347
348 #endif
349
350 void
351 xaw_update_one_widget (widget_instance *instance, Widget widget,
352 widget_value *val, Boolean deep_p)
353 {
354 #if 0
355 if (XtIsSubclass (widget, scrollbarWidgetClass))
356 {
357 xaw_update_scrollbar (instance, widget, val);
358 }
359 #endif
360 if (XtIsSubclass (widget, dialogWidgetClass))
361 {
362
363 #ifdef HAVE_XFT
364 if (instance->xft_data && instance->xft_data[0].xft_font)
365 {
366 set_text (&instance->xft_data[0], instance->parent,
367 val->contents->value, 10);
368 }
369 #endif
370 XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
371 }
372 else if (XtIsSubclass (widget, commandWidgetClass))
373 {
374 Dimension bw = 0;
375 Arg al[10];
376 int ac = 0;
377
378 XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
379 if (bw == 0)
380 /* Don't let buttons end up with 0 borderwidth, that's ugly...
381 Yeah, all this should really be done through app-defaults files
382 or fallback resources, but that's a whole different can of worms
383 that I don't feel like opening right now. Making Athena widgets
384 not look like shit is just entirely too much work.
385 */
386 {
387 XtSetArg (al[0], XtNborderWidth, 1);
388 XtSetValues (widget, al, 1);
389 }
390
391 XtSetSensitive (widget, val->enabled);
392 XtSetArg (al[ac], XtNlabel, val->value);ac++;
393 /* Force centered button text. Se above. */
394 XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
395 #ifdef HAVE_XFT
396 if (instance->xft_data && instance->xft_data[0].xft_font)
397 {
398 int th;
399 int nr;
400 for (nr = 0; nr < instance->nr_xft_data; ++nr)
401 if (instance->xft_data[nr].widget == widget)
402 break;
403 if (nr < instance->nr_xft_data)
404 {
405 set_text (&instance->xft_data[nr], instance->parent,
406 val->value, 6);
407
408 /* Must set internalHeight to twice the highlight thickness,
409 or else it gets overwritten by our pixmap. Probably a bug. */
410 XtVaGetValues (widget, XtNhighlightThickness, &th, NULL);
411 XtSetArg (al[ac], XtNinternalHeight, 2*th);ac++;
412 }
413 }
414 #endif
415 XtSetValues (widget, al, ac);
416 XtRemoveAllCallbacks (widget, XtNcallback);
417 XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
418 }
419 }
420
421 void
422 xaw_update_one_value (widget_instance *instance, Widget widget, widget_value *val)
423 {
424 /* This function is not used by the scrollbars and those are the only
425 Athena widget implemented at the moment so do nothing. */
426 return;
427 }
428
429 void
430 xaw_destroy_instance (widget_instance *instance)
431 {
432 #ifdef HAVE_XFT
433 if (instance->xft_data)
434 {
435 int i;
436 for (i = 0; i < instance->nr_xft_data; ++i)
437 {
438 if (instance->xft_data[i].xft_draw)
439 XftDrawDestroy (instance->xft_data[i].xft_draw);
440 if (instance->xft_data[i].p != None)
441 {
442 XtVaSetValues (instance->xft_data[i].widget, XtNbitmap, None,
443 NULL);
444 XFreePixmap (XtDisplay (instance->widget),
445 instance->xft_data[i].p);
446 }
447 }
448 if (instance->xft_data[0].xft_font)
449 XftFontClose (XtDisplay (instance->widget),
450 instance->xft_data[0].xft_font);
451 free (instance->xft_data);
452 }
453 #endif
454 if (XtIsSubclass (instance->widget, dialogWidgetClass))
455 /* Need to destroy the Shell too. */
456 XtDestroyWidget (XtParent (instance->widget));
457 else
458 XtDestroyWidget (instance->widget);
459 }
460
461 void
462 xaw_popup_menu (Widget widget, XEvent *event)
463 {
464 /* An Athena menubar has not been implemented. */
465 return;
466 }
467
468 void
469 xaw_pop_instance (widget_instance *instance, Boolean up)
470 {
471 Widget widget = instance->widget;
472
473 if (up)
474 {
475 if (XtIsSubclass (widget, dialogWidgetClass))
476 {
477 /* For dialogs, we need to call XtPopup on the parent instead
478 of calling XtManageChild on the widget.
479 Also we need to hack the shell's WM_PROTOCOLS to get it to
480 understand what the close box is supposed to do!!
481 */
482 Display *dpy = XtDisplay (widget);
483 Widget shell = XtParent (widget);
484 Atom props [2];
485 int i = 0;
486 props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
487 XChangeProperty (dpy, XtWindow (shell),
488 XInternAtom (dpy, "WM_PROTOCOLS", False),
489 XA_ATOM, 32, PropModeAppend,
490 (unsigned char *) props, i);
491
492 /* Center the widget in its parent. Why isn't this kind of crap
493 done automatically? I thought toolkits were supposed to make
494 life easier?
495 */
496 {
497 unsigned int x, y, w, h;
498 Widget topmost = instance->parent;
499 Arg args[2];
500
501 w = shell->core.width;
502 h = shell->core.height;
503 while (topmost->core.parent && XtIsRealized (topmost->core.parent))
504 topmost = topmost->core.parent;
505 if (topmost->core.width < w) x = topmost->core.x;
506 else x = topmost->core.x + ((topmost->core.width - w) / 2);
507 if (topmost->core.height < h) y = topmost->core.y;
508 else y = topmost->core.y + ((topmost->core.height - h) / 2);
509 /* Using XtMoveWidget caused the widget to come
510 out in the wrong place with vtwm.
511 Question of virtual vs real coords, perhaps. */
512 XtSetArg (args[0], XtNx, x);
513 XtSetArg (args[1], XtNy, y);
514 XtSetValues (shell, args, 2);
515 }
516
517 /* Finally, pop it up. */
518 XtPopup (shell, XtGrabNonexclusive);
519 }
520 else
521 XtManageChild (widget);
522 }
523 else
524 {
525 if (XtIsSubclass (widget, dialogWidgetClass))
526 XtUnmanageChild (XtParent (widget));
527 else
528 XtUnmanageChild (widget);
529 }
530 }
531
532 \f
533 /* Dialog boxes */
534
535 static char overrideTrans[] =
536 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
537 /* Dialogs pop down on any key press */
538 static char dialogOverride[] =
539 "<KeyPress>Escape: lwlib_delete_dialog()";
540 static void wm_delete_window (Widget w,
541 XEvent *event,
542 String *params,
543 Cardinal *num_params);
544 static XtActionsRec xaw_actions [] = {
545 {"lwlib_delete_dialog", wm_delete_window}
546 };
547 static Boolean actions_initted = False;
548
549 #ifdef HAVE_XFT
550 static XtActionsRec button_actions[] =
551 {
552 { "my_reset", command_reset },
553 { "my_press", command_press },
554 };
555 char buttonTrans[] =
556 "<Leave>: reset() my_reset()\n"
557 "<Btn1Down>: set() my_press()\n"
558 "<Btn1Up>: my_reset() notify() unset()\n";
559 #endif
560
561 static Widget
562 make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
563 radio_box, list, left_buttons, right_buttons, instance)
564 char* name;
565 Widget parent;
566 Boolean pop_up_p;
567 char* shell_title;
568 char* icon_name;
569 Boolean text_input_slot;
570 Boolean radio_box;
571 Boolean list;
572 int left_buttons;
573 int right_buttons;
574 widget_instance *instance;
575 {
576 Arg av [20];
577 int ac = 0;
578 int i, bc;
579 char button_name [255];
580 Widget shell;
581 Widget dialog;
582 Widget button;
583 XtTranslations override;
584 #ifdef HAVE_XFT
585 XftFont *xft_font = 0;
586 XtTranslations button_override;
587 #endif
588
589 if (! pop_up_p) abort (); /* not implemented */
590 if (text_input_slot) abort (); /* not implemented */
591 if (radio_box) abort (); /* not implemented */
592 if (list) abort (); /* not implemented */
593
594 if (! actions_initted)
595 {
596 XtAppContext app = XtWidgetToApplicationContext (parent);
597 XtAppAddActions (app, xaw_actions,
598 sizeof (xaw_actions) / sizeof (xaw_actions[0]));
599 #ifdef HAVE_XFT
600 XtAppAddActions (app, button_actions,
601 sizeof (button_actions) / sizeof (button_actions[0]));
602 #endif
603 actions_initted = True;
604 }
605
606 override = XtParseTranslationTable (overrideTrans);
607
608 ac = 0;
609 XtSetArg (av[ac], XtNtitle, shell_title); ac++;
610 XtSetArg (av[ac], XtNallowShellResize, True); ac++;
611
612 /* Don't allow any geometry request from the user. */
613 XtSetArg (av[ac], XtNgeometry, 0); ac++;
614
615 shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
616 parent, av, ac);
617 XtOverrideTranslations (shell, override);
618
619 ac = 0;
620 dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
621 override = XtParseTranslationTable (dialogOverride);
622 XtOverrideTranslations (dialog, override);
623
624 #ifdef HAVE_XFT
625 {
626 int num;
627 Widget *ch = NULL;
628 Widget w = 0;
629 XtVaGetValues (dialog,
630 XtNnumChildren, &num,
631 XtNchildren, &ch, NULL);
632 for (i = 0; i < num; ++i)
633 {
634 if (!XtIsSubclass (ch[i], commandWidgetClass)
635 && XtIsSubclass (ch[i], labelWidgetClass))
636 {
637 w = ch[i];
638 break;
639 }
640 }
641 instance->xft_data = 0;
642 instance->nr_xft_data = 0;
643 if (w)
644 {
645 XtResource rec[] =
646 { { "faceName", "FaceName", XtRString, sizeof(String), 0, XtRString,
647 (XtPointer)"Sans-14" }};
648 char *faceName;
649 XtVaGetSubresources (dialog, &faceName, "Dialog", "dialog",
650 rec, 1, (String)NULL);
651 if (strcmp ("none", faceName) != 0)
652 xft_font = openFont (dialog, faceName);
653 if (xft_font)
654 {
655 instance->nr_xft_data = left_buttons + right_buttons + 1;
656 instance->xft_data = calloc (instance->nr_xft_data,
657 sizeof(*instance->xft_data));
658
659 fill_xft_data (&instance->xft_data[0], w, xft_font);
660 }
661 }
662
663 button_override = XtParseTranslationTable (buttonTrans);
664 }
665 #endif
666
667 bc = 0;
668 button = 0;
669 for (i = 0; i < left_buttons; i++)
670 {
671 ac = 0;
672 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
673 XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
674 XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
675 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
676 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
677 XtSetArg (av [ac], XtNresizable, True); ac++;
678 #ifdef HAVE_XAW3D
679 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
680 {
681 /* Turn of dithered shadow if we can. Looks bad */
682 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
683 }
684 #endif
685 sprintf (button_name, "button%d", ++bc);
686 button = XtCreateManagedWidget (button_name, commandWidgetClass,
687 dialog, av, ac);
688 #ifdef HAVE_XFT
689 if (xft_font)
690 {
691 fill_xft_data (&instance->xft_data[bc], button, xft_font);
692 XtOverrideTranslations (button, button_override);
693 }
694 #endif
695 }
696
697 for (i = 0; i < right_buttons; i++)
698 {
699 ac = 0;
700 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
701 if (i == 0)
702 {
703 /* Separator to the other buttons. */
704 XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
705 }
706 XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
707 XtSetArg (av [ac], XtNright, XtChainRight); ac++;
708 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
709 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
710 XtSetArg (av [ac], XtNresizable, True); ac++;
711 #ifdef HAVE_XAW3D
712 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
713 {
714 /* Turn of dithered shadow if we can. Looks bad */
715 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
716 }
717 #endif
718 sprintf (button_name, "button%d", ++bc);
719 button = XtCreateManagedWidget (button_name, commandWidgetClass,
720 dialog, av, ac);
721 #ifdef HAVE_XFT
722 if (xft_font)
723 {
724 fill_xft_data (&instance->xft_data[bc], button, xft_font);
725 XtOverrideTranslations (button, button_override);
726 }
727 #endif
728 }
729
730 return dialog;
731 }
732
733 Widget
734 xaw_create_dialog (widget_instance *instance)
735 {
736 char *name = instance->info->type;
737 Widget parent = instance->parent;
738 Widget widget;
739 Boolean pop_up_p = instance->pop_up_p;
740 char *shell_name = 0;
741 char *icon_name = 0;
742 Boolean text_input_slot = False;
743 Boolean radio_box = False;
744 Boolean list = False;
745 int total_buttons;
746 int left_buttons = 0;
747 int right_buttons = 1;
748
749 switch (name [0]) {
750 case 'E': case 'e':
751 icon_name = "dbox-error";
752 shell_name = "Error";
753 break;
754
755 case 'I': case 'i':
756 icon_name = "dbox-info";
757 shell_name = "Information";
758 break;
759
760 case 'L': case 'l':
761 list = True;
762 icon_name = "dbox-question";
763 shell_name = "Prompt";
764 break;
765
766 case 'P': case 'p':
767 text_input_slot = True;
768 icon_name = "dbox-question";
769 shell_name = "Prompt";
770 break;
771
772 case 'Q': case 'q':
773 icon_name = "dbox-question";
774 shell_name = "Question";
775 break;
776 }
777
778 total_buttons = name [1] - '0';
779
780 if (name [3] == 'T' || name [3] == 't')
781 {
782 text_input_slot = False;
783 radio_box = True;
784 }
785 else if (name [3])
786 right_buttons = name [4] - '0';
787
788 left_buttons = total_buttons - right_buttons;
789
790 widget = make_dialog (name, parent, pop_up_p,
791 shell_name, icon_name, text_input_slot, radio_box,
792 list, left_buttons, right_buttons, instance);
793 return widget;
794 }
795
796
797 static void
798 xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
799 {
800 widget_instance *instance = (widget_instance *) closure;
801 Widget instance_widget;
802 LWLIB_ID id;
803 XtPointer user_data;
804
805 lw_internal_update_other_instances (widget, closure, call_data);
806
807 if (! instance)
808 return;
809 if (widget->core.being_destroyed)
810 return;
811
812 instance_widget = instance->widget;
813 if (!instance_widget)
814 return;
815
816 id = instance->info->id;
817
818 #if 0
819 user_data = NULL;
820 XtVaGetValues (widget, XtNuserData, &user_data, NULL);
821 #else
822 /* Damn! Athena doesn't give us a way to hang our own data on the
823 buttons, so we have to go find it... I guess this assumes that
824 all instances of a button have the same call data. */
825 {
826 widget_value *val = instance->info->val->contents;
827 char *name = XtName (widget);
828 while (val)
829 {
830 if (val->name && !strcmp (val->name, name))
831 break;
832 val = val->next;
833 }
834 if (! val) abort ();
835 user_data = val->call_data;
836 }
837 #endif
838
839 if (instance->info->selection_cb)
840 instance->info->selection_cb (widget, id, user_data);
841 }
842
843 static void
844 wm_delete_window (Widget w,
845 XEvent *event,
846 String *params,
847 Cardinal *num_params)
848 {
849 LWLIB_ID id;
850 Cardinal nkids;
851 int i;
852 Widget *kids = 0;
853 Widget widget = 0, shell;
854
855 if (XtIsSubclass (w, dialogWidgetClass))
856 shell = XtParent (w);
857 else
858 shell = w;
859
860 if (! XtIsSubclass (shell, shellWidgetClass))
861 abort ();
862 XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
863 XtVaGetValues (shell, XtNchildren, &kids, NULL);
864 if (!kids || !*kids)
865 abort ();
866 for (i = 0; i < nkids; i++)
867 {
868 widget = kids[i];
869 if (XtIsSubclass (widget, dialogWidgetClass))
870 break;
871 }
872 if (! widget) return;
873
874 id = lw_get_widget_id (widget);
875 if (! id) abort ();
876
877 {
878 widget_info *info = lw_get_widget_info (id);
879 if (! info) abort ();
880 if (info->selection_cb)
881 info->selection_cb (widget, id, (XtPointer) -1);
882 }
883
884 lw_destroy_all_widgets (id);
885 }
886
887 \f
888 /* Scrollbars */
889
890 #if 0
891 static void
892 xaw_scrollbar_scroll (widget, closure, call_data)
893 Widget widget;
894 XtPointer closure;
895 XtPointer call_data;
896 {
897 widget_instance *instance = (widget_instance *) closure;
898 LWLIB_ID id;
899 scroll_event event_data;
900
901 if (!instance || widget->core.being_destroyed)
902 return;
903
904 id = instance->info->id;
905 event_data.slider_value = 0;
906 event_data.time = 0;
907
908 if ((int) call_data > 0)
909 event_data.action = SCROLLBAR_PAGE_DOWN;
910 else
911 event_data.action = SCROLLBAR_PAGE_UP;
912
913 if (instance->info->pre_activate_cb)
914 instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
915 }
916 #endif
917
918 #if 0
919 static void
920 xaw_scrollbar_jump (widget, closure, call_data)
921 Widget widget;
922 XtPointer closure;
923 XtPointer call_data;
924 {
925 widget_instance *instance = (widget_instance *) closure;
926 LWLIB_ID id;
927 scroll_event event_data;
928 scrollbar_values *val =
929 (scrollbar_values *) instance->info->val->scrollbar_data;
930 float percent;
931
932 if (!instance || widget->core.being_destroyed)
933 return;
934
935 id = instance->info->id;
936
937 percent = * (float *) call_data;
938 event_data.slider_value =
939 (int) (percent * (float) (val->maximum - val->minimum)) + val->minimum;
940
941 event_data.time = 0;
942 event_data.action = SCROLLBAR_DRAG;
943
944 if (instance->info->pre_activate_cb)
945 instance->info->pre_activate_cb (widget, id, (XtPointer) &event_data);
946 }
947 #endif
948
949 static Widget
950 xaw_create_scrollbar (widget_instance *instance)
951 {
952 #if 0
953 Arg av[20];
954 int ac = 0;
955 Dimension width;
956 Widget scrollbar;
957
958 XtVaGetValues (instance->parent, XtNwidth, &width, NULL);
959
960 XtSetArg (av[ac], XtNshowGrip, 0); ac++;
961 XtSetArg (av[ac], XtNresizeToPreferred, 1); ac++;
962 XtSetArg (av[ac], XtNallowResize, True); ac++;
963 XtSetArg (av[ac], XtNskipAdjust, True); ac++;
964 XtSetArg (av[ac], XtNwidth, width); ac++;
965 XtSetArg (av[ac], XtNmappedWhenManaged, True); ac++;
966
967 scrollbar =
968 XtCreateWidget (instance->info->name, scrollbarWidgetClass,
969 instance->parent, av, ac);
970
971 /* We have to force the border width to be 0 otherwise the
972 geometry manager likes to start looping for awhile... */
973 XtVaSetValues (scrollbar, XtNborderWidth, 0, NULL);
974
975 XtRemoveAllCallbacks (scrollbar, "jumpProc");
976 XtRemoveAllCallbacks (scrollbar, "scrollProc");
977
978 XtAddCallback (scrollbar, "jumpProc", xaw_scrollbar_jump,
979 (XtPointer) instance);
980 XtAddCallback (scrollbar, "scrollProc", xaw_scrollbar_scroll,
981 (XtPointer) instance);
982
983 return scrollbar;
984 #else
985 return NULL;
986 #endif
987 }
988
989 static Widget
990 xaw_create_main (widget_instance *instance)
991 {
992 Arg al[1];
993 int ac;
994
995 /* Create a vertical Paned to hold menubar */
996 ac = 0;
997 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
998 return XtCreateWidget (instance->info->name, panedWidgetClass,
999 instance->parent, al, ac);
1000 }
1001
1002 widget_creation_entry
1003 xaw_creation_table [] =
1004 {
1005 {"scrollbar", xaw_create_scrollbar},
1006 {"main", xaw_create_main},
1007 {NULL, NULL}
1008 };
1009
1010 /* arch-tag: fbbd3589-ae1c-41a0-9142-f628cfee6564
1011 (do not change this comment) */