comparison src/gui_athena.c @ 7:3fc0f57ecb91 v7.0001

updated for version 7.0001
author vimboss
date Sun, 13 Jun 2004 20:20:40 +0000
parents
children eff3887963cc
comparison
equal deleted inserted replaced
6:c2daee826b8f 7:3fc0f57ecb91
1 /* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 * GUI/Motif support by Robert Webb
5 * Athena port by Bill Foster
6 *
7 * Do ":help uganda" in Vim to read copying and usage conditions.
8 * Do ":help credits" in Vim to see a list of people who contributed.
9 * See README.txt for an overview of the Vim source code.
10 */
11
12 #include <X11/StringDefs.h>
13 #include <X11/Intrinsic.h>
14 #ifdef FEAT_GUI_NEXTAW
15 # include <X11/neXtaw/Form.h>
16 # include <X11/neXtaw/SimpleMenu.h>
17 # include <X11/neXtaw/MenuButton.h>
18 # include <X11/neXtaw/SmeBSB.h>
19 # include <X11/neXtaw/SmeLine.h>
20 # include <X11/neXtaw/Box.h>
21 # include <X11/neXtaw/Dialog.h>
22 # include <X11/neXtaw/Text.h>
23 # include <X11/neXtaw/AsciiText.h>
24 # include <X11/neXtaw/Scrollbar.h>
25 #else
26 # include <X11/Xaw/Form.h>
27 # include <X11/Xaw/SimpleMenu.h>
28 # include <X11/Xaw/MenuButton.h>
29 # include <X11/Xaw/SmeBSB.h>
30 # include <X11/Xaw/SmeLine.h>
31 # include <X11/Xaw/Box.h>
32 # include <X11/Xaw/Dialog.h>
33 # include <X11/Xaw/Text.h>
34 # include <X11/Xaw/AsciiText.h>
35 #endif /* FEAT_GUI_NEXTAW */
36
37 #include "vim.h"
38 #ifndef FEAT_GUI_NEXTAW
39 # include "gui_at_sb.h"
40 #endif
41
42 extern Widget vimShell;
43
44 static Widget vimForm = (Widget)0;
45 static Widget textArea = (Widget)0;
46 #ifdef FEAT_MENU
47 static Widget menuBar = (Widget)0;
48 static XtIntervalId timer = 0; /* 0 = expired, otherwise active */
49
50 /* Used to figure out menu ordering */
51 static vimmenu_T *a_cur_menu = NULL;
52 static Cardinal athena_calculate_ins_pos __ARGS((Widget));
53
54 static Pixmap gui_athena_create_pullright_pixmap __ARGS((Widget));
55 static void gui_athena_menu_timeout __ARGS((XtPointer, XtIntervalId *));
56 static void gui_athena_popup_callback __ARGS((Widget, XtPointer, XtPointer));
57 static void gui_athena_delayed_arm_action __ARGS((Widget, XEvent *, String *,
58 Cardinal *));
59 static void gui_athena_popdown_submenus_action __ARGS((Widget, XEvent *,
60 String *, Cardinal *));
61 static XtActionsRec pullAction[2] = {
62 { "menu-delayedpopup", (XtActionProc)gui_athena_delayed_arm_action},
63 { "menu-popdownsubmenus", (XtActionProc)gui_athena_popdown_submenus_action}
64 };
65 #endif
66
67 #ifdef FEAT_TOOLBAR
68 static void gui_mch_reset_focus __ARGS((void));
69 static Widget toolBar = (Widget)0;
70 #endif
71
72 static void gui_athena_scroll_cb_jump __ARGS((Widget, XtPointer, XtPointer));
73 static void gui_athena_scroll_cb_scroll __ARGS((Widget, XtPointer, XtPointer));
74 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_MENU)
75 static void gui_athena_menu_colors __ARGS((Widget id));
76 #endif
77 static void gui_athena_scroll_colors __ARGS((Widget id));
78
79 #ifdef FEAT_MENU
80 static XtTranslations popupTrans, parentTrans, menuTrans, supermenuTrans;
81 static Pixmap pullerBitmap = None;
82 static int puller_width = 0;
83 #endif
84
85 /*
86 * Scrollbar callback (XtNjumpProc) for when the scrollbar is dragged with the
87 * left or middle mouse button.
88 */
89 /* ARGSUSED */
90 static void
91 gui_athena_scroll_cb_jump(w, client_data, call_data)
92 Widget w;
93 XtPointer client_data, call_data;
94 {
95 scrollbar_T *sb, *sb_info;
96 long value;
97
98 sb = gui_find_scrollbar((long)client_data);
99
100 if (sb == NULL)
101 return;
102 else if (sb->wp != NULL) /* Left or right scrollbar */
103 {
104 /*
105 * Careful: need to get scrollbar info out of first (left) scrollbar
106 * for window, but keep real scrollbar too because we must pass it to
107 * gui_drag_scrollbar().
108 */
109 sb_info = &sb->wp->w_scrollbars[0];
110 }
111 else /* Bottom scrollbar */
112 sb_info = sb;
113
114 value = (long)(*((float *)call_data) * (float)(sb_info->max + 1) + 0.001);
115 if (value > sb_info->max)
116 value = sb_info->max;
117
118 gui_drag_scrollbar(sb, value, TRUE);
119 }
120
121 /*
122 * Scrollbar callback (XtNscrollProc) for paging up or down with the left or
123 * right mouse buttons.
124 */
125 /* ARGSUSED */
126 static void
127 gui_athena_scroll_cb_scroll(w, client_data, call_data)
128 Widget w;
129 XtPointer client_data, call_data;
130 {
131 scrollbar_T *sb, *sb_info;
132 long value;
133 int data = (int)(long)call_data;
134 int page;
135
136 sb = gui_find_scrollbar((long)client_data);
137
138 if (sb == NULL)
139 return;
140 if (sb->wp != NULL) /* Left or right scrollbar */
141 {
142 /*
143 * Careful: need to get scrollbar info out of first (left) scrollbar
144 * for window, but keep real scrollbar too because we must pass it to
145 * gui_drag_scrollbar().
146 */
147 sb_info = &sb->wp->w_scrollbars[0];
148
149 if (sb_info->size > 5)
150 page = sb_info->size - 2; /* use two lines of context */
151 else
152 page = sb_info->size;
153 #ifdef FEAT_GUI_NEXTAW
154 if (data < 0)
155 {
156 data = (data - gui.char_height + 1) / gui.char_height;
157 if (data > -sb_info->size)
158 data = -1;
159 else
160 data = -page;
161 }
162 else if (data > 0)
163 {
164 data = (data + gui.char_height - 1) / gui.char_height;
165 if (data < sb_info->size)
166 data = 1;
167 else
168 data = page;
169 }
170 #else
171 switch (data)
172 {
173 case ONE_LINE_DATA: data = 1; break;
174 case -ONE_LINE_DATA: data = -1; break;
175 case ONE_PAGE_DATA: data = page; break;
176 case -ONE_PAGE_DATA: data = -page; break;
177 case END_PAGE_DATA: data = sb_info->max; break;
178 case -END_PAGE_DATA: data = -sb_info->max; break;
179 default: data = 0; break;
180 }
181 #endif
182 }
183 else /* Bottom scrollbar */
184 {
185 sb_info = sb;
186 #ifdef FEAT_GUI_NEXTAW
187 if (data < 0)
188 {
189 data = (data - gui.char_width + 1) / gui.char_width;
190 if (data > -sb->size)
191 data = -1;
192 }
193 else if (data > 0)
194 {
195 data = (data + gui.char_width - 1) / gui.char_width;
196 if (data < sb->size)
197 data = 1;
198 }
199 #endif
200 if (data < -1) /* page-width left */
201 {
202 if (sb->size > 8)
203 data = -(sb->size - 5);
204 else
205 data = -sb->size;
206 }
207 else if (data > 1) /* page-width right */
208 {
209 if (sb->size > 8)
210 data = (sb->size - 5);
211 else
212 data = sb->size;
213 }
214 }
215
216 value = sb_info->value + data;
217 if (value > sb_info->max)
218 value = sb_info->max;
219 else if (value < 0)
220 value = 0;
221
222 /* Update the bottom scrollbar an extra time (why is this needed?? */
223 if (sb->wp == NULL) /* Bottom scrollbar */
224 gui_mch_set_scrollbar_thumb(sb, value, sb->size, sb->max);
225
226 gui_drag_scrollbar(sb, value, FALSE);
227 }
228
229 /*
230 * Create all the Athena widgets necessary.
231 */
232 void
233 gui_x11_create_widgets()
234 {
235 /*
236 * We don't have any borders handled internally by the textArea to worry
237 * about so only skip over the configured border width.
238 */
239 gui.border_offset = gui.border_width;
240
241 #if 0 /* not needed? */
242 XtInitializeWidgetClass(formWidgetClass);
243 XtInitializeWidgetClass(boxWidgetClass);
244 XtInitializeWidgetClass(coreWidgetClass);
245 #ifdef FEAT_MENU
246 XtInitializeWidgetClass(menuButtonWidgetClass);
247 #endif
248 XtInitializeWidgetClass(simpleMenuWidgetClass);
249 #ifdef FEAT_GUI_NEXTAW
250 XtInitializeWidgetClass(scrollbarWidgetClass);
251 #else
252 XtInitializeWidgetClass(vim_scrollbarWidgetClass);
253 #endif
254 #endif
255
256 /* The form containing all the other widgets */
257 vimForm = XtVaCreateManagedWidget("vimForm",
258 formWidgetClass, vimShell,
259 XtNborderWidth, 0,
260 NULL);
261 gui_athena_scroll_colors(vimForm);
262
263 #ifdef FEAT_MENU
264 /* The top menu bar */
265 menuBar = XtVaCreateManagedWidget("menuBar",
266 boxWidgetClass, vimForm,
267 XtNresizable, True,
268 XtNtop, XtChainTop,
269 XtNbottom, XtChainTop,
270 XtNleft, XtChainLeft,
271 XtNright, XtChainRight,
272 XtNinsertPosition, athena_calculate_ins_pos,
273 NULL);
274 gui_athena_menu_colors(menuBar);
275 if (gui.menu_fg_pixel != INVALCOLOR)
276 XtVaSetValues(menuBar, XtNborderColor, gui.menu_fg_pixel, NULL);
277 #endif
278
279 #ifdef FEAT_TOOLBAR
280 /* Don't create it Managed, it will be managed when creating the first
281 * item. Otherwise an empty toolbar shows up. */
282 toolBar = XtVaCreateWidget("toolBar",
283 boxWidgetClass, vimForm,
284 XtNresizable, True,
285 XtNtop, XtChainTop,
286 XtNbottom, XtChainTop,
287 XtNleft, XtChainLeft,
288 XtNright, XtChainRight,
289 XtNorientation, XtorientHorizontal,
290 XtNhSpace, 1,
291 XtNvSpace, 3,
292 XtNinsertPosition, athena_calculate_ins_pos,
293 NULL);
294 gui_athena_menu_colors(toolBar);
295 #endif
296
297 /* The text area. */
298 textArea = XtVaCreateManagedWidget("textArea",
299 coreWidgetClass, vimForm,
300 XtNresizable, True,
301 XtNtop, XtChainTop,
302 XtNbottom, XtChainTop,
303 XtNleft, XtChainLeft,
304 XtNright, XtChainLeft,
305 XtNbackground, gui.back_pixel,
306 XtNborderWidth, 0,
307 NULL);
308
309 /*
310 * Install the callbacks.
311 */
312 gui_x11_callbacks(textArea, vimForm);
313
314 #ifdef FEAT_MENU
315 popupTrans = XtParseTranslationTable(
316 "<EnterWindow>: menu-popdownsubmenus() highlight() menu-delayedpopup()\n"
317 "<LeaveWindow>: unhighlight()\n"
318 "<BtnUp>: menu-popdownsubmenus() XtMenuPopdown() notify() unhighlight()\n"
319 "<Motion>: highlight() menu-delayedpopup()");
320 parentTrans = XtParseTranslationTable("<LeaveWindow>: unhighlight()");
321 menuTrans = XtParseTranslationTable(
322 "<EnterWindow>: menu-popdownsubmenus() highlight() menu-delayedpopup()\n"
323 "<LeaveWindow>: menu-popdownsubmenus() XtMenuPopdown() unhighlight()\n"
324 "<BtnUp>: notify() unhighlight()\n"
325 "<BtnMotion>: highlight() menu-delayedpopup()");
326 supermenuTrans = XtParseTranslationTable(
327 "<EnterWindow>: menu-popdownsubmenus() highlight() menu-delayedpopup()\n"
328 "<LeaveWindow>: unhighlight()\n"
329 "<BtnUp>: menu-popdownsubmenus() XtMenuPopdown() notify() unhighlight()\n"
330 "<BtnMotion>: highlight() menu-delayedpopup()");
331
332 XtAppAddActions(XtWidgetToApplicationContext(vimForm), pullAction,
333 XtNumber(pullAction));
334 #endif
335
336 /* Pretend we don't have input focus, we will get an event if we do. */
337 gui.in_focus = FALSE;
338 }
339
340 #ifdef FEAT_MENU
341 /*
342 * Calculates the Pixmap based on the size of the current menu font.
343 */
344 static Pixmap
345 gui_athena_create_pullright_pixmap(w)
346 Widget w;
347 {
348 Pixmap retval;
349 #ifdef FONTSET_ALWAYS
350 XFontSet font = None;
351 #else
352 XFontStruct *font = NULL;
353 #endif
354
355 #ifdef FONTSET_ALWAYS
356 if (gui.menu_fontset == NOFONTSET)
357 #else
358 if (gui.menu_font == NOFONT)
359 #endif
360 {
361 XrmValue from, to;
362 WidgetList children;
363 Cardinal num_children;
364
365 #ifdef FONTSET_ALWAYS
366 from.size = strlen(from.addr = XtDefaultFontSet);
367 to.addr = (XtPointer)&font;
368 to.size = sizeof(XFontSet);
369 #else
370 from.size = strlen(from.addr = XtDefaultFont);
371 to.addr = (XtPointer)&font;
372 to.size = sizeof(XFontStruct *);
373 #endif
374 /* Assumption: The menuBar children will use the same font as the
375 * pulldown menu items AND they will all be of type
376 * XtNfont.
377 */
378 XtVaGetValues(menuBar, XtNchildren, &children,
379 XtNnumChildren, &num_children,
380 NULL);
381 if (XtConvertAndStore(w ? w :
382 (num_children > 0) ? children[0] : menuBar,
383 XtRString, &from,
384 #ifdef FONTSET_ALWAYS
385 XtRFontSet, &to
386 #else
387 XtRFontStruct, &to
388 #endif
389 ) == False)
390 return None;
391 /* "font" should now contain data */
392 }
393 else
394 #ifdef FONTSET_ALWAYS
395 font = (XFontSet)gui.menu_fontset;
396 #else
397 font = (XFontStruct *)gui.menu_font;
398 #endif
399
400 {
401 int width, height;
402 GC draw_gc, undraw_gc;
403 XGCValues gc_values;
404 XPoint points[3];
405
406 #ifdef FONTSET_ALWAYS
407 height = fontset_height2(font);
408 #else
409 height = font->max_bounds.ascent + font->max_bounds.descent;
410 #endif
411 width = height - 2;
412 puller_width = width + 4;
413 retval = XCreatePixmap(gui.dpy,DefaultRootWindow(gui.dpy),width,
414 height, 1);
415 gc_values.foreground = 1;
416 gc_values.background = 0;
417 draw_gc = XCreateGC(gui.dpy, retval,
418 GCForeground | GCBackground,
419 &gc_values);
420 gc_values.foreground = 0;
421 gc_values.background = 1;
422 undraw_gc = XCreateGC(gui.dpy, retval,
423 GCForeground | GCBackground,
424 &gc_values);
425 points[0].x = 0;
426 points[0].y = 0;
427 points[1].x = width - 1;
428 points[1].y = (height - 1) / 2;
429 points[2].x = 0;
430 points[2].y = height - 1;
431 XFillRectangle(gui.dpy, retval, undraw_gc, 0, 0, height, height);
432 XFillPolygon(gui.dpy, retval, draw_gc, points, XtNumber(points),
433 Convex, CoordModeOrigin);
434 XFreeGC(gui.dpy, draw_gc);
435 XFreeGC(gui.dpy, undraw_gc);
436 }
437 return retval;
438 }
439 #endif
440
441 /*
442 * Called when the GUI is not going to start after all.
443 */
444 void
445 gui_x11_destroy_widgets()
446 {
447 textArea = NULL;
448 #ifdef FEAT_MENU
449 menuBar = NULL;
450 #endif
451 #ifdef FEAT_TOOLBAR
452 toolBar = NULL;
453 #endif
454 }
455
456 #if defined(FEAT_TOOLBAR) || defined(PROTO)
457 void
458 gui_mch_set_toolbar_pos(x, y, w, h)
459 int x;
460 int y;
461 int w;
462 int h;
463 {
464 Dimension border;
465 int height;
466
467 if (!XtIsManaged(toolBar)) /* nothing to do */
468 return;
469 XtUnmanageChild(toolBar);
470 XtVaGetValues(toolBar,
471 XtNborderWidth, &border,
472 NULL);
473 height = h - 2 * border;
474 if (height < 0)
475 height = 1;
476 XtVaSetValues(toolBar,
477 XtNhorizDistance, x,
478 XtNvertDistance, y,
479 XtNwidth, w - 2 * border,
480 XtNheight, height,
481 NULL);
482 XtManageChild(toolBar);
483 }
484 #endif
485
486 void
487 gui_mch_set_text_area_pos(x, y, w, h)
488 int x;
489 int y;
490 int w;
491 int h;
492 {
493 XtUnmanageChild(textArea);
494 XtVaSetValues(textArea,
495 XtNhorizDistance, x,
496 XtNvertDistance, y,
497 XtNwidth, w,
498 XtNheight, h,
499 NULL);
500 XtManageChild(textArea);
501 #ifdef FEAT_TOOLBAR
502 /* Give keyboard focus to the textArea instead of the toolbar. */
503 gui_mch_reset_focus();
504 #endif
505 }
506
507 #ifdef FEAT_TOOLBAR
508 /*
509 * A toolbar button has been pushed; now reset the input focus
510 * such that the user can type page up/down etc. and have the
511 * input go to the editor window, not the button
512 */
513 static void
514 gui_mch_reset_focus()
515 {
516 XtSetKeyboardFocus(vimForm, textArea);
517 }
518 #endif
519
520
521 void
522 gui_x11_set_back_color()
523 {
524 if (textArea != NULL)
525 XtVaSetValues(textArea,
526 XtNbackground, gui.back_pixel,
527 NULL);
528 }
529
530 #if defined(FEAT_MENU) || defined(PROTO)
531 /*
532 * Menu stuff.
533 */
534
535 static char_u *make_pull_name __ARGS((char_u * name));
536 static Widget get_popup_entry __ARGS((Widget w));
537 static Widget submenu_widget __ARGS((Widget));
538 static Boolean has_submenu __ARGS((Widget));
539 static void gui_mch_submenu_change __ARGS((vimmenu_T *mp, int colors));
540 static void gui_athena_menu_font __ARGS((Widget id));
541 static Boolean gui_athena_menu_has_submenus __ARGS((Widget, Widget));
542
543 void
544 gui_mch_enable_menu(flag)
545 int flag;
546 {
547 if (flag)
548 {
549 XtManageChild(menuBar);
550 # ifdef FEAT_TOOLBAR
551 if (XtIsManaged(toolBar))
552 {
553 XtVaSetValues(toolBar,
554 XtNvertDistance, gui.menu_height,
555 NULL);
556 XtVaSetValues(textArea,
557 XtNvertDistance, gui.menu_height + gui.toolbar_height,
558 NULL);
559 }
560 # endif
561 }
562 else
563 {
564 XtUnmanageChild(menuBar);
565 # ifdef FEAT_TOOLBAR
566 if (XtIsManaged(toolBar))
567 {
568 XtVaSetValues(toolBar,
569 XtNvertDistance, 0,
570 NULL);
571 }
572 # endif
573 }
574 }
575
576 void
577 gui_mch_set_menu_pos(x, y, w, h)
578 int x;
579 int y;
580 int w;
581 int h;
582 {
583 Dimension border;
584 int height;
585
586 XtUnmanageChild(menuBar);
587 XtVaGetValues(menuBar, XtNborderWidth, &border, NULL);
588 /* avoid trouble when there are no menu items, and h is 1 */
589 height = h - 2 * border;
590 if (height < 0)
591 height = 1;
592 XtVaSetValues(menuBar,
593 XtNhorizDistance, x,
594 XtNvertDistance, y,
595 XtNwidth, w - 2 * border,
596 XtNheight, height,
597 NULL);
598 XtManageChild(menuBar);
599 }
600
601 /*
602 * Used to calculate the insertion position of a widget with respect to its
603 * neighbors.
604 *
605 * Valid range of return values is: 0 (beginning of children) to
606 * numChildren (end of children).
607 */
608 static Cardinal
609 athena_calculate_ins_pos(widget)
610 Widget widget;
611 {
612 /* Assume that if the parent of the vimmenu_T is NULL, then we can get
613 * to this menu by traversing "next", starting at "root_menu".
614 *
615 * This holds true for popup menus, toolbar, and toplevel menu items.
616 */
617
618 /* Popup menus: "id" is NULL. Only submenu_id is valid */
619
620 /* Menus that are not toplevel: "parent" will be non-NULL, "id" &
621 * "submenu_id" will be non-NULL.
622 */
623
624 /* Toplevel menus: "parent" is NULL, id is the widget of the menu item */
625
626 WidgetList children;
627 Cardinal num_children = 0;
628 int retval;
629 Arg args[2];
630 int n = 0;
631 int i;
632
633 XtSetArg(args[n], XtNchildren, &children); n++;
634 XtSetArg(args[n], XtNnumChildren, &num_children); n++;
635 XtGetValues(XtParent(widget), args, n);
636
637 retval = num_children;
638 for (i = 0; i < num_children; ++i)
639 {
640 Widget current = children[i];
641 vimmenu_T *menu = NULL;
642
643 for (menu = (a_cur_menu->parent == NULL)
644 ? root_menu : a_cur_menu->parent->children;
645 menu != NULL;
646 menu = menu->next)
647 if (current == menu->id
648 && a_cur_menu->priority < menu->priority
649 && i < retval)
650 retval = i;
651 }
652 return retval;
653 }
654
655 /* ARGSUSED */
656 void
657 gui_mch_add_menu(menu, idx)
658 vimmenu_T *menu;
659 int idx;
660 {
661 char_u *pullright_name;
662 Dimension height, space, border;
663 vimmenu_T *parent = menu->parent;
664
665 a_cur_menu = menu;
666 if (parent == NULL)
667 {
668 if (menu_is_popup(menu->dname))
669 {
670 menu->submenu_id = XtVaCreatePopupShell((char *)menu->dname,
671 simpleMenuWidgetClass, vimShell,
672 XtNinsertPosition, athena_calculate_ins_pos,
673 XtNtranslations, popupTrans,
674 NULL);
675 gui_athena_menu_colors(menu->submenu_id);
676 }
677 else if (menu_is_menubar(menu->dname))
678 {
679 menu->id = XtVaCreateManagedWidget((char *)menu->dname,
680 menuButtonWidgetClass, menuBar,
681 XtNmenuName, menu->dname,
682 #ifdef FONTSET_ALWAYS
683 XtNinternational, True,
684 #endif
685 NULL);
686 if (menu->id == (Widget)0)
687 return;
688 gui_athena_menu_colors(menu->id);
689 gui_athena_menu_font(menu->id);
690
691 menu->submenu_id = XtVaCreatePopupShell((char *)menu->dname,
692 simpleMenuWidgetClass, menu->id,
693 XtNinsertPosition, athena_calculate_ins_pos,
694 XtNtranslations, supermenuTrans,
695 NULL);
696 gui_athena_menu_colors(menu->submenu_id);
697 gui_athena_menu_font(menu->submenu_id);
698
699 /* Don't update the menu height when it was set at a fixed value */
700 if (!gui.menu_height_fixed)
701 {
702 /*
703 * When we add a top-level item to the menu bar, we can figure
704 * out how high the menu bar should be.
705 */
706 XtVaGetValues(menuBar,
707 XtNvSpace, &space,
708 XtNborderWidth, &border,
709 NULL);
710 XtVaGetValues(menu->id,
711 XtNheight, &height,
712 NULL);
713 gui.menu_height = height + 2 * (space + border);
714 }
715 }
716 }
717 else if (parent->submenu_id != (Widget)0)
718 {
719 menu->id = XtVaCreateManagedWidget((char *)menu->dname,
720 smeBSBObjectClass, parent->submenu_id,
721 XtNlabel, menu->dname,
722 #ifdef FONTSET_ALWAYS
723 XtNinternational, True,
724 #endif
725 NULL);
726 if (menu->id == (Widget)0)
727 return;
728 if (pullerBitmap == None)
729 pullerBitmap = gui_athena_create_pullright_pixmap(menu->id);
730
731 XtVaSetValues(menu->id, XtNrightBitmap, pullerBitmap,
732 NULL);
733 /* If there are other menu items that are not pulldown menus,
734 * we need to adjust the right margins of those, too.
735 */
736 {
737 WidgetList children;
738 Cardinal num_children;
739 int i;
740
741 XtVaGetValues(parent->submenu_id, XtNchildren, &children,
742 XtNnumChildren, &num_children,
743 NULL);
744 for (i = 0; i < num_children; ++i)
745 {
746 XtVaSetValues(children[i],
747 XtNrightMargin, puller_width,
748 NULL);
749 }
750 }
751 gui_athena_menu_colors(menu->id);
752 gui_athena_menu_font(menu->id);
753
754 pullright_name = make_pull_name(menu->dname);
755 menu->submenu_id = XtVaCreatePopupShell((char *)pullright_name,
756 simpleMenuWidgetClass, parent->submenu_id,
757 XtNtranslations, menuTrans,
758 NULL);
759 gui_athena_menu_colors(menu->submenu_id);
760 gui_athena_menu_font(menu->submenu_id);
761 vim_free(pullright_name);
762 XtAddCallback(menu->submenu_id, XtNpopupCallback,
763 gui_athena_popup_callback, (XtPointer)menu);
764
765 if (parent->parent != NULL)
766 XtOverrideTranslations(parent->submenu_id, parentTrans);
767 }
768 a_cur_menu = NULL;
769 }
770
771 /* Used to determine whether a SimpleMenu has pulldown entries.
772 *
773 * "id" is the parent of the menu items.
774 * Ignore widget "ignore" in the pane.
775 */
776 static Boolean
777 gui_athena_menu_has_submenus(id, ignore)
778 Widget id;
779 Widget ignore;
780 {
781 WidgetList children;
782 Cardinal num_children;
783 int i;
784
785 XtVaGetValues(id, XtNchildren, &children,
786 XtNnumChildren, &num_children,
787 NULL);
788 for (i = 0; i < num_children; ++i)
789 {
790 if (children[i] == ignore)
791 continue;
792 if (has_submenu(children[i]))
793 return True;
794 }
795 return False;
796 }
797
798 static void
799 gui_athena_menu_font(id)
800 Widget id;
801 {
802 #ifdef FONTSET_ALWAYS
803 if (gui.menu_fontset != NOFONTSET)
804 {
805 if (XtIsManaged(id))
806 {
807 XtUnmanageChild(id);
808 XtVaSetValues(id, XtNfontSet, gui.menu_fontset, NULL);
809 /* We should force the widget to recalculate it's
810 * geometry now. */
811 XtManageChild(id);
812 }
813 else
814 XtVaSetValues(id, XtNfontSet, gui.menu_fontset, NULL);
815 if (has_submenu(id))
816 XtVaSetValues(id, XtNrightBitmap, pullerBitmap, NULL);
817 }
818 #else
819 int managed = FALSE;
820
821 if (gui.menu_font != NOFONT)
822 {
823 if (XtIsManaged(id))
824 {
825 XtUnmanageChild(id);
826 managed = TRUE;
827 }
828
829 # ifdef FEAT_XFONTSET
830 if (gui.fontset != NOFONTSET)
831 XtVaSetValues(id, XtNfontSet, gui.menu_font, NULL);
832 else
833 # endif
834 XtVaSetValues(id, XtNfont, gui.menu_font, NULL);
835 if (has_submenu(id))
836 XtVaSetValues(id, XtNrightBitmap, pullerBitmap, NULL);
837
838 /* Force the widget to recalculate it's geometry now. */
839 if (managed)
840 XtManageChild(id);
841 }
842 #endif
843 }
844
845
846 void
847 gui_mch_new_menu_font()
848 {
849 Pixmap oldpuller = None;
850
851 if (menuBar == (Widget)0)
852 return;
853
854 if (pullerBitmap != None)
855 {
856 oldpuller = pullerBitmap;
857 pullerBitmap = gui_athena_create_pullright_pixmap(NULL);
858 }
859 gui_mch_submenu_change(root_menu, FALSE);
860
861 {
862 /* Iterate through the menubar menu items and get the height of
863 * each one. The menu bar height is set to the maximum of all
864 * the heights.
865 */
866 vimmenu_T *mp;
867 int max_height = 9999;
868
869 for (mp = root_menu; mp != NULL; mp = mp->next)
870 {
871 if (menu_is_menubar(mp->dname))
872 {
873 Dimension height;
874
875 XtVaGetValues(mp->id,
876 XtNheight,(XtArgVal *)&height,
877 NULL);
878 if (height < max_height)
879 max_height = height;
880 }
881 }
882 if (max_height != 9999)
883 {
884 /* Don't update the menu height when it was set at a fixed value */
885 if (!gui.menu_height_fixed)
886 {
887 Dimension space, border;
888
889 XtVaGetValues(menuBar,
890 XtNvSpace, &space,
891 XtNborderWidth, &border,
892 NULL);
893 gui.menu_height = max_height + 2 * (space + border);
894 }
895 }
896 }
897 /* Now, to simulate the window being resized. Only, this
898 * will resize the window to it's current state.
899 *
900 * There has to be a better way, but I do not see one at this time.
901 * (David Harrison)
902 */
903 {
904 Position w, h;
905
906 XtVaGetValues(vimShell,
907 XtNwidth, &w,
908 XtNheight, &h,
909 NULL);
910 gui_resize_shell(w, h
911 #ifdef FEAT_XIM
912 - xim_get_status_area_height()
913 #endif
914 );
915 }
916 gui_set_shellsize(FALSE, TRUE);
917 ui_new_shellsize();
918 if (oldpuller != None)
919 XFreePixmap(gui.dpy, oldpuller);
920 }
921
922 #if defined(FEAT_BEVAL) || defined(PROTO)
923 void
924 gui_mch_new_tooltip_font()
925 {
926 # ifdef FEAT_TOOLBAR
927 vimmenu_T *menu;
928
929 if (toolBar == (Widget)0)
930 return;
931
932 menu = gui_find_menu((char_u *)"ToolBar");
933 if (menu != NULL)
934 gui_mch_submenu_change(menu, FALSE);
935 # endif
936 }
937
938 void
939 gui_mch_new_tooltip_colors()
940 {
941 # ifdef FEAT_TOOLBAR
942 vimmenu_T *menu;
943
944 if (toolBar == (Widget)0)
945 return;
946
947 menu = gui_find_menu((char_u *)"ToolBar");
948 if (menu != NULL)
949 gui_mch_submenu_change(menu, TRUE);
950 # endif
951 }
952 #endif
953
954 static void
955 gui_mch_submenu_change(menu, colors)
956 vimmenu_T *menu;
957 int colors; /* TRUE for colors, FALSE for font */
958 {
959 vimmenu_T *mp;
960
961 for (mp = menu; mp != NULL; mp = mp->next)
962 {
963 if (mp->id != (Widget)0)
964 {
965 if (colors)
966 {
967 gui_athena_menu_colors(mp->id);
968 #ifdef FEAT_TOOLBAR
969 /* For a toolbar item: Free the pixmap and allocate a new one,
970 * so that the background color is right. */
971 if (mp->image != (Pixmap)0)
972 {
973 XFreePixmap(gui.dpy, mp->image);
974 get_toolbar_pixmap(mp, &mp->image, NULL);
975 if (mp->image != (Pixmap)0)
976 XtVaSetValues(mp->id, XtNbitmap, mp->image, NULL);
977 }
978
979 # ifdef FEAT_BEVAL
980 /* If we have a tooltip, then we need to change it's colors */
981 if (mp->tip != NULL)
982 {
983 Arg args[2];
984
985 args[0].name = XtNbackground;
986 args[0].value = gui.tooltip_bg_pixel;
987 args[1].name = XtNforeground;
988 args[1].value = gui.tooltip_fg_pixel;
989 XtSetValues(mp->tip->balloonLabel, &args[0], XtNumber(args));
990 }
991 # endif
992 #endif
993 }
994 else
995 {
996 gui_athena_menu_font(mp->id);
997 #ifdef FEAT_BEVAL
998 /* If we have a tooltip, then we need to change it's font */
999 /* Assume XtNinternational == True (in createBalloonEvalWindow)
1000 */
1001 if (mp->tip != NULL)
1002 {
1003 Arg args[1];
1004
1005 args[0].name = XtNfontSet;
1006 args[0].value = (XtArgVal)gui.tooltip_fontset;
1007 XtSetValues(mp->tip->balloonLabel, &args[0], XtNumber(args));
1008 }
1009 #endif
1010 }
1011 }
1012
1013 if (mp->children != NULL)
1014 {
1015 /* Set the colors/font for the tear off widget */
1016 if (mp->submenu_id != (Widget)0)
1017 {
1018 if (colors)
1019 gui_athena_menu_colors(mp->submenu_id);
1020 else
1021 gui_athena_menu_font(mp->submenu_id);
1022 }
1023 /* Set the colors for the children */
1024 gui_mch_submenu_change(mp->children, colors);
1025 }
1026 }
1027 }
1028
1029 /*
1030 * Make a submenu name into a pullright name.
1031 * Replace '.' by '_', can't include '.' in the submenu name.
1032 */
1033 static char_u *
1034 make_pull_name(name)
1035 char_u * name;
1036 {
1037 char_u *pname;
1038 char_u *p;
1039
1040 pname = vim_strnsave(name, STRLEN(name) + strlen("-pullright"));
1041 if (pname != NULL)
1042 {
1043 strcat((char *)pname, "-pullright");
1044 while ((p = vim_strchr(pname, '.')) != NULL)
1045 *p = '_';
1046 }
1047 return pname;
1048 }
1049
1050 /* ARGSUSED */
1051 void
1052 gui_mch_add_menu_item(menu, idx)
1053 vimmenu_T *menu;
1054 int idx;
1055 {
1056 vimmenu_T *parent = menu->parent;
1057
1058 a_cur_menu = menu;
1059 # ifdef FEAT_TOOLBAR
1060 if (menu_is_toolbar(parent->name))
1061 {
1062 WidgetClass type;
1063 int n;
1064 Arg args[21];
1065
1066 n = 0;
1067 if (menu_is_separator(menu->name))
1068 {
1069 XtSetArg(args[n], XtNlabel, ""); n++;
1070 XtSetArg(args[n], XtNborderWidth, 0); n++;
1071 }
1072 else
1073 {
1074 get_toolbar_pixmap(menu, &menu->image, NULL);
1075 XtSetArg(args[n], XtNlabel, menu->dname); n++;
1076 XtSetArg(args[n], XtNinternalHeight, 1); n++;
1077 XtSetArg(args[n], XtNinternalWidth, 1); n++;
1078 XtSetArg(args[n], XtNborderWidth, 1); n++;
1079 if (menu->image != 0)
1080 XtSetArg(args[n], XtNbitmap, menu->image); n++;
1081 }
1082 XtSetArg(args[n], XtNhighlightThickness, 0); n++;
1083 type = commandWidgetClass;
1084 /* TODO: figure out the position in the toolbar?
1085 * This currently works fine for the default toolbar, but
1086 * what if we add/remove items during later runtime?
1087 */
1088
1089 /* NOTE: "idx" isn't used here. The position is calculated by
1090 * athena_calculate_ins_pos(). The position it calculates
1091 * should be equal to "idx".
1092 */
1093 /* TODO: Could we just store "idx" and use that as the child
1094 * placement?
1095 */
1096
1097 if (menu->id == NULL)
1098 {
1099 menu->id = XtCreateManagedWidget((char *)menu->dname,
1100 type, toolBar, args, n);
1101 XtAddCallback(menu->id,
1102 XtNcallback, gui_x11_menu_cb, menu);
1103 }
1104 else
1105 XtSetValues(menu->id, args, n);
1106 gui_athena_menu_colors(menu->id);
1107
1108 #ifdef FEAT_BEVAL
1109 gui_mch_menu_set_tip(menu);
1110 #endif
1111
1112 menu->parent = parent;
1113 menu->submenu_id = NULL;
1114 if (!XtIsManaged(toolBar)
1115 && vim_strchr(p_go, GO_TOOLBAR) != NULL)
1116 gui_mch_show_toolbar(TRUE);
1117 gui.toolbar_height = gui_mch_compute_toolbar_height();
1118 return;
1119 } /* toolbar menu item */
1120 # endif
1121
1122 /* Add menu separator */
1123 if (menu_is_separator(menu->name))
1124 {
1125 menu->submenu_id = (Widget)0;
1126 menu->id = XtVaCreateManagedWidget((char *)menu->dname,
1127 smeLineObjectClass, parent->submenu_id,
1128 NULL);
1129 if (menu->id == (Widget)0)
1130 return;
1131 gui_athena_menu_colors(menu->id);
1132 }
1133 else
1134 {
1135 if (parent != NULL && parent->submenu_id != (Widget)0)
1136 {
1137 menu->submenu_id = (Widget)0;
1138 menu->id = XtVaCreateManagedWidget((char *)menu->dname,
1139 smeBSBObjectClass, parent->submenu_id,
1140 XtNlabel, menu->dname,
1141 #ifdef FONTSET_ALWAYS
1142 XtNinternational, True,
1143 #endif
1144 NULL);
1145 if (menu->id == (Widget)0)
1146 return;
1147
1148 /* If there are other "pulldown" items in this pane, then adjust
1149 * the right margin to accomodate the arrow pixmap, otherwise
1150 * the right margin will be the same as the left margin.
1151 */
1152 {
1153 Dimension left_margin;
1154
1155 XtVaGetValues(menu->id, XtNleftMargin, &left_margin, NULL);
1156 XtVaSetValues(menu->id, XtNrightMargin,
1157 gui_athena_menu_has_submenus(parent->submenu_id, NULL) ?
1158 puller_width :
1159 left_margin,
1160 NULL);
1161 }
1162
1163 gui_athena_menu_colors(menu->id);
1164 gui_athena_menu_font(menu->id);
1165 XtAddCallback(menu->id, XtNcallback, gui_x11_menu_cb,
1166 (XtPointer)menu);
1167 }
1168 }
1169 a_cur_menu = NULL;
1170 }
1171
1172 #if defined(FEAT_TOOLBAR) || defined(PROTO)
1173 void
1174 gui_mch_show_toolbar(int showit)
1175 {
1176 Cardinal numChildren; /* how many children toolBar has */
1177
1178 if (toolBar == (Widget)0)
1179 return;
1180 XtVaGetValues(toolBar, XtNnumChildren, &numChildren, NULL);
1181 if (showit && numChildren > 0)
1182 {
1183 /* Assume that we want to show the toolbar if p_toolbar contains valid
1184 * option settings, therefore p_toolbar must not be NULL.
1185 */
1186 WidgetList children;
1187
1188 XtVaGetValues(toolBar, XtNchildren, &children, NULL);
1189 {
1190 void (*action)(BalloonEval *);
1191 int text = 0;
1192
1193 if (strstr((const char *)p_toolbar, "tooltips"))
1194 action = &gui_mch_enable_beval_area;
1195 else
1196 action = &gui_mch_disable_beval_area;
1197 if (strstr((const char *)p_toolbar, "text"))
1198 text = 1;
1199 else if (strstr((const char *)p_toolbar, "icons"))
1200 text = -1;
1201 if (text != 0)
1202 {
1203 vimmenu_T *toolbar;
1204 vimmenu_T *cur;
1205
1206 for (toolbar = root_menu; toolbar; toolbar = toolbar->next)
1207 if (menu_is_toolbar(toolbar->dname))
1208 break;
1209 /* Assumption: toolbar is NULL if there is no toolbar,
1210 * otherwise it contains the toolbar menu structure.
1211 *
1212 * Assumption: "numChildren" == the number of items in the list
1213 * of items beginning with toolbar->children.
1214 */
1215 if (toolbar)
1216 {
1217 for (cur = toolbar->children; cur; cur = cur->next)
1218 {
1219 Arg args[2];
1220 int n = 0;
1221
1222 /* Enable/Disable tooltip (OK to enable while currently
1223 * enabled)
1224 */
1225 if (cur->tip != NULL)
1226 (*action)(cur->tip);
1227 if (text == 1)
1228 {
1229 XtSetArg(args[n], XtNbitmap, None);
1230 n++;
1231 XtSetArg(args[n], XtNlabel,
1232 menu_is_separator(cur->name) ? "" :
1233 (char *)cur->dname);
1234 n++;
1235 }
1236 else
1237 {
1238 XtSetArg(args[n], XtNbitmap, cur->image);
1239 n++;
1240 XtSetArg(args[n], XtNlabel, (cur->image == None) ?
1241 menu_is_separator(cur->name) ?
1242 "" :
1243 (char *)cur->dname
1244 :
1245 (char *)None);
1246 n++;
1247 }
1248 if (cur->id != NULL)
1249 {
1250 XtUnmanageChild(cur->id);
1251 XtSetValues(cur->id, args, n);
1252 XtManageChild(cur->id);
1253 }
1254 }
1255 }
1256 }
1257 }
1258 gui.toolbar_height = gui_mch_compute_toolbar_height();
1259 XtManageChild(toolBar);
1260 if (XtIsManaged(menuBar))
1261 {
1262 XtVaSetValues(textArea,
1263 XtNvertDistance, gui.toolbar_height + gui.menu_height,
1264 NULL);
1265 XtVaSetValues(toolBar,
1266 XtNvertDistance, gui.menu_height,
1267 NULL);
1268 }
1269 else
1270 {
1271 XtVaSetValues(textArea,
1272 XtNvertDistance, gui.toolbar_height,
1273 NULL);
1274 XtVaSetValues(toolBar,
1275 XtNvertDistance, 0,
1276 NULL);
1277 }
1278 }
1279 else
1280 {
1281 gui.toolbar_height = 0;
1282 if (XtIsManaged(menuBar))
1283 XtVaSetValues(textArea,
1284 XtNvertDistance, gui.menu_height,
1285 NULL);
1286 else
1287 XtVaSetValues(textArea,
1288 XtNvertDistance, 0,
1289 NULL);
1290
1291 XtUnmanageChild(toolBar);
1292 }
1293 gui_set_shellsize(FALSE, FALSE);
1294 }
1295
1296
1297 int
1298 gui_mch_compute_toolbar_height()
1299 {
1300 Dimension height; /* total Toolbar height */
1301 Dimension whgt; /* height of each widget */
1302 Dimension marginHeight; /* XmNmarginHeight of toolBar */
1303 Dimension shadowThickness; /* thickness of Xtparent(toolBar) */
1304 WidgetList children; /* list of toolBar's children */
1305 Cardinal numChildren; /* how many children toolBar has */
1306 int i;
1307
1308 height = 0;
1309 shadowThickness = 0;
1310 marginHeight = 0;
1311 if (toolBar != (Widget)0)
1312 {
1313 XtVaGetValues(toolBar,
1314 XtNborderWidth, &shadowThickness,
1315 XtNvSpace, &marginHeight,
1316 XtNchildren, &children,
1317 XtNnumChildren, &numChildren,
1318 NULL);
1319 for (i = 0; i < numChildren; i++)
1320 {
1321 whgt = 0;
1322
1323 XtVaGetValues(children[i], XtNheight, &whgt, NULL);
1324 if (height < whgt)
1325 height = whgt;
1326 }
1327 }
1328
1329 return (int)(height + (marginHeight << 1) + (shadowThickness << 1));
1330 }
1331
1332 void
1333 gui_mch_get_toolbar_colors(bgp, fgp, bsp, tsp, hsp)
1334 Pixel *bgp;
1335 Pixel *fgp;
1336 Pixel *bsp;
1337 Pixel *tsp;
1338 Pixel *hsp;
1339 {
1340 XtVaGetValues(toolBar, XtNbackground, bgp, XtNborderColor, fgp, NULL);
1341 *bsp = *bgp;
1342 *tsp = *fgp;
1343 *hsp = *tsp;
1344 }
1345 #endif
1346
1347
1348 /* ARGSUSED */
1349 void
1350 gui_mch_toggle_tearoffs(enable)
1351 int enable;
1352 {
1353 /* no tearoff menus */
1354 }
1355
1356 void
1357 gui_mch_new_menu_colors()
1358 {
1359 if (menuBar == (Widget)0)
1360 return;
1361 if (gui.menu_fg_pixel != INVALCOLOR)
1362 XtVaSetValues(menuBar, XtNborderColor, gui.menu_fg_pixel, NULL);
1363 gui_athena_menu_colors(menuBar);
1364 #ifdef FEAT_TOOLBAR
1365 gui_athena_menu_colors(toolBar);
1366 #endif
1367
1368 gui_mch_submenu_change(root_menu, TRUE);
1369 }
1370
1371 /*
1372 * Destroy the machine specific menu widget.
1373 */
1374 void
1375 gui_mch_destroy_menu(menu)
1376 vimmenu_T *menu;
1377 {
1378 Widget parent;
1379
1380 /* There is no item for the toolbar. */
1381 if (menu->id == (Widget)0)
1382 return;
1383
1384 parent = XtParent(menu->id);
1385
1386 /* When removing the last "pulldown" menu item from a pane, adjust the
1387 * right margins of the remaining widgets.
1388 */
1389 if (menu->submenu_id != (Widget)0)
1390 {
1391 /* Go through the menu items in the parent of this item and
1392 * adjust their margins, if necessary.
1393 * This takes care of the case when we delete the last menu item in a
1394 * pane that has a submenu. In this case, there will be no arrow
1395 * pixmaps shown anymore.
1396 */
1397 {
1398 WidgetList children;
1399 Cardinal num_children;
1400 int i;
1401 Dimension right_margin = 0;
1402 Boolean get_left_margin = False;
1403
1404 XtVaGetValues(parent, XtNchildren, &children,
1405 XtNnumChildren, &num_children,
1406 NULL);
1407 if (gui_athena_menu_has_submenus(parent, menu->id))
1408 right_margin = puller_width;
1409 else
1410 get_left_margin = True;
1411
1412 for (i = 0; i < num_children; ++i)
1413 {
1414 if (children[i] == menu->id)
1415 continue;
1416 if (get_left_margin == True)
1417 {
1418 Dimension left_margin;
1419
1420 XtVaGetValues(children[i], XtNleftMargin, &left_margin,
1421 NULL);
1422 XtVaSetValues(children[i], XtNrightMargin, left_margin,
1423 NULL);
1424 }
1425 else
1426 XtVaSetValues(children[i], XtNrightMargin, right_margin,
1427 NULL);
1428 }
1429 }
1430 }
1431 /* Please be sure to destroy the parent widget first (i.e. menu->id).
1432 *
1433 * This code should be basically identical to that in the file gui_motif.c
1434 * because they are both Xt based.
1435 */
1436 if (menu->id != (Widget)0)
1437 {
1438 Cardinal num_children;
1439 Dimension height, space, border;
1440
1441 XtVaGetValues(menuBar,
1442 XtNvSpace, &space,
1443 XtNborderWidth, &border,
1444 NULL);
1445 XtVaGetValues(menu->id,
1446 XtNheight, &height,
1447 NULL);
1448 #if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL)
1449 if (parent == toolBar && menu->tip != NULL)
1450 {
1451 /* We try to destroy this before the actual menu, because there are
1452 * callbacks, etc. that will be unregistered during the tooltip
1453 * destruction.
1454 *
1455 * If you call "gui_mch_destroy_beval_area()" after destroying
1456 * menu->id, then the tooltip's window will have already been
1457 * deallocated by Xt, and unknown behaviour will ensue (probably
1458 * a core dump).
1459 */
1460 gui_mch_destroy_beval_area(menu->tip);
1461 menu->tip = NULL;
1462 }
1463 #endif
1464 /*
1465 * This is a hack to stop the Athena simpleMenuWidget from getting a
1466 * BadValue error when a menu's last child is destroyed. We check to
1467 * see if this is the last child and if so, don't delete it. The parent
1468 * will be deleted soon anyway, and it will delete it's children like
1469 * all good widgets do.
1470 */
1471 /* NOTE: The cause of the BadValue X Protocol Error is because when the
1472 * last child is destroyed, it is first unmanaged, thus causing a
1473 * geometry resize request from the parent Shell widget.
1474 * Since the Shell widget has no more children, it is resized to have
1475 * width/height of 0. XConfigureWindow() is then called with the
1476 * width/height of 0, which generates the BadValue.
1477 *
1478 * This happens in phase two of the widget destruction process.
1479 */
1480 {
1481 if (parent != menuBar
1482 #ifdef FEAT_TOOLBAR
1483 && parent != toolBar
1484 #endif
1485 )
1486 {
1487 XtVaGetValues(parent, XtNnumChildren, &num_children, NULL);
1488 if (num_children > 1)
1489 XtDestroyWidget(menu->id);
1490 }
1491 else
1492 XtDestroyWidget(menu->id);
1493 menu->id = (Widget)0;
1494 }
1495
1496 if (parent == menuBar)
1497 {
1498 if (!gui.menu_height_fixed)
1499 gui.menu_height = height + 2 * (space + border);
1500 }
1501 #ifdef FEAT_TOOLBAR
1502 else if (parent == toolBar)
1503 {
1504 /* When removing last toolbar item, don't display the toolbar. */
1505 XtVaGetValues(toolBar, XtNnumChildren, &num_children, NULL);
1506 if (num_children == 0)
1507 gui_mch_show_toolbar(FALSE);
1508 else
1509 gui.toolbar_height = gui_mch_compute_toolbar_height();
1510 }
1511 #endif
1512 }
1513 if (menu->submenu_id != (Widget)0)
1514 {
1515 XtDestroyWidget(menu->submenu_id);
1516 menu->submenu_id = (Widget)0;
1517 }
1518 }
1519
1520 /*ARGSUSED*/
1521 static void
1522 gui_athena_menu_timeout(client_data, id)
1523 XtPointer client_data;
1524 XtIntervalId *id;
1525 {
1526 Widget w = (Widget)client_data;
1527 Widget popup;
1528
1529 timer = 0;
1530 if (XtIsSubclass(w,smeBSBObjectClass))
1531 {
1532 Pixmap p;
1533
1534 XtVaGetValues(w, XtNrightBitmap, &p, NULL);
1535 if ((p != None) && (p != XtUnspecifiedPixmap))
1536 {
1537 /* We are dealing with an item that has a submenu */
1538 popup = get_popup_entry(XtParent(w));
1539 if (popup == (Widget)0)
1540 return;
1541 XtPopup(popup, XtGrabNonexclusive);
1542 }
1543 }
1544 }
1545
1546 /* This routine is used to calculate the position (in screen coordinates)
1547 * where a submenu should appear relative to the menu entry that popped it
1548 * up. It should appear even with and just slightly to the left of the
1549 * rightmost end of the menu entry that caused the popup.
1550 *
1551 * This is called when XtPopup() is called.
1552 */
1553 /*ARGSUSED*/
1554 static void
1555 gui_athena_popup_callback(w, client_data, call_data)
1556 Widget w;
1557 XtPointer client_data;
1558 XtPointer call_data;
1559 {
1560 /* Assumption: XtIsSubclass(XtParent(w),simpleMenuWidgetClass) */
1561 vimmenu_T *menu = (vimmenu_T *)client_data;
1562 Dimension width;
1563 Position root_x, root_y;
1564
1565 /* First, popdown any siblings that may have menus popped up */
1566 {
1567 vimmenu_T *i;
1568
1569 for (i = menu->parent->children; i != NULL; i = i->next)
1570 {
1571 if (i->submenu_id != NULL && XtIsManaged(i->submenu_id))
1572 XtPopdown(i->submenu_id);
1573 }
1574 }
1575 XtVaGetValues(XtParent(w),
1576 XtNwidth, &width,
1577 NULL);
1578 /* Assumption: XawSimpleMenuGetActiveEntry(XtParent(w)) == menu->id */
1579 /* i.e. This IS the active entry */
1580 XtTranslateCoords(menu->id,width - 5, 0, &root_x, &root_y);
1581 XtVaSetValues(w, XtNx, root_x,
1582 XtNy, root_y,
1583 NULL);
1584 }
1585
1586 /* ARGSUSED */
1587 static void
1588 gui_athena_popdown_submenus_action(w, event, args, nargs)
1589 Widget w;
1590 XEvent *event;
1591 String *args;
1592 Cardinal *nargs;
1593 {
1594 WidgetList children;
1595 Cardinal num_children;
1596
1597 XtVaGetValues(w, XtNchildren, &children,
1598 XtNnumChildren, &num_children,
1599 NULL);
1600 for (; num_children > 0; --num_children)
1601 {
1602 Widget child = children[num_children - 1];
1603
1604 if (has_submenu(child))
1605 {
1606 Widget temp_w;
1607
1608 temp_w = submenu_widget(child);
1609 gui_athena_popdown_submenus_action(temp_w,event,args,nargs);
1610 XtPopdown(temp_w);
1611 }
1612 }
1613 }
1614
1615 /* Used to determine if the given widget has a submenu that can be popped up. */
1616 static Boolean
1617 has_submenu(widget)
1618 Widget widget;
1619 {
1620 if ((widget != NULL) && XtIsSubclass(widget,smeBSBObjectClass))
1621 {
1622 Pixmap p;
1623
1624 XtVaGetValues(widget, XtNrightBitmap, &p, NULL);
1625 if ((p != None) && (p != XtUnspecifiedPixmap))
1626 return True;
1627 }
1628 return False;
1629 }
1630
1631 /* ARGSUSED */
1632 static void
1633 gui_athena_delayed_arm_action(w, event, args, nargs)
1634 Widget w;
1635 XEvent *event;
1636 String *args;
1637 Cardinal *nargs;
1638 {
1639 Dimension width, height;
1640
1641 if (event->type != MotionNotify)
1642 return;
1643
1644 XtVaGetValues(w,
1645 XtNwidth, &width,
1646 XtNheight, &height,
1647 NULL);
1648
1649 if (event->xmotion.x >= (int)width || event->xmotion.y >= (int)height)
1650 return;
1651
1652 {
1653 static Widget previous_active_widget = NULL;
1654 Widget current;
1655
1656 current = XawSimpleMenuGetActiveEntry(w);
1657 if (current != previous_active_widget)
1658 {
1659 if (timer)
1660 {
1661 /* If the timeout hasn't been triggered, remove it */
1662 XtRemoveTimeOut(timer);
1663 }
1664 gui_athena_popdown_submenus_action(w,event,args,nargs);
1665 if (has_submenu(current))
1666 {
1667 XtAppAddTimeOut(XtWidgetToApplicationContext(w), 600L,
1668 gui_athena_menu_timeout,
1669 (XtPointer)current);
1670 }
1671 previous_active_widget = current;
1672 }
1673 }
1674 }
1675
1676 static Widget
1677 get_popup_entry(w)
1678 Widget w;
1679 {
1680 Widget menuw;
1681
1682 /* Get the active entry for the current menu */
1683 if ((menuw = XawSimpleMenuGetActiveEntry(w)) == (Widget)0)
1684 return NULL;
1685
1686 return submenu_widget(menuw);
1687 }
1688
1689 /* Given the widget that has been determined to have a submenu, return the submenu widget
1690 * that is to be popped up.
1691 */
1692 static Widget
1693 submenu_widget(widget)
1694 Widget widget;
1695 {
1696 /* Precondition: has_submenu(widget) == True
1697 * XtIsSubclass(XtParent(widget),simpleMenuWidgetClass) == True
1698 */
1699
1700 char_u *pullright_name;
1701 Widget popup;
1702
1703 pullright_name = make_pull_name((char_u *)XtName(widget));
1704 popup = XtNameToWidget(XtParent(widget), (char *)pullright_name);
1705 vim_free(pullright_name);
1706
1707 return popup;
1708 /* Postcondition: (popup != NULL) implies
1709 * (XtIsSubclass(popup,simpleMenuWidgetClass) == True) */
1710 }
1711
1712 /* ARGSUSED */
1713 void
1714 gui_mch_show_popupmenu(menu)
1715 vimmenu_T *menu;
1716 {
1717 int rootx, rooty, winx, winy;
1718 Window root, child;
1719 unsigned int mask;
1720
1721 if (menu->submenu_id == (Widget)0)
1722 return;
1723
1724 /* Position the popup menu at the pointer */
1725 if (XQueryPointer(gui.dpy, XtWindow(vimShell), &root, &child,
1726 &rootx, &rooty, &winx, &winy, &mask))
1727 {
1728 rootx -= 30;
1729 if (rootx < 0)
1730 rootx = 0;
1731 rooty -= 5;
1732 if (rooty < 0)
1733 rooty = 0;
1734 XtVaSetValues(menu->submenu_id,
1735 XtNx, rootx,
1736 XtNy, rooty,
1737 NULL);
1738 }
1739
1740 XtOverrideTranslations(menu->submenu_id, popupTrans);
1741 XtPopupSpringLoaded(menu->submenu_id);
1742 }
1743
1744 #endif /* FEAT_MENU */
1745
1746 /*
1747 * Set the menu and scrollbar colors to their default values.
1748 */
1749 void
1750 gui_mch_def_colors()
1751 {
1752 /*
1753 * Get the colors ourselves. Using the automatic conversion doesn't
1754 * handle looking for approximate colors.
1755 */
1756 if (gui.in_use)
1757 {
1758 gui.menu_fg_pixel = gui_get_color((char_u *)gui.rsrc_menu_fg_name);
1759 gui.menu_bg_pixel = gui_get_color((char_u *)gui.rsrc_menu_bg_name);
1760 gui.scroll_fg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_fg_name);
1761 gui.scroll_bg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_bg_name);
1762 #ifdef FEAT_BEVAL
1763 gui.tooltip_fg_pixel = gui_get_color((char_u *)gui.rsrc_tooltip_fg_name);
1764 gui.tooltip_bg_pixel = gui_get_color((char_u *)gui.rsrc_tooltip_bg_name);
1765 #endif
1766 }
1767 }
1768
1769
1770 /*
1771 * Scrollbar stuff.
1772 */
1773
1774 void
1775 gui_mch_set_scrollbar_thumb(sb, val, size, max)
1776 scrollbar_T *sb;
1777 long val;
1778 long size;
1779 long max;
1780 {
1781 double v, s;
1782
1783 if (sb->id == (Widget)0)
1784 return;
1785
1786 /*
1787 * Athena scrollbar must go from 0.0 to 1.0.
1788 */
1789 if (max == 0)
1790 {
1791 /* So you can't scroll it at all (normally it scrolls past end) */
1792 #ifdef FEAT_GUI_NEXTAW
1793 XawScrollbarSetThumb(sb->id, 0.0, 1.0);
1794 #else
1795 vim_XawScrollbarSetThumb(sb->id, 0.0, 1.0, 0.0);
1796 #endif
1797 }
1798 else
1799 {
1800 v = (double)val / (double)(max + 1);
1801 s = (double)size / (double)(max + 1);
1802 #ifdef FEAT_GUI_NEXTAW
1803 XawScrollbarSetThumb(sb->id, v, s);
1804 #else
1805 vim_XawScrollbarSetThumb(sb->id, v, s, 1.0);
1806 #endif
1807 }
1808 }
1809
1810 void
1811 gui_mch_set_scrollbar_pos(sb, x, y, w, h)
1812 scrollbar_T *sb;
1813 int x;
1814 int y;
1815 int w;
1816 int h;
1817 {
1818 if (sb->id == (Widget)0)
1819 return;
1820
1821 XtUnmanageChild(sb->id);
1822 XtVaSetValues(sb->id,
1823 XtNhorizDistance, x,
1824 XtNvertDistance, y,
1825 XtNwidth, w,
1826 XtNheight, h,
1827 NULL);
1828 XtManageChild(sb->id);
1829 }
1830
1831 void
1832 gui_mch_enable_scrollbar(sb, flag)
1833 scrollbar_T *sb;
1834 int flag;
1835 {
1836 if (sb->id != (Widget)0)
1837 {
1838 if (flag)
1839 XtManageChild(sb->id);
1840 else
1841 XtUnmanageChild(sb->id);
1842 }
1843 }
1844
1845 void
1846 gui_mch_create_scrollbar(sb, orient)
1847 scrollbar_T *sb;
1848 int orient; /* SBAR_VERT or SBAR_HORIZ */
1849 {
1850 sb->id = XtVaCreateWidget("scrollBar",
1851 #ifdef FEAT_GUI_NEXTAW
1852 scrollbarWidgetClass, vimForm,
1853 #else
1854 vim_scrollbarWidgetClass, vimForm,
1855 #endif
1856 XtNresizable, True,
1857 XtNtop, XtChainTop,
1858 XtNbottom, XtChainTop,
1859 XtNleft, XtChainLeft,
1860 XtNright, XtChainLeft,
1861 XtNborderWidth, 0,
1862 XtNorientation, (orient == SBAR_VERT) ? XtorientVertical
1863 : XtorientHorizontal,
1864 XtNforeground, gui.scroll_fg_pixel,
1865 XtNbackground, gui.scroll_bg_pixel,
1866 NULL);
1867 if (sb->id == (Widget)0)
1868 return;
1869
1870 XtAddCallback(sb->id, XtNjumpProc,
1871 gui_athena_scroll_cb_jump, (XtPointer)sb->ident);
1872 XtAddCallback(sb->id, XtNscrollProc,
1873 gui_athena_scroll_cb_scroll, (XtPointer)sb->ident);
1874
1875 #ifdef FEAT_GUI_NEXTAW
1876 XawScrollbarSetThumb(sb->id, 0.0, 1.0);
1877 #else
1878 vim_XawScrollbarSetThumb(sb->id, 0.0, 1.0, 0.0);
1879 #endif
1880 }
1881
1882 #if defined(FEAT_WINDOWS) || defined(PROTO)
1883 void
1884 gui_mch_destroy_scrollbar(sb)
1885 scrollbar_T *sb;
1886 {
1887 if (sb->id != (Widget)0)
1888 XtDestroyWidget(sb->id);
1889 }
1890 #endif
1891
1892 void
1893 gui_mch_set_scrollbar_colors(sb)
1894 scrollbar_T *sb;
1895 {
1896 if (sb->id != (Widget)0)
1897 XtVaSetValues(sb->id,
1898 XtNforeground, gui.scroll_fg_pixel,
1899 XtNbackground, gui.scroll_bg_pixel,
1900 NULL);
1901
1902 /* This is needed for the rectangle below the vertical scrollbars. */
1903 if (sb == &gui.bottom_sbar && vimForm != (Widget)0)
1904 gui_athena_scroll_colors(vimForm);
1905 }
1906
1907 /*
1908 * Miscellaneous stuff:
1909 */
1910 Window
1911 gui_x11_get_wid()
1912 {
1913 return XtWindow(textArea);
1914 }
1915
1916 #if defined(FEAT_BROWSE) || defined(PROTO)
1917 /*
1918 * Put up a file requester.
1919 * Returns the selected name in allocated memory, or NULL for Cancel.
1920 */
1921 /* ARGSUSED */
1922 char_u *
1923 gui_mch_browse(saving, title, dflt, ext, initdir, filter)
1924 int saving; /* select file to write */
1925 char_u *title; /* not used (title for the window) */
1926 char_u *dflt; /* not used (default name) */
1927 char_u *ext; /* not used (extension added) */
1928 char_u *initdir; /* initial directory, NULL for current dir */
1929 char_u *filter; /* not used (file name filter) */
1930 {
1931 Position x, y;
1932 char_u dirbuf[MAXPATHL];
1933
1934 /* Concatenate "initdir" and "dflt". */
1935 if (initdir == NULL || *initdir == NUL)
1936 mch_dirname(dirbuf, MAXPATHL);
1937 else if (STRLEN(initdir) + 2 < MAXPATHL)
1938 STRCPY(dirbuf, initdir);
1939 else
1940 dirbuf[0] = NUL;
1941 if (dflt != NULL && *dflt != NUL
1942 && STRLEN(dirbuf) + 2 + STRLEN(dflt) < MAXPATHL)
1943 {
1944 add_pathsep(dirbuf);
1945 STRCAT(dirbuf, dflt);
1946 }
1947
1948 /* Position the file selector just below the menubar */
1949 XtTranslateCoords(vimShell, (Position)0, (Position)
1950 #ifdef FEAT_MENU
1951 gui.menu_height
1952 #else
1953 0
1954 #endif
1955 , &x, &y);
1956 return (char_u *)vim_SelFile(vimShell, (char *)title, (char *)dirbuf,
1957 NULL, (int)x, (int)y, gui.menu_fg_pixel, gui.menu_bg_pixel,
1958 gui.scroll_fg_pixel, gui.scroll_bg_pixel);
1959 }
1960 #endif
1961
1962 #if defined(FEAT_GUI_DIALOG) || defined(PROTO)
1963
1964 static int dialogStatus;
1965 static Atom dialogatom;
1966
1967 static void keyhit_callback __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *cont));
1968 static void butproc __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
1969 static void dialog_wm_handler __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *dum));
1970
1971 /*
1972 * Callback function for the textfield. When CR is hit this works like
1973 * hitting the "OK" button, ESC like "Cancel".
1974 */
1975 /* ARGSUSED */
1976 static void
1977 keyhit_callback(w, client_data, event, cont)
1978 Widget w;
1979 XtPointer client_data;
1980 XEvent *event;
1981 Boolean *cont;
1982 {
1983 char buf[2];
1984
1985 if (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1)
1986 {
1987 if (*buf == CAR)
1988 dialogStatus = 1;
1989 else if (*buf == ESC)
1990 dialogStatus = 0;
1991 }
1992 }
1993
1994 /* ARGSUSED */
1995 static void
1996 butproc(w, client_data, call_data)
1997 Widget w;
1998 XtPointer client_data;
1999 XtPointer call_data;
2000 {
2001 dialogStatus = (int)(long)client_data + 1;
2002 }
2003
2004 /*
2005 * Function called when dialog window closed.
2006 */
2007 /*ARGSUSED*/
2008 static void
2009 dialog_wm_handler(w, client_data, event, dum)
2010 Widget w;
2011 XtPointer client_data;
2012 XEvent *event;
2013 Boolean *dum;
2014 {
2015 if (event->type == ClientMessage
2016 && ((XClientMessageEvent *)event)->data.l[0] == dialogatom)
2017 dialogStatus = 0;
2018 }
2019
2020 /* ARGSUSED */
2021 int
2022 gui_mch_dialog(type, title, message, buttons, dfltbutton, textfield)
2023 int type;
2024 char_u *title;
2025 char_u *message;
2026 char_u *buttons;
2027 int dfltbutton;
2028 char_u *textfield;
2029 {
2030 char_u *buts;
2031 char_u *p, *next;
2032 XtAppContext app;
2033 XEvent event;
2034 Position wd, hd;
2035 Position wv, hv;
2036 Position x, y;
2037 Widget dialog;
2038 Widget dialogshell;
2039 Widget dialogmessage;
2040 Widget dialogtextfield = 0;
2041 Widget dialogButton;
2042 Widget prev_dialogButton = NULL;
2043 int butcount;
2044 int vertical;
2045
2046 if (title == NULL)
2047 title = (char_u *)_("Vim dialog");
2048 dialogStatus = -1;
2049
2050 /* if our pointer is currently hidden, then we should show it. */
2051 gui_mch_mousehide(FALSE);
2052
2053 /* Check 'v' flag in 'guioptions': vertical button placement. */
2054 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
2055
2056 /* The shell is created each time, to make sure it is resized properly */
2057 dialogshell = XtVaCreatePopupShell("dialogShell",
2058 transientShellWidgetClass, vimShell,
2059 XtNtitle, title,
2060 NULL);
2061 if (dialogshell == (Widget)0)
2062 goto error;
2063
2064 dialog = XtVaCreateManagedWidget("dialog",
2065 formWidgetClass, dialogshell,
2066 XtNdefaultDistance, 20,
2067 NULL);
2068 if (dialog == (Widget)0)
2069 goto error;
2070 gui_athena_menu_colors(dialog);
2071 dialogmessage = XtVaCreateManagedWidget("dialogMessage",
2072 labelWidgetClass, dialog,
2073 XtNlabel, message,
2074 XtNtop, XtChainTop,
2075 XtNbottom, XtChainTop,
2076 XtNleft, XtChainLeft,
2077 XtNright, XtChainLeft,
2078 XtNresizable, True,
2079 XtNborderWidth, 0,
2080 NULL);
2081 gui_athena_menu_colors(dialogmessage);
2082
2083 if (textfield != NULL)
2084 {
2085 dialogtextfield = XtVaCreateManagedWidget("textfield",
2086 asciiTextWidgetClass, dialog,
2087 XtNwidth, 400,
2088 XtNtop, XtChainTop,
2089 XtNbottom, XtChainTop,
2090 XtNleft, XtChainLeft,
2091 XtNright, XtChainRight,
2092 XtNfromVert, dialogmessage,
2093 XtNresizable, True,
2094 XtNstring, textfield,
2095 XtNlength, IOSIZE,
2096 XtNuseStringInPlace, True,
2097 XtNeditType, XawtextEdit,
2098 XtNwrap, XawtextWrapNever,
2099 XtNresize, XawtextResizeHeight,
2100 NULL);
2101 XtManageChild(dialogtextfield);
2102 XtAddEventHandler(dialogtextfield, KeyPressMask, False,
2103 (XtEventHandler)keyhit_callback, (XtPointer)NULL);
2104 XawTextSetInsertionPoint(dialogtextfield,
2105 (XawTextPosition)STRLEN(textfield));
2106 XtSetKeyboardFocus(dialog, dialogtextfield);
2107 }
2108
2109 /* make a copy, so that we can insert NULs */
2110 buts = vim_strsave(buttons);
2111 if (buts == NULL)
2112 return -1;
2113
2114 p = buts;
2115 for (butcount = 0; *p; ++butcount)
2116 {
2117 for (next = p; *next; ++next)
2118 {
2119 if (*next == DLG_HOTKEY_CHAR)
2120 mch_memmove(next, next + 1, STRLEN(next));
2121 if (*next == DLG_BUTTON_SEP)
2122 {
2123 *next++ = NUL;
2124 break;
2125 }
2126 }
2127 dialogButton = XtVaCreateManagedWidget("button",
2128 commandWidgetClass, dialog,
2129 XtNlabel, p,
2130 XtNtop, XtChainBottom,
2131 XtNbottom, XtChainBottom,
2132 XtNleft, XtChainLeft,
2133 XtNright, XtChainLeft,
2134 XtNfromVert, textfield == NULL ? dialogmessage : dialogtextfield,
2135 XtNvertDistance, vertical ? 4 : 20,
2136 XtNresizable, False,
2137 NULL);
2138 gui_athena_menu_colors(dialogButton);
2139 if (butcount > 0)
2140 XtVaSetValues(dialogButton,
2141 vertical ? XtNfromVert : XtNfromHoriz, prev_dialogButton,
2142 NULL);
2143
2144 XtAddCallback(dialogButton, XtNcallback, butproc, (XtPointer)butcount);
2145 p = next;
2146 prev_dialogButton = dialogButton;
2147 }
2148 vim_free(buts);
2149
2150 XtRealizeWidget(dialogshell);
2151
2152 /* Setup for catching the close-window event, don't let it close Vim! */
2153 dialogatom = XInternAtom(gui.dpy, "WM_DELETE_WINDOW", False);
2154 XSetWMProtocols(gui.dpy, XtWindow(dialogshell), &dialogatom, 1);
2155 XtAddEventHandler(dialogshell, NoEventMask, True, dialog_wm_handler, NULL);
2156
2157 XtVaGetValues(dialogshell,
2158 XtNwidth, &wd,
2159 XtNheight, &hd,
2160 NULL);
2161 XtVaGetValues(vimShell,
2162 XtNwidth, &wv,
2163 XtNheight, &hv,
2164 NULL);
2165 XtTranslateCoords(vimShell,
2166 (Position)((wv - wd) / 2),
2167 (Position)((hv - hd) / 2),
2168 &x, &y);
2169 if (x < 0)
2170 x = 0;
2171 if (y < 0)
2172 y = 0;
2173 XtVaSetValues(dialogshell, XtNx, x, XtNy, y, NULL);
2174
2175 /* Position the mouse pointer in the dialog, required for when focus
2176 * follows mouse. */
2177 XWarpPointer(gui.dpy, (Window)0, XtWindow(dialogshell), 0, 0, 0, 0, 20, 40);
2178
2179
2180 app = XtWidgetToApplicationContext(dialogshell);
2181
2182 XtPopup(dialogshell, XtGrabNonexclusive);
2183
2184 while (1)
2185 {
2186 XtAppNextEvent(app, &event);
2187 XtDispatchEvent(&event);
2188 if (dialogStatus >= 0)
2189 break;
2190 }
2191
2192 XtPopdown(dialogshell);
2193
2194 if (textfield != NULL && dialogStatus < 0)
2195 *textfield = NUL;
2196
2197 error:
2198 XtDestroyWidget(dialogshell);
2199
2200 return dialogStatus;
2201 }
2202 #endif
2203
2204 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_MENU)
2205 /*
2206 * Set the colors of Widget "id" to the menu colors.
2207 */
2208 static void
2209 gui_athena_menu_colors(id)
2210 Widget id;
2211 {
2212 if (gui.menu_bg_pixel != INVALCOLOR)
2213 XtVaSetValues(id, XtNbackground, gui.menu_bg_pixel, NULL);
2214 if (gui.menu_fg_pixel != INVALCOLOR)
2215 XtVaSetValues(id, XtNforeground, gui.menu_fg_pixel, NULL);
2216 }
2217 #endif
2218
2219 /*
2220 * Set the colors of Widget "id" to the scroll colors.
2221 */
2222 static void
2223 gui_athena_scroll_colors(id)
2224 Widget id;
2225 {
2226 if (gui.scroll_bg_pixel != INVALCOLOR)
2227 XtVaSetValues(id, XtNbackground, gui.scroll_bg_pixel, NULL);
2228 if (gui.scroll_fg_pixel != INVALCOLOR)
2229 XtVaSetValues(id, XtNforeground, gui.scroll_fg_pixel, NULL);
2230 }