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.
122 scroll_cb(w
, client_data
, call_data
)
124 XtPointer client_data
, call_data
;
130 sb
= gui_find_scrollbar((long)client_data
);
132 value
= ((XmScrollBarCallbackStruct
*)call_data
)->value
;
133 dragging
= (((XmScrollBarCallbackStruct
*)call_data
)->reason
==
135 gui_drag_scrollbar(sb
, value
, dragging
);
138 #ifdef FEAT_GUI_TABLINE
141 tabline_cb(w
, client_data
, call_data
)
143 XtPointer client_data
, call_data
;
145 XmNotebookCallbackStruct
*nptr
;
147 nptr
= (XmNotebookCallbackStruct
*)call_data
;
148 if (nptr
->reason
!= (int)XmCR_NONE
)
149 send_tabline_event(nptr
->page_number
);
154 tabline_button_cb(w
, client_data
, call_data
)
156 XtPointer client_data
, call_data
;
160 XtVaGetValues(w
, XmNuserData
, &cmd
, NULL
);
161 XtVaGetValues(tabLine_menu
, XmNuserData
, &tab_idx
, NULL
);
163 send_tabline_menu_event(tab_idx
, cmd
);
167 * Tabline single mouse click timeout handler
171 motif_tabline_timer_cb (timed_out
, interval_id
)
173 XtIntervalId
*interval_id
;
175 *((int *)timed_out
) = TRUE
;
179 * check if the tabline tab scroller is clicked
182 tabline_scroller_clicked(scroller_name
, event
)
184 XButtonPressedEvent
*event
;
187 Position pos_x
, pos_y
;
188 Dimension width
, height
;
190 tab_scroll_w
= XtNameToWidget(tabLine
, scroller_name
);
191 if (tab_scroll_w
!= (Widget
)0) {
192 XtVaGetValues(tab_scroll_w
, XmNx
, &pos_x
, XmNy
, &pos_y
, XmNwidth
,
193 &width
, XmNheight
, &height
, NULL
);
195 /* Tab scroller (next) is visible */
196 if ((event
->x
>= pos_x
) && (event
->x
<= pos_x
+ width
) &&
197 (event
->y
>= pos_y
) && (event
->y
<= pos_y
+ height
)) {
198 /* Clicked on the scroller */
208 tabline_menu_cb(w
, closure
, e
, continue_dispatch
)
212 Boolean
*continue_dispatch
;
215 XButtonPressedEvent
*event
;
218 Cardinal numChildren
;
219 static XtIntervalId timer
= (XtIntervalId
)0;
220 static int timed_out
= TRUE
;
222 event
= (XButtonPressedEvent
*)e
;
224 if (event
->button
== Button1
)
226 if (tabline_scroller_clicked("MajorTabScrollerNext", event
)
227 || tabline_scroller_clicked("MajorTabScrollerPrevious", event
))
232 XtRemoveTimeOut(timer
);
236 * Double click on the tabline gutter, add a new tab
238 send_tabline_menu_event(0, TABLINE_MENU_NEW
);
243 * Single click on the tabline gutter, start a timer to check
246 timer
= XtAppAddTimeOut(app_context
, (long_u
)p_mouset
,
247 motif_tabline_timer_cb
, &timed_out
);
253 if (event
->button
!= Button3
)
256 /* When ignoring events don't show the menu. */
264 if (event
->subwindow
!= None
)
266 tab_w
= XtWindowToWidget(XtDisplay(w
), event
->subwindow
);
267 /* LINTED: avoid warning: dubious operation on enum */
268 if (tab_w
!= (Widget
)0 && XmIsPushButton(tab_w
))
269 XtVaGetValues(tab_w
, XmNpageNumber
, &tab_idx
, NULL
);
272 XtVaSetValues(tabLine_menu
, XmNuserData
, tab_idx
, NULL
);
273 XtVaGetValues(tabLine_menu
, XmNchildren
, &children
, XmNnumChildren
,
275 XtManageChildren(children
, numChildren
);
276 XmMenuPosition(tabLine_menu
, (XButtonPressedEvent
*)e
) ;
277 XtManageChild(tabLine_menu
);
282 tabline_balloon_cb(beval
, state
)
289 if (beval
->target
== (Widget
)0)
292 XtVaGetValues(beval
->target
, XmNpageNumber
, &nr
, NULL
);
293 tp
= find_tabpage(nr
);
297 get_tabline_label(tp
, TRUE
);
298 gui_mch_post_balloon(beval
, NameBuff
);
304 * End of call-back routines
308 * Implement three dimensional shading of insensitive labels.
313 #include <Xm/LabelP.h>
315 static XtExposeProc old_label_expose
= NULL
;
317 static void label_expose
__ARGS((Widget _w
, XEvent
*_event
, Region _region
));
320 label_expose(_w
, _event
, _region
)
326 XmLabelWidget lw
= (XmLabelWidget
)_w
;
327 unsigned char label_type
= (int)XmSTRING
;
329 XtVaGetValues(_w
, XmNlabelType
, &label_type
, (XtPointer
)0);
331 if (XtIsSensitive(_w
) || label_type
!= (int)XmSTRING
)
332 (*old_label_expose
)(_w
, _event
, _region
);
340 _XmFontListGetDefaultFont(lw
->label
.font
, &fs
);
342 /* FIXME: we should be doing the whole drawing ourself here. */
343 insensitiveGC
= lw
->label
.insensitive_GC
;
345 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
346 dynamic
= GCClipMask
| GCClipXOrigin
| GCClipYOrigin
;
347 values
.graphics_exposures
= False
;
352 values
.font
= fs
->fid
;
355 if (lw
->primitive
.top_shadow_pixmap
!= None
356 && lw
->primitive
.top_shadow_pixmap
!= XmUNSPECIFIED_PIXMAP
)
358 mask
|= GCFillStyle
| GCTile
;
359 values
.fill_style
= FillTiled
;
360 values
.tile
= lw
->primitive
.top_shadow_pixmap
;
363 lw
->label
.TextRect
.x
+= 1;
364 lw
->label
.TextRect
.y
+= 1;
365 if (lw
->label
._acc_text
!= 0)
367 lw
->label
.acc_TextRect
.x
+= 1;
368 lw
->label
.acc_TextRect
.y
+= 1;
371 values
.foreground
= lw
->primitive
.top_shadow_color
;
372 values
.background
= lw
->core
.background_pixel
;
374 lw
->label
.insensitive_GC
= XtAllocateGC((Widget
)lw
, 0, mask
,
375 &values
, dynamic
, (XtGCMask
)0);
376 (*old_label_expose
)(_w
, _event
, _region
);
377 XtReleaseGC(_w
, lw
->label
.insensitive_GC
);
379 lw
->label
.TextRect
.x
-= 1;
380 lw
->label
.TextRect
.y
-= 1;
381 if (lw
->label
._acc_text
!= 0)
383 lw
->label
.acc_TextRect
.x
-= 1;
384 lw
->label
.acc_TextRect
.y
-= 1;
387 values
.foreground
= lw
->primitive
.bottom_shadow_color
;
388 values
.background
= lw
->core
.background_pixel
;
390 lw
->label
.insensitive_GC
= XtAllocateGC((Widget
) lw
, 0, mask
,
391 &values
, dynamic
, (XtGCMask
)0);
392 (*old_label_expose
)(_w
, _event
, _region
);
393 XtReleaseGC(_w
, lw
->label
.insensitive_GC
);
395 lw
->label
.insensitive_GC
= insensitiveGC
;
400 * Create all the motif widgets necessary.
403 gui_x11_create_widgets()
405 #ifdef FEAT_GUI_TABLINE
406 Widget button
, scroller
;
413 * Install the 3D shade effect drawing routines.
415 if (old_label_expose
== NULL
)
417 old_label_expose
= xmLabelWidgetClass
->core_class
.expose
;
418 xmLabelWidgetClass
->core_class
.expose
= label_expose
;
422 * Start out by adding the configured border width into the border offset
424 gui
.border_offset
= gui
.border_width
;
427 * Install the tearOffModel resource converter.
429 #if (XmVersion >= 1002)
430 XmRepTypeInstallTearOffModelConverter();
433 /* Make sure the "Quit" menu entry of the window manager is ignored */
434 XtVaSetValues(vimShell
, XmNdeleteResponse
, XmDO_NOTHING
, NULL
);
436 vimForm
= XtVaCreateManagedWidget("vimForm",
437 xmFormWidgetClass
, vimShell
,
439 XmNhighlightThickness
, 0,
440 XmNshadowThickness
, 0,
443 XmNresizePolicy
, XmRESIZE_ANY
,
445 gui_motif_menu_colors(vimForm
);
449 Arg al
[7]; /* Make sure there is enough room for arguments! */
452 # if (XmVersion >= 1002)
453 XtSetArg(al
[ac
], XmNtearOffModel
, tearoff_val
); ac
++;
455 XtSetArg(al
[ac
], XmNleftAttachment
, XmATTACH_FORM
); ac
++;
456 XtSetArg(al
[ac
], XmNtopAttachment
, XmATTACH_FORM
); ac
++;
457 XtSetArg(al
[ac
], XmNrightAttachment
, XmATTACH_FORM
); ac
++;
458 # ifndef FEAT_TOOLBAR
459 /* Always stick to right hand side. */
460 XtSetArg(al
[ac
], XmNrightOffset
, 0); ac
++;
462 XtSetArg(al
[ac
], XmNmarginHeight
, 0); ac
++;
463 menuBar
= XmCreateMenuBar(vimForm
, "menuBar", al
, ac
);
464 XtManageChild(menuBar
);
466 /* Remember the default colors, needed for ":hi clear". */
467 XtVaGetValues(menuBar
,
468 XmNbackground
, &gui
.menu_def_bg_pixel
,
469 XmNforeground
, &gui
.menu_def_fg_pixel
,
471 gui_motif_menu_colors(menuBar
);
477 * Create an empty ToolBar. We should get buttons defined from menu.vim.
479 toolBarFrame
= XtVaCreateWidget("toolBarFrame",
480 xmFrameWidgetClass
, vimForm
,
481 XmNshadowThickness
, 0,
484 XmNleftAttachment
, XmATTACH_FORM
,
485 XmNrightAttachment
, XmATTACH_FORM
,
487 gui_motif_menu_colors(toolBarFrame
);
489 toolBar
= XtVaCreateManagedWidget("toolBar",
490 xmRowColumnWidgetClass
, toolBarFrame
,
491 XmNchildType
, XmFRAME_WORKAREA_CHILD
,
492 XmNrowColumnType
, XmWORK_AREA
,
493 XmNorientation
, XmHORIZONTAL
,
494 XmNtraversalOn
, False
,
495 XmNisHomogeneous
, False
,
496 XmNpacking
, XmPACK_TIGHT
,
498 XmNshadowThickness
, 0,
499 XmNhighlightThickness
, 0,
504 gui_motif_menu_colors(toolBar
);
508 #ifdef FEAT_GUI_TABLINE
509 /* Create the Vim GUI tabline */
511 XtSetArg(args
[n
], XmNbindingType
, XmNONE
); n
++;
512 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
513 XtSetArg(args
[n
], XmNbackPageSize
, XmNONE
); n
++;
514 XtSetArg(args
[n
], XmNbackPageNumber
, 0); n
++;
515 XtSetArg(args
[n
], XmNbackPagePlacement
, XmTOP_RIGHT
); n
++;
516 XtSetArg(args
[n
], XmNmajorTabSpacing
, 0); n
++;
517 XtSetArg(args
[n
], XmNshadowThickness
, 0); n
++;
518 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
519 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
520 tabLine
= XmCreateNotebook(vimForm
, "Vim tabline", args
, n
);
522 XtAddCallback(tabLine
, XmNpageChangedCallback
, (XtCallbackProc
)tabline_cb
,
524 XtAddEventHandler(tabLine
, ButtonPressMask
, False
,
525 (XtEventHandler
)tabline_menu_cb
, NULL
);
527 gui
.tabline_height
= TABLINE_HEIGHT
;
530 * Set the size of the minor next/prev scrollers to zero, so
531 * that they are not displayed. Due to a bug in OpenMotif 2.3,
532 * even if these children widget are unmanaged, they are again
533 * managed by the Notebook widget and the notebook widget geometry
534 * is adjusted to account for the minor scroller widgets.
536 scroller
= XtNameToWidget(tabLine
, "MinorTabScrollerNext");
537 XtVaSetValues(scroller
, XmNwidth
, 0, XmNresizable
, False
,
538 XmNtraversalOn
, False
, NULL
);
539 scroller
= XtNameToWidget(tabLine
, "MinorTabScrollerPrevious");
540 XtVaSetValues(scroller
, XmNwidth
, 0, XmNresizable
, False
,
541 XmNtraversalOn
, False
, NULL
);
543 /* Create the tabline popup menu */
544 tabLine_menu
= XmCreatePopupMenu(tabLine
, "tabline popup", NULL
, 0);
546 /* Add the buttons to the menu */
548 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_CLOSE
); n
++;
549 xms
= XmStringCreate((char *)"Close tab", STRING_TAG
);
550 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
551 button
= XmCreatePushButton(tabLine_menu
, "Close", args
, n
);
552 XtAddCallback(button
, XmNactivateCallback
,
553 (XtCallbackProc
)tabline_button_cb
, NULL
);
557 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_NEW
); n
++;
558 xms
= XmStringCreate((char *)"New Tab", STRING_TAG
);
559 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
560 button
= XmCreatePushButton(tabLine_menu
, "New Tab", args
, n
);
561 XtAddCallback(button
, XmNactivateCallback
,
562 (XtCallbackProc
)tabline_button_cb
, NULL
);
566 XtSetArg(args
[n
], XmNuserData
, TABLINE_MENU_OPEN
); n
++;
567 xms
= XmStringCreate((char *)"Open tab...", STRING_TAG
);
568 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
569 button
= XmCreatePushButton(tabLine_menu
, "Open tab...", args
, n
);
570 XtAddCallback(button
, XmNactivateCallback
,
571 (XtCallbackProc
)tabline_button_cb
, NULL
);
575 textAreaForm
= XtVaCreateManagedWidget("textAreaForm",
576 xmFormWidgetClass
, vimForm
,
577 XmNleftAttachment
, XmATTACH_FORM
,
578 XmNrightAttachment
, XmATTACH_FORM
,
579 XmNbottomAttachment
, XmATTACH_FORM
,
580 XmNtopAttachment
, XmATTACH_FORM
,
583 XmNresizePolicy
, XmRESIZE_ANY
,
585 gui_motif_scroll_colors(textAreaForm
);
587 textArea
= XtVaCreateManagedWidget("textArea",
588 xmDrawingAreaWidgetClass
, textAreaForm
,
589 XmNforeground
, gui
.norm_pixel
,
590 XmNbackground
, gui
.back_pixel
,
591 XmNleftAttachment
, XmATTACH_FORM
,
592 XmNtopAttachment
, XmATTACH_FORM
,
593 XmNrightAttachment
, XmATTACH_FORM
,
594 XmNbottomAttachment
, XmATTACH_FORM
,
597 * These take some control away from the user, but avoids making them
598 * add resources to get a decent looking setup.
601 XmNhighlightThickness
, 0,
602 XmNshadowThickness
, 0,
609 footer
= XtVaCreateWidget("footer",
610 xmLabelGadgetClass
, vimForm
,
611 XmNalignment
, XmALIGNMENT_BEGINNING
,
614 XmNtraversalOn
, False
,
615 XmNrecomputeSize
, False
,
616 XmNleftAttachment
, XmATTACH_FORM
,
618 XmNrightAttachment
, XmATTACH_FORM
,
619 XmNbottomAttachment
, XmATTACH_FORM
,
621 gui_mch_set_footer((char_u
*) "");
625 * Install the callbacks.
627 gui_x11_callbacks(textArea
, vimForm
);
629 /* Pretend we don't have input focus, we will get an event if we do. */
630 gui
.in_focus
= FALSE
;
634 * Called when the GUI is not going to start after all.
637 gui_x11_destroy_widgets()
647 gui_mch_set_text_area_pos(x
, y
, w
, h
)
654 /* Give keyboard focus to the textArea instead of the toolbar. */
660 gui_x11_set_back_color()
662 if (textArea
!= NULL
)
663 #if (XmVersion >= 1002)
664 XmChangeColor(textArea
, gui
.back_pixel
);
666 XtVaSetValues(textArea
,
667 XmNbackground
, gui
.back_pixel
,
673 * Manage dialog centered on pointer. This could be used by the Athena code as
677 manage_centered(dialog_child
)
680 Widget shell
= XtParent(dialog_child
);
683 unsigned int width
, height
, border_width
, depth
;
684 int x
, y
, win_x
, win_y
, maxX
, maxY
;
685 Boolean mappedWhenManaged
;
687 /* Temporarily set value of XmNmappedWhenManaged
688 to stop the dialog from popping up right away */
689 XtVaGetValues(shell
, XmNmappedWhenManaged
, &mappedWhenManaged
, 0);
690 XtVaSetValues(shell
, XmNmappedWhenManaged
, False
, 0);
692 XtManageChild(dialog_child
);
694 /* Get the pointer position (x, y) */
695 XQueryPointer(XtDisplay(shell
), XtWindow(shell
), &root
, &child
,
696 &x
, &y
, &win_x
, &win_y
, &mask
);
698 /* Translate the pointer position (x, y) into a position for the new
699 window that will place the pointer at its center */
700 XGetGeometry(XtDisplay(shell
), XtWindow(shell
), &root
, &win_x
, &win_y
,
701 &width
, &height
, &border_width
, &depth
);
702 width
+= 2 * border_width
;
703 height
+= 2 * border_width
;
707 /* Ensure that the dialog remains on screen */
708 maxX
= XtScreen(shell
)->width
- width
;
709 maxY
= XtScreen(shell
)->height
- height
;
719 /* Set desired window position in the DialogShell */
720 XtVaSetValues(shell
, XmNx
, x
, XmNy
, y
, NULL
);
725 /* Restore the value of XmNmappedWhenManaged */
726 XtVaSetValues(shell
, XmNmappedWhenManaged
, mappedWhenManaged
, 0);
729 #if defined(FEAT_MENU) || defined(FEAT_SUN_WORKSHOP) \
730 || defined(FEAT_GUI_DIALOG) || defined(PROTO)
733 * Encapsulate the way an XmFontList is created.
736 gui_motif_create_fontlist(font
)
739 XmFontList font_list
;
741 # if (XmVersion <= 1001)
742 /* Motif 1.1 method */
743 font_list
= XmFontListCreate(font
, STRING_TAG
);
745 /* Motif 1.2 method */
746 XmFontListEntry font_list_entry
;
748 font_list_entry
= XmFontListEntryCreate(STRING_TAG
, XmFONT_IS_FONT
,
750 font_list
= XmFontListAppendEntry(NULL
, font_list_entry
);
751 XmFontListEntryFree(&font_list_entry
);
756 # if ((XmVersion > 1001) && defined(FEAT_XFONTSET)) || defined(PROTO)
758 gui_motif_fontset2fontlist(fontset
)
761 XmFontList font_list
;
763 /* Motif 1.2 method */
764 XmFontListEntry font_list_entry
;
766 font_list_entry
= XmFontListEntryCreate(STRING_TAG
,
768 (XtPointer
)*fontset
);
769 font_list
= XmFontListAppendEntry(NULL
, font_list_entry
);
770 XmFontListEntryFree(&font_list_entry
);
777 #if defined(FEAT_MENU) || defined(PROTO)
782 static void gui_motif_add_actext
__ARGS((vimmenu_T
*menu
));
783 #if (XmVersion >= 1002)
784 static void toggle_tearoff
__ARGS((Widget wid
));
785 static void gui_mch_recurse_tearoffs
__ARGS((vimmenu_T
*menu
));
787 static void submenu_change
__ARGS((vimmenu_T
*mp
, int colors
));
789 static void do_set_mnemonics
__ARGS((int enable
));
790 static int menu_enabled
= TRUE
;
793 gui_mch_enable_menu(flag
)
798 XtManageChild(menuBar
);
800 if (XtIsManaged(XtParent(toolBar
)))
802 /* toolBar is attached to top form */
803 XtVaSetValues(XtParent(toolBar
),
804 XmNtopAttachment
, XmATTACH_WIDGET
,
805 XmNtopWidget
, menuBar
,
807 #ifdef FEAT_GUI_TABLINE
810 XtVaSetValues(tabLine
,
811 XmNtopAttachment
, XmATTACH_WIDGET
,
812 XmNtopWidget
, XtParent(toolBar
),
814 XtVaSetValues(textAreaForm
,
815 XmNtopAttachment
, XmATTACH_WIDGET
,
816 XmNtopWidget
, tabLine
,
821 XtVaSetValues(textAreaForm
,
822 XmNtopAttachment
, XmATTACH_WIDGET
,
823 XmNtopWidget
, XtParent(toolBar
),
829 #ifdef FEAT_GUI_TABLINE
832 XtVaSetValues(tabLine
,
833 XmNtopAttachment
, XmATTACH_WIDGET
,
834 XmNtopWidget
, menuBar
,
836 XtVaSetValues(textAreaForm
,
837 XmNtopAttachment
, XmATTACH_WIDGET
,
838 XmNtopWidget
, tabLine
,
843 XtVaSetValues(textAreaForm
,
844 XmNtopAttachment
, XmATTACH_WIDGET
,
845 XmNtopWidget
, menuBar
,
851 XtUnmanageChild(menuBar
);
853 if (XtIsManaged(XtParent(toolBar
)))
855 XtVaSetValues(XtParent(toolBar
),
856 XmNtopAttachment
, XmATTACH_FORM
,
858 #ifdef FEAT_GUI_TABLINE
861 XtVaSetValues(tabLine
,
862 XmNtopAttachment
, XmATTACH_WIDGET
,
863 XmNtopWidget
, XtParent(toolBar
),
865 XtVaSetValues(textAreaForm
,
866 XmNtopAttachment
, XmATTACH_WIDGET
,
867 XmNtopWidget
, tabLine
,
872 XtVaSetValues(textAreaForm
,
873 XmNtopAttachment
, XmATTACH_WIDGET
,
874 XmNtopWidget
, XtParent(toolBar
),
880 #ifdef FEAT_GUI_TABLINE
883 XtVaSetValues(tabLine
,
884 XmNtopAttachment
, XmATTACH_FORM
,
886 XtVaSetValues(textAreaForm
,
887 XmNtopAttachment
, XmATTACH_WIDGET
,
888 XmNtopWidget
, tabLine
,
893 XtVaSetValues(textAreaForm
,
894 XmNtopAttachment
, XmATTACH_FORM
,
902 * Enable or disable mnemonics for the toplevel menus.
905 gui_motif_set_mnemonics(enable
)
909 * Don't enable menu mnemonics when the menu bar is disabled, LessTif
910 * crashes when using a mnemonic then.
914 do_set_mnemonics(enable
);
918 do_set_mnemonics(enable
)
923 for (menu
= root_menu
; menu
!= NULL
; menu
= menu
->next
)
924 if (menu
->id
!= (Widget
)0)
925 XtVaSetValues(menu
->id
,
926 XmNmnemonic
, enable
? menu
->mnemonic
: NUL
,
931 gui_mch_add_menu(menu
, idx
)
937 vimmenu_T
*parent
= menu
->parent
;
940 if (menu_is_popup(menu
->name
))
945 /* Only create the popup menu when it's actually used, otherwise there
946 * is a delay when using the right mouse button. */
947 # if (XmVersion <= 1002)
948 if (mouse_model_popup())
951 if (gui
.menu_bg_pixel
!= INVALCOLOR
)
953 XtSetArg(arg
[0], XmNbackground
, gui
.menu_bg_pixel
); n
++;
955 if (gui
.menu_fg_pixel
!= INVALCOLOR
)
957 XtSetArg(arg
[1], XmNforeground
, gui
.menu_fg_pixel
); n
++;
959 menu
->submenu_id
= XmCreatePopupMenu(textArea
, "contextMenu",
961 menu
->id
= (Widget
)0;
967 if (!menu_is_menubar(menu
->name
)
968 || (parent
!= NULL
&& parent
->submenu_id
== (Widget
)0))
971 label
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
974 menu
->id
= XtVaCreateWidget("subMenu",
975 xmCascadeButtonWidgetClass
,
976 (parent
== NULL
) ? menuBar
: parent
->submenu_id
,
977 XmNlabelString
, label
,
978 XmNmnemonic
, p_wak
[0] == 'n' ? NUL
: menu
->mnemonic
,
979 #if (XmVersion >= 1002)
980 /* submenu: count the tearoff item (needed for LessTif) */
981 XmNpositionIndex
, idx
+ (parent
!= NULL
982 && tearoff_val
== (int)XmTEAR_OFF_ENABLED
? 1 : 0),
985 gui_motif_menu_colors(menu
->id
);
986 gui_motif_menu_fontlist(menu
->id
);
989 if (menu
->id
== (Widget
)0) /* failed */
992 /* add accelerator text */
993 gui_motif_add_actext(menu
);
995 shell
= XtVaCreateWidget("subMenuShell",
996 xmMenuShellWidgetClass
, menu
->id
,
1000 gui_motif_menu_colors(shell
);
1001 menu
->submenu_id
= XtVaCreateWidget("rowColumnMenu",
1002 xmRowColumnWidgetClass
, shell
,
1003 XmNrowColumnType
, XmMENU_PULLDOWN
,
1005 gui_motif_menu_colors(menu
->submenu_id
);
1007 if (menu
->submenu_id
== (Widget
)0) /* failed */
1010 #if (XmVersion >= 1002)
1011 /* Set the colors for the tear off widget */
1012 toggle_tearoff(menu
->submenu_id
);
1015 XtVaSetValues(menu
->id
,
1016 XmNsubMenuId
, menu
->submenu_id
,
1020 * The "Help" menu is a special case, and should be placed at the far
1021 * right hand side of the menu-bar. It's recognized by its high priority.
1023 if (parent
== NULL
&& menu
->priority
>= 9999)
1024 XtVaSetValues(menuBar
,
1025 XmNmenuHelpWidget
, menu
->id
,
1029 * When we add a top-level item to the menu bar, we can figure out how
1030 * high the menu bar should be.
1033 gui_mch_compute_menu_height(menu
->id
);
1038 * Add mnemonic and accelerator text to a menu button.
1041 gui_motif_add_actext(menu
)
1046 /* Add accelerator text, if there is one */
1047 if (menu
->actext
!= NULL
&& menu
->id
!= (Widget
)0)
1049 label
= XmStringCreate((char *)menu
->actext
, STRING_TAG
);
1052 XtVaSetValues(menu
->id
, XmNacceleratorText
, label
, NULL
);
1053 XmStringFree(label
);
1058 gui_mch_toggle_tearoffs(enable
)
1061 #if (XmVersion >= 1002)
1063 tearoff_val
= (int)XmTEAR_OFF_ENABLED
;
1065 tearoff_val
= (int)XmTEAR_OFF_DISABLED
;
1066 toggle_tearoff(menuBar
);
1067 gui_mch_recurse_tearoffs(root_menu
);
1071 #if (XmVersion >= 1002)
1073 * Set the tearoff for one menu widget on or off, and set the color of the
1082 XtVaSetValues(wid
, XmNtearOffModel
, tearoff_val
, NULL
);
1083 if (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1084 && (w
= XmGetTearOffControl(wid
)) != (Widget
)0)
1085 gui_motif_menu_colors(w
);
1089 gui_mch_recurse_tearoffs(menu
)
1092 while (menu
!= NULL
)
1094 if (!menu_is_popup(menu
->name
))
1096 if (menu
->submenu_id
!= (Widget
)0)
1097 toggle_tearoff(menu
->submenu_id
);
1098 gui_mch_recurse_tearoffs(menu
->children
);
1106 gui_mch_text_area_extra_height()
1108 Dimension shadowHeight
;
1110 XtVaGetValues(textAreaForm
, XmNshadowThickness
, &shadowHeight
, NULL
);
1111 return shadowHeight
;
1115 * Compute the height of the menu bar.
1116 * We need to check all the items for their position and height, for the case
1117 * there are several rows, and/or some characters extend higher or lower.
1120 gui_mch_compute_menu_height(id
)
1121 Widget id
; /* can be NULL when deleting menu */
1124 Dimension margin
, shadow
;
1126 static Dimension height
= 21; /* normal height of a menu item */
1129 * Get the height of the new item, before managing it, because it will
1130 * still reflect the font size. After managing it depends on the menu
1131 * height, which is what we just wanted to get!.
1133 if (id
!= (Widget
)0)
1134 XtVaGetValues(id
, XmNheight
, &height
, NULL
);
1136 /* Find any menu Widget, to be able to call XtManageChild() */
1138 for (mp
= root_menu
; mp
!= NULL
; mp
= mp
->next
)
1139 if (mp
->id
!= (Widget
)0 && menu_is_menubar(mp
->name
))
1146 * Now manage the menu item, to make them all be positioned (makes an
1147 * extra row when needed, removes it when not needed).
1149 if (id
!= (Widget
)0)
1153 * Now find the menu item that is the furthest down, and get it's position.
1156 for (mp
= root_menu
; mp
!= NULL
; mp
= mp
->next
)
1158 if (mp
->id
!= (Widget
)0 && menu_is_menubar(mp
->name
))
1160 XtVaGetValues(mp
->id
, XmNy
, &y
, NULL
);
1166 XtVaGetValues(menuBar
,
1167 XmNmarginHeight
, &margin
,
1168 XmNshadowThickness
, &shadow
,
1172 * This computation is the result of trial-and-error:
1173 * maxy = The maximum position of an item; required for when there are
1175 * height = height of an item, before managing it; Hopefully this will
1176 * change with the font height. Includes shadow-border.
1177 * shadow = shadow-border; must be subtracted from the height.
1178 * margin = margin around the menu buttons; Must be added.
1179 * Add 4 for the underlining of shortcut keys.
1181 gui
.menu_height
= maxy
+ height
- 2 * shadow
+ 2 * margin
+ 4;
1183 /* Somehow the menu bar doesn't resize automatically. Set it here,
1184 * even though this is a catch 22. Don't do this when starting up,
1185 * somehow the menu gets very high then. */
1186 if (gui
.shell_created
)
1187 XtVaSetValues(menuBar
, XmNheight
, gui
.menu_height
, NULL
);
1193 * Icons used by the toolbar code.
1195 #include "gui_x11_pm.h"
1197 static int check_xpm
__ARGS((char_u
*path
));
1198 static char **get_toolbar_pixmap
__ARGS((vimmenu_T
*menu
, char **fname
));
1199 static int add_pixmap_args
__ARGS((vimmenu_T
*menu
, Arg
*args
, int n
));
1202 * Read an Xpm file. Return OK or FAIL.
1208 XpmAttributes attrs
;
1213 attrs
.valuemask
= 0;
1215 /* Create the "sensitive" pixmap */
1216 status
= XpmReadFileToPixmap(gui
.dpy
,
1217 RootWindow(gui
.dpy
, DefaultScreen(gui
.dpy
)),
1218 (char *)path
, &map
, &mask
, &attrs
);
1219 XpmFreeAttributes(&attrs
);
1221 if (status
== XpmSuccess
)
1228 * Allocated a pixmap for toolbar menu "menu".
1229 * When it's to be read from a file, "fname" is set to the file name
1230 * (in allocated memory).
1231 * Return a blank pixmap if it fails.
1234 get_toolbar_pixmap(menu
, fname
)
1238 char_u buf
[MAXPATHL
]; /* buffer storing expanded pathname */
1239 char **xpm
= NULL
; /* xpm array */
1243 buf
[0] = NUL
; /* start with NULL path */
1245 if (menu
->iconfile
!= NULL
)
1247 /* Use the "icon=" argument. */
1248 gui_find_iconfile(menu
->iconfile
, buf
, "xpm");
1249 res
= check_xpm(buf
);
1251 /* If it failed, try using the menu name. */
1252 if (res
== FAIL
&& gui_find_bitmap(menu
->name
, buf
, "xpm") == OK
)
1253 res
= check_xpm(buf
);
1256 *fname
= (char *)vim_strsave(buf
);
1257 return tb_blank_xpm
;
1261 if (menu
->icon_builtin
|| gui_find_bitmap(menu
->name
, buf
, "xpm") == FAIL
)
1263 if (menu
->iconidx
>= 0 && menu
->iconidx
1264 < (sizeof(built_in_pixmaps
) / sizeof(built_in_pixmaps
[0])))
1265 xpm
= built_in_pixmaps
[menu
->iconidx
];
1274 * Add arguments for the toolbar pixmap to a menu item.
1277 add_pixmap_args(menu
, args
, n
)
1282 vim_free(menu
->xpm_fname
);
1283 menu
->xpm
= get_toolbar_pixmap(menu
, &menu
->xpm_fname
);
1284 if (menu
->xpm
== NULL
)
1286 XtSetArg(args
[n
], XmNlabelType
, XmSTRING
); n
++;
1290 if (menu
->xpm_fname
!= NULL
)
1292 XtSetArg(args
[n
], XmNpixmapFile
, menu
->xpm_fname
); n
++;
1294 XtSetArg(args
[n
], XmNpixmapData
, menu
->xpm
); n
++;
1295 XtSetArg(args
[n
], XmNlabelLocation
, XmBOTTOM
); n
++;
1299 #endif /* FEAT_TOOLBAR */
1302 gui_mch_add_menu_item(menu
, idx
)
1307 vimmenu_T
*parent
= menu
->parent
;
1313 # if (XmVersion <= 1002)
1314 /* Don't add Popup menu items when the popup menu isn't used. */
1315 if (menu_is_child_of_popup(menu
) && !mouse_model_popup())
1319 # ifdef FEAT_TOOLBAR
1320 if (menu_is_toolbar(parent
->name
))
1323 XmString xms
= NULL
; /* fallback label if pixmap not found */
1328 if (menu_is_separator(menu
->name
))
1334 * A separator has the format "-sep%d[:%d]-". The optional :%d is
1335 * a width specifier. If no width is specified then we choose one.
1337 cp
= (char *)vim_strchr(menu
->name
, ':');
1339 wid
= (Dimension
)atoi(++cp
);
1344 /* We better use a FormWidget here, since it's far more
1345 * flexible in terms of size. */
1346 type
= xmFormWidgetClass
;
1347 XtSetArg(args
[n
], XmNwidth
, wid
); n
++;
1349 type
= xmSeparatorWidgetClass
;
1350 XtSetArg(args
[n
], XmNwidth
, wid
); n
++;
1351 XtSetArg(args
[n
], XmNminWidth
, wid
); n
++;
1352 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
1353 XtSetArg(args
[n
], XmNseparatorType
, XmSHADOW_ETCHED_IN
); n
++;
1358 /* Without shadows one can't sense whatever the button has been
1359 * pressed or not! However we wan't to save a bit of space...
1360 * Need the highlightThickness to see the focus.
1362 XtSetArg(args
[n
], XmNhighlightThickness
, 1); n
++;
1363 XtSetArg(args
[n
], XmNhighlightOnEnter
, True
); n
++;
1364 XtSetArg(args
[n
], XmNmarginWidth
, 0); n
++;
1365 XtSetArg(args
[n
], XmNmarginHeight
, 0); n
++;
1366 XtSetArg(args
[n
], XmNtraversalOn
, False
); n
++;
1367 /* Set the label here, so that we can switch between icons/text
1368 * by changing the XmNlabelType resource. */
1369 xms
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
1370 XtSetArg(args
[n
], XmNlabelString
, xms
); n
++;
1372 n
= add_pixmap_args(menu
, args
, n
);
1374 type
= xmEnhancedButtonWidgetClass
;
1377 XtSetArg(args
[n
], XmNpositionIndex
, idx
); n
++;
1378 if (menu
->id
== NULL
)
1380 menu
->id
= XtCreateManagedWidget((char *)menu
->dname
,
1381 type
, toolBar
, args
, n
);
1382 if (menu
->id
!= NULL
&& type
== xmEnhancedButtonWidgetClass
)
1384 XtAddCallback(menu
->id
,
1385 XmNactivateCallback
, gui_x11_menu_cb
, menu
);
1387 XtAddEventHandler(menu
->id
, EnterWindowMask
, False
,
1388 toolbarbutton_enter_cb
, menu
);
1389 XtAddEventHandler(menu
->id
, LeaveWindowMask
, False
,
1390 toolbarbutton_leave_cb
, menu
);
1395 XtSetValues(menu
->id
, args
, n
);
1400 gui_mch_menu_set_tip(menu
);
1403 menu
->parent
= parent
;
1404 menu
->submenu_id
= NULL
;
1405 /* When adding first item to toolbar it might have to be enabled .*/
1406 if (!XtIsManaged(XtParent(toolBar
))
1407 && vim_strchr(p_go
, GO_TOOLBAR
) != NULL
)
1408 gui_mch_show_toolbar(TRUE
);
1409 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
1411 } /* toolbar menu item */
1414 /* No parent, must be a non-menubar menu */
1415 if (parent
->submenu_id
== (Widget
)0)
1418 menu
->submenu_id
= (Widget
)0;
1420 /* Add menu separator */
1421 if (menu_is_separator(menu
->name
))
1423 menu
->id
= XtVaCreateWidget("subMenu",
1424 xmSeparatorGadgetClass
, parent
->submenu_id
,
1425 #if (XmVersion >= 1002)
1426 /* count the tearoff item (needed for LessTif) */
1427 XmNpositionIndex
, idx
+ (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1431 gui_motif_menu_colors(menu
->id
);
1435 label
= XmStringCreate((char *)menu
->dname
, STRING_TAG
);
1438 menu
->id
= XtVaCreateWidget("subMenu",
1439 xmPushButtonWidgetClass
, parent
->submenu_id
,
1440 XmNlabelString
, label
,
1441 XmNmnemonic
, menu
->mnemonic
,
1442 #if (XmVersion >= 1002)
1443 /* count the tearoff item (needed for LessTif) */
1444 XmNpositionIndex
, idx
+ (tearoff_val
== (int)XmTEAR_OFF_ENABLED
1448 gui_motif_menu_colors(menu
->id
);
1449 gui_motif_menu_fontlist(menu
->id
);
1450 XmStringFree(label
);
1452 if (menu
->id
!= (Widget
)0)
1454 XtAddCallback(menu
->id
, XmNactivateCallback
, gui_x11_menu_cb
,
1456 /* add accelerator text */
1457 gui_motif_add_actext(menu
);
1461 #if (XmVersion <= 1002) || defined(PROTO)
1463 * This function will destroy/create the popup menus dynamically,
1464 * according to the value of 'mousemodel'.
1465 * This will fix the "right mouse button freeze" that occurs when
1466 * there exists a popup menu but it isn't managed.
1469 gui_motif_update_mousemodel(menu
)
1474 /* When GUI hasn't started the menus have not been created. */
1480 if (menu
->children
!= NULL
)
1482 if (menu_is_popup(menu
->name
))
1484 if (mouse_model_popup())
1486 /* Popup menu will be used. Create the popup menus. */
1487 gui_mch_add_menu(menu
, idx
);
1488 gui_motif_update_mousemodel(menu
->children
);
1492 /* Popup menu will not be used. Destroy the popup menus. */
1493 gui_motif_update_mousemodel(menu
->children
);
1494 gui_mch_destroy_menu(menu
);
1498 else if (menu_is_child_of_popup(menu
))
1500 if (mouse_model_popup())
1501 gui_mch_add_menu_item(menu
, idx
);
1503 gui_mch_destroy_menu(menu
);
1512 gui_mch_new_menu_colors()
1514 if (menuBar
== (Widget
)0)
1516 gui_motif_menu_colors(menuBar
);
1518 gui_motif_menu_colors(toolBarFrame
);
1519 gui_motif_menu_colors(toolBar
);
1522 submenu_change(root_menu
, TRUE
);
1526 gui_mch_new_menu_font()
1528 if (menuBar
== (Widget
)0)
1530 submenu_change(root_menu
, FALSE
);
1535 XtVaGetValues(menuBar
, XmNheight
, &height
, NULL
);
1536 gui
.menu_height
= height
;
1538 XtVaGetValues(vimShell
, XtNwidth
, &w
, XtNheight
, &h
, NULL
);
1539 gui_resize_shell(w
, h
1541 - xim_get_status_area_height()
1545 gui_set_shellsize(FALSE
, TRUE
, RESIZE_VERT
);
1549 #if defined(FEAT_BEVAL) || defined(PROTO)
1551 gui_mch_new_tooltip_font()
1553 # ifdef FEAT_TOOLBAR
1556 if (toolBar
== (Widget
)0)
1559 menu
= gui_find_menu((char_u
*)"ToolBar");
1561 submenu_change(menu
, FALSE
);
1566 gui_mch_new_tooltip_colors()
1568 # ifdef FEAT_TOOLBAR
1571 if (toolBar
== (Widget
)0)
1574 toolbar
= gui_find_menu((char_u
*)"ToolBar");
1575 if (toolbar
!= NULL
)
1576 submenu_change(toolbar
, TRUE
);
1582 submenu_change(menu
, colors
)
1584 int colors
; /* TRUE for colors, FALSE for font */
1588 for (mp
= menu
; mp
!= NULL
; mp
= mp
->next
)
1590 if (mp
->id
!= (Widget
)0)
1594 gui_motif_menu_colors(mp
->id
);
1596 /* For a toolbar item: Free the pixmap and allocate a new one,
1597 * so that the background color is right. */
1598 if (mp
->xpm
!= NULL
)
1603 n
= add_pixmap_args(mp
, args
, n
);
1604 XtSetValues(mp
->id
, args
, n
);
1607 /* If we have a tooltip, then we need to change it's font */
1608 if (mp
->tip
!= NULL
)
1612 args
[0].name
= XmNbackground
;
1613 args
[0].value
= gui
.tooltip_bg_pixel
;
1614 args
[1].name
= XmNforeground
;
1615 args
[1].value
= gui
.tooltip_fg_pixel
;
1616 XtSetValues(mp
->tip
->balloonLabel
, &args
[0], XtNumber(args
));
1623 gui_motif_menu_fontlist(mp
->id
);
1625 /* If we have a tooltip, then we need to change it's font */
1626 if (mp
->tip
!= NULL
)
1630 args
[0].name
= XmNfontList
;
1631 args
[0].value
= (XtArgVal
)gui_motif_fontset2fontlist(
1632 &gui
.tooltip_fontset
);
1633 XtSetValues(mp
->tip
->balloonLabel
, &args
[0], XtNumber(args
));
1639 if (mp
->children
!= NULL
)
1641 #if (XmVersion >= 1002)
1642 /* Set the colors/font for the tear off widget */
1643 if (mp
->submenu_id
!= (Widget
)0)
1646 gui_motif_menu_colors(mp
->submenu_id
);
1648 gui_motif_menu_fontlist(mp
->submenu_id
);
1649 toggle_tearoff(mp
->submenu_id
);
1652 /* Set the colors for the children */
1653 submenu_change(mp
->children
, colors
);
1659 * Destroy the machine specific menu widget.
1662 gui_mch_destroy_menu(menu
)
1665 /* Please be sure to destroy the parent widget first (i.e. menu->id).
1666 * On the other hand, problems have been reported that the submenu must be
1669 * This code should be basically identical to that in the file gui_athena.c
1670 * because they are both Xt based.
1672 if (menu
->submenu_id
!= (Widget
)0)
1674 XtDestroyWidget(menu
->submenu_id
);
1675 menu
->submenu_id
= (Widget
)0;
1678 if (menu
->id
!= (Widget
)0)
1682 parent
= XtParent(menu
->id
);
1683 #if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL)
1684 if (parent
== toolBar
&& menu
->tip
!= NULL
)
1686 /* We try to destroy this before the actual menu, because there are
1687 * callbacks, etc. that will be unregistered during the tooltip
1690 * If you call "gui_mch_destroy_beval_area()" after destroying
1691 * menu->id, then the tooltip's window will have already been
1692 * deallocated by Xt, and unknown behaviour will ensue (probably
1695 gui_mch_destroy_beval_area(menu
->tip
);
1699 XtDestroyWidget(menu
->id
);
1700 menu
->id
= (Widget
)0;
1701 if (parent
== menuBar
)
1702 gui_mch_compute_menu_height((Widget
)0);
1704 else if (parent
== toolBar
)
1706 Cardinal num_children
;
1708 /* When removing last toolbar item, don't display the toolbar. */
1709 XtVaGetValues(toolBar
, XmNnumChildren
, &num_children
, NULL
);
1710 if (num_children
== 0)
1711 gui_mch_show_toolbar(FALSE
);
1713 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
1721 gui_mch_show_popupmenu(menu
)
1725 XmMenuPosition(menu
->submenu_id
, gui_x11_get_last_mouse_event());
1726 XtManageChild(menu
->submenu_id
);
1730 #endif /* FEAT_MENU */
1733 * Set the menu and scrollbar colors to their default values.
1736 gui_mch_def_colors()
1740 /* Use the values saved when starting up. These should come from the
1741 * window manager or a resources file. */
1742 gui
.menu_fg_pixel
= gui
.menu_def_fg_pixel
;
1743 gui
.menu_bg_pixel
= gui
.menu_def_bg_pixel
;
1744 gui
.scroll_fg_pixel
= gui
.scroll_def_fg_pixel
;
1745 gui
.scroll_bg_pixel
= gui
.scroll_def_bg_pixel
;
1747 gui
.tooltip_fg_pixel
=
1748 gui_get_color((char_u
*)gui
.rsrc_tooltip_fg_name
);
1749 gui
.tooltip_bg_pixel
=
1750 gui_get_color((char_u
*)gui
.rsrc_tooltip_bg_name
);
1761 gui_mch_set_scrollbar_thumb(sb
, val
, size
, max
)
1767 if (sb
->id
!= (Widget
)0)
1768 XtVaSetValues(sb
->id
,
1770 XmNsliderSize
, size
,
1771 XmNpageIncrement
, (size
> 2 ? size
- 2 : 1),
1772 XmNmaximum
, max
+ 1, /* Motif has max one past the end */
1777 gui_mch_set_scrollbar_pos(sb
, x
, y
, w
, h
)
1784 if (sb
->id
!= (Widget
)0)
1786 if (sb
->type
== SBAR_LEFT
|| sb
->type
== SBAR_RIGHT
)
1789 h
-= gui
.border_offset
;
1791 y
-= gui
.border_offset
;
1792 XtVaSetValues(sb
->id
,
1794 XmNbottomOffset
, -y
- h
,
1799 XtVaSetValues(sb
->id
,
1802 XmNrightOffset
, gui
.which_scrollbars
[SBAR_RIGHT
]
1803 ? gui
.scrollbar_width
: 0,
1806 XtManageChild(sb
->id
);
1811 gui_mch_enable_scrollbar(sb
, flag
)
1818 if (sb
->id
!= (Widget
)0)
1826 XtSetArg(args
[n
], XmNleftOffset
, gui
.scrollbar_width
); n
++;
1830 XtSetArg(args
[n
], XmNrightOffset
, gui
.scrollbar_width
); n
++;
1834 XtSetArg(args
[n
], XmNbottomOffset
, gui
.scrollbar_height
);n
++;
1837 XtSetValues(textArea
, args
, n
);
1838 XtManageChild(sb
->id
);
1842 if (!gui
.which_scrollbars
[sb
->type
])
1844 /* The scrollbars of this type are all disabled, adjust the
1845 * textArea attachment offset. */
1849 XtSetArg(args
[n
], XmNleftOffset
, 0); n
++;
1853 XtSetArg(args
[n
], XmNrightOffset
, 0); n
++;
1857 XtSetArg(args
[n
], XmNbottomOffset
, 0);n
++;
1860 XtSetValues(textArea
, args
, n
);
1862 XtUnmanageChild(sb
->id
);
1868 gui_mch_create_scrollbar(sb
, orient
)
1870 int orient
; /* SBAR_VERT or SBAR_HORIZ */
1876 XtSetArg(args
[n
], XmNminimum
, 0); n
++;
1877 XtSetArg(args
[n
], XmNorientation
,
1878 (orient
== SBAR_VERT
) ? XmVERTICAL
: XmHORIZONTAL
); n
++;
1883 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
1884 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_OPPOSITE_FORM
); n
++;
1885 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
1889 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
1890 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_OPPOSITE_FORM
); n
++;
1891 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
1895 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
1896 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
1897 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
1901 sb
->id
= XtCreateWidget("scrollBar",
1902 xmScrollBarWidgetClass
, textAreaForm
, args
, n
);
1904 /* Remember the default colors, needed for ":hi clear". */
1905 if (gui
.scroll_def_bg_pixel
== (guicolor_T
)0
1906 && gui
.scroll_def_fg_pixel
== (guicolor_T
)0)
1907 XtVaGetValues(sb
->id
,
1908 XmNbackground
, &gui
.scroll_def_bg_pixel
,
1909 XmNforeground
, &gui
.scroll_def_fg_pixel
,
1912 if (sb
->id
!= (Widget
)0)
1914 gui_mch_set_scrollbar_colors(sb
);
1915 XtAddCallback(sb
->id
, XmNvalueChangedCallback
,
1916 scroll_cb
, (XtPointer
)sb
->ident
);
1917 XtAddCallback(sb
->id
, XmNdragCallback
,
1918 scroll_cb
, (XtPointer
)sb
->ident
);
1919 XtAddEventHandler(sb
->id
, KeyPressMask
, FALSE
, gui_x11_key_hit_cb
,
1924 #if defined(FEAT_WINDOWS) || defined(PROTO)
1926 gui_mch_destroy_scrollbar(sb
)
1929 if (sb
->id
!= (Widget
)0)
1930 XtDestroyWidget(sb
->id
);
1935 gui_mch_set_scrollbar_colors(sb
)
1938 if (sb
->id
!= (Widget
)0)
1940 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
1942 #if (XmVersion>=1002)
1943 XmChangeColor(sb
->id
, gui
.scroll_bg_pixel
);
1945 XtVaSetValues(sb
->id
,
1946 XmNtroughColor
, gui
.scroll_bg_pixel
,
1951 if (gui
.scroll_fg_pixel
!= INVALCOLOR
)
1952 XtVaSetValues(sb
->id
,
1953 XmNforeground
, gui
.scroll_fg_pixel
,
1954 #if (XmVersion<1002)
1955 XmNbackground
, gui
.scroll_fg_pixel
,
1960 /* This is needed for the rectangle below the vertical scrollbars. */
1961 if (sb
== &gui
.bottom_sbar
&& textAreaForm
!= (Widget
)0)
1962 gui_motif_scroll_colors(textAreaForm
);
1966 * Miscellaneous stuff:
1972 return(XtWindow(textArea
));
1976 * Look for a widget in the widget tree w, with a mnemonic matching keycode.
1977 * When one is found, simulate a button press on that widget and give it the
1978 * keyboard focus. If the mnemonic is on a label, look in the userData field
1979 * of the label to see if it points to another widget, and give that the focus.
1982 do_mnemonic(Widget w
, unsigned int keycode
)
1984 WidgetList children
;
1987 KeySym mnemonic
= '\0';
1990 unsigned char rowColType
;
1992 if (XtIsComposite(w
))
1994 if (XtClass(w
) == xmRowColumnWidgetClass
)
1996 XtVaGetValues(w
, XmNrowColumnType
, &rowColType
, 0);
1997 isMenu
= (rowColType
!= (unsigned char)XmWORK_AREA
);
2003 XtVaGetValues(w
, XmNchildren
, &children
, XmNnumChildren
,
2005 for (i
= 0; i
< numChildren
; i
++)
2006 do_mnemonic(children
[i
], keycode
);
2011 XtVaGetValues(w
, XmNmnemonic
, &mnemonic
, 0);
2012 if (mnemonic
!= '\0')
2014 mneString
[0] = mnemonic
;
2015 mneString
[1] = '\0';
2016 if (XKeysymToKeycode(XtDisplay(XtParent(w
)),
2017 XStringToKeysym(mneString
)) == keycode
)
2019 if (XtClass(w
) == xmLabelWidgetClass
2020 || XtClass(w
) == xmLabelGadgetClass
)
2022 XtVaGetValues(w
, XmNuserData
, &userData
, 0);
2023 if (userData
!= NULL
&& XtIsWidget(userData
))
2024 XmProcessTraversal(userData
, XmTRAVERSE_CURRENT
);
2028 XKeyPressedEvent keyEvent
;
2030 XmProcessTraversal(w
, XmTRAVERSE_CURRENT
);
2032 memset((char *) &keyEvent
, 0, sizeof(XKeyPressedEvent
));
2033 keyEvent
.type
= KeyPress
;
2034 keyEvent
.serial
= 1;
2035 keyEvent
.send_event
= True
;
2036 keyEvent
.display
= XtDisplay(w
);
2037 keyEvent
.window
= XtWindow(w
);
2038 XtCallActionProc(w
, "Activate", (XEvent
*) & keyEvent
,
2047 * Callback routine for dialog mnemonic processing.
2051 mnemonic_event(Widget w
, XtPointer call_data
, XKeyEvent
*event
)
2053 do_mnemonic(w
, event
->keycode
);
2058 * Search the widget tree under w for widgets with mnemonics. When found, add
2059 * a passive grab to the dialog widget for the mnemonic character, thus
2060 * directing mnemonic events to the dialog widget.
2063 add_mnemonic_grabs(Widget dialog
, Widget w
)
2066 WidgetList children
;
2069 KeySym mnemonic
= '\0';
2070 unsigned char rowColType
;
2072 if (XtIsComposite(w
))
2074 if (XtClass(w
) == xmRowColumnWidgetClass
)
2076 XtVaGetValues(w
, XmNrowColumnType
, &rowColType
, 0);
2077 isMenu
= (rowColType
!= (unsigned char)XmWORK_AREA
);
2083 XtVaGetValues(w
, XmNchildren
, &children
, XmNnumChildren
,
2085 for (i
= 0; i
< numChildren
; i
++)
2086 add_mnemonic_grabs(dialog
, children
[i
]);
2091 XtVaGetValues(w
, XmNmnemonic
, &mnemonic
, 0);
2092 if (mnemonic
!= '\0')
2094 mneString
[0] = mnemonic
;
2095 mneString
[1] = '\0';
2096 XtGrabKey(dialog
, XKeysymToKeycode(XtDisplay(dialog
),
2097 XStringToKeysym(mneString
)),
2098 Mod1Mask
, True
, GrabModeAsync
, GrabModeAsync
);
2104 * Add a handler for mnemonics in a dialog. Motif itself only handles
2105 * mnemonics in menus. Mnemonics added or changed after this call will be
2108 * To add a mnemonic to a text field or list, set the XmNmnemonic resource on
2109 * the appropriate label and set the XmNuserData resource of the label to the
2110 * widget to get the focus when the mnemonic is typed.
2113 activate_dialog_mnemonics(Widget dialog
)
2118 XtAddEventHandler(dialog
, KeyPressMask
, False
,
2119 (XtEventHandler
) mnemonic_event
, (XtPointer
) NULL
);
2120 add_mnemonic_grabs(dialog
, dialog
);
2124 * Removes the event handler and key-grabs for dialog mnemonic handling.
2127 suppress_dialog_mnemonics(Widget dialog
)
2132 XtUngrabKey(dialog
, AnyKey
, Mod1Mask
);
2133 XtRemoveEventHandler(dialog
, KeyPressMask
, False
,
2134 (XtEventHandler
) mnemonic_event
, (XtPointer
) NULL
);
2137 #if defined(FEAT_BROWSE) || defined(FEAT_GUI_DIALOG)
2138 static void set_fontlist
__ARGS((Widget wg
));
2141 * Use the 'guifont' or 'guifontset' as a fontlist for a dialog widget.
2149 #ifdef FONTSET_ALWAYS
2150 if (gui
.fontset
!= NOFONTSET
)
2152 fl
= gui_motif_fontset2fontlist((XFontSet
*)&gui
.fontset
);
2155 if (XtIsManaged(id
))
2157 XtUnmanageChild(id
);
2158 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2159 /* We should force the widget to recalculate it's
2164 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2169 if (gui
.norm_font
!= NOFONT
)
2171 fl
= gui_motif_create_fontlist((XFontStruct
*)gui
.norm_font
);
2174 if (XtIsManaged(id
))
2176 XtUnmanageChild(id
);
2177 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2178 /* We should force the widget to recalculate it's
2183 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
2191 #if defined(FEAT_BROWSE) || defined(PROTO)
2194 * file selector related stuff
2197 #include <Xm/FileSB.h>
2198 #include <Xm/XmStrDefs.h>
2200 typedef struct dialog_callback_arg
2202 char * args
; /* not used right now */
2206 static Widget dialog_wgt
;
2207 static char *browse_fname
= NULL
;
2208 static XmStringCharSet charset
= (XmStringCharSet
) XmSTRING_DEFAULT_CHARSET
;
2209 /* used to set up XmStrings */
2211 static void DialogCancelCB
__ARGS((Widget
, XtPointer
, XtPointer
));
2212 static void DialogAcceptCB
__ARGS((Widget
, XtPointer
, XtPointer
));
2215 * This function is used to translate the predefined label text of the
2216 * precomposed dialogs. We do this explicitly to allow:
2218 * - usage of gettext for translation, as in all the other places.
2220 * - equalize the messages between different GUI implementations as far as
2223 static void set_predefined_label
__ARGS((Widget parent
, String name
, char *new_label
));
2226 set_predefined_label(parent
, name
, new_label
)
2234 KeySym mnemonic
= NUL
;
2236 w
= XtNameToWidget(parent
, name
);
2241 p
= vim_strsave((char_u
*)new_label
);
2244 for (next
= p
; *next
; ++next
)
2246 if (*next
== DLG_HOTKEY_CHAR
)
2248 int len
= STRLEN(next
);
2252 mch_memmove(next
, next
+ 1, len
);
2258 str
= XmStringCreate((char *)p
, STRING_TAG
);
2264 XmNlabelString
, str
,
2265 XmNmnemonic
, mnemonic
,
2269 gui_motif_menu_fontlist(w
);
2273 set_predefined_fontlist(parent
, name
)
2278 w
= XtNameToWidget(parent
, name
);
2287 * Put up a file requester.
2288 * Returns the selected name in allocated memory, or NULL for Cancel.
2292 gui_mch_browse(saving
, title
, dflt
, ext
, initdir
, filter
)
2293 int saving
; /* select file to write */
2294 char_u
*title
; /* title for the window */
2295 char_u
*dflt
; /* default name */
2296 char_u
*ext
; /* not used (extension added) */
2297 char_u
*initdir
; /* initial directory, NULL for current dir */
2298 char_u
*filter
; /* file name filter */
2300 char_u dirbuf
[MAXPATHL
];
2301 char_u dfltbuf
[MAXPATHL
];
2303 char_u
*tofree
= NULL
;
2305 /* There a difference between the resource name and value, Therefore, we
2306 * avoid to (ab-)use the (maybe internationalized!) dialog title as a
2310 dialog_wgt
= XmCreateFileSelectionDialog(vimShell
, "browseDialog", NULL
, 0);
2312 if (initdir
== NULL
|| *initdir
== NUL
)
2314 mch_dirname(dirbuf
, MAXPATHL
);
2319 dflt
= (char_u
*)"";
2320 else if (STRLEN(initdir
) + STRLEN(dflt
) + 2 < MAXPATHL
)
2322 /* The default selection should be the full path, "dflt" is only the
2324 STRCPY(dfltbuf
, initdir
);
2325 add_pathsep(dfltbuf
);
2326 STRCAT(dfltbuf
, dflt
);
2330 /* Can only use one pattern for a file name. Get the first pattern out of
2331 * the filter. An empty pattern means everything matches. */
2333 pattern
= (char_u
*)"";
2339 for (p
= filter
; *p
!= NUL
; ++p
)
2341 if (*p
== '\t') /* end of description, start of pattern */
2343 if (*p
== ';' || *p
== '\n') /* end of (first) pattern */
2346 pattern
= vim_strnsave(s
, p
- s
);
2348 if (pattern
== NULL
)
2349 pattern
= (char_u
*)"";
2352 XtVaSetValues(dialog_wgt
,
2354 XmNdirectory
, XmRString
, (char *)initdir
, STRLEN(initdir
) + 1,
2356 XmNdirSpec
, XmRString
, (char *)dflt
, STRLEN(dflt
) + 1,
2358 XmNpattern
, XmRString
, (char *)pattern
, STRLEN(pattern
) + 1,
2360 XmNdialogTitle
, XmRString
, (char *)title
, STRLEN(title
) + 1,
2363 set_predefined_label(dialog_wgt
, "Apply", _("&Filter"));
2364 set_predefined_label(dialog_wgt
, "Cancel", _("&Cancel"));
2365 set_predefined_label(dialog_wgt
, "Dir", _("Directories"));
2366 set_predefined_label(dialog_wgt
, "FilterLabel", _("Filter"));
2367 set_predefined_label(dialog_wgt
, "Help", _("&Help"));
2368 set_predefined_label(dialog_wgt
, "Items", _("Files"));
2369 set_predefined_label(dialog_wgt
, "OK", _("&OK"));
2370 set_predefined_label(dialog_wgt
, "Selection", _("Selection"));
2372 /* This is to save us from silly external settings using not fixed with
2373 * fonts for file selection.
2375 set_predefined_fontlist(dialog_wgt
, "DirListSW.DirList");
2376 set_predefined_fontlist(dialog_wgt
, "ItemsListSW.ItemsList");
2378 gui_motif_menu_colors(dialog_wgt
);
2379 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
2380 XtVaSetValues(dialog_wgt
, XmNtroughColor
, gui
.scroll_bg_pixel
, NULL
);
2382 XtAddCallback(dialog_wgt
, XmNokCallback
, DialogAcceptCB
, (XtPointer
)0);
2383 XtAddCallback(dialog_wgt
, XmNcancelCallback
, DialogCancelCB
, (XtPointer
)0);
2384 /* We have no help in this window, so hide help button */
2385 XtUnmanageChild(XmFileSelectionBoxGetChild(dialog_wgt
,
2386 (unsigned char)XmDIALOG_HELP_BUTTON
));
2388 manage_centered(dialog_wgt
);
2389 activate_dialog_mnemonics(dialog_wgt
);
2391 /* sit in a loop until the dialog box has gone away */
2394 XtAppProcessEvent(XtWidgetToApplicationContext(dialog_wgt
),
2395 (XtInputMask
)XtIMAll
);
2396 } while (XtIsManaged(dialog_wgt
));
2398 suppress_dialog_mnemonics(dialog_wgt
);
2399 XtDestroyWidget(dialog_wgt
);
2402 if (browse_fname
== NULL
)
2404 return vim_strsave((char_u
*)browse_fname
);
2408 * The code below was originally taken from
2409 * /usr/examples/motif/xmsamplers/xmeditor.c
2410 * on Digital Unix 4.0d, but heavily modified.
2414 * Process callback from Dialog cancel actions.
2418 DialogCancelCB(w
, client_data
, call_data
)
2419 Widget w
; /* widget id */
2420 XtPointer client_data
; /* data from application */
2421 XtPointer call_data
; /* data from widget class */
2423 if (browse_fname
!= NULL
)
2425 XtFree(browse_fname
);
2426 browse_fname
= NULL
;
2428 XtUnmanageChild(dialog_wgt
);
2432 * Process callback from Dialog actions.
2436 DialogAcceptCB(w
, client_data
, call_data
)
2437 Widget w
; /* widget id */
2438 XtPointer client_data
; /* data from application */
2439 XtPointer call_data
; /* data from widget class */
2441 XmFileSelectionBoxCallbackStruct
*fcb
;
2443 if (browse_fname
!= NULL
)
2445 XtFree(browse_fname
);
2446 browse_fname
= NULL
;
2448 fcb
= (XmFileSelectionBoxCallbackStruct
*)call_data
;
2450 /* get the filename from the file selection box */
2451 XmStringGetLtoR(fcb
->value
, charset
, &browse_fname
);
2453 /* popdown the file selection box */
2454 XtUnmanageChild(dialog_wgt
);
2457 #endif /* FEAT_BROWSE */
2459 #if defined(FEAT_GUI_DIALOG) || defined(PROTO)
2461 static int dialogStatus
;
2463 static void keyhit_callback
__ARGS((Widget w
, XtPointer client_data
, XEvent
*event
, Boolean
*cont
));
2464 static void butproc
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
2467 * Callback function for the textfield. When CR is hit this works like
2468 * hitting the "OK" button, ESC like "Cancel".
2472 keyhit_callback(w
, client_data
, event
, cont
)
2474 XtPointer client_data
;
2481 if (XLookupString(&(event
->xkey
), buf
, 2, &key_sym
, NULL
) == 1)
2485 else if (*buf
== ESC
)
2488 if ((key_sym
== XK_Left
|| key_sym
== XK_Right
)
2489 && !(event
->xkey
.state
& ShiftMask
))
2490 XmTextFieldClearSelection(w
, XtLastTimestampProcessed(gui
.dpy
));
2495 butproc(w
, client_data
, call_data
)
2497 XtPointer client_data
;
2498 XtPointer call_data
;
2500 dialogStatus
= (int)(long)client_data
+ 1;
2505 static Widget
create_pixmap_label(Widget parent
, String name
, char **data
, ArgList args
, Cardinal arg
);
2508 create_pixmap_label(parent
, name
, data
, args
, arg
)
2522 XpmColorSymbol color
[5] =
2525 {"iconColor1", NULL
, 0},
2526 {"bottomShadowColor", NULL
, 0},
2527 {"topShadowColor", NULL
, 0},
2528 {"selectColor", NULL
, 0}
2531 label
= XmCreateLabelGadget(parent
, name
, args
, arg
);
2534 * We need to be careful here, since in case of gadgets, there is
2535 * no way to get the background color directly from the widget itself.
2536 * In such cases we get it from The Core part of his parent instead.
2538 dsp
= XtDisplayOfObject(label
);
2539 scr
= XtScreenOfObject(label
);
2540 XtVaGetValues(XtIsSubclass(label
, coreWidgetClass
)
2541 ? label
: XtParent(label
),
2543 XmNbackground
, &color
[0].pixel
,
2544 XmNforeground
, &color
[1].pixel
,
2545 XmNbottomShadowColor
, &color
[2].pixel
,
2546 XmNtopShadowColor
, &color
[3].pixel
,
2547 XmNhighlight
, &color
[4].pixel
,
2550 attr
.valuemask
= XpmColorSymbols
| XpmCloseness
| XpmDepth
;
2551 attr
.colorsymbols
= color
;
2552 attr
.numsymbols
= 5;
2553 attr
.closeness
= 65535;
2555 XpmCreatePixmapFromData(dsp
, RootWindowOfScreen(scr
),
2556 data
, &pixmap
, NULL
, &attr
);
2558 XtVaGetValues(label
, XmNrecomputeSize
, &rs
, NULL
);
2559 XtVaSetValues(label
, XmNrecomputeSize
, True
, NULL
);
2560 XtVaSetValues(label
,
2561 XmNlabelType
, XmPIXMAP
,
2562 XmNlabelPixmap
, pixmap
,
2564 XtVaSetValues(label
, XmNrecomputeSize
, rs
, NULL
);
2572 gui_mch_dialog(type
, title
, message
, button_names
, dfltbutton
, textfield
)
2576 char_u
*button_names
;
2578 char_u
*textfield
; /* buffer of size IOSIZE */
2586 Widget dialogform
= NULL
;
2588 Widget dialogtextfield
= NULL
;
2590 Widget sep_form
= NULL
;
2592 Widget separator
= NULL
;
2596 char **icon_data
= NULL
;
2597 Widget dialogpixmap
= NULL
;
2601 title
= (char_u
*)_("Vim dialog");
2603 /* if our pointer is currently hidden, then we should show it. */
2604 gui_mch_mousehide(FALSE
);
2606 dialogform
= XmCreateFormDialog(vimShell
, (char *)"dialog", NULL
, 0);
2608 /* Check 'v' flag in 'guioptions': vertical button placement. */
2609 vertical
= (vim_strchr(p_go
, GO_VERTICAL
) != NULL
);
2611 /* Set the title of the Dialog window */
2612 label
= XmStringCreateSimple((char *)title
);
2615 XtVaSetValues(dialogform
,
2616 XmNdialogTitle
, label
,
2617 XmNhorizontalSpacing
, 4,
2618 XmNverticalSpacing
, vertical
? 0 : 4,
2620 XmStringFree(label
);
2622 /* make a copy, so that we can insert NULs */
2623 buts
= vim_strsave(button_names
);
2627 /* Count the number of buttons and allocate buttons[]. */
2629 for (p
= buts
; *p
; ++p
)
2630 if (*p
== DLG_BUTTON_SEP
)
2632 buttons
= (Widget
*)alloc((unsigned)(butcount
* sizeof(Widget
)));
2633 if (buttons
== NULL
)
2640 * Create the buttons.
2642 sep_form
= (Widget
) 0;
2644 for (butcount
= 0; *p
; ++butcount
)
2646 KeySym mnemonic
= NUL
;
2648 for (next
= p
; *next
; ++next
)
2650 if (*next
== DLG_HOTKEY_CHAR
)
2652 int len
= STRLEN(next
);
2656 mch_memmove(next
, next
+ 1, len
);
2660 if (*next
== DLG_BUTTON_SEP
)
2666 label
= XmStringCreate(_((char *)p
), STRING_TAG
);
2670 buttons
[butcount
] = XtVaCreateManagedWidget("button",
2671 xmPushButtonWidgetClass
, dialogform
,
2672 XmNlabelString
, label
,
2673 XmNmnemonic
, mnemonic
,
2674 XmNbottomAttachment
, XmATTACH_FORM
,
2676 XmNshowAsDefault
, butcount
== dfltbutton
- 1,
2677 XmNdefaultButtonShadowThickness
, 1,
2679 XmStringFree(label
);
2680 gui_motif_menu_fontlist(buttons
[butcount
]);
2682 /* Layout properly. */
2687 XtVaSetValues(buttons
[butcount
],
2688 XmNtopWidget
, buttons
[butcount
- 1],
2694 XtVaSetValues(buttons
[butcount
],
2695 XmNrightAttachment
, XmATTACH_FORM
,
2699 /* fill in a form as invisible separator */
2700 sep_form
= XtVaCreateWidget("separatorForm",
2701 xmFormWidgetClass
, dialogform
,
2702 XmNleftAttachment
, XmATTACH_WIDGET
,
2703 XmNleftWidget
, buttons
[butcount
- 1],
2704 XmNrightAttachment
, XmATTACH_WIDGET
,
2705 XmNrightWidget
, buttons
[butcount
],
2706 XmNbottomAttachment
, XmATTACH_FORM
,
2709 XtManageChild(sep_form
);
2713 XtVaSetValues(buttons
[butcount
],
2714 XmNleftAttachment
, XmATTACH_WIDGET
,
2715 XmNleftWidget
, buttons
[butcount
- 1],
2724 XtVaSetValues(buttons
[0],
2725 XmNrightAttachment
, XmATTACH_FORM
,
2729 /* fill in a form as invisible separator */
2730 sep_form
= XtVaCreateWidget("separatorForm",
2731 xmFormWidgetClass
, dialogform
,
2732 XmNleftAttachment
, XmATTACH_FORM
,
2734 XmNrightAttachment
, XmATTACH_WIDGET
,
2735 XmNrightWidget
, buttons
[0],
2736 XmNbottomAttachment
, XmATTACH_FORM
,
2739 XtManageChild(sep_form
);
2742 XtVaSetValues(buttons
[0],
2743 XmNleftAttachment
, XmATTACH_FORM
,
2748 XtAddCallback(buttons
[butcount
], XmNactivateCallback
,
2749 (XtCallbackProc
)butproc
, (XtPointer
)(long)butcount
);
2754 separator
= (Widget
) 0;
2757 /* Create the separator for beauty. */
2759 XtSetArg(args
[n
], XmNorientation
, XmHORIZONTAL
); n
++;
2760 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_WIDGET
); n
++;
2761 XtSetArg(args
[n
], XmNbottomWidget
, buttons
[0]); n
++;
2762 XtSetArg(args
[n
], XmNbottomOffset
, 4); n
++;
2763 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
2764 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_FORM
); n
++;
2765 separator
= XmCreateSeparatorGadget(dialogform
, "separator", args
, n
);
2766 XtManageChild(separator
);
2769 if (textfield
!= NULL
)
2771 dialogtextfield
= XtVaCreateWidget("textField",
2772 xmTextFieldWidgetClass
, dialogform
,
2773 XmNleftAttachment
, XmATTACH_FORM
,
2774 XmNrightAttachment
, XmATTACH_FORM
,
2777 XtVaSetValues(dialogtextfield
,
2778 XmNbottomAttachment
, XmATTACH_WIDGET
,
2779 XmNbottomWidget
, separator
,
2782 XtVaSetValues(dialogtextfield
,
2783 XmNbottomAttachment
, XmATTACH_FORM
,
2786 set_fontlist(dialogtextfield
);
2787 XmTextFieldSetString(dialogtextfield
, (char *)textfield
);
2788 XtManageChild(dialogtextfield
);
2789 XtAddEventHandler(dialogtextfield
, KeyPressMask
, False
,
2790 (XtEventHandler
)keyhit_callback
, (XtPointer
)NULL
);
2793 /* Form holding both message and pixmap labels */
2794 form
= XtVaCreateWidget("separatorForm",
2795 xmFormWidgetClass
, dialogform
,
2796 XmNleftAttachment
, XmATTACH_FORM
,
2797 XmNrightAttachment
, XmATTACH_FORM
,
2798 XmNtopAttachment
, XmATTACH_FORM
,
2800 XtManageChild(form
);
2803 /* Add a pixmap, left of the message. */
2807 icon_data
= generic_xpm
;
2810 icon_data
= error_xpm
;
2813 icon_data
= alert_xpm
;
2816 icon_data
= info_xpm
;
2819 icon_data
= quest_xpm
;
2822 icon_data
= generic_xpm
;
2826 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
2827 XtSetArg(args
[n
], XmNtopOffset
, 8); n
++;
2828 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
2829 XtSetArg(args
[n
], XmNbottomOffset
, 8); n
++;
2830 XtSetArg(args
[n
], XmNleftAttachment
, XmATTACH_FORM
); n
++;
2831 XtSetArg(args
[n
], XmNleftOffset
, 8); n
++;
2833 dialogpixmap
= create_pixmap_label(form
, "dialogPixmap",
2834 icon_data
, args
, n
);
2835 XtManageChild(dialogpixmap
);
2838 /* Create the dialog message.
2839 * Since LessTif is apparently having problems with the creation of
2840 * properly localized string, we use LtoR here. The symptom is that the
2841 * string sill not show properly in multiple lines as it does in native
2844 label
= XmStringCreateLtoR((char *)message
, STRING_TAG
);
2847 w
= XtVaCreateManagedWidget("dialogMessage",
2848 xmLabelGadgetClass
, form
,
2849 XmNlabelString
, label
,
2850 XmNalignment
, XmALIGNMENT_BEGINNING
,
2851 XmNtopAttachment
, XmATTACH_FORM
,
2854 XmNleftAttachment
, XmATTACH_WIDGET
,
2855 XmNleftWidget
, dialogpixmap
,
2857 XmNleftAttachment
, XmATTACH_FORM
,
2860 XmNrightAttachment
, XmATTACH_FORM
,
2862 XmNbottomAttachment
, XmATTACH_FORM
,
2865 XmStringFree(label
);
2868 if (textfield
!= NULL
)
2871 XmNbottomAttachment
, XmATTACH_WIDGET
,
2872 XmNbottomWidget
, dialogtextfield
,
2879 XmNbottomAttachment
, XmATTACH_WIDGET
,
2880 XmNbottomWidget
, separator
,
2884 XmNbottomAttachment
, XmATTACH_FORM
,
2890 if (dfltbutton
> butcount
)
2891 dfltbutton
= butcount
;
2892 XtVaSetValues(dialogform
,
2893 XmNdefaultButton
, buttons
[dfltbutton
- 1], NULL
);
2894 if (textfield
!= NULL
)
2895 XtVaSetValues(dialogform
, XmNinitialFocus
, dialogtextfield
, NULL
);
2897 XtVaSetValues(dialogform
, XmNinitialFocus
, buttons
[dfltbutton
- 1],
2900 manage_centered(dialogform
);
2901 activate_dialog_mnemonics(dialogform
);
2903 if (textfield
!= NULL
&& *textfield
!= NUL
)
2905 /* This only works after the textfield has been realised. */
2906 XmTextFieldSetSelection(dialogtextfield
,
2907 (XmTextPosition
)0, (XmTextPosition
)STRLEN(textfield
),
2908 XtLastTimestampProcessed(gui
.dpy
));
2909 XmTextFieldSetCursorPosition(dialogtextfield
,
2910 (XmTextPosition
)STRLEN(textfield
));
2913 app
= XtWidgetToApplicationContext(dialogform
);
2915 /* Loop until a button is pressed or the dialog is killed somehow. */
2919 XtAppProcessEvent(app
, (XtInputMask
)XtIMAll
);
2920 if (dialogStatus
>= 0 || !XtIsManaged(dialogform
))
2926 if (textfield
!= NULL
)
2928 p
= (char_u
*)XmTextGetString(dialogtextfield
);
2929 if (p
== NULL
|| dialogStatus
< 0)
2932 vim_strncpy(textfield
, p
, IOSIZE
- 1);
2935 suppress_dialog_mnemonics(dialogform
);
2936 XtDestroyWidget(dialogform
);
2938 return dialogStatus
;
2940 #endif /* FEAT_GUI_DIALOG */
2942 #if defined(FEAT_FOOTER) || defined(PROTO)
2945 gui_mch_compute_footer_height()
2947 Dimension height
; /* total Toolbar height */
2948 Dimension top
; /* XmNmarginTop */
2949 Dimension bottom
; /* XmNmarginBottom */
2950 Dimension shadow
; /* XmNshadowThickness */
2952 XtVaGetValues(footer
,
2955 XmNmarginBottom
, &bottom
,
2956 XmNshadowThickness
, &shadow
,
2959 return (int) height
+ top
+ bottom
+ (shadow
<< 1);
2962 #if 0 /* not used */
2964 gui_mch_set_footer_pos(h
)
2965 int h
; /* textArea height */
2967 XtVaSetValues(footer
,
2968 XmNtopOffset
, h
+ 7,
2974 gui_mch_enable_footer(showit
)
2979 gui
.footer_height
= gui_mch_compute_footer_height();
2980 XtManageChild(footer
);
2984 gui
.footer_height
= 0;
2985 XtUnmanageChild(footer
);
2987 XtVaSetValues(textAreaForm
, XmNbottomOffset
, gui
.footer_height
, NULL
);
2991 gui_mch_set_footer(s
)
2996 xms
= XmStringCreate((char *)s
, STRING_TAG
);
2999 XtVaSetValues(footer
, XmNlabelString
, xms
, NULL
);
3007 #if defined(FEAT_TOOLBAR) || defined(PROTO)
3009 gui_mch_show_toolbar(int showit
)
3011 Cardinal numChildren
; /* how many children toolBar has */
3013 if (toolBar
== (Widget
)0)
3015 XtVaGetValues(toolBar
, XmNnumChildren
, &numChildren
, NULL
);
3016 if (showit
&& numChildren
> 0)
3018 /* Assume that we want to show the toolbar if p_toolbar contains
3019 * valid option settings, therefore p_toolbar must not be NULL.
3021 WidgetList children
;
3023 XtVaGetValues(toolBar
, XmNchildren
, &children
, NULL
);
3025 void (*action
)(BalloonEval
*);
3028 if (strstr((const char *)p_toolbar
, "tooltips"))
3029 action
= &gui_mch_enable_beval_area
;
3031 action
= &gui_mch_disable_beval_area
;
3032 if (strstr((const char *)p_toolbar
, "text"))
3034 else if (strstr((const char *)p_toolbar
, "icons"))
3041 for (toolbar
= root_menu
; toolbar
; toolbar
= toolbar
->next
)
3042 if (menu_is_toolbar(toolbar
->dname
))
3044 /* Assumption: toolbar is NULL if there is no toolbar,
3045 * otherwise it contains the toolbar menu structure.
3047 * Assumption: "numChildren" == the number of items in the list
3048 * of items beginning with toolbar->children.
3052 for (cur
= toolbar
->children
; cur
; cur
= cur
->next
)
3057 /* Enable/Disable tooltip (OK to enable while
3058 * currently enabled). */
3059 if (cur
->tip
!= NULL
)
3060 (*action
)(cur
->tip
);
3061 if (!menu_is_separator(cur
->name
))
3063 if (text
== 1 || cur
->xpm
== NULL
)
3065 XtSetArg(args
[n
], XmNlabelType
, XmSTRING
);
3068 if (cur
->id
!= NULL
)
3070 XtUnmanageChild(cur
->id
);
3071 XtSetValues(cur
->id
, args
, n
);
3072 XtManageChild(cur
->id
);
3079 gui
.toolbar_height
= gui_mch_compute_toolbar_height();
3080 XtManageChild(XtParent(toolBar
));
3081 #ifdef FEAT_GUI_TABLINE
3082 if (showing_tabline
)
3084 XtVaSetValues(tabLine
,
3085 XmNtopAttachment
, XmATTACH_WIDGET
,
3086 XmNtopWidget
, XtParent(toolBar
),
3088 XtVaSetValues(textAreaForm
,
3089 XmNtopAttachment
, XmATTACH_WIDGET
,
3090 XmNtopWidget
, tabLine
,
3095 XtVaSetValues(textAreaForm
,
3096 XmNtopAttachment
, XmATTACH_WIDGET
,
3097 XmNtopWidget
, XtParent(toolBar
),
3099 if (XtIsManaged(menuBar
))
3100 XtVaSetValues(XtParent(toolBar
),
3101 XmNtopAttachment
, XmATTACH_WIDGET
,
3102 XmNtopWidget
, menuBar
,
3105 XtVaSetValues(XtParent(toolBar
),
3106 XmNtopAttachment
, XmATTACH_FORM
,
3111 gui
.toolbar_height
= 0;
3112 if (XtIsManaged(menuBar
))
3114 #ifdef FEAT_GUI_TABLINE
3115 if (showing_tabline
)
3117 XtVaSetValues(tabLine
,
3118 XmNtopAttachment
, XmATTACH_WIDGET
,
3119 XmNtopWidget
, menuBar
,
3121 XtVaSetValues(textAreaForm
,
3122 XmNtopAttachment
, XmATTACH_WIDGET
,
3123 XmNtopWidget
, tabLine
,
3128 XtVaSetValues(textAreaForm
,
3129 XmNtopAttachment
, XmATTACH_WIDGET
,
3130 XmNtopWidget
, menuBar
,
3135 #ifdef FEAT_GUI_TABLINE
3136 if (showing_tabline
)
3138 XtVaSetValues(tabLine
,
3139 XmNtopAttachment
, XmATTACH_FORM
,
3141 XtVaSetValues(textAreaForm
,
3142 XmNtopAttachment
, XmATTACH_WIDGET
,
3143 XmNtopWidget
, tabLine
,
3148 XtVaSetValues(textAreaForm
,
3149 XmNtopAttachment
, XmATTACH_FORM
,
3153 XtUnmanageChild(XtParent(toolBar
));
3155 gui_set_shellsize(FALSE
, FALSE
, RESIZE_VERT
);
3159 * A toolbar button has been pushed; now reset the input focus
3160 * such that the user can type page up/down etc. and have the
3161 * input go to the editor window, not the button
3166 if (textArea
!= NULL
)
3167 XmProcessTraversal(textArea
, XmTRAVERSE_CURRENT
);
3171 gui_mch_compute_toolbar_height()
3174 Dimension height
; /* total Toolbar height */
3175 Dimension whgt
; /* height of each widget */
3176 WidgetList children
; /* list of toolBar's children */
3177 Cardinal numChildren
; /* how many children toolBar has */
3182 if (toolBar
!= (Widget
)0 && toolBarFrame
!= (Widget
)0)
3183 { /* get height of XmFrame parent */
3189 XtVaGetValues(toolBarFrame
,
3190 XmNshadowThickness
, &fst
,
3191 XmNmarginHeight
, &fmh
,
3193 borders
+= fst
+ fmh
;
3194 XtVaGetValues(toolBar
,
3195 XmNshadowThickness
, &tst
,
3196 XmNmarginHeight
, &tmh
,
3197 XmNchildren
, &children
,
3198 XmNnumChildren
, &numChildren
, NULL
);
3199 borders
+= tst
+ tmh
;
3200 for (i
= 0; i
< numChildren
; i
++)
3203 XtVaGetValues(children
[i
], XmNheight
, &whgt
, NULL
);
3208 #ifdef LESSTIF_VERSION
3209 /* Hack: When starting up we get wrong dimensions. */
3214 return (int)(height
+ (borders
<< 1));
3218 motif_get_toolbar_colors(bgp
, fgp
, bsp
, tsp
, hsp
)
3225 XtVaGetValues(toolBar
,
3228 XmNbottomShadowColor
, bsp
,
3229 XmNtopShadowColor
, tsp
,
3230 XmNhighlightColor
, hsp
,
3236 * The next toolbar enter/leave callbacks should really do balloon help. But
3237 * I have to use footer help for backwards compatability. Hopefully both will
3238 * get implemented and the user will have a choice.
3242 toolbarbutton_enter_cb(w
, client_data
, event
, cont
)
3244 XtPointer client_data
;
3248 vimmenu_T
*menu
= (vimmenu_T
*) client_data
;
3250 if (menu
->strings
[MENU_INDEX_TIP
] != NULL
)
3252 if (vim_strchr(p_go
, GO_FOOTER
) != NULL
)
3253 gui_mch_set_footer(menu
->strings
[MENU_INDEX_TIP
]);
3259 toolbarbutton_leave_cb(w
, client_data
, event
, cont
)
3261 XtPointer client_data
;
3265 gui_mch_set_footer((char_u
*) "");
3270 #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
3272 * Show or hide the tabline.
3275 gui_mch_show_tabline(int showit
)
3277 if (tabLine
== (Widget
)0)
3280 if (!showit
!= !showing_tabline
)
3284 XtManageChild(tabLine
);
3285 XtUnmanageChild(XtNameToWidget(tabLine
, "PageScroller"));
3286 XtUnmanageChild(XtNameToWidget(tabLine
, "MinorTabScrollerNext"));
3287 XtUnmanageChild(XtNameToWidget(tabLine
,
3288 "MinorTabScrollerPrevious"));
3290 # ifdef FEAT_TOOLBAR
3291 if (XtIsManaged(XtParent(toolBar
)))
3292 XtVaSetValues(tabLine
,
3293 XmNtopAttachment
, XmATTACH_WIDGET
,
3294 XmNtopWidget
, XtParent(toolBar
), NULL
);
3297 if (XtIsManaged(menuBar
))
3298 XtVaSetValues(tabLine
,
3299 XmNtopAttachment
, XmATTACH_WIDGET
,
3300 XmNtopWidget
, menuBar
, NULL
);
3303 XtVaSetValues(tabLine
,
3304 XmNtopAttachment
, XmATTACH_FORM
, NULL
);
3305 XtVaSetValues(textAreaForm
,
3306 XmNtopAttachment
, XmATTACH_WIDGET
,
3307 XmNtopWidget
, tabLine
,
3312 XtUnmanageChild(tabLine
);
3314 # ifdef FEAT_TOOLBAR
3315 if (XtIsManaged(XtParent(toolBar
)))
3316 XtVaSetValues(textAreaForm
,
3317 XmNtopAttachment
, XmATTACH_WIDGET
,
3318 XmNtopWidget
, XtParent(toolBar
), NULL
);
3321 if (XtIsManaged(menuBar
))
3322 XtVaSetValues(textAreaForm
,
3323 XmNtopAttachment
, XmATTACH_WIDGET
,
3324 XmNtopWidget
, menuBar
, NULL
);
3327 XtVaSetValues(textAreaForm
,
3328 XmNtopAttachment
, XmATTACH_FORM
, NULL
);
3330 showing_tabline
= showit
;
3335 * Return TRUE when tabline is displayed.
3338 gui_mch_showing_tabline(void)
3340 return tabLine
!= (Widget
)0 && showing_tabline
;
3344 * Update the labels of the tabline.
3347 gui_mch_update_tabline(void)
3352 int curtabidx
= 0, currentpage
;
3354 XmNotebookPageInfo page_info
;
3355 XmNotebookPageStatus page_status
;
3356 int last_page
, tab_count
;
3361 if (tabLine
== (Widget
)0)
3364 /* Add a label for each tab page. They all contain the same text area. */
3365 for (tp
= first_tabpage
; tp
!= NULL
; tp
= tp
->tp_next
, ++nr
)
3370 page_status
= XmNotebookGetPageInfo(tabLine
, nr
, &page_info
);
3371 if (page_status
== XmPAGE_INVALID
3372 || page_info
.major_tab_widget
== (Widget
)0)
3376 XtSetArg(args
[n
], XmNnotebookChildType
, XmMAJOR_TAB
); n
++;
3377 XtSetArg(args
[n
], XmNtraversalOn
, False
); n
++;
3378 XtSetArg(args
[n
], XmNalignment
, XmALIGNMENT_BEGINNING
); n
++;
3379 XtSetArg(args
[n
], XmNhighlightThickness
, 1); n
++;
3380 XtSetArg(args
[n
], XmNshadowThickness
, 1); n
++;
3381 tab
= XmCreatePushButton(tabLine
, "-Empty-", args
, n
);
3383 beval
= gui_mch_create_beval_area(tab
, NULL
, tabline_balloon_cb
,
3385 XtVaSetValues(tab
, XmNuserData
, beval
, NULL
);
3388 tab
= page_info
.major_tab_widget
;
3390 XtVaSetValues(tab
, XmNpageNumber
, nr
, NULL
);
3393 * Change the label text only if it is different
3395 XtVaGetValues(tab
, XmNlabelString
, &label_str
, NULL
);
3396 if (XmStringGetLtoR(label_str
, XmSTRING_DEFAULT_CHARSET
, &label_cstr
))
3398 get_tabline_label(tp
, FALSE
);
3399 if (STRCMP(label_cstr
, NameBuff
) != 0)
3401 XtVaSetValues(tab
, XtVaTypedArg
, XmNlabelString
, XmRString
,
3402 NameBuff
, STRLEN(NameBuff
) + 1, NULL
);
3404 * Force a resize of the tab label button
3406 XtUnmanageChild(tab
);
3415 XtVaGetValues(tabLine
, XmNlastPageNumber
, &last_page
, NULL
);
3417 /* Remove any old labels. */
3418 while (nr
<= last_page
)
3420 if (XmNotebookGetPageInfo(tabLine
, nr
, &page_info
) != XmPAGE_INVALID
3421 && page_info
.page_number
== nr
3422 && page_info
.major_tab_widget
!= (Widget
)0)
3424 XtVaGetValues(page_info
.major_tab_widget
, XmNuserData
, &beval
, NULL
);
3426 gui_mch_destroy_beval_area(beval
);
3427 XtUnmanageChild(page_info
.major_tab_widget
);
3428 XtDestroyWidget(page_info
.major_tab_widget
);
3433 XtVaSetValues(tabLine
, XmNlastPageNumber
, tab_count
, NULL
);
3435 XtVaGetValues(tabLine
, XmNcurrentPageNumber
, ¤tpage
, NULL
);
3436 if (currentpage
!= curtabidx
)
3437 XtVaSetValues(tabLine
, XmNcurrentPageNumber
, curtabidx
, NULL
);
3441 * Set the current tab to "nr". First tab is 1.
3444 gui_mch_set_curtab(nr
)
3449 if (tabLine
== (Widget
)0)
3452 XtVaGetValues(tabLine
, XmNcurrentPageNumber
, ¤tpage
, NULL
);
3453 if (currentpage
!= nr
)
3454 XtVaSetValues(tabLine
, XmNcurrentPageNumber
, nr
, NULL
);
3459 * Set the colors of Widget "id" to the menu colors.
3462 gui_motif_menu_colors(id
)
3465 if (gui
.menu_bg_pixel
!= INVALCOLOR
)
3466 #if (XmVersion >= 1002)
3467 XmChangeColor(id
, gui
.menu_bg_pixel
);
3469 XtVaSetValues(id
, XmNbackground
, gui
.menu_bg_pixel
, NULL
);
3471 if (gui
.menu_fg_pixel
!= INVALCOLOR
)
3472 XtVaSetValues(id
, XmNforeground
, gui
.menu_fg_pixel
, NULL
);
3476 * Set the colors of Widget "id" to the scrollbar colors.
3479 gui_motif_scroll_colors(id
)
3482 if (gui
.scroll_bg_pixel
!= INVALCOLOR
)
3483 #if (XmVersion >= 1002)
3484 XmChangeColor(id
, gui
.scroll_bg_pixel
);
3486 XtVaSetValues(id
, XmNbackground
, gui
.scroll_bg_pixel
, NULL
);
3488 if (gui
.scroll_fg_pixel
!= INVALCOLOR
)
3489 XtVaSetValues(id
, XmNforeground
, gui
.scroll_fg_pixel
, NULL
);
3493 * Set the fontlist for Widget "id" to use gui.menu_fontset or gui.menu_font.
3497 gui_motif_menu_fontlist(id
)
3501 #ifdef FONTSET_ALWAYS
3502 if (gui
.menu_fontset
!= NOFONTSET
)
3506 fl
= gui_motif_fontset2fontlist((XFontSet
*)&gui
.menu_fontset
);
3509 if (XtIsManaged(id
))
3511 XtUnmanageChild(id
);
3512 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3513 /* We should force the widget to recalculate it's
3518 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3523 if (gui
.menu_font
!= NOFONT
)
3527 fl
= gui_motif_create_fontlist((XFontStruct
*)gui
.menu_font
);
3530 if (XtIsManaged(id
))
3532 XtUnmanageChild(id
);
3533 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3534 /* We should force the widget to recalculate it's
3539 XtVaSetValues(id
, XmNfontList
, fl
, NULL
);
3549 * We don't create it twice for the sake of speed.
3552 typedef struct _SharedFindReplace
3554 Widget dialog
; /* the main dialog widget */
3555 Widget wword
; /* 'Exact match' check button */
3556 Widget mcase
; /* 'match case' check button */
3557 Widget up
; /* search direction 'Up' radio button */
3558 Widget down
; /* search direction 'Down' radio button */
3559 Widget what
; /* 'Find what' entry text widget */
3560 Widget with
; /* 'Replace with' entry text widget */
3561 Widget find
; /* 'Find Next' action button */
3562 Widget replace
; /* 'Replace With' action button */
3563 Widget all
; /* 'Replace All' action button */
3564 Widget undo
; /* 'Undo' action button */
3567 } SharedFindReplace
;
3569 static SharedFindReplace find_widgets
= { NULL
};
3570 static SharedFindReplace repl_widgets
= { NULL
};
3572 static void find_replace_destroy_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3573 static void find_replace_dismiss_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3574 static void entry_activate_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3575 static void find_replace_callback
__ARGS((Widget w
, XtPointer client_data
, XtPointer call_data
));
3576 static void find_replace_keypress
__ARGS((Widget w
, SharedFindReplace
* frdp
, XKeyEvent
* event
));
3577 static void find_replace_dialog_create
__ARGS((char_u
*entry_text
, int do_replace
));
3581 find_replace_destroy_callback(w
, client_data
, call_data
)
3583 XtPointer client_data
;
3584 XtPointer call_data
;
3586 SharedFindReplace
*cd
= (SharedFindReplace
*)client_data
;
3589 /* suppress_dialog_mnemonics(cd->dialog); */
3590 cd
->dialog
= (Widget
)0;
3595 find_replace_dismiss_callback(w
, client_data
, call_data
)
3597 XtPointer client_data
;
3598 XtPointer call_data
;
3600 SharedFindReplace
*cd
= (SharedFindReplace
*)client_data
;
3603 XtUnmanageChild(cd
->dialog
);
3608 entry_activate_callback(w
, client_data
, call_data
)
3610 XtPointer client_data
;
3611 XtPointer call_data
;
3613 XmProcessTraversal((Widget
)client_data
, XmTRAVERSE_CURRENT
);
3618 find_replace_callback(w
, client_data
, call_data
)
3620 XtPointer client_data
;
3621 XtPointer call_data
;
3623 long_u flags
= (long_u
)client_data
;
3624 char *find_text
, *repl_text
;
3625 Boolean direction_down
= TRUE
;
3628 SharedFindReplace
*sfr
;
3630 if (flags
== FRD_UNDO
)
3632 char_u
*save_cpo
= p_cpo
;
3634 /* No need to be Vi compatible here. */
3635 p_cpo
= (char_u
*)"";
3638 gui_update_screen();
3642 /* Get the search/replace strings from the dialog */
3643 if (flags
== FRD_FINDNEXT
)
3646 sfr
= &find_widgets
;
3650 repl_text
= XmTextFieldGetString(repl_widgets
.with
);
3651 sfr
= &repl_widgets
;
3653 find_text
= XmTextFieldGetString(sfr
->what
);
3654 XtVaGetValues(sfr
->down
, XmNset
, &direction_down
, NULL
);
3655 XtVaGetValues(sfr
->wword
, XmNset
, &wword
, NULL
);
3656 XtVaGetValues(sfr
->mcase
, XmNset
, &mcase
, NULL
);
3658 flags
|= FRD_WHOLE_WORD
;
3660 flags
|= FRD_MATCH_CASE
;
3662 (void)gui_do_findrepl((int)flags
, (char_u
*)find_text
, (char_u
*)repl_text
,
3665 if (find_text
!= NULL
)
3667 if (repl_text
!= NULL
)
3673 find_replace_keypress(w
, frdp
, event
)
3675 SharedFindReplace
*frdp
;
3683 keysym
= XLookupKeysym(event
, 0);
3685 /* the scape key pops the whole dialog down */
3686 if (keysym
== XK_Escape
)
3687 XtUnmanageChild(frdp
->dialog
);
3697 KeySym mnemonic
= NUL
;
3702 p
= vim_strsave(label
);
3705 for (next
= p
; *next
; ++next
)
3707 if (*next
== DLG_HOTKEY_CHAR
)
3709 int len
= STRLEN(next
);
3713 mch_memmove(next
, next
+ 1, len
);
3719 str
= XmStringCreateSimple((char *)p
);
3724 XmNlabelString
, str
,
3725 XmNmnemonic
, mnemonic
,
3729 gui_motif_menu_fontlist(w
);
3733 find_replace_dialog_create(arg
, do_replace
)
3737 SharedFindReplace
*frdp
;
3752 frdp
= do_replace
? &repl_widgets
: &find_widgets
;
3754 /* Get the search string to use. */
3755 entry_text
= get_find_dialog_text(arg
, &wword
, &mcase
);
3757 /* If the dialog already exists, just raise it. */
3760 gui_motif_synch_fonts();
3762 /* If the window is already up, just pop it to the top */
3763 if (XtIsManaged(frdp
->dialog
))
3764 XMapRaised(XtDisplay(frdp
->dialog
),
3765 XtWindow(XtParent(frdp
->dialog
)));
3767 XtManageChild(frdp
->dialog
);
3768 XtPopup(XtParent(frdp
->dialog
), XtGrabNone
);
3769 XmProcessTraversal(frdp
->what
, XmTRAVERSE_CURRENT
);
3771 if (entry_text
!= NULL
)
3772 XmTextFieldSetString(frdp
->what
, (char *)entry_text
);
3773 vim_free(entry_text
);
3775 XtVaSetValues(frdp
->wword
, XmNset
, wword
, NULL
);
3779 /* Create a fresh new dialog window */
3781 str
= XmStringCreateSimple(_("VIM - Search and Replace..."));
3783 str
= XmStringCreateSimple(_("VIM - Search..."));
3786 XtSetArg(args
[n
], XmNautoUnmanage
, False
); n
++;
3787 XtSetArg(args
[n
], XmNnoResize
, True
); n
++;
3788 XtSetArg(args
[n
], XmNdialogTitle
, str
); n
++;
3790 frdp
->dialog
= XmCreateFormDialog(vimShell
, "findReplaceDialog", args
, n
);
3792 XtAddCallback(frdp
->dialog
, XmNdestroyCallback
,
3793 find_replace_destroy_callback
, frdp
);
3795 button_form
= XtVaCreateWidget("buttonForm",
3796 xmFormWidgetClass
, frdp
->dialog
,
3797 XmNrightAttachment
, XmATTACH_FORM
,
3799 XmNtopAttachment
, XmATTACH_FORM
,
3801 XmNbottomAttachment
, XmATTACH_FORM
,
3805 frdp
->find
= XtVaCreateManagedWidget("findButton",
3806 xmPushButtonWidgetClass
, button_form
,
3808 XmNtopAttachment
, XmATTACH_FORM
,
3809 XmNleftAttachment
, XmATTACH_FORM
,
3810 XmNrightAttachment
, XmATTACH_FORM
,
3812 set_label(frdp
->find
, _("Find &Next"));
3814 XtAddCallback(frdp
->find
, XmNactivateCallback
,
3815 find_replace_callback
,
3816 (XtPointer
) (do_replace
? FRD_R_FINDNEXT
: FRD_FINDNEXT
));
3820 frdp
->replace
= XtVaCreateManagedWidget("replaceButton",
3821 xmPushButtonWidgetClass
, button_form
,
3822 XmNtopAttachment
, XmATTACH_WIDGET
,
3823 XmNtopWidget
, frdp
->find
,
3824 XmNleftAttachment
, XmATTACH_FORM
,
3825 XmNrightAttachment
, XmATTACH_FORM
,
3827 set_label(frdp
->replace
, _("&Replace"));
3828 XtAddCallback(frdp
->replace
, XmNactivateCallback
,
3829 find_replace_callback
, (XtPointer
)FRD_REPLACE
);
3831 frdp
->all
= XtVaCreateManagedWidget("replaceAllButton",
3832 xmPushButtonWidgetClass
, button_form
,
3833 XmNtopAttachment
, XmATTACH_WIDGET
,
3834 XmNtopWidget
, frdp
->replace
,
3835 XmNleftAttachment
, XmATTACH_FORM
,
3836 XmNrightAttachment
, XmATTACH_FORM
,
3838 set_label(frdp
->all
, _("Replace &All"));
3839 XtAddCallback(frdp
->all
, XmNactivateCallback
,
3840 find_replace_callback
, (XtPointer
)FRD_REPLACEALL
);
3842 frdp
->undo
= XtVaCreateManagedWidget("undoButton",
3843 xmPushButtonWidgetClass
, button_form
,
3844 XmNtopAttachment
, XmATTACH_WIDGET
,
3845 XmNtopWidget
, frdp
->all
,
3846 XmNleftAttachment
, XmATTACH_FORM
,
3847 XmNrightAttachment
, XmATTACH_FORM
,
3849 set_label(frdp
->undo
, _("&Undo"));
3850 XtAddCallback(frdp
->undo
, XmNactivateCallback
,
3851 find_replace_callback
, (XtPointer
)FRD_UNDO
);
3854 frdp
->cancel
= XtVaCreateManagedWidget("closeButton",
3855 xmPushButtonWidgetClass
, button_form
,
3856 XmNleftAttachment
, XmATTACH_FORM
,
3857 XmNrightAttachment
, XmATTACH_FORM
,
3858 XmNbottomAttachment
, XmATTACH_FORM
,
3860 set_label(frdp
->cancel
, _("&Cancel"));
3861 XtAddCallback(frdp
->cancel
, XmNactivateCallback
,
3862 find_replace_dismiss_callback
, frdp
);
3863 gui_motif_menu_fontlist(frdp
->cancel
);
3865 XtManageChild(button_form
);
3868 XtSetArg(args
[n
], XmNorientation
, XmVERTICAL
); n
++;
3869 XtSetArg(args
[n
], XmNrightAttachment
, XmATTACH_WIDGET
); n
++;
3870 XtSetArg(args
[n
], XmNrightWidget
, button_form
); n
++;
3871 XtSetArg(args
[n
], XmNrightOffset
, 4); n
++;
3872 XtSetArg(args
[n
], XmNtopAttachment
, XmATTACH_FORM
); n
++;
3873 XtSetArg(args
[n
], XmNbottomAttachment
, XmATTACH_FORM
); n
++;
3874 separator
= XmCreateSeparatorGadget(frdp
->dialog
, "separator", args
, n
);
3875 XtManageChild(separator
);
3877 input_form
= XtVaCreateWidget("inputForm",
3878 xmFormWidgetClass
, frdp
->dialog
,
3879 XmNleftAttachment
, XmATTACH_FORM
,
3881 XmNrightAttachment
, XmATTACH_WIDGET
,
3882 XmNrightWidget
, separator
,
3884 XmNtopAttachment
, XmATTACH_FORM
,
3890 Widget label_with
= (Widget
)0;
3892 str
= XmStringCreateSimple(_("Find what:"));
3893 label_what
= XtVaCreateManagedWidget("whatLabel",
3894 xmLabelGadgetClass
, input_form
,
3895 XmNlabelString
, str
,
3896 XmNleftAttachment
, XmATTACH_FORM
,
3897 XmNtopAttachment
, XmATTACH_FORM
,
3901 gui_motif_menu_fontlist(label_what
);
3903 frdp
->what
= XtVaCreateManagedWidget("whatText",
3904 xmTextFieldWidgetClass
, input_form
,
3905 XmNtopAttachment
, XmATTACH_FORM
,
3906 XmNrightAttachment
, XmATTACH_FORM
,
3907 XmNleftAttachment
, XmATTACH_FORM
,
3912 frdp
->with
= XtVaCreateManagedWidget("withText",
3913 xmTextFieldWidgetClass
, input_form
,
3914 XmNtopAttachment
, XmATTACH_WIDGET
,
3915 XmNtopWidget
, frdp
->what
,
3917 XmNleftAttachment
, XmATTACH_FORM
,
3918 XmNrightAttachment
, XmATTACH_FORM
,
3919 XmNbottomAttachment
, XmATTACH_FORM
,
3922 XtAddCallback(frdp
->with
, XmNactivateCallback
,
3923 find_replace_callback
, (XtPointer
) FRD_R_FINDNEXT
);
3925 str
= XmStringCreateSimple(_("Replace with:"));
3926 label_with
= XtVaCreateManagedWidget("withLabel",
3927 xmLabelGadgetClass
, input_form
,
3928 XmNlabelString
, str
,
3929 XmNleftAttachment
, XmATTACH_FORM
,
3930 XmNtopAttachment
, XmATTACH_WIDGET
,
3931 XmNtopWidget
, frdp
->what
,
3933 XmNbottomAttachment
, XmATTACH_FORM
,
3936 gui_motif_menu_fontlist(label_with
);
3939 * Make the entry activation only change the input focus onto the
3942 XtAddCallback(frdp
->what
, XmNactivateCallback
,
3943 entry_activate_callback
, frdp
->with
);
3944 XtAddEventHandler(frdp
->with
, KeyPressMask
, False
,
3945 (XtEventHandler
)find_replace_keypress
,
3952 * Make the entry activation do the search.
3954 XtAddCallback(frdp
->what
, XmNactivateCallback
,
3955 find_replace_callback
, (XtPointer
)FRD_FINDNEXT
);
3957 XtAddEventHandler(frdp
->what
, KeyPressMask
, False
,
3958 (XtEventHandler
)find_replace_keypress
,
3961 /* Get the maximum width between the label widgets and line them up.
3964 XtSetArg(args
[n
], XmNwidth
, &width
); n
++;
3965 XtGetValues(label_what
, args
, n
);
3969 XtGetValues(label_with
, args
, n
);
3974 XtVaSetValues(frdp
->what
, XmNleftOffset
, widest
, NULL
);
3976 XtVaSetValues(frdp
->with
, XmNleftOffset
, widest
, NULL
);
3980 XtManageChild(input_form
);
3986 frame
= XtVaCreateWidget("directionFrame",
3987 xmFrameWidgetClass
, frdp
->dialog
,
3988 XmNtopAttachment
, XmATTACH_WIDGET
,
3989 XmNtopWidget
, input_form
,
3991 XmNbottomAttachment
, XmATTACH_FORM
,
3993 XmNrightAttachment
, XmATTACH_OPPOSITE_WIDGET
,
3994 XmNrightWidget
, input_form
,
3997 str
= XmStringCreateSimple(_("Direction"));
3998 w
= XtVaCreateManagedWidget("directionFrameLabel",
3999 xmLabelGadgetClass
, frame
,
4000 XmNlabelString
, str
,
4001 XmNchildHorizontalAlignment
, XmALIGNMENT_BEGINNING
,
4002 XmNchildType
, XmFRAME_TITLE_CHILD
,
4005 gui_motif_menu_fontlist(w
);
4007 radio_box
= XmCreateRadioBox(frame
, "radioBox",
4010 str
= XmStringCreateSimple( _("Up"));
4011 frdp
->up
= XtVaCreateManagedWidget("upRadioButton",
4012 xmToggleButtonGadgetClass
, radio_box
,
4013 XmNlabelString
, str
,
4017 gui_motif_menu_fontlist(frdp
->up
);
4019 str
= XmStringCreateSimple(_("Down"));
4020 frdp
->down
= XtVaCreateManagedWidget("downRadioButton",
4021 xmToggleButtonGadgetClass
, radio_box
,
4022 XmNlabelString
, str
,
4026 gui_motif_menu_fontlist(frdp
->down
);
4028 XtManageChild(radio_box
);
4029 XtManageChild(frame
);
4032 toggle_form
= XtVaCreateWidget("toggleForm",
4033 xmFormWidgetClass
, frdp
->dialog
,
4034 XmNleftAttachment
, XmATTACH_FORM
,
4036 XmNrightAttachment
, XmATTACH_WIDGET
,
4037 XmNrightWidget
, frame
,
4039 XmNtopAttachment
, XmATTACH_WIDGET
,
4040 XmNtopWidget
, input_form
,
4042 XmNbottomAttachment
, XmATTACH_FORM
,
4046 str
= XmStringCreateSimple(_("Match whole word only"));
4047 frdp
->wword
= XtVaCreateManagedWidget("wordToggle",
4048 xmToggleButtonGadgetClass
, toggle_form
,
4049 XmNlabelString
, str
,
4050 XmNtopAttachment
, XmATTACH_FORM
,
4052 XmNleftAttachment
, XmATTACH_FORM
,
4058 str
= XmStringCreateSimple(_("Match case"));
4059 frdp
->mcase
= XtVaCreateManagedWidget("caseToggle",
4060 xmToggleButtonGadgetClass
, toggle_form
,
4061 XmNlabelString
, str
,
4062 XmNleftAttachment
, XmATTACH_FORM
,
4064 XmNtopAttachment
, XmATTACH_WIDGET
,
4065 XmNtopWidget
, frdp
->wword
,
4070 gui_motif_menu_fontlist(frdp
->wword
);
4071 gui_motif_menu_fontlist(frdp
->mcase
);
4073 XtManageChild(toggle_form
);
4075 if (entry_text
!= NULL
)
4076 XmTextFieldSetString(frdp
->what
, (char *)entry_text
);
4077 vim_free(entry_text
);
4079 gui_motif_synch_fonts();
4081 manage_centered(frdp
->dialog
);
4082 activate_dialog_mnemonics(frdp
->dialog
);
4083 XmProcessTraversal(frdp
->what
, XmTRAVERSE_CURRENT
);
4087 gui_mch_find_dialog(eap
)
4093 find_replace_dialog_create(eap
->arg
, FALSE
);
4098 gui_mch_replace_dialog(eap
)
4104 find_replace_dialog_create(eap
->arg
, TRUE
);
4108 * Synchronize all gui elements, which are dependant upon the
4109 * main text font used. Those are in esp. the find/replace dialogs.
4110 * If you don't understand why this should be needed, please try to
4111 * search for "piê¶æ" in iso8859-2.
4114 gui_motif_synch_fonts(void)
4116 SharedFindReplace
*frdp
;
4119 XmFontList font_list
;
4121 /* FIXME: Unless we find out how to create a XmFontList from a XFontSet,
4122 * we just give up here on font synchronization. */
4123 font
= (XFontStruct
*)gui
.norm_font
;
4127 font_list
= gui_motif_create_fontlist(font
);
4129 /* OK this loop is a bit tricky... */
4130 for (do_replace
= 0; do_replace
<= 1; ++do_replace
)
4132 frdp
= (do_replace
) ? (&repl_widgets
) : (&find_widgets
);
4135 XtVaSetValues(frdp
->what
, XmNfontList
, font_list
, NULL
);
4137 XtVaSetValues(frdp
->with
, XmNfontList
, font_list
, NULL
);
4141 XmFontListFree(font_list
);