1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
4 * GUI/Motif support by Robert Webb
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.
12 #include <Xm/RowColumn.h>
16 #include <Xm/Separator.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>
26 #include <Xm/LabelG.h>
27 #include <Xm/ToggleBG.h>
28 #include <Xm/SeparatoG.h>
31 #include <X11/keysym.h>
32 #include <X11/Xatom.h>
33 #include <X11/StringDefs.h>
34 #include <X11/Intrinsic.h>
41 # ifdef HAVE_XM_XPMP_H
45 #ifdef HAVE_XM_NOTEBOOK_H
46 # include <Xm/Notebook.h>
49 #include "gui_xmebw.h" /* for our Enhanced Button Widget */
51 #if defined(FEAT_GUI_DIALOG) && defined(HAVE_XPM)
52 # include "../pixmaps/alert.xpm"
53 # include "../pixmaps/error.xpm"
54 # include "../pixmaps/generic.xpm"
55 # include "../pixmaps/info.xpm"
56 # include "../pixmaps/quest.xpm"
61 extern Widget vimShell
;
63 static Widget vimForm
;
64 static Widget textAreaForm
;
67 static Widget toolBarFrame
;
68 static Widget toolBar
;
70 #ifdef FEAT_GUI_TABLINE
71 static Widget tabLine
;
72 static Widget tabLine_menu
= 0;
73 static int showing_tabline
= 0;
79 # if (XmVersion >= 1002)
80 /* remember the last set value for the tearoff item */
81 static int tearoff_val
= (int)XmTEAR_OFF_ENABLED
;
83 static Widget menuBar
;
86 static void scroll_cb
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
87 #ifdef FEAT_GUI_TABLINE
88 static void tabline_cb
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
89 static void tabline_button_cb
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
90 static void tabline_menu_cb
__ARGS((Widget w
, XtPointer closure
, XEvent
*e
, Boolean
*continue_dispatch
));
91 static void tabline_balloon_cb
__ARGS((BalloonEval
*beval
, int state
));
95 static void toolbarbutton_enter_cb
__ARGS((Widget
, XtPointer
, XEvent
*, Boolean
*));
96 static void toolbarbutton_leave_cb
__ARGS((Widget
, XtPointer
, XEvent
*, Boolean
*));
98 static void reset_focus
__ARGS((void));
101 static int gui_mch_compute_footer_height
__ARGS((void));
104 static void attachDump(Widget
, char *);
107 static void gui_motif_menu_colors
__ARGS((Widget id
));
108 static void gui_motif_scroll_colors
__ARGS((Widget id
));
110 #if (XmVersion >= 1002)
111 # define STRING_TAG XmFONTLIST_DEFAULT_TAG
113 # define STRING_TAG XmSTRING_DEFAULT_CHARSET
117 * Call-back routines.
121 scroll_cb(w
, client_data
, call_data
)
123 XtPointer client_data
, call_data
;
129 sb
= gui_find_scrollbar((long)client_data
);
131 value
= ((XmScrollBarCallbackStruct
*)call_data
)->value
;
132 dragging
= (((XmScrollBarCallbackStruct
*)call_data
)->reason
==
134 gui_drag_scrollbar(sb
, value
, dragging
);
137 #ifdef FEAT_GUI_TABLINE
139 tabline_cb(w
, client_data
, call_data
)
141 XtPointer client_data UNUSED
;
144 XmNotebookCallbackStruct
*nptr
;
146 nptr
= (XmNotebookCallbackStruct
*)call_data
;
147 if (nptr
->reason
!= (int)XmCR_NONE
)
148 send_tabline_event(nptr
->page_number
);
152 tabline_button_cb(w
, client_data
, call_data
)
154 XtPointer client_data UNUSED
;
155 XtPointer call_data UNUSED
;
159 XtVaGetValues(w
, XmNuserData
, &cmd
, NULL
);
160 XtVaGetValues(tabLine_menu
, XmNuserData
, &tab_idx
, NULL
);
162 send_tabline_menu_event(tab_idx
, cmd
);
166 * Tabline single mouse click timeout handler
169 motif_tabline_timer_cb (timed_out
, interval_id
)
171 XtIntervalId
*interval_id UNUSED
;
173 *((int *)timed_out
) = TRUE
;
177 * check if the tabline tab scroller is clicked
180 tabline_scroller_clicked(scroller_name
, event
)
182 XButtonPressedEvent
*event
;
185 Position pos_x
, pos_y
;
186 Dimension width
, height
;
188 tab_scroll_w
= XtNameToWidget(tabLine
, scroller_name
);
189 if (tab_scroll_w
!= (Widget
)0) {
190 XtVaGetValues(tab_scroll_w
, XmNx
, &pos_x
, XmNy
, &pos_y
, XmNwidth
,
191 &width
, XmNheight
, &height
, NULL
);
193 /* Tab scroller (next) is visible */
194 if ((event
->x
>= pos_x
) && (event
->x
<= pos_x
+ width
) &&
195 (event
->y
>= pos_y
) && (event
->y
<= pos_y
+ height
)) {
196 /* Clicked on the scroller */
205 tabline_menu_cb(w
, closure
, e
, continue_dispatch
)
207 XtPointer closure UNUSED
;
209 Boolean
*continue_dispatch UNUSED
;
212 XButtonPressedEvent
*event
;
215 Cardinal numChildren
;
216 static XtIntervalId timer
= (XtIntervalId
)0;
217 static int timed_out
= TRUE
;
219 event
= (XButtonPressedEvent
*)e
;
221 if (event
->button
== Button1
)
223 if (tabline_scroller_clicked("MajorTabScrollerNext", event
)
224 || tabline_scroller_clicked("MajorTabScrollerPrevious", event
))
229 XtRemoveTimeOut(timer
);
233 * Double click on the tabline gutter, add a new tab
235 send_tabline_menu_event(0, TABLINE_MENU_NEW
);
240 * Single click on the tabline gutter, start a timer to check
243 timer
= XtAppAddTimeOut(app_context
, (long_u
)p_mouset
,
244 motif_tabline_timer_cb
, &timed_out
);
250 if (event
->button
!= Button3
)
253 /* When ignoring events don't show the menu. */
261 if (event
->subwindow
!= None
)
263 tab_w
= XtWindowToWidget(XtDisplay(w
), event
->subwindow
);
264 /* LINTED: avoid warning: dubious operation on enum */
265 if (tab_w
!= (Widget
)0 && XmIsPushButton(tab_w
))
266 XtVaGetValues(tab_w
, XmNpageNumber
, &tab_idx
, NULL
);
269 XtVaSetValues(tabLine_menu
, XmNuserData
, tab_idx
, NULL
);
270 XtVaGetValues(tabLine_menu
, XmNchildren
, &children
, XmNnumChildren
,
272 XtManageChildren(children
, numChildren
);
273 XmMenuPosition(tabLine_menu
, (XButtonPressedEvent
*)e
) ;
274 XtManageChild(tabLine_menu
);
278 tabline_balloon_cb(beval
, state
)
285 if (beval
->target
== (Widget
)0)
288 XtVaGetValues(beval
->target
, XmNpageNumber
, &nr
, NULL
);
289 tp
= find_tabpage(nr
);
293 get_tabline_label(tp
, TRUE
);
294 gui_mch_post_balloon(beval
, NameBuff
);
300 * End of call-back routines
304 * Implement three dimensional shading of insensitive labels.
309 #include <Xm/LabelP.h>
311 static XtExposeProc old_label_expose
= NULL
;
313 static void label_expose
__ARGS((Widget _w
, XEvent
*_event
, Region _region
));
316 label_expose(_w
, _event
, _region
)
322 XmLabelWidget lw
= (XmLabelWidget
)_w
;
323 unsigned char label_type
= (int)XmSTRING
;
325 XtVaGetValues(_w
, XmNlabelType
, &label_type
, (XtPointer
)0);
327 if (XtIsSensitive(_w
) || label_type
!= (int)XmSTRING
)
328 (*old_label_expose
)(_w
, _event
, _region
);
336 _XmFontListGetDefaultFont(lw
->label
.font
, &fs
);
338 /* FIXME: we should be doing the whole drawing ourself here. */
339 insensitiveGC
= lw
->label
.insensitive_GC
;
341 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
342 dynamic
= GCClipMask
| GCClipXOrigin
| GCClipYOrigin
;
343 values
.graphics_exposures
= False
;
348 values
.font
= fs
->fid
;
351 if (lw
->primitive
.top_shadow_pixmap
!= None
352 && lw
->primitive
.top_shadow_pixmap
!= XmUNSPECIFIED_PIXMAP
)
354 mask
|= GCFillStyle
| GCTile
;
355 values
.fill_style
= FillTiled
;
356 values
.tile
= lw
->primitive
.top_shadow_pixmap
;
359 lw
->label
.TextRect
.x
+= 1;
360 lw
->label
.TextRect
.y
+= 1;
361 if (lw
->label
._acc_text
!= 0)
363 lw
->label
.acc_TextRect
.x
+= 1;
364 lw
->label
.acc_TextRect
.y
+= 1;
367 values
.foreground
= lw
->primitive
.top_shadow_color
;
368 values
.background
= lw
->core
.background_pixel
;
370 lw
->label
.insensitive_GC
= XtAllocateGC((Widget
)lw
, 0, mask
,
371 &values
, dynamic
, (XtGCMask
)0);
372 (*old_label_expose
)(_w
, _event
, _region
);
373 XtReleaseGC(_w
, lw
->label
.insensitive_GC
);
375 lw
->label
.TextRect
.x
-= 1;
376 lw
->label
.TextRect
.y
-= 1;
377 if (lw
->label
._acc_text
!= 0)
379 lw
->label
.acc_TextRect
.x
-= 1;
380 lw
->label
.acc_TextRect
.y
-= 1;
383 values
.foreground
= lw
->primitive
.bottom_shadow_color
;
384 values
.background
= lw
->core
.background_pixel
;
386 lw
->label
.insensitive_GC
= XtAllocateGC((Widget
) lw
, 0, mask
,
387 &values
, dynamic
, (XtGCMask
)0);
388 (*old_label_expose
)(_w
, _event
, _region
);
389 XtReleaseGC(_w
, lw
->label
.insensitive_GC
);
391 lw
->label
.insensitive_GC
= insensitiveGC
;
396 * Create all the motif widgets necessary.
399 gui_x11_create_widgets()
401 #ifdef FEAT_GUI_TABLINE
402 Widget button
, scroller
;
409 * Install the 3D shade effect drawing routines.
411 if (old_label_expose
== NULL
)
413 old_label_expose
= xmLabelWidgetClass
->core_class
.expose
;
414 xmLabelWidgetClass
->core_class
.expose
= label_expose
;
418 * Start out by adding the configured border width into the border offset
420 gui
.border_offset
= gui
.border_width
;
423 * Install the tearOffModel resource converter.
425 #if (XmVersion >= 1002)
426 XmRepTypeInstallTearOffModelConverter();
429 /* Make sure the "Quit" menu entry of the window manager is ignored */
430 XtVaSetValues(vimShell
, XmNdeleteResponse
, XmDO_NOTHING
, NULL
);
432 vimForm
= XtVaCreateManagedWidget("vimForm",
433 xmFormWidgetClass
, vimShell
,
435 XmNhighlightThickness
, 0,
436 XmNshadowThickness
, 0,
439 XmNresizePolicy
, XmRESIZE_ANY
,
441 gui_motif_menu_colors(vimForm
);
445 Arg al
[7]; /* Make sure there is enough room for arguments! */
448 # if (XmVersion >= 1002)
449 XtSetArg(al
[ac
], XmNtearOffModel
, tearoff_val
); ac
++;
451 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
452 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
453 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
454 # ifndef FEAT_TOOLBAR
455 /* Always stick to right hand side. */
456 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
458 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
459 menuBar
= XmCreateMenuBar(vimForm
, "menuBar", al
, ac
);
460 XtManageChild(menuBar
);
462 /* Remember the default colors, needed for ":hi clear". */
463 XtVaGetValues(menuBar
,
464 XmNbackground
, &gui
.menu_def_bg_pixel
,
465 XmNforeground
, &gui
.menu_def_fg_pixel
,
467 gui_motif_menu_colors(menuBar
);
473 * Create an empty ToolBar. We should get buttons defined from menu.vim.
475 toolBarFrame
= XtVaCreateWidget("toolBarFrame",
476 xmFrameWidgetClass
, vimForm
,
477 XmNshadowThickness
, 0,
480 XmNleftAttachment
, XmATTACH_FORM
,
481 XmNrightAttachment
, XmATTACH_FORM
,
483 gui_motif_menu_colors(toolBarFrame
);
485 toolBar
= XtVaCreateManagedWidget("toolBar",
486 xmRowColumnWidgetClass
, toolBarFrame
,
487 XmNchildType
, XmFRAME_WORKAREA_CHILD
,
488 XmNrowColumnType
, XmWORK_AREA
,
489 XmNorientation
, XmHORIZONTAL
,
490 XmNtraversalOn
, False
,
491 XmNisHomogeneous
, False
,
492 XmNpacking
, XmPACK_TIGHT
,
494 XmNshadowThickness
, 0,
495 XmNhighlightThickness
, 0,
500 gui_motif_menu_colors(toolBar
);
504 #ifdef FEAT_GUI_TABLINE
505 /* Create the Vim GUI tabline */
507 XtSetArg(args
[n
], XmNbindingType
, XmNONE
); n
++;
508 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
509 XtSetArg(args
[n
], XmNbackPageSize
, XmNONE
); n
++;
510 XtSetArg(args
[n
], XmNbackPageNumber
, 0); n
++;
511 XtSetArg(args
[n
], XmNbackPagePlacement
, XmTOP_RIGHT
); n
++;
512 XtSetArg(args
[n
], XmNmajorTabSpacing
, 0); n
++;
513 XtSetArg(args
[n
], XmNshadowThickness
, 0); n
++;
514 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
515 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
516 tabLine
= XmCreateNotebook(vimForm
, "Vim tabline", args
, n
);
518 XtAddCallback(tabLine
, XmNpageChangedCallback
, (XtCallbackProc
)tabline_cb
,
520 XtAddEventHandler(tabLine
, ButtonPressMask
, False
,
521 (XtEventHandler
)tabline_menu_cb
, NULL
);
523 gui
.tabline_height
= TABLINE_HEIGHT
;
526 * Set the size of the minor next/prev scrollers to zero, so
527 * that they are not displayed. Due to a bug in OpenMotif 2.3,
528 * even if these children widget are unmanaged, they are again
529 * managed by the Notebook widget and the notebook widget geometry
530 * is adjusted to account for the minor scroller widgets.
532 scroller
= XtNameToWidget(tabLine
, "MinorTabScrollerNext");
533 XtVaSetValues(scroller
, XmNwidth
, 0, XmNresizable
, False
,
534 XmNtraversalOn
, False
, NULL
);
535 scroller
= XtNameToWidget(tabLine
, "MinorTabScrollerPrevious");
536 XtVaSetValues(scroller
, XmNwidth
, 0, XmNresizable
, False
,
537 XmNtraversalOn
, False
, NULL
);
539 /* Create the tabline popup menu */
540 tabLine_menu
= XmCreatePopupMenu(tabLine
, "tabline popup", NULL
, 0);
542 /* Add the buttons to the menu */
544 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_CLOSE
); n
++;
545 xms
= XmStringCreate((char *)"Close tab", STRING_TAG
);
546 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
547 button
= XmCreatePushButton(tabLine_menu
, "Close", args
, n
);
548 XtAddCallback(button
, XmNactivateCallback
,
549 (XtCallbackProc
)tabline_button_cb
, NULL
);
553 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_NEW
); n
++;
554 xms
= XmStringCreate((char *)"New Tab", STRING_TAG
);
555 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
556 button
= XmCreatePushButton(tabLine_menu
, "New Tab", args
, n
);
557 XtAddCallback(button
, XmNactivateCallback
,
558 (XtCallbackProc
)tabline_button_cb
, NULL
);
562 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_OPEN
); n
++;
563 xms
= XmStringCreate((char *)"Open tab...", STRING_TAG
);
564 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
565 button
= XmCreatePushButton(tabLine_menu
, "Open tab...", args
, n
);
566 XtAddCallback(button
, XmNactivateCallback
,
567 (XtCallbackProc
)tabline_button_cb
, NULL
);
571 textAreaForm
= XtVaCreateManagedWidget("textAreaForm",
572 xmFormWidgetClass
, vimForm
,
573 XmNleftAttachment
, XmATTACH_FORM
,
574 XmNrightAttachment
, XmATTACH_FORM
,
575 XmNbottomAttachment
, XmATTACH_FORM
,
576 XmNtopAttachment
, XmATTACH_FORM
,
579 XmNresizePolicy
, XmRESIZE_ANY
,
581 gui_motif_scroll_colors(textAreaForm
);
583 textArea
= XtVaCreateManagedWidget("textArea",
584 xmDrawingAreaWidgetClass
, textAreaForm
,
585 XmNforeground
, gui
.norm_pixel
,
586 XmNbackground
, gui
.back_pixel
,
587 XmNleftAttachment
, XmATTACH_FORM
,
588 XmNtopAttachment
, XmATTACH_FORM
,
589 XmNrightAttachment
, XmATTACH_FORM
,
590 XmNbottomAttachment
, XmATTACH_FORM
,
593 * These take some control away from the user, but avoids making them
594 * add resources to get a decent looking setup.
597 XmNhighlightThickness
, 0,
598 XmNshadowThickness
, 0,
605 footer
= XtVaCreateWidget("footer",
606 xmLabelGadgetClass
, vimForm
,
607 XmNalignment
, XmALIGNMENT_BEGINNING
,
610 XmNtraversalOn
, False
,
611 XmNrecomputeSize
, False
,
612 XmNleftAttachment
, XmATTACH_FORM
,
614 XmNrightAttachment
, XmATTACH_FORM
,
615 XmNbottomAttachment
, XmATTACH_FORM
,
617 gui_mch_set_footer((char_u
*) "");
621 * Install the callbacks.
623 gui_x11_callbacks(textArea
, vimForm
);
625 /* Pretend we don't have input focus, we will get an event if we do. */
626 gui
.in_focus
= FALSE
;
630 * Called when the GUI is not going to start after all.
633 gui_x11_destroy_widgets()
642 gui_mch_set_text_area_pos(x
, y
, w
, h
)
649 /* Give keyboard focus to the textArea instead of the toolbar. */
655 gui_x11_set_back_color()
657 if (textArea
!= NULL
)
658 #if (XmVersion >= 1002)
659 XmChangeColor(textArea
, gui
.back_pixel
);
661 XtVaSetValues(textArea
,
662 XmNbackground
, gui
.back_pixel
,
668 * Manage dialog centered on pointer. This could be used by the Athena code as
672 manage_centered(dialog_child
)
675 Widget shell
= XtParent(dialog_child
);
678 unsigned int width
, height
, border_width
, depth
;
679 int x
, y
, win_x
, win_y
, maxX
, maxY
;
680 Boolean mappedWhenManaged
;
682 /* Temporarily set value of XmNmappedWhenManaged
683 to stop the dialog from popping up right away */
684 XtVaGetValues(shell
, XmNmappedWhenManaged
, &mappedWhenManaged
, NULL
);
685 XtVaSetValues(shell
, XmNmappedWhenManaged
, False
, NULL
);
687 XtManageChild(dialog_child
);
689 /* Get the pointer position (x, y) */
690 XQueryPointer(XtDisplay(shell
), XtWindow(shell
), &root
, &child
,
691 &x
, &y
, &win_x
, &win_y
, &mask
);
693 /* Translate the pointer position (x, y) into a position for the new
694 window that will place the pointer at its center */
695 XGetGeometry(XtDisplay(shell
), XtWindow(shell
), &root
, &win_x
, &win_y
,
696 &width
, &height
, &border_width
, &depth
);
697 width
+= 2 * border_width
;
698 height
+= 2 * border_width
;
702 /* Ensure that the dialog remains on screen */
703 maxX
= XtScreen(shell
)->width
- width
;
704 maxY
= XtScreen(shell
)->height
- height
;
714 /* Set desired window position in the DialogShell */
715 XtVaSetValues(shell
, XmNx
, x
, XmNy
, y
, NULL
);
720 /* Restore the value of XmNmappedWhenManaged */
721 XtVaSetValues(shell
, XmNmappedWhenManaged
, mappedWhenManaged
, NULL
);
724 #if defined(FEAT_MENU) || defined(FEAT_SUN_WORKSHOP) \
725 || defined(FEAT_GUI_DIALOG) || defined(PROTO)
728 * Encapsulate the way an XmFontList is created.
731 gui_motif_create_fontlist(font
)
734 XmFontList font_list
;
736 # if (XmVersion <= 1001)
737 /* Motif 1.1 method */
738 font_list
= XmFontListCreate(font
, STRING_TAG
);
740 /* Motif 1.2 method */
741 XmFontListEntry font_list_entry
;
743 font_list_entry
= XmFontListEntryCreate(STRING_TAG
, XmFONT_IS_FONT
,
745 font_list
= XmFontListAppendEntry(NULL
, font_list_entry
);
746 XmFontListEntryFree(&font_list_entry
);
751 # if ((XmVersion > 1001) && defined(FEAT_XFONTSET)) || defined(PROTO)
753 gui_motif_fontset2fontlist(fontset
)
756 XmFontList font_list
;
758 /* Motif 1.2 method */
759 XmFontListEntry font_list_entry
;
761 font_list_entry
= XmFontListEntryCreate(STRING_TAG
,
763 (XtPointer
)*fontset
);
764 font_list
= XmFontListAppendEntry(NULL
, font_list_entry
);
765 XmFontListEntryFree(&font_list_entry
);
772 #if defined(FEAT_MENU) || defined(PROTO)
777 static void gui_motif_add_actext
__ARGS((vimmenu_T
*menu
));
778 #if (XmVersion >= 1002)
779 static void toggle_tearoff
__ARGS((Widget wid
));
780 static void gui_mch_recurse_tearoffs
__ARGS((vimmenu_T
*menu
));
782 static void submenu_change
__ARGS((vimmenu_T
*mp
, int colors
));
784 static void do_set_mnemonics
__ARGS((int enable
));
785 static int menu_enabled
= TRUE
;
788 gui_mch_enable_menu(flag
)
793 XtManageChild(menuBar
);
795 if (XtIsManaged(XtParent(toolBar
)))
797 /* toolBar is attached to top form */
798 XtVaSetValues(XtParent(toolBar
),
799 XmNtopAttachment
, XmATTACH_WIDGET
,
800 XmNtopWidget
, menuBar
,
802 #ifdef FEAT_GUI_TABLINE
805 XtVaSetValues(tabLine
,
806 XmNtopAttachment
, XmATTACH_WIDGET
,
807 XmNtopWidget
, XtParent(toolBar
),
809 XtVaSetValues(textAreaForm
,
810 XmNtopAttachment
, XmATTACH_WIDGET
,
811 XmNtopWidget
, tabLine
,
816 XtVaSetValues(textAreaForm
,
817 XmNtopAttachment
, XmATTACH_WIDGET
,
818 XmNtopWidget
, XtParent(toolBar
),
824 #ifdef FEAT_GUI_TABLINE
827 XtVaSetValues(tabLine
,
828 XmNtopAttachment
, XmATTACH_WIDGET
,
829 XmNtopWidget
, menuBar
,
831 XtVaSetValues(textAreaForm
,
832 XmNtopAttachment
, XmATTACH_WIDGET
,
833 XmNtopWidget
, tabLine
,
838 XtVaSetValues(textAreaForm
,
839 XmNtopAttachment
, XmATTACH_WIDGET
,
840 XmNtopWidget
, menuBar
,
846 XtUnmanageChild(menuBar
);
848 if (XtIsManaged(XtParent(toolBar
)))
850 XtVaSetValues(XtParent(toolBar
),
851 XmNtopAttachment
, XmATTACH_FORM
,
853 #ifdef FEAT_GUI_TABLINE
856 XtVaSetValues(tabLine
,
857 XmNtopAttachment
, XmATTACH_WIDGET
,
858 XmNtopWidget
, XtParent(toolBar
),
860 XtVaSetValues(textAreaForm
,
861 XmNtopAttachment
, XmATTACH_WIDGET
,
862 XmNtopWidget
, tabLine
,
867 XtVaSetValues(textAreaForm
,
868 XmNtopAttachment
, XmATTACH_WIDGET
,
869 XmNtopWidget
, XtParent(toolBar
),
875 #ifdef FEAT_GUI_TABLINE
878 XtVaSetValues(tabLine
,
879 XmNtopAttachment
, XmATTACH_FORM
,
881 XtVaSetValues(textAreaForm
,
882 XmNtopAttachment
, XmATTACH_WIDGET
,
883 XmNtopWidget
, tabLine
,
888 XtVaSetValues(textAreaForm
,
889 XmNtopAttachment
, XmATTACH_FORM
,
897 * Enable or disable mnemonics for the toplevel menus.
900 gui_motif_set_mnemonics(enable
)
904 * Don't enable menu mnemonics when the menu bar is disabled, LessTif
905 * crashes when using a mnemonic then.
909 do_set_mnemonics(enable
);
913 do_set_mnemonics(enable
)
918 for (menu
= root_menu
; menu
!= NULL
; menu
= menu
->next
)
919 if (menu
->id
!= (Widget
)0)
920 XtVaSetValues(menu
->id
,
921 XmNmnemonic
, enable
? menu
->mnemonic
: NUL
,
926 gui_mch_add_menu(menu
, idx
)
932 vimmenu_T
*parent
= menu
->parent
;
935 if (menu_is_popup(menu
->name
))
940 /* Only create the popup menu when it's actually used, otherwise there
941 * is a delay when using the right mouse button. */
942 # if (XmVersion <= 1002)
943 if (mouse_model_popup())
946 if (gui
.menu_bg_pixel
!= INVALCOLOR
)
948 XtSetArg(arg
[0], XmNbackground
, gui
.menu_bg_pixel
); n
++;
950 if (gui
.menu_fg_pixel
!= INVALCOLOR
)
952 XtSetArg(arg
[1], XmNforeground
, gui
.menu_fg_pixel
); n
++;
954 menu
->submenu_id
= XmCreatePopupMenu(textArea
, "contextMenu",
956 menu
->id
= (Widget
)0;
962 if (!menu_is_menubar(menu
->name
)
963 || (parent
!= NULL
&& parent
->submenu_id
== (Widget
)0))
966 label
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
969 menu
->id
= XtVaCreateWidget("subMenu",
970 xmCascadeButtonWidgetClass
,
971 (parent
== NULL
) ? menuBar
: parent
->submenu_id
,
972 XmNlabelString
, label
,
973 XmNmnemonic
, p_wak
[0] == 'n' ? NUL
: menu
->mnemonic
,
974 #if (XmVersion >= 1002)
975 /* submenu: count the tearoff item (needed for LessTif) */
976 XmNpositionIndex
, idx
+ (parent
!= NULL
977 && tearoff_val
== (int)XmTEAR_OFF_ENABLED
? 1 : 0),
980 gui_motif_menu_colors(menu
->id
);
981 gui_motif_menu_fontlist(menu
->id
);
984 if (menu
->id
== (Widget
)0) /* failed */
987 /* add accelerator text */
988 gui_motif_add_actext(menu
);
990 shell
= XtVaCreateWidget("subMenuShell",
991 xmMenuShellWidgetClass
, menu
->id
,
995 gui_motif_menu_colors(shell
);
996 menu
->submenu_id
= XtVaCreateWidget("rowColumnMenu",
997 xmRowColumnWidgetClass
, shell
,
998 XmNrowColumnType
, XmMENU_PULLDOWN
,
1000 gui_motif_menu_colors(menu
->submenu_id
);
1002 if (menu
->submenu_id
== (Widget
)0) /* failed */
1005 #if (XmVersion >= 1002)
1006 /* Set the colors for the tear off widget */
1007 toggle_tearoff(menu
->submenu_id
);
1010 XtVaSetValues(menu
->id
,
1011 XmNsubMenuId
, menu
->submenu_id
,
1015 * The "Help" menu is a special case, and should be placed at the far
1016 * right hand side of the menu-bar. It's recognized by its high priority.
1018 if (parent
== NULL
&& menu
->priority
>= 9999)
1019 XtVaSetValues(menuBar
,
1020 XmNmenuHelpWidget
, menu
->id
,
1024 * When we add a top-level item to the menu bar, we can figure out how
1025 * high the menu bar should be.
1028 gui_mch_compute_menu_height(menu
->id
);
1033 * Add mnemonic and accelerator text to a menu button.
1036 gui_motif_add_actext(menu
)
1041 /* Add accelerator text, if there is one */
1042 if (menu
->actext
!= NULL
&& menu
->id
!= (Widget
)0)
1044 label
= XmStringCreate((char *)menu
->actext
, STRING_TAG
);
1047 XtVaSetValues(menu
->id
, XmNacceleratorText
, label
, NULL
);
1048 XmStringFree(label
);
1053 gui_mch_toggle_tearoffs(enable
)
1056 #if (XmVersion >= 1002)
1058 tearoff_val
= (int)XmTEAR_OFF_ENABLED
;
1060 tearoff_val
= (int)XmTEAR_OFF_DISABLED
;
1061 toggle_tearoff(menuBar
);
1062 gui_mch_recurse_tearoffs(root_menu
);
1066 #if (XmVersion >= 1002)
1068 * Set the tearoff for one menu widget on or off, and set the color of the
1077 XtVaSetValues(wid
, XmNtearOffModel
, tearoff_val
, NULL
);
1078 if (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1079 && (w
= XmGetTearOffControl(wid
)) != (Widget
)0)
1080 gui_motif_menu_colors(w
);
1084 gui_mch_recurse_tearoffs(menu
)
1087 while (menu
!= NULL
)
1089 if (!menu_is_popup(menu
->name
))
1091 if (menu
->submenu_id
!= (Widget
)0)
1092 toggle_tearoff(menu
->submenu_id
);
1093 gui_mch_recurse_tearoffs(menu
->children
);
1101 gui_mch_text_area_extra_height()
1103 Dimension shadowHeight
;
1105 XtVaGetValues(textAreaForm
, XmNshadowThickness
, &shadowHeight
, NULL
);
1106 return shadowHeight
;
1110 * Compute the height of the menu bar.
1111 * We need to check all the items for their position and height, for the case
1112 * there are several rows, and/or some characters extend higher or lower.
1115 gui_mch_compute_menu_height(id
)
1116 Widget id
; /* can be NULL when deleting menu */
1119 Dimension margin
, shadow
;
1121 static Dimension height
= 21; /* normal height of a menu item */
1124 * Get the height of the new item, before managing it, because it will
1125 * still reflect the font size. After managing it depends on the menu
1126 * height, which is what we just wanted to get!.
1128 if (id
!= (Widget
)0)
1129 XtVaGetValues(id
, XmNheight
, &height
, NULL
);
1131 /* Find any menu Widget, to be able to call XtManageChild() */
1133 for (mp
= root_menu
; mp
!= NULL
; mp
= mp
->next
)
1134 if (mp
->id
!= (Widget
)0 && menu_is_menubar(mp
->name
))
1141 * Now manage the menu item, to make them all be positioned (makes an
1142 * extra row when needed, removes it when not needed).
1144 if (id
!= (Widget
)0)
1148 * Now find the menu item that is the furthest down, and get it's position.
1151 for (mp
= root_menu
; mp
!= NULL
; mp
= mp
->next
)
1153 if (mp
->id
!= (Widget
)0 && menu_is_menubar(mp
->name
))
1155 XtVaGetValues(mp
->id
, XmNy
, &y
, NULL
);
1161 XtVaGetValues(menuBar
,
1162 XmNmarginHeight
, &margin
,
1163 XmNshadowThickness
, &shadow
,
1167 * This computation is the result of trial-and-error:
1168 * maxy = The maximum position of an item; required for when there are
1170 * height = height of an item, before managing it; Hopefully this will
1171 * change with the font height. Includes shadow-border.
1172 * shadow = shadow-border; must be subtracted from the height.
1173 * margin = margin around the menu buttons; Must be added.
1174 * Add 4 for the underlining of shortcut keys.
1176 gui
.menu_height
= maxy
+ height
- 2 * shadow
+ 2 * margin
+ 4;
1178 /* Somehow the menu bar doesn't resize automatically. Set it here,
1179 * even though this is a catch 22. Don't do this when starting up,
1180 * somehow the menu gets very high then. */
1181 if (gui
.shell_created
)
1182 XtVaSetValues(menuBar
, XmNheight
, gui
.menu_height
, NULL
);
1188 * Icons used by the toolbar code.
1190 #include "gui_x11_pm.h"
1192 static int check_xpm
__ARGS((char_u
*path
));
1193 static char **get_toolbar_pixmap
__ARGS((vimmenu_T
*menu
, char **fname
));
1194 static int add_pixmap_args
__ARGS((vimmenu_T
*menu
, Arg
*args
, int n
));
1197 * Read an Xpm file. Return OK or FAIL.
1203 XpmAttributes attrs
;
1208 attrs
.valuemask
= 0;
1210 /* Create the "sensitive" pixmap */
1211 status
= XpmReadFileToPixmap(gui
.dpy
,
1212 RootWindow(gui
.dpy
, DefaultScreen(gui
.dpy
)),
1213 (char *)path
, &map
, &mask
, &attrs
);
1214 XpmFreeAttributes(&attrs
);
1216 if (status
== XpmSuccess
)
1223 * Allocated a pixmap for toolbar menu "menu".
1224 * When it's to be read from a file, "fname" is set to the file name
1225 * (in allocated memory).
1226 * Return a blank pixmap if it fails.
1229 get_toolbar_pixmap(menu
, fname
)
1233 char_u buf
[MAXPATHL
]; /* buffer storing expanded pathname */
1234 char **xpm
= NULL
; /* xpm array */
1238 buf
[0] = NUL
; /* start with NULL path */
1240 if (menu
->iconfile
!= NULL
)
1242 /* Use the "icon=" argument. */
1243 gui_find_iconfile(menu
->iconfile
, buf
, "xpm");
1244 res
= check_xpm(buf
);
1246 /* If it failed, try using the menu name. */
1247 if (res
== FAIL
&& gui_find_bitmap(menu
->name
, buf
, "xpm") == OK
)
1248 res
= check_xpm(buf
);
1251 *fname
= (char *)vim_strsave(buf
);
1252 return tb_blank_xpm
;
1256 if (menu
->icon_builtin
|| gui_find_bitmap(menu
->name
, buf
, "xpm") == FAIL
)
1258 if (menu
->iconidx
>= 0 && menu
->iconidx
1259 < (int)(sizeof(built_in_pixmaps
) / sizeof(built_in_pixmaps
[0])))
1260 xpm
= built_in_pixmaps
[menu
->iconidx
];
1269 * Add arguments for the toolbar pixmap to a menu item.
1272 add_pixmap_args(menu
, args
, n
)
1277 vim_free(menu
->xpm_fname
);
1278 menu
->xpm
= get_toolbar_pixmap(menu
, &menu
->xpm_fname
);
1279 if (menu
->xpm
== NULL
)
1281 XtSetArg(args
[n
], XmNlabelType
, XmSTRING
); n
++;
1285 if (menu
->xpm_fname
!= NULL
)
1287 XtSetArg(args
[n
], XmNpixmapFile
, menu
->xpm_fname
); n
++;
1289 XtSetArg(args
[n
], XmNpixmapData
, menu
->xpm
); n
++;
1290 XtSetArg(args
[n
], XmNlabelLocation
, XmBOTTOM
); n
++;
1294 #endif /* FEAT_TOOLBAR */
1297 gui_mch_add_menu_item(menu
, idx
)
1302 vimmenu_T
*parent
= menu
->parent
;
1308 # if (XmVersion <= 1002)
1309 /* Don't add Popup menu items when the popup menu isn't used. */
1310 if (menu_is_child_of_popup(menu
) && !mouse_model_popup())
1314 # ifdef FEAT_TOOLBAR
1315 if (menu_is_toolbar(parent
->name
))
1318 XmString xms
= NULL
; /* fallback label if pixmap not found */
1323 if (menu_is_separator(menu
->name
))
1329 * A separator has the format "-sep%d[:%d]-". The optional :%d is
1330 * a width specifier. If no width is specified then we choose one.
1332 cp
= (char *)vim_strchr(menu
->name
, ':');
1334 wid
= (Dimension
)atoi(++cp
);
1339 /* We better use a FormWidget here, since it's far more
1340 * flexible in terms of size. */
1341 type
= xmFormWidgetClass
;
1342 XtSetArg(args
[n
], XmNwidth
, wid
); n
++;
1344 type
= xmSeparatorWidgetClass
;
1345 XtSetArg(args
[n
], XmNwidth
, wid
); n
++;
1346 XtSetArg(args
[n
], XmNminWidth
, wid
); n
++;
1347 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
1348 XtSetArg(args
[n
], XmNseparatorType
, XmSHADOW_ETCHED_IN
); n
++;
1353 /* Without shadows one can't sense whatever the button has been
1354 * pressed or not! However we wan't to save a bit of space...
1355 * Need the highlightThickness to see the focus.
1357 XtSetArg(args
[n
], XmNhighlightThickness
, 1); n
++;
1358 XtSetArg(args
[n
], XmNhighlightOnEnter
, True
); n
++;
1359 XtSetArg(args
[n
], XmNmarginWidth
, 0); n
++;
1360 XtSetArg(args
[n
], XmNmarginHeight
, 0); n
++;
1361 XtSetArg(args
[n
], XmNtraversalOn
, False
); n
++;
1362 /* Set the label here, so that we can switch between icons/text
1363 * by changing the XmNlabelType resource. */
1364 xms
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
1365 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
1367 n
= add_pixmap_args(menu
, args
, n
);
1369 type
= xmEnhancedButtonWidgetClass
;
1372 XtSetArg(args
[n
], XmNpositionIndex
, idx
); n
++;
1373 if (menu
->id
== NULL
)
1375 menu
->id
= XtCreateManagedWidget((char *)menu
->dname
,
1376 type
, toolBar
, args
, n
);
1377 if (menu
->id
!= NULL
&& type
== xmEnhancedButtonWidgetClass
)
1379 XtAddCallback(menu
->id
,
1380 XmNactivateCallback
, gui_x11_menu_cb
, menu
);
1382 XtAddEventHandler(menu
->id
, EnterWindowMask
, False
,
1383 toolbarbutton_enter_cb
, menu
);
1384 XtAddEventHandler(menu
->id
, LeaveWindowMask
, False
,
1385 toolbarbutton_leave_cb
, menu
);
1390 XtSetValues(menu
->id
, args
, n
);
1395 gui_mch_menu_set_tip(menu
);
1398 menu
->parent
= parent
;
1399 menu
->submenu_id
= NULL
;
1400 /* When adding first item to toolbar it might have to be enabled .*/
1401 if (!XtIsManaged(XtParent(toolBar
))
1402 && vim_strchr(p_go
, GO_TOOLBAR
) != NULL
)
1403 gui_mch_show_toolbar(TRUE
);
1404 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
1406 } /* toolbar menu item */
1409 /* No parent, must be a non-menubar menu */
1410 if (parent
->submenu_id
== (Widget
)0)
1413 menu
->submenu_id
= (Widget
)0;
1415 /* Add menu separator */
1416 if (menu_is_separator(menu
->name
))
1418 menu
->id
= XtVaCreateWidget("subMenu",
1419 xmSeparatorGadgetClass
, parent
->submenu_id
,
1420 #if (XmVersion >= 1002)
1421 /* count the tearoff item (needed for LessTif) */
1422 XmNpositionIndex
, idx
+ (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1426 gui_motif_menu_colors(menu
->id
);
1430 label
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
1433 menu
->id
= XtVaCreateWidget("subMenu",
1434 xmPushButtonWidgetClass
, parent
->submenu_id
,
1435 XmNlabelString
, label
,
1436 XmNmnemonic
, menu
->mnemonic
,
1437 #if (XmVersion >= 1002)
1438 /* count the tearoff item (needed for LessTif) */
1439 XmNpositionIndex
, idx
+ (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1443 gui_motif_menu_colors(menu
->id
);
1444 gui_motif_menu_fontlist(menu
->id
);
1445 XmStringFree(label
);
1447 if (menu
->id
!= (Widget
)0)
1449 XtAddCallback(menu
->id
, XmNactivateCallback
, gui_x11_menu_cb
,
1451 /* add accelerator text */
1452 gui_motif_add_actext(menu
);
1456 #if (XmVersion <= 1002) || defined(PROTO)
1458 * This function will destroy/create the popup menus dynamically,
1459 * according to the value of 'mousemodel'.
1460 * This will fix the "right mouse button freeze" that occurs when
1461 * there exists a popup menu but it isn't managed.
1464 gui_motif_update_mousemodel(menu
)
1469 /* When GUI hasn't started the menus have not been created. */
1475 if (menu
->children
!= NULL
)
1477 if (menu_is_popup(menu
->name
))
1479 if (mouse_model_popup())
1481 /* Popup menu will be used. Create the popup menus. */
1482 gui_mch_add_menu(menu
, idx
);
1483 gui_motif_update_mousemodel(menu
->children
);
1487 /* Popup menu will not be used. Destroy the popup menus. */
1488 gui_motif_update_mousemodel(menu
->children
);
1489 gui_mch_destroy_menu(menu
);
1493 else if (menu_is_child_of_popup(menu
))
1495 if (mouse_model_popup())
1496 gui_mch_add_menu_item(menu
, idx
);
1498 gui_mch_destroy_menu(menu
);
1507 gui_mch_new_menu_colors()
1509 if (menuBar
== (Widget
)0)
1511 gui_motif_menu_colors(menuBar
);
1513 gui_motif_menu_colors(toolBarFrame
);
1514 gui_motif_menu_colors(toolBar
);
1517 submenu_change(root_menu
, TRUE
);
1521 gui_mch_new_menu_font()
1523 if (menuBar
== (Widget
)0)
1525 submenu_change(root_menu
, FALSE
);
1530 XtVaGetValues(menuBar
, XmNheight
, &height
, NULL
);
1531 gui
.menu_height
= height
;
1533 XtVaGetValues(vimShell
, XtNwidth
, &w
, XtNheight
, &h
, NULL
);
1534 gui_resize_shell(w
, h
1536 - xim_get_status_area_height()
1540 gui_set_shellsize(FALSE
, TRUE
, RESIZE_VERT
);
1544 #if defined(FEAT_BEVAL) || defined(PROTO)
1546 gui_mch_new_tooltip_font()
1548 # ifdef FEAT_TOOLBAR
1551 if (toolBar
== (Widget
)0)
1554 menu
= gui_find_menu((char_u
*)"ToolBar");
1556 submenu_change(menu
, FALSE
);
1561 gui_mch_new_tooltip_colors()
1563 # ifdef FEAT_TOOLBAR
1566 if (toolBar
== (Widget
)0)
1569 toolbar
= gui_find_menu((char_u
*)"ToolBar");
1570 if (toolbar
!= NULL
)
1571 submenu_change(toolbar
, TRUE
);
1577 submenu_change(menu
, colors
)
1579 int colors
; /* TRUE for colors, FALSE for font */
1583 for (mp
= menu
; mp
!= NULL
; mp
= mp
->next
)
1585 if (mp
->id
!= (Widget
)0)
1589 gui_motif_menu_colors(mp
->id
);
1591 /* For a toolbar item: Free the pixmap and allocate a new one,
1592 * so that the background color is right. */
1593 if (mp
->xpm
!= NULL
)
1598 n
= add_pixmap_args(mp
, args
, n
);
1599 XtSetValues(mp
->id
, args
, n
);
1602 /* If we have a tooltip, then we need to change it's font */
1603 if (mp
->tip
!= NULL
)
1607 args
[0].name
= XmNbackground
;
1608 args
[0].value
= gui
.tooltip_bg_pixel
;
1609 args
[1].name
= XmNforeground
;
1610 args
[1].value
= gui
.tooltip_fg_pixel
;
1611 XtSetValues(mp
->tip
->balloonLabel
, &args
[0], XtNumber(args
));
1618 gui_motif_menu_fontlist(mp
->id
);
1620 /* If we have a tooltip, then we need to change it's font */
1621 if (mp
->tip
!= NULL
)
1625 args
[0].name
= XmNfontList
;
1626 args
[0].value
= (XtArgVal
)gui_motif_fontset2fontlist(
1627 &gui
.tooltip_fontset
);
1628 XtSetValues(mp
->tip
->balloonLabel
, &args
[0], XtNumber(args
));
1634 if (mp
->children
!= NULL
)
1636 #if (XmVersion >= 1002)
1637 /* Set the colors/font for the tear off widget */
1638 if (mp
->submenu_id
!= (Widget
)0)
1641 gui_motif_menu_colors(mp
->submenu_id
);
1643 gui_motif_menu_fontlist(mp
->submenu_id
);
1644 toggle_tearoff(mp
->submenu_id
);
1647 /* Set the colors for the children */
1648 submenu_change(mp
->children
, colors
);
1654 * Destroy the machine specific menu widget.
1657 gui_mch_destroy_menu(menu
)
1660 /* Please be sure to destroy the parent widget first (i.e. menu->id).
1661 * On the other hand, problems have been reported that the submenu must be
1664 * This code should be basically identical to that in the file gui_athena.c
1665 * because they are both Xt based.
1667 if (menu
->submenu_id
!= (Widget
)0)
1669 XtDestroyWidget(menu
->submenu_id
);
1670 menu
->submenu_id
= (Widget
)0;
1673 if (menu
->id
!= (Widget
)0)
1677 parent
= XtParent(menu
->id
);
1678 #if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL)
1679 if (parent
== toolBar
&& menu
->tip
!= NULL
)
1681 /* We try to destroy this before the actual menu, because there are
1682 * callbacks, etc. that will be unregistered during the tooltip
1685 * If you call "gui_mch_destroy_beval_area()" after destroying
1686 * menu->id, then the tooltip's window will have already been
1687 * deallocated by Xt, and unknown behaviour will ensue (probably
1690 gui_mch_destroy_beval_area(menu
->tip
);
1694 XtDestroyWidget(menu
->id
);
1695 menu
->id
= (Widget
)0;
1696 if (parent
== menuBar
)
1697 gui_mch_compute_menu_height((Widget
)0);
1699 else if (parent
== toolBar
)
1701 Cardinal num_children
;
1703 /* When removing last toolbar item, don't display the toolbar. */
1704 XtVaGetValues(toolBar
, XmNnumChildren
, &num_children
, NULL
);
1705 if (num_children
== 0)
1706 gui_mch_show_toolbar(FALSE
);
1708 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
1715 gui_mch_show_popupmenu(menu
)
1716 vimmenu_T
*menu UNUSED
;
1719 XmMenuPosition(menu
->submenu_id
, gui_x11_get_last_mouse_event());
1720 XtManageChild(menu
->submenu_id
);
1724 #endif /* FEAT_MENU */
1727 * Set the menu and scrollbar colors to their default values.
1730 gui_mch_def_colors()
1734 /* Use the values saved when starting up. These should come from the
1735 * window manager or a resources file. */
1736 gui
.menu_fg_pixel
= gui
.menu_def_fg_pixel
;
1737 gui
.menu_bg_pixel
= gui
.menu_def_bg_pixel
;
1738 gui
.scroll_fg_pixel
= gui
.scroll_def_fg_pixel
;
1739 gui
.scroll_bg_pixel
= gui
.scroll_def_bg_pixel
;
1741 gui
.tooltip_fg_pixel
=
1742 gui_get_color((char_u
*)gui
.rsrc_tooltip_fg_name
);
1743 gui
.tooltip_bg_pixel
=
1744 gui_get_color((char_u
*)gui
.rsrc_tooltip_bg_name
);
1755 gui_mch_set_scrollbar_thumb(sb
, val
, size
, max
)
1761 if (sb
->id
!= (Widget
)0)
1762 XtVaSetValues(sb
->id
,
1764 XmNsliderSize
, size
,
1765 XmNpageIncrement
, (size
> 2 ? size
- 2 : 1),
1766 XmNmaximum
, max
+ 1, /* Motif has max one past the end */
1771 gui_mch_set_scrollbar_pos(sb
, x
, y
, w
, h
)
1778 if (sb
->id
!= (Widget
)0)
1780 if (sb
->type
== SBAR_LEFT
|| sb
->type
== SBAR_RIGHT
)
1783 h
-= gui
.border_offset
;
1785 y
-= gui
.border_offset
;
1786 XtVaSetValues(sb
->id
,
1788 XmNbottomOffset
, -y
- h
,
1793 XtVaSetValues(sb
->id
,
1796 XmNrightOffset
, gui
.which_scrollbars
[SBAR_RIGHT
]
1797 ? gui
.scrollbar_width
: 0,
1800 XtManageChild(sb
->id
);
1805 gui_mch_enable_scrollbar(sb
, flag
)
1812 if (sb
->id
!= (Widget
)0)
1820 XtSetArg(args
[n
], XmNleftOffset
, gui
.scrollbar_width
); n
++;
1824 XtSetArg(args
[n
], XmNrightOffset
, gui
.scrollbar_width
); n
++;
1828 XtSetArg(args
[n
], XmNbottomOffset
, gui
.scrollbar_height
);n
++;
1831 XtSetValues(textArea
, args
, n
);
1832 XtManageChild(sb
->id
);
1836 if (!gui
.which_scrollbars
[sb
->type
])
1838 /* The scrollbars of this type are all disabled, adjust the
1839 * textArea attachment offset. */
1843 XtSetArg(args
[n
], XmNleftOffset
, 0); n
++;
1847 XtSetArg(args
[n
], XmNrightOffset
, 0); n
++;
1851 XtSetArg(args
[n
], XmNbottomOffset
, 0);n
++;
1854 XtSetValues(textArea
, args
, n
);
1856 XtUnmanageChild(sb
->id
);
1862 gui_mch_create_scrollbar(sb
, orient
)
1864 int orient
; /* SBAR_VERT or SBAR_HORIZ */
1870 XtSetArg(args
[n
], XmNminimum
, 0); n
++;
1871 XtSetArg(args
[n
], XmNorientation
,
1872 (orient
== SBAR_VERT
) ? XmVERTICAL
: XmHORIZONTAL
); n
++;
1877 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
1878 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_OPPOSITE_FORM
); n
++;
1879 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
1883 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
1884 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_OPPOSITE_FORM
); n
++;
1885 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
1889 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
1890 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
1891 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
1895 sb
->id
= XtCreateWidget("scrollBar",
1896 xmScrollBarWidgetClass
, textAreaForm
, args
, n
);
1898 /* Remember the default colors, needed for ":hi clear". */
1899 if (gui
.scroll_def_bg_pixel
== (guicolor_T
)0
1900 && gui
.scroll_def_fg_pixel
== (guicolor_T
)0)
1901 XtVaGetValues(sb
->id
,
1902 XmNbackground
, &gui
.scroll_def_bg_pixel
,
1903 XmNforeground
, &gui
.scroll_def_fg_pixel
,
1906 if (sb
->id
!= (Widget
)0)
1908 gui_mch_set_scrollbar_colors(sb
);
1909 XtAddCallback(sb
->id
, XmNvalueChangedCallback
,
1910 scroll_cb
, (XtPointer
)sb
->ident
);
1911 XtAddCallback(sb
->id
, XmNdragCallback
,
1912 scroll_cb
, (XtPointer
)sb
->ident
);
1913 XtAddEventHandler(sb
->id
, KeyPressMask
, FALSE
, gui_x11_key_hit_cb
,
1918 #if defined(FEAT_WINDOWS) || defined(PROTO)
1920 gui_mch_destroy_scrollbar(sb
)
1923 if (sb
->id
!= (Widget
)0)
1924 XtDestroyWidget(sb
->id
);
1929 gui_mch_set_scrollbar_colors(sb
)
1932 if (sb
->id
!= (Widget
)0)
1934 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
1936 #if (XmVersion>=1002)
1937 XmChangeColor(sb
->id
, gui
.scroll_bg_pixel
);
1939 XtVaSetValues(sb
->id
,
1940 XmNtroughColor
, gui
.scroll_bg_pixel
,
1945 if (gui
.scroll_fg_pixel
!= INVALCOLOR
)
1946 XtVaSetValues(sb
->id
,
1947 XmNforeground
, gui
.scroll_fg_pixel
,
1948 #if (XmVersion<1002)
1949 XmNbackground
, gui
.scroll_fg_pixel
,
1954 /* This is needed for the rectangle below the vertical scrollbars. */
1955 if (sb
== &gui
.bottom_sbar
&& textAreaForm
!= (Widget
)0)
1956 gui_motif_scroll_colors(textAreaForm
);
1960 * Miscellaneous stuff:
1966 return(XtWindow(textArea
));
1970 * Look for a widget in the widget tree w, with a mnemonic matching keycode.
1971 * When one is found, simulate a button press on that widget and give it the
1972 * keyboard focus. If the mnemonic is on a label, look in the userData field
1973 * of the label to see if it points to another widget, and give that the focus.
1976 do_mnemonic(Widget w
, unsigned int keycode
)
1978 WidgetList children
;
1981 KeySym mnemonic
= '\0';
1984 unsigned char rowColType
;
1986 if (XtIsComposite(w
))
1988 if (XtClass(w
) == xmRowColumnWidgetClass
)
1990 XtVaGetValues(w
, XmNrowColumnType
, &rowColType
, NULL
);
1991 isMenu
= (rowColType
!= (unsigned char)XmWORK_AREA
);
1997 XtVaGetValues(w
, XmNchildren
, &children
, XmNnumChildren
,
1998 &numChildren
, NULL
);
1999 for (i
= 0; i
< numChildren
; i
++)
2000 do_mnemonic(children
[i
], keycode
);
2005 XtVaGetValues(w
, XmNmnemonic
, &mnemonic
, NULL
);
2006 if (mnemonic
!= '\0')
2008 mneString
[0] = mnemonic
;
2009 mneString
[1] = '\0';
2010 if (XKeysymToKeycode(XtDisplay(XtParent(w
)),
2011 XStringToKeysym(mneString
)) == keycode
)
2013 if (XtClass(w
) == xmLabelWidgetClass
2014 || XtClass(w
) == xmLabelGadgetClass
)
2016 XtVaGetValues(w
, XmNuserData
, &userData
, NULL
);
2017 if (userData
!= NULL
&& XtIsWidget(userData
))
2018 XmProcessTraversal(userData
, XmTRAVERSE_CURRENT
);
2022 XKeyPressedEvent keyEvent
;
2024 XmProcessTraversal(w
, XmTRAVERSE_CURRENT
);
2026 memset((char *) &keyEvent
, 0, sizeof(XKeyPressedEvent
));
2027 keyEvent
.type
= KeyPress
;
2028 keyEvent
.serial
= 1;
2029 keyEvent
.send_event
= True
;
2030 keyEvent
.display
= XtDisplay(w
);
2031 keyEvent
.window
= XtWindow(w
);
2032 XtCallActionProc(w
, "Activate", (XEvent
*) & keyEvent
,
2041 * Callback routine for dialog mnemonic processing.
2044 mnemonic_event(Widget w
, XtPointer call_data UNUSED
, XKeyEvent
*event
)
2046 do_mnemonic(w
, event
->keycode
);
2051 * Search the widget tree under w for widgets with mnemonics. When found, add
2052 * a passive grab to the dialog widget for the mnemonic character, thus
2053 * directing mnemonic events to the dialog widget.
2056 add_mnemonic_grabs(Widget dialog
, Widget w
)
2059 WidgetList children
;
2062 KeySym mnemonic
= '\0';
2063 unsigned char rowColType
;
2065 if (XtIsComposite(w
))
2067 if (XtClass(w
) == xmRowColumnWidgetClass
)
2069 XtVaGetValues(w
, XmNrowColumnType
, &rowColType
, NULL
);
2070 isMenu
= (rowColType
!= (unsigned char)XmWORK_AREA
);
2076 XtVaGetValues(w
, XmNchildren
, &children
, XmNnumChildren
,
2077 &numChildren
, NULL
);
2078 for (i
= 0; i
< numChildren
; i
++)
2079 add_mnemonic_grabs(dialog
, children
[i
]);
2084 XtVaGetValues(w
, XmNmnemonic
, &mnemonic
, NULL
);
2085 if (mnemonic
!= '\0')
2087 mneString
[0] = mnemonic
;
2088 mneString
[1] = '\0';
2089 XtGrabKey(dialog
, XKeysymToKeycode(XtDisplay(dialog
),
2090 XStringToKeysym(mneString
)),
2091 Mod1Mask
, True
, GrabModeAsync
, GrabModeAsync
);
2097 * Add a handler for mnemonics in a dialog. Motif itself only handles
2098 * mnemonics in menus. Mnemonics added or changed after this call will be
2101 * To add a mnemonic to a text field or list, set the XmNmnemonic resource on
2102 * the appropriate label and set the XmNuserData resource of the label to the
2103 * widget to get the focus when the mnemonic is typed.
2106 activate_dialog_mnemonics(Widget dialog
)
2111 XtAddEventHandler(dialog
, KeyPressMask
, False
,
2112 (XtEventHandler
) mnemonic_event
, (XtPointer
) NULL
);
2113 add_mnemonic_grabs(dialog
, dialog
);
2117 * Removes the event handler and key-grabs for dialog mnemonic handling.
2120 suppress_dialog_mnemonics(Widget dialog
)
2125 XtUngrabKey(dialog
, AnyKey
, Mod1Mask
);
2126 XtRemoveEventHandler(dialog
, KeyPressMask
, False
,
2127 (XtEventHandler
) mnemonic_event
, (XtPointer
) NULL
);
2130 #if defined(FEAT_BROWSE) || defined(FEAT_GUI_DIALOG)
2131 static void set_fontlist
__ARGS((Widget wg
));
2134 * Use the 'guifont' or 'guifontset' as a fontlist for a dialog widget.
2142 #ifdef FONTSET_ALWAYS
2143 if (gui
.fontset
!= NOFONTSET
)
2145 fl
= gui_motif_fontset2fontlist((XFontSet
*)&gui
.fontset
);
2148 if (XtIsManaged(id
))
2150 XtUnmanageChild(id
);
2151 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2152 /* We should force the widget to recalculate it's
2157 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2162 if (gui
.norm_font
!= NOFONT
)
2164 fl
= gui_motif_create_fontlist((XFontStruct
*)gui
.norm_font
);
2167 if (XtIsManaged(id
))
2169 XtUnmanageChild(id
);
2170 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2171 /* We should force the widget to recalculate it's
2176 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2184 #if defined(FEAT_BROWSE) || defined(PROTO)
2187 * file selector related stuff
2190 #include <Xm/FileSB.h>
2191 #include <Xm/XmStrDefs.h>
2193 typedef struct dialog_callback_arg
2195 char * args
; /* not used right now */
2199 static Widget dialog_wgt
;
2200 static char *browse_fname
= NULL
;
2201 static XmStringCharSet charset
= (XmStringCharSet
) XmSTRING_DEFAULT_CHARSET
;
2202 /* used to set up XmStrings */
2204 static void DialogCancelCB
__ARGS((Widget
, XtPointer
, XtPointer
));
2205 static void DialogAcceptCB
__ARGS((Widget
, XtPointer
, XtPointer
));
2208 * This function is used to translate the predefined label text of the
2209 * precomposed dialogs. We do this explicitly to allow:
2211 * - usage of gettext for translation, as in all the other places.
2213 * - equalize the messages between different GUI implementations as far as
2216 static void set_predefined_label
__ARGS((Widget parent
, String name
, char *new_label
));
2219 set_predefined_label(parent
, name
, new_label
)
2227 KeySym mnemonic
= NUL
;
2229 w
= XtNameToWidget(parent
, name
);
2234 p
= vim_strsave((char_u
*)new_label
);
2237 for (next
= p
; *next
; ++next
)
2239 if (*next
== DLG_HOTKEY_CHAR
)
2241 int len
= STRLEN(next
);
2245 mch_memmove(next
, next
+ 1, len
);
2251 str
= XmStringCreate((char *)p
, STRING_TAG
);
2257 XmNlabelString
, str
,
2258 XmNmnemonic
, mnemonic
,
2262 gui_motif_menu_fontlist(w
);
2266 set_predefined_fontlist(parent
, name
)
2271 w
= XtNameToWidget(parent
, name
);
2280 * Put up a file requester.
2281 * Returns the selected name in allocated memory, or NULL for Cancel.
2284 gui_mch_browse(saving
, title
, dflt
, ext
, initdir
, filter
)
2285 int saving UNUSED
; /* select file to write */
2286 char_u
*title
; /* title for the window */
2287 char_u
*dflt
; /* default name */
2288 char_u
*ext UNUSED
; /* not used (extension added) */
2289 char_u
*initdir
; /* initial directory, NULL for current dir */
2290 char_u
*filter
; /* file name filter */
2292 char_u dirbuf
[MAXPATHL
];
2293 char_u dfltbuf
[MAXPATHL
];
2295 char_u
*tofree
= NULL
;
2297 /* There a difference between the resource name and value, Therefore, we
2298 * avoid to (ab-)use the (maybe internationalized!) dialog title as a
2302 dialog_wgt
= XmCreateFileSelectionDialog(vimShell
, "browseDialog", NULL
, 0);
2304 if (initdir
== NULL
|| *initdir
== NUL
)
2306 mch_dirname(dirbuf
, MAXPATHL
);
2311 dflt
= (char_u
*)"";
2312 else if (STRLEN(initdir
) + STRLEN(dflt
) + 2 < MAXPATHL
)
2314 /* The default selection should be the full path, "dflt" is only the
2316 STRCPY(dfltbuf
, initdir
);
2317 add_pathsep(dfltbuf
);
2318 STRCAT(dfltbuf
, dflt
);
2322 /* Can only use one pattern for a file name. Get the first pattern out of
2323 * the filter. An empty pattern means everything matches. */
2325 pattern
= (char_u
*)"";
2331 for (p
= filter
; *p
!= NUL
; ++p
)
2333 if (*p
== '\t') /* end of description, start of pattern */
2335 if (*p
== ';' || *p
== '\n') /* end of (first) pattern */
2338 pattern
= vim_strnsave(s
, p
- s
);
2340 if (pattern
== NULL
)
2341 pattern
= (char_u
*)"";
2344 XtVaSetValues(dialog_wgt
,
2346 XmNdirectory
, XmRString
, (char *)initdir
, STRLEN(initdir
) + 1,
2348 XmNdirSpec
, XmRString
, (char *)dflt
, STRLEN(dflt
) + 1,
2350 XmNpattern
, XmRString
, (char *)pattern
, STRLEN(pattern
) + 1,
2352 XmNdialogTitle
, XmRString
, (char *)title
, STRLEN(title
) + 1,
2355 set_predefined_label(dialog_wgt
, "Apply", _("&Filter"));
2356 set_predefined_label(dialog_wgt
, "Cancel", _("&Cancel"));
2357 set_predefined_label(dialog_wgt
, "Dir", _("Directories"));
2358 set_predefined_label(dialog_wgt
, "FilterLabel", _("Filter"));
2359 set_predefined_label(dialog_wgt
, "Help", _("&Help"));
2360 set_predefined_label(dialog_wgt
, "Items", _("Files"));
2361 set_predefined_label(dialog_wgt
, "OK", _("&OK"));
2362 set_predefined_label(dialog_wgt
, "Selection", _("Selection"));
2364 /* This is to save us from silly external settings using not fixed with
2365 * fonts for file selection.
2367 set_predefined_fontlist(dialog_wgt
, "DirListSW.DirList");
2368 set_predefined_fontlist(dialog_wgt
, "ItemsListSW.ItemsList");
2370 gui_motif_menu_colors(dialog_wgt
);
2371 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
2372 XtVaSetValues(dialog_wgt
, XmNtroughColor
, gui
.scroll_bg_pixel
, NULL
);
2374 XtAddCallback(dialog_wgt
, XmNokCallback
, DialogAcceptCB
, (XtPointer
)0);
2375 XtAddCallback(dialog_wgt
, XmNcancelCallback
, DialogCancelCB
, (XtPointer
)0);
2376 /* We have no help in this window, so hide help button */
2377 XtUnmanageChild(XmFileSelectionBoxGetChild(dialog_wgt
,
2378 (unsigned char)XmDIALOG_HELP_BUTTON
));
2380 manage_centered(dialog_wgt
);
2381 activate_dialog_mnemonics(dialog_wgt
);
2383 /* sit in a loop until the dialog box has gone away */
2386 XtAppProcessEvent(XtWidgetToApplicationContext(dialog_wgt
),
2387 (XtInputMask
)XtIMAll
);
2388 } while (XtIsManaged(dialog_wgt
));
2390 suppress_dialog_mnemonics(dialog_wgt
);
2391 XtDestroyWidget(dialog_wgt
);
2394 if (browse_fname
== NULL
)
2396 return vim_strsave((char_u
*)browse_fname
);
2400 * The code below was originally taken from
2401 * /usr/examples/motif/xmsamplers/xmeditor.c
2402 * on Digital Unix 4.0d, but heavily modified.
2406 * Process callback from Dialog cancel actions.
2409 DialogCancelCB(w
, client_data
, call_data
)
2410 Widget w UNUSED
; /* widget id */
2411 XtPointer client_data UNUSED
; /* data from application */
2412 XtPointer call_data UNUSED
; /* data from widget class */
2414 if (browse_fname
!= NULL
)
2416 XtFree(browse_fname
);
2417 browse_fname
= NULL
;
2419 XtUnmanageChild(dialog_wgt
);
2423 * Process callback from Dialog actions.
2426 DialogAcceptCB(w
, client_data
, call_data
)
2427 Widget w UNUSED
; /* widget id */
2428 XtPointer client_data UNUSED
; /* data from application */
2429 XtPointer call_data
; /* data from widget class */
2431 XmFileSelectionBoxCallbackStruct
*fcb
;
2433 if (browse_fname
!= NULL
)
2435 XtFree(browse_fname
);
2436 browse_fname
= NULL
;
2438 fcb
= (XmFileSelectionBoxCallbackStruct
*)call_data
;
2440 /* get the filename from the file selection box */
2441 XmStringGetLtoR(fcb
->value
, charset
, &browse_fname
);
2443 /* popdown the file selection box */
2444 XtUnmanageChild(dialog_wgt
);
2447 #endif /* FEAT_BROWSE */
2449 #if defined(FEAT_GUI_DIALOG) || defined(PROTO)
2451 static int dialogStatus
;
2453 static void keyhit_callback
__ARGS((Widget w
, XtPointer client_data
, XEvent
*event
, Boolean
*cont
));
2454 static void butproc
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
2457 * Callback function for the textfield. When CR is hit this works like
2458 * hitting the "OK" button, ESC like "Cancel".
2461 keyhit_callback(w
, client_data
, event
, cont
)
2463 XtPointer client_data UNUSED
;
2465 Boolean
*cont UNUSED
;
2470 if (XLookupString(&(event
->xkey
), buf
, 2, &key_sym
, NULL
) == 1)
2474 else if (*buf
== ESC
)
2477 if ((key_sym
== XK_Left
|| key_sym
== XK_Right
)
2478 && !(event
->xkey
.state
& ShiftMask
))
2479 XmTextFieldClearSelection(w
, XtLastTimestampProcessed(gui
.dpy
));
2483 butproc(w
, client_data
, call_data
)
2485 XtPointer client_data
;
2486 XtPointer call_data UNUSED
;
2488 dialogStatus
= (int)(long)client_data
+ 1;
2493 static Widget
create_pixmap_label(Widget parent
, String name
, char **data
, ArgList args
, Cardinal arg
);
2496 create_pixmap_label(parent
, name
, data
, args
, arg
)
2510 XpmColorSymbol color
[5] =
2513 {"iconColor1", NULL
, 0},
2514 {"bottomShadowColor", NULL
, 0},
2515 {"topShadowColor", NULL
, 0},
2516 {"selectColor", NULL
, 0}
2519 label
= XmCreateLabelGadget(parent
, name
, args
, arg
);
2522 * We need to be careful here, since in case of gadgets, there is
2523 * no way to get the background color directly from the widget itself.
2524 * In such cases we get it from The Core part of his parent instead.
2526 dsp
= XtDisplayOfObject(label
);
2527 scr
= XtScreenOfObject(label
);
2528 XtVaGetValues(XtIsSubclass(label
, coreWidgetClass
)
2529 ? label
: XtParent(label
),
2531 XmNbackground
, &color
[0].pixel
,
2532 XmNforeground
, &color
[1].pixel
,
2533 XmNbottomShadowColor
, &color
[2].pixel
,
2534 XmNtopShadowColor
, &color
[3].pixel
,
2535 XmNhighlight
, &color
[4].pixel
,
2538 attr
.valuemask
= XpmColorSymbols
| XpmCloseness
| XpmDepth
;
2539 attr
.colorsymbols
= color
;
2540 attr
.numsymbols
= 5;
2541 attr
.closeness
= 65535;
2543 XpmCreatePixmapFromData(dsp
, RootWindowOfScreen(scr
),
2544 data
, &pixmap
, NULL
, &attr
);
2546 XtVaGetValues(label
, XmNrecomputeSize
, &rs
, NULL
);
2547 XtVaSetValues(label
, XmNrecomputeSize
, True
, NULL
);
2548 XtVaSetValues(label
,
2549 XmNlabelType
, XmPIXMAP
,
2550 XmNlabelPixmap
, pixmap
,
2552 XtVaSetValues(label
, XmNrecomputeSize
, rs
, NULL
);
2559 gui_mch_dialog(type
, title
, message
, button_names
, dfltbutton
, textfield
)
2563 char_u
*button_names
;
2565 char_u
*textfield
; /* buffer of size IOSIZE */
2573 Widget dialogform
= NULL
;
2575 Widget dialogtextfield
= NULL
;
2577 Widget sep_form
= NULL
;
2579 Widget separator
= NULL
;
2583 char **icon_data
= NULL
;
2584 Widget dialogpixmap
= NULL
;
2588 title
= (char_u
*)_("Vim dialog");
2590 /* if our pointer is currently hidden, then we should show it. */
2591 gui_mch_mousehide(FALSE
);
2593 dialogform
= XmCreateFormDialog(vimShell
, (char *)"dialog", NULL
, 0);
2595 /* Check 'v' flag in 'guioptions': vertical button placement. */
2596 vertical
= (vim_strchr(p_go
, GO_VERTICAL
) != NULL
);
2598 /* Set the title of the Dialog window */
2599 label
= XmStringCreateSimple((char *)title
);
2602 XtVaSetValues(dialogform
,
2603 XmNdialogTitle
, label
,
2604 XmNhorizontalSpacing
, 4,
2605 XmNverticalSpacing
, vertical
? 0 : 4,
2607 XmStringFree(label
);
2609 /* make a copy, so that we can insert NULs */
2610 buts
= vim_strsave(button_names
);
2614 /* Count the number of buttons and allocate buttons[]. */
2616 for (p
= buts
; *p
; ++p
)
2617 if (*p
== DLG_BUTTON_SEP
)
2619 buttons
= (Widget
*)alloc((unsigned)(butcount
* sizeof(Widget
)));
2620 if (buttons
== NULL
)
2627 * Create the buttons.
2629 sep_form
= (Widget
) 0;
2631 for (butcount
= 0; *p
; ++butcount
)
2633 KeySym mnemonic
= NUL
;
2635 for (next
= p
; *next
; ++next
)
2637 if (*next
== DLG_HOTKEY_CHAR
)
2639 int len
= STRLEN(next
);
2643 mch_memmove(next
, next
+ 1, len
);
2647 if (*next
== DLG_BUTTON_SEP
)
2653 label
= XmStringCreate(_((char *)p
), STRING_TAG
);
2657 buttons
[butcount
] = XtVaCreateManagedWidget("button",
2658 xmPushButtonWidgetClass
, dialogform
,
2659 XmNlabelString
, label
,
2660 XmNmnemonic
, mnemonic
,
2661 XmNbottomAttachment
, XmATTACH_FORM
,
2663 XmNshowAsDefault
, butcount
== dfltbutton
- 1,
2664 XmNdefaultButtonShadowThickness
, 1,
2666 XmStringFree(label
);
2667 gui_motif_menu_fontlist(buttons
[butcount
]);
2669 /* Layout properly. */
2674 XtVaSetValues(buttons
[butcount
],
2675 XmNtopWidget
, buttons
[butcount
- 1],
2681 XtVaSetValues(buttons
[butcount
],
2682 XmNrightAttachment
, XmATTACH_FORM
,
2686 /* fill in a form as invisible separator */
2687 sep_form
= XtVaCreateWidget("separatorForm",
2688 xmFormWidgetClass
, dialogform
,
2689 XmNleftAttachment
, XmATTACH_WIDGET
,
2690 XmNleftWidget
, buttons
[butcount
- 1],
2691 XmNrightAttachment
, XmATTACH_WIDGET
,
2692 XmNrightWidget
, buttons
[butcount
],
2693 XmNbottomAttachment
, XmATTACH_FORM
,
2696 XtManageChild(sep_form
);
2700 XtVaSetValues(buttons
[butcount
],
2701 XmNleftAttachment
, XmATTACH_WIDGET
,
2702 XmNleftWidget
, buttons
[butcount
- 1],
2711 XtVaSetValues(buttons
[0],
2712 XmNrightAttachment
, XmATTACH_FORM
,
2716 /* fill in a form as invisible separator */
2717 sep_form
= XtVaCreateWidget("separatorForm",
2718 xmFormWidgetClass
, dialogform
,
2719 XmNleftAttachment
, XmATTACH_FORM
,
2721 XmNrightAttachment
, XmATTACH_WIDGET
,
2722 XmNrightWidget
, buttons
[0],
2723 XmNbottomAttachment
, XmATTACH_FORM
,
2726 XtManageChild(sep_form
);
2729 XtVaSetValues(buttons
[0],
2730 XmNleftAttachment
, XmATTACH_FORM
,
2735 XtAddCallback(buttons
[butcount
], XmNactivateCallback
,
2736 (XtCallbackProc
)butproc
, (XtPointer
)(long)butcount
);
2741 separator
= (Widget
) 0;
2744 /* Create the separator for beauty. */
2746 XtSetArg(args
[n
], XmNorientation
, XmHORIZONTAL
); n
++;
2747 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_WIDGET
); n
++;
2748 XtSetArg(args
[n
], XmNbottomWidget
, buttons
[0]); n
++;
2749 XtSetArg(args
[n
], XmNbottomOffset
, 4); n
++;
2750 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
2751 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
2752 separator
= XmCreateSeparatorGadget(dialogform
, "separator", args
, n
);
2753 XtManageChild(separator
);
2756 if (textfield
!= NULL
)
2758 dialogtextfield
= XtVaCreateWidget("textField",
2759 xmTextFieldWidgetClass
, dialogform
,
2760 XmNleftAttachment
, XmATTACH_FORM
,
2761 XmNrightAttachment
, XmATTACH_FORM
,
2764 XtVaSetValues(dialogtextfield
,
2765 XmNbottomAttachment
, XmATTACH_WIDGET
,
2766 XmNbottomWidget
, separator
,
2769 XtVaSetValues(dialogtextfield
,
2770 XmNbottomAttachment
, XmATTACH_FORM
,
2773 set_fontlist(dialogtextfield
);
2774 XmTextFieldSetString(dialogtextfield
, (char *)textfield
);
2775 XtManageChild(dialogtextfield
);
2776 XtAddEventHandler(dialogtextfield
, KeyPressMask
, False
,
2777 (XtEventHandler
)keyhit_callback
, (XtPointer
)NULL
);
2780 /* Form holding both message and pixmap labels */
2781 form
= XtVaCreateWidget("separatorForm",
2782 xmFormWidgetClass
, dialogform
,
2783 XmNleftAttachment
, XmATTACH_FORM
,
2784 XmNrightAttachment
, XmATTACH_FORM
,
2785 XmNtopAttachment
, XmATTACH_FORM
,
2787 XtManageChild(form
);
2790 /* Add a pixmap, left of the message. */
2794 icon_data
= generic_xpm
;
2797 icon_data
= error_xpm
;
2800 icon_data
= alert_xpm
;
2803 icon_data
= info_xpm
;
2806 icon_data
= quest_xpm
;
2809 icon_data
= generic_xpm
;
2813 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
2814 XtSetArg(args
[n
], XmNtopOffset
, 8); n
++;
2815 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
2816 XtSetArg(args
[n
], XmNbottomOffset
, 8); n
++;
2817 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
2818 XtSetArg(args
[n
], XmNleftOffset
, 8); n
++;
2820 dialogpixmap
= create_pixmap_label(form
, "dialogPixmap",
2821 icon_data
, args
, n
);
2822 XtManageChild(dialogpixmap
);
2825 /* Create the dialog message.
2826 * Since LessTif is apparently having problems with the creation of
2827 * properly localized string, we use LtoR here. The symptom is that the
2828 * string sill not show properly in multiple lines as it does in native
2831 label
= XmStringCreateLtoR((char *)message
, STRING_TAG
);
2834 w
= XtVaCreateManagedWidget("dialogMessage",
2835 xmLabelGadgetClass
, form
,
2836 XmNlabelString
, label
,
2837 XmNalignment
, XmALIGNMENT_BEGINNING
,
2838 XmNtopAttachment
, XmATTACH_FORM
,
2841 XmNleftAttachment
, XmATTACH_WIDGET
,
2842 XmNleftWidget
, dialogpixmap
,
2844 XmNleftAttachment
, XmATTACH_FORM
,
2847 XmNrightAttachment
, XmATTACH_FORM
,
2849 XmNbottomAttachment
, XmATTACH_FORM
,
2852 XmStringFree(label
);
2855 if (textfield
!= NULL
)
2858 XmNbottomAttachment
, XmATTACH_WIDGET
,
2859 XmNbottomWidget
, dialogtextfield
,
2866 XmNbottomAttachment
, XmATTACH_WIDGET
,
2867 XmNbottomWidget
, separator
,
2871 XmNbottomAttachment
, XmATTACH_FORM
,
2877 if (dfltbutton
> butcount
)
2878 dfltbutton
= butcount
;
2879 XtVaSetValues(dialogform
,
2880 XmNdefaultButton
, buttons
[dfltbutton
- 1], NULL
);
2881 if (textfield
!= NULL
)
2882 XtVaSetValues(dialogform
, XmNinitialFocus
, dialogtextfield
, NULL
);
2884 XtVaSetValues(dialogform
, XmNinitialFocus
, buttons
[dfltbutton
- 1],
2887 manage_centered(dialogform
);
2888 activate_dialog_mnemonics(dialogform
);
2890 if (textfield
!= NULL
&& *textfield
!= NUL
)
2892 /* This only works after the textfield has been realised. */
2893 XmTextFieldSetSelection(dialogtextfield
,
2894 (XmTextPosition
)0, (XmTextPosition
)STRLEN(textfield
),
2895 XtLastTimestampProcessed(gui
.dpy
));
2896 XmTextFieldSetCursorPosition(dialogtextfield
,
2897 (XmTextPosition
)STRLEN(textfield
));
2900 app
= XtWidgetToApplicationContext(dialogform
);
2902 /* Loop until a button is pressed or the dialog is killed somehow. */
2906 XtAppProcessEvent(app
, (XtInputMask
)XtIMAll
);
2907 if (dialogStatus
>= 0 || !XtIsManaged(dialogform
))
2913 if (textfield
!= NULL
)
2915 p
= (char_u
*)XmTextGetString(dialogtextfield
);
2916 if (p
== NULL
|| dialogStatus
< 0)
2919 vim_strncpy(textfield
, p
, IOSIZE
- 1);
2922 suppress_dialog_mnemonics(dialogform
);
2923 XtDestroyWidget(dialogform
);
2925 return dialogStatus
;
2927 #endif /* FEAT_GUI_DIALOG */
2929 #if defined(FEAT_FOOTER) || defined(PROTO)
2932 gui_mch_compute_footer_height()
2934 Dimension height
; /* total Toolbar height */
2935 Dimension top
; /* XmNmarginTop */
2936 Dimension bottom
; /* XmNmarginBottom */
2937 Dimension shadow
; /* XmNshadowThickness */
2939 XtVaGetValues(footer
,
2942 XmNmarginBottom
, &bottom
,
2943 XmNshadowThickness
, &shadow
,
2946 return (int) height
+ top
+ bottom
+ (shadow
<< 1);
2949 #if 0 /* not used */
2951 gui_mch_set_footer_pos(h
)
2952 int h
; /* textArea height */
2954 XtVaSetValues(footer
,
2955 XmNtopOffset
, h
+ 7,
2961 gui_mch_enable_footer(showit
)
2966 gui
.footer_height
= gui_mch_compute_footer_height();
2967 XtManageChild(footer
);
2971 gui
.footer_height
= 0;
2972 XtUnmanageChild(footer
);
2974 XtVaSetValues(textAreaForm
, XmNbottomOffset
, gui
.footer_height
, NULL
);
2978 gui_mch_set_footer(s
)
2983 xms
= XmStringCreate((char *)s
, STRING_TAG
);
2986 XtVaSetValues(footer
, XmNlabelString
, xms
, NULL
);
2994 #if defined(FEAT_TOOLBAR) || defined(PROTO)
2996 gui_mch_show_toolbar(int showit
)
2998 Cardinal numChildren
; /* how many children toolBar has */
3000 if (toolBar
== (Widget
)0)
3002 XtVaGetValues(toolBar
, XmNnumChildren
, &numChildren
, NULL
);
3003 if (showit
&& numChildren
> 0)
3005 /* Assume that we want to show the toolbar if p_toolbar contains
3006 * valid option settings, therefore p_toolbar must not be NULL.
3008 WidgetList children
;
3010 XtVaGetValues(toolBar
, XmNchildren
, &children
, NULL
);
3012 void (*action
)(BalloonEval
*);
3015 if (strstr((const char *)p_toolbar
, "tooltips"))
3016 action
= &gui_mch_enable_beval_area
;
3018 action
= &gui_mch_disable_beval_area
;
3019 if (strstr((const char *)p_toolbar
, "text"))
3021 else if (strstr((const char *)p_toolbar
, "icons"))
3028 for (toolbar
= root_menu
; toolbar
; toolbar
= toolbar
->next
)
3029 if (menu_is_toolbar(toolbar
->dname
))
3031 /* Assumption: toolbar is NULL if there is no toolbar,
3032 * otherwise it contains the toolbar menu structure.
3034 * Assumption: "numChildren" == the number of items in the list
3035 * of items beginning with toolbar->children.
3039 for (cur
= toolbar
->children
; cur
; cur
= cur
->next
)
3044 /* Enable/Disable tooltip (OK to enable while
3045 * currently enabled). */
3046 if (cur
->tip
!= NULL
)
3047 (*action
)(cur
->tip
);
3048 if (!menu_is_separator(cur
->name
))
3050 if (text
== 1 || cur
->xpm
== NULL
)
3052 XtSetArg(args
[n
], XmNlabelType
, XmSTRING
);
3055 if (cur
->id
!= NULL
)
3057 XtUnmanageChild(cur
->id
);
3058 XtSetValues(cur
->id
, args
, n
);
3059 XtManageChild(cur
->id
);
3066 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
3067 XtManageChild(XtParent(toolBar
));
3068 #ifdef FEAT_GUI_TABLINE
3069 if (showing_tabline
)
3071 XtVaSetValues(tabLine
,
3072 XmNtopAttachment
, XmATTACH_WIDGET
,
3073 XmNtopWidget
, XtParent(toolBar
),
3075 XtVaSetValues(textAreaForm
,
3076 XmNtopAttachment
, XmATTACH_WIDGET
,
3077 XmNtopWidget
, tabLine
,
3082 XtVaSetValues(textAreaForm
,
3083 XmNtopAttachment
, XmATTACH_WIDGET
,
3084 XmNtopWidget
, XtParent(toolBar
),
3086 if (XtIsManaged(menuBar
))
3087 XtVaSetValues(XtParent(toolBar
),
3088 XmNtopAttachment
, XmATTACH_WIDGET
,
3089 XmNtopWidget
, menuBar
,
3092 XtVaSetValues(XtParent(toolBar
),
3093 XmNtopAttachment
, XmATTACH_FORM
,
3098 gui
.toolbar_height
= 0;
3099 if (XtIsManaged(menuBar
))
3101 #ifdef FEAT_GUI_TABLINE
3102 if (showing_tabline
)
3104 XtVaSetValues(tabLine
,
3105 XmNtopAttachment
, XmATTACH_WIDGET
,
3106 XmNtopWidget
, menuBar
,
3108 XtVaSetValues(textAreaForm
,
3109 XmNtopAttachment
, XmATTACH_WIDGET
,
3110 XmNtopWidget
, tabLine
,
3115 XtVaSetValues(textAreaForm
,
3116 XmNtopAttachment
, XmATTACH_WIDGET
,
3117 XmNtopWidget
, menuBar
,
3122 #ifdef FEAT_GUI_TABLINE
3123 if (showing_tabline
)
3125 XtVaSetValues(tabLine
,
3126 XmNtopAttachment
, XmATTACH_FORM
,
3128 XtVaSetValues(textAreaForm
,
3129 XmNtopAttachment
, XmATTACH_WIDGET
,
3130 XmNtopWidget
, tabLine
,
3135 XtVaSetValues(textAreaForm
,
3136 XmNtopAttachment
, XmATTACH_FORM
,
3140 XtUnmanageChild(XtParent(toolBar
));
3142 gui_set_shellsize(FALSE
, FALSE
, RESIZE_VERT
);
3146 * A toolbar button has been pushed; now reset the input focus
3147 * such that the user can type page up/down etc. and have the
3148 * input go to the editor window, not the button
3153 if (textArea
!= NULL
)
3154 XmProcessTraversal(textArea
, XmTRAVERSE_CURRENT
);
3158 gui_mch_compute_toolbar_height()
3161 Dimension height
; /* total Toolbar height */
3162 Dimension whgt
; /* height of each widget */
3163 WidgetList children
; /* list of toolBar's children */
3164 Cardinal numChildren
; /* how many children toolBar has */
3169 if (toolBar
!= (Widget
)0 && toolBarFrame
!= (Widget
)0)
3170 { /* get height of XmFrame parent */
3176 XtVaGetValues(toolBarFrame
,
3177 XmNshadowThickness
, &fst
,
3178 XmNmarginHeight
, &fmh
,
3180 borders
+= fst
+ fmh
;
3181 XtVaGetValues(toolBar
,
3182 XmNshadowThickness
, &tst
,
3183 XmNmarginHeight
, &tmh
,
3184 XmNchildren
, &children
,
3185 XmNnumChildren
, &numChildren
, NULL
);
3186 borders
+= tst
+ tmh
;
3187 for (i
= 0; i
< (int)numChildren
; i
++)
3190 XtVaGetValues(children
[i
], XmNheight
, &whgt
, NULL
);
3195 #ifdef LESSTIF_VERSION
3196 /* Hack: When starting up we get wrong dimensions. */
3201 return (int)(height
+ (borders
<< 1));
3205 motif_get_toolbar_colors(bgp
, fgp
, bsp
, tsp
, hsp
)
3212 XtVaGetValues(toolBar
,
3215 XmNbottomShadowColor
, bsp
,
3216 XmNtopShadowColor
, tsp
,
3217 XmNhighlightColor
, hsp
,
3223 * The next toolbar enter/leave callbacks should really do balloon help. But
3224 * I have to use footer help for backwards compatability. Hopefully both will
3225 * get implemented and the user will have a choice.
3228 toolbarbutton_enter_cb(w
, client_data
, event
, cont
)
3230 XtPointer client_data
;
3231 XEvent
*event UNUSED
;
3232 Boolean
*cont UNUSED
;
3234 vimmenu_T
*menu
= (vimmenu_T
*) client_data
;
3236 if (menu
->strings
[MENU_INDEX_TIP
] != NULL
)
3238 if (vim_strchr(p_go
, GO_FOOTER
) != NULL
)
3239 gui_mch_set_footer(menu
->strings
[MENU_INDEX_TIP
]);
3244 toolbarbutton_leave_cb(w
, client_data
, event
, cont
)
3246 XtPointer client_data UNUSED
;
3247 XEvent
*event UNUSED
;
3248 Boolean
*cont UNUSED
;
3250 gui_mch_set_footer((char_u
*) "");
3255 #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
3257 * Show or hide the tabline.
3260 gui_mch_show_tabline(int showit
)
3262 if (tabLine
== (Widget
)0)
3265 if (!showit
!= !showing_tabline
)
3269 XtManageChild(tabLine
);
3270 XtUnmanageChild(XtNameToWidget(tabLine
, "PageScroller"));
3271 XtUnmanageChild(XtNameToWidget(tabLine
, "MinorTabScrollerNext"));
3272 XtUnmanageChild(XtNameToWidget(tabLine
,
3273 "MinorTabScrollerPrevious"));
3275 # ifdef FEAT_TOOLBAR
3276 if (XtIsManaged(XtParent(toolBar
)))
3277 XtVaSetValues(tabLine
,
3278 XmNtopAttachment
, XmATTACH_WIDGET
,
3279 XmNtopWidget
, XtParent(toolBar
), NULL
);
3282 if (XtIsManaged(menuBar
))
3283 XtVaSetValues(tabLine
,
3284 XmNtopAttachment
, XmATTACH_WIDGET
,
3285 XmNtopWidget
, menuBar
, NULL
);
3288 XtVaSetValues(tabLine
,
3289 XmNtopAttachment
, XmATTACH_FORM
, NULL
);
3290 XtVaSetValues(textAreaForm
,
3291 XmNtopAttachment
, XmATTACH_WIDGET
,
3292 XmNtopWidget
, tabLine
,
3297 XtUnmanageChild(tabLine
);
3299 # ifdef FEAT_TOOLBAR
3300 if (XtIsManaged(XtParent(toolBar
)))
3301 XtVaSetValues(textAreaForm
,
3302 XmNtopAttachment
, XmATTACH_WIDGET
,
3303 XmNtopWidget
, XtParent(toolBar
), NULL
);
3306 if (XtIsManaged(menuBar
))
3307 XtVaSetValues(textAreaForm
,
3308 XmNtopAttachment
, XmATTACH_WIDGET
,
3309 XmNtopWidget
, menuBar
, NULL
);
3312 XtVaSetValues(textAreaForm
,
3313 XmNtopAttachment
, XmATTACH_FORM
, NULL
);
3315 showing_tabline
= showit
;
3320 * Return TRUE when tabline is displayed.
3323 gui_mch_showing_tabline(void)
3325 return tabLine
!= (Widget
)0 && showing_tabline
;
3329 * Update the labels of the tabline.
3332 gui_mch_update_tabline(void)
3337 int curtabidx
= 0, currentpage
;
3339 XmNotebookPageInfo page_info
;
3340 XmNotebookPageStatus page_status
;
3341 int last_page
, tab_count
;
3346 if (tabLine
== (Widget
)0)
3349 /* Add a label for each tab page. They all contain the same text area. */
3350 for (tp
= first_tabpage
; tp
!= NULL
; tp
= tp
->tp_next
, ++nr
)
3355 page_status
= XmNotebookGetPageInfo(tabLine
, nr
, &page_info
);
3356 if (page_status
== XmPAGE_INVALID
3357 || page_info
.major_tab_widget
== (Widget
)0)
3361 XtSetArg(args
[n
], XmNnotebookChildType
, XmMAJOR_TAB
); n
++;
3362 XtSetArg(args
[n
], XmNtraversalOn
, False
); n
++;
3363 XtSetArg(args
[n
], XmNalignment
, XmALIGNMENT_BEGINNING
); n
++;
3364 XtSetArg(args
[n
], XmNhighlightThickness
, 1); n
++;
3365 XtSetArg(args
[n
], XmNshadowThickness
, 1); n
++;
3366 tab
= XmCreatePushButton(tabLine
, "-Empty-", args
, n
);
3368 beval
= gui_mch_create_beval_area(tab
, NULL
, tabline_balloon_cb
,
3370 XtVaSetValues(tab
, XmNuserData
, beval
, NULL
);
3373 tab
= page_info
.major_tab_widget
;
3375 XtVaSetValues(tab
, XmNpageNumber
, nr
, NULL
);
3378 * Change the label text only if it is different
3380 XtVaGetValues(tab
, XmNlabelString
, &label_str
, NULL
);
3381 if (XmStringGetLtoR(label_str
, XmSTRING_DEFAULT_CHARSET
, &label_cstr
))
3383 get_tabline_label(tp
, FALSE
);
3384 if (STRCMP(label_cstr
, NameBuff
) != 0)
3386 XtVaSetValues(tab
, XtVaTypedArg
, XmNlabelString
, XmRString
,
3387 NameBuff
, STRLEN(NameBuff
) + 1, NULL
);
3389 * Force a resize of the tab label button
3391 XtUnmanageChild(tab
);
3400 XtVaGetValues(tabLine
, XmNlastPageNumber
, &last_page
, NULL
);
3402 /* Remove any old labels. */
3403 while (nr
<= last_page
)
3405 if (XmNotebookGetPageInfo(tabLine
, nr
, &page_info
) != XmPAGE_INVALID
3406 && page_info
.page_number
== nr
3407 && page_info
.major_tab_widget
!= (Widget
)0)
3409 XtVaGetValues(page_info
.major_tab_widget
, XmNuserData
, &beval
, NULL
);
3411 gui_mch_destroy_beval_area(beval
);
3412 XtUnmanageChild(page_info
.major_tab_widget
);
3413 XtDestroyWidget(page_info
.major_tab_widget
);
3418 XtVaSetValues(tabLine
, XmNlastPageNumber
, tab_count
, NULL
);
3420 XtVaGetValues(tabLine
, XmNcurrentPageNumber
, ¤tpage
, NULL
);
3421 if (currentpage
!= curtabidx
)
3422 XtVaSetValues(tabLine
, XmNcurrentPageNumber
, curtabidx
, NULL
);
3426 * Set the current tab to "nr". First tab is 1.
3429 gui_mch_set_curtab(nr
)
3434 if (tabLine
== (Widget
)0)
3437 XtVaGetValues(tabLine
, XmNcurrentPageNumber
, ¤tpage
, NULL
);
3438 if (currentpage
!= nr
)
3439 XtVaSetValues(tabLine
, XmNcurrentPageNumber
, nr
, NULL
);
3444 * Set the colors of Widget "id" to the menu colors.
3447 gui_motif_menu_colors(id
)
3450 if (gui
.menu_bg_pixel
!= INVALCOLOR
)
3451 #if (XmVersion >= 1002)
3452 XmChangeColor(id
, gui
.menu_bg_pixel
);
3454 XtVaSetValues(id
, XmNbackground
, gui
.menu_bg_pixel
, NULL
);
3456 if (gui
.menu_fg_pixel
!= INVALCOLOR
)
3457 XtVaSetValues(id
, XmNforeground
, gui
.menu_fg_pixel
, NULL
);
3461 * Set the colors of Widget "id" to the scrollbar colors.
3464 gui_motif_scroll_colors(id
)
3467 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
3468 #if (XmVersion >= 1002)
3469 XmChangeColor(id
, gui
.scroll_bg_pixel
);
3471 XtVaSetValues(id
, XmNbackground
, gui
.scroll_bg_pixel
, NULL
);
3473 if (gui
.scroll_fg_pixel
!= INVALCOLOR
)
3474 XtVaSetValues(id
, XmNforeground
, gui
.scroll_fg_pixel
, NULL
);
3478 * Set the fontlist for Widget "id" to use gui.menu_fontset or gui.menu_font.
3481 gui_motif_menu_fontlist(id
)
3485 #ifdef FONTSET_ALWAYS
3486 if (gui
.menu_fontset
!= NOFONTSET
)
3490 fl
= gui_motif_fontset2fontlist((XFontSet
*)&gui
.menu_fontset
);
3493 if (XtIsManaged(id
))
3495 XtUnmanageChild(id
);
3496 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3497 /* We should force the widget to recalculate it's
3502 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3507 if (gui
.menu_font
!= NOFONT
)
3511 fl
= gui_motif_create_fontlist((XFontStruct
*)gui
.menu_font
);
3514 if (XtIsManaged(id
))
3516 XtUnmanageChild(id
);
3517 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3518 /* We should force the widget to recalculate it's
3523 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3533 * We don't create it twice for the sake of speed.
3536 typedef struct _SharedFindReplace
3538 Widget dialog
; /* the main dialog widget */
3539 Widget wword
; /* 'Exact match' check button */
3540 Widget mcase
; /* 'match case' check button */
3541 Widget up
; /* search direction 'Up' radio button */
3542 Widget down
; /* search direction 'Down' radio button */
3543 Widget what
; /* 'Find what' entry text widget */
3544 Widget with
; /* 'Replace with' entry text widget */
3545 Widget find
; /* 'Find Next' action button */
3546 Widget replace
; /* 'Replace With' action button */
3547 Widget all
; /* 'Replace All' action button */
3548 Widget undo
; /* 'Undo' action button */
3551 } SharedFindReplace
;
3553 static SharedFindReplace find_widgets
= {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
3554 static SharedFindReplace repl_widgets
= {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
3556 static void find_replace_destroy_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3557 static void find_replace_dismiss_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3558 static void entry_activate_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3559 static void find_replace_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3560 static void find_replace_keypress
__ARGS((Widget w
, SharedFindReplace
* frdp
, XKeyEvent
* event
));
3561 static void find_replace_dialog_create
__ARGS((char_u
*entry_text
, int do_replace
));
3564 find_replace_destroy_callback(w
, client_data
, call_data
)
3566 XtPointer client_data
;
3567 XtPointer call_data UNUSED
;
3569 SharedFindReplace
*cd
= (SharedFindReplace
*)client_data
;
3572 /* suppress_dialog_mnemonics(cd->dialog); */
3573 cd
->dialog
= (Widget
)0;
3577 find_replace_dismiss_callback(w
, client_data
, call_data
)
3579 XtPointer client_data
;
3580 XtPointer call_data UNUSED
;
3582 SharedFindReplace
*cd
= (SharedFindReplace
*)client_data
;
3585 XtUnmanageChild(cd
->dialog
);
3589 entry_activate_callback(w
, client_data
, call_data
)
3591 XtPointer client_data
;
3592 XtPointer call_data UNUSED
;
3594 XmProcessTraversal((Widget
)client_data
, XmTRAVERSE_CURRENT
);
3598 find_replace_callback(w
, client_data
, call_data
)
3600 XtPointer client_data
;
3601 XtPointer call_data UNUSED
;
3603 long_u flags
= (long_u
)client_data
;
3604 char *find_text
, *repl_text
;
3605 Boolean direction_down
= TRUE
;
3608 SharedFindReplace
*sfr
;
3610 if (flags
== FRD_UNDO
)
3612 char_u
*save_cpo
= p_cpo
;
3614 /* No need to be Vi compatible here. */
3615 p_cpo
= (char_u
*)"";
3618 gui_update_screen();
3622 /* Get the search/replace strings from the dialog */
3623 if (flags
== FRD_FINDNEXT
)
3626 sfr
= &find_widgets
;
3630 repl_text
= XmTextFieldGetString(repl_widgets
.with
);
3631 sfr
= &repl_widgets
;
3633 find_text
= XmTextFieldGetString(sfr
->what
);
3634 XtVaGetValues(sfr
->down
, XmNset
, &direction_down
, NULL
);
3635 XtVaGetValues(sfr
->wword
, XmNset
, &wword
, NULL
);
3636 XtVaGetValues(sfr
->mcase
, XmNset
, &mcase
, NULL
);
3638 flags
|= FRD_WHOLE_WORD
;
3640 flags
|= FRD_MATCH_CASE
;
3642 (void)gui_do_findrepl((int)flags
, (char_u
*)find_text
, (char_u
*)repl_text
,
3645 if (find_text
!= NULL
)
3647 if (repl_text
!= NULL
)
3652 find_replace_keypress(w
, frdp
, event
)
3654 SharedFindReplace
*frdp
;
3662 keysym
= XLookupKeysym(event
, 0);
3664 /* the scape key pops the whole dialog down */
3665 if (keysym
== XK_Escape
)
3666 XtUnmanageChild(frdp
->dialog
);
3676 KeySym mnemonic
= NUL
;
3681 p
= vim_strsave(label
);
3684 for (next
= p
; *next
; ++next
)
3686 if (*next
== DLG_HOTKEY_CHAR
)
3688 int len
= STRLEN(next
);
3692 mch_memmove(next
, next
+ 1, len
);
3698 str
= XmStringCreateSimple((char *)p
);
3703 XmNlabelString
, str
,
3704 XmNmnemonic
, mnemonic
,
3708 gui_motif_menu_fontlist(w
);
3712 find_replace_dialog_create(arg
, do_replace
)
3716 SharedFindReplace
*frdp
;
3731 frdp
= do_replace
? &repl_widgets
: &find_widgets
;
3733 /* Get the search string to use. */
3734 entry_text
= get_find_dialog_text(arg
, &wword
, &mcase
);
3736 /* If the dialog already exists, just raise it. */
3739 gui_motif_synch_fonts();
3741 /* If the window is already up, just pop it to the top */
3742 if (XtIsManaged(frdp
->dialog
))
3743 XMapRaised(XtDisplay(frdp
->dialog
),
3744 XtWindow(XtParent(frdp
->dialog
)));
3746 XtManageChild(frdp
->dialog
);
3747 XtPopup(XtParent(frdp
->dialog
), XtGrabNone
);
3748 XmProcessTraversal(frdp
->what
, XmTRAVERSE_CURRENT
);
3750 if (entry_text
!= NULL
)
3751 XmTextFieldSetString(frdp
->what
, (char *)entry_text
);
3752 vim_free(entry_text
);
3754 XtVaSetValues(frdp
->wword
, XmNset
, wword
, NULL
);
3758 /* Create a fresh new dialog window */
3760 str
= XmStringCreateSimple(_("VIM - Search and Replace..."));
3762 str
= XmStringCreateSimple(_("VIM - Search..."));
3765 XtSetArg(args
[n
], XmNautoUnmanage
, False
); n
++;
3766 XtSetArg(args
[n
], XmNnoResize
, True
); n
++;
3767 XtSetArg(args
[n
], XmNdialogTitle
, str
); n
++;
3769 frdp
->dialog
= XmCreateFormDialog(vimShell
, "findReplaceDialog", args
, n
);
3771 XtAddCallback(frdp
->dialog
, XmNdestroyCallback
,
3772 find_replace_destroy_callback
, frdp
);
3774 button_form
= XtVaCreateWidget("buttonForm",
3775 xmFormWidgetClass
, frdp
->dialog
,
3776 XmNrightAttachment
, XmATTACH_FORM
,
3778 XmNtopAttachment
, XmATTACH_FORM
,
3780 XmNbottomAttachment
, XmATTACH_FORM
,
3784 frdp
->find
= XtVaCreateManagedWidget("findButton",
3785 xmPushButtonWidgetClass
, button_form
,
3787 XmNtopAttachment
, XmATTACH_FORM
,
3788 XmNleftAttachment
, XmATTACH_FORM
,
3789 XmNrightAttachment
, XmATTACH_FORM
,
3791 set_label(frdp
->find
, _("Find &Next"));
3793 XtAddCallback(frdp
->find
, XmNactivateCallback
,
3794 find_replace_callback
,
3795 (do_replace
? (XtPointer
)FRD_R_FINDNEXT
: (XtPointer
)FRD_FINDNEXT
));
3799 frdp
->replace
= XtVaCreateManagedWidget("replaceButton",
3800 xmPushButtonWidgetClass
, button_form
,
3801 XmNtopAttachment
, XmATTACH_WIDGET
,
3802 XmNtopWidget
, frdp
->find
,
3803 XmNleftAttachment
, XmATTACH_FORM
,
3804 XmNrightAttachment
, XmATTACH_FORM
,
3806 set_label(frdp
->replace
, _("&Replace"));
3807 XtAddCallback(frdp
->replace
, XmNactivateCallback
,
3808 find_replace_callback
, (XtPointer
)FRD_REPLACE
);
3810 frdp
->all
= XtVaCreateManagedWidget("replaceAllButton",
3811 xmPushButtonWidgetClass
, button_form
,
3812 XmNtopAttachment
, XmATTACH_WIDGET
,
3813 XmNtopWidget
, frdp
->replace
,
3814 XmNleftAttachment
, XmATTACH_FORM
,
3815 XmNrightAttachment
, XmATTACH_FORM
,
3817 set_label(frdp
->all
, _("Replace &All"));
3818 XtAddCallback(frdp
->all
, XmNactivateCallback
,
3819 find_replace_callback
, (XtPointer
)FRD_REPLACEALL
);
3821 frdp
->undo
= XtVaCreateManagedWidget("undoButton",
3822 xmPushButtonWidgetClass
, button_form
,
3823 XmNtopAttachment
, XmATTACH_WIDGET
,
3824 XmNtopWidget
, frdp
->all
,
3825 XmNleftAttachment
, XmATTACH_FORM
,
3826 XmNrightAttachment
, XmATTACH_FORM
,
3828 set_label(frdp
->undo
, _("&Undo"));
3829 XtAddCallback(frdp
->undo
, XmNactivateCallback
,
3830 find_replace_callback
, (XtPointer
)FRD_UNDO
);
3833 frdp
->cancel
= XtVaCreateManagedWidget("closeButton",
3834 xmPushButtonWidgetClass
, button_form
,
3835 XmNleftAttachment
, XmATTACH_FORM
,
3836 XmNrightAttachment
, XmATTACH_FORM
,
3837 XmNbottomAttachment
, XmATTACH_FORM
,
3839 set_label(frdp
->cancel
, _("&Cancel"));
3840 XtAddCallback(frdp
->cancel
, XmNactivateCallback
,
3841 find_replace_dismiss_callback
, frdp
);
3842 gui_motif_menu_fontlist(frdp
->cancel
);
3844 XtManageChild(button_form
);
3847 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
3848 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_WIDGET
); n
++;
3849 XtSetArg(args
[n
], XmNrightWidget
, button_form
); n
++;
3850 XtSetArg(args
[n
], XmNrightOffset
, 4); n
++;
3851 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
3852 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
3853 separator
= XmCreateSeparatorGadget(frdp
->dialog
, "separator", args
, n
);
3854 XtManageChild(separator
);
3856 input_form
= XtVaCreateWidget("inputForm",
3857 xmFormWidgetClass
, frdp
->dialog
,
3858 XmNleftAttachment
, XmATTACH_FORM
,
3860 XmNrightAttachment
, XmATTACH_WIDGET
,
3861 XmNrightWidget
, separator
,
3863 XmNtopAttachment
, XmATTACH_FORM
,
3869 Widget label_with
= (Widget
)0;
3871 str
= XmStringCreateSimple(_("Find what:"));
3872 label_what
= XtVaCreateManagedWidget("whatLabel",
3873 xmLabelGadgetClass
, input_form
,
3874 XmNlabelString
, str
,
3875 XmNleftAttachment
, XmATTACH_FORM
,
3876 XmNtopAttachment
, XmATTACH_FORM
,
3880 gui_motif_menu_fontlist(label_what
);
3882 frdp
->what
= XtVaCreateManagedWidget("whatText",
3883 xmTextFieldWidgetClass
, input_form
,
3884 XmNtopAttachment
, XmATTACH_FORM
,
3885 XmNrightAttachment
, XmATTACH_FORM
,
3886 XmNleftAttachment
, XmATTACH_FORM
,
3891 frdp
->with
= XtVaCreateManagedWidget("withText",
3892 xmTextFieldWidgetClass
, input_form
,
3893 XmNtopAttachment
, XmATTACH_WIDGET
,
3894 XmNtopWidget
, frdp
->what
,
3896 XmNleftAttachment
, XmATTACH_FORM
,
3897 XmNrightAttachment
, XmATTACH_FORM
,
3898 XmNbottomAttachment
, XmATTACH_FORM
,
3901 XtAddCallback(frdp
->with
, XmNactivateCallback
,
3902 find_replace_callback
, (XtPointer
) FRD_R_FINDNEXT
);
3904 str
= XmStringCreateSimple(_("Replace with:"));
3905 label_with
= XtVaCreateManagedWidget("withLabel",
3906 xmLabelGadgetClass
, input_form
,
3907 XmNlabelString
, str
,
3908 XmNleftAttachment
, XmATTACH_FORM
,
3909 XmNtopAttachment
, XmATTACH_WIDGET
,
3910 XmNtopWidget
, frdp
->what
,
3912 XmNbottomAttachment
, XmATTACH_FORM
,
3915 gui_motif_menu_fontlist(label_with
);
3918 * Make the entry activation only change the input focus onto the
3921 XtAddCallback(frdp
->what
, XmNactivateCallback
,
3922 entry_activate_callback
, frdp
->with
);
3923 XtAddEventHandler(frdp
->with
, KeyPressMask
, False
,
3924 (XtEventHandler
)find_replace_keypress
,
3931 * Make the entry activation do the search.
3933 XtAddCallback(frdp
->what
, XmNactivateCallback
,
3934 find_replace_callback
, (XtPointer
)FRD_FINDNEXT
);
3936 XtAddEventHandler(frdp
->what
, KeyPressMask
, False
,
3937 (XtEventHandler
)find_replace_keypress
,
3940 /* Get the maximum width between the label widgets and line them up.
3943 XtSetArg(args
[n
], XmNwidth
, &width
); n
++;
3944 XtGetValues(label_what
, args
, n
);
3948 XtGetValues(label_with
, args
, n
);
3953 XtVaSetValues(frdp
->what
, XmNleftOffset
, widest
, NULL
);
3955 XtVaSetValues(frdp
->with
, XmNleftOffset
, widest
, NULL
);
3959 XtManageChild(input_form
);
3965 frame
= XtVaCreateWidget("directionFrame",
3966 xmFrameWidgetClass
, frdp
->dialog
,
3967 XmNtopAttachment
, XmATTACH_WIDGET
,
3968 XmNtopWidget
, input_form
,
3970 XmNbottomAttachment
, XmATTACH_FORM
,
3972 XmNrightAttachment
, XmATTACH_OPPOSITE_WIDGET
,
3973 XmNrightWidget
, input_form
,
3976 str
= XmStringCreateSimple(_("Direction"));
3977 w
= XtVaCreateManagedWidget("directionFrameLabel",
3978 xmLabelGadgetClass
, frame
,
3979 XmNlabelString
, str
,
3980 XmNchildHorizontalAlignment
, XmALIGNMENT_BEGINNING
,
3981 XmNchildType
, XmFRAME_TITLE_CHILD
,
3984 gui_motif_menu_fontlist(w
);
3986 radio_box
= XmCreateRadioBox(frame
, "radioBox",
3989 str
= XmStringCreateSimple( _("Up"));
3990 frdp
->up
= XtVaCreateManagedWidget("upRadioButton",
3991 xmToggleButtonGadgetClass
, radio_box
,
3992 XmNlabelString
, str
,
3996 gui_motif_menu_fontlist(frdp
->up
);
3998 str
= XmStringCreateSimple(_("Down"));
3999 frdp
->down
= XtVaCreateManagedWidget("downRadioButton",
4000 xmToggleButtonGadgetClass
, radio_box
,
4001 XmNlabelString
, str
,
4005 gui_motif_menu_fontlist(frdp
->down
);
4007 XtManageChild(radio_box
);
4008 XtManageChild(frame
);
4011 toggle_form
= XtVaCreateWidget("toggleForm",
4012 xmFormWidgetClass
, frdp
->dialog
,
4013 XmNleftAttachment
, XmATTACH_FORM
,
4015 XmNrightAttachment
, XmATTACH_WIDGET
,
4016 XmNrightWidget
, frame
,
4018 XmNtopAttachment
, XmATTACH_WIDGET
,
4019 XmNtopWidget
, input_form
,
4021 XmNbottomAttachment
, XmATTACH_FORM
,
4025 str
= XmStringCreateSimple(_("Match whole word only"));
4026 frdp
->wword
= XtVaCreateManagedWidget("wordToggle",
4027 xmToggleButtonGadgetClass
, toggle_form
,
4028 XmNlabelString
, str
,
4029 XmNtopAttachment
, XmATTACH_FORM
,
4031 XmNleftAttachment
, XmATTACH_FORM
,
4037 str
= XmStringCreateSimple(_("Match case"));
4038 frdp
->mcase
= XtVaCreateManagedWidget("caseToggle",
4039 xmToggleButtonGadgetClass
, toggle_form
,
4040 XmNlabelString
, str
,
4041 XmNleftAttachment
, XmATTACH_FORM
,
4043 XmNtopAttachment
, XmATTACH_WIDGET
,
4044 XmNtopWidget
, frdp
->wword
,
4049 gui_motif_menu_fontlist(frdp
->wword
);
4050 gui_motif_menu_fontlist(frdp
->mcase
);
4052 XtManageChild(toggle_form
);
4054 if (entry_text
!= NULL
)
4055 XmTextFieldSetString(frdp
->what
, (char *)entry_text
);
4056 vim_free(entry_text
);
4058 gui_motif_synch_fonts();
4060 manage_centered(frdp
->dialog
);
4061 activate_dialog_mnemonics(frdp
->dialog
);
4062 XmProcessTraversal(frdp
->what
, XmTRAVERSE_CURRENT
);
4066 gui_mch_find_dialog(eap
)
4072 find_replace_dialog_create(eap
->arg
, FALSE
);
4077 gui_mch_replace_dialog(eap
)
4083 find_replace_dialog_create(eap
->arg
, TRUE
);
4087 * Synchronize all gui elements, which are dependant upon the
4088 * main text font used. Those are in esp. the find/replace dialogs.
4089 * If you don't understand why this should be needed, please try to
4090 * search for "piê¶æ" in iso8859-2.
4093 gui_motif_synch_fonts(void)
4095 SharedFindReplace
*frdp
;
4098 XmFontList font_list
;
4100 /* FIXME: Unless we find out how to create a XmFontList from a XFontSet,
4101 * we just give up here on font synchronization. */
4102 font
= (XFontStruct
*)gui
.norm_font
;
4106 font_list
= gui_motif_create_fontlist(font
);
4108 /* OK this loop is a bit tricky... */
4109 for (do_replace
= 0; do_replace
<= 1; ++do_replace
)
4111 frdp
= (do_replace
) ? (&repl_widgets
) : (&find_widgets
);
4114 XtVaSetValues(frdp
->what
, XmNfontList
, font_list
, NULL
);
4116 XtVaSetValues(frdp
->with
, XmNfontList
, font_list
, NULL
);
4120 XmFontListFree(font_list
);