blob: c011981a17ec1d1c72c5e8b556bd804ef46ead76 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* 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>
Bram Moolenaarc6fe9192006-04-09 21:54:49 +000029#include <Xm/XmP.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000030
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
Bram Moolenaarfc1421e2006-04-20 22:17:20 +000045#ifdef HAVE_XM_NOTEBOOK_H
46# include <Xm/Notebook.h>
47#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000048
Bram Moolenaarb7fcef52005-01-02 11:31:05 +000049#include "gui_xmebw.h" /* for our Enhanced Button Widget */
50
Bram Moolenaar071d4272004-06-13 20:20:40 +000051#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
61extern Widget vimShell;
62
63static Widget vimForm;
64static Widget textAreaForm;
65Widget textArea;
66#ifdef FEAT_TOOLBAR
67static Widget toolBarFrame;
68static Widget toolBar;
69#endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +000070#ifdef FEAT_GUI_TABLINE
71static Widget tabLine;
72static Widget tabLine_menu = 0;
73static int showing_tabline = 0;
74#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000075#ifdef FEAT_FOOTER
76static Widget footer;
77#endif
78#ifdef FEAT_MENU
79# if (XmVersion >= 1002)
80/* remember the last set value for the tearoff item */
81static int tearoff_val = (int)XmTEAR_OFF_ENABLED;
82# endif
83static Widget menuBar;
84#endif
85
Bram Moolenaard25c16e2016-01-29 22:13:30 +010086static void scroll_cb(Widget w, XtPointer client_data, XtPointer call_data);
Bram Moolenaar910f66f2006-04-05 20:41:53 +000087#ifdef FEAT_GUI_TABLINE
Bram Moolenaard25c16e2016-01-29 22:13:30 +010088static void tabline_cb(Widget w, XtPointer client_data, XtPointer call_data);
89static void tabline_button_cb(Widget w, XtPointer client_data, XtPointer call_data);
90static void tabline_menu_cb(Widget w, XtPointer closure, XEvent *e, Boolean *continue_dispatch);
91static void tabline_balloon_cb(BalloonEval *beval, int state);
Bram Moolenaar910f66f2006-04-05 20:41:53 +000092#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000093#ifdef FEAT_TOOLBAR
Bram Moolenaar071d4272004-06-13 20:20:40 +000094# ifdef FEAT_FOOTER
Bram Moolenaard25c16e2016-01-29 22:13:30 +010095static void toolbarbutton_enter_cb(Widget, XtPointer, XEvent *, Boolean *);
96static void toolbarbutton_leave_cb(Widget, XtPointer, XEvent *, Boolean *);
Bram Moolenaar071d4272004-06-13 20:20:40 +000097# endif
Bram Moolenaard25c16e2016-01-29 22:13:30 +010098static void reset_focus(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +000099#endif
100#ifdef FEAT_FOOTER
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100101static int gui_mch_compute_footer_height(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000102#endif
103#ifdef WSDEBUG
104static void attachDump(Widget, char *);
105#endif
106
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100107static void gui_motif_menu_colors(Widget id);
108static void gui_motif_scroll_colors(Widget id);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000109
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
Bram Moolenaar071d4272004-06-13 20:20:40 +0000120 static void
121scroll_cb(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000122 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000123 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
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000137#ifdef FEAT_GUI_TABLINE
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000138 static void
139tabline_cb(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000140 Widget w UNUSED;
141 XtPointer client_data UNUSED;
142 XtPointer call_data;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000143{
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
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000151 static void
152tabline_button_cb(w, client_data, call_data)
153 Widget w;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000154 XtPointer client_data UNUSED;
155 XtPointer call_data UNUSED;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000156{
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000157 int cmd, tab_idx;
158
159 XtVaGetValues(w, XmNuserData, &cmd, NULL);
160 XtVaGetValues(tabLine_menu, XmNuserData, &tab_idx, NULL);
161
Bram Moolenaarc6fe9192006-04-09 21:54:49 +0000162 send_tabline_menu_event(tab_idx, cmd);
163}
164
165/*
166 * Tabline single mouse click timeout handler
167 */
Bram Moolenaarc6fe9192006-04-09 21:54:49 +0000168 static void
169motif_tabline_timer_cb (timed_out, interval_id)
170 XtPointer timed_out;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000171 XtIntervalId *interval_id UNUSED;
Bram Moolenaarc6fe9192006-04-09 21:54:49 +0000172{
173 *((int *)timed_out) = TRUE;
174}
175
176/*
177 * check if the tabline tab scroller is clicked
178 */
179 static int
180tabline_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;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000202}
203
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000204 static void
205tabline_menu_cb(w, closure, e, continue_dispatch)
206 Widget w;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000207 XtPointer closure UNUSED;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000208 XEvent *e;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000209 Boolean *continue_dispatch UNUSED;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000210{
211 Widget tab_w;
212 XButtonPressedEvent *event;
213 int tab_idx = 0;
214 WidgetList children;
215 Cardinal numChildren;
Bram Moolenaarc6fe9192006-04-09 21:54:49 +0000216 static XtIntervalId timer = (XtIntervalId)0;
217 static int timed_out = TRUE;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000218
219 event = (XButtonPressedEvent *)e;
220
Bram Moolenaarc6fe9192006-04-09 21:54:49 +0000221 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
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000250 if (event->button != Button3)
251 return;
252
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000253 /* 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
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000261 if (event->subwindow != None)
262 {
263 tab_w = XtWindowToWidget(XtDisplay(w), event->subwindow);
Bram Moolenaarc6fe9192006-04-09 21:54:49 +0000264 /* LINTED: avoid warning: dubious operation on enum */
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000265 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}
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000276
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000277 static void
278tabline_balloon_cb(beval, state)
279 BalloonEval *beval;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000280 int state UNUSED;
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000281{
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
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000297#endif
298
Bram Moolenaar071d4272004-06-13 20:20:40 +0000299/*
300 * End of call-back routines
301 */
302
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000303/*
304 * Implement three dimensional shading of insensitive labels.
Bram Moolenaara0a83be2005-01-04 21:26:43 +0000305 * By Marcin Dalecki.
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000306 */
307
308#include <Xm/XmP.h>
309#include <Xm/LabelP.h>
310
311static XtExposeProc old_label_expose = NULL;
312
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100313static void label_expose(Widget _w, XEvent *_event, Region _region);
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000314
315 static void
316label_expose(_w, _event, _region)
317 Widget _w;
318 XEvent *_event;
319 Region _region;
320{
321 GC insensitiveGC;
322 XmLabelWidget lw = (XmLabelWidget)_w;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000323 unsigned char label_type = (int)XmSTRING;
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000324
325 XtVaGetValues(_w, XmNlabelType, &label_type, (XtPointer)0);
326
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000327 if (XtIsSensitive(_w) || label_type != (int)XmSTRING)
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000328 (*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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000370 lw->label.insensitive_GC = XtAllocateGC((Widget)lw, 0, mask,
371 &values, dynamic, (XtGCMask)0);
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000372 (*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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000386 lw->label.insensitive_GC = XtAllocateGC((Widget) lw, 0, mask,
387 &values, dynamic, (XtGCMask)0);
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000388 (*old_label_expose)(_w, _event, _region);
389 XtReleaseGC(_w, lw->label.insensitive_GC);
390
391 lw->label.insensitive_GC = insensitiveGC;
392 }
393}
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000394
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395/*
396 * Create all the motif widgets necessary.
397 */
398 void
399gui_x11_create_widgets()
400{
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000401#ifdef FEAT_GUI_TABLINE
Bram Moolenaar18144c82006-04-12 21:52:12 +0000402 Widget button, scroller;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000403 Arg args[10];
404 int n;
405 XmString xms;
406#endif
407
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000408 /*
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 }
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000416
Bram Moolenaar071d4272004-06-13 20:20:40 +0000417 /*
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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000458 XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000459 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
Bram Moolenaar071d4272004-06-13 20:20:40 +0000502#endif
503
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000504#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
Bram Moolenaar551dbcc2006-04-25 22:13:59 +0000523 gui.tabline_height = TABLINE_HEIGHT;
524
Bram Moolenaar18144c82006-04-12 21:52:12 +0000525 /*
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
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000539 /* Create the tabline popup menu */
540 tabLine_menu = XmCreatePopupMenu(tabLine, "tabline popup", NULL, 0);
541
542 /* Add the buttons to the menu */
Bram Moolenaar7098ee52015-06-09 19:14:24 +0200543 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 }
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000554
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
Bram Moolenaar071d4272004-06-13 20:20:40 +0000574 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
636gui_x11_destroy_widgets()
637{
638 textArea = NULL;
639#ifdef FEAT_MENU
640 menuBar = NULL;
641#endif
642}
643
Bram Moolenaar071d4272004-06-13 20:20:40 +0000644 void
645gui_mch_set_text_area_pos(x, y, w, h)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000646 int x UNUSED;
647 int y UNUSED;
648 int w UNUSED;
649 int h UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000650{
651#ifdef FEAT_TOOLBAR
652 /* Give keyboard focus to the textArea instead of the toolbar. */
Bram Moolenaarf9980f12005-01-03 20:58:59 +0000653 reset_focus();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654#endif
655}
656
657 void
658gui_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 */
Bram Moolenaardfccaf02004-12-31 20:56:11 +0000674 void
Bram Moolenaar071d4272004-06-13 20:20:40 +0000675manage_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 */
Bram Moolenaar46784652008-06-20 09:40:11 +0000687 XtVaGetValues(shell, XmNmappedWhenManaged, &mappedWhenManaged, NULL);
688 XtVaSetValues(shell, XmNmappedWhenManaged, False, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000689
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 */
Bram Moolenaar46784652008-06-20 09:40:11 +0000724 XtVaSetValues(shell, XmNmappedWhenManaged, mappedWhenManaged, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000725}
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
734gui_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
756gui_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
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100780static void gui_motif_add_actext(vimmenu_T *menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000781#if (XmVersion >= 1002)
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100782static void toggle_tearoff(Widget wid);
783static void gui_mch_recurse_tearoffs(vimmenu_T *menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784#endif
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100785static void submenu_change(vimmenu_T *mp, int colors);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100787static void do_set_mnemonics(int enable);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788static int menu_enabled = TRUE;
789
790 void
791gui_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);
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000805#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);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000823 }
824 else
825#endif
826 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000827#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);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 }
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);
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000856#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);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874 }
875 else
876#endif
877 {
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000878#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);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894 }
895 }
896
897}
898
899/*
900 * Enable or disable mnemonics for the toplevel menus.
901 */
902 void
903gui_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
916do_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
929gui_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
1039gui_motif_add_actext(menu)
1040 vimmenu_T *menu;
1041{
1042 XmString label;
1043
Bram Moolenaar933eb392007-05-10 17:52:45 +00001044 /* Add accelerator text, if there is one */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001045 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
1056gui_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
1075toggle_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
1087gui_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
1104gui_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
1118gui_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
Bram Moolenaar071d4272004-06-13 20:20:40 +00001181 /* 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);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001186}
1187
Bram Moolenaarb23c3382005-01-31 19:09:12 +00001188#ifdef FEAT_TOOLBAR
1189
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001190/*
1191 * Icons used by the toolbar code.
1192 */
1193#include "gui_x11_pm.h"
1194
Bram Moolenaard25c16e2016-01-29 22:13:30 +01001195static int check_xpm(char_u *path);
1196static char **get_toolbar_pixmap(vimmenu_T *menu, char **fname);
1197static int add_pixmap_args(vimmenu_T *menu, Arg *args, int n);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001198
1199/*
1200 * Read an Xpm file. Return OK or FAIL.
1201 */
1202 static int
1203check_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".
Bram Moolenaar7c626922005-02-07 22:01:03 +00001227 * When it's to be read from a file, "fname" is set to the file name
1228 * (in allocated memory).
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001229 * Return a blank pixmap if it fails.
1230 */
1231 static char **
Bram Moolenaar7c626922005-02-07 22:01:03 +00001232get_toolbar_pixmap(menu, fname)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001233 vimmenu_T *menu;
Bram Moolenaar7c626922005-02-07 22:01:03 +00001234 char **fname;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001235{
1236 char_u buf[MAXPATHL]; /* buffer storing expanded pathname */
1237 char **xpm = NULL; /* xpm array */
1238 int res;
1239
Bram Moolenaar7c626922005-02-07 22:01:03 +00001240 *fname = NULL;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001241 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)
Bram Moolenaar7c626922005-02-07 22:01:03 +00001253 {
1254 *fname = (char *)vim_strsave(buf);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001255 return tb_blank_xpm;
Bram Moolenaar7c626922005-02-07 22:01:03 +00001256 }
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001257 }
1258
1259 if (menu->icon_builtin || gui_find_bitmap(menu->name, buf, "xpm") == FAIL)
1260 {
1261 if (menu->iconidx >= 0 && menu->iconidx
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001262 < (int)(sizeof(built_in_pixmaps) / sizeof(built_in_pixmaps[0])))
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001263 xpm = built_in_pixmaps[menu->iconidx];
1264 else
1265 xpm = tb_blank_xpm;
1266 }
1267
1268 return xpm;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001269}
Bram Moolenaar7c626922005-02-07 22:01:03 +00001270
1271/*
1272 * Add arguments for the toolbar pixmap to a menu item.
1273 */
1274 static int
1275add_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}
Bram Moolenaarb23c3382005-01-31 19:09:12 +00001297#endif /* FEAT_TOOLBAR */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298
1299 void
1300gui_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
Bram Moolenaar071d4272004-06-13 20:20:40 +00001341 type = xmSeparatorWidgetClass;
1342 XtSetArg(args[n], XmNwidth, wid); n++;
1343 XtSetArg(args[n], XmNminWidth, wid); n++;
1344 XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001345 XtSetArg(args[n], XmNseparatorType, XmSHADOW_ETCHED_IN); n++;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001346 }
1347 else
1348 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001349 /* Without shadows one can't sense whatever the button has been
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001350 * pressed or not! However we want to save a bit of space...
Bram Moolenaardfccaf02004-12-31 20:56:11 +00001351 * Need the highlightThickness to see the focus.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001352 */
Bram Moolenaardfccaf02004-12-31 20:56:11 +00001353 XtSetArg(args[n], XmNhighlightThickness, 1); n++;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001354 XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
1355 XtSetArg(args[n], XmNmarginWidth, 0); n++;
1356 XtSetArg(args[n], XmNmarginHeight, 0); n++;
Bram Moolenaarf9980f12005-01-03 20:58:59 +00001357 XtSetArg(args[n], XmNtraversalOn, False); n++;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001358 /* 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++;
Bram Moolenaardfccaf02004-12-31 20:56:11 +00001362
Bram Moolenaar7c626922005-02-07 22:01:03 +00001363 n = add_pixmap_args(menu, args, n);
1364
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001365 type = xmEnhancedButtonWidgetClass;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001366 }
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);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001373 if (menu->id != NULL && type == xmEnhancedButtonWidgetClass)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001374 {
1375 XtAddCallback(menu->id,
1376 XmNactivateCallback, gui_x11_menu_cb, menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001377# 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
Bram Moolenaarf193fff2006-04-27 00:02:13 +00001390# ifdef FEAT_BEVAL
Bram Moolenaar071d4272004-06-13 20:20:40 +00001391 gui_mch_menu_set_tip(menu);
Bram Moolenaarf193fff2006-04-27 00:02:13 +00001392# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001393
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
1460gui_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
1503gui_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
Bram Moolenaarf9980f12005-01-03 20:58:59 +00001513 submenu_change(root_menu, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001514}
1515
1516 void
1517gui_mch_new_menu_font()
1518{
1519 if (menuBar == (Widget)0)
1520 return;
Bram Moolenaarf9980f12005-01-03 20:58:59 +00001521 submenu_change(root_menu, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001522 {
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 }
Bram Moolenaar2e2a2812006-03-27 20:55:21 +00001536 gui_set_shellsize(FALSE, TRUE, RESIZE_VERT);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001537 ui_new_shellsize();
1538}
1539
1540#if defined(FEAT_BEVAL) || defined(PROTO)
1541 void
1542gui_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)
Bram Moolenaarf9980f12005-01-03 20:58:59 +00001552 submenu_change(menu, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001553# endif
1554}
1555
1556 void
1557gui_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)
Bram Moolenaarf9980f12005-01-03 20:58:59 +00001567 submenu_change(toolbar, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001568# endif
1569}
1570#endif
1571
1572 static void
Bram Moolenaarf9980f12005-01-03 20:58:59 +00001573submenu_change(menu, colors)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001574 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. */
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001589 if (mp->xpm != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001590 {
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001591 int n = 0;
1592 Arg args[18];
1593
Bram Moolenaar7c626922005-02-07 22:01:03 +00001594 n = add_pixmap_args(mp, args, n);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001595 XtSetValues(mp->id, args, n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001596 }
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 */
Bram Moolenaarf9980f12005-01-03 20:58:59 +00001644 submenu_change(mp->children, colors);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001645 }
1646 }
1647}
1648
1649/*
1650 * Destroy the machine specific menu widget.
1651 */
1652 void
1653gui_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)
Bram Moolenaar4317d9b2005-03-18 20:25:31 +00001675 if (parent == toolBar && menu->tip != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001676 {
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
Bram Moolenaar071d4272004-06-13 20:20:40 +00001710 void
1711gui_mch_show_popupmenu(menu)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001712 vimmenu_T *menu UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001713{
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
1726gui_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
1751gui_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
1767gui_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
1801gui_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
1858gui_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;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001866 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
1916gui_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
1925gui_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
1960gui_x11_get_wid()
1961{
1962 return(XtWindow(textArea));
1963}
1964
Bram Moolenaardfccaf02004-12-31 20:56:11 +00001965/*
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
1972do_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 {
Bram Moolenaar46784652008-06-20 09:40:11 +00001986 XtVaGetValues(w, XmNrowColumnType, &rowColType, NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00001987 isMenu = (rowColType != (unsigned char)XmWORK_AREA);
1988 }
1989 else
1990 isMenu = False;
1991 if (!isMenu)
1992 {
1993 XtVaGetValues(w, XmNchildren, &children, XmNnumChildren,
Bram Moolenaar46784652008-06-20 09:40:11 +00001994 &numChildren, NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00001995 for (i = 0; i < numChildren; i++)
1996 do_mnemonic(children[i], keycode);
1997 }
1998 }
1999 else
2000 {
Bram Moolenaar46784652008-06-20 09:40:11 +00002001 XtVaGetValues(w, XmNmnemonic, &mnemonic, NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002002 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 {
Bram Moolenaar46784652008-06-20 09:40:11 +00002012 XtVaGetValues(w, XmNuserData, &userData, NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002013 if (userData != NULL && XtIsWidget(userData))
2014 XmProcessTraversal(userData, XmTRAVERSE_CURRENT);
2015 }
2016 else
2017 {
2018 XKeyPressedEvent keyEvent;
2019
2020 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
2021
Bram Moolenaar7db5fc82010-05-24 11:59:29 +02002022 vim_memset((char *) &keyEvent, 0, sizeof(XKeyPressedEvent));
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002023 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 */
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002039 static void
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002040mnemonic_event(Widget w, XtPointer call_data UNUSED, XKeyEvent *event)
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002041{
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
2052add_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 {
Bram Moolenaar46784652008-06-20 09:40:11 +00002065 XtVaGetValues(w, XmNrowColumnType, &rowColType, NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002066 isMenu = (rowColType != (unsigned char)XmWORK_AREA);
2067 }
2068 else
2069 isMenu = False;
2070 if (!isMenu)
2071 {
2072 XtVaGetValues(w, XmNchildren, &children, XmNnumChildren,
Bram Moolenaar46784652008-06-20 09:40:11 +00002073 &numChildren, NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002074 for (i = 0; i < numChildren; i++)
2075 add_mnemonic_grabs(dialog, children[i]);
2076 }
2077 }
2078 else
2079 {
Bram Moolenaar46784652008-06-20 09:40:11 +00002080 XtVaGetValues(w, XmNmnemonic, &mnemonic, NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002081 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
2102activate_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
2116suppress_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)
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002127static void set_fontlist(Widget wg);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002128
2129/*
2130 * Use the 'guifont' or 'guifontset' as a fontlist for a dialog widget.
2131 */
2132 static void
2133set_fontlist(id)
2134 Widget id;
2135{
2136 XmFontList fl;
2137
2138#ifdef FONTSET_ALWAYS
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00002139 if (gui.fontset != NOFONTSET)
2140 {
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002141 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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00002158 if (gui.norm_font != NOFONT)
2159 {
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002160 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
Bram Moolenaar071d4272004-06-13 20:20:40 +00002179
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
2189typedef struct dialog_callback_arg
2190{
2191 char * args; /* not used right now */
2192 int id;
2193} dcbarg_T;
2194
2195static Widget dialog_wgt;
2196static char *browse_fname = NULL;
2197static XmStringCharSet charset = (XmStringCharSet) XmSTRING_DEFAULT_CHARSET;
2198 /* used to set up XmStrings */
2199
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002200static void DialogCancelCB(Widget, XtPointer, XtPointer);
2201static void DialogAcceptCB(Widget, XtPointer, XtPointer);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002202
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 */
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002212static void set_predefined_label(Widget parent, String name, char *new_label);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002213
2214static void
2215set_predefined_label(parent, name, new_label)
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002216 Widget parent;
2217 String name;
2218 char *new_label;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002219{
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002220 XmString str;
2221 Widget w;
2222 char_u *p, *next;
2223 KeySym mnemonic = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002224
2225 w = XtNameToWidget(parent, name);
2226
2227 if (!w)
2228 return;
2229
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002230 p = vim_strsave((char_u *)new_label);
2231 if (p == NULL)
2232 return;
2233 for (next = p; *next; ++next)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002234 {
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002235 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);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002256 XmStringFree(str);
2257 }
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002258 gui_motif_menu_fontlist(w);
2259}
2260
2261static void
2262set_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);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002273}
2274
2275/*
2276 * Put up a file requester.
2277 * Returns the selected name in allocated memory, or NULL for Cancel.
2278 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002279 char_u *
2280gui_mch_browse(saving, title, dflt, ext, initdir, filter)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002281 int saving UNUSED; /* select file to write */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282 char_u *title; /* title for the window */
2283 char_u *dflt; /* default name */
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002284 char_u *ext UNUSED; /* not used (extension added) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002285 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
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002293 /* 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);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002299
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
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002351 set_predefined_label(dialog_wgt, "Apply", _("&Filter"));
2352 set_predefined_label(dialog_wgt, "Cancel", _("&Cancel"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002353 set_predefined_label(dialog_wgt, "Dir", _("Directories"));
2354 set_predefined_label(dialog_wgt, "FilterLabel", _("Filter"));
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002355 set_predefined_label(dialog_wgt, "Help", _("&Help"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002356 set_predefined_label(dialog_wgt, "Items", _("Files"));
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002357 set_predefined_label(dialog_wgt, "OK", _("&OK"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002358 set_predefined_label(dialog_wgt, "Selection", _("Selection"));
2359
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002360 /* 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
Bram Moolenaar071d4272004-06-13 20:20:40 +00002366 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);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002377 activate_dialog_mnemonics(dialog_wgt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002378
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
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002386 suppress_dialog_mnemonics(dialog_wgt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002387 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 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002404 static void
2405DialogCancelCB(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002406 Widget w UNUSED; /* widget id */
2407 XtPointer client_data UNUSED; /* data from application */
2408 XtPointer call_data UNUSED; /* data from widget class */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002409{
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 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002421 static void
2422DialogAcceptCB(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002423 Widget w UNUSED; /* widget id */
2424 XtPointer client_data UNUSED; /* data from application */
2425 XtPointer call_data; /* data from widget class */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002426{
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
2447static int dialogStatus;
2448
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002449static void keyhit_callback(Widget w, XtPointer client_data, XEvent *event, Boolean *cont);
2450static void butproc(Widget w, XtPointer client_data, XtPointer call_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002451
2452/*
2453 * Callback function for the textfield. When CR is hit this works like
2454 * hitting the "OK" button, ESC like "Cancel".
2455 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002456 static void
2457keyhit_callback(w, client_data, event, cont)
2458 Widget w;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002459 XtPointer client_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002460 XEvent *event;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002461 Boolean *cont UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002462{
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
Bram Moolenaar071d4272004-06-13 20:20:40 +00002478 static void
2479butproc(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002480 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002481 XtPointer client_data;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002482 XtPointer call_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002483{
2484 dialogStatus = (int)(long)client_data + 1;
2485}
2486
Bram Moolenaar071d4272004-06-13 20:20:40 +00002487#ifdef HAVE_XPM
2488
2489static Widget create_pixmap_label(Widget parent, String name, char **data, ArgList args, Cardinal arg);
2490
2491 static Widget
2492create_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 /*
Bram Moolenaar933eb392007-05-10 17:52:45 +00002518 * We need to be careful here, since in case of gadgets, there is
Bram Moolenaar071d4272004-06-13 20:20:40 +00002519 * 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
Bram Moolenaar071d4272004-06-13 20:20:40 +00002554 int
Bram Moolenaard2c340a2011-01-17 20:08:11 +01002555gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield, ex_cmd)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002556 int type UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002557 char_u *title;
2558 char_u *message;
2559 char_u *button_names;
2560 int dfltbutton;
2561 char_u *textfield; /* buffer of size IOSIZE */
Bram Moolenaard2c340a2011-01-17 20:08:11 +01002562 int ex_cmd UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002563{
2564 char_u *buts;
2565 char_u *p, *next;
2566 XtAppContext app;
2567 XmString label;
2568 int butcount;
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002569 Widget w;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002570 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 {
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002630 KeySym mnemonic = NUL;
2631
Bram Moolenaar071d4272004-06-13 20:20:40 +00002632 for (next = p; *next; ++next)
2633 {
2634 if (*next == DLG_HOTKEY_CHAR)
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002635 {
2636 int len = STRLEN(next);
2637
2638 if (len > 0)
2639 {
2640 mch_memmove(next, next + 1, len);
2641 mnemonic = next[0];
2642 }
2643 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002644 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,
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002657 XmNmnemonic, mnemonic,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002658 XmNbottomAttachment, XmATTACH_FORM,
2659 XmNbottomOffset, 4,
2660 XmNshowAsDefault, butcount == dfltbutton - 1,
2661 XmNdefaultButtonShadowThickness, 1,
2662 NULL);
2663 XmStringFree(label);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002664 gui_motif_menu_fontlist(buttons[butcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002665
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
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002770 set_fontlist(dialogtextfield);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002771 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
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002822 /* 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);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002829 if (label == NULL)
2830 return -1;
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002831 w = XtVaCreateManagedWidget("dialogMessage",
Bram Moolenaar071d4272004-06-13 20:20:40 +00002832 xmLabelGadgetClass, form,
2833 XmNlabelString, label,
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002834 XmNalignment, XmALIGNMENT_BEGINNING,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002835 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);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002850 set_fontlist(w);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002851
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);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002885 activate_dialog_mnemonics(dialogform);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002886
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
Bram Moolenaarbbebc852005-07-18 21:47:53 +00002916 vim_strncpy(textfield, p, IOSIZE - 1);
Bram Moolenaar103e6ef2010-05-13 16:31:25 +02002917 XtFree((char *)p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002918 }
2919
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002920 suppress_dialog_mnemonics(dialogform);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002921 XtDestroyWidget(dialogform);
2922
2923 return dialogStatus;
2924}
2925#endif /* FEAT_GUI_DIALOG */
2926
2927#if defined(FEAT_FOOTER) || defined(PROTO)
2928
2929 static int
2930gui_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
Bram Moolenaar071d4272004-06-13 20:20:40 +00002947 void
2948gui_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
2965gui_mch_set_footer(s)
2966 char_u *s;
2967{
2968 XmString xms;
2969
2970 xms = XmStringCreate((char *)s, STRING_TAG);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00002971 if (xms != NULL)
2972 {
2973 XtVaSetValues(footer, XmNlabelString, xms, NULL);
2974 XmStringFree(xms);
2975 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002976}
2977
2978#endif
2979
2980
2981#if defined(FEAT_TOOLBAR) || defined(PROTO)
2982 void
2983gui_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
Bram Moolenaarf193fff2006-04-27 00:02:13 +00003032 * currently enabled). */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003033 if (cur->tip != NULL)
3034 (*action)(cur->tip);
3035 if (!menu_is_separator(cur->name))
3036 {
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003037 if (text == 1 || cur->xpm == NULL)
3038 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003039 XtSetArg(args[n], XmNlabelType, XmSTRING);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003040 ++n;
3041 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003042 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));
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003055#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);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003073 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))
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003087 {
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 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003107 else
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003108 {
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 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003126
3127 XtUnmanageChild(XtParent(toolBar));
3128 }
Bram Moolenaar2e2a2812006-03-27 20:55:21 +00003129 gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003130}
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
Bram Moolenaarf9980f12005-01-03 20:58:59 +00003138reset_focus()
Bram Moolenaar071d4272004-06-13 20:20:40 +00003139{
3140 if (textArea != NULL)
3141 XmProcessTraversal(textArea, XmTRAVERSE_CURRENT);
3142}
3143
3144 int
3145gui_mch_compute_toolbar_height()
3146{
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003147 Dimension borders;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003148 Dimension height; /* total Toolbar height */
3149 Dimension whgt; /* height of each widget */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003150 WidgetList children; /* list of toolBar's children */
3151 Cardinal numChildren; /* how many children toolBar has */
3152 int i;
3153
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003154 borders = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003155 height = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003156 if (toolBar != (Widget)0 && toolBarFrame != (Widget)0)
3157 { /* get height of XmFrame parent */
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003158 Dimension fst;
3159 Dimension fmh;
3160 Dimension tst;
3161 Dimension tmh;
3162
Bram Moolenaar071d4272004-06-13 20:20:40 +00003163 XtVaGetValues(toolBarFrame,
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003164 XmNshadowThickness, &fst,
3165 XmNmarginHeight, &fmh,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003166 NULL);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003167 borders += fst + fmh;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003168 XtVaGetValues(toolBar,
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003169 XmNshadowThickness, &tst,
3170 XmNmarginHeight, &tmh,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003171 XmNchildren, &children,
3172 XmNnumChildren, &numChildren, NULL);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003173 borders += tst + tmh;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003174 for (i = 0; i < (int)numChildren; i++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003175 {
3176 whgt = 0;
3177 XtVaGetValues(children[i], XmNheight, &whgt, NULL);
3178 if (height < whgt)
3179 height = whgt;
3180 }
3181 }
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003182#ifdef LESSTIF_VERSION
3183 /* Hack: When starting up we get wrong dimensions. */
3184 if (height < 10)
3185 height = 24;
3186#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003187
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003188 return (int)(height + (borders << 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003189}
3190
Bram Moolenaar7c626922005-02-07 22:01:03 +00003191 void
3192motif_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,
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00003200 XmNbackground, bgp,
3201 XmNforeground, fgp,
3202 XmNbottomShadowColor, bsp,
3203 XmNtopShadowColor, tsp,
3204 XmNhighlightColor, hsp,
3205 NULL);
Bram Moolenaar7c626922005-02-07 22:01:03 +00003206}
3207
Bram Moolenaar071d4272004-06-13 20:20:40 +00003208# ifdef FEAT_FOOTER
3209/*
3210 * The next toolbar enter/leave callbacks should really do balloon help. But
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003211 * I have to use footer help for backwards compatibility. Hopefully both will
Bram Moolenaar071d4272004-06-13 20:20:40 +00003212 * get implemented and the user will have a choice.
3213 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003214 static void
3215toolbarbutton_enter_cb(w, client_data, event, cont)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003216 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003217 XtPointer client_data;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003218 XEvent *event UNUSED;
3219 Boolean *cont UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003220{
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
Bram Moolenaar071d4272004-06-13 20:20:40 +00003230 static void
3231toolbarbutton_leave_cb(w, client_data, event, cont)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003232 Widget w UNUSED;
3233 XtPointer client_data UNUSED;
3234 XEvent *event UNUSED;
3235 Boolean *cont UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003236{
3237 gui_mch_set_footer((char_u *) "");
3238}
3239# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003240#endif
3241
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003242#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
3243/*
3244 * Show or hide the tabline.
3245 */
3246 void
3247gui_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"));
Bram Moolenaarc6fe9192006-04-09 21:54:49 +00003258 XtUnmanageChild(XtNameToWidget(tabLine, "MinorTabScrollerNext"));
3259 XtUnmanageChild(XtNameToWidget(tabLine,
3260 "MinorTabScrollerPrevious"));
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003261#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
3310gui_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
3319gui_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;
Bram Moolenaarc6fe9192006-04-09 21:54:49 +00003329 XmString label_str;
3330 char *label_cstr;
Bram Moolenaarf193fff2006-04-27 00:02:13 +00003331 BalloonEval *beval;
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003332
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
Bram Moolenaarf193fff2006-04-27 00:02:13 +00003344 || page_info.major_tab_widget == (Widget)0)
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003345 {
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);
Bram Moolenaarf193fff2006-04-27 00:02:13 +00003355 beval = gui_mch_create_beval_area(tab, NULL, tabline_balloon_cb,
3356 NULL);
3357 XtVaSetValues(tab, XmNuserData, beval, NULL);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003358 }
3359 else
3360 tab = page_info.major_tab_widget;
3361
3362 XtVaSetValues(tab, XmNpageNumber, nr, NULL);
Bram Moolenaarc6fe9192006-04-09 21:54:49 +00003363
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 {
Bram Moolenaar57657d82006-04-21 22:12:41 +00003370 get_tabline_label(tp, FALSE);
3371 if (STRCMP(label_cstr, NameBuff) != 0)
3372 {
Bram Moolenaarc6fe9192006-04-09 21:54:49 +00003373 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 }
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003383 }
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 {
Bram Moolenaarf193fff2006-04-27 00:02:13 +00003396 XtVaGetValues(page_info.major_tab_widget, XmNuserData, &beval, NULL);
3397 if (beval != NULL)
3398 gui_mch_destroy_beval_area(beval);
Bram Moolenaar910f66f2006-04-05 20:41:53 +00003399 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
3416gui_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
Bram Moolenaar071d4272004-06-13 20:20:40 +00003430/*
3431 * Set the colors of Widget "id" to the menu colors.
3432 */
3433 static void
3434gui_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
3451gui_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
Bram Moolenaar071d4272004-06-13 20:20:40 +00003464/*
3465 * Set the fontlist for Widget "id" to use gui.menu_fontset or gui.menu_font.
3466 */
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003467 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00003468gui_motif_menu_fontlist(id)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003469 Widget id UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003470{
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003471#ifdef FEAT_MENU
Bram Moolenaar071d4272004-06-13 20:20:40 +00003472#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
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003515#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003516}
3517
Bram Moolenaar071d4272004-06-13 20:20:40 +00003518
3519/*
3520 * We don't create it twice for the sake of speed.
3521 */
3522
3523typedef 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
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003540static SharedFindReplace find_widgets = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
3541static SharedFindReplace repl_widgets = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
Bram Moolenaar071d4272004-06-13 20:20:40 +00003542
Bram Moolenaard25c16e2016-01-29 22:13:30 +01003543static void find_replace_destroy_callback(Widget w, XtPointer client_data, XtPointer call_data);
3544static void find_replace_dismiss_callback(Widget w, XtPointer client_data, XtPointer call_data);
3545static void entry_activate_callback(Widget w, XtPointer client_data, XtPointer call_data);
3546static void find_replace_callback(Widget w, XtPointer client_data, XtPointer call_data);
3547static void find_replace_keypress(Widget w, SharedFindReplace * frdp, XKeyEvent * event);
3548static void find_replace_dialog_create(char_u *entry_text, int do_replace);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003549
Bram Moolenaar071d4272004-06-13 20:20:40 +00003550 static void
3551find_replace_destroy_callback(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003552 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003553 XtPointer client_data;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003554 XtPointer call_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003555{
3556 SharedFindReplace *cd = (SharedFindReplace *)client_data;
3557
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00003558 if (cd != NULL)
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003559 /* suppress_dialog_mnemonics(cd->dialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003560 cd->dialog = (Widget)0;
3561}
3562
Bram Moolenaar071d4272004-06-13 20:20:40 +00003563 static void
3564find_replace_dismiss_callback(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003565 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003566 XtPointer client_data;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003567 XtPointer call_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003568{
3569 SharedFindReplace *cd = (SharedFindReplace *)client_data;
3570
3571 if (cd != NULL)
3572 XtUnmanageChild(cd->dialog);
3573}
3574
Bram Moolenaar071d4272004-06-13 20:20:40 +00003575 static void
3576entry_activate_callback(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003577 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003578 XtPointer client_data;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003579 XtPointer call_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003580{
3581 XmProcessTraversal((Widget)client_data, XmTRAVERSE_CURRENT);
3582}
3583
Bram Moolenaar071d4272004-06-13 20:20:40 +00003584 static void
3585find_replace_callback(w, client_data, call_data)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003586 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003587 XtPointer client_data;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003588 XtPointer call_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003589{
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
Bram Moolenaar071d4272004-06-13 20:20:40 +00003638 static void
3639find_replace_keypress(w, frdp, event)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00003640 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003641 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
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003657set_label(w, label)
3658 Widget w;
Bram Moolenaar3dbcd0c2013-06-22 13:00:16 +02003659 char *label;
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003660{
3661 XmString str;
3662 char_u *p, *next;
3663 KeySym mnemonic = NUL;
3664
3665 if (!w)
3666 return;
3667
Bram Moolenaar3dbcd0c2013-06-22 13:00:16 +02003668 p = vim_strsave((char_u *)label);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003669 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
Bram Moolenaar071d4272004-06-13 20:20:40 +00003699find_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 {
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003726 gui_motif_synch_fonts();
3727
Bram Moolenaar071d4272004-06-13 20:20:40 +00003728 /* 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
Bram Moolenaar071d4272004-06-13 20:20:40 +00003771 frdp->find = XtVaCreateManagedWidget("findButton",
3772 xmPushButtonWidgetClass, button_form,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003773 XmNsensitive, True,
3774 XmNtopAttachment, XmATTACH_FORM,
3775 XmNleftAttachment, XmATTACH_FORM,
3776 XmNrightAttachment, XmATTACH_FORM,
3777 NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003778 set_label(frdp->find, _("Find &Next"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003779
3780 XtAddCallback(frdp->find, XmNactivateCallback,
3781 find_replace_callback,
Bram Moolenaare9e3b572008-01-22 10:06:48 +00003782 (do_replace ? (XtPointer)FRD_R_FINDNEXT : (XtPointer)FRD_FINDNEXT));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003783
3784 if (do_replace)
3785 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00003786 frdp->replace = XtVaCreateManagedWidget("replaceButton",
3787 xmPushButtonWidgetClass, button_form,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003788 XmNtopAttachment, XmATTACH_WIDGET,
3789 XmNtopWidget, frdp->find,
3790 XmNleftAttachment, XmATTACH_FORM,
3791 XmNrightAttachment, XmATTACH_FORM,
3792 NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003793 set_label(frdp->replace, _("&Replace"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003794 XtAddCallback(frdp->replace, XmNactivateCallback,
3795 find_replace_callback, (XtPointer)FRD_REPLACE);
3796
Bram Moolenaar071d4272004-06-13 20:20:40 +00003797 frdp->all = XtVaCreateManagedWidget("replaceAllButton",
3798 xmPushButtonWidgetClass, button_form,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003799 XmNtopAttachment, XmATTACH_WIDGET,
3800 XmNtopWidget, frdp->replace,
3801 XmNleftAttachment, XmATTACH_FORM,
3802 XmNrightAttachment, XmATTACH_FORM,
3803 NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003804 set_label(frdp->all, _("Replace &All"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003805 XtAddCallback(frdp->all, XmNactivateCallback,
3806 find_replace_callback, (XtPointer)FRD_REPLACEALL);
3807
Bram Moolenaar071d4272004-06-13 20:20:40 +00003808 frdp->undo = XtVaCreateManagedWidget("undoButton",
3809 xmPushButtonWidgetClass, button_form,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003810 XmNtopAttachment, XmATTACH_WIDGET,
3811 XmNtopWidget, frdp->all,
3812 XmNleftAttachment, XmATTACH_FORM,
3813 XmNrightAttachment, XmATTACH_FORM,
3814 NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003815 set_label(frdp->undo, _("&Undo"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003816 XtAddCallback(frdp->undo, XmNactivateCallback,
3817 find_replace_callback, (XtPointer)FRD_UNDO);
3818 }
3819
Bram Moolenaar071d4272004-06-13 20:20:40 +00003820 frdp->cancel = XtVaCreateManagedWidget("closeButton",
3821 xmPushButtonWidgetClass, button_form,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003822 XmNleftAttachment, XmATTACH_FORM,
3823 XmNrightAttachment, XmATTACH_FORM,
3824 XmNbottomAttachment, XmATTACH_FORM,
3825 NULL);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003826 set_label(frdp->cancel, _("&Cancel"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003827 XtAddCallback(frdp->cancel, XmNactivateCallback,
3828 find_replace_dismiss_callback, frdp);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003829 gui_motif_menu_fontlist(frdp->cancel);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003830
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);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003867 gui_motif_menu_fontlist(label_what);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003868
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);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003902 gui_motif_menu_fontlist(label_with);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003903
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;
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003950 Widget w;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003951
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"));
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003964 w = XtVaCreateManagedWidget("directionFrameLabel",
Bram Moolenaar071d4272004-06-13 20:20:40 +00003965 xmLabelGadgetClass, frame,
3966 XmNlabelString, str,
3967 XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
3968 XmNchildType, XmFRAME_TITLE_CHILD,
3969 NULL);
3970 XmStringFree(str);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003971 gui_motif_menu_fontlist(w);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003972
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);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003983 gui_motif_menu_fontlist(frdp->up);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003984
3985 str = XmStringCreateSimple(_("Down"));
3986 frdp->down = XtVaCreateManagedWidget("downRadioButton",
3987 xmToggleButtonGadgetClass, radio_box,
3988 XmNlabelString, str,
3989 XmNset, True,
3990 NULL);
3991 XmStringFree(str);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003992 gui_motif_menu_fontlist(frdp->down);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003993
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);
Bram Moolenaardfccaf02004-12-31 20:56:11 +00004036 gui_motif_menu_fontlist(frdp->wword);
4037 gui_motif_menu_fontlist(frdp->mcase);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004038
4039 XtManageChild(toggle_form);
4040
4041 if (entry_text != NULL)
4042 XmTextFieldSetString(frdp->what, (char *)entry_text);
4043 vim_free(entry_text);
4044
Bram Moolenaardfccaf02004-12-31 20:56:11 +00004045 gui_motif_synch_fonts();
4046
4047 manage_centered(frdp->dialog);
4048 activate_dialog_mnemonics(frdp->dialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004049 XmProcessTraversal(frdp->what, XmTRAVERSE_CURRENT);
4050}
4051
4052 void
4053gui_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
4064gui_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}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00004072
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
4080gui_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}