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>
29 #include <Xm/Notebook.h>
32 #include <X11/keysym.h>
33 #include <X11/Xatom.h>
34 #include <X11/StringDefs.h>
35 #include <X11/Intrinsic.h>
42 # ifdef HAVE_XM_XPMP_H
47 #include "gui_xmebw.h" /* for our Enhanced Button Widget */
49 #if defined(FEAT_GUI_DIALOG) && defined(HAVE_XPM)
50 # include "../pixmaps/alert.xpm"
51 # include "../pixmaps/error.xpm"
52 # include "../pixmaps/generic.xpm"
53 # include "../pixmaps/info.xpm"
54 # include "../pixmaps/quest.xpm"
59 extern Widget vimShell
;
61 static Widget vimForm
;
62 static Widget textAreaForm
;
65 static Widget toolBarFrame
;
66 static Widget toolBar
;
68 #ifdef FEAT_GUI_TABLINE
69 static Widget tabLine
;
70 static Widget tabLine_menu
= 0;
71 static int showing_tabline
= 0;
77 # if (XmVersion >= 1002)
78 /* remember the last set value for the tearoff item */
79 static int tearoff_val
= (int)XmTEAR_OFF_ENABLED
;
81 static Widget menuBar
;
84 static void scroll_cb
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
85 #ifdef FEAT_GUI_TABLINE
86 static void tabline_cb
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
87 static void tabline_button_cb
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
88 static void tabline_menu_cb
__ARGS((Widget w
, XtPointer closure
, XEvent
*e
, Boolean
*continue_dispatch
));
92 static void toolbarbutton_enter_cb
__ARGS((Widget
, XtPointer
, XEvent
*, Boolean
*));
93 static void toolbarbutton_leave_cb
__ARGS((Widget
, XtPointer
, XEvent
*, Boolean
*));
95 static void reset_focus
__ARGS((void));
98 static int gui_mch_compute_footer_height
__ARGS((void));
101 static void attachDump(Widget
, char *);
104 static void gui_motif_menu_colors
__ARGS((Widget id
));
105 static void gui_motif_scroll_colors
__ARGS((Widget id
));
107 #if (XmVersion >= 1002)
108 # define STRING_TAG XmFONTLIST_DEFAULT_TAG
110 # define STRING_TAG XmSTRING_DEFAULT_CHARSET
114 * Call-back routines.
119 scroll_cb(w
, client_data
, call_data
)
121 XtPointer client_data
, call_data
;
127 sb
= gui_find_scrollbar((long)client_data
);
129 value
= ((XmScrollBarCallbackStruct
*)call_data
)->value
;
130 dragging
= (((XmScrollBarCallbackStruct
*)call_data
)->reason
==
132 gui_drag_scrollbar(sb
, value
, dragging
);
135 #ifdef FEAT_GUI_TABLINE
138 tabline_cb(w
, client_data
, call_data
)
140 XtPointer client_data
, call_data
;
142 XmNotebookCallbackStruct
*nptr
;
144 nptr
= (XmNotebookCallbackStruct
*)call_data
;
145 if (nptr
->reason
!= (int)XmCR_NONE
)
146 send_tabline_event(nptr
->page_number
);
151 tabline_button_cb(w
, client_data
, call_data
)
153 XtPointer client_data
, call_data
;
157 XtVaGetValues(w
, XmNuserData
, &cmd
, NULL
);
158 XtVaGetValues(tabLine_menu
, XmNuserData
, &tab_idx
, NULL
);
160 send_tabline_menu_event(tab_idx
, cmd
);
164 * Tabline single mouse click timeout handler
168 motif_tabline_timer_cb (timed_out
, interval_id
)
170 XtIntervalId
*interval_id
;
172 *((int *)timed_out
) = TRUE
;
176 * check if the tabline tab scroller is clicked
179 tabline_scroller_clicked(scroller_name
, event
)
181 XButtonPressedEvent
*event
;
184 Position pos_x
, pos_y
;
185 Dimension width
, height
;
187 tab_scroll_w
= XtNameToWidget(tabLine
, scroller_name
);
188 if (tab_scroll_w
!= (Widget
)0) {
189 XtVaGetValues(tab_scroll_w
, XmNx
, &pos_x
, XmNy
, &pos_y
, XmNwidth
,
190 &width
, XmNheight
, &height
, NULL
);
192 /* Tab scroller (next) is visible */
193 if ((event
->x
>= pos_x
) && (event
->x
<= pos_x
+ width
) &&
194 (event
->y
>= pos_y
) && (event
->y
<= pos_y
+ height
)) {
195 /* Clicked on the scroller */
205 tabline_menu_cb(w
, closure
, e
, continue_dispatch
)
209 Boolean
*continue_dispatch
;
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 if (event
->subwindow
!= None
)
255 tab_w
= XtWindowToWidget(XtDisplay(w
), event
->subwindow
);
256 /* LINTED: avoid warning: dubious operation on enum */
257 if (tab_w
!= (Widget
)0 && XmIsPushButton(tab_w
))
258 XtVaGetValues(tab_w
, XmNpageNumber
, &tab_idx
, NULL
);
261 XtVaSetValues(tabLine_menu
, XmNuserData
, tab_idx
, NULL
);
262 XtVaGetValues(tabLine_menu
, XmNchildren
, &children
, XmNnumChildren
,
264 XtManageChildren(children
, numChildren
);
265 XmMenuPosition(tabLine_menu
, (XButtonPressedEvent
*)e
) ;
266 XtManageChild(tabLine_menu
);
271 * End of call-back routines
275 * Implement three dimensional shading of insensitive labels.
280 #include <Xm/LabelP.h>
282 static XtExposeProc old_label_expose
= NULL
;
284 static void label_expose
__ARGS((Widget _w
, XEvent
*_event
, Region _region
));
287 label_expose(_w
, _event
, _region
)
293 XmLabelWidget lw
= (XmLabelWidget
)_w
;
294 unsigned char label_type
= (int)XmSTRING
;
296 XtVaGetValues(_w
, XmNlabelType
, &label_type
, (XtPointer
)0);
298 if (XtIsSensitive(_w
) || label_type
!= (int)XmSTRING
)
299 (*old_label_expose
)(_w
, _event
, _region
);
307 _XmFontListGetDefaultFont(lw
->label
.font
, &fs
);
309 /* FIXME: we should be doing the whole drawing ourself here. */
310 insensitiveGC
= lw
->label
.insensitive_GC
;
312 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
313 dynamic
= GCClipMask
| GCClipXOrigin
| GCClipYOrigin
;
314 values
.graphics_exposures
= False
;
319 values
.font
= fs
->fid
;
322 if (lw
->primitive
.top_shadow_pixmap
!= None
323 && lw
->primitive
.top_shadow_pixmap
!= XmUNSPECIFIED_PIXMAP
)
325 mask
|= GCFillStyle
| GCTile
;
326 values
.fill_style
= FillTiled
;
327 values
.tile
= lw
->primitive
.top_shadow_pixmap
;
330 lw
->label
.TextRect
.x
+= 1;
331 lw
->label
.TextRect
.y
+= 1;
332 if (lw
->label
._acc_text
!= 0)
334 lw
->label
.acc_TextRect
.x
+= 1;
335 lw
->label
.acc_TextRect
.y
+= 1;
338 values
.foreground
= lw
->primitive
.top_shadow_color
;
339 values
.background
= lw
->core
.background_pixel
;
341 lw
->label
.insensitive_GC
= XtAllocateGC((Widget
)lw
, 0, mask
,
342 &values
, dynamic
, (XtGCMask
)0);
343 (*old_label_expose
)(_w
, _event
, _region
);
344 XtReleaseGC(_w
, lw
->label
.insensitive_GC
);
346 lw
->label
.TextRect
.x
-= 1;
347 lw
->label
.TextRect
.y
-= 1;
348 if (lw
->label
._acc_text
!= 0)
350 lw
->label
.acc_TextRect
.x
-= 1;
351 lw
->label
.acc_TextRect
.y
-= 1;
354 values
.foreground
= lw
->primitive
.bottom_shadow_color
;
355 values
.background
= lw
->core
.background_pixel
;
357 lw
->label
.insensitive_GC
= XtAllocateGC((Widget
) lw
, 0, mask
,
358 &values
, dynamic
, (XtGCMask
)0);
359 (*old_label_expose
)(_w
, _event
, _region
);
360 XtReleaseGC(_w
, lw
->label
.insensitive_GC
);
362 lw
->label
.insensitive_GC
= insensitiveGC
;
367 * Create all the motif widgets necessary.
370 gui_x11_create_widgets()
372 #ifdef FEAT_GUI_TABLINE
373 Widget button
, scroller
;
380 * Install the 3D shade effect drawing routines.
382 if (old_label_expose
== NULL
)
384 old_label_expose
= xmLabelWidgetClass
->core_class
.expose
;
385 xmLabelWidgetClass
->core_class
.expose
= label_expose
;
389 * Start out by adding the configured border width into the border offset
391 gui
.border_offset
= gui
.border_width
;
394 * Install the tearOffModel resource converter.
396 #if (XmVersion >= 1002)
397 XmRepTypeInstallTearOffModelConverter();
400 /* Make sure the "Quit" menu entry of the window manager is ignored */
401 XtVaSetValues(vimShell
, XmNdeleteResponse
, XmDO_NOTHING
, NULL
);
403 vimForm
= XtVaCreateManagedWidget("vimForm",
404 xmFormWidgetClass
, vimShell
,
406 XmNhighlightThickness
, 0,
407 XmNshadowThickness
, 0,
410 XmNresizePolicy
, XmRESIZE_ANY
,
412 gui_motif_menu_colors(vimForm
);
416 Arg al
[7]; /* Make sure there is enough room for arguments! */
419 # if (XmVersion >= 1002)
420 XtSetArg(al
[ac
], XmNtearOffModel
, tearoff_val
); ac
++;
422 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
423 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
424 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
425 # ifndef FEAT_TOOLBAR
426 /* Always stick to right hand side. */
427 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
429 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
430 menuBar
= XmCreateMenuBar(vimForm
, "menuBar", al
, ac
);
431 XtManageChild(menuBar
);
433 /* Remember the default colors, needed for ":hi clear". */
434 XtVaGetValues(menuBar
,
435 XmNbackground
, &gui
.menu_def_bg_pixel
,
436 XmNforeground
, &gui
.menu_def_fg_pixel
,
438 gui_motif_menu_colors(menuBar
);
444 * Create an empty ToolBar. We should get buttons defined from menu.vim.
446 toolBarFrame
= XtVaCreateWidget("toolBarFrame",
447 xmFrameWidgetClass
, vimForm
,
448 XmNshadowThickness
, 0,
451 XmNleftAttachment
, XmATTACH_FORM
,
452 XmNrightAttachment
, XmATTACH_FORM
,
454 gui_motif_menu_colors(toolBarFrame
);
456 toolBar
= XtVaCreateManagedWidget("toolBar",
457 xmRowColumnWidgetClass
, toolBarFrame
,
458 XmNchildType
, XmFRAME_WORKAREA_CHILD
,
459 XmNrowColumnType
, XmWORK_AREA
,
460 XmNorientation
, XmHORIZONTAL
,
461 XmNtraversalOn
, False
,
462 XmNisHomogeneous
, False
,
463 XmNpacking
, XmPACK_TIGHT
,
465 XmNshadowThickness
, 0,
466 XmNhighlightThickness
, 0,
471 gui_motif_menu_colors(toolBar
);
475 #ifdef FEAT_GUI_TABLINE
476 /* Create the Vim GUI tabline */
478 XtSetArg(args
[n
], XmNbindingType
, XmNONE
); n
++;
479 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
480 XtSetArg(args
[n
], XmNbackPageSize
, XmNONE
); n
++;
481 XtSetArg(args
[n
], XmNbackPageNumber
, 0); n
++;
482 XtSetArg(args
[n
], XmNbackPagePlacement
, XmTOP_RIGHT
); n
++;
483 XtSetArg(args
[n
], XmNmajorTabSpacing
, 0); n
++;
484 XtSetArg(args
[n
], XmNshadowThickness
, 0); n
++;
485 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
486 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
487 tabLine
= XmCreateNotebook(vimForm
, "Vim tabline", args
, n
);
489 XtAddCallback(tabLine
, XmNpageChangedCallback
, (XtCallbackProc
)tabline_cb
,
491 XtAddEventHandler(tabLine
, ButtonPressMask
, False
,
492 (XtEventHandler
)tabline_menu_cb
, NULL
);
495 * Set the size of the minor next/prev scrollers to zero, so
496 * that they are not displayed. Due to a bug in OpenMotif 2.3,
497 * even if these children widget are unmanaged, they are again
498 * managed by the Notebook widget and the notebook widget geometry
499 * is adjusted to account for the minor scroller widgets.
501 scroller
= XtNameToWidget(tabLine
, "MinorTabScrollerNext");
502 XtVaSetValues(scroller
, XmNwidth
, 0, XmNresizable
, False
,
503 XmNtraversalOn
, False
, NULL
);
504 scroller
= XtNameToWidget(tabLine
, "MinorTabScrollerPrevious");
505 XtVaSetValues(scroller
, XmNwidth
, 0, XmNresizable
, False
,
506 XmNtraversalOn
, False
, NULL
);
508 /* Create the tabline popup menu */
509 tabLine_menu
= XmCreatePopupMenu(tabLine
, "tabline popup", NULL
, 0);
511 /* Add the buttons to the menu */
513 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_CLOSE
); n
++;
514 xms
= XmStringCreate((char *)"Close tab", STRING_TAG
);
515 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
516 button
= XmCreatePushButton(tabLine_menu
, "Close", args
, n
);
517 XtAddCallback(button
, XmNactivateCallback
,
518 (XtCallbackProc
)tabline_button_cb
, NULL
);
522 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_NEW
); n
++;
523 xms
= XmStringCreate((char *)"New Tab", STRING_TAG
);
524 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
525 button
= XmCreatePushButton(tabLine_menu
, "New Tab", args
, n
);
526 XtAddCallback(button
, XmNactivateCallback
,
527 (XtCallbackProc
)tabline_button_cb
, NULL
);
531 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_OPEN
); n
++;
532 xms
= XmStringCreate((char *)"Open tab...", STRING_TAG
);
533 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
534 button
= XmCreatePushButton(tabLine_menu
, "Open tab...", args
, n
);
535 XtAddCallback(button
, XmNactivateCallback
,
536 (XtCallbackProc
)tabline_button_cb
, NULL
);
540 textAreaForm
= XtVaCreateManagedWidget("textAreaForm",
541 xmFormWidgetClass
, vimForm
,
542 XmNleftAttachment
, XmATTACH_FORM
,
543 XmNrightAttachment
, XmATTACH_FORM
,
544 XmNbottomAttachment
, XmATTACH_FORM
,
545 XmNtopAttachment
, XmATTACH_FORM
,
548 XmNresizePolicy
, XmRESIZE_ANY
,
550 gui_motif_scroll_colors(textAreaForm
);
552 textArea
= XtVaCreateManagedWidget("textArea",
553 xmDrawingAreaWidgetClass
, textAreaForm
,
554 XmNforeground
, gui
.norm_pixel
,
555 XmNbackground
, gui
.back_pixel
,
556 XmNleftAttachment
, XmATTACH_FORM
,
557 XmNtopAttachment
, XmATTACH_FORM
,
558 XmNrightAttachment
, XmATTACH_FORM
,
559 XmNbottomAttachment
, XmATTACH_FORM
,
562 * These take some control away from the user, but avoids making them
563 * add resources to get a decent looking setup.
566 XmNhighlightThickness
, 0,
567 XmNshadowThickness
, 0,
574 footer
= XtVaCreateWidget("footer",
575 xmLabelGadgetClass
, vimForm
,
576 XmNalignment
, XmALIGNMENT_BEGINNING
,
579 XmNtraversalOn
, False
,
580 XmNrecomputeSize
, False
,
581 XmNleftAttachment
, XmATTACH_FORM
,
583 XmNrightAttachment
, XmATTACH_FORM
,
584 XmNbottomAttachment
, XmATTACH_FORM
,
586 gui_mch_set_footer((char_u
*) "");
590 * Install the callbacks.
592 gui_x11_callbacks(textArea
, vimForm
);
594 /* Pretend we don't have input focus, we will get an event if we do. */
595 gui
.in_focus
= FALSE
;
599 * Called when the GUI is not going to start after all.
602 gui_x11_destroy_widgets()
612 gui_mch_set_text_area_pos(x
, y
, w
, h
)
619 /* Give keyboard focus to the textArea instead of the toolbar. */
625 gui_x11_set_back_color()
627 if (textArea
!= NULL
)
628 #if (XmVersion >= 1002)
629 XmChangeColor(textArea
, gui
.back_pixel
);
631 XtVaSetValues(textArea
,
632 XmNbackground
, gui
.back_pixel
,
638 * Manage dialog centered on pointer. This could be used by the Athena code as
642 manage_centered(dialog_child
)
645 Widget shell
= XtParent(dialog_child
);
648 unsigned int width
, height
, border_width
, depth
;
649 int x
, y
, win_x
, win_y
, maxX
, maxY
;
650 Boolean mappedWhenManaged
;
652 /* Temporarily set value of XmNmappedWhenManaged
653 to stop the dialog from popping up right away */
654 XtVaGetValues(shell
, XmNmappedWhenManaged
, &mappedWhenManaged
, 0);
655 XtVaSetValues(shell
, XmNmappedWhenManaged
, False
, 0);
657 XtManageChild(dialog_child
);
659 /* Get the pointer position (x, y) */
660 XQueryPointer(XtDisplay(shell
), XtWindow(shell
), &root
, &child
,
661 &x
, &y
, &win_x
, &win_y
, &mask
);
663 /* Translate the pointer position (x, y) into a position for the new
664 window that will place the pointer at its center */
665 XGetGeometry(XtDisplay(shell
), XtWindow(shell
), &root
, &win_x
, &win_y
,
666 &width
, &height
, &border_width
, &depth
);
667 width
+= 2 * border_width
;
668 height
+= 2 * border_width
;
672 /* Ensure that the dialog remains on screen */
673 maxX
= XtScreen(shell
)->width
- width
;
674 maxY
= XtScreen(shell
)->height
- height
;
684 /* Set desired window position in the DialogShell */
685 XtVaSetValues(shell
, XmNx
, x
, XmNy
, y
, NULL
);
690 /* Restore the value of XmNmappedWhenManaged */
691 XtVaSetValues(shell
, XmNmappedWhenManaged
, mappedWhenManaged
, 0);
694 #if defined(FEAT_MENU) || defined(FEAT_SUN_WORKSHOP) \
695 || defined(FEAT_GUI_DIALOG) || defined(PROTO)
698 * Encapsulate the way an XmFontList is created.
701 gui_motif_create_fontlist(font
)
704 XmFontList font_list
;
706 # if (XmVersion <= 1001)
707 /* Motif 1.1 method */
708 font_list
= XmFontListCreate(font
, STRING_TAG
);
710 /* Motif 1.2 method */
711 XmFontListEntry font_list_entry
;
713 font_list_entry
= XmFontListEntryCreate(STRING_TAG
, XmFONT_IS_FONT
,
715 font_list
= XmFontListAppendEntry(NULL
, font_list_entry
);
716 XmFontListEntryFree(&font_list_entry
);
721 # if ((XmVersion > 1001) && defined(FEAT_XFONTSET)) || defined(PROTO)
723 gui_motif_fontset2fontlist(fontset
)
726 XmFontList font_list
;
728 /* Motif 1.2 method */
729 XmFontListEntry font_list_entry
;
731 font_list_entry
= XmFontListEntryCreate(STRING_TAG
,
733 (XtPointer
)*fontset
);
734 font_list
= XmFontListAppendEntry(NULL
, font_list_entry
);
735 XmFontListEntryFree(&font_list_entry
);
742 #if defined(FEAT_MENU) || defined(PROTO)
747 static void gui_motif_add_actext
__ARGS((vimmenu_T
*menu
));
748 #if (XmVersion >= 1002)
749 static void toggle_tearoff
__ARGS((Widget wid
));
750 static void gui_mch_recurse_tearoffs
__ARGS((vimmenu_T
*menu
));
752 static void submenu_change
__ARGS((vimmenu_T
*mp
, int colors
));
754 static void do_set_mnemonics
__ARGS((int enable
));
755 static int menu_enabled
= TRUE
;
758 gui_mch_enable_menu(flag
)
763 XtManageChild(menuBar
);
765 if (XtIsManaged(XtParent(toolBar
)))
767 /* toolBar is attached to top form */
768 XtVaSetValues(XtParent(toolBar
),
769 XmNtopAttachment
, XmATTACH_WIDGET
,
770 XmNtopWidget
, menuBar
,
772 #ifdef FEAT_GUI_TABLINE
775 XtVaSetValues(tabLine
,
776 XmNtopAttachment
, XmATTACH_WIDGET
,
777 XmNtopWidget
, XtParent(toolBar
),
779 XtVaSetValues(textAreaForm
,
780 XmNtopAttachment
, XmATTACH_WIDGET
,
781 XmNtopWidget
, tabLine
,
786 XtVaSetValues(textAreaForm
,
787 XmNtopAttachment
, XmATTACH_WIDGET
,
788 XmNtopWidget
, XtParent(toolBar
),
794 #ifdef FEAT_GUI_TABLINE
797 XtVaSetValues(tabLine
,
798 XmNtopAttachment
, XmATTACH_WIDGET
,
799 XmNtopWidget
, menuBar
,
801 XtVaSetValues(textAreaForm
,
802 XmNtopAttachment
, XmATTACH_WIDGET
,
803 XmNtopWidget
, tabLine
,
808 XtVaSetValues(textAreaForm
,
809 XmNtopAttachment
, XmATTACH_WIDGET
,
810 XmNtopWidget
, menuBar
,
816 XtUnmanageChild(menuBar
);
818 if (XtIsManaged(XtParent(toolBar
)))
820 XtVaSetValues(XtParent(toolBar
),
821 XmNtopAttachment
, XmATTACH_FORM
,
823 #ifdef FEAT_GUI_TABLINE
826 XtVaSetValues(tabLine
,
827 XmNtopAttachment
, XmATTACH_WIDGET
,
828 XmNtopWidget
, XtParent(toolBar
),
830 XtVaSetValues(textAreaForm
,
831 XmNtopAttachment
, XmATTACH_WIDGET
,
832 XmNtopWidget
, tabLine
,
837 XtVaSetValues(textAreaForm
,
838 XmNtopAttachment
, XmATTACH_WIDGET
,
839 XmNtopWidget
, XtParent(toolBar
),
845 #ifdef FEAT_GUI_TABLINE
848 XtVaSetValues(tabLine
,
849 XmNtopAttachment
, XmATTACH_FORM
,
851 XtVaSetValues(textAreaForm
,
852 XmNtopAttachment
, XmATTACH_WIDGET
,
853 XmNtopWidget
, tabLine
,
858 XtVaSetValues(textAreaForm
,
859 XmNtopAttachment
, XmATTACH_FORM
,
867 * Enable or disable mnemonics for the toplevel menus.
870 gui_motif_set_mnemonics(enable
)
874 * Don't enable menu mnemonics when the menu bar is disabled, LessTif
875 * crashes when using a mnemonic then.
879 do_set_mnemonics(enable
);
883 do_set_mnemonics(enable
)
888 for (menu
= root_menu
; menu
!= NULL
; menu
= menu
->next
)
889 if (menu
->id
!= (Widget
)0)
890 XtVaSetValues(menu
->id
,
891 XmNmnemonic
, enable
? menu
->mnemonic
: NUL
,
896 gui_mch_add_menu(menu
, idx
)
902 vimmenu_T
*parent
= menu
->parent
;
905 if (menu_is_popup(menu
->name
))
910 /* Only create the popup menu when it's actually used, otherwise there
911 * is a delay when using the right mouse button. */
912 # if (XmVersion <= 1002)
913 if (mouse_model_popup())
916 if (gui
.menu_bg_pixel
!= INVALCOLOR
)
918 XtSetArg(arg
[0], XmNbackground
, gui
.menu_bg_pixel
); n
++;
920 if (gui
.menu_fg_pixel
!= INVALCOLOR
)
922 XtSetArg(arg
[1], XmNforeground
, gui
.menu_fg_pixel
); n
++;
924 menu
->submenu_id
= XmCreatePopupMenu(textArea
, "contextMenu",
926 menu
->id
= (Widget
)0;
932 if (!menu_is_menubar(menu
->name
)
933 || (parent
!= NULL
&& parent
->submenu_id
== (Widget
)0))
936 label
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
939 menu
->id
= XtVaCreateWidget("subMenu",
940 xmCascadeButtonWidgetClass
,
941 (parent
== NULL
) ? menuBar
: parent
->submenu_id
,
942 XmNlabelString
, label
,
943 XmNmnemonic
, p_wak
[0] == 'n' ? NUL
: menu
->mnemonic
,
944 #if (XmVersion >= 1002)
945 /* submenu: count the tearoff item (needed for LessTif) */
946 XmNpositionIndex
, idx
+ (parent
!= NULL
947 && tearoff_val
== (int)XmTEAR_OFF_ENABLED
? 1 : 0),
950 gui_motif_menu_colors(menu
->id
);
951 gui_motif_menu_fontlist(menu
->id
);
954 if (menu
->id
== (Widget
)0) /* failed */
957 /* add accelerator text */
958 gui_motif_add_actext(menu
);
960 shell
= XtVaCreateWidget("subMenuShell",
961 xmMenuShellWidgetClass
, menu
->id
,
965 gui_motif_menu_colors(shell
);
966 menu
->submenu_id
= XtVaCreateWidget("rowColumnMenu",
967 xmRowColumnWidgetClass
, shell
,
968 XmNrowColumnType
, XmMENU_PULLDOWN
,
970 gui_motif_menu_colors(menu
->submenu_id
);
972 if (menu
->submenu_id
== (Widget
)0) /* failed */
975 #if (XmVersion >= 1002)
976 /* Set the colors for the tear off widget */
977 toggle_tearoff(menu
->submenu_id
);
980 XtVaSetValues(menu
->id
,
981 XmNsubMenuId
, menu
->submenu_id
,
985 * The "Help" menu is a special case, and should be placed at the far
986 * right hand side of the menu-bar. It's recognized by its high priority.
988 if (parent
== NULL
&& menu
->priority
>= 9999)
989 XtVaSetValues(menuBar
,
990 XmNmenuHelpWidget
, menu
->id
,
994 * When we add a top-level item to the menu bar, we can figure out how
995 * high the menu bar should be.
998 gui_mch_compute_menu_height(menu
->id
);
1003 * Add mnemonic and accelerator text to a menu button.
1006 gui_motif_add_actext(menu
)
1011 /* Add accelrator text, if there is one */
1012 if (menu
->actext
!= NULL
&& menu
->id
!= (Widget
)0)
1014 label
= XmStringCreate((char *)menu
->actext
, STRING_TAG
);
1017 XtVaSetValues(menu
->id
, XmNacceleratorText
, label
, NULL
);
1018 XmStringFree(label
);
1023 gui_mch_toggle_tearoffs(enable
)
1026 #if (XmVersion >= 1002)
1028 tearoff_val
= (int)XmTEAR_OFF_ENABLED
;
1030 tearoff_val
= (int)XmTEAR_OFF_DISABLED
;
1031 toggle_tearoff(menuBar
);
1032 gui_mch_recurse_tearoffs(root_menu
);
1036 #if (XmVersion >= 1002)
1038 * Set the tearoff for one menu widget on or off, and set the color of the
1047 XtVaSetValues(wid
, XmNtearOffModel
, tearoff_val
, NULL
);
1048 if (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1049 && (w
= XmGetTearOffControl(wid
)) != (Widget
)0)
1050 gui_motif_menu_colors(w
);
1054 gui_mch_recurse_tearoffs(menu
)
1057 while (menu
!= NULL
)
1059 if (!menu_is_popup(menu
->name
))
1061 if (menu
->submenu_id
!= (Widget
)0)
1062 toggle_tearoff(menu
->submenu_id
);
1063 gui_mch_recurse_tearoffs(menu
->children
);
1071 gui_mch_text_area_extra_height()
1073 Dimension shadowHeight
;
1075 XtVaGetValues(textAreaForm
, XmNshadowThickness
, &shadowHeight
, NULL
);
1076 return shadowHeight
;
1080 * Compute the height of the menu bar.
1081 * We need to check all the items for their position and height, for the case
1082 * there are several rows, and/or some characters extend higher or lower.
1085 gui_mch_compute_menu_height(id
)
1086 Widget id
; /* can be NULL when deleting menu */
1089 Dimension margin
, shadow
;
1091 static Dimension height
= 21; /* normal height of a menu item */
1094 * Get the height of the new item, before managing it, because it will
1095 * still reflect the font size. After managing it depends on the menu
1096 * height, which is what we just wanted to get!.
1098 if (id
!= (Widget
)0)
1099 XtVaGetValues(id
, XmNheight
, &height
, NULL
);
1101 /* Find any menu Widget, to be able to call XtManageChild() */
1103 for (mp
= root_menu
; mp
!= NULL
; mp
= mp
->next
)
1104 if (mp
->id
!= (Widget
)0 && menu_is_menubar(mp
->name
))
1111 * Now manage the menu item, to make them all be positioned (makes an
1112 * extra row when needed, removes it when not needed).
1114 if (id
!= (Widget
)0)
1118 * Now find the menu item that is the furthest down, and get it's position.
1121 for (mp
= root_menu
; mp
!= NULL
; mp
= mp
->next
)
1123 if (mp
->id
!= (Widget
)0 && menu_is_menubar(mp
->name
))
1125 XtVaGetValues(mp
->id
, XmNy
, &y
, NULL
);
1131 XtVaGetValues(menuBar
,
1132 XmNmarginHeight
, &margin
,
1133 XmNshadowThickness
, &shadow
,
1137 * This computation is the result of trial-and-error:
1138 * maxy = The maximum position of an item; required for when there are
1140 * height = height of an item, before managing it; Hopefully this will
1141 * change with the font height. Includes shadow-border.
1142 * shadow = shadow-border; must be subtracted from the height.
1143 * margin = margin around the menu buttons; Must be added.
1144 * Add 4 for the underlining of shortcut keys.
1146 gui
.menu_height
= maxy
+ height
- 2 * shadow
+ 2 * margin
+ 4;
1148 /* Somehow the menu bar doesn't resize automatically. Set it here,
1149 * even though this is a catch 22. Don't do this when starting up,
1150 * somehow the menu gets very high then. */
1151 if (gui
.shell_created
)
1152 XtVaSetValues(menuBar
, XmNheight
, gui
.menu_height
, NULL
);
1158 * Icons used by the toolbar code.
1160 #include "gui_x11_pm.h"
1162 static int check_xpm
__ARGS((char_u
*path
));
1163 static char **get_toolbar_pixmap
__ARGS((vimmenu_T
*menu
, char **fname
));
1164 static int add_pixmap_args
__ARGS((vimmenu_T
*menu
, Arg
*args
, int n
));
1167 * Read an Xpm file. Return OK or FAIL.
1173 XpmAttributes attrs
;
1178 attrs
.valuemask
= 0;
1180 /* Create the "sensitive" pixmap */
1181 status
= XpmReadFileToPixmap(gui
.dpy
,
1182 RootWindow(gui
.dpy
, DefaultScreen(gui
.dpy
)),
1183 (char *)path
, &map
, &mask
, &attrs
);
1184 XpmFreeAttributes(&attrs
);
1186 if (status
== XpmSuccess
)
1193 * Allocated a pixmap for toolbar menu "menu".
1194 * When it's to be read from a file, "fname" is set to the file name
1195 * (in allocated memory).
1196 * Return a blank pixmap if it fails.
1199 get_toolbar_pixmap(menu
, fname
)
1203 char_u buf
[MAXPATHL
]; /* buffer storing expanded pathname */
1204 char **xpm
= NULL
; /* xpm array */
1208 buf
[0] = NUL
; /* start with NULL path */
1210 if (menu
->iconfile
!= NULL
)
1212 /* Use the "icon=" argument. */
1213 gui_find_iconfile(menu
->iconfile
, buf
, "xpm");
1214 res
= check_xpm(buf
);
1216 /* If it failed, try using the menu name. */
1217 if (res
== FAIL
&& gui_find_bitmap(menu
->name
, buf
, "xpm") == OK
)
1218 res
= check_xpm(buf
);
1221 *fname
= (char *)vim_strsave(buf
);
1222 return tb_blank_xpm
;
1226 if (menu
->icon_builtin
|| gui_find_bitmap(menu
->name
, buf
, "xpm") == FAIL
)
1228 if (menu
->iconidx
>= 0 && menu
->iconidx
1229 < (sizeof(built_in_pixmaps
) / sizeof(built_in_pixmaps
[0])))
1230 xpm
= built_in_pixmaps
[menu
->iconidx
];
1239 * Add arguments for the toolbar pixmap to a menu item.
1242 add_pixmap_args(menu
, args
, n
)
1247 vim_free(menu
->xpm_fname
);
1248 menu
->xpm
= get_toolbar_pixmap(menu
, &menu
->xpm_fname
);
1249 if (menu
->xpm
== NULL
)
1251 XtSetArg(args
[n
], XmNlabelType
, XmSTRING
); n
++;
1255 if (menu
->xpm_fname
!= NULL
)
1257 XtSetArg(args
[n
], XmNpixmapFile
, menu
->xpm_fname
); n
++;
1259 XtSetArg(args
[n
], XmNpixmapData
, menu
->xpm
); n
++;
1260 XtSetArg(args
[n
], XmNlabelLocation
, XmBOTTOM
); n
++;
1264 #endif /* FEAT_TOOLBAR */
1267 gui_mch_add_menu_item(menu
, idx
)
1272 vimmenu_T
*parent
= menu
->parent
;
1278 # if (XmVersion <= 1002)
1279 /* Don't add Popup menu items when the popup menu isn't used. */
1280 if (menu_is_child_of_popup(menu
) && !mouse_model_popup())
1284 # ifdef FEAT_TOOLBAR
1285 if (menu_is_toolbar(parent
->name
))
1288 XmString xms
= NULL
; /* fallback label if pixmap not found */
1293 if (menu_is_separator(menu
->name
))
1299 * A separator has the format "-sep%d[:%d]-". The optional :%d is
1300 * a width specifier. If no width is specified then we choose one.
1302 cp
= (char *)vim_strchr(menu
->name
, ':');
1304 wid
= (Dimension
)atoi(++cp
);
1309 /* We better use a FormWidget here, since it's far more
1310 * flexible in terms of size. */
1311 type
= xmFormWidgetClass
;
1312 XtSetArg(args
[n
], XmNwidth
, wid
); n
++;
1314 type
= xmSeparatorWidgetClass
;
1315 XtSetArg(args
[n
], XmNwidth
, wid
); n
++;
1316 XtSetArg(args
[n
], XmNminWidth
, wid
); n
++;
1317 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
1318 XtSetArg(args
[n
], XmNseparatorType
, XmSHADOW_ETCHED_IN
); n
++;
1323 /* Without shadows one can't sense whatever the button has been
1324 * pressed or not! However we wan't to save a bit of space...
1325 * Need the highlightThickness to see the focus.
1327 XtSetArg(args
[n
], XmNhighlightThickness
, 1); n
++;
1328 XtSetArg(args
[n
], XmNhighlightOnEnter
, True
); n
++;
1329 XtSetArg(args
[n
], XmNmarginWidth
, 0); n
++;
1330 XtSetArg(args
[n
], XmNmarginHeight
, 0); n
++;
1331 XtSetArg(args
[n
], XmNtraversalOn
, False
); n
++;
1332 /* Set the label here, so that we can switch between icons/text
1333 * by changing the XmNlabelType resource. */
1334 xms
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
1335 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
1337 n
= add_pixmap_args(menu
, args
, n
);
1339 type
= xmEnhancedButtonWidgetClass
;
1342 XtSetArg(args
[n
], XmNpositionIndex
, idx
); n
++;
1343 if (menu
->id
== NULL
)
1345 menu
->id
= XtCreateManagedWidget((char *)menu
->dname
,
1346 type
, toolBar
, args
, n
);
1347 if (menu
->id
!= NULL
&& type
== xmEnhancedButtonWidgetClass
)
1349 XtAddCallback(menu
->id
,
1350 XmNactivateCallback
, gui_x11_menu_cb
, menu
);
1352 XtAddEventHandler(menu
->id
, EnterWindowMask
, False
,
1353 toolbarbutton_enter_cb
, menu
);
1354 XtAddEventHandler(menu
->id
, LeaveWindowMask
, False
,
1355 toolbarbutton_leave_cb
, menu
);
1360 XtSetValues(menu
->id
, args
, n
);
1365 gui_mch_menu_set_tip(menu
);
1368 menu
->parent
= parent
;
1369 menu
->submenu_id
= NULL
;
1370 /* When adding first item to toolbar it might have to be enabled .*/
1371 if (!XtIsManaged(XtParent(toolBar
))
1372 && vim_strchr(p_go
, GO_TOOLBAR
) != NULL
)
1373 gui_mch_show_toolbar(TRUE
);
1374 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
1376 } /* toolbar menu item */
1379 /* No parent, must be a non-menubar menu */
1380 if (parent
->submenu_id
== (Widget
)0)
1383 menu
->submenu_id
= (Widget
)0;
1385 /* Add menu separator */
1386 if (menu_is_separator(menu
->name
))
1388 menu
->id
= XtVaCreateWidget("subMenu",
1389 xmSeparatorGadgetClass
, parent
->submenu_id
,
1390 #if (XmVersion >= 1002)
1391 /* count the tearoff item (needed for LessTif) */
1392 XmNpositionIndex
, idx
+ (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1396 gui_motif_menu_colors(menu
->id
);
1400 label
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
1403 menu
->id
= XtVaCreateWidget("subMenu",
1404 xmPushButtonWidgetClass
, parent
->submenu_id
,
1405 XmNlabelString
, label
,
1406 XmNmnemonic
, menu
->mnemonic
,
1407 #if (XmVersion >= 1002)
1408 /* count the tearoff item (needed for LessTif) */
1409 XmNpositionIndex
, idx
+ (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1413 gui_motif_menu_colors(menu
->id
);
1414 gui_motif_menu_fontlist(menu
->id
);
1415 XmStringFree(label
);
1417 if (menu
->id
!= (Widget
)0)
1419 XtAddCallback(menu
->id
, XmNactivateCallback
, gui_x11_menu_cb
,
1421 /* add accelerator text */
1422 gui_motif_add_actext(menu
);
1426 #if (XmVersion <= 1002) || defined(PROTO)
1428 * This function will destroy/create the popup menus dynamically,
1429 * according to the value of 'mousemodel'.
1430 * This will fix the "right mouse button freeze" that occurs when
1431 * there exists a popup menu but it isn't managed.
1434 gui_motif_update_mousemodel(menu
)
1439 /* When GUI hasn't started the menus have not been created. */
1445 if (menu
->children
!= NULL
)
1447 if (menu_is_popup(menu
->name
))
1449 if (mouse_model_popup())
1451 /* Popup menu will be used. Create the popup menus. */
1452 gui_mch_add_menu(menu
, idx
);
1453 gui_motif_update_mousemodel(menu
->children
);
1457 /* Popup menu will not be used. Destroy the popup menus. */
1458 gui_motif_update_mousemodel(menu
->children
);
1459 gui_mch_destroy_menu(menu
);
1463 else if (menu_is_child_of_popup(menu
))
1465 if (mouse_model_popup())
1466 gui_mch_add_menu_item(menu
, idx
);
1468 gui_mch_destroy_menu(menu
);
1477 gui_mch_new_menu_colors()
1479 if (menuBar
== (Widget
)0)
1481 gui_motif_menu_colors(menuBar
);
1483 gui_motif_menu_colors(toolBarFrame
);
1484 gui_motif_menu_colors(toolBar
);
1487 submenu_change(root_menu
, TRUE
);
1491 gui_mch_new_menu_font()
1493 if (menuBar
== (Widget
)0)
1495 submenu_change(root_menu
, FALSE
);
1500 XtVaGetValues(menuBar
, XmNheight
, &height
, NULL
);
1501 gui
.menu_height
= height
;
1503 XtVaGetValues(vimShell
, XtNwidth
, &w
, XtNheight
, &h
, NULL
);
1504 gui_resize_shell(w
, h
1506 - xim_get_status_area_height()
1510 gui_set_shellsize(FALSE
, TRUE
, RESIZE_VERT
);
1514 #if defined(FEAT_BEVAL) || defined(PROTO)
1516 gui_mch_new_tooltip_font()
1518 # ifdef FEAT_TOOLBAR
1521 if (toolBar
== (Widget
)0)
1524 menu
= gui_find_menu((char_u
*)"ToolBar");
1526 submenu_change(menu
, FALSE
);
1531 gui_mch_new_tooltip_colors()
1533 # ifdef FEAT_TOOLBAR
1536 if (toolBar
== (Widget
)0)
1539 toolbar
= gui_find_menu((char_u
*)"ToolBar");
1540 if (toolbar
!= NULL
)
1541 submenu_change(toolbar
, TRUE
);
1547 submenu_change(menu
, colors
)
1549 int colors
; /* TRUE for colors, FALSE for font */
1553 for (mp
= menu
; mp
!= NULL
; mp
= mp
->next
)
1555 if (mp
->id
!= (Widget
)0)
1559 gui_motif_menu_colors(mp
->id
);
1561 /* For a toolbar item: Free the pixmap and allocate a new one,
1562 * so that the background color is right. */
1563 if (mp
->xpm
!= NULL
)
1568 n
= add_pixmap_args(mp
, args
, n
);
1569 XtSetValues(mp
->id
, args
, n
);
1572 /* If we have a tooltip, then we need to change it's font */
1573 if (mp
->tip
!= NULL
)
1577 args
[0].name
= XmNbackground
;
1578 args
[0].value
= gui
.tooltip_bg_pixel
;
1579 args
[1].name
= XmNforeground
;
1580 args
[1].value
= gui
.tooltip_fg_pixel
;
1581 XtSetValues(mp
->tip
->balloonLabel
, &args
[0], XtNumber(args
));
1588 gui_motif_menu_fontlist(mp
->id
);
1590 /* If we have a tooltip, then we need to change it's font */
1591 if (mp
->tip
!= NULL
)
1595 args
[0].name
= XmNfontList
;
1596 args
[0].value
= (XtArgVal
)gui_motif_fontset2fontlist(
1597 &gui
.tooltip_fontset
);
1598 XtSetValues(mp
->tip
->balloonLabel
, &args
[0], XtNumber(args
));
1604 if (mp
->children
!= NULL
)
1606 #if (XmVersion >= 1002)
1607 /* Set the colors/font for the tear off widget */
1608 if (mp
->submenu_id
!= (Widget
)0)
1611 gui_motif_menu_colors(mp
->submenu_id
);
1613 gui_motif_menu_fontlist(mp
->submenu_id
);
1614 toggle_tearoff(mp
->submenu_id
);
1617 /* Set the colors for the children */
1618 submenu_change(mp
->children
, colors
);
1624 * Destroy the machine specific menu widget.
1627 gui_mch_destroy_menu(menu
)
1630 /* Please be sure to destroy the parent widget first (i.e. menu->id).
1631 * On the other hand, problems have been reported that the submenu must be
1634 * This code should be basically identical to that in the file gui_athena.c
1635 * because they are both Xt based.
1637 if (menu
->submenu_id
!= (Widget
)0)
1639 XtDestroyWidget(menu
->submenu_id
);
1640 menu
->submenu_id
= (Widget
)0;
1643 if (menu
->id
!= (Widget
)0)
1647 parent
= XtParent(menu
->id
);
1648 #if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL)
1649 if (parent
== toolBar
&& menu
->tip
!= NULL
)
1651 /* We try to destroy this before the actual menu, because there are
1652 * callbacks, etc. that will be unregistered during the tooltip
1655 * If you call "gui_mch_destroy_beval_area()" after destroying
1656 * menu->id, then the tooltip's window will have already been
1657 * deallocated by Xt, and unknown behaviour will ensue (probably
1660 gui_mch_destroy_beval_area(menu
->tip
);
1664 XtDestroyWidget(menu
->id
);
1665 menu
->id
= (Widget
)0;
1666 if (parent
== menuBar
)
1667 gui_mch_compute_menu_height((Widget
)0);
1669 else if (parent
== toolBar
)
1671 Cardinal num_children
;
1673 /* When removing last toolbar item, don't display the toolbar. */
1674 XtVaGetValues(toolBar
, XmNnumChildren
, &num_children
, NULL
);
1675 if (num_children
== 0)
1676 gui_mch_show_toolbar(FALSE
);
1678 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
1686 gui_mch_show_popupmenu(menu
)
1690 XmMenuPosition(menu
->submenu_id
, gui_x11_get_last_mouse_event());
1691 XtManageChild(menu
->submenu_id
);
1695 #endif /* FEAT_MENU */
1698 * Set the menu and scrollbar colors to their default values.
1701 gui_mch_def_colors()
1705 /* Use the values saved when starting up. These should come from the
1706 * window manager or a resources file. */
1707 gui
.menu_fg_pixel
= gui
.menu_def_fg_pixel
;
1708 gui
.menu_bg_pixel
= gui
.menu_def_bg_pixel
;
1709 gui
.scroll_fg_pixel
= gui
.scroll_def_fg_pixel
;
1710 gui
.scroll_bg_pixel
= gui
.scroll_def_bg_pixel
;
1712 gui
.tooltip_fg_pixel
=
1713 gui_get_color((char_u
*)gui
.rsrc_tooltip_fg_name
);
1714 gui
.tooltip_bg_pixel
=
1715 gui_get_color((char_u
*)gui
.rsrc_tooltip_bg_name
);
1726 gui_mch_set_scrollbar_thumb(sb
, val
, size
, max
)
1732 if (sb
->id
!= (Widget
)0)
1733 XtVaSetValues(sb
->id
,
1735 XmNsliderSize
, size
,
1736 XmNpageIncrement
, (size
> 2 ? size
- 2 : 1),
1737 XmNmaximum
, max
+ 1, /* Motif has max one past the end */
1742 gui_mch_set_scrollbar_pos(sb
, x
, y
, w
, h
)
1749 if (sb
->id
!= (Widget
)0)
1751 if (sb
->type
== SBAR_LEFT
|| sb
->type
== SBAR_RIGHT
)
1754 h
-= gui
.border_offset
;
1756 y
-= gui
.border_offset
;
1757 XtVaSetValues(sb
->id
,
1759 XmNbottomOffset
, -y
- h
,
1764 XtVaSetValues(sb
->id
,
1767 XmNrightOffset
, gui
.which_scrollbars
[SBAR_RIGHT
]
1768 ? gui
.scrollbar_width
: 0,
1771 XtManageChild(sb
->id
);
1776 gui_mch_enable_scrollbar(sb
, flag
)
1783 if (sb
->id
!= (Widget
)0)
1791 XtSetArg(args
[n
], XmNleftOffset
, gui
.scrollbar_width
); n
++;
1795 XtSetArg(args
[n
], XmNrightOffset
, gui
.scrollbar_width
); n
++;
1799 XtSetArg(args
[n
], XmNbottomOffset
, gui
.scrollbar_height
);n
++;
1802 XtSetValues(textArea
, args
, n
);
1803 XtManageChild(sb
->id
);
1807 if (!gui
.which_scrollbars
[sb
->type
])
1809 /* The scrollbars of this type are all disabled, adjust the
1810 * textArea attachment offset. */
1814 XtSetArg(args
[n
], XmNleftOffset
, 0); n
++;
1818 XtSetArg(args
[n
], XmNrightOffset
, 0); n
++;
1822 XtSetArg(args
[n
], XmNbottomOffset
, 0);n
++;
1825 XtSetValues(textArea
, args
, n
);
1827 XtUnmanageChild(sb
->id
);
1833 gui_mch_create_scrollbar(sb
, orient
)
1835 int orient
; /* SBAR_VERT or SBAR_HORIZ */
1841 XtSetArg(args
[n
], XmNminimum
, 0); n
++;
1842 XtSetArg(args
[n
], XmNorientation
,
1843 (orient
== SBAR_VERT
) ? XmVERTICAL
: XmHORIZONTAL
); n
++;
1848 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
1849 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_OPPOSITE_FORM
); n
++;
1850 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
1854 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
1855 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_OPPOSITE_FORM
); n
++;
1856 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
1860 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
1861 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
1862 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
1866 sb
->id
= XtCreateWidget("scrollBar",
1867 xmScrollBarWidgetClass
, textAreaForm
, args
, n
);
1869 /* Remember the default colors, needed for ":hi clear". */
1870 if (gui
.scroll_def_bg_pixel
== (guicolor_T
)0
1871 && gui
.scroll_def_fg_pixel
== (guicolor_T
)0)
1872 XtVaGetValues(sb
->id
,
1873 XmNbackground
, &gui
.scroll_def_bg_pixel
,
1874 XmNforeground
, &gui
.scroll_def_fg_pixel
,
1877 if (sb
->id
!= (Widget
)0)
1879 gui_mch_set_scrollbar_colors(sb
);
1880 XtAddCallback(sb
->id
, XmNvalueChangedCallback
,
1881 scroll_cb
, (XtPointer
)sb
->ident
);
1882 XtAddCallback(sb
->id
, XmNdragCallback
,
1883 scroll_cb
, (XtPointer
)sb
->ident
);
1884 XtAddEventHandler(sb
->id
, KeyPressMask
, FALSE
, gui_x11_key_hit_cb
,
1889 #if defined(FEAT_WINDOWS) || defined(PROTO)
1891 gui_mch_destroy_scrollbar(sb
)
1894 if (sb
->id
!= (Widget
)0)
1895 XtDestroyWidget(sb
->id
);
1900 gui_mch_set_scrollbar_colors(sb
)
1903 if (sb
->id
!= (Widget
)0)
1905 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
1907 #if (XmVersion>=1002)
1908 XmChangeColor(sb
->id
, gui
.scroll_bg_pixel
);
1910 XtVaSetValues(sb
->id
,
1911 XmNtroughColor
, gui
.scroll_bg_pixel
,
1916 if (gui
.scroll_fg_pixel
!= INVALCOLOR
)
1917 XtVaSetValues(sb
->id
,
1918 XmNforeground
, gui
.scroll_fg_pixel
,
1919 #if (XmVersion<1002)
1920 XmNbackground
, gui
.scroll_fg_pixel
,
1925 /* This is needed for the rectangle below the vertical scrollbars. */
1926 if (sb
== &gui
.bottom_sbar
&& textAreaForm
!= (Widget
)0)
1927 gui_motif_scroll_colors(textAreaForm
);
1931 * Miscellaneous stuff:
1937 return(XtWindow(textArea
));
1941 * Look for a widget in the widget tree w, with a mnemonic matching keycode.
1942 * When one is found, simulate a button press on that widget and give it the
1943 * keyboard focus. If the mnemonic is on a label, look in the userData field
1944 * of the label to see if it points to another widget, and give that the focus.
1947 do_mnemonic(Widget w
, unsigned int keycode
)
1949 WidgetList children
;
1952 KeySym mnemonic
= '\0';
1955 unsigned char rowColType
;
1957 if (XtIsComposite(w
))
1959 if (XtClass(w
) == xmRowColumnWidgetClass
)
1961 XtVaGetValues(w
, XmNrowColumnType
, &rowColType
, 0);
1962 isMenu
= (rowColType
!= (unsigned char)XmWORK_AREA
);
1968 XtVaGetValues(w
, XmNchildren
, &children
, XmNnumChildren
,
1970 for (i
= 0; i
< numChildren
; i
++)
1971 do_mnemonic(children
[i
], keycode
);
1976 XtVaGetValues(w
, XmNmnemonic
, &mnemonic
, 0);
1977 if (mnemonic
!= '\0')
1979 mneString
[0] = mnemonic
;
1980 mneString
[1] = '\0';
1981 if (XKeysymToKeycode(XtDisplay(XtParent(w
)),
1982 XStringToKeysym(mneString
)) == keycode
)
1984 if (XtClass(w
) == xmLabelWidgetClass
1985 || XtClass(w
) == xmLabelGadgetClass
)
1987 XtVaGetValues(w
, XmNuserData
, &userData
, 0);
1988 if (userData
!= NULL
&& XtIsWidget(userData
))
1989 XmProcessTraversal(userData
, XmTRAVERSE_CURRENT
);
1993 XKeyPressedEvent keyEvent
;
1995 XmProcessTraversal(w
, XmTRAVERSE_CURRENT
);
1997 memset((char *) &keyEvent
, 0, sizeof(XKeyPressedEvent
));
1998 keyEvent
.type
= KeyPress
;
1999 keyEvent
.serial
= 1;
2000 keyEvent
.send_event
= True
;
2001 keyEvent
.display
= XtDisplay(w
);
2002 keyEvent
.window
= XtWindow(w
);
2003 XtCallActionProc(w
, "Activate", (XEvent
*) & keyEvent
,
2012 * Callback routine for dialog mnemonic processing.
2016 mnemonic_event(Widget w
, XtPointer call_data
, XKeyEvent
*event
)
2018 do_mnemonic(w
, event
->keycode
);
2023 * Search the widget tree under w for widgets with mnemonics. When found, add
2024 * a passive grab to the dialog widget for the mnemonic character, thus
2025 * directing mnemonic events to the dialog widget.
2028 add_mnemonic_grabs(Widget dialog
, Widget w
)
2031 WidgetList children
;
2034 KeySym mnemonic
= '\0';
2035 unsigned char rowColType
;
2037 if (XtIsComposite(w
))
2039 if (XtClass(w
) == xmRowColumnWidgetClass
)
2041 XtVaGetValues(w
, XmNrowColumnType
, &rowColType
, 0);
2042 isMenu
= (rowColType
!= (unsigned char)XmWORK_AREA
);
2048 XtVaGetValues(w
, XmNchildren
, &children
, XmNnumChildren
,
2050 for (i
= 0; i
< numChildren
; i
++)
2051 add_mnemonic_grabs(dialog
, children
[i
]);
2056 XtVaGetValues(w
, XmNmnemonic
, &mnemonic
, 0);
2057 if (mnemonic
!= '\0')
2059 mneString
[0] = mnemonic
;
2060 mneString
[1] = '\0';
2061 XtGrabKey(dialog
, XKeysymToKeycode(XtDisplay(dialog
),
2062 XStringToKeysym(mneString
)),
2063 Mod1Mask
, True
, GrabModeAsync
, GrabModeAsync
);
2069 * Add a handler for mnemonics in a dialog. Motif itself only handles
2070 * mnemonics in menus. Mnemonics added or changed after this call will be
2073 * To add a mnemonic to a text field or list, set the XmNmnemonic resource on
2074 * the appropriate label and set the XmNuserData resource of the label to the
2075 * widget to get the focus when the mnemonic is typed.
2078 activate_dialog_mnemonics(Widget dialog
)
2083 XtAddEventHandler(dialog
, KeyPressMask
, False
,
2084 (XtEventHandler
) mnemonic_event
, (XtPointer
) NULL
);
2085 add_mnemonic_grabs(dialog
, dialog
);
2089 * Removes the event handler and key-grabs for dialog mnemonic handling.
2092 suppress_dialog_mnemonics(Widget dialog
)
2097 XtUngrabKey(dialog
, AnyKey
, Mod1Mask
);
2098 XtRemoveEventHandler(dialog
, KeyPressMask
, False
,
2099 (XtEventHandler
) mnemonic_event
, (XtPointer
) NULL
);
2102 #if defined(FEAT_BROWSE) || defined(FEAT_GUI_DIALOG)
2103 static void set_fontlist
__ARGS((Widget wg
));
2106 * Use the 'guifont' or 'guifontset' as a fontlist for a dialog widget.
2114 #ifdef FONTSET_ALWAYS
2115 if (gui
.fontset
!= NOFONTSET
)
2117 fl
= gui_motif_fontset2fontlist((XFontSet
*)&gui
.fontset
);
2120 if (XtIsManaged(id
))
2122 XtUnmanageChild(id
);
2123 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2124 /* We should force the widget to recalculate it's
2129 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2134 if (gui
.norm_font
!= NOFONT
)
2136 fl
= gui_motif_create_fontlist((XFontStruct
*)gui
.norm_font
);
2139 if (XtIsManaged(id
))
2141 XtUnmanageChild(id
);
2142 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2143 /* We should force the widget to recalculate it's
2148 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2156 #if defined(FEAT_BROWSE) || defined(PROTO)
2159 * file selector related stuff
2162 #include <Xm/FileSB.h>
2163 #include <Xm/XmStrDefs.h>
2165 typedef struct dialog_callback_arg
2167 char * args
; /* not used right now */
2171 static Widget dialog_wgt
;
2172 static char *browse_fname
= NULL
;
2173 static XmStringCharSet charset
= (XmStringCharSet
) XmSTRING_DEFAULT_CHARSET
;
2174 /* used to set up XmStrings */
2176 static void DialogCancelCB
__ARGS((Widget
, XtPointer
, XtPointer
));
2177 static void DialogAcceptCB
__ARGS((Widget
, XtPointer
, XtPointer
));
2180 * This function is used to translate the predefined label text of the
2181 * precomposed dialogs. We do this explicitly to allow:
2183 * - usage of gettext for translation, as in all the other places.
2185 * - equalize the messages between different GUI implementations as far as
2188 static void set_predefined_label
__ARGS((Widget parent
, String name
, char *new_label
));
2191 set_predefined_label(parent
, name
, new_label
)
2199 KeySym mnemonic
= NUL
;
2201 w
= XtNameToWidget(parent
, name
);
2206 p
= vim_strsave((char_u
*)new_label
);
2209 for (next
= p
; *next
; ++next
)
2211 if (*next
== DLG_HOTKEY_CHAR
)
2213 int len
= STRLEN(next
);
2217 mch_memmove(next
, next
+ 1, len
);
2223 str
= XmStringCreate((char *)p
, STRING_TAG
);
2229 XmNlabelString
, str
,
2230 XmNmnemonic
, mnemonic
,
2234 gui_motif_menu_fontlist(w
);
2238 set_predefined_fontlist(parent
, name
)
2243 w
= XtNameToWidget(parent
, name
);
2252 * Put up a file requester.
2253 * Returns the selected name in allocated memory, or NULL for Cancel.
2257 gui_mch_browse(saving
, title
, dflt
, ext
, initdir
, filter
)
2258 int saving
; /* select file to write */
2259 char_u
*title
; /* title for the window */
2260 char_u
*dflt
; /* default name */
2261 char_u
*ext
; /* not used (extension added) */
2262 char_u
*initdir
; /* initial directory, NULL for current dir */
2263 char_u
*filter
; /* file name filter */
2265 char_u dirbuf
[MAXPATHL
];
2266 char_u dfltbuf
[MAXPATHL
];
2268 char_u
*tofree
= NULL
;
2270 /* There a difference between the resource name and value, Therefore, we
2271 * avoid to (ab-)use the (maybe internationalized!) dialog title as a
2275 dialog_wgt
= XmCreateFileSelectionDialog(vimShell
, "browseDialog", NULL
, 0);
2277 if (initdir
== NULL
|| *initdir
== NUL
)
2279 mch_dirname(dirbuf
, MAXPATHL
);
2284 dflt
= (char_u
*)"";
2285 else if (STRLEN(initdir
) + STRLEN(dflt
) + 2 < MAXPATHL
)
2287 /* The default selection should be the full path, "dflt" is only the
2289 STRCPY(dfltbuf
, initdir
);
2290 add_pathsep(dfltbuf
);
2291 STRCAT(dfltbuf
, dflt
);
2295 /* Can only use one pattern for a file name. Get the first pattern out of
2296 * the filter. An empty pattern means everything matches. */
2298 pattern
= (char_u
*)"";
2304 for (p
= filter
; *p
!= NUL
; ++p
)
2306 if (*p
== '\t') /* end of description, start of pattern */
2308 if (*p
== ';' || *p
== '\n') /* end of (first) pattern */
2311 pattern
= vim_strnsave(s
, p
- s
);
2313 if (pattern
== NULL
)
2314 pattern
= (char_u
*)"";
2317 XtVaSetValues(dialog_wgt
,
2319 XmNdirectory
, XmRString
, (char *)initdir
, STRLEN(initdir
) + 1,
2321 XmNdirSpec
, XmRString
, (char *)dflt
, STRLEN(dflt
) + 1,
2323 XmNpattern
, XmRString
, (char *)pattern
, STRLEN(pattern
) + 1,
2325 XmNdialogTitle
, XmRString
, (char *)title
, STRLEN(title
) + 1,
2328 set_predefined_label(dialog_wgt
, "Apply", _("&Filter"));
2329 set_predefined_label(dialog_wgt
, "Cancel", _("&Cancel"));
2330 set_predefined_label(dialog_wgt
, "Dir", _("Directories"));
2331 set_predefined_label(dialog_wgt
, "FilterLabel", _("Filter"));
2332 set_predefined_label(dialog_wgt
, "Help", _("&Help"));
2333 set_predefined_label(dialog_wgt
, "Items", _("Files"));
2334 set_predefined_label(dialog_wgt
, "OK", _("&OK"));
2335 set_predefined_label(dialog_wgt
, "Selection", _("Selection"));
2337 /* This is to save us from silly external settings using not fixed with
2338 * fonts for file selection.
2340 set_predefined_fontlist(dialog_wgt
, "DirListSW.DirList");
2341 set_predefined_fontlist(dialog_wgt
, "ItemsListSW.ItemsList");
2343 gui_motif_menu_colors(dialog_wgt
);
2344 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
2345 XtVaSetValues(dialog_wgt
, XmNtroughColor
, gui
.scroll_bg_pixel
, NULL
);
2347 XtAddCallback(dialog_wgt
, XmNokCallback
, DialogAcceptCB
, (XtPointer
)0);
2348 XtAddCallback(dialog_wgt
, XmNcancelCallback
, DialogCancelCB
, (XtPointer
)0);
2349 /* We have no help in this window, so hide help button */
2350 XtUnmanageChild(XmFileSelectionBoxGetChild(dialog_wgt
,
2351 (unsigned char)XmDIALOG_HELP_BUTTON
));
2353 manage_centered(dialog_wgt
);
2354 activate_dialog_mnemonics(dialog_wgt
);
2356 /* sit in a loop until the dialog box has gone away */
2359 XtAppProcessEvent(XtWidgetToApplicationContext(dialog_wgt
),
2360 (XtInputMask
)XtIMAll
);
2361 } while (XtIsManaged(dialog_wgt
));
2363 suppress_dialog_mnemonics(dialog_wgt
);
2364 XtDestroyWidget(dialog_wgt
);
2367 if (browse_fname
== NULL
)
2369 return vim_strsave((char_u
*)browse_fname
);
2373 * The code below was originally taken from
2374 * /usr/examples/motif/xmsamplers/xmeditor.c
2375 * on Digital Unix 4.0d, but heavily modified.
2379 * Process callback from Dialog cancel actions.
2383 DialogCancelCB(w
, client_data
, call_data
)
2384 Widget w
; /* widget id */
2385 XtPointer client_data
; /* data from application */
2386 XtPointer call_data
; /* data from widget class */
2388 if (browse_fname
!= NULL
)
2390 XtFree(browse_fname
);
2391 browse_fname
= NULL
;
2393 XtUnmanageChild(dialog_wgt
);
2397 * Process callback from Dialog actions.
2401 DialogAcceptCB(w
, client_data
, call_data
)
2402 Widget w
; /* widget id */
2403 XtPointer client_data
; /* data from application */
2404 XtPointer call_data
; /* data from widget class */
2406 XmFileSelectionBoxCallbackStruct
*fcb
;
2408 if (browse_fname
!= NULL
)
2410 XtFree(browse_fname
);
2411 browse_fname
= NULL
;
2413 fcb
= (XmFileSelectionBoxCallbackStruct
*)call_data
;
2415 /* get the filename from the file selection box */
2416 XmStringGetLtoR(fcb
->value
, charset
, &browse_fname
);
2418 /* popdown the file selection box */
2419 XtUnmanageChild(dialog_wgt
);
2422 #endif /* FEAT_BROWSE */
2424 #if defined(FEAT_GUI_DIALOG) || defined(PROTO)
2426 static int dialogStatus
;
2428 static void keyhit_callback
__ARGS((Widget w
, XtPointer client_data
, XEvent
*event
, Boolean
*cont
));
2429 static void butproc
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
2432 * Callback function for the textfield. When CR is hit this works like
2433 * hitting the "OK" button, ESC like "Cancel".
2437 keyhit_callback(w
, client_data
, event
, cont
)
2439 XtPointer client_data
;
2446 if (XLookupString(&(event
->xkey
), buf
, 2, &key_sym
, NULL
) == 1)
2450 else if (*buf
== ESC
)
2453 if ((key_sym
== XK_Left
|| key_sym
== XK_Right
)
2454 && !(event
->xkey
.state
& ShiftMask
))
2455 XmTextFieldClearSelection(w
, XtLastTimestampProcessed(gui
.dpy
));
2460 butproc(w
, client_data
, call_data
)
2462 XtPointer client_data
;
2463 XtPointer call_data
;
2465 dialogStatus
= (int)(long)client_data
+ 1;
2470 static Widget
create_pixmap_label(Widget parent
, String name
, char **data
, ArgList args
, Cardinal arg
);
2473 create_pixmap_label(parent
, name
, data
, args
, arg
)
2487 XpmColorSymbol color
[5] =
2490 {"iconColor1", NULL
, 0},
2491 {"bottomShadowColor", NULL
, 0},
2492 {"topShadowColor", NULL
, 0},
2493 {"selectColor", NULL
, 0}
2496 label
= XmCreateLabelGadget(parent
, name
, args
, arg
);
2499 * We need to be carefull here, since in case of gadgets, there is
2500 * no way to get the background color directly from the widget itself.
2501 * In such cases we get it from The Core part of his parent instead.
2503 dsp
= XtDisplayOfObject(label
);
2504 scr
= XtScreenOfObject(label
);
2505 XtVaGetValues(XtIsSubclass(label
, coreWidgetClass
)
2506 ? label
: XtParent(label
),
2508 XmNbackground
, &color
[0].pixel
,
2509 XmNforeground
, &color
[1].pixel
,
2510 XmNbottomShadowColor
, &color
[2].pixel
,
2511 XmNtopShadowColor
, &color
[3].pixel
,
2512 XmNhighlight
, &color
[4].pixel
,
2515 attr
.valuemask
= XpmColorSymbols
| XpmCloseness
| XpmDepth
;
2516 attr
.colorsymbols
= color
;
2517 attr
.numsymbols
= 5;
2518 attr
.closeness
= 65535;
2520 XpmCreatePixmapFromData(dsp
, RootWindowOfScreen(scr
),
2521 data
, &pixmap
, NULL
, &attr
);
2523 XtVaGetValues(label
, XmNrecomputeSize
, &rs
, NULL
);
2524 XtVaSetValues(label
, XmNrecomputeSize
, True
, NULL
);
2525 XtVaSetValues(label
,
2526 XmNlabelType
, XmPIXMAP
,
2527 XmNlabelPixmap
, pixmap
,
2529 XtVaSetValues(label
, XmNrecomputeSize
, rs
, NULL
);
2537 gui_mch_dialog(type
, title
, message
, button_names
, dfltbutton
, textfield
)
2541 char_u
*button_names
;
2543 char_u
*textfield
; /* buffer of size IOSIZE */
2551 Widget dialogform
= NULL
;
2553 Widget dialogtextfield
= NULL
;
2555 Widget sep_form
= NULL
;
2557 Widget separator
= NULL
;
2561 char **icon_data
= NULL
;
2562 Widget dialogpixmap
= NULL
;
2566 title
= (char_u
*)_("Vim dialog");
2568 /* if our pointer is currently hidden, then we should show it. */
2569 gui_mch_mousehide(FALSE
);
2571 dialogform
= XmCreateFormDialog(vimShell
, (char *)"dialog", NULL
, 0);
2573 /* Check 'v' flag in 'guioptions': vertical button placement. */
2574 vertical
= (vim_strchr(p_go
, GO_VERTICAL
) != NULL
);
2576 /* Set the title of the Dialog window */
2577 label
= XmStringCreateSimple((char *)title
);
2580 XtVaSetValues(dialogform
,
2581 XmNdialogTitle
, label
,
2582 XmNhorizontalSpacing
, 4,
2583 XmNverticalSpacing
, vertical
? 0 : 4,
2585 XmStringFree(label
);
2587 /* make a copy, so that we can insert NULs */
2588 buts
= vim_strsave(button_names
);
2592 /* Count the number of buttons and allocate buttons[]. */
2594 for (p
= buts
; *p
; ++p
)
2595 if (*p
== DLG_BUTTON_SEP
)
2597 buttons
= (Widget
*)alloc((unsigned)(butcount
* sizeof(Widget
)));
2598 if (buttons
== NULL
)
2605 * Create the buttons.
2607 sep_form
= (Widget
) 0;
2609 for (butcount
= 0; *p
; ++butcount
)
2611 KeySym mnemonic
= NUL
;
2613 for (next
= p
; *next
; ++next
)
2615 if (*next
== DLG_HOTKEY_CHAR
)
2617 int len
= STRLEN(next
);
2621 mch_memmove(next
, next
+ 1, len
);
2625 if (*next
== DLG_BUTTON_SEP
)
2631 label
= XmStringCreate(_((char *)p
), STRING_TAG
);
2635 buttons
[butcount
] = XtVaCreateManagedWidget("button",
2636 xmPushButtonWidgetClass
, dialogform
,
2637 XmNlabelString
, label
,
2638 XmNmnemonic
, mnemonic
,
2639 XmNbottomAttachment
, XmATTACH_FORM
,
2641 XmNshowAsDefault
, butcount
== dfltbutton
- 1,
2642 XmNdefaultButtonShadowThickness
, 1,
2644 XmStringFree(label
);
2645 gui_motif_menu_fontlist(buttons
[butcount
]);
2647 /* Layout properly. */
2652 XtVaSetValues(buttons
[butcount
],
2653 XmNtopWidget
, buttons
[butcount
- 1],
2659 XtVaSetValues(buttons
[butcount
],
2660 XmNrightAttachment
, XmATTACH_FORM
,
2664 /* fill in a form as invisible separator */
2665 sep_form
= XtVaCreateWidget("separatorForm",
2666 xmFormWidgetClass
, dialogform
,
2667 XmNleftAttachment
, XmATTACH_WIDGET
,
2668 XmNleftWidget
, buttons
[butcount
- 1],
2669 XmNrightAttachment
, XmATTACH_WIDGET
,
2670 XmNrightWidget
, buttons
[butcount
],
2671 XmNbottomAttachment
, XmATTACH_FORM
,
2674 XtManageChild(sep_form
);
2678 XtVaSetValues(buttons
[butcount
],
2679 XmNleftAttachment
, XmATTACH_WIDGET
,
2680 XmNleftWidget
, buttons
[butcount
- 1],
2689 XtVaSetValues(buttons
[0],
2690 XmNrightAttachment
, XmATTACH_FORM
,
2694 /* fill in a form as invisible separator */
2695 sep_form
= XtVaCreateWidget("separatorForm",
2696 xmFormWidgetClass
, dialogform
,
2697 XmNleftAttachment
, XmATTACH_FORM
,
2699 XmNrightAttachment
, XmATTACH_WIDGET
,
2700 XmNrightWidget
, buttons
[0],
2701 XmNbottomAttachment
, XmATTACH_FORM
,
2704 XtManageChild(sep_form
);
2707 XtVaSetValues(buttons
[0],
2708 XmNleftAttachment
, XmATTACH_FORM
,
2713 XtAddCallback(buttons
[butcount
], XmNactivateCallback
,
2714 (XtCallbackProc
)butproc
, (XtPointer
)(long)butcount
);
2719 separator
= (Widget
) 0;
2722 /* Create the separator for beauty. */
2724 XtSetArg(args
[n
], XmNorientation
, XmHORIZONTAL
); n
++;
2725 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_WIDGET
); n
++;
2726 XtSetArg(args
[n
], XmNbottomWidget
, buttons
[0]); n
++;
2727 XtSetArg(args
[n
], XmNbottomOffset
, 4); n
++;
2728 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
2729 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
2730 separator
= XmCreateSeparatorGadget(dialogform
, "separator", args
, n
);
2731 XtManageChild(separator
);
2734 if (textfield
!= NULL
)
2736 dialogtextfield
= XtVaCreateWidget("textField",
2737 xmTextFieldWidgetClass
, dialogform
,
2738 XmNleftAttachment
, XmATTACH_FORM
,
2739 XmNrightAttachment
, XmATTACH_FORM
,
2742 XtVaSetValues(dialogtextfield
,
2743 XmNbottomAttachment
, XmATTACH_WIDGET
,
2744 XmNbottomWidget
, separator
,
2747 XtVaSetValues(dialogtextfield
,
2748 XmNbottomAttachment
, XmATTACH_FORM
,
2751 set_fontlist(dialogtextfield
);
2752 XmTextFieldSetString(dialogtextfield
, (char *)textfield
);
2753 XtManageChild(dialogtextfield
);
2754 XtAddEventHandler(dialogtextfield
, KeyPressMask
, False
,
2755 (XtEventHandler
)keyhit_callback
, (XtPointer
)NULL
);
2758 /* Form holding both message and pixmap labels */
2759 form
= XtVaCreateWidget("separatorForm",
2760 xmFormWidgetClass
, dialogform
,
2761 XmNleftAttachment
, XmATTACH_FORM
,
2762 XmNrightAttachment
, XmATTACH_FORM
,
2763 XmNtopAttachment
, XmATTACH_FORM
,
2765 XtManageChild(form
);
2768 /* Add a pixmap, left of the message. */
2772 icon_data
= generic_xpm
;
2775 icon_data
= error_xpm
;
2778 icon_data
= alert_xpm
;
2781 icon_data
= info_xpm
;
2784 icon_data
= quest_xpm
;
2787 icon_data
= generic_xpm
;
2791 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
2792 XtSetArg(args
[n
], XmNtopOffset
, 8); n
++;
2793 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
2794 XtSetArg(args
[n
], XmNbottomOffset
, 8); n
++;
2795 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
2796 XtSetArg(args
[n
], XmNleftOffset
, 8); n
++;
2798 dialogpixmap
= create_pixmap_label(form
, "dialogPixmap",
2799 icon_data
, args
, n
);
2800 XtManageChild(dialogpixmap
);
2803 /* Create the dialog message.
2804 * Since LessTif is apparently having problems with the creation of
2805 * properly localized string, we use LtoR here. The symptom is that the
2806 * string sill not show properly in multiple lines as it does in native
2809 label
= XmStringCreateLtoR((char *)message
, STRING_TAG
);
2812 w
= XtVaCreateManagedWidget("dialogMessage",
2813 xmLabelGadgetClass
, form
,
2814 XmNlabelString
, label
,
2815 XmNalignment
, XmALIGNMENT_BEGINNING
,
2816 XmNtopAttachment
, XmATTACH_FORM
,
2819 XmNleftAttachment
, XmATTACH_WIDGET
,
2820 XmNleftWidget
, dialogpixmap
,
2822 XmNleftAttachment
, XmATTACH_FORM
,
2825 XmNrightAttachment
, XmATTACH_FORM
,
2827 XmNbottomAttachment
, XmATTACH_FORM
,
2830 XmStringFree(label
);
2833 if (textfield
!= NULL
)
2836 XmNbottomAttachment
, XmATTACH_WIDGET
,
2837 XmNbottomWidget
, dialogtextfield
,
2844 XmNbottomAttachment
, XmATTACH_WIDGET
,
2845 XmNbottomWidget
, separator
,
2849 XmNbottomAttachment
, XmATTACH_FORM
,
2855 if (dfltbutton
> butcount
)
2856 dfltbutton
= butcount
;
2857 XtVaSetValues(dialogform
,
2858 XmNdefaultButton
, buttons
[dfltbutton
- 1], NULL
);
2859 if (textfield
!= NULL
)
2860 XtVaSetValues(dialogform
, XmNinitialFocus
, dialogtextfield
, NULL
);
2862 XtVaSetValues(dialogform
, XmNinitialFocus
, buttons
[dfltbutton
- 1],
2865 manage_centered(dialogform
);
2866 activate_dialog_mnemonics(dialogform
);
2868 if (textfield
!= NULL
&& *textfield
!= NUL
)
2870 /* This only works after the textfield has been realised. */
2871 XmTextFieldSetSelection(dialogtextfield
,
2872 (XmTextPosition
)0, (XmTextPosition
)STRLEN(textfield
),
2873 XtLastTimestampProcessed(gui
.dpy
));
2874 XmTextFieldSetCursorPosition(dialogtextfield
,
2875 (XmTextPosition
)STRLEN(textfield
));
2878 app
= XtWidgetToApplicationContext(dialogform
);
2880 /* Loop until a button is pressed or the dialog is killed somehow. */
2884 XtAppProcessEvent(app
, (XtInputMask
)XtIMAll
);
2885 if (dialogStatus
>= 0 || !XtIsManaged(dialogform
))
2891 if (textfield
!= NULL
)
2893 p
= (char_u
*)XmTextGetString(dialogtextfield
);
2894 if (p
== NULL
|| dialogStatus
< 0)
2897 vim_strncpy(textfield
, p
, IOSIZE
- 1);
2900 suppress_dialog_mnemonics(dialogform
);
2901 XtDestroyWidget(dialogform
);
2903 return dialogStatus
;
2905 #endif /* FEAT_GUI_DIALOG */
2907 #if defined(FEAT_FOOTER) || defined(PROTO)
2910 gui_mch_compute_footer_height()
2912 Dimension height
; /* total Toolbar height */
2913 Dimension top
; /* XmNmarginTop */
2914 Dimension bottom
; /* XmNmarginBottom */
2915 Dimension shadow
; /* XmNshadowThickness */
2917 XtVaGetValues(footer
,
2920 XmNmarginBottom
, &bottom
,
2921 XmNshadowThickness
, &shadow
,
2924 return (int) height
+ top
+ bottom
+ (shadow
<< 1);
2927 #if 0 /* not used */
2929 gui_mch_set_footer_pos(h
)
2930 int h
; /* textArea height */
2932 XtVaSetValues(footer
,
2933 XmNtopOffset
, h
+ 7,
2939 gui_mch_enable_footer(showit
)
2944 gui
.footer_height
= gui_mch_compute_footer_height();
2945 XtManageChild(footer
);
2949 gui
.footer_height
= 0;
2950 XtUnmanageChild(footer
);
2952 XtVaSetValues(textAreaForm
, XmNbottomOffset
, gui
.footer_height
, NULL
);
2956 gui_mch_set_footer(s
)
2961 xms
= XmStringCreate((char *)s
, STRING_TAG
);
2964 XtVaSetValues(footer
, XmNlabelString
, xms
, NULL
);
2972 #if defined(FEAT_TOOLBAR) || defined(PROTO)
2974 gui_mch_show_toolbar(int showit
)
2976 Cardinal numChildren
; /* how many children toolBar has */
2978 if (toolBar
== (Widget
)0)
2980 XtVaGetValues(toolBar
, XmNnumChildren
, &numChildren
, NULL
);
2981 if (showit
&& numChildren
> 0)
2983 /* Assume that we want to show the toolbar if p_toolbar contains
2984 * valid option settings, therefore p_toolbar must not be NULL.
2986 WidgetList children
;
2988 XtVaGetValues(toolBar
, XmNchildren
, &children
, NULL
);
2990 void (*action
)(BalloonEval
*);
2993 if (strstr((const char *)p_toolbar
, "tooltips"))
2994 action
= &gui_mch_enable_beval_area
;
2996 action
= &gui_mch_disable_beval_area
;
2997 if (strstr((const char *)p_toolbar
, "text"))
2999 else if (strstr((const char *)p_toolbar
, "icons"))
3006 for (toolbar
= root_menu
; toolbar
; toolbar
= toolbar
->next
)
3007 if (menu_is_toolbar(toolbar
->dname
))
3009 /* Assumption: toolbar is NULL if there is no toolbar,
3010 * otherwise it contains the toolbar menu structure.
3012 * Assumption: "numChildren" == the number of items in the list
3013 * of items beginning with toolbar->children.
3017 for (cur
= toolbar
->children
; cur
; cur
= cur
->next
)
3022 /* Enable/Disable tooltip (OK to enable while
3023 * currently enabled)
3025 if (cur
->tip
!= NULL
)
3026 (*action
)(cur
->tip
);
3027 if (!menu_is_separator(cur
->name
))
3029 if (text
== 1 || cur
->xpm
== NULL
)
3031 XtSetArg(args
[n
], XmNlabelType
, XmSTRING
);
3034 if (cur
->id
!= NULL
)
3036 XtUnmanageChild(cur
->id
);
3037 XtSetValues(cur
->id
, args
, n
);
3038 XtManageChild(cur
->id
);
3045 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
3046 XtManageChild(XtParent(toolBar
));
3047 #ifdef FEAT_GUI_TABLINE
3048 if (showing_tabline
)
3050 XtVaSetValues(tabLine
,
3051 XmNtopAttachment
, XmATTACH_WIDGET
,
3052 XmNtopWidget
, XtParent(toolBar
),
3054 XtVaSetValues(textAreaForm
,
3055 XmNtopAttachment
, XmATTACH_WIDGET
,
3056 XmNtopWidget
, tabLine
,
3061 XtVaSetValues(textAreaForm
,
3062 XmNtopAttachment
, XmATTACH_WIDGET
,
3063 XmNtopWidget
, XtParent(toolBar
),
3065 if (XtIsManaged(menuBar
))
3066 XtVaSetValues(XtParent(toolBar
),
3067 XmNtopAttachment
, XmATTACH_WIDGET
,
3068 XmNtopWidget
, menuBar
,
3071 XtVaSetValues(XtParent(toolBar
),
3072 XmNtopAttachment
, XmATTACH_FORM
,
3077 gui
.toolbar_height
= 0;
3078 if (XtIsManaged(menuBar
))
3080 #ifdef FEAT_GUI_TABLINE
3081 if (showing_tabline
)
3083 XtVaSetValues(tabLine
,
3084 XmNtopAttachment
, XmATTACH_WIDGET
,
3085 XmNtopWidget
, menuBar
,
3087 XtVaSetValues(textAreaForm
,
3088 XmNtopAttachment
, XmATTACH_WIDGET
,
3089 XmNtopWidget
, tabLine
,
3094 XtVaSetValues(textAreaForm
,
3095 XmNtopAttachment
, XmATTACH_WIDGET
,
3096 XmNtopWidget
, menuBar
,
3101 #ifdef FEAT_GUI_TABLINE
3102 if (showing_tabline
)
3104 XtVaSetValues(tabLine
,
3105 XmNtopAttachment
, XmATTACH_FORM
,
3107 XtVaSetValues(textAreaForm
,
3108 XmNtopAttachment
, XmATTACH_WIDGET
,
3109 XmNtopWidget
, tabLine
,
3114 XtVaSetValues(textAreaForm
,
3115 XmNtopAttachment
, XmATTACH_FORM
,
3119 XtUnmanageChild(XtParent(toolBar
));
3121 gui_set_shellsize(FALSE
, FALSE
, RESIZE_VERT
);
3125 * A toolbar button has been pushed; now reset the input focus
3126 * such that the user can type page up/down etc. and have the
3127 * input go to the editor window, not the button
3132 if (textArea
!= NULL
)
3133 XmProcessTraversal(textArea
, XmTRAVERSE_CURRENT
);
3137 gui_mch_compute_toolbar_height()
3140 Dimension height
; /* total Toolbar height */
3141 Dimension whgt
; /* height of each widget */
3142 WidgetList children
; /* list of toolBar's children */
3143 Cardinal numChildren
; /* how many children toolBar has */
3148 if (toolBar
!= (Widget
)0 && toolBarFrame
!= (Widget
)0)
3149 { /* get height of XmFrame parent */
3155 XtVaGetValues(toolBarFrame
,
3156 XmNshadowThickness
, &fst
,
3157 XmNmarginHeight
, &fmh
,
3159 borders
+= fst
+ fmh
;
3160 XtVaGetValues(toolBar
,
3161 XmNshadowThickness
, &tst
,
3162 XmNmarginHeight
, &tmh
,
3163 XmNchildren
, &children
,
3164 XmNnumChildren
, &numChildren
, NULL
);
3165 borders
+= tst
+ tmh
;
3166 for (i
= 0; i
< numChildren
; i
++)
3169 XtVaGetValues(children
[i
], XmNheight
, &whgt
, NULL
);
3174 #ifdef LESSTIF_VERSION
3175 /* Hack: When starting up we get wrong dimensions. */
3180 return (int)(height
+ (borders
<< 1));
3184 motif_get_toolbar_colors(bgp
, fgp
, bsp
, tsp
, hsp
)
3191 XtVaGetValues(toolBar
,
3194 XmNbottomShadowColor
, bsp
,
3195 XmNtopShadowColor
, tsp
,
3196 XmNhighlightColor
, hsp
,
3202 * The next toolbar enter/leave callbacks should really do balloon help. But
3203 * I have to use footer help for backwards compatability. Hopefully both will
3204 * get implemented and the user will have a choice.
3208 toolbarbutton_enter_cb(w
, client_data
, event
, cont
)
3210 XtPointer client_data
;
3214 vimmenu_T
*menu
= (vimmenu_T
*) client_data
;
3216 if (menu
->strings
[MENU_INDEX_TIP
] != NULL
)
3218 if (vim_strchr(p_go
, GO_FOOTER
) != NULL
)
3219 gui_mch_set_footer(menu
->strings
[MENU_INDEX_TIP
]);
3225 toolbarbutton_leave_cb(w
, client_data
, event
, cont
)
3227 XtPointer client_data
;
3231 gui_mch_set_footer((char_u
*) "");
3236 #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
3238 * Show or hide the tabline.
3241 gui_mch_show_tabline(int showit
)
3243 if (tabLine
== (Widget
)0)
3246 if (!showit
!= !showing_tabline
)
3250 XtManageChild(tabLine
);
3251 XtUnmanageChild(XtNameToWidget(tabLine
, "PageScroller"));
3252 XtUnmanageChild(XtNameToWidget(tabLine
, "MinorTabScrollerNext"));
3253 XtUnmanageChild(XtNameToWidget(tabLine
,
3254 "MinorTabScrollerPrevious"));
3256 # ifdef FEAT_TOOLBAR
3257 if (XtIsManaged(XtParent(toolBar
)))
3258 XtVaSetValues(tabLine
,
3259 XmNtopAttachment
, XmATTACH_WIDGET
,
3260 XmNtopWidget
, XtParent(toolBar
), NULL
);
3263 if (XtIsManaged(menuBar
))
3264 XtVaSetValues(tabLine
,
3265 XmNtopAttachment
, XmATTACH_WIDGET
,
3266 XmNtopWidget
, menuBar
, NULL
);
3269 XtVaSetValues(tabLine
,
3270 XmNtopAttachment
, XmATTACH_FORM
, NULL
);
3271 XtVaSetValues(textAreaForm
,
3272 XmNtopAttachment
, XmATTACH_WIDGET
,
3273 XmNtopWidget
, tabLine
,
3278 XtUnmanageChild(tabLine
);
3280 # ifdef FEAT_TOOLBAR
3281 if (XtIsManaged(XtParent(toolBar
)))
3282 XtVaSetValues(textAreaForm
,
3283 XmNtopAttachment
, XmATTACH_WIDGET
,
3284 XmNtopWidget
, XtParent(toolBar
), NULL
);
3287 if (XtIsManaged(menuBar
))
3288 XtVaSetValues(textAreaForm
,
3289 XmNtopAttachment
, XmATTACH_WIDGET
,
3290 XmNtopWidget
, menuBar
, NULL
);
3293 XtVaSetValues(textAreaForm
,
3294 XmNtopAttachment
, XmATTACH_FORM
, NULL
);
3296 showing_tabline
= showit
;
3301 * Return TRUE when tabline is displayed.
3304 gui_mch_showing_tabline(void)
3306 return tabLine
!= (Widget
)0 && showing_tabline
;
3310 * Update the labels of the tabline.
3313 gui_mch_update_tabline(void)
3318 int curtabidx
= 0, currentpage
;
3320 XmNotebookPageInfo page_info
;
3321 XmNotebookPageStatus page_status
;
3322 int last_page
, tab_count
;
3326 if (tabLine
== (Widget
)0)
3329 /* Add a label for each tab page. They all contain the same text area. */
3330 for (tp
= first_tabpage
; tp
!= NULL
; tp
= tp
->tp_next
, ++nr
)
3335 page_status
= XmNotebookGetPageInfo(tabLine
, nr
, &page_info
);
3336 if (page_status
== XmPAGE_INVALID
3337 || page_info
.major_tab_widget
== (Widget
)0)
3341 XtSetArg(args
[n
], XmNnotebookChildType
, XmMAJOR_TAB
); n
++;
3342 XtSetArg(args
[n
], XmNtraversalOn
, False
); n
++;
3343 XtSetArg(args
[n
], XmNalignment
, XmALIGNMENT_BEGINNING
); n
++;
3344 XtSetArg(args
[n
], XmNhighlightThickness
, 1); n
++;
3345 XtSetArg(args
[n
], XmNshadowThickness
, 1); n
++;
3346 tab
= XmCreatePushButton(tabLine
, "-Empty-", args
, n
);
3350 tab
= page_info
.major_tab_widget
;
3352 XtVaSetValues(tab
, XmNpageNumber
, nr
, NULL
);
3355 * Change the label text only if it is different
3357 XtVaGetValues(tab
, XmNlabelString
, &label_str
, NULL
);
3358 if (XmStringGetLtoR(label_str
, XmSTRING_DEFAULT_CHARSET
, &label_cstr
))
3360 get_tabline_label(tp
);
3361 if (STRCMP(label_cstr
, NameBuff
) != 0) {
3362 XtVaSetValues(tab
, XtVaTypedArg
, XmNlabelString
, XmRString
,
3363 NameBuff
, STRLEN(NameBuff
) + 1, NULL
);
3365 * Force a resize of the tab label button
3367 XtUnmanageChild(tab
);
3376 XtVaGetValues(tabLine
, XmNlastPageNumber
, &last_page
, NULL
);
3378 /* Remove any old labels. */
3379 while (nr
<= last_page
)
3381 if (XmNotebookGetPageInfo(tabLine
, nr
, &page_info
) != XmPAGE_INVALID
3382 && page_info
.page_number
== nr
3383 && page_info
.major_tab_widget
!= (Widget
)0)
3385 XtUnmanageChild(page_info
.major_tab_widget
);
3386 XtDestroyWidget(page_info
.major_tab_widget
);
3391 XtVaSetValues(tabLine
, XmNlastPageNumber
, tab_count
, NULL
);
3393 XtVaGetValues(tabLine
, XmNcurrentPageNumber
, ¤tpage
, NULL
);
3394 if (currentpage
!= curtabidx
)
3395 XtVaSetValues(tabLine
, XmNcurrentPageNumber
, curtabidx
, NULL
);
3399 * Set the current tab to "nr". First tab is 1.
3402 gui_mch_set_curtab(nr
)
3407 if (tabLine
== (Widget
)0)
3410 XtVaGetValues(tabLine
, XmNcurrentPageNumber
, ¤tpage
, NULL
);
3411 if (currentpage
!= nr
)
3412 XtVaSetValues(tabLine
, XmNcurrentPageNumber
, nr
, NULL
);
3417 * Set the colors of Widget "id" to the menu colors.
3420 gui_motif_menu_colors(id
)
3423 if (gui
.menu_bg_pixel
!= INVALCOLOR
)
3424 #if (XmVersion >= 1002)
3425 XmChangeColor(id
, gui
.menu_bg_pixel
);
3427 XtVaSetValues(id
, XmNbackground
, gui
.menu_bg_pixel
, NULL
);
3429 if (gui
.menu_fg_pixel
!= INVALCOLOR
)
3430 XtVaSetValues(id
, XmNforeground
, gui
.menu_fg_pixel
, NULL
);
3434 * Set the colors of Widget "id" to the scrollbar colors.
3437 gui_motif_scroll_colors(id
)
3440 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
3441 #if (XmVersion >= 1002)
3442 XmChangeColor(id
, gui
.scroll_bg_pixel
);
3444 XtVaSetValues(id
, XmNbackground
, gui
.scroll_bg_pixel
, NULL
);
3446 if (gui
.scroll_fg_pixel
!= INVALCOLOR
)
3447 XtVaSetValues(id
, XmNforeground
, gui
.scroll_fg_pixel
, NULL
);
3451 * Set the fontlist for Widget "id" to use gui.menu_fontset or gui.menu_font.
3455 gui_motif_menu_fontlist(id
)
3459 #ifdef FONTSET_ALWAYS
3460 if (gui
.menu_fontset
!= NOFONTSET
)
3464 fl
= gui_motif_fontset2fontlist((XFontSet
*)&gui
.menu_fontset
);
3467 if (XtIsManaged(id
))
3469 XtUnmanageChild(id
);
3470 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3471 /* We should force the widget to recalculate it's
3476 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3481 if (gui
.menu_font
!= NOFONT
)
3485 fl
= gui_motif_create_fontlist((XFontStruct
*)gui
.menu_font
);
3488 if (XtIsManaged(id
))
3490 XtUnmanageChild(id
);
3491 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3492 /* We should force the widget to recalculate it's
3497 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3507 * We don't create it twice for the sake of speed.
3510 typedef struct _SharedFindReplace
3512 Widget dialog
; /* the main dialog widget */
3513 Widget wword
; /* 'Exact match' check button */
3514 Widget mcase
; /* 'match case' check button */
3515 Widget up
; /* search direction 'Up' radio button */
3516 Widget down
; /* search direction 'Down' radio button */
3517 Widget what
; /* 'Find what' entry text widget */
3518 Widget with
; /* 'Replace with' entry text widget */
3519 Widget find
; /* 'Find Next' action button */
3520 Widget replace
; /* 'Replace With' action button */
3521 Widget all
; /* 'Replace All' action button */
3522 Widget undo
; /* 'Undo' action button */
3525 } SharedFindReplace
;
3527 static SharedFindReplace find_widgets
= { NULL
};
3528 static SharedFindReplace repl_widgets
= { NULL
};
3530 static void find_replace_destroy_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3531 static void find_replace_dismiss_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3532 static void entry_activate_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3533 static void find_replace_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3534 static void find_replace_keypress
__ARGS((Widget w
, SharedFindReplace
* frdp
, XKeyEvent
* event
));
3535 static void find_replace_dialog_create
__ARGS((char_u
*entry_text
, int do_replace
));
3539 find_replace_destroy_callback(w
, client_data
, call_data
)
3541 XtPointer client_data
;
3542 XtPointer call_data
;
3544 SharedFindReplace
*cd
= (SharedFindReplace
*)client_data
;
3547 /* suppress_dialog_mnemonics(cd->dialog); */
3548 cd
->dialog
= (Widget
)0;
3553 find_replace_dismiss_callback(w
, client_data
, call_data
)
3555 XtPointer client_data
;
3556 XtPointer call_data
;
3558 SharedFindReplace
*cd
= (SharedFindReplace
*)client_data
;
3561 XtUnmanageChild(cd
->dialog
);
3566 entry_activate_callback(w
, client_data
, call_data
)
3568 XtPointer client_data
;
3569 XtPointer call_data
;
3571 XmProcessTraversal((Widget
)client_data
, XmTRAVERSE_CURRENT
);
3576 find_replace_callback(w
, client_data
, call_data
)
3578 XtPointer client_data
;
3579 XtPointer call_data
;
3581 long_u flags
= (long_u
)client_data
;
3582 char *find_text
, *repl_text
;
3583 Boolean direction_down
= TRUE
;
3586 SharedFindReplace
*sfr
;
3588 if (flags
== FRD_UNDO
)
3590 char_u
*save_cpo
= p_cpo
;
3592 /* No need to be Vi compatible here. */
3593 p_cpo
= (char_u
*)"";
3596 gui_update_screen();
3600 /* Get the search/replace strings from the dialog */
3601 if (flags
== FRD_FINDNEXT
)
3604 sfr
= &find_widgets
;
3608 repl_text
= XmTextFieldGetString(repl_widgets
.with
);
3609 sfr
= &repl_widgets
;
3611 find_text
= XmTextFieldGetString(sfr
->what
);
3612 XtVaGetValues(sfr
->down
, XmNset
, &direction_down
, NULL
);
3613 XtVaGetValues(sfr
->wword
, XmNset
, &wword
, NULL
);
3614 XtVaGetValues(sfr
->mcase
, XmNset
, &mcase
, NULL
);
3616 flags
|= FRD_WHOLE_WORD
;
3618 flags
|= FRD_MATCH_CASE
;
3620 (void)gui_do_findrepl((int)flags
, (char_u
*)find_text
, (char_u
*)repl_text
,
3623 if (find_text
!= NULL
)
3625 if (repl_text
!= NULL
)
3631 find_replace_keypress(w
, frdp
, event
)
3633 SharedFindReplace
*frdp
;
3641 keysym
= XLookupKeysym(event
, 0);
3643 /* the scape key pops the whole dialog down */
3644 if (keysym
== XK_Escape
)
3645 XtUnmanageChild(frdp
->dialog
);
3655 KeySym mnemonic
= NUL
;
3660 p
= vim_strsave(label
);
3663 for (next
= p
; *next
; ++next
)
3665 if (*next
== DLG_HOTKEY_CHAR
)
3667 int len
= STRLEN(next
);
3671 mch_memmove(next
, next
+ 1, len
);
3677 str
= XmStringCreateSimple((char *)p
);
3682 XmNlabelString
, str
,
3683 XmNmnemonic
, mnemonic
,
3687 gui_motif_menu_fontlist(w
);
3691 find_replace_dialog_create(arg
, do_replace
)
3695 SharedFindReplace
*frdp
;
3710 frdp
= do_replace
? &repl_widgets
: &find_widgets
;
3712 /* Get the search string to use. */
3713 entry_text
= get_find_dialog_text(arg
, &wword
, &mcase
);
3715 /* If the dialog already exists, just raise it. */
3718 gui_motif_synch_fonts();
3720 /* If the window is already up, just pop it to the top */
3721 if (XtIsManaged(frdp
->dialog
))
3722 XMapRaised(XtDisplay(frdp
->dialog
),
3723 XtWindow(XtParent(frdp
->dialog
)));
3725 XtManageChild(frdp
->dialog
);
3726 XtPopup(XtParent(frdp
->dialog
), XtGrabNone
);
3727 XmProcessTraversal(frdp
->what
, XmTRAVERSE_CURRENT
);
3729 if (entry_text
!= NULL
)
3730 XmTextFieldSetString(frdp
->what
, (char *)entry_text
);
3731 vim_free(entry_text
);
3733 XtVaSetValues(frdp
->wword
, XmNset
, wword
, NULL
);
3737 /* Create a fresh new dialog window */
3739 str
= XmStringCreateSimple(_("VIM - Search and Replace..."));
3741 str
= XmStringCreateSimple(_("VIM - Search..."));
3744 XtSetArg(args
[n
], XmNautoUnmanage
, False
); n
++;
3745 XtSetArg(args
[n
], XmNnoResize
, True
); n
++;
3746 XtSetArg(args
[n
], XmNdialogTitle
, str
); n
++;
3748 frdp
->dialog
= XmCreateFormDialog(vimShell
, "findReplaceDialog", args
, n
);
3750 XtAddCallback(frdp
->dialog
, XmNdestroyCallback
,
3751 find_replace_destroy_callback
, frdp
);
3753 button_form
= XtVaCreateWidget("buttonForm",
3754 xmFormWidgetClass
, frdp
->dialog
,
3755 XmNrightAttachment
, XmATTACH_FORM
,
3757 XmNtopAttachment
, XmATTACH_FORM
,
3759 XmNbottomAttachment
, XmATTACH_FORM
,
3763 frdp
->find
= XtVaCreateManagedWidget("findButton",
3764 xmPushButtonWidgetClass
, button_form
,
3766 XmNtopAttachment
, XmATTACH_FORM
,
3767 XmNleftAttachment
, XmATTACH_FORM
,
3768 XmNrightAttachment
, XmATTACH_FORM
,
3770 set_label(frdp
->find
, _("Find &Next"));
3772 XtAddCallback(frdp
->find
, XmNactivateCallback
,
3773 find_replace_callback
,
3774 (XtPointer
) (do_replace
? FRD_R_FINDNEXT
: FRD_FINDNEXT
));
3778 frdp
->replace
= XtVaCreateManagedWidget("replaceButton",
3779 xmPushButtonWidgetClass
, button_form
,
3780 XmNtopAttachment
, XmATTACH_WIDGET
,
3781 XmNtopWidget
, frdp
->find
,
3782 XmNleftAttachment
, XmATTACH_FORM
,
3783 XmNrightAttachment
, XmATTACH_FORM
,
3785 set_label(frdp
->replace
, _("&Replace"));
3786 XtAddCallback(frdp
->replace
, XmNactivateCallback
,
3787 find_replace_callback
, (XtPointer
)FRD_REPLACE
);
3789 frdp
->all
= XtVaCreateManagedWidget("replaceAllButton",
3790 xmPushButtonWidgetClass
, button_form
,
3791 XmNtopAttachment
, XmATTACH_WIDGET
,
3792 XmNtopWidget
, frdp
->replace
,
3793 XmNleftAttachment
, XmATTACH_FORM
,
3794 XmNrightAttachment
, XmATTACH_FORM
,
3796 set_label(frdp
->all
, _("Replace &All"));
3797 XtAddCallback(frdp
->all
, XmNactivateCallback
,
3798 find_replace_callback
, (XtPointer
)FRD_REPLACEALL
);
3800 frdp
->undo
= XtVaCreateManagedWidget("undoButton",
3801 xmPushButtonWidgetClass
, button_form
,
3802 XmNtopAttachment
, XmATTACH_WIDGET
,
3803 XmNtopWidget
, frdp
->all
,
3804 XmNleftAttachment
, XmATTACH_FORM
,
3805 XmNrightAttachment
, XmATTACH_FORM
,
3807 set_label(frdp
->undo
, _("&Undo"));
3808 XtAddCallback(frdp
->undo
, XmNactivateCallback
,
3809 find_replace_callback
, (XtPointer
)FRD_UNDO
);
3812 frdp
->cancel
= XtVaCreateManagedWidget("closeButton",
3813 xmPushButtonWidgetClass
, button_form
,
3814 XmNleftAttachment
, XmATTACH_FORM
,
3815 XmNrightAttachment
, XmATTACH_FORM
,
3816 XmNbottomAttachment
, XmATTACH_FORM
,
3818 set_label(frdp
->cancel
, _("&Cancel"));
3819 XtAddCallback(frdp
->cancel
, XmNactivateCallback
,
3820 find_replace_dismiss_callback
, frdp
);
3821 gui_motif_menu_fontlist(frdp
->cancel
);
3823 XtManageChild(button_form
);
3826 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
3827 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_WIDGET
); n
++;
3828 XtSetArg(args
[n
], XmNrightWidget
, button_form
); n
++;
3829 XtSetArg(args
[n
], XmNrightOffset
, 4); n
++;
3830 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
3831 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
3832 separator
= XmCreateSeparatorGadget(frdp
->dialog
, "separator", args
, n
);
3833 XtManageChild(separator
);
3835 input_form
= XtVaCreateWidget("inputForm",
3836 xmFormWidgetClass
, frdp
->dialog
,
3837 XmNleftAttachment
, XmATTACH_FORM
,
3839 XmNrightAttachment
, XmATTACH_WIDGET
,
3840 XmNrightWidget
, separator
,
3842 XmNtopAttachment
, XmATTACH_FORM
,
3848 Widget label_with
= (Widget
)0;
3850 str
= XmStringCreateSimple(_("Find what:"));
3851 label_what
= XtVaCreateManagedWidget("whatLabel",
3852 xmLabelGadgetClass
, input_form
,
3853 XmNlabelString
, str
,
3854 XmNleftAttachment
, XmATTACH_FORM
,
3855 XmNtopAttachment
, XmATTACH_FORM
,
3859 gui_motif_menu_fontlist(label_what
);
3861 frdp
->what
= XtVaCreateManagedWidget("whatText",
3862 xmTextFieldWidgetClass
, input_form
,
3863 XmNtopAttachment
, XmATTACH_FORM
,
3864 XmNrightAttachment
, XmATTACH_FORM
,
3865 XmNleftAttachment
, XmATTACH_FORM
,
3870 frdp
->with
= XtVaCreateManagedWidget("withText",
3871 xmTextFieldWidgetClass
, input_form
,
3872 XmNtopAttachment
, XmATTACH_WIDGET
,
3873 XmNtopWidget
, frdp
->what
,
3875 XmNleftAttachment
, XmATTACH_FORM
,
3876 XmNrightAttachment
, XmATTACH_FORM
,
3877 XmNbottomAttachment
, XmATTACH_FORM
,
3880 XtAddCallback(frdp
->with
, XmNactivateCallback
,
3881 find_replace_callback
, (XtPointer
) FRD_R_FINDNEXT
);
3883 str
= XmStringCreateSimple(_("Replace with:"));
3884 label_with
= XtVaCreateManagedWidget("withLabel",
3885 xmLabelGadgetClass
, input_form
,
3886 XmNlabelString
, str
,
3887 XmNleftAttachment
, XmATTACH_FORM
,
3888 XmNtopAttachment
, XmATTACH_WIDGET
,
3889 XmNtopWidget
, frdp
->what
,
3891 XmNbottomAttachment
, XmATTACH_FORM
,
3894 gui_motif_menu_fontlist(label_with
);
3897 * Make the entry activation only change the input focus onto the
3900 XtAddCallback(frdp
->what
, XmNactivateCallback
,
3901 entry_activate_callback
, frdp
->with
);
3902 XtAddEventHandler(frdp
->with
, KeyPressMask
, False
,
3903 (XtEventHandler
)find_replace_keypress
,
3910 * Make the entry activation do the search.
3912 XtAddCallback(frdp
->what
, XmNactivateCallback
,
3913 find_replace_callback
, (XtPointer
)FRD_FINDNEXT
);
3915 XtAddEventHandler(frdp
->what
, KeyPressMask
, False
,
3916 (XtEventHandler
)find_replace_keypress
,
3919 /* Get the maximum width between the label widgets and line them up.
3922 XtSetArg(args
[n
], XmNwidth
, &width
); n
++;
3923 XtGetValues(label_what
, args
, n
);
3927 XtGetValues(label_with
, args
, n
);
3932 XtVaSetValues(frdp
->what
, XmNleftOffset
, widest
, NULL
);
3934 XtVaSetValues(frdp
->with
, XmNleftOffset
, widest
, NULL
);
3938 XtManageChild(input_form
);
3944 frame
= XtVaCreateWidget("directionFrame",
3945 xmFrameWidgetClass
, frdp
->dialog
,
3946 XmNtopAttachment
, XmATTACH_WIDGET
,
3947 XmNtopWidget
, input_form
,
3949 XmNbottomAttachment
, XmATTACH_FORM
,
3951 XmNrightAttachment
, XmATTACH_OPPOSITE_WIDGET
,
3952 XmNrightWidget
, input_form
,
3955 str
= XmStringCreateSimple(_("Direction"));
3956 w
= XtVaCreateManagedWidget("directionFrameLabel",
3957 xmLabelGadgetClass
, frame
,
3958 XmNlabelString
, str
,
3959 XmNchildHorizontalAlignment
, XmALIGNMENT_BEGINNING
,
3960 XmNchildType
, XmFRAME_TITLE_CHILD
,
3963 gui_motif_menu_fontlist(w
);
3965 radio_box
= XmCreateRadioBox(frame
, "radioBox",
3968 str
= XmStringCreateSimple( _("Up"));
3969 frdp
->up
= XtVaCreateManagedWidget("upRadioButton",
3970 xmToggleButtonGadgetClass
, radio_box
,
3971 XmNlabelString
, str
,
3975 gui_motif_menu_fontlist(frdp
->up
);
3977 str
= XmStringCreateSimple(_("Down"));
3978 frdp
->down
= XtVaCreateManagedWidget("downRadioButton",
3979 xmToggleButtonGadgetClass
, radio_box
,
3980 XmNlabelString
, str
,
3984 gui_motif_menu_fontlist(frdp
->down
);
3986 XtManageChild(radio_box
);
3987 XtManageChild(frame
);
3990 toggle_form
= XtVaCreateWidget("toggleForm",
3991 xmFormWidgetClass
, frdp
->dialog
,
3992 XmNleftAttachment
, XmATTACH_FORM
,
3994 XmNrightAttachment
, XmATTACH_WIDGET
,
3995 XmNrightWidget
, frame
,
3997 XmNtopAttachment
, XmATTACH_WIDGET
,
3998 XmNtopWidget
, input_form
,
4000 XmNbottomAttachment
, XmATTACH_FORM
,
4004 str
= XmStringCreateSimple(_("Match whole word only"));
4005 frdp
->wword
= XtVaCreateManagedWidget("wordToggle",
4006 xmToggleButtonGadgetClass
, toggle_form
,
4007 XmNlabelString
, str
,
4008 XmNtopAttachment
, XmATTACH_FORM
,
4010 XmNleftAttachment
, XmATTACH_FORM
,
4016 str
= XmStringCreateSimple(_("Match case"));
4017 frdp
->mcase
= XtVaCreateManagedWidget("caseToggle",
4018 xmToggleButtonGadgetClass
, toggle_form
,
4019 XmNlabelString
, str
,
4020 XmNleftAttachment
, XmATTACH_FORM
,
4022 XmNtopAttachment
, XmATTACH_WIDGET
,
4023 XmNtopWidget
, frdp
->wword
,
4028 gui_motif_menu_fontlist(frdp
->wword
);
4029 gui_motif_menu_fontlist(frdp
->mcase
);
4031 XtManageChild(toggle_form
);
4033 if (entry_text
!= NULL
)
4034 XmTextFieldSetString(frdp
->what
, (char *)entry_text
);
4035 vim_free(entry_text
);
4037 gui_motif_synch_fonts();
4039 manage_centered(frdp
->dialog
);
4040 activate_dialog_mnemonics(frdp
->dialog
);
4041 XmProcessTraversal(frdp
->what
, XmTRAVERSE_CURRENT
);
4045 gui_mch_find_dialog(eap
)
4051 find_replace_dialog_create(eap
->arg
, FALSE
);
4056 gui_mch_replace_dialog(eap
)
4062 find_replace_dialog_create(eap
->arg
, TRUE
);
4066 * Synchronize all gui elements, which are dependant upon the
4067 * main text font used. Those are in esp. the find/replace dialogs.
4068 * If you don't understand why this should be needed, please try to
4069 * search for "piê¶æ" in iso8859-2.
4072 gui_motif_synch_fonts(void)
4074 SharedFindReplace
*frdp
;
4077 XmFontList font_list
;
4079 /* FIXME: Unless we find out how to create a XmFontList from a XFontSet,
4080 * we just give up here on font synchronization. */
4081 font
= (XFontStruct
*)gui
.norm_font
;
4085 font_list
= gui_motif_create_fontlist(font
);
4087 /* OK this loop is a bit tricky... */
4088 for (do_replace
= 0; do_replace
<= 1; ++do_replace
)
4090 frdp
= (do_replace
) ? (&repl_widgets
) : (&find_widgets
);
4093 XtVaSetValues(frdp
->what
, XmNfontList
, font_list
, NULL
);
4095 XtVaSetValues(frdp
->with
, XmNfontList
, font_list
, NULL
);
4099 XmFontListFree(font_list
);