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