xref: /vim-8.2.3635/src/gui_motif.c (revision 2bf24176)
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  *
6  * Do ":help uganda"  in Vim to read copying and usage conditions.
7  * Do ":help credits" in Vim to see a list of people who contributed.
8  * See README.txt for an overview of the Vim source code.
9  */
10 
11 #include <Xm/Form.h>
12 #include <Xm/RowColumn.h>
13 #include <Xm/PushB.h>
14 #include <Xm/Text.h>
15 #include <Xm/TextF.h>
16 #include <Xm/Separator.h>
17 #include <Xm/Label.h>
18 #include <Xm/CascadeB.h>
19 #include <Xm/ScrollBar.h>
20 #include <Xm/MenuShell.h>
21 #include <Xm/DrawingA.h>
22 #if (XmVersion >= 1002)
23 # include <Xm/RepType.h>
24 #endif
25 #include <Xm/Frame.h>
26 #include <Xm/LabelG.h>
27 #include <Xm/ToggleBG.h>
28 #include <Xm/SeparatoG.h>
29 #include <Xm/XmP.h>
30 
31 #include <X11/keysym.h>
32 #include <X11/Xatom.h>
33 #include <X11/StringDefs.h>
34 #include <X11/Intrinsic.h>
35 
36 #include "vim.h"
37 
38 #ifdef HAVE_X11_XPM_H
39 # include <X11/xpm.h>
40 #else
41 # ifdef HAVE_XM_XPMP_H
42 #  include <Xm/XpmP.h>
43 # endif
44 #endif
45 #ifdef HAVE_XM_NOTEBOOK_H
46 # include <Xm/Notebook.h>
47 #endif
48 
49 #include "gui_xmebw.h"	/* for our Enhanced Button Widget */
50 
51 #if defined(FEAT_GUI_DIALOG) && defined(HAVE_XPM)
52 # include "../pixmaps/alert.xpm"
53 # include "../pixmaps/error.xpm"
54 # include "../pixmaps/generic.xpm"
55 # include "../pixmaps/info.xpm"
56 # include "../pixmaps/quest.xpm"
57 #endif
58 
59 #define MOTIF_POPUP
60 
61 extern Widget vimShell;
62 
63 static Widget vimForm;
64 static Widget textAreaForm;
65 Widget textArea;
66 #ifdef FEAT_TOOLBAR
67 static Widget toolBarFrame;
68 static Widget toolBar;
69 #endif
70 #ifdef FEAT_GUI_TABLINE
71 static Widget	tabLine;
72 static Widget	tabLine_menu = 0;
73 static int	showing_tabline = 0;
74 #endif
75 #ifdef FEAT_FOOTER
76 static Widget footer;
77 #endif
78 #ifdef FEAT_MENU
79 # if (XmVersion >= 1002)
80 /* remember the last set value for the tearoff item */
81 static int tearoff_val = (int)XmTEAR_OFF_ENABLED;
82 # endif
83 static Widget menuBar;
84 #endif
85 
86 static void scroll_cb __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
87 #ifdef FEAT_GUI_TABLINE
88 static void tabline_cb __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
89 static void tabline_button_cb __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
90 static void tabline_menu_cb __ARGS((Widget w, XtPointer	closure, XEvent	*e, Boolean *continue_dispatch));
91 static void tabline_balloon_cb __ARGS((BalloonEval *beval, int state));
92 #endif
93 #ifdef FEAT_TOOLBAR
94 # ifdef FEAT_FOOTER
95 static void toolbarbutton_enter_cb __ARGS((Widget, XtPointer, XEvent *, Boolean *));
96 static void toolbarbutton_leave_cb __ARGS((Widget, XtPointer, XEvent *, Boolean *));
97 # endif
98 static void reset_focus __ARGS((void));
99 #endif
100 #ifdef FEAT_FOOTER
101 static int gui_mch_compute_footer_height __ARGS((void));
102 #endif
103 #ifdef WSDEBUG
104 static void attachDump(Widget, char *);
105 #endif
106 
107 static void gui_motif_menu_colors __ARGS((Widget id));
108 static void gui_motif_scroll_colors __ARGS((Widget id));
109 
110 #if (XmVersion >= 1002)
111 # define STRING_TAG  XmFONTLIST_DEFAULT_TAG
112 #else
113 # define STRING_TAG  XmSTRING_DEFAULT_CHARSET
114 #endif
115 
116 /*
117  * Call-back routines.
118  */
119 
120     static void
121 scroll_cb(w, client_data, call_data)
122     Widget	w UNUSED;
123     XtPointer	client_data, call_data;
124 {
125     scrollbar_T *sb;
126     long	value;
127     int		dragging;
128 
129     sb = gui_find_scrollbar((long)client_data);
130 
131     value = ((XmScrollBarCallbackStruct *)call_data)->value;
132     dragging = (((XmScrollBarCallbackStruct *)call_data)->reason ==
133 							      (int)XmCR_DRAG);
134     gui_drag_scrollbar(sb, value, dragging);
135 }
136 
137 #ifdef FEAT_GUI_TABLINE
138     static void
139 tabline_cb(w, client_data, call_data)
140     Widget	w UNUSED;
141     XtPointer	client_data UNUSED;
142     XtPointer	call_data;
143 {
144     XmNotebookCallbackStruct *nptr;
145 
146     nptr = (XmNotebookCallbackStruct *)call_data;
147     if (nptr->reason != (int)XmCR_NONE)
148 	send_tabline_event(nptr->page_number);
149 }
150 
151     static void
152 tabline_button_cb(w, client_data, call_data)
153     Widget	w;
154     XtPointer	client_data UNUSED;
155     XtPointer	call_data UNUSED;
156 {
157     int		cmd, tab_idx;
158 
159     XtVaGetValues(w, XmNuserData, &cmd, NULL);
160     XtVaGetValues(tabLine_menu, XmNuserData, &tab_idx, NULL);
161 
162     send_tabline_menu_event(tab_idx, cmd);
163 }
164 
165 /*
166  * Tabline single mouse click timeout handler
167  */
168     static void
169 motif_tabline_timer_cb (timed_out, interval_id)
170     XtPointer		timed_out;
171     XtIntervalId	*interval_id UNUSED;
172 {
173     *((int *)timed_out) = TRUE;
174 }
175 
176 /*
177  * check if the tabline tab scroller is clicked
178  */
179     static int
180 tabline_scroller_clicked(scroller_name, event)
181     char		*scroller_name;
182     XButtonPressedEvent *event;
183 {
184     Widget	tab_scroll_w;
185     Position	pos_x, pos_y;
186     Dimension	width, height;
187 
188     tab_scroll_w = XtNameToWidget(tabLine, scroller_name);
189     if (tab_scroll_w != (Widget)0) {
190 	XtVaGetValues(tab_scroll_w, XmNx, &pos_x, XmNy, &pos_y, XmNwidth,
191 		      &width, XmNheight, &height, NULL);
192 	if (pos_x >= 0) {
193 	    /* Tab scroller (next) is visible */
194 	    if ((event->x >= pos_x) && (event->x <= pos_x + width) &&
195 		(event->y >= pos_y) && (event->y <= pos_y + height)) {
196 		/* Clicked on the scroller */
197 		return TRUE;
198 	    }
199 	}
200     }
201     return FALSE;
202 }
203 
204     static void
205 tabline_menu_cb(w, closure, e, continue_dispatch)
206     Widget	w;
207     XtPointer	closure UNUSED;
208     XEvent	*e;
209     Boolean	*continue_dispatch UNUSED;
210 {
211     Widget			tab_w;
212     XButtonPressedEvent		*event;
213     int				tab_idx = 0;
214     WidgetList			children;
215     Cardinal			numChildren;
216     static XtIntervalId		timer = (XtIntervalId)0;
217     static int			timed_out = TRUE;
218 
219     event = (XButtonPressedEvent *)e;
220 
221     if (event->button == Button1)
222     {
223 	if (tabline_scroller_clicked("MajorTabScrollerNext", event)
224 	    || tabline_scroller_clicked("MajorTabScrollerPrevious", event))
225 	    return;
226 
227 	if (!timed_out)
228 	{
229 	    XtRemoveTimeOut(timer);
230 	    timed_out = TRUE;
231 
232 	    /*
233 	     * Double click on the tabline gutter, add a new tab
234 	     */
235 	    send_tabline_menu_event(0, TABLINE_MENU_NEW);
236 	}
237 	else
238 	{
239 	    /*
240 	     * Single click on the tabline gutter, start a timer to check
241 	     * for double clicks
242 	     */
243 	    timer = XtAppAddTimeOut(app_context, (long_u)p_mouset,
244 				    motif_tabline_timer_cb, &timed_out);
245 	    timed_out = FALSE;
246 	}
247 	return;
248     }
249 
250     if (event->button != Button3)
251 	return;
252 
253     /* When ignoring events don't show the menu. */
254     if (hold_gui_events
255 # ifdef FEAT_CMDWIN
256 	    || cmdwin_type != 0
257 # endif
258        )
259 	return;
260 
261     if (event->subwindow != None)
262     {
263 	tab_w = XtWindowToWidget(XtDisplay(w), event->subwindow);
264 	/* LINTED: avoid warning: dubious operation on enum */
265 	if (tab_w != (Widget)0 && XmIsPushButton(tab_w))
266 	    XtVaGetValues(tab_w, XmNpageNumber, &tab_idx, NULL);
267     }
268 
269     XtVaSetValues(tabLine_menu, XmNuserData, tab_idx, NULL);
270     XtVaGetValues(tabLine_menu, XmNchildren, &children, XmNnumChildren,
271 		  &numChildren, NULL);
272     XtManageChildren(children, numChildren);
273     XmMenuPosition(tabLine_menu, (XButtonPressedEvent *)e) ;
274     XtManageChild(tabLine_menu);
275 }
276 
277     static void
278 tabline_balloon_cb(beval, state)
279     BalloonEval	*beval;
280     int		state UNUSED;
281 {
282     int		nr;
283     tabpage_T	*tp;
284 
285     if (beval->target == (Widget)0)
286 	return;
287 
288     XtVaGetValues(beval->target, XmNpageNumber, &nr, NULL);
289     tp = find_tabpage(nr);
290     if (tp == NULL)
291 	return;
292 
293     get_tabline_label(tp, TRUE);
294     gui_mch_post_balloon(beval, NameBuff);
295 }
296 
297 #endif
298 
299 /*
300  * End of call-back routines
301  */
302 
303 /*
304  * Implement three dimensional shading of insensitive labels.
305  * By Marcin Dalecki.
306  */
307 
308 #include <Xm/XmP.h>
309 #include <Xm/LabelP.h>
310 
311 static XtExposeProc old_label_expose = NULL;
312 
313 static void label_expose __ARGS((Widget _w, XEvent *_event, Region _region));
314 
315     static void
316 label_expose(_w, _event, _region)
317     Widget	_w;
318     XEvent	*_event;
319     Region	_region;
320 {
321     GC		    insensitiveGC;
322     XmLabelWidget   lw = (XmLabelWidget)_w;
323     unsigned char   label_type = (int)XmSTRING;
324 
325     XtVaGetValues(_w, XmNlabelType, &label_type, (XtPointer)0);
326 
327     if (XtIsSensitive(_w) || label_type != (int)XmSTRING)
328 	(*old_label_expose)(_w, _event, _region);
329     else
330     {
331 	XGCValues   values;
332 	XtGCMask    mask;
333 	XtGCMask    dynamic;
334 	XFontStruct *fs;
335 
336 	_XmFontListGetDefaultFont(lw->label.font, &fs);
337 
338 	/* FIXME: we should be doing the whole drawing ourself here. */
339 	insensitiveGC = lw->label.insensitive_GC;
340 
341 	mask = GCForeground | GCBackground | GCGraphicsExposures;
342 	dynamic = GCClipMask | GCClipXOrigin | GCClipYOrigin;
343 	values.graphics_exposures = False;
344 
345 	if (fs != 0)
346 	{
347 	    mask |= GCFont;
348 	    values.font = fs->fid;
349 	}
350 
351 	if (lw->primitive.top_shadow_pixmap != None
352 		&& lw->primitive.top_shadow_pixmap != XmUNSPECIFIED_PIXMAP)
353 	{
354 	    mask |= GCFillStyle | GCTile;
355 	    values.fill_style = FillTiled;
356 	    values.tile = lw->primitive.top_shadow_pixmap;
357 	}
358 
359 	lw->label.TextRect.x += 1;
360 	lw->label.TextRect.y += 1;
361 	if (lw->label._acc_text != 0)
362 	{
363 	    lw->label.acc_TextRect.x += 1;
364 	    lw->label.acc_TextRect.y += 1;
365 	}
366 
367 	values.foreground = lw->primitive.top_shadow_color;
368 	values.background = lw->core.background_pixel;
369 
370 	lw->label.insensitive_GC = XtAllocateGC((Widget)lw, 0, mask,
371 					       &values, dynamic, (XtGCMask)0);
372 	(*old_label_expose)(_w, _event, _region);
373 	XtReleaseGC(_w, lw->label.insensitive_GC);
374 
375 	lw->label.TextRect.x -= 1;
376 	lw->label.TextRect.y -= 1;
377 	if (lw->label._acc_text != 0)
378 	{
379 	    lw->label.acc_TextRect.x -= 1;
380 	    lw->label.acc_TextRect.y -= 1;
381 	}
382 
383 	values.foreground = lw->primitive.bottom_shadow_color;
384 	values.background = lw->core.background_pixel;
385 
386 	lw->label.insensitive_GC = XtAllocateGC((Widget) lw, 0, mask,
387 					       &values, dynamic, (XtGCMask)0);
388 	(*old_label_expose)(_w, _event, _region);
389 	XtReleaseGC(_w, lw->label.insensitive_GC);
390 
391 	lw->label.insensitive_GC = insensitiveGC;
392     }
393 }
394 
395 /*
396  * Create all the motif widgets necessary.
397  */
398     void
399 gui_x11_create_widgets()
400 {
401 #ifdef FEAT_GUI_TABLINE
402     Widget	button, scroller;
403     Arg		args[10];
404     int		n;
405     XmString	xms;
406 #endif
407 
408     /*
409      * Install the 3D shade effect drawing routines.
410      */
411     if (old_label_expose == NULL)
412     {
413 	old_label_expose = xmLabelWidgetClass->core_class.expose;
414 	xmLabelWidgetClass->core_class.expose = label_expose;
415     }
416 
417     /*
418      * Start out by adding the configured border width into the border offset
419      */
420     gui.border_offset = gui.border_width;
421 
422     /*
423      * Install the tearOffModel resource converter.
424      */
425 #if (XmVersion >= 1002)
426     XmRepTypeInstallTearOffModelConverter();
427 #endif
428 
429     /* Make sure the "Quit" menu entry of the window manager is ignored */
430     XtVaSetValues(vimShell, XmNdeleteResponse, XmDO_NOTHING, NULL);
431 
432     vimForm = XtVaCreateManagedWidget("vimForm",
433 	xmFormWidgetClass, vimShell,
434 	XmNborderWidth, 0,
435 	XmNhighlightThickness, 0,
436 	XmNshadowThickness, 0,
437 	XmNmarginWidth, 0,
438 	XmNmarginHeight, 0,
439 	XmNresizePolicy, XmRESIZE_ANY,
440 	NULL);
441     gui_motif_menu_colors(vimForm);
442 
443 #ifdef FEAT_MENU
444     {
445 	Arg al[7]; /* Make sure there is enough room for arguments! */
446 	int ac = 0;
447 
448 # if (XmVersion >= 1002)
449 	XtSetArg(al[ac], XmNtearOffModel, tearoff_val); ac++;
450 # endif
451 	XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
452 	XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
453 	XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
454 # ifndef FEAT_TOOLBAR
455 	/* Always stick to right hand side. */
456 	XtSetArg(al[ac], XmNrightOffset, 0); ac++;
457 # endif
458 	XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
459 	menuBar = XmCreateMenuBar(vimForm, "menuBar", al, ac);
460 	XtManageChild(menuBar);
461 
462 	/* Remember the default colors, needed for ":hi clear". */
463 	XtVaGetValues(menuBar,
464 	    XmNbackground, &gui.menu_def_bg_pixel,
465 	    XmNforeground, &gui.menu_def_fg_pixel,
466 	    NULL);
467 	gui_motif_menu_colors(menuBar);
468     }
469 #endif
470 
471 #ifdef FEAT_TOOLBAR
472     /*
473      * Create an empty ToolBar. We should get buttons defined from menu.vim.
474      */
475     toolBarFrame = XtVaCreateWidget("toolBarFrame",
476 	xmFrameWidgetClass, vimForm,
477 	XmNshadowThickness, 0,
478 	XmNmarginHeight, 0,
479 	XmNmarginWidth, 0,
480 	XmNleftAttachment, XmATTACH_FORM,
481 	XmNrightAttachment, XmATTACH_FORM,
482 	NULL);
483     gui_motif_menu_colors(toolBarFrame);
484 
485     toolBar = XtVaCreateManagedWidget("toolBar",
486 	xmRowColumnWidgetClass, toolBarFrame,
487 	XmNchildType, XmFRAME_WORKAREA_CHILD,
488 	XmNrowColumnType, XmWORK_AREA,
489 	XmNorientation, XmHORIZONTAL,
490 	XmNtraversalOn, False,
491 	XmNisHomogeneous, False,
492 	XmNpacking, XmPACK_TIGHT,
493 	XmNspacing, 0,
494 	XmNshadowThickness, 0,
495 	XmNhighlightThickness, 0,
496 	XmNmarginHeight, 0,
497 	XmNmarginWidth, 0,
498 	XmNadjustLast, True,
499 	NULL);
500     gui_motif_menu_colors(toolBar);
501 
502 #endif
503 
504 #ifdef FEAT_GUI_TABLINE
505     /* Create the Vim GUI tabline */
506     n = 0;
507     XtSetArg(args[n], XmNbindingType, XmNONE); n++;
508     XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
509     XtSetArg(args[n], XmNbackPageSize, XmNONE); n++;
510     XtSetArg(args[n], XmNbackPageNumber, 0); n++;
511     XtSetArg(args[n], XmNbackPagePlacement, XmTOP_RIGHT); n++;
512     XtSetArg(args[n], XmNmajorTabSpacing, 0); n++;
513     XtSetArg(args[n], XmNshadowThickness, 0); n++;
514     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
515     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
516     tabLine = XmCreateNotebook(vimForm, "Vim tabline", args, n);
517 
518     XtAddCallback(tabLine, XmNpageChangedCallback, (XtCallbackProc)tabline_cb,
519 			NULL);
520     XtAddEventHandler(tabLine, ButtonPressMask, False,
521 			(XtEventHandler)tabline_menu_cb, NULL);
522 
523     gui.tabline_height = TABLINE_HEIGHT;
524 
525     /*
526      * Set the size of the minor next/prev scrollers to zero, so
527      * that they are not displayed. Due to a bug in OpenMotif 2.3,
528      * even if these children widget are unmanaged, they are again
529      * managed by the Notebook widget and the notebook widget geometry
530      * is adjusted to account for the minor scroller widgets.
531      */
532     scroller = XtNameToWidget(tabLine, "MinorTabScrollerNext");
533     XtVaSetValues(scroller, XmNwidth, 0, XmNresizable, False,
534 		  XmNtraversalOn, False, NULL);
535     scroller = XtNameToWidget(tabLine, "MinorTabScrollerPrevious");
536     XtVaSetValues(scroller, XmNwidth, 0, XmNresizable, False,
537 		  XmNtraversalOn, False, NULL);
538 
539     /* Create the tabline popup menu */
540     tabLine_menu = XmCreatePopupMenu(tabLine, "tabline popup", NULL, 0);
541 
542     /* Add the buttons to the menu */
543     if (first_tabpage->tp_next != NULL)
544     {
545 	n = 0;
546 	XtSetArg(args[n], XmNuserData, TABLINE_MENU_CLOSE); n++;
547 	xms = XmStringCreate((char *)"Close tab", STRING_TAG);
548 	XtSetArg(args[n], XmNlabelString, xms); n++;
549 	button = XmCreatePushButton(tabLine_menu, "Close", args, n);
550 	XtAddCallback(button, XmNactivateCallback,
551 		      (XtCallbackProc)tabline_button_cb, NULL);
552 	XmStringFree(xms);
553     }
554 
555     n = 0;
556     XtSetArg(args[n], XmNuserData, TABLINE_MENU_NEW); n++;
557     xms = XmStringCreate((char *)"New Tab", STRING_TAG);
558     XtSetArg(args[n], XmNlabelString, xms); n++;
559     button = XmCreatePushButton(tabLine_menu, "New Tab", args, n);
560     XtAddCallback(button, XmNactivateCallback,
561 		  (XtCallbackProc)tabline_button_cb, NULL);
562     XmStringFree(xms);
563 
564     n = 0;
565     XtSetArg(args[n], XmNuserData, TABLINE_MENU_OPEN); n++;
566     xms = XmStringCreate((char *)"Open tab...", STRING_TAG);
567     XtSetArg(args[n], XmNlabelString, xms); n++;
568     button = XmCreatePushButton(tabLine_menu, "Open tab...", args, n);
569     XtAddCallback(button, XmNactivateCallback,
570 		  (XtCallbackProc)tabline_button_cb, NULL);
571     XmStringFree(xms);
572 #endif
573 
574     textAreaForm = XtVaCreateManagedWidget("textAreaForm",
575 	xmFormWidgetClass, vimForm,
576 	XmNleftAttachment, XmATTACH_FORM,
577 	XmNrightAttachment, XmATTACH_FORM,
578 	XmNbottomAttachment, XmATTACH_FORM,
579 	XmNtopAttachment, XmATTACH_FORM,
580 	XmNmarginWidth, 0,
581 	XmNmarginHeight, 0,
582 	XmNresizePolicy, XmRESIZE_ANY,
583 	NULL);
584     gui_motif_scroll_colors(textAreaForm);
585 
586     textArea = XtVaCreateManagedWidget("textArea",
587 	xmDrawingAreaWidgetClass, textAreaForm,
588 	XmNforeground, gui.norm_pixel,
589 	XmNbackground, gui.back_pixel,
590 	XmNleftAttachment, XmATTACH_FORM,
591 	XmNtopAttachment, XmATTACH_FORM,
592 	XmNrightAttachment, XmATTACH_FORM,
593 	XmNbottomAttachment, XmATTACH_FORM,
594 
595 	/*
596 	 * These take some control away from the user, but avoids making them
597 	 * add resources to get a decent looking setup.
598 	 */
599 	XmNborderWidth, 0,
600 	XmNhighlightThickness, 0,
601 	XmNshadowThickness, 0,
602 	NULL);
603 
604 #ifdef FEAT_FOOTER
605     /*
606      * Create the Footer.
607      */
608     footer = XtVaCreateWidget("footer",
609 	xmLabelGadgetClass, vimForm,
610 	XmNalignment, XmALIGNMENT_BEGINNING,
611 	XmNmarginHeight, 0,
612 	XmNmarginWidth, 0,
613 	XmNtraversalOn, False,
614 	XmNrecomputeSize, False,
615 	XmNleftAttachment, XmATTACH_FORM,
616 	XmNleftOffset, 5,
617 	XmNrightAttachment, XmATTACH_FORM,
618 	XmNbottomAttachment, XmATTACH_FORM,
619 	NULL);
620     gui_mch_set_footer((char_u *) "");
621 #endif
622 
623     /*
624      * Install the callbacks.
625      */
626     gui_x11_callbacks(textArea, vimForm);
627 
628     /* Pretend we don't have input focus, we will get an event if we do. */
629     gui.in_focus = FALSE;
630 }
631 
632 /*
633  * Called when the GUI is not going to start after all.
634  */
635     void
636 gui_x11_destroy_widgets()
637 {
638     textArea = NULL;
639 #ifdef FEAT_MENU
640     menuBar = NULL;
641 #endif
642 }
643 
644     void
645 gui_mch_set_text_area_pos(x, y, w, h)
646     int	    x UNUSED;
647     int	    y UNUSED;
648     int	    w UNUSED;
649     int	    h UNUSED;
650 {
651 #ifdef FEAT_TOOLBAR
652     /* Give keyboard focus to the textArea instead of the toolbar. */
653     reset_focus();
654 #endif
655 }
656 
657     void
658 gui_x11_set_back_color()
659 {
660     if (textArea != NULL)
661 #if (XmVersion >= 1002)
662 	XmChangeColor(textArea, gui.back_pixel);
663 #else
664 	XtVaSetValues(textArea,
665 		  XmNbackground, gui.back_pixel,
666 		  NULL);
667 #endif
668 }
669 
670 /*
671  * Manage dialog centered on pointer. This could be used by the Athena code as
672  * well.
673  */
674     void
675 manage_centered(dialog_child)
676     Widget dialog_child;
677 {
678     Widget shell = XtParent(dialog_child);
679     Window root, child;
680     unsigned int mask;
681     unsigned int width, height, border_width, depth;
682     int x, y, win_x, win_y, maxX, maxY;
683     Boolean mappedWhenManaged;
684 
685     /* Temporarily set value of XmNmappedWhenManaged
686        to stop the dialog from popping up right away */
687     XtVaGetValues(shell, XmNmappedWhenManaged, &mappedWhenManaged, NULL);
688     XtVaSetValues(shell, XmNmappedWhenManaged, False, NULL);
689 
690     XtManageChild(dialog_child);
691 
692     /* Get the pointer position (x, y) */
693     XQueryPointer(XtDisplay(shell), XtWindow(shell), &root, &child,
694 		  &x, &y, &win_x, &win_y, &mask);
695 
696     /* Translate the pointer position (x, y) into a position for the new
697        window that will place the pointer at its center */
698     XGetGeometry(XtDisplay(shell), XtWindow(shell), &root, &win_x, &win_y,
699 		 &width, &height, &border_width, &depth);
700     width += 2 * border_width;
701     height += 2 * border_width;
702     x -= width / 2;
703     y -= height / 2;
704 
705     /* Ensure that the dialog remains on screen */
706     maxX = XtScreen(shell)->width - width;
707     maxY = XtScreen(shell)->height - height;
708     if (x < 0)
709 	x = 0;
710     if (x > maxX)
711 	x = maxX;
712     if (y < 0)
713 	y = 0;
714     if (y > maxY)
715 	y = maxY;
716 
717     /* Set desired window position in the DialogShell */
718     XtVaSetValues(shell, XmNx, x, XmNy, y, NULL);
719 
720     /* Map the widget */
721     XtMapWidget(shell);
722 
723     /* Restore the value of XmNmappedWhenManaged */
724     XtVaSetValues(shell, XmNmappedWhenManaged, mappedWhenManaged, NULL);
725 }
726 
727 #if defined(FEAT_MENU) || defined(FEAT_SUN_WORKSHOP) \
728 	|| defined(FEAT_GUI_DIALOG) || defined(PROTO)
729 
730 /*
731  * Encapsulate the way an XmFontList is created.
732  */
733     XmFontList
734 gui_motif_create_fontlist(font)
735     XFontStruct    *font;
736 {
737     XmFontList font_list;
738 
739 # if (XmVersion <= 1001)
740     /* Motif 1.1 method */
741     font_list = XmFontListCreate(font, STRING_TAG);
742 # else
743     /* Motif 1.2 method */
744     XmFontListEntry font_list_entry;
745 
746     font_list_entry = XmFontListEntryCreate(STRING_TAG, XmFONT_IS_FONT,
747 					    (XtPointer)font);
748     font_list = XmFontListAppendEntry(NULL, font_list_entry);
749     XmFontListEntryFree(&font_list_entry);
750 # endif
751     return font_list;
752 }
753 
754 # if ((XmVersion > 1001) && defined(FEAT_XFONTSET)) || defined(PROTO)
755     XmFontList
756 gui_motif_fontset2fontlist(fontset)
757     XFontSet	*fontset;
758 {
759     XmFontList font_list;
760 
761     /* Motif 1.2 method */
762     XmFontListEntry font_list_entry;
763 
764     font_list_entry = XmFontListEntryCreate(STRING_TAG,
765 					    XmFONT_IS_FONTSET,
766 					    (XtPointer)*fontset);
767     font_list = XmFontListAppendEntry(NULL, font_list_entry);
768     XmFontListEntryFree(&font_list_entry);
769     return font_list;
770 }
771 # endif
772 
773 #endif
774 
775 #if defined(FEAT_MENU) || defined(PROTO)
776 /*
777  * Menu stuff.
778  */
779 
780 static void gui_motif_add_actext __ARGS((vimmenu_T *menu));
781 #if (XmVersion >= 1002)
782 static void toggle_tearoff __ARGS((Widget wid));
783 static void gui_mch_recurse_tearoffs __ARGS((vimmenu_T *menu));
784 #endif
785 static void submenu_change __ARGS((vimmenu_T *mp, int colors));
786 
787 static void do_set_mnemonics __ARGS((int enable));
788 static int menu_enabled = TRUE;
789 
790     void
791 gui_mch_enable_menu(flag)
792     int	    flag;
793 {
794     if (flag)
795     {
796 	XtManageChild(menuBar);
797 #ifdef FEAT_TOOLBAR
798 	if (XtIsManaged(XtParent(toolBar)))
799 	{
800 	    /* toolBar is attached to top form */
801 	    XtVaSetValues(XtParent(toolBar),
802 		XmNtopAttachment, XmATTACH_WIDGET,
803 		XmNtopWidget, menuBar,
804 		NULL);
805 #ifdef FEAT_GUI_TABLINE
806 	    if (showing_tabline)
807 	    {
808 		XtVaSetValues(tabLine,
809 			      XmNtopAttachment, XmATTACH_WIDGET,
810 			      XmNtopWidget, XtParent(toolBar),
811 			      NULL);
812 		XtVaSetValues(textAreaForm,
813 			      XmNtopAttachment, XmATTACH_WIDGET,
814 			      XmNtopWidget, tabLine,
815 			      NULL);
816 	    }
817 	    else
818 #endif
819 		XtVaSetValues(textAreaForm,
820 			      XmNtopAttachment, XmATTACH_WIDGET,
821 			      XmNtopWidget, XtParent(toolBar),
822 			      NULL);
823 	}
824 	else
825 #endif
826 	{
827 #ifdef FEAT_GUI_TABLINE
828 	    if (showing_tabline)
829 	    {
830 		XtVaSetValues(tabLine,
831 			      XmNtopAttachment, XmATTACH_WIDGET,
832 			      XmNtopWidget, menuBar,
833 			      NULL);
834 		XtVaSetValues(textAreaForm,
835 			      XmNtopAttachment, XmATTACH_WIDGET,
836 			      XmNtopWidget, tabLine,
837 			      NULL);
838 	    }
839 	    else
840 #endif
841 		XtVaSetValues(textAreaForm,
842 			      XmNtopAttachment, XmATTACH_WIDGET,
843 			      XmNtopWidget, menuBar,
844 			      NULL);
845 	}
846     }
847     else
848     {
849 	XtUnmanageChild(menuBar);
850 #ifdef FEAT_TOOLBAR
851 	if (XtIsManaged(XtParent(toolBar)))
852 	{
853 	    XtVaSetValues(XtParent(toolBar),
854 		XmNtopAttachment, XmATTACH_FORM,
855 		NULL);
856 #ifdef FEAT_GUI_TABLINE
857 	    if (showing_tabline)
858 	    {
859 		XtVaSetValues(tabLine,
860 			      XmNtopAttachment, XmATTACH_WIDGET,
861 			      XmNtopWidget, XtParent(toolBar),
862 			      NULL);
863 		XtVaSetValues(textAreaForm,
864 			      XmNtopAttachment, XmATTACH_WIDGET,
865 			      XmNtopWidget, tabLine,
866 			      NULL);
867 	    }
868 	    else
869 #endif
870 		XtVaSetValues(textAreaForm,
871 			      XmNtopAttachment, XmATTACH_WIDGET,
872 			      XmNtopWidget, XtParent(toolBar),
873 			      NULL);
874 	}
875 	else
876 #endif
877 	{
878 #ifdef FEAT_GUI_TABLINE
879 	    if (showing_tabline)
880 	    {
881 		XtVaSetValues(tabLine,
882 			      XmNtopAttachment, XmATTACH_FORM,
883 			      NULL);
884 		XtVaSetValues(textAreaForm,
885 			      XmNtopAttachment, XmATTACH_WIDGET,
886 			      XmNtopWidget, tabLine,
887 			      NULL);
888 	    }
889 	    else
890 #endif
891 		XtVaSetValues(textAreaForm,
892 			      XmNtopAttachment, XmATTACH_FORM,
893 			      NULL);
894 	}
895     }
896 
897 }
898 
899 /*
900  * Enable or disable mnemonics for the toplevel menus.
901  */
902     void
903 gui_motif_set_mnemonics(enable)
904     int		enable;
905 {
906     /*
907      * Don't enable menu mnemonics when the menu bar is disabled, LessTif
908      * crashes when using a mnemonic then.
909      */
910     if (!menu_enabled)
911 	enable = FALSE;
912     do_set_mnemonics(enable);
913 }
914 
915     static void
916 do_set_mnemonics(enable)
917     int		enable;
918 {
919     vimmenu_T	*menu;
920 
921     for (menu = root_menu; menu != NULL; menu = menu->next)
922 	if (menu->id != (Widget)0)
923 	    XtVaSetValues(menu->id,
924 		    XmNmnemonic, enable ? menu->mnemonic : NUL,
925 		    NULL);
926 }
927 
928     void
929 gui_mch_add_menu(menu, idx)
930     vimmenu_T	*menu;
931     int		idx;
932 {
933     XmString	label;
934     Widget	shell;
935     vimmenu_T	*parent = menu->parent;
936 
937 #ifdef MOTIF_POPUP
938     if (menu_is_popup(menu->name))
939     {
940 	Arg arg[2];
941 	int n = 0;
942 
943 	/* Only create the popup menu when it's actually used, otherwise there
944 	 * is a delay when using the right mouse button. */
945 # if (XmVersion <= 1002)
946 	if (mouse_model_popup())
947 # endif
948 	{
949 	    if (gui.menu_bg_pixel != INVALCOLOR)
950 	    {
951 		XtSetArg(arg[0], XmNbackground, gui.menu_bg_pixel); n++;
952 	    }
953 	    if (gui.menu_fg_pixel != INVALCOLOR)
954 	    {
955 		XtSetArg(arg[1], XmNforeground, gui.menu_fg_pixel); n++;
956 	    }
957 	    menu->submenu_id = XmCreatePopupMenu(textArea, "contextMenu",
958 								      arg, n);
959 	    menu->id = (Widget)0;
960 	}
961 	return;
962     }
963 #endif
964 
965     if (!menu_is_menubar(menu->name)
966 	    || (parent != NULL && parent->submenu_id == (Widget)0))
967 	return;
968 
969     label = XmStringCreate((char *)menu->dname, STRING_TAG);
970     if (label == NULL)
971 	return;
972     menu->id = XtVaCreateWidget("subMenu",
973 	    xmCascadeButtonWidgetClass,
974 	    (parent == NULL) ? menuBar : parent->submenu_id,
975 	    XmNlabelString, label,
976 	    XmNmnemonic, p_wak[0] == 'n' ? NUL : menu->mnemonic,
977 #if (XmVersion >= 1002)
978 	    /* submenu: count the tearoff item (needed for LessTif) */
979 	    XmNpositionIndex, idx + (parent != NULL
980 			   && tearoff_val == (int)XmTEAR_OFF_ENABLED ? 1 : 0),
981 #endif
982 	    NULL);
983     gui_motif_menu_colors(menu->id);
984     gui_motif_menu_fontlist(menu->id);
985     XmStringFree(label);
986 
987     if (menu->id == (Widget)0)		/* failed */
988 	return;
989 
990     /* add accelerator text */
991     gui_motif_add_actext(menu);
992 
993     shell = XtVaCreateWidget("subMenuShell",
994 	xmMenuShellWidgetClass, menu->id,
995 	XmNwidth, 1,
996 	XmNheight, 1,
997 	NULL);
998     gui_motif_menu_colors(shell);
999     menu->submenu_id = XtVaCreateWidget("rowColumnMenu",
1000 	xmRowColumnWidgetClass, shell,
1001 	XmNrowColumnType, XmMENU_PULLDOWN,
1002 	NULL);
1003     gui_motif_menu_colors(menu->submenu_id);
1004 
1005     if (menu->submenu_id == (Widget)0)		/* failed */
1006 	return;
1007 
1008 #if (XmVersion >= 1002)
1009     /* Set the colors for the tear off widget */
1010     toggle_tearoff(menu->submenu_id);
1011 #endif
1012 
1013     XtVaSetValues(menu->id,
1014 	XmNsubMenuId, menu->submenu_id,
1015 	NULL);
1016 
1017     /*
1018      * The "Help" menu is a special case, and should be placed at the far
1019      * right hand side of the menu-bar.  It's recognized by its high priority.
1020      */
1021     if (parent == NULL && menu->priority >= 9999)
1022 	XtVaSetValues(menuBar,
1023 		XmNmenuHelpWidget, menu->id,
1024 		NULL);
1025 
1026     /*
1027      * When we add a top-level item to the menu bar, we can figure out how
1028      * high the menu bar should be.
1029      */
1030     if (parent == NULL)
1031 	gui_mch_compute_menu_height(menu->id);
1032 }
1033 
1034 
1035 /*
1036  * Add mnemonic and accelerator text to a menu button.
1037  */
1038     static void
1039 gui_motif_add_actext(menu)
1040     vimmenu_T	*menu;
1041 {
1042     XmString	label;
1043 
1044     /* Add accelerator text, if there is one */
1045     if (menu->actext != NULL && menu->id != (Widget)0)
1046     {
1047 	label = XmStringCreate((char *)menu->actext, STRING_TAG);
1048 	if (label == NULL)
1049 	    return;
1050 	XtVaSetValues(menu->id, XmNacceleratorText, label, NULL);
1051 	XmStringFree(label);
1052     }
1053 }
1054 
1055     void
1056 gui_mch_toggle_tearoffs(enable)
1057     int		enable;
1058 {
1059 #if (XmVersion >= 1002)
1060     if (enable)
1061 	tearoff_val = (int)XmTEAR_OFF_ENABLED;
1062     else
1063 	tearoff_val = (int)XmTEAR_OFF_DISABLED;
1064     toggle_tearoff(menuBar);
1065     gui_mch_recurse_tearoffs(root_menu);
1066 #endif
1067 }
1068 
1069 #if (XmVersion >= 1002)
1070 /*
1071  * Set the tearoff for one menu widget on or off, and set the color of the
1072  * tearoff widget.
1073  */
1074     static void
1075 toggle_tearoff(wid)
1076     Widget	wid;
1077 {
1078     Widget	w;
1079 
1080     XtVaSetValues(wid, XmNtearOffModel, tearoff_val, NULL);
1081     if (tearoff_val == (int)XmTEAR_OFF_ENABLED
1082 	    && (w = XmGetTearOffControl(wid)) != (Widget)0)
1083 	gui_motif_menu_colors(w);
1084 }
1085 
1086     static void
1087 gui_mch_recurse_tearoffs(menu)
1088     vimmenu_T	*menu;
1089 {
1090     while (menu != NULL)
1091     {
1092 	if (!menu_is_popup(menu->name))
1093 	{
1094 	    if (menu->submenu_id != (Widget)0)
1095 		toggle_tearoff(menu->submenu_id);
1096 	    gui_mch_recurse_tearoffs(menu->children);
1097 	}
1098 	menu = menu->next;
1099     }
1100 }
1101 #endif
1102 
1103     int
1104 gui_mch_text_area_extra_height()
1105 {
1106     Dimension	shadowHeight;
1107 
1108     XtVaGetValues(textAreaForm, XmNshadowThickness, &shadowHeight, NULL);
1109     return shadowHeight;
1110 }
1111 
1112 /*
1113  * Compute the height of the menu bar.
1114  * We need to check all the items for their position and height, for the case
1115  * there are several rows, and/or some characters extend higher or lower.
1116  */
1117     void
1118 gui_mch_compute_menu_height(id)
1119     Widget	id;		    /* can be NULL when deleting menu */
1120 {
1121     Dimension	y, maxy;
1122     Dimension	margin, shadow;
1123     vimmenu_T	*mp;
1124     static Dimension	height = 21;	/* normal height of a menu item */
1125 
1126     /*
1127      * Get the height of the new item, before managing it, because it will
1128      * still reflect the font size.  After managing it depends on the menu
1129      * height, which is what we just wanted to get!.
1130      */
1131     if (id != (Widget)0)
1132 	XtVaGetValues(id, XmNheight, &height, NULL);
1133 
1134     /* Find any menu Widget, to be able to call XtManageChild() */
1135     else
1136 	for (mp = root_menu; mp != NULL; mp = mp->next)
1137 	    if (mp->id != (Widget)0 && menu_is_menubar(mp->name))
1138 	    {
1139 		id = mp->id;
1140 		break;
1141 	    }
1142 
1143     /*
1144      * Now manage the menu item, to make them all be positioned (makes an
1145      * extra row when needed, removes it when not needed).
1146      */
1147     if (id != (Widget)0)
1148 	XtManageChild(id);
1149 
1150     /*
1151      * Now find the menu item that is the furthest down, and get it's position.
1152      */
1153     maxy = 0;
1154     for (mp = root_menu; mp != NULL; mp = mp->next)
1155     {
1156 	if (mp->id != (Widget)0 && menu_is_menubar(mp->name))
1157 	{
1158 	    XtVaGetValues(mp->id, XmNy, &y, NULL);
1159 	    if (y > maxy)
1160 		maxy = y;
1161 	}
1162     }
1163 
1164     XtVaGetValues(menuBar,
1165 	XmNmarginHeight, &margin,
1166 	XmNshadowThickness, &shadow,
1167 	NULL);
1168 
1169     /*
1170      * This computation is the result of trial-and-error:
1171      * maxy =	The maximum position of an item; required for when there are
1172      *		two or more rows
1173      * height = height of an item, before managing it;	Hopefully this will
1174      *		change with the font height.  Includes shadow-border.
1175      * shadow =	shadow-border; must be subtracted from the height.
1176      * margin = margin around the menu buttons;  Must be added.
1177      * Add 4 for the underlining of shortcut keys.
1178      */
1179     gui.menu_height = maxy + height - 2 * shadow + 2 * margin + 4;
1180 
1181     /* Somehow the menu bar doesn't resize automatically.  Set it here,
1182      * even though this is a catch 22.  Don't do this when starting up,
1183      * somehow the menu gets very high then. */
1184     if (gui.shell_created)
1185 	XtVaSetValues(menuBar, XmNheight, gui.menu_height, NULL);
1186 }
1187 
1188 #ifdef FEAT_TOOLBAR
1189 
1190 /*
1191  * Icons used by the toolbar code.
1192  */
1193 #include "gui_x11_pm.h"
1194 
1195 static int check_xpm __ARGS((char_u *path));
1196 static char **get_toolbar_pixmap __ARGS((vimmenu_T *menu, char **fname));
1197 static int add_pixmap_args __ARGS((vimmenu_T *menu, Arg *args, int n));
1198 
1199 /*
1200  * Read an Xpm file.  Return OK or FAIL.
1201  */
1202     static int
1203 check_xpm(path)
1204     char_u	*path;
1205 {
1206     XpmAttributes attrs;
1207     int		status;
1208     Pixmap	mask;
1209     Pixmap	map;
1210 
1211     attrs.valuemask = 0;
1212 
1213     /* Create the "sensitive" pixmap */
1214     status = XpmReadFileToPixmap(gui.dpy,
1215 	    RootWindow(gui.dpy, DefaultScreen(gui.dpy)),
1216 	    (char *)path, &map, &mask, &attrs);
1217     XpmFreeAttributes(&attrs);
1218 
1219     if (status == XpmSuccess)
1220 	return OK;
1221     return FAIL;
1222 }
1223 
1224 
1225 /*
1226  * Allocated a pixmap for toolbar menu "menu".
1227  * When it's to be read from a file, "fname" is set to the file name
1228  * (in allocated memory).
1229  * Return a blank pixmap if it fails.
1230  */
1231     static char **
1232 get_toolbar_pixmap(menu, fname)
1233     vimmenu_T	*menu;
1234     char	**fname;
1235 {
1236     char_u	buf[MAXPATHL];		/* buffer storing expanded pathname */
1237     char	**xpm = NULL;		/* xpm array */
1238     int		res;
1239 
1240     *fname = NULL;
1241     buf[0] = NUL;			/* start with NULL path */
1242 
1243     if (menu->iconfile != NULL)
1244     {
1245 	/* Use the "icon="  argument. */
1246 	gui_find_iconfile(menu->iconfile, buf, "xpm");
1247 	res = check_xpm(buf);
1248 
1249 	/* If it failed, try using the menu name. */
1250 	if (res == FAIL && gui_find_bitmap(menu->name, buf, "xpm") == OK)
1251 	    res = check_xpm(buf);
1252 	if (res == OK)
1253 	{
1254 	    *fname = (char *)vim_strsave(buf);
1255 	    return tb_blank_xpm;
1256 	}
1257     }
1258 
1259     if (menu->icon_builtin || gui_find_bitmap(menu->name, buf, "xpm") == FAIL)
1260     {
1261 	if (menu->iconidx >= 0 && menu->iconidx
1262 	       < (int)(sizeof(built_in_pixmaps) / sizeof(built_in_pixmaps[0])))
1263 	    xpm = built_in_pixmaps[menu->iconidx];
1264 	else
1265 	    xpm = tb_blank_xpm;
1266     }
1267 
1268     return xpm;
1269 }
1270 
1271 /*
1272  * Add arguments for the toolbar pixmap to a menu item.
1273  */
1274     static int
1275 add_pixmap_args(menu, args, n)
1276     vimmenu_T	*menu;
1277     Arg		*args;
1278     int		n;
1279 {
1280     vim_free(menu->xpm_fname);
1281     menu->xpm = get_toolbar_pixmap(menu, &menu->xpm_fname);
1282     if (menu->xpm == NULL)
1283     {
1284 	XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
1285     }
1286     else
1287     {
1288 	if (menu->xpm_fname != NULL)
1289 	{
1290 	    XtSetArg(args[n], XmNpixmapFile, menu->xpm_fname); n++;
1291 	}
1292 	XtSetArg(args[n], XmNpixmapData, menu->xpm); n++;
1293 	XtSetArg(args[n], XmNlabelLocation, XmBOTTOM); n++;
1294     }
1295     return n;
1296 }
1297 #endif /* FEAT_TOOLBAR */
1298 
1299     void
1300 gui_mch_add_menu_item(menu, idx)
1301     vimmenu_T	*menu;
1302     int		idx;
1303 {
1304     XmString	label;
1305     vimmenu_T	*parent = menu->parent;
1306 
1307 # ifdef EBCDIC
1308     menu->mnemonic = 0;
1309 # endif
1310 
1311 # if (XmVersion <= 1002)
1312     /* Don't add Popup menu items when the popup menu isn't used. */
1313     if (menu_is_child_of_popup(menu) && !mouse_model_popup())
1314 	return;
1315 # endif
1316 
1317 # ifdef FEAT_TOOLBAR
1318     if (menu_is_toolbar(parent->name))
1319     {
1320 	WidgetClass	type;
1321 	XmString	xms = NULL;    /* fallback label if pixmap not found */
1322 	int		n;
1323 	Arg		args[18];
1324 
1325 	n = 0;
1326 	if (menu_is_separator(menu->name))
1327 	{
1328 	    char	*cp;
1329 	    Dimension	wid;
1330 
1331 	    /*
1332 	     * A separator has the format "-sep%d[:%d]-". The optional :%d is
1333 	     * a width specifier. If no width is specified then we choose one.
1334 	     */
1335 	    cp = (char *)vim_strchr(menu->name, ':');
1336 	    if (cp != NULL)
1337 		wid = (Dimension)atoi(++cp);
1338 	    else
1339 		wid = 4;
1340 
1341 	    type = xmSeparatorWidgetClass;
1342 	    XtSetArg(args[n], XmNwidth, wid); n++;
1343 	    XtSetArg(args[n], XmNminWidth, wid); n++;
1344 	    XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
1345 	    XtSetArg(args[n], XmNseparatorType, XmSHADOW_ETCHED_IN); n++;
1346 	}
1347 	else
1348 	{
1349 	    /* Without shadows one can't sense whatever the button has been
1350 	     * pressed or not! However we want to save a bit of space...
1351 	     * Need the highlightThickness to see the focus.
1352 	     */
1353 	    XtSetArg(args[n], XmNhighlightThickness, 1); n++;
1354 	    XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
1355 	    XtSetArg(args[n], XmNmarginWidth, 0); n++;
1356 	    XtSetArg(args[n], XmNmarginHeight, 0); n++;
1357 	    XtSetArg(args[n], XmNtraversalOn, False); n++;
1358 	    /* Set the label here, so that we can switch between icons/text
1359 	     * by changing the XmNlabelType resource. */
1360 	    xms = XmStringCreate((char *)menu->dname, STRING_TAG);
1361 	    XtSetArg(args[n], XmNlabelString, xms); n++;
1362 
1363 	    n = add_pixmap_args(menu, args, n);
1364 
1365 	    type = xmEnhancedButtonWidgetClass;
1366 	}
1367 
1368 	XtSetArg(args[n], XmNpositionIndex, idx); n++;
1369 	if (menu->id == NULL)
1370 	{
1371 	    menu->id = XtCreateManagedWidget((char *)menu->dname,
1372 			type, toolBar, args, n);
1373 	    if (menu->id != NULL && type == xmEnhancedButtonWidgetClass)
1374 	    {
1375 		XtAddCallback(menu->id,
1376 			XmNactivateCallback, gui_x11_menu_cb, menu);
1377 # ifdef FEAT_FOOTER
1378 		XtAddEventHandler(menu->id, EnterWindowMask, False,
1379 			toolbarbutton_enter_cb, menu);
1380 		XtAddEventHandler(menu->id, LeaveWindowMask, False,
1381 			toolbarbutton_leave_cb, menu);
1382 # endif
1383 	    }
1384 	}
1385 	else
1386 	    XtSetValues(menu->id, args, n);
1387 	if (xms != NULL)
1388 	    XmStringFree(xms);
1389 
1390 # ifdef FEAT_BEVAL
1391 	gui_mch_menu_set_tip(menu);
1392 # endif
1393 
1394 	menu->parent = parent;
1395 	menu->submenu_id = NULL;
1396 	/* When adding first item to toolbar it might have to be enabled .*/
1397 	if (!XtIsManaged(XtParent(toolBar))
1398 		    && vim_strchr(p_go, GO_TOOLBAR) != NULL)
1399 	    gui_mch_show_toolbar(TRUE);
1400 	gui.toolbar_height = gui_mch_compute_toolbar_height();
1401 	return;
1402     } /* toolbar menu item */
1403 # endif
1404 
1405     /* No parent, must be a non-menubar menu */
1406     if (parent->submenu_id == (Widget)0)
1407 	return;
1408 
1409     menu->submenu_id = (Widget)0;
1410 
1411     /* Add menu separator */
1412     if (menu_is_separator(menu->name))
1413     {
1414 	menu->id = XtVaCreateWidget("subMenu",
1415 		xmSeparatorGadgetClass, parent->submenu_id,
1416 #if (XmVersion >= 1002)
1417 		/* count the tearoff item (needed for LessTif) */
1418 		XmNpositionIndex, idx + (tearoff_val == (int)XmTEAR_OFF_ENABLED
1419 								     ? 1 : 0),
1420 #endif
1421 		NULL);
1422 	gui_motif_menu_colors(menu->id);
1423 	return;
1424     }
1425 
1426     label = XmStringCreate((char *)menu->dname, STRING_TAG);
1427     if (label == NULL)
1428 	return;
1429     menu->id = XtVaCreateWidget("subMenu",
1430 	xmPushButtonWidgetClass, parent->submenu_id,
1431 	XmNlabelString, label,
1432 	XmNmnemonic, menu->mnemonic,
1433 #if (XmVersion >= 1002)
1434 	/* count the tearoff item (needed for LessTif) */
1435 	XmNpositionIndex, idx + (tearoff_val == (int)XmTEAR_OFF_ENABLED
1436 								     ? 1 : 0),
1437 #endif
1438 	NULL);
1439     gui_motif_menu_colors(menu->id);
1440     gui_motif_menu_fontlist(menu->id);
1441     XmStringFree(label);
1442 
1443     if (menu->id != (Widget)0)
1444     {
1445 	XtAddCallback(menu->id, XmNactivateCallback, gui_x11_menu_cb,
1446 		(XtPointer)menu);
1447 	/* add accelerator text */
1448 	gui_motif_add_actext(menu);
1449     }
1450 }
1451 
1452 #if (XmVersion <= 1002) || defined(PROTO)
1453 /*
1454  * This function will destroy/create the popup menus dynamically,
1455  * according to the value of 'mousemodel'.
1456  * This will fix the "right mouse button freeze" that occurs when
1457  * there exists a popup menu but it isn't managed.
1458  */
1459     void
1460 gui_motif_update_mousemodel(menu)
1461     vimmenu_T	*menu;
1462 {
1463     int		idx = 0;
1464 
1465     /* When GUI hasn't started the menus have not been created. */
1466     if (!gui.in_use)
1467       return;
1468 
1469     while (menu)
1470     {
1471       if (menu->children != NULL)
1472       {
1473 	  if (menu_is_popup(menu->name))
1474 	  {
1475 	      if (mouse_model_popup())
1476 	      {
1477 		  /* Popup menu will be used.  Create the popup menus. */
1478 		  gui_mch_add_menu(menu, idx);
1479 		  gui_motif_update_mousemodel(menu->children);
1480 	      }
1481 	      else
1482 	      {
1483 		  /* Popup menu will not be used.  Destroy the popup menus. */
1484 		  gui_motif_update_mousemodel(menu->children);
1485 		  gui_mch_destroy_menu(menu);
1486 	      }
1487 	  }
1488       }
1489       else if (menu_is_child_of_popup(menu))
1490       {
1491 	  if (mouse_model_popup())
1492 	      gui_mch_add_menu_item(menu, idx);
1493 	  else
1494 	      gui_mch_destroy_menu(menu);
1495       }
1496       menu = menu->next;
1497       ++idx;
1498     }
1499 }
1500 #endif
1501 
1502     void
1503 gui_mch_new_menu_colors()
1504 {
1505     if (menuBar == (Widget)0)
1506 	return;
1507     gui_motif_menu_colors(menuBar);
1508 #ifdef FEAT_TOOLBAR
1509     gui_motif_menu_colors(toolBarFrame);
1510     gui_motif_menu_colors(toolBar);
1511 #endif
1512 
1513     submenu_change(root_menu, TRUE);
1514 }
1515 
1516     void
1517 gui_mch_new_menu_font()
1518 {
1519     if (menuBar == (Widget)0)
1520 	return;
1521     submenu_change(root_menu, FALSE);
1522     {
1523 	Dimension   height;
1524 	Position w, h;
1525 
1526 	XtVaGetValues(menuBar, XmNheight, &height, NULL);
1527 	gui.menu_height = height;
1528 
1529 	XtVaGetValues(vimShell, XtNwidth, &w, XtNheight, &h, NULL);
1530 	gui_resize_shell(w, h
1531 #ifdef FEAT_XIM
1532 		- xim_get_status_area_height()
1533 #endif
1534 		     );
1535     }
1536     gui_set_shellsize(FALSE, TRUE, RESIZE_VERT);
1537     ui_new_shellsize();
1538 }
1539 
1540 #if defined(FEAT_BEVAL) || defined(PROTO)
1541     void
1542 gui_mch_new_tooltip_font()
1543 {
1544 # ifdef FEAT_TOOLBAR
1545     vimmenu_T   *menu;
1546 
1547     if (toolBar == (Widget)0)
1548 	return;
1549 
1550     menu = gui_find_menu((char_u *)"ToolBar");
1551     if (menu != NULL)
1552 	submenu_change(menu, FALSE);
1553 # endif
1554 }
1555 
1556     void
1557 gui_mch_new_tooltip_colors()
1558 {
1559 # ifdef FEAT_TOOLBAR
1560     vimmenu_T   *toolbar;
1561 
1562     if (toolBar == (Widget)0)
1563 	return;
1564 
1565     toolbar = gui_find_menu((char_u *)"ToolBar");
1566     if (toolbar != NULL)
1567 	submenu_change(toolbar, TRUE);
1568 # endif
1569 }
1570 #endif
1571 
1572     static void
1573 submenu_change(menu, colors)
1574     vimmenu_T	*menu;
1575     int		colors;		/* TRUE for colors, FALSE for font */
1576 {
1577     vimmenu_T	*mp;
1578 
1579     for (mp = menu; mp != NULL; mp = mp->next)
1580     {
1581 	if (mp->id != (Widget)0)
1582 	{
1583 	    if (colors)
1584 	    {
1585 		gui_motif_menu_colors(mp->id);
1586 #ifdef FEAT_TOOLBAR
1587 		/* For a toolbar item: Free the pixmap and allocate a new one,
1588 		 * so that the background color is right. */
1589 		if (mp->xpm != NULL)
1590 		{
1591 		    int		n = 0;
1592 		    Arg		args[18];
1593 
1594 		    n = add_pixmap_args(mp, args, n);
1595 		    XtSetValues(mp->id, args, n);
1596 		}
1597 # ifdef FEAT_BEVAL
1598 		/* If we have a tooltip, then we need to change it's font */
1599 		if (mp->tip != NULL)
1600 		{
1601 		    Arg args[2];
1602 
1603 		    args[0].name = XmNbackground;
1604 		    args[0].value = gui.tooltip_bg_pixel;
1605 		    args[1].name = XmNforeground;
1606 		    args[1].value = gui.tooltip_fg_pixel;
1607 		    XtSetValues(mp->tip->balloonLabel, &args[0], XtNumber(args));
1608 		}
1609 # endif
1610 #endif
1611 	    }
1612 	    else
1613 	    {
1614 		gui_motif_menu_fontlist(mp->id);
1615 #ifdef FEAT_BEVAL
1616 		/* If we have a tooltip, then we need to change it's font */
1617 		if (mp->tip != NULL)
1618 		{
1619 		    Arg args[1];
1620 
1621 		    args[0].name = XmNfontList;
1622 		    args[0].value = (XtArgVal)gui_motif_fontset2fontlist(
1623 						    &gui.tooltip_fontset);
1624 		    XtSetValues(mp->tip->balloonLabel, &args[0], XtNumber(args));
1625 		}
1626 #endif
1627 	    }
1628 	}
1629 
1630 	if (mp->children != NULL)
1631 	{
1632 #if (XmVersion >= 1002)
1633 	    /* Set the colors/font for the tear off widget */
1634 	    if (mp->submenu_id != (Widget)0)
1635 	    {
1636 		if (colors)
1637 		    gui_motif_menu_colors(mp->submenu_id);
1638 		else
1639 		    gui_motif_menu_fontlist(mp->submenu_id);
1640 		toggle_tearoff(mp->submenu_id);
1641 	    }
1642 #endif
1643 	    /* Set the colors for the children */
1644 	    submenu_change(mp->children, colors);
1645 	}
1646     }
1647 }
1648 
1649 /*
1650  * Destroy the machine specific menu widget.
1651  */
1652     void
1653 gui_mch_destroy_menu(menu)
1654     vimmenu_T	*menu;
1655 {
1656     /* Please be sure to destroy the parent widget first (i.e. menu->id).
1657      * On the other hand, problems have been reported that the submenu must be
1658      * deleted first...
1659      *
1660      * This code should be basically identical to that in the file gui_athena.c
1661      * because they are both Xt based.
1662      */
1663     if (menu->submenu_id != (Widget)0)
1664     {
1665 	XtDestroyWidget(menu->submenu_id);
1666 	menu->submenu_id = (Widget)0;
1667     }
1668 
1669     if (menu->id != (Widget)0)
1670     {
1671 	Widget	    parent;
1672 
1673 	parent = XtParent(menu->id);
1674 #if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL)
1675 	if (parent == toolBar && menu->tip != NULL)
1676 	{
1677 	    /* We try to destroy this before the actual menu, because there are
1678 	     * callbacks, etc. that will be unregistered during the tooltip
1679 	     * destruction.
1680 	     *
1681 	     * If you call "gui_mch_destroy_beval_area()" after destroying
1682 	     * menu->id, then the tooltip's window will have already been
1683 	     * deallocated by Xt, and unknown behaviour will ensue (probably
1684 	     * a core dump).
1685 	     */
1686 	    gui_mch_destroy_beval_area(menu->tip);
1687 	    menu->tip = NULL;
1688 	}
1689 #endif
1690 	XtDestroyWidget(menu->id);
1691 	menu->id = (Widget)0;
1692 	if (parent == menuBar)
1693 	    gui_mch_compute_menu_height((Widget)0);
1694 #ifdef FEAT_TOOLBAR
1695 	else if (parent == toolBar)
1696 	{
1697 	    Cardinal    num_children;
1698 
1699 	    /* When removing last toolbar item, don't display the toolbar. */
1700 	    XtVaGetValues(toolBar, XmNnumChildren, &num_children, NULL);
1701 	    if (num_children == 0)
1702 		gui_mch_show_toolbar(FALSE);
1703 	    else
1704 		gui.toolbar_height = gui_mch_compute_toolbar_height();
1705 	}
1706 #endif
1707     }
1708 }
1709 
1710     void
1711 gui_mch_show_popupmenu(menu)
1712     vimmenu_T *menu UNUSED;
1713 {
1714 #ifdef MOTIF_POPUP
1715     XmMenuPosition(menu->submenu_id, gui_x11_get_last_mouse_event());
1716     XtManageChild(menu->submenu_id);
1717 #endif
1718 }
1719 
1720 #endif /* FEAT_MENU */
1721 
1722 /*
1723  * Set the menu and scrollbar colors to their default values.
1724  */
1725     void
1726 gui_mch_def_colors()
1727 {
1728     if (gui.in_use)
1729     {
1730 	/* Use the values saved when starting up.  These should come from the
1731 	 * window manager or a resources file. */
1732 	gui.menu_fg_pixel = gui.menu_def_fg_pixel;
1733 	gui.menu_bg_pixel = gui.menu_def_bg_pixel;
1734 	gui.scroll_fg_pixel = gui.scroll_def_fg_pixel;
1735 	gui.scroll_bg_pixel = gui.scroll_def_bg_pixel;
1736 #ifdef FEAT_BEVAL
1737 	gui.tooltip_fg_pixel =
1738 			gui_get_color((char_u *)gui.rsrc_tooltip_fg_name);
1739 	gui.tooltip_bg_pixel =
1740 			gui_get_color((char_u *)gui.rsrc_tooltip_bg_name);
1741 #endif
1742     }
1743 }
1744 
1745 
1746 /*
1747  * Scrollbar stuff.
1748  */
1749 
1750     void
1751 gui_mch_set_scrollbar_thumb(sb, val, size, max)
1752     scrollbar_T *sb;
1753     long	val;
1754     long	size;
1755     long	max;
1756 {
1757     if (sb->id != (Widget)0)
1758 	XtVaSetValues(sb->id,
1759 		  XmNvalue, val,
1760 		  XmNsliderSize, size,
1761 		  XmNpageIncrement, (size > 2 ? size - 2 : 1),
1762 		  XmNmaximum, max + 1,	    /* Motif has max one past the end */
1763 		  NULL);
1764 }
1765 
1766     void
1767 gui_mch_set_scrollbar_pos(sb, x, y, w, h)
1768     scrollbar_T *sb;
1769     int		x;
1770     int		y;
1771     int		w;
1772     int		h;
1773 {
1774     if (sb->id != (Widget)0)
1775     {
1776 	if (sb->type == SBAR_LEFT || sb->type == SBAR_RIGHT)
1777 	{
1778 	    if (y == 0)
1779 		h -= gui.border_offset;
1780 	    else
1781 		y -= gui.border_offset;
1782 	    XtVaSetValues(sb->id,
1783 			  XmNtopOffset, y,
1784 			  XmNbottomOffset, -y - h,
1785 			  XmNwidth, w,
1786 			  NULL);
1787 	}
1788 	else
1789 	    XtVaSetValues(sb->id,
1790 			  XmNtopOffset, y,
1791 			  XmNleftOffset, x,
1792 			  XmNrightOffset, gui.which_scrollbars[SBAR_RIGHT]
1793 						    ? gui.scrollbar_width : 0,
1794 			  XmNheight, h,
1795 			  NULL);
1796 	XtManageChild(sb->id);
1797     }
1798 }
1799 
1800     void
1801 gui_mch_enable_scrollbar(sb, flag)
1802     scrollbar_T *sb;
1803     int		flag;
1804 {
1805     Arg		args[16];
1806     int		n;
1807 
1808     if (sb->id != (Widget)0)
1809     {
1810 	n = 0;
1811 	if (flag)
1812 	{
1813 	    switch (sb->type)
1814 	    {
1815 		case SBAR_LEFT:
1816 		    XtSetArg(args[n], XmNleftOffset, gui.scrollbar_width); n++;
1817 		    break;
1818 
1819 		case SBAR_RIGHT:
1820 		    XtSetArg(args[n], XmNrightOffset, gui.scrollbar_width); n++;
1821 		    break;
1822 
1823 		case SBAR_BOTTOM:
1824 		    XtSetArg(args[n], XmNbottomOffset, gui.scrollbar_height);n++;
1825 		    break;
1826 	    }
1827 	    XtSetValues(textArea, args, n);
1828 	    XtManageChild(sb->id);
1829 	}
1830 	else
1831 	{
1832 	    if (!gui.which_scrollbars[sb->type])
1833 	    {
1834 		/* The scrollbars of this type are all disabled, adjust the
1835 		 * textArea attachment offset. */
1836 		switch (sb->type)
1837 		{
1838 		    case SBAR_LEFT:
1839 			XtSetArg(args[n], XmNleftOffset, 0); n++;
1840 			break;
1841 
1842 		    case SBAR_RIGHT:
1843 			XtSetArg(args[n], XmNrightOffset, 0); n++;
1844 			break;
1845 
1846 		    case SBAR_BOTTOM:
1847 			XtSetArg(args[n], XmNbottomOffset, 0);n++;
1848 			break;
1849 		}
1850 		XtSetValues(textArea, args, n);
1851 	    }
1852 	    XtUnmanageChild(sb->id);
1853 	}
1854     }
1855 }
1856 
1857     void
1858 gui_mch_create_scrollbar(sb, orient)
1859     scrollbar_T *sb;
1860     int		orient;	/* SBAR_VERT or SBAR_HORIZ */
1861 {
1862     Arg		args[16];
1863     int		n;
1864 
1865     n = 0;
1866     XtSetArg(args[n], XmNminimum, 0); n++;
1867     XtSetArg(args[n], XmNorientation,
1868 	    (orient == SBAR_VERT) ? XmVERTICAL : XmHORIZONTAL); n++;
1869 
1870     switch (sb->type)
1871     {
1872 	case SBAR_LEFT:
1873 	    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
1874 	    XtSetArg(args[n], XmNbottomAttachment, XmATTACH_OPPOSITE_FORM); n++;
1875 	    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
1876 	    break;
1877 
1878 	case SBAR_RIGHT:
1879 	    XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
1880 	    XtSetArg(args[n], XmNbottomAttachment, XmATTACH_OPPOSITE_FORM); n++;
1881 	    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
1882 	    break;
1883 
1884 	case SBAR_BOTTOM:
1885 	    XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
1886 	    XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
1887 	    XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
1888 	    break;
1889     }
1890 
1891     sb->id = XtCreateWidget("scrollBar",
1892 	    xmScrollBarWidgetClass, textAreaForm, args, n);
1893 
1894     /* Remember the default colors, needed for ":hi clear". */
1895     if (gui.scroll_def_bg_pixel == (guicolor_T)0
1896 	    && gui.scroll_def_fg_pixel == (guicolor_T)0)
1897 	XtVaGetValues(sb->id,
1898 		XmNbackground, &gui.scroll_def_bg_pixel,
1899 		XmNforeground, &gui.scroll_def_fg_pixel,
1900 		NULL);
1901 
1902     if (sb->id != (Widget)0)
1903     {
1904 	gui_mch_set_scrollbar_colors(sb);
1905 	XtAddCallback(sb->id, XmNvalueChangedCallback,
1906 		      scroll_cb, (XtPointer)sb->ident);
1907 	XtAddCallback(sb->id, XmNdragCallback,
1908 		      scroll_cb, (XtPointer)sb->ident);
1909 	XtAddEventHandler(sb->id, KeyPressMask, FALSE, gui_x11_key_hit_cb,
1910 	    (XtPointer)0);
1911     }
1912 }
1913 
1914 #if defined(FEAT_WINDOWS) || defined(PROTO)
1915     void
1916 gui_mch_destroy_scrollbar(sb)
1917     scrollbar_T *sb;
1918 {
1919     if (sb->id != (Widget)0)
1920 	XtDestroyWidget(sb->id);
1921 }
1922 #endif
1923 
1924     void
1925 gui_mch_set_scrollbar_colors(sb)
1926     scrollbar_T *sb;
1927 {
1928     if (sb->id != (Widget)0)
1929     {
1930 	if (gui.scroll_bg_pixel != INVALCOLOR)
1931 	{
1932 #if (XmVersion>=1002)
1933 	    XmChangeColor(sb->id, gui.scroll_bg_pixel);
1934 #else
1935 	    XtVaSetValues(sb->id,
1936 		    XmNtroughColor, gui.scroll_bg_pixel,
1937 		    NULL);
1938 #endif
1939 	}
1940 
1941 	if (gui.scroll_fg_pixel != INVALCOLOR)
1942 	    XtVaSetValues(sb->id,
1943 		    XmNforeground, gui.scroll_fg_pixel,
1944 #if (XmVersion<1002)
1945 		    XmNbackground, gui.scroll_fg_pixel,
1946 #endif
1947 		    NULL);
1948     }
1949 
1950     /* This is needed for the rectangle below the vertical scrollbars. */
1951     if (sb == &gui.bottom_sbar && textAreaForm != (Widget)0)
1952 	gui_motif_scroll_colors(textAreaForm);
1953 }
1954 
1955 /*
1956  * Miscellaneous stuff:
1957  */
1958 
1959     Window
1960 gui_x11_get_wid()
1961 {
1962     return(XtWindow(textArea));
1963 }
1964 
1965 /*
1966  * Look for a widget in the widget tree w, with a mnemonic matching keycode.
1967  * When one is found, simulate a button press on that widget and give it the
1968  * keyboard focus.  If the mnemonic is on a label, look in the userData field
1969  * of the label to see if it points to another widget, and give that the focus.
1970  */
1971     static void
1972 do_mnemonic(Widget w, unsigned int keycode)
1973 {
1974     WidgetList	    children;
1975     int		    numChildren, i;
1976     Boolean	    isMenu;
1977     KeySym	    mnemonic = '\0';
1978     char	    mneString[2];
1979     Widget	    userData;
1980     unsigned char   rowColType;
1981 
1982     if (XtIsComposite(w))
1983     {
1984 	if (XtClass(w) == xmRowColumnWidgetClass)
1985 	{
1986 	    XtVaGetValues(w, XmNrowColumnType, &rowColType, NULL);
1987 	    isMenu = (rowColType != (unsigned char)XmWORK_AREA);
1988 	}
1989 	else
1990 	    isMenu = False;
1991 	if (!isMenu)
1992 	{
1993 	    XtVaGetValues(w, XmNchildren, &children, XmNnumChildren,
1994 			  &numChildren, NULL);
1995 	    for (i = 0; i < numChildren; i++)
1996 		do_mnemonic(children[i], keycode);
1997 	}
1998     }
1999     else
2000     {
2001 	XtVaGetValues(w, XmNmnemonic, &mnemonic, NULL);
2002 	if (mnemonic != '\0')
2003 	{
2004 	    mneString[0] = mnemonic;
2005 	    mneString[1] = '\0';
2006 	    if (XKeysymToKeycode(XtDisplay(XtParent(w)),
2007 				       XStringToKeysym(mneString)) == keycode)
2008 	    {
2009 		if (XtClass(w) == xmLabelWidgetClass
2010 			|| XtClass(w) == xmLabelGadgetClass)
2011 		{
2012 		    XtVaGetValues(w, XmNuserData, &userData, NULL);
2013 		    if (userData != NULL && XtIsWidget(userData))
2014 			XmProcessTraversal(userData, XmTRAVERSE_CURRENT);
2015 		}
2016 		else
2017 		{
2018 		    XKeyPressedEvent keyEvent;
2019 
2020 		    XmProcessTraversal(w, XmTRAVERSE_CURRENT);
2021 
2022 		    vim_memset((char *) &keyEvent, 0, sizeof(XKeyPressedEvent));
2023 		    keyEvent.type = KeyPress;
2024 		    keyEvent.serial = 1;
2025 		    keyEvent.send_event = True;
2026 		    keyEvent.display = XtDisplay(w);
2027 		    keyEvent.window = XtWindow(w);
2028 		    XtCallActionProc(w, "Activate", (XEvent *) & keyEvent,
2029 								     NULL, 0);
2030 		}
2031 	    }
2032 	}
2033     }
2034 }
2035 
2036 /*
2037  * Callback routine for dialog mnemonic processing.
2038  */
2039     static void
2040 mnemonic_event(Widget w, XtPointer call_data UNUSED, XKeyEvent *event)
2041 {
2042     do_mnemonic(w, event->keycode);
2043 }
2044 
2045 
2046 /*
2047  * Search the widget tree under w for widgets with mnemonics.  When found, add
2048  * a passive grab to the dialog widget for the mnemonic character, thus
2049  * directing mnemonic events to the dialog widget.
2050  */
2051     static void
2052 add_mnemonic_grabs(Widget dialog, Widget w)
2053 {
2054     char	    mneString[2];
2055     WidgetList	    children;
2056     int		    numChildren, i;
2057     Boolean	    isMenu;
2058     KeySym	    mnemonic = '\0';
2059     unsigned char   rowColType;
2060 
2061     if (XtIsComposite(w))
2062     {
2063 	if (XtClass(w) == xmRowColumnWidgetClass)
2064 	{
2065 	    XtVaGetValues(w, XmNrowColumnType, &rowColType, NULL);
2066 	    isMenu = (rowColType != (unsigned char)XmWORK_AREA);
2067 	}
2068 	else
2069 	    isMenu = False;
2070 	if (!isMenu)
2071 	{
2072 	    XtVaGetValues(w, XmNchildren, &children, XmNnumChildren,
2073 							  &numChildren, NULL);
2074 	    for (i = 0; i < numChildren; i++)
2075 		add_mnemonic_grabs(dialog, children[i]);
2076 	}
2077     }
2078     else
2079     {
2080 	XtVaGetValues(w, XmNmnemonic, &mnemonic, NULL);
2081 	if (mnemonic != '\0')
2082 	{
2083 	    mneString[0] = mnemonic;
2084 	    mneString[1] = '\0';
2085 	    XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog),
2086 						  XStringToKeysym(mneString)),
2087 		    Mod1Mask, True, GrabModeAsync, GrabModeAsync);
2088 	}
2089     }
2090 }
2091 
2092 /*
2093  * Add a handler for mnemonics in a dialog.  Motif itself only handles
2094  * mnemonics in menus. Mnemonics added or changed after this call will be
2095  * ignored.
2096  *
2097  * To add a mnemonic to a text field or list, set the XmNmnemonic resource on
2098  * the appropriate label and set the XmNuserData resource of the label to the
2099  * widget to get the focus when the mnemonic is typed.
2100  */
2101     static void
2102 activate_dialog_mnemonics(Widget dialog)
2103 {
2104     if (!dialog)
2105 	return;
2106 
2107     XtAddEventHandler(dialog, KeyPressMask, False,
2108 			   (XtEventHandler) mnemonic_event, (XtPointer) NULL);
2109     add_mnemonic_grabs(dialog, dialog);
2110 }
2111 
2112 /*
2113  * Removes the event handler and key-grabs for dialog mnemonic handling.
2114  */
2115     static void
2116 suppress_dialog_mnemonics(Widget dialog)
2117 {
2118     if (!dialog)
2119 	return;
2120 
2121     XtUngrabKey(dialog, AnyKey, Mod1Mask);
2122     XtRemoveEventHandler(dialog, KeyPressMask, False,
2123 			   (XtEventHandler) mnemonic_event, (XtPointer) NULL);
2124 }
2125 
2126 #if defined(FEAT_BROWSE) || defined(FEAT_GUI_DIALOG)
2127 static void set_fontlist __ARGS((Widget wg));
2128 
2129 /*
2130  * Use the 'guifont' or 'guifontset' as a fontlist for a dialog widget.
2131  */
2132     static void
2133 set_fontlist(id)
2134     Widget id;
2135 {
2136     XmFontList fl;
2137 
2138 #ifdef FONTSET_ALWAYS
2139     if (gui.fontset != NOFONTSET)
2140     {
2141 	fl = gui_motif_fontset2fontlist((XFontSet *)&gui.fontset);
2142 	if (fl != NULL)
2143 	{
2144 	    if (XtIsManaged(id))
2145 	    {
2146 		XtUnmanageChild(id);
2147 		XtVaSetValues(id, XmNfontList, fl, NULL);
2148 		/* We should force the widget to recalculate it's
2149 		 * geometry now. */
2150 		XtManageChild(id);
2151 	    }
2152 	    else
2153 		XtVaSetValues(id, XmNfontList, fl, NULL);
2154 	    XmFontListFree(fl);
2155 	}
2156     }
2157 #else
2158     if (gui.norm_font != NOFONT)
2159     {
2160 	fl = gui_motif_create_fontlist((XFontStruct *)gui.norm_font);
2161 	if (fl != NULL)
2162 	{
2163 	    if (XtIsManaged(id))
2164 	    {
2165 		XtUnmanageChild(id);
2166 		XtVaSetValues(id, XmNfontList, fl, NULL);
2167 		/* We should force the widget to recalculate it's
2168 		 * geometry now. */
2169 		XtManageChild(id);
2170 	    }
2171 	    else
2172 		XtVaSetValues(id, XmNfontList, fl, NULL);
2173 	    XmFontListFree(fl);
2174 	}
2175     }
2176 #endif
2177 }
2178 #endif
2179 
2180 #if defined(FEAT_BROWSE) || defined(PROTO)
2181 
2182 /*
2183  * file selector related stuff
2184  */
2185 
2186 #include <Xm/FileSB.h>
2187 #include <Xm/XmStrDefs.h>
2188 
2189 typedef struct dialog_callback_arg
2190 {
2191     char *  args;   /* not used right now */
2192     int	    id;
2193 } dcbarg_T;
2194 
2195 static Widget dialog_wgt;
2196 static char *browse_fname = NULL;
2197 static XmStringCharSet charset = (XmStringCharSet) XmSTRING_DEFAULT_CHARSET;
2198 				/* used to set up XmStrings */
2199 
2200 static void DialogCancelCB __ARGS((Widget, XtPointer, XtPointer));
2201 static void DialogAcceptCB __ARGS((Widget, XtPointer, XtPointer));
2202 
2203 /*
2204  * This function is used to translate the predefined label text of the
2205  * precomposed dialogs. We do this explicitly to allow:
2206  *
2207  * - usage of gettext for translation, as in all the other places.
2208  *
2209  * - equalize the messages between different GUI implementations as far as
2210  * possible.
2211  */
2212 static void set_predefined_label __ARGS((Widget parent, String name, char *new_label));
2213 
2214 static void
2215 set_predefined_label(parent, name, new_label)
2216     Widget  parent;
2217     String  name;
2218     char    *new_label;
2219 {
2220     XmString	str;
2221     Widget	w;
2222     char_u	*p, *next;
2223     KeySym	mnemonic = NUL;
2224 
2225     w = XtNameToWidget(parent, name);
2226 
2227     if (!w)
2228 	return;
2229 
2230     p = vim_strsave((char_u *)new_label);
2231     if (p == NULL)
2232 	return;
2233     for (next = p; *next; ++next)
2234     {
2235 	if (*next == DLG_HOTKEY_CHAR)
2236 	{
2237 	    int len = STRLEN(next);
2238 
2239 	    if (len > 0)
2240 	    {
2241 		mch_memmove(next, next + 1, len);
2242 		mnemonic = next[0];
2243 	    }
2244 	}
2245     }
2246 
2247     str = XmStringCreate((char *)p, STRING_TAG);
2248     vim_free(p);
2249 
2250     if (str != NULL)
2251     {
2252 	XtVaSetValues(w,
2253 		XmNlabelString, str,
2254 		XmNmnemonic, mnemonic,
2255 		NULL);
2256 	XmStringFree(str);
2257     }
2258     gui_motif_menu_fontlist(w);
2259 }
2260 
2261 static void
2262 set_predefined_fontlist(parent, name)
2263     Widget parent;
2264     String name;
2265 {
2266     Widget w;
2267     w = XtNameToWidget(parent, name);
2268 
2269     if (!w)
2270 	return;
2271 
2272     set_fontlist(w);
2273 }
2274 
2275 /*
2276  * Put up a file requester.
2277  * Returns the selected name in allocated memory, or NULL for Cancel.
2278  */
2279     char_u *
2280 gui_mch_browse(saving, title, dflt, ext, initdir, filter)
2281     int		saving UNUSED;	/* select file to write */
2282     char_u	*title;		/* title for the window */
2283     char_u	*dflt;		/* default name */
2284     char_u	*ext UNUSED;	/* not used (extension added) */
2285     char_u	*initdir;	/* initial directory, NULL for current dir */
2286     char_u	*filter;	/* file name filter */
2287 {
2288     char_u	dirbuf[MAXPATHL];
2289     char_u	dfltbuf[MAXPATHL];
2290     char_u	*pattern;
2291     char_u	*tofree = NULL;
2292 
2293     /* There a difference between the resource name and value, Therefore, we
2294      * avoid to (ab-)use the (maybe internationalized!) dialog title as a
2295      * dialog name.
2296      */
2297 
2298     dialog_wgt = XmCreateFileSelectionDialog(vimShell, "browseDialog", NULL, 0);
2299 
2300     if (initdir == NULL || *initdir == NUL)
2301     {
2302 	mch_dirname(dirbuf, MAXPATHL);
2303 	initdir = dirbuf;
2304     }
2305 
2306     if (dflt == NULL)
2307 	dflt = (char_u *)"";
2308     else if (STRLEN(initdir) + STRLEN(dflt) + 2 < MAXPATHL)
2309     {
2310 	/* The default selection should be the full path, "dflt" is only the
2311 	 * file name. */
2312 	STRCPY(dfltbuf, initdir);
2313 	add_pathsep(dfltbuf);
2314 	STRCAT(dfltbuf, dflt);
2315 	dflt = dfltbuf;
2316     }
2317 
2318     /* Can only use one pattern for a file name.  Get the first pattern out of
2319      * the filter.  An empty pattern means everything matches. */
2320     if (filter == NULL)
2321 	pattern = (char_u *)"";
2322     else
2323     {
2324 	char_u	*s, *p;
2325 
2326 	s = filter;
2327 	for (p = filter; *p != NUL; ++p)
2328 	{
2329 	    if (*p == '\t')	/* end of description, start of pattern */
2330 		s = p + 1;
2331 	    if (*p == ';' || *p == '\n')	/* end of (first) pattern */
2332 		break;
2333 	}
2334 	pattern = vim_strnsave(s, p - s);
2335 	tofree = pattern;
2336 	if (pattern == NULL)
2337 	    pattern = (char_u *)"";
2338     }
2339 
2340     XtVaSetValues(dialog_wgt,
2341 	XtVaTypedArg,
2342 	    XmNdirectory, XmRString, (char *)initdir, STRLEN(initdir) + 1,
2343 	XtVaTypedArg,
2344 	    XmNdirSpec,	XmRString, (char *)dflt, STRLEN(dflt) + 1,
2345 	XtVaTypedArg,
2346 	    XmNpattern,	XmRString, (char *)pattern, STRLEN(pattern) + 1,
2347 	XtVaTypedArg,
2348 	    XmNdialogTitle, XmRString, (char *)title, STRLEN(title) + 1,
2349 	NULL);
2350 
2351     set_predefined_label(dialog_wgt, "Apply", _("&Filter"));
2352     set_predefined_label(dialog_wgt, "Cancel", _("&Cancel"));
2353     set_predefined_label(dialog_wgt, "Dir", _("Directories"));
2354     set_predefined_label(dialog_wgt, "FilterLabel", _("Filter"));
2355     set_predefined_label(dialog_wgt, "Help", _("&Help"));
2356     set_predefined_label(dialog_wgt, "Items", _("Files"));
2357     set_predefined_label(dialog_wgt, "OK", _("&OK"));
2358     set_predefined_label(dialog_wgt, "Selection", _("Selection"));
2359 
2360     /* This is to save us from silly external settings using not fixed with
2361      * fonts for file selection.
2362      */
2363     set_predefined_fontlist(dialog_wgt, "DirListSW.DirList");
2364     set_predefined_fontlist(dialog_wgt, "ItemsListSW.ItemsList");
2365 
2366     gui_motif_menu_colors(dialog_wgt);
2367     if (gui.scroll_bg_pixel != INVALCOLOR)
2368 	XtVaSetValues(dialog_wgt, XmNtroughColor, gui.scroll_bg_pixel, NULL);
2369 
2370     XtAddCallback(dialog_wgt, XmNokCallback, DialogAcceptCB, (XtPointer)0);
2371     XtAddCallback(dialog_wgt, XmNcancelCallback, DialogCancelCB, (XtPointer)0);
2372     /* We have no help in this window, so hide help button */
2373     XtUnmanageChild(XmFileSelectionBoxGetChild(dialog_wgt,
2374 					(unsigned char)XmDIALOG_HELP_BUTTON));
2375 
2376     manage_centered(dialog_wgt);
2377     activate_dialog_mnemonics(dialog_wgt);
2378 
2379     /* sit in a loop until the dialog box has gone away */
2380     do
2381     {
2382 	XtAppProcessEvent(XtWidgetToApplicationContext(dialog_wgt),
2383 	    (XtInputMask)XtIMAll);
2384     } while (XtIsManaged(dialog_wgt));
2385 
2386     suppress_dialog_mnemonics(dialog_wgt);
2387     XtDestroyWidget(dialog_wgt);
2388     vim_free(tofree);
2389 
2390     if (browse_fname == NULL)
2391 	return NULL;
2392     return vim_strsave((char_u *)browse_fname);
2393 }
2394 
2395 /*
2396  * The code below was originally taken from
2397  *	/usr/examples/motif/xmsamplers/xmeditor.c
2398  * on Digital Unix 4.0d, but heavily modified.
2399  */
2400 
2401 /*
2402  * Process callback from Dialog cancel actions.
2403  */
2404     static void
2405 DialogCancelCB(w, client_data, call_data)
2406     Widget	w UNUSED;		/*  widget id		*/
2407     XtPointer	client_data UNUSED;	/*  data from application   */
2408     XtPointer	call_data UNUSED;	/*  data from widget class  */
2409 {
2410     if (browse_fname != NULL)
2411     {
2412 	XtFree(browse_fname);
2413 	browse_fname = NULL;
2414     }
2415     XtUnmanageChild(dialog_wgt);
2416 }
2417 
2418 /*
2419  * Process callback from Dialog actions.
2420  */
2421     static void
2422 DialogAcceptCB(w, client_data, call_data)
2423     Widget	w UNUSED;		/*  widget id		*/
2424     XtPointer	client_data UNUSED;	/*  data from application   */
2425     XtPointer	call_data;		/*  data from widget class  */
2426 {
2427     XmFileSelectionBoxCallbackStruct *fcb;
2428 
2429     if (browse_fname != NULL)
2430     {
2431 	XtFree(browse_fname);
2432 	browse_fname = NULL;
2433     }
2434     fcb = (XmFileSelectionBoxCallbackStruct *)call_data;
2435 
2436     /* get the filename from the file selection box */
2437     XmStringGetLtoR(fcb->value, charset, &browse_fname);
2438 
2439     /* popdown the file selection box */
2440     XtUnmanageChild(dialog_wgt);
2441 }
2442 
2443 #endif /* FEAT_BROWSE */
2444 
2445 #if defined(FEAT_GUI_DIALOG) || defined(PROTO)
2446 
2447 static int	dialogStatus;
2448 
2449 static void keyhit_callback __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *cont));
2450 static void butproc __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
2451 
2452 /*
2453  * Callback function for the textfield.  When CR is hit this works like
2454  * hitting the "OK" button, ESC like "Cancel".
2455  */
2456     static void
2457 keyhit_callback(w, client_data, event, cont)
2458     Widget		w;
2459     XtPointer		client_data UNUSED;
2460     XEvent		*event;
2461     Boolean		*cont UNUSED;
2462 {
2463     char	buf[2];
2464     KeySym	key_sym;
2465 
2466     if (XLookupString(&(event->xkey), buf, 2, &key_sym, NULL) == 1)
2467     {
2468 	if (*buf == CAR)
2469 	    dialogStatus = 1;
2470 	else if (*buf == ESC)
2471 	    dialogStatus = 2;
2472     }
2473     if ((key_sym == XK_Left || key_sym == XK_Right)
2474 	    && !(event->xkey.state & ShiftMask))
2475 	XmTextFieldClearSelection(w, XtLastTimestampProcessed(gui.dpy));
2476 }
2477 
2478     static void
2479 butproc(w, client_data, call_data)
2480     Widget	w UNUSED;
2481     XtPointer	client_data;
2482     XtPointer	call_data UNUSED;
2483 {
2484     dialogStatus = (int)(long)client_data + 1;
2485 }
2486 
2487 #ifdef HAVE_XPM
2488 
2489 static Widget create_pixmap_label(Widget parent, String name, char **data, ArgList args, Cardinal arg);
2490 
2491     static Widget
2492 create_pixmap_label(parent, name, data, args, arg)
2493     Widget	parent;
2494     String	name;
2495     char	**data;
2496     ArgList	args;
2497     Cardinal	arg;
2498 {
2499     Widget		label;
2500     Display		*dsp;
2501     Screen		*scr;
2502     int			depth;
2503     Pixmap		pixmap = 0;
2504     XpmAttributes	attr;
2505     Boolean		rs;
2506     XpmColorSymbol	color[5] =
2507     {
2508 	{"none", NULL, 0},
2509 	{"iconColor1", NULL, 0},
2510 	{"bottomShadowColor", NULL, 0},
2511 	{"topShadowColor", NULL, 0},
2512 	{"selectColor", NULL, 0}
2513     };
2514 
2515     label = XmCreateLabelGadget(parent, name, args, arg);
2516 
2517     /*
2518      * We need to be careful here, since in case of gadgets, there is
2519      * no way to get the background color directly from the widget itself.
2520      * In such cases we get it from The Core part of his parent instead.
2521      */
2522     dsp = XtDisplayOfObject(label);
2523     scr = XtScreenOfObject(label);
2524     XtVaGetValues(XtIsSubclass(label, coreWidgetClass)
2525 	    ?  label : XtParent(label),
2526 		  XmNdepth, &depth,
2527 		  XmNbackground, &color[0].pixel,
2528 		  XmNforeground, &color[1].pixel,
2529 		  XmNbottomShadowColor, &color[2].pixel,
2530 		  XmNtopShadowColor, &color[3].pixel,
2531 		  XmNhighlight, &color[4].pixel,
2532 		  NULL);
2533 
2534     attr.valuemask = XpmColorSymbols | XpmCloseness | XpmDepth;
2535     attr.colorsymbols = color;
2536     attr.numsymbols = 5;
2537     attr.closeness = 65535;
2538     attr.depth = depth;
2539     XpmCreatePixmapFromData(dsp, RootWindowOfScreen(scr),
2540 		    data, &pixmap, NULL, &attr);
2541 
2542     XtVaGetValues(label, XmNrecomputeSize, &rs, NULL);
2543     XtVaSetValues(label, XmNrecomputeSize, True, NULL);
2544     XtVaSetValues(label,
2545 	    XmNlabelType, XmPIXMAP,
2546 	    XmNlabelPixmap, pixmap,
2547 	    NULL);
2548     XtVaSetValues(label, XmNrecomputeSize, rs, NULL);
2549 
2550     return label;
2551 }
2552 #endif
2553 
2554     int
2555 gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield, ex_cmd)
2556     int		type UNUSED;
2557     char_u	*title;
2558     char_u	*message;
2559     char_u	*button_names;
2560     int		dfltbutton;
2561     char_u	*textfield;		/* buffer of size IOSIZE */
2562     int		ex_cmd UNUSED;
2563 {
2564     char_u		*buts;
2565     char_u		*p, *next;
2566     XtAppContext	app;
2567     XmString		label;
2568     int			butcount;
2569     Widget		w;
2570     Widget		dialogform = NULL;
2571     Widget		form = NULL;
2572     Widget		dialogtextfield = NULL;
2573     Widget		*buttons;
2574     Widget		sep_form = NULL;
2575     Boolean		vertical;
2576     Widget		separator = NULL;
2577     int			n;
2578     Arg			args[6];
2579 #ifdef HAVE_XPM
2580     char		**icon_data = NULL;
2581     Widget		dialogpixmap = NULL;
2582 #endif
2583 
2584     if (title == NULL)
2585 	title = (char_u *)_("Vim dialog");
2586 
2587     /* if our pointer is currently hidden, then we should show it. */
2588     gui_mch_mousehide(FALSE);
2589 
2590     dialogform = XmCreateFormDialog(vimShell, (char *)"dialog", NULL, 0);
2591 
2592     /* Check 'v' flag in 'guioptions': vertical button placement. */
2593     vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
2594 
2595     /* Set the title of the Dialog window */
2596     label = XmStringCreateSimple((char *)title);
2597     if (label == NULL)
2598 	return -1;
2599     XtVaSetValues(dialogform,
2600 	    XmNdialogTitle, label,
2601 	    XmNhorizontalSpacing, 4,
2602 	    XmNverticalSpacing, vertical ? 0 : 4,
2603 	    NULL);
2604     XmStringFree(label);
2605 
2606     /* make a copy, so that we can insert NULs */
2607     buts = vim_strsave(button_names);
2608     if (buts == NULL)
2609 	return -1;
2610 
2611     /* Count the number of buttons and allocate buttons[]. */
2612     butcount = 1;
2613     for (p = buts; *p; ++p)
2614 	if (*p == DLG_BUTTON_SEP)
2615 	    ++butcount;
2616     buttons = (Widget *)alloc((unsigned)(butcount * sizeof(Widget)));
2617     if (buttons == NULL)
2618     {
2619 	vim_free(buts);
2620 	return -1;
2621     }
2622 
2623     /*
2624      * Create the buttons.
2625      */
2626     sep_form = (Widget) 0;
2627     p = buts;
2628     for (butcount = 0; *p; ++butcount)
2629     {
2630 	KeySym mnemonic = NUL;
2631 
2632 	for (next = p; *next; ++next)
2633 	{
2634 	    if (*next == DLG_HOTKEY_CHAR)
2635 	    {
2636 		int len = STRLEN(next);
2637 
2638 		if (len > 0)
2639 		{
2640 		    mch_memmove(next, next + 1, len);
2641 		    mnemonic = next[0];
2642 		}
2643 	    }
2644 	    if (*next == DLG_BUTTON_SEP)
2645 	    {
2646 		*next++ = NUL;
2647 		break;
2648 	    }
2649 	}
2650 	label = XmStringCreate(_((char *)p), STRING_TAG);
2651 	if (label == NULL)
2652 	    break;
2653 
2654 	buttons[butcount] = XtVaCreateManagedWidget("button",
2655 		xmPushButtonWidgetClass, dialogform,
2656 		XmNlabelString, label,
2657 		XmNmnemonic, mnemonic,
2658 		XmNbottomAttachment, XmATTACH_FORM,
2659 		XmNbottomOffset, 4,
2660 		XmNshowAsDefault, butcount == dfltbutton - 1,
2661 		XmNdefaultButtonShadowThickness, 1,
2662 		NULL);
2663 	XmStringFree(label);
2664 	gui_motif_menu_fontlist(buttons[butcount]);
2665 
2666 	/* Layout properly. */
2667 
2668 	if (butcount > 0)
2669 	{
2670 	    if (vertical)
2671 		XtVaSetValues(buttons[butcount],
2672 			XmNtopWidget, buttons[butcount - 1],
2673 			NULL);
2674 	    else
2675 	    {
2676 		if (*next == NUL)
2677 		{
2678 		    XtVaSetValues(buttons[butcount],
2679 			    XmNrightAttachment, XmATTACH_FORM,
2680 			    XmNrightOffset, 4,
2681 			    NULL);
2682 
2683 		    /* fill in a form as invisible separator */
2684 		    sep_form = XtVaCreateWidget("separatorForm",
2685 			    xmFormWidgetClass,	dialogform,
2686 			    XmNleftAttachment, XmATTACH_WIDGET,
2687 			    XmNleftWidget, buttons[butcount - 1],
2688 			    XmNrightAttachment, XmATTACH_WIDGET,
2689 			    XmNrightWidget, buttons[butcount],
2690 			    XmNbottomAttachment, XmATTACH_FORM,
2691 			    XmNbottomOffset, 4,
2692 			    NULL);
2693 		    XtManageChild(sep_form);
2694 		}
2695 		else
2696 		{
2697 		    XtVaSetValues(buttons[butcount],
2698 			    XmNleftAttachment, XmATTACH_WIDGET,
2699 			    XmNleftWidget, buttons[butcount - 1],
2700 			    NULL);
2701 		}
2702 	    }
2703 	}
2704 	else if (!vertical)
2705 	{
2706 	    if (*next == NUL)
2707 	    {
2708 		XtVaSetValues(buttons[0],
2709 			XmNrightAttachment, XmATTACH_FORM,
2710 			XmNrightOffset, 4,
2711 			NULL);
2712 
2713 		/* fill in a form as invisible separator */
2714 		sep_form = XtVaCreateWidget("separatorForm",
2715 			xmFormWidgetClass, dialogform,
2716 			XmNleftAttachment, XmATTACH_FORM,
2717 			XmNleftOffset, 4,
2718 			XmNrightAttachment, XmATTACH_WIDGET,
2719 			XmNrightWidget, buttons[0],
2720 			XmNbottomAttachment, XmATTACH_FORM,
2721 			XmNbottomOffset, 4,
2722 			NULL);
2723 		XtManageChild(sep_form);
2724 	    }
2725 	    else
2726 		XtVaSetValues(buttons[0],
2727 			XmNleftAttachment, XmATTACH_FORM,
2728 			XmNleftOffset, 4,
2729 			NULL);
2730 	}
2731 
2732 	XtAddCallback(buttons[butcount], XmNactivateCallback,
2733 			  (XtCallbackProc)butproc, (XtPointer)(long)butcount);
2734 	p = next;
2735     }
2736     vim_free(buts);
2737 
2738     separator = (Widget) 0;
2739     if (butcount > 0)
2740     {
2741 	/* Create the separator for beauty. */
2742 	n = 0;
2743 	XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
2744 	XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
2745 	XtSetArg(args[n], XmNbottomWidget, buttons[0]); n++;
2746 	XtSetArg(args[n], XmNbottomOffset, 4); n++;
2747 	XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
2748 	XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
2749 	separator = XmCreateSeparatorGadget(dialogform, "separator", args, n);
2750 	XtManageChild(separator);
2751     }
2752 
2753     if (textfield != NULL)
2754     {
2755 	dialogtextfield = XtVaCreateWidget("textField",
2756 		xmTextFieldWidgetClass, dialogform,
2757 		XmNleftAttachment, XmATTACH_FORM,
2758 		XmNrightAttachment, XmATTACH_FORM,
2759 		NULL);
2760 	if (butcount > 0)
2761 	    XtVaSetValues(dialogtextfield,
2762 		    XmNbottomAttachment, XmATTACH_WIDGET,
2763 		    XmNbottomWidget, separator,
2764 		    NULL);
2765 	else
2766 	    XtVaSetValues(dialogtextfield,
2767 		    XmNbottomAttachment, XmATTACH_FORM,
2768 		    NULL);
2769 
2770 	set_fontlist(dialogtextfield);
2771 	XmTextFieldSetString(dialogtextfield, (char *)textfield);
2772 	XtManageChild(dialogtextfield);
2773 	XtAddEventHandler(dialogtextfield, KeyPressMask, False,
2774 			    (XtEventHandler)keyhit_callback, (XtPointer)NULL);
2775     }
2776 
2777     /* Form holding both message and pixmap labels */
2778     form = XtVaCreateWidget("separatorForm",
2779 	    xmFormWidgetClass, dialogform,
2780 	    XmNleftAttachment, XmATTACH_FORM,
2781 	    XmNrightAttachment, XmATTACH_FORM,
2782 	    XmNtopAttachment, XmATTACH_FORM,
2783 	    NULL);
2784     XtManageChild(form);
2785 
2786 #ifdef HAVE_XPM
2787     /* Add a pixmap, left of the message. */
2788     switch (type)
2789     {
2790 	case VIM_GENERIC:
2791 	    icon_data = generic_xpm;
2792 	    break;
2793 	case VIM_ERROR:
2794 	    icon_data = error_xpm;
2795 	    break;
2796 	case VIM_WARNING:
2797 	    icon_data = alert_xpm;
2798 	    break;
2799 	case VIM_INFO:
2800 	    icon_data = info_xpm;
2801 	    break;
2802 	case VIM_QUESTION:
2803 	    icon_data = quest_xpm;
2804 	    break;
2805 	default:
2806 	    icon_data = generic_xpm;
2807     }
2808 
2809     n = 0;
2810     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
2811     XtSetArg(args[n], XmNtopOffset, 8); n++;
2812     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
2813     XtSetArg(args[n], XmNbottomOffset, 8); n++;
2814     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
2815     XtSetArg(args[n], XmNleftOffset, 8); n++;
2816 
2817     dialogpixmap = create_pixmap_label(form, "dialogPixmap",
2818 	    icon_data, args, n);
2819     XtManageChild(dialogpixmap);
2820 #endif
2821 
2822     /* Create the dialog message.
2823      * Since LessTif is apparently having problems with the creation of
2824      * properly localized string, we use LtoR here. The symptom is that the
2825      * string sill not show properly in multiple lines as it does in native
2826      * Motif.
2827      */
2828     label = XmStringCreateLtoR((char *)message, STRING_TAG);
2829     if (label == NULL)
2830 	return -1;
2831     w = XtVaCreateManagedWidget("dialogMessage",
2832 				xmLabelGadgetClass, form,
2833 				XmNlabelString, label,
2834 				XmNalignment, XmALIGNMENT_BEGINNING,
2835 				XmNtopAttachment, XmATTACH_FORM,
2836 				XmNtopOffset, 8,
2837 #ifdef HAVE_XPM
2838 				XmNleftAttachment, XmATTACH_WIDGET,
2839 				XmNleftWidget, dialogpixmap,
2840 #else
2841 				XmNleftAttachment, XmATTACH_FORM,
2842 #endif
2843 				XmNleftOffset, 8,
2844 				XmNrightAttachment, XmATTACH_FORM,
2845 				XmNrightOffset, 8,
2846 				XmNbottomAttachment, XmATTACH_FORM,
2847 				XmNbottomOffset, 8,
2848 				NULL);
2849     XmStringFree(label);
2850     set_fontlist(w);
2851 
2852     if (textfield != NULL)
2853     {
2854 	XtVaSetValues(form,
2855 		XmNbottomAttachment, XmATTACH_WIDGET,
2856 		XmNbottomWidget, dialogtextfield,
2857 		NULL);
2858     }
2859     else
2860     {
2861 	if (butcount > 0)
2862 	    XtVaSetValues(form,
2863 		    XmNbottomAttachment, XmATTACH_WIDGET,
2864 		    XmNbottomWidget, separator,
2865 		    NULL);
2866 	else
2867 	    XtVaSetValues(form,
2868 		    XmNbottomAttachment, XmATTACH_FORM,
2869 		    NULL);
2870     }
2871 
2872     if (dfltbutton < 1)
2873 	dfltbutton = 1;
2874     if (dfltbutton > butcount)
2875 	dfltbutton = butcount;
2876     XtVaSetValues(dialogform,
2877 	    XmNdefaultButton, buttons[dfltbutton - 1], NULL);
2878     if (textfield != NULL)
2879 	XtVaSetValues(dialogform, XmNinitialFocus, dialogtextfield, NULL);
2880     else
2881 	XtVaSetValues(dialogform, XmNinitialFocus, buttons[dfltbutton - 1],
2882 									NULL);
2883 
2884     manage_centered(dialogform);
2885     activate_dialog_mnemonics(dialogform);
2886 
2887     if (textfield != NULL && *textfield != NUL)
2888     {
2889 	/* This only works after the textfield has been realised. */
2890 	XmTextFieldSetSelection(dialogtextfield,
2891 			 (XmTextPosition)0, (XmTextPosition)STRLEN(textfield),
2892 					   XtLastTimestampProcessed(gui.dpy));
2893 	XmTextFieldSetCursorPosition(dialogtextfield,
2894 					   (XmTextPosition)STRLEN(textfield));
2895     }
2896 
2897     app = XtWidgetToApplicationContext(dialogform);
2898 
2899     /* Loop until a button is pressed or the dialog is killed somehow. */
2900     dialogStatus = -1;
2901     for (;;)
2902     {
2903 	XtAppProcessEvent(app, (XtInputMask)XtIMAll);
2904 	if (dialogStatus >= 0 || !XtIsManaged(dialogform))
2905 	    break;
2906     }
2907 
2908     vim_free(buttons);
2909 
2910     if (textfield != NULL)
2911     {
2912 	p = (char_u *)XmTextGetString(dialogtextfield);
2913 	if (p == NULL || dialogStatus < 0)
2914 	    *textfield = NUL;
2915 	else
2916 	    vim_strncpy(textfield, p, IOSIZE - 1);
2917 	XtFree((char *)p);
2918     }
2919 
2920     suppress_dialog_mnemonics(dialogform);
2921     XtDestroyWidget(dialogform);
2922 
2923     return dialogStatus;
2924 }
2925 #endif /* FEAT_GUI_DIALOG */
2926 
2927 #if defined(FEAT_FOOTER) || defined(PROTO)
2928 
2929     static int
2930 gui_mch_compute_footer_height()
2931 {
2932     Dimension	height;		    /* total Toolbar height */
2933     Dimension	top;		    /* XmNmarginTop */
2934     Dimension	bottom;		    /* XmNmarginBottom */
2935     Dimension	shadow;		    /* XmNshadowThickness */
2936 
2937     XtVaGetValues(footer,
2938 	    XmNheight, &height,
2939 	    XmNmarginTop, &top,
2940 	    XmNmarginBottom, &bottom,
2941 	    XmNshadowThickness, &shadow,
2942 	    NULL);
2943 
2944     return (int) height + top + bottom + (shadow << 1);
2945 }
2946 
2947     void
2948 gui_mch_enable_footer(showit)
2949     int		showit;
2950 {
2951     if (showit)
2952     {
2953 	gui.footer_height = gui_mch_compute_footer_height();
2954 	XtManageChild(footer);
2955     }
2956     else
2957     {
2958 	gui.footer_height = 0;
2959 	XtUnmanageChild(footer);
2960     }
2961     XtVaSetValues(textAreaForm, XmNbottomOffset, gui.footer_height, NULL);
2962 }
2963 
2964     void
2965 gui_mch_set_footer(s)
2966     char_u	*s;
2967 {
2968     XmString	xms;
2969 
2970     xms = XmStringCreate((char *)s, STRING_TAG);
2971     if (xms != NULL)
2972     {
2973 	XtVaSetValues(footer, XmNlabelString, xms, NULL);
2974 	XmStringFree(xms);
2975     }
2976 }
2977 
2978 #endif
2979 
2980 
2981 #if defined(FEAT_TOOLBAR) || defined(PROTO)
2982     void
2983 gui_mch_show_toolbar(int showit)
2984 {
2985     Cardinal	numChildren;	    /* how many children toolBar has */
2986 
2987     if (toolBar == (Widget)0)
2988 	return;
2989     XtVaGetValues(toolBar, XmNnumChildren, &numChildren, NULL);
2990     if (showit && numChildren > 0)
2991     {
2992 	/* Assume that we want to show the toolbar if p_toolbar contains
2993 	 * valid option settings, therefore p_toolbar must not be NULL.
2994 	 */
2995 	WidgetList  children;
2996 
2997 	XtVaGetValues(toolBar, XmNchildren, &children, NULL);
2998 	{
2999 	    void    (*action)(BalloonEval *);
3000 	    int	    text = 0;
3001 
3002 	    if (strstr((const char *)p_toolbar, "tooltips"))
3003 		action = &gui_mch_enable_beval_area;
3004 	    else
3005 		action = &gui_mch_disable_beval_area;
3006 	    if (strstr((const char *)p_toolbar, "text"))
3007 		text = 1;
3008 	    else if (strstr((const char *)p_toolbar, "icons"))
3009 		text = -1;
3010 	    if (text != 0)
3011 	    {
3012 		vimmenu_T   *toolbar;
3013 		vimmenu_T   *cur;
3014 
3015 		for (toolbar = root_menu; toolbar; toolbar = toolbar->next)
3016 		    if (menu_is_toolbar(toolbar->dname))
3017 			break;
3018 		/* Assumption: toolbar is NULL if there is no toolbar,
3019 		 *	       otherwise it contains the toolbar menu structure.
3020 		 *
3021 		 * Assumption: "numChildren" == the number of items in the list
3022 		 *	       of items beginning with toolbar->children.
3023 		 */
3024 		if (toolbar)
3025 		{
3026 		    for (cur = toolbar->children; cur; cur = cur->next)
3027 		    {
3028 			Arg	    args[1];
3029 			int	    n = 0;
3030 
3031 			/* Enable/Disable tooltip (OK to enable while
3032 			 * currently enabled). */
3033 			if (cur->tip != NULL)
3034 			    (*action)(cur->tip);
3035 			if (!menu_is_separator(cur->name))
3036 			{
3037 			    if (text == 1 || cur->xpm == NULL)
3038 			    {
3039 				XtSetArg(args[n], XmNlabelType, XmSTRING);
3040 				++n;
3041 			    }
3042 			    if (cur->id != NULL)
3043 			    {
3044 				XtUnmanageChild(cur->id);
3045 				XtSetValues(cur->id, args, n);
3046 				XtManageChild(cur->id);
3047 			    }
3048 			}
3049 		    }
3050 		}
3051 	    }
3052 	}
3053 	gui.toolbar_height = gui_mch_compute_toolbar_height();
3054 	XtManageChild(XtParent(toolBar));
3055 #ifdef FEAT_GUI_TABLINE
3056 	if (showing_tabline)
3057 	{
3058 	    XtVaSetValues(tabLine,
3059 			  XmNtopAttachment, XmATTACH_WIDGET,
3060 			  XmNtopWidget, XtParent(toolBar),
3061 			  NULL);
3062 	    XtVaSetValues(textAreaForm,
3063 			  XmNtopAttachment, XmATTACH_WIDGET,
3064 			  XmNtopWidget, tabLine,
3065 			  NULL);
3066 	}
3067 	else
3068 #endif
3069 	    XtVaSetValues(textAreaForm,
3070 			  XmNtopAttachment, XmATTACH_WIDGET,
3071 			  XmNtopWidget, XtParent(toolBar),
3072 			  NULL);
3073 	if (XtIsManaged(menuBar))
3074 	    XtVaSetValues(XtParent(toolBar),
3075 		    XmNtopAttachment, XmATTACH_WIDGET,
3076 		    XmNtopWidget, menuBar,
3077 		    NULL);
3078 	else
3079 	    XtVaSetValues(XtParent(toolBar),
3080 		    XmNtopAttachment, XmATTACH_FORM,
3081 		    NULL);
3082     }
3083     else
3084     {
3085 	gui.toolbar_height = 0;
3086 	if (XtIsManaged(menuBar))
3087 	{
3088 #ifdef FEAT_GUI_TABLINE
3089 	    if (showing_tabline)
3090 	    {
3091 		XtVaSetValues(tabLine,
3092 			      XmNtopAttachment, XmATTACH_WIDGET,
3093 			      XmNtopWidget, menuBar,
3094 			      NULL);
3095 		XtVaSetValues(textAreaForm,
3096 			      XmNtopAttachment, XmATTACH_WIDGET,
3097 			      XmNtopWidget, tabLine,
3098 			      NULL);
3099 	    }
3100 	    else
3101 #endif
3102 		XtVaSetValues(textAreaForm,
3103 			      XmNtopAttachment, XmATTACH_WIDGET,
3104 			      XmNtopWidget, menuBar,
3105 			      NULL);
3106 	}
3107 	else
3108 	{
3109 #ifdef FEAT_GUI_TABLINE
3110 	    if (showing_tabline)
3111 	    {
3112 		XtVaSetValues(tabLine,
3113 			      XmNtopAttachment, XmATTACH_FORM,
3114 			      NULL);
3115 		XtVaSetValues(textAreaForm,
3116 			      XmNtopAttachment, XmATTACH_WIDGET,
3117 			      XmNtopWidget, tabLine,
3118 			      NULL);
3119 	    }
3120 	    else
3121 #endif
3122 		XtVaSetValues(textAreaForm,
3123 			      XmNtopAttachment, XmATTACH_FORM,
3124 			      NULL);
3125 	}
3126 
3127 	XtUnmanageChild(XtParent(toolBar));
3128     }
3129     gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
3130 }
3131 
3132 /*
3133  * A toolbar button has been pushed; now reset the input focus
3134  * such that the user can type page up/down etc. and have the
3135  * input go to the editor window, not the button
3136  */
3137     static void
3138 reset_focus()
3139 {
3140     if (textArea != NULL)
3141 	XmProcessTraversal(textArea, XmTRAVERSE_CURRENT);
3142 }
3143 
3144     int
3145 gui_mch_compute_toolbar_height()
3146 {
3147     Dimension	borders;
3148     Dimension	height;		    /* total Toolbar height */
3149     Dimension	whgt;		    /* height of each widget */
3150     WidgetList	children;	    /* list of toolBar's children */
3151     Cardinal	numChildren;	    /* how many children toolBar has */
3152     int		i;
3153 
3154     borders = 0;
3155     height = 0;
3156     if (toolBar != (Widget)0 && toolBarFrame != (Widget)0)
3157     {				    /* get height of XmFrame parent */
3158 	Dimension	fst;
3159 	Dimension	fmh;
3160 	Dimension	tst;
3161 	Dimension	tmh;
3162 
3163 	XtVaGetValues(toolBarFrame,
3164 		XmNshadowThickness, &fst,
3165 		XmNmarginHeight, &fmh,
3166 		NULL);
3167 	borders += fst + fmh;
3168 	XtVaGetValues(toolBar,
3169 		XmNshadowThickness, &tst,
3170 		XmNmarginHeight, &tmh,
3171 		XmNchildren, &children,
3172 		XmNnumChildren, &numChildren, NULL);
3173 	borders += tst + tmh;
3174 	for (i = 0; i < (int)numChildren; i++)
3175 	{
3176 	    whgt = 0;
3177 	    XtVaGetValues(children[i], XmNheight, &whgt, NULL);
3178 	    if (height < whgt)
3179 		height = whgt;
3180 	}
3181     }
3182 #ifdef LESSTIF_VERSION
3183     /* Hack: When starting up we get wrong dimensions. */
3184     if (height < 10)
3185 	height = 24;
3186 #endif
3187 
3188     return (int)(height + (borders << 1));
3189 }
3190 
3191     void
3192 motif_get_toolbar_colors(bgp, fgp, bsp, tsp, hsp)
3193     Pixel       *bgp;
3194     Pixel       *fgp;
3195     Pixel       *bsp;
3196     Pixel       *tsp;
3197     Pixel       *hsp;
3198 {
3199     XtVaGetValues(toolBar,
3200 	    XmNbackground, bgp,
3201 	    XmNforeground, fgp,
3202 	    XmNbottomShadowColor, bsp,
3203 	    XmNtopShadowColor, tsp,
3204 	    XmNhighlightColor, hsp,
3205 	    NULL);
3206 }
3207 
3208 # ifdef FEAT_FOOTER
3209 /*
3210  * The next toolbar enter/leave callbacks should really do balloon help.  But
3211  * I have to use footer help for backwards compatibility.  Hopefully both will
3212  * get implemented and the user will have a choice.
3213  */
3214     static void
3215 toolbarbutton_enter_cb(w, client_data, event, cont)
3216     Widget	w UNUSED;
3217     XtPointer	client_data;
3218     XEvent	*event UNUSED;
3219     Boolean	*cont UNUSED;
3220 {
3221     vimmenu_T	*menu = (vimmenu_T *) client_data;
3222 
3223     if (menu->strings[MENU_INDEX_TIP] != NULL)
3224     {
3225 	if (vim_strchr(p_go, GO_FOOTER) != NULL)
3226 	    gui_mch_set_footer(menu->strings[MENU_INDEX_TIP]);
3227     }
3228 }
3229 
3230     static void
3231 toolbarbutton_leave_cb(w, client_data, event, cont)
3232     Widget	w UNUSED;
3233     XtPointer	client_data UNUSED;
3234     XEvent	*event UNUSED;
3235     Boolean	*cont UNUSED;
3236 {
3237     gui_mch_set_footer((char_u *) "");
3238 }
3239 # endif
3240 #endif
3241 
3242 #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
3243 /*
3244  * Show or hide the tabline.
3245  */
3246     void
3247 gui_mch_show_tabline(int showit)
3248 {
3249     if (tabLine == (Widget)0)
3250 	return;
3251 
3252     if (!showit != !showing_tabline)
3253     {
3254 	if (showit)
3255 	{
3256 	    XtManageChild(tabLine);
3257 	    XtUnmanageChild(XtNameToWidget(tabLine, "PageScroller"));
3258 	    XtUnmanageChild(XtNameToWidget(tabLine, "MinorTabScrollerNext"));
3259 	    XtUnmanageChild(XtNameToWidget(tabLine,
3260 					   "MinorTabScrollerPrevious"));
3261 #ifdef FEAT_MENU
3262 # ifdef FEAT_TOOLBAR
3263 	    if (XtIsManaged(XtParent(toolBar)))
3264 		XtVaSetValues(tabLine,
3265 			      XmNtopAttachment, XmATTACH_WIDGET,
3266 			      XmNtopWidget, XtParent(toolBar), NULL);
3267 	    else
3268 # endif
3269 		if (XtIsManaged(menuBar))
3270 		XtVaSetValues(tabLine,
3271 			      XmNtopAttachment, XmATTACH_WIDGET,
3272 			      XmNtopWidget, menuBar, NULL);
3273 	    else
3274 #endif
3275 		XtVaSetValues(tabLine,
3276 			      XmNtopAttachment, XmATTACH_FORM, NULL);
3277 	    XtVaSetValues(textAreaForm,
3278 			  XmNtopAttachment, XmATTACH_WIDGET,
3279 			  XmNtopWidget, tabLine,
3280 			  NULL);
3281 	}
3282 	else
3283 	{
3284 	    XtUnmanageChild(tabLine);
3285 #ifdef FEAT_MENU
3286 # ifdef FEAT_TOOLBAR
3287 	    if (XtIsManaged(XtParent(toolBar)))
3288 		XtVaSetValues(textAreaForm,
3289 			      XmNtopAttachment, XmATTACH_WIDGET,
3290 			      XmNtopWidget, XtParent(toolBar), NULL);
3291 	    else
3292 # endif
3293 		if (XtIsManaged(menuBar))
3294 		XtVaSetValues(textAreaForm,
3295 			      XmNtopAttachment, XmATTACH_WIDGET,
3296 			      XmNtopWidget, menuBar, NULL);
3297 	    else
3298 #endif
3299 		XtVaSetValues(textAreaForm,
3300 			      XmNtopAttachment, XmATTACH_FORM, NULL);
3301 	}
3302 	showing_tabline = showit;
3303     }
3304 }
3305 
3306 /*
3307  * Return TRUE when tabline is displayed.
3308  */
3309     int
3310 gui_mch_showing_tabline(void)
3311 {
3312     return tabLine != (Widget)0 && showing_tabline;
3313 }
3314 
3315 /*
3316  * Update the labels of the tabline.
3317  */
3318     void
3319 gui_mch_update_tabline(void)
3320 {
3321     tabpage_T		*tp;
3322     int			nr = 1, n;
3323     Arg			args[10];
3324     int			curtabidx = 0, currentpage;
3325     Widget		tab;
3326     XmNotebookPageInfo	page_info;
3327     XmNotebookPageStatus page_status;
3328     int			last_page, tab_count;
3329     XmString		label_str;
3330     char		*label_cstr;
3331     BalloonEval		*beval;
3332 
3333     if (tabLine == (Widget)0)
3334 	return;
3335 
3336     /* Add a label for each tab page.  They all contain the same text area. */
3337     for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
3338     {
3339 	if (tp == curtab)
3340 	    curtabidx = nr;
3341 
3342 	page_status = XmNotebookGetPageInfo(tabLine, nr, &page_info);
3343 	if (page_status == XmPAGE_INVALID
3344 		|| page_info.major_tab_widget == (Widget)0)
3345 	{
3346 	    /* Add the tab */
3347 	    n = 0;
3348 	    XtSetArg(args[n], XmNnotebookChildType, XmMAJOR_TAB); n++;
3349 	    XtSetArg(args[n], XmNtraversalOn, False); n++;
3350 	    XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
3351 	    XtSetArg(args[n], XmNhighlightThickness, 1); n++;
3352 	    XtSetArg(args[n], XmNshadowThickness , 1); n++;
3353 	    tab = XmCreatePushButton(tabLine, "-Empty-", args, n);
3354 	    XtManageChild(tab);
3355 	    beval = gui_mch_create_beval_area(tab, NULL, tabline_balloon_cb,
3356 									NULL);
3357 	    XtVaSetValues(tab, XmNuserData, beval, NULL);
3358 	}
3359 	else
3360 	    tab = page_info.major_tab_widget;
3361 
3362 	XtVaSetValues(tab, XmNpageNumber, nr, NULL);
3363 
3364 	/*
3365 	 * Change the label text only if it is different
3366 	 */
3367 	XtVaGetValues(tab, XmNlabelString, &label_str, NULL);
3368 	if (XmStringGetLtoR(label_str, XmSTRING_DEFAULT_CHARSET, &label_cstr))
3369 	{
3370 	    get_tabline_label(tp, FALSE);
3371 	    if (STRCMP(label_cstr, NameBuff) != 0)
3372 	    {
3373 		XtVaSetValues(tab, XtVaTypedArg, XmNlabelString, XmRString,
3374 			      NameBuff, STRLEN(NameBuff) + 1, NULL);
3375 		/*
3376 		 * Force a resize of the tab label button
3377 		 */
3378 		XtUnmanageChild(tab);
3379 		XtManageChild(tab);
3380 	    }
3381 	    XtFree(label_cstr);
3382 	}
3383     }
3384 
3385     tab_count = nr - 1;
3386 
3387     XtVaGetValues(tabLine, XmNlastPageNumber, &last_page, NULL);
3388 
3389     /* Remove any old labels. */
3390     while (nr <= last_page)
3391     {
3392 	if (XmNotebookGetPageInfo(tabLine, nr, &page_info) != XmPAGE_INVALID
3393 	    && page_info.page_number == nr
3394 	    && page_info.major_tab_widget != (Widget)0)
3395 	{
3396 	    XtVaGetValues(page_info.major_tab_widget, XmNuserData, &beval, NULL);
3397 	    if (beval != NULL)
3398 		gui_mch_destroy_beval_area(beval);
3399 	    XtUnmanageChild(page_info.major_tab_widget);
3400 	    XtDestroyWidget(page_info.major_tab_widget);
3401 	}
3402 	nr++;
3403     }
3404 
3405     XtVaSetValues(tabLine, XmNlastPageNumber, tab_count, NULL);
3406 
3407     XtVaGetValues(tabLine, XmNcurrentPageNumber, &currentpage, NULL);
3408     if (currentpage != curtabidx)
3409 	XtVaSetValues(tabLine, XmNcurrentPageNumber, curtabidx, NULL);
3410 }
3411 
3412 /*
3413  * Set the current tab to "nr".  First tab is 1.
3414  */
3415     void
3416 gui_mch_set_curtab(nr)
3417     int		nr;
3418 {
3419     int		currentpage;
3420 
3421     if (tabLine == (Widget)0)
3422 	return;
3423 
3424     XtVaGetValues(tabLine, XmNcurrentPageNumber, &currentpage, NULL);
3425     if (currentpage != nr)
3426 	XtVaSetValues(tabLine, XmNcurrentPageNumber, nr, NULL);
3427 }
3428 #endif
3429 
3430 /*
3431  * Set the colors of Widget "id" to the menu colors.
3432  */
3433     static void
3434 gui_motif_menu_colors(id)
3435     Widget  id;
3436 {
3437     if (gui.menu_bg_pixel != INVALCOLOR)
3438 #if (XmVersion >= 1002)
3439 	XmChangeColor(id, gui.menu_bg_pixel);
3440 #else
3441 	XtVaSetValues(id, XmNbackground, gui.menu_bg_pixel, NULL);
3442 #endif
3443     if (gui.menu_fg_pixel != INVALCOLOR)
3444 	XtVaSetValues(id, XmNforeground, gui.menu_fg_pixel, NULL);
3445 }
3446 
3447 /*
3448  * Set the colors of Widget "id" to the scrollbar colors.
3449  */
3450     static void
3451 gui_motif_scroll_colors(id)
3452     Widget  id;
3453 {
3454     if (gui.scroll_bg_pixel != INVALCOLOR)
3455 #if (XmVersion >= 1002)
3456 	XmChangeColor(id, gui.scroll_bg_pixel);
3457 #else
3458 	XtVaSetValues(id, XmNbackground, gui.scroll_bg_pixel, NULL);
3459 #endif
3460     if (gui.scroll_fg_pixel != INVALCOLOR)
3461 	XtVaSetValues(id, XmNforeground, gui.scroll_fg_pixel, NULL);
3462 }
3463 
3464 /*
3465  * Set the fontlist for Widget "id" to use gui.menu_fontset or gui.menu_font.
3466  */
3467     void
3468 gui_motif_menu_fontlist(id)
3469     Widget  id UNUSED;
3470 {
3471 #ifdef FEAT_MENU
3472 #ifdef FONTSET_ALWAYS
3473     if (gui.menu_fontset != NOFONTSET)
3474     {
3475 	XmFontList fl;
3476 
3477 	fl = gui_motif_fontset2fontlist((XFontSet *)&gui.menu_fontset);
3478 	if (fl != NULL)
3479 	{
3480 	    if (XtIsManaged(id))
3481 	    {
3482 		XtUnmanageChild(id);
3483 		XtVaSetValues(id, XmNfontList, fl, NULL);
3484 		/* We should force the widget to recalculate it's
3485 		 * geometry now. */
3486 		XtManageChild(id);
3487 	    }
3488 	    else
3489 		XtVaSetValues(id, XmNfontList, fl, NULL);
3490 	    XmFontListFree(fl);
3491 	}
3492     }
3493 #else
3494     if (gui.menu_font != NOFONT)
3495     {
3496 	XmFontList fl;
3497 
3498 	fl = gui_motif_create_fontlist((XFontStruct *)gui.menu_font);
3499 	if (fl != NULL)
3500 	{
3501 	    if (XtIsManaged(id))
3502 	    {
3503 		XtUnmanageChild(id);
3504 		XtVaSetValues(id, XmNfontList, fl, NULL);
3505 		/* We should force the widget to recalculate it's
3506 		 * geometry now. */
3507 		XtManageChild(id);
3508 	    }
3509 	    else
3510 		XtVaSetValues(id, XmNfontList, fl, NULL);
3511 	    XmFontListFree(fl);
3512 	}
3513     }
3514 #endif
3515 #endif
3516 }
3517 
3518 
3519 /*
3520  * We don't create it twice for the sake of speed.
3521  */
3522 
3523 typedef struct _SharedFindReplace
3524 {
3525     Widget dialog;	/* the main dialog widget */
3526     Widget wword;	/* 'Exact match' check button */
3527     Widget mcase;	/* 'match case' check button */
3528     Widget up;		/* search direction 'Up' radio button */
3529     Widget down;	/* search direction 'Down' radio button */
3530     Widget what;	/* 'Find what' entry text widget */
3531     Widget with;	/* 'Replace with' entry text widget */
3532     Widget find;	/* 'Find Next' action button */
3533     Widget replace;	/* 'Replace With' action button */
3534     Widget all;		/* 'Replace All' action button */
3535     Widget undo;	/* 'Undo' action button */
3536 
3537     Widget cancel;
3538 } SharedFindReplace;
3539 
3540 static SharedFindReplace find_widgets = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
3541 static SharedFindReplace repl_widgets = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
3542 
3543 static void find_replace_destroy_callback __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
3544 static void find_replace_dismiss_callback __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
3545 static void entry_activate_callback __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
3546 static void find_replace_callback __ARGS((Widget w, XtPointer client_data, XtPointer call_data));
3547 static void find_replace_keypress __ARGS((Widget w, SharedFindReplace * frdp, XKeyEvent * event));
3548 static void find_replace_dialog_create __ARGS((char_u *entry_text, int do_replace));
3549 
3550     static void
3551 find_replace_destroy_callback(w, client_data, call_data)
3552     Widget	w UNUSED;
3553     XtPointer	client_data;
3554     XtPointer	call_data UNUSED;
3555 {
3556     SharedFindReplace *cd = (SharedFindReplace *)client_data;
3557 
3558     if (cd != NULL)
3559        /* suppress_dialog_mnemonics(cd->dialog); */
3560 	cd->dialog = (Widget)0;
3561 }
3562 
3563     static void
3564 find_replace_dismiss_callback(w, client_data, call_data)
3565     Widget	w UNUSED;
3566     XtPointer	client_data;
3567     XtPointer	call_data UNUSED;
3568 {
3569     SharedFindReplace *cd = (SharedFindReplace *)client_data;
3570 
3571     if (cd != NULL)
3572 	XtUnmanageChild(cd->dialog);
3573 }
3574 
3575     static void
3576 entry_activate_callback(w, client_data, call_data)
3577     Widget	w UNUSED;
3578     XtPointer	client_data;
3579     XtPointer	call_data UNUSED;
3580 {
3581     XmProcessTraversal((Widget)client_data, XmTRAVERSE_CURRENT);
3582 }
3583 
3584     static void
3585 find_replace_callback(w, client_data, call_data)
3586     Widget	w UNUSED;
3587     XtPointer	client_data;
3588     XtPointer	call_data UNUSED;
3589 {
3590     long_u	flags = (long_u)client_data;
3591     char	*find_text, *repl_text;
3592     Boolean	direction_down = TRUE;
3593     Boolean	wword;
3594     Boolean	mcase;
3595     SharedFindReplace *sfr;
3596 
3597     if (flags == FRD_UNDO)
3598     {
3599 	char_u	*save_cpo = p_cpo;
3600 
3601 	/* No need to be Vi compatible here. */
3602 	p_cpo = (char_u *)"";
3603 	u_undo(1);
3604 	p_cpo = save_cpo;
3605 	gui_update_screen();
3606 	return;
3607     }
3608 
3609     /* Get the search/replace strings from the dialog */
3610     if (flags == FRD_FINDNEXT)
3611     {
3612 	repl_text = NULL;
3613 	sfr = &find_widgets;
3614     }
3615     else
3616     {
3617 	repl_text = XmTextFieldGetString(repl_widgets.with);
3618 	sfr = &repl_widgets;
3619     }
3620     find_text = XmTextFieldGetString(sfr->what);
3621     XtVaGetValues(sfr->down, XmNset, &direction_down, NULL);
3622     XtVaGetValues(sfr->wword, XmNset, &wword, NULL);
3623     XtVaGetValues(sfr->mcase, XmNset, &mcase, NULL);
3624     if (wword)
3625 	flags |= FRD_WHOLE_WORD;
3626     if (mcase)
3627 	flags |= FRD_MATCH_CASE;
3628 
3629     (void)gui_do_findrepl((int)flags, (char_u *)find_text, (char_u *)repl_text,
3630 							      direction_down);
3631 
3632     if (find_text != NULL)
3633 	XtFree(find_text);
3634     if (repl_text != NULL)
3635 	XtFree(repl_text);
3636 }
3637 
3638     static void
3639 find_replace_keypress(w, frdp, event)
3640     Widget		w UNUSED;
3641     SharedFindReplace	*frdp;
3642     XKeyEvent		*event;
3643 {
3644     KeySym keysym;
3645 
3646     if (frdp == NULL)
3647 	return;
3648 
3649     keysym = XLookupKeysym(event, 0);
3650 
3651     /* the scape key pops the whole dialog down */
3652     if (keysym == XK_Escape)
3653 	XtUnmanageChild(frdp->dialog);
3654 }
3655 
3656     static void
3657 set_label(w, label)
3658     Widget w;
3659     char *label;
3660 {
3661     XmString	str;
3662     char_u	*p, *next;
3663     KeySym	mnemonic = NUL;
3664 
3665     if (!w)
3666 	return;
3667 
3668     p = vim_strsave((char_u *)label);
3669     if (p == NULL)
3670 	return;
3671     for (next = p; *next; ++next)
3672     {
3673 	if (*next == DLG_HOTKEY_CHAR)
3674 	{
3675 	    int len = STRLEN(next);
3676 
3677 	    if (len > 0)
3678 	    {
3679 		mch_memmove(next, next + 1, len);
3680 		mnemonic = next[0];
3681 	    }
3682 	}
3683     }
3684 
3685     str = XmStringCreateSimple((char *)p);
3686     vim_free(p);
3687     if (str)
3688     {
3689 	XtVaSetValues(w,
3690 		XmNlabelString, str,
3691 		XmNmnemonic, mnemonic,
3692 		NULL);
3693 	XmStringFree(str);
3694     }
3695     gui_motif_menu_fontlist(w);
3696 }
3697 
3698     static void
3699 find_replace_dialog_create(arg, do_replace)
3700     char_u	*arg;
3701     int		do_replace;
3702 {
3703     SharedFindReplace	*frdp;
3704     Widget		separator;
3705     Widget		input_form;
3706     Widget		button_form;
3707     Widget		toggle_form;
3708     Widget		frame;
3709     XmString		str;
3710     int			n;
3711     Arg			args[6];
3712     int			wword = FALSE;
3713     int			mcase = !p_ic;
3714     Dimension		width;
3715     Dimension		widest;
3716     char_u		*entry_text;
3717 
3718     frdp = do_replace ? &repl_widgets : &find_widgets;
3719 
3720     /* Get the search string to use. */
3721     entry_text = get_find_dialog_text(arg, &wword, &mcase);
3722 
3723     /* If the dialog already exists, just raise it. */
3724     if (frdp->dialog)
3725     {
3726 	gui_motif_synch_fonts();
3727 
3728 	/* If the window is already up, just pop it to the top */
3729 	if (XtIsManaged(frdp->dialog))
3730 	    XMapRaised(XtDisplay(frdp->dialog),
3731 					    XtWindow(XtParent(frdp->dialog)));
3732 	else
3733 	    XtManageChild(frdp->dialog);
3734 	XtPopup(XtParent(frdp->dialog), XtGrabNone);
3735 	XmProcessTraversal(frdp->what, XmTRAVERSE_CURRENT);
3736 
3737 	if (entry_text != NULL)
3738 	    XmTextFieldSetString(frdp->what, (char *)entry_text);
3739 	vim_free(entry_text);
3740 
3741 	XtVaSetValues(frdp->wword, XmNset, wword, NULL);
3742 	return;
3743     }
3744 
3745     /* Create a fresh new dialog window */
3746     if (do_replace)
3747 	 str = XmStringCreateSimple(_("VIM - Search and Replace..."));
3748     else
3749 	 str = XmStringCreateSimple(_("VIM - Search..."));
3750 
3751     n = 0;
3752     XtSetArg(args[n], XmNautoUnmanage, False); n++;
3753     XtSetArg(args[n], XmNnoResize, True); n++;
3754     XtSetArg(args[n], XmNdialogTitle, str); n++;
3755 
3756     frdp->dialog = XmCreateFormDialog(vimShell, "findReplaceDialog", args, n);
3757     XmStringFree(str);
3758     XtAddCallback(frdp->dialog, XmNdestroyCallback,
3759 	    find_replace_destroy_callback, frdp);
3760 
3761     button_form = XtVaCreateWidget("buttonForm",
3762 	    xmFormWidgetClass,	frdp->dialog,
3763 	    XmNrightAttachment, XmATTACH_FORM,
3764 	    XmNrightOffset, 4,
3765 	    XmNtopAttachment, XmATTACH_FORM,
3766 	    XmNtopOffset, 4,
3767 	    XmNbottomAttachment, XmATTACH_FORM,
3768 	    XmNbottomOffset, 4,
3769 	    NULL);
3770 
3771     frdp->find = XtVaCreateManagedWidget("findButton",
3772 	    xmPushButtonWidgetClass, button_form,
3773 	    XmNsensitive, True,
3774 	    XmNtopAttachment, XmATTACH_FORM,
3775 	    XmNleftAttachment, XmATTACH_FORM,
3776 	    XmNrightAttachment, XmATTACH_FORM,
3777 	    NULL);
3778     set_label(frdp->find, _("Find &Next"));
3779 
3780     XtAddCallback(frdp->find, XmNactivateCallback,
3781 	    find_replace_callback,
3782 	    (do_replace ? (XtPointer)FRD_R_FINDNEXT : (XtPointer)FRD_FINDNEXT));
3783 
3784     if (do_replace)
3785     {
3786 	frdp->replace = XtVaCreateManagedWidget("replaceButton",
3787 		xmPushButtonWidgetClass, button_form,
3788 		XmNtopAttachment, XmATTACH_WIDGET,
3789 		XmNtopWidget, frdp->find,
3790 		XmNleftAttachment, XmATTACH_FORM,
3791 		XmNrightAttachment, XmATTACH_FORM,
3792 		NULL);
3793 	set_label(frdp->replace, _("&Replace"));
3794 	XtAddCallback(frdp->replace, XmNactivateCallback,
3795 		find_replace_callback, (XtPointer)FRD_REPLACE);
3796 
3797 	frdp->all = XtVaCreateManagedWidget("replaceAllButton",
3798 		xmPushButtonWidgetClass, button_form,
3799 		XmNtopAttachment, XmATTACH_WIDGET,
3800 		XmNtopWidget, frdp->replace,
3801 		XmNleftAttachment, XmATTACH_FORM,
3802 		XmNrightAttachment, XmATTACH_FORM,
3803 		NULL);
3804 	set_label(frdp->all, _("Replace &All"));
3805 	XtAddCallback(frdp->all, XmNactivateCallback,
3806 		find_replace_callback, (XtPointer)FRD_REPLACEALL);
3807 
3808 	frdp->undo = XtVaCreateManagedWidget("undoButton",
3809 		xmPushButtonWidgetClass, button_form,
3810 		XmNtopAttachment, XmATTACH_WIDGET,
3811 		XmNtopWidget, frdp->all,
3812 		XmNleftAttachment, XmATTACH_FORM,
3813 		XmNrightAttachment, XmATTACH_FORM,
3814 		NULL);
3815 	set_label(frdp->undo, _("&Undo"));
3816 	XtAddCallback(frdp->undo, XmNactivateCallback,
3817 		find_replace_callback, (XtPointer)FRD_UNDO);
3818     }
3819 
3820     frdp->cancel = XtVaCreateManagedWidget("closeButton",
3821 	    xmPushButtonWidgetClass, button_form,
3822 	    XmNleftAttachment, XmATTACH_FORM,
3823 	    XmNrightAttachment, XmATTACH_FORM,
3824 	    XmNbottomAttachment, XmATTACH_FORM,
3825 	    NULL);
3826     set_label(frdp->cancel, _("&Cancel"));
3827     XtAddCallback(frdp->cancel, XmNactivateCallback,
3828 	    find_replace_dismiss_callback, frdp);
3829     gui_motif_menu_fontlist(frdp->cancel);
3830 
3831     XtManageChild(button_form);
3832 
3833     n = 0;
3834     XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
3835     XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
3836     XtSetArg(args[n], XmNrightWidget, button_form); n++;
3837     XtSetArg(args[n], XmNrightOffset, 4); n++;
3838     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
3839     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
3840     separator = XmCreateSeparatorGadget(frdp->dialog, "separator", args, n);
3841     XtManageChild(separator);
3842 
3843     input_form = XtVaCreateWidget("inputForm",
3844 	    xmFormWidgetClass,	frdp->dialog,
3845 	    XmNleftAttachment, XmATTACH_FORM,
3846 	    XmNleftOffset, 4,
3847 	    XmNrightAttachment, XmATTACH_WIDGET,
3848 	    XmNrightWidget, separator,
3849 	    XmNrightOffset, 4,
3850 	    XmNtopAttachment, XmATTACH_FORM,
3851 	    XmNtopOffset, 4,
3852 	    NULL);
3853 
3854     {
3855 	Widget label_what;
3856 	Widget label_with = (Widget)0;
3857 
3858 	str = XmStringCreateSimple(_("Find what:"));
3859 	label_what = XtVaCreateManagedWidget("whatLabel",
3860 		xmLabelGadgetClass, input_form,
3861 		XmNlabelString, str,
3862 		XmNleftAttachment,	XmATTACH_FORM,
3863 		XmNtopAttachment, XmATTACH_FORM,
3864 		XmNtopOffset, 4,
3865 		NULL);
3866 	XmStringFree(str);
3867 	gui_motif_menu_fontlist(label_what);
3868 
3869 	frdp->what = XtVaCreateManagedWidget("whatText",
3870 		xmTextFieldWidgetClass, input_form,
3871 		XmNtopAttachment, XmATTACH_FORM,
3872 		XmNrightAttachment, XmATTACH_FORM,
3873 		XmNleftAttachment, XmATTACH_FORM,
3874 		NULL);
3875 
3876 	if (do_replace)
3877 	{
3878 	    frdp->with = XtVaCreateManagedWidget("withText",
3879 		    xmTextFieldWidgetClass,	input_form,
3880 		    XmNtopAttachment, XmATTACH_WIDGET,
3881 		    XmNtopWidget, frdp->what,
3882 		    XmNtopOffset, 4,
3883 		    XmNleftAttachment, XmATTACH_FORM,
3884 		    XmNrightAttachment, XmATTACH_FORM,
3885 		    XmNbottomAttachment, XmATTACH_FORM,
3886 		    NULL);
3887 
3888 	    XtAddCallback(frdp->with, XmNactivateCallback,
3889 		    find_replace_callback, (XtPointer) FRD_R_FINDNEXT);
3890 
3891 	    str = XmStringCreateSimple(_("Replace with:"));
3892 	    label_with = XtVaCreateManagedWidget("withLabel",
3893 		    xmLabelGadgetClass, input_form,
3894 		    XmNlabelString, str,
3895 		    XmNleftAttachment, XmATTACH_FORM,
3896 		    XmNtopAttachment, XmATTACH_WIDGET,
3897 		    XmNtopWidget, frdp->what,
3898 		    XmNtopOffset, 4,
3899 		    XmNbottomAttachment, XmATTACH_FORM,
3900 		    NULL);
3901 	    XmStringFree(str);
3902 	    gui_motif_menu_fontlist(label_with);
3903 
3904 	    /*
3905 	     * Make the entry activation only change the input focus onto the
3906 	     * with item.
3907 	     */
3908 	    XtAddCallback(frdp->what, XmNactivateCallback,
3909 		    entry_activate_callback, frdp->with);
3910 	    XtAddEventHandler(frdp->with, KeyPressMask, False,
3911 			    (XtEventHandler)find_replace_keypress,
3912 			    (XtPointer) frdp);
3913 
3914 	}
3915 	else
3916 	{
3917 	    /*
3918 	     * Make the entry activation do the search.
3919 	     */
3920 	    XtAddCallback(frdp->what, XmNactivateCallback,
3921 		    find_replace_callback, (XtPointer)FRD_FINDNEXT);
3922 	}
3923 	XtAddEventHandler(frdp->what, KeyPressMask, False,
3924 			    (XtEventHandler)find_replace_keypress,
3925 			    (XtPointer)frdp);
3926 
3927 	/* Get the maximum width between the label widgets and line them up.
3928 	 */
3929 	n = 0;
3930 	XtSetArg(args[n], XmNwidth, &width); n++;
3931 	XtGetValues(label_what, args, n);
3932 	widest = width;
3933 	if (do_replace)
3934 	{
3935 	    XtGetValues(label_with, args, n);
3936 	    if (width > widest)
3937 		widest = width;
3938 	}
3939 
3940 	XtVaSetValues(frdp->what, XmNleftOffset, widest, NULL);
3941 	if (do_replace)
3942 	    XtVaSetValues(frdp->with, XmNleftOffset, widest, NULL);
3943 
3944     }
3945 
3946     XtManageChild(input_form);
3947 
3948     {
3949 	Widget radio_box;
3950 	Widget w;
3951 
3952 	frame = XtVaCreateWidget("directionFrame",
3953 		xmFrameWidgetClass, frdp->dialog,
3954 		XmNtopAttachment, XmATTACH_WIDGET,
3955 		XmNtopWidget, input_form,
3956 		XmNtopOffset, 4,
3957 		XmNbottomAttachment, XmATTACH_FORM,
3958 		XmNbottomOffset, 4,
3959 		XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
3960 		XmNrightWidget, input_form,
3961 		NULL);
3962 
3963 	str = XmStringCreateSimple(_("Direction"));
3964 	w = XtVaCreateManagedWidget("directionFrameLabel",
3965 		xmLabelGadgetClass, frame,
3966 		XmNlabelString, str,
3967 		XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
3968 		XmNchildType, XmFRAME_TITLE_CHILD,
3969 		NULL);
3970 	XmStringFree(str);
3971 	gui_motif_menu_fontlist(w);
3972 
3973 	radio_box = XmCreateRadioBox(frame, "radioBox",
3974 		(ArgList)NULL, 0);
3975 
3976 	str = XmStringCreateSimple( _("Up"));
3977 	frdp->up = XtVaCreateManagedWidget("upRadioButton",
3978 		xmToggleButtonGadgetClass, radio_box,
3979 		XmNlabelString, str,
3980 		XmNset, False,
3981 		NULL);
3982 	XmStringFree(str);
3983 	gui_motif_menu_fontlist(frdp->up);
3984 
3985 	str = XmStringCreateSimple(_("Down"));
3986 	frdp->down = XtVaCreateManagedWidget("downRadioButton",
3987 		xmToggleButtonGadgetClass, radio_box,
3988 		XmNlabelString, str,
3989 		XmNset, True,
3990 		NULL);
3991 	XmStringFree(str);
3992 	gui_motif_menu_fontlist(frdp->down);
3993 
3994 	XtManageChild(radio_box);
3995 	XtManageChild(frame);
3996     }
3997 
3998     toggle_form = XtVaCreateWidget("toggleForm",
3999 	    xmFormWidgetClass,	frdp->dialog,
4000 	    XmNleftAttachment, XmATTACH_FORM,
4001 	    XmNleftOffset, 4,
4002 	    XmNrightAttachment, XmATTACH_WIDGET,
4003 	    XmNrightWidget, frame,
4004 	    XmNrightOffset, 4,
4005 	    XmNtopAttachment, XmATTACH_WIDGET,
4006 	    XmNtopWidget, input_form,
4007 	    XmNtopOffset, 4,
4008 	    XmNbottomAttachment, XmATTACH_FORM,
4009 	    XmNbottomOffset, 4,
4010 	    NULL);
4011 
4012     str = XmStringCreateSimple(_("Match whole word only"));
4013     frdp->wword = XtVaCreateManagedWidget("wordToggle",
4014 	    xmToggleButtonGadgetClass, toggle_form,
4015 	    XmNlabelString, str,
4016 	    XmNtopAttachment, XmATTACH_FORM,
4017 	    XmNtopOffset, 4,
4018 	    XmNleftAttachment, XmATTACH_FORM,
4019 	    XmNleftOffset, 4,
4020 	    XmNset, wword,
4021 	    NULL);
4022     XmStringFree(str);
4023 
4024     str = XmStringCreateSimple(_("Match case"));
4025     frdp->mcase = XtVaCreateManagedWidget("caseToggle",
4026 	    xmToggleButtonGadgetClass, toggle_form,
4027 	    XmNlabelString, str,
4028 	    XmNleftAttachment, XmATTACH_FORM,
4029 	    XmNleftOffset, 4,
4030 	    XmNtopAttachment, XmATTACH_WIDGET,
4031 	    XmNtopWidget, frdp->wword,
4032 	    XmNtopOffset, 4,
4033 	    XmNset, mcase,
4034 	    NULL);
4035     XmStringFree(str);
4036     gui_motif_menu_fontlist(frdp->wword);
4037     gui_motif_menu_fontlist(frdp->mcase);
4038 
4039     XtManageChild(toggle_form);
4040 
4041     if (entry_text != NULL)
4042 	XmTextFieldSetString(frdp->what, (char *)entry_text);
4043     vim_free(entry_text);
4044 
4045     gui_motif_synch_fonts();
4046 
4047     manage_centered(frdp->dialog);
4048     activate_dialog_mnemonics(frdp->dialog);
4049     XmProcessTraversal(frdp->what, XmTRAVERSE_CURRENT);
4050 }
4051 
4052    void
4053 gui_mch_find_dialog(eap)
4054     exarg_T	*eap;
4055 {
4056     if (!gui.in_use)
4057 	return;
4058 
4059     find_replace_dialog_create(eap->arg, FALSE);
4060 }
4061 
4062 
4063     void
4064 gui_mch_replace_dialog(eap)
4065     exarg_T	*eap;
4066 {
4067     if (!gui.in_use)
4068 	return;
4069 
4070     find_replace_dialog_create(eap->arg, TRUE);
4071 }
4072 
4073 /*
4074  * Synchronize all gui elements, which are dependant upon the
4075  * main text font used. Those are in esp. the find/replace dialogs.
4076  * If you don't understand why this should be needed, please try to
4077  * search for "pi��" in iso8859-2.
4078  */
4079     void
4080 gui_motif_synch_fonts(void)
4081 {
4082     SharedFindReplace *frdp;
4083     int		    do_replace;
4084     XFontStruct	    *font;
4085     XmFontList	    font_list;
4086 
4087     /* FIXME: Unless we find out how to create a XmFontList from a XFontSet,
4088      * we just give up here on font synchronization. */
4089     font = (XFontStruct *)gui.norm_font;
4090     if (font == NULL)
4091 	return;
4092 
4093     font_list = gui_motif_create_fontlist(font);
4094 
4095     /* OK this loop is a bit tricky... */
4096     for (do_replace = 0; do_replace <= 1; ++do_replace)
4097     {
4098 	frdp = (do_replace) ? (&repl_widgets) : (&find_widgets);
4099 	if (frdp->dialog)
4100 	{
4101 	    XtVaSetValues(frdp->what, XmNfontList, font_list, NULL);
4102 	    if (do_replace)
4103 		XtVaSetValues(frdp->with, XmNfontList, font_list, NULL);
4104 	}
4105     }
4106 
4107     XmFontListFree(font_list);
4108 }
4109