summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile13
-rw-r--r--src/gui_amiga.c2
-rw-r--r--src/gui_beos.cc2
-rw-r--r--src/gui_kde_x11.cc2
-rw-r--r--src/gui_mac.c2
-rw-r--r--src/gui_motif.c606
-rw-r--r--src/gui_photon.c2
-rw-r--r--src/gui_riscos.c2
-rw-r--r--src/gui_w48.c2
-rw-r--r--src/gui_xmdlg.c1287
-rw-r--r--src/misc2.c4
-rw-r--r--src/proto.h1
-rw-r--r--src/proto/gui_xmdlg.pro3
-rw-r--r--src/workshop.c2
14 files changed, 1844 insertions, 86 deletions
diff --git a/src/Makefile b/src/Makefile
index 9b21a2e76..5e43ee9df 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1089,9 +1089,11 @@ GTK_MAN_TARGETS = yes
GTK_TESTTARGET = gui
### Motif GUI
-MOTIF_SRC = gui.c gui_motif.c gui_x11.c pty.c gui_beval.c
+MOTIF_SRC = gui.c gui_motif.c gui_x11.c pty.c gui_beval.c \
+ gui_xmdlg.c
MOTIF_OBJ = objects/gui.o objects/gui_motif.o objects/gui_x11.o \
- objects/pty.o objects/gui_beval.o
+ objects/pty.o objects/gui_beval.o \
+ objects/gui_xmdlg.o
MOTIF_DEFS = -DFEAT_GUI_MOTIF $(NARROW_PROTO)
MOTIF_IPATH = $(GUI_INC_LOC)
MOTIF_LIBS_DIR = $(GUI_LIB_LOC)
@@ -1203,8 +1205,8 @@ CARBONGUI_BUNDLE = $(VIMNAME).app
CARBONGUI_TESTARG = VIMPROG=../$(CARBONGUI_BUNDLE)/Contents/MacOS/$(VIMTARGET)
# All GUI files
-ALL_GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_motif.c gui_athena.c gui_gtk_x11.c gui_x11.c gui_at_sb.c gui_at_fs.c pty.c gui_kde.cc gui_kde_wid.cc gui_kde_x11.cc gui_kde_wid_moc.cc
-ALL_GUI_PRO = gui.pro gui_gtk.pro gui_motif.pro gui_athena.pro gui_gtk_x11.pro gui_x11.pro gui_w16.pro gui_w32.pro gui_amiga.pro gui_photon.pro
+ALL_GUI_SRC = gui.c gui_gtk.c gui_gtk_f.c gui_motif.c gui_xmdlg.c gui_athena.c gui_gtk_x11.c gui_x11.c gui_at_sb.c gui_at_fs.c pty.c gui_kde.cc gui_kde_wid.cc gui_kde_x11.cc gui_kde_wid_moc.cc
+ALL_GUI_PRO = gui.pro gui_gtk.pro gui_motif.pro gui_xmdlg.pro gui_athena.pro gui_gtk_x11.pro gui_x11.pro gui_w16.pro gui_w32.pro gui_amiga.pro gui_photon.pro
# }}}
@@ -2194,6 +2196,9 @@ objects/gui_gtk_x11.o: gui_gtk_x11.c
objects/gui_motif.o: gui_motif.c
$(CCC) -o $@ gui_motif.c
+objects/gui_xmdlg.o: gui_xmdlg.c
+ $(CCC) -o $@ gui_xmdlg.c
+
objects/gui_x11.o: gui_x11.c
$(CCC) -o $@ gui_x11.c
diff --git a/src/gui_amiga.c b/src/gui_amiga.c
index 9ce44ed36..0b76245fd 100644
--- a/src/gui_amiga.c
+++ b/src/gui_amiga.c
@@ -1238,6 +1238,7 @@ gui_mch_get_font(char_u *name, int giveErrorIfMissing)
return NULL;
}
+#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return the name of font "font" in allocated memory.
* We always use the default font.
@@ -1247,6 +1248,7 @@ gui_mch_get_fontname(GuiFont font, char_u *name)
{
return vim_strsave((char_u *)"default");
}
+#endif
void
gui_mch_set_font(GuiFont font)
diff --git a/src/gui_beos.cc b/src/gui_beos.cc
index 32e4db0cb..315136559 100644
--- a/src/gui_beos.cc
+++ b/src/gui_beos.cc
@@ -2396,6 +2396,7 @@ error:
return (GuiFont)font;
}
+#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return the name of font "font" in allocated memory.
*/
@@ -2404,6 +2405,7 @@ gui_mch_get_fontname(GuiFont font, char_u *name)
{
return vim_strsave(((VimFont *)font)->name);
}
+#endif
/*
* Set the current text font.
diff --git a/src/gui_kde_x11.cc b/src/gui_kde_x11.cc
index 8956264d4..c8873ecb7 100644
--- a/src/gui_kde_x11.cc
+++ b/src/gui_kde_x11.cc
@@ -700,6 +700,7 @@ gui_mch_get_font(char_u * name, int report_error)//{{{
return (GuiFont) myFont;
}//}}}
+#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return the name of font "font" in allocated memory.
* Don't know how to get the actual name, thus use the provided name.
@@ -711,6 +712,7 @@ gui_mch_get_fontname(GuiFont font, char_u *name)//{{{
return NULL;
return vim_strsave(name);
}//}}}
+#endif
/*
* Set the current text font.
diff --git a/src/gui_mac.c b/src/gui_mac.c
index f5e29abf2..3b73339df 100644
--- a/src/gui_mac.c
+++ b/src/gui_mac.c
@@ -3569,6 +3569,7 @@ gui_mch_get_font(name, giveErrorIfMissing)
return font;
}
+#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return the name of font "font" in allocated memory.
* Don't know how to get the actual name, thus use the provided name.
@@ -3582,6 +3583,7 @@ gui_mch_get_fontname(font, name)
return NULL;
return vim_strsave(name);
}
+#endif
/*
* Set the current text font.
diff --git a/src/gui_motif.c b/src/gui_motif.c
index 4fe26ec57..d345af5cb 100644
--- a/src/gui_motif.c
+++ b/src/gui_motif.c
@@ -93,9 +93,6 @@ static void attachDump(Widget, char *);
static void gui_motif_menu_colors __ARGS((Widget id));
static void gui_motif_scroll_colors __ARGS((Widget id));
-#ifdef FEAT_MENU
-static void gui_motif_menu_fontlist __ARGS((Widget id));
-#endif
#if (XmVersion >= 1002)
# define STRING_TAG XmFONTLIST_DEFAULT_TAG
@@ -125,17 +122,122 @@ scroll_cb(w, client_data, call_data)
gui_drag_scrollbar(sb, value, dragging);
}
-
/*
* End of call-back routines
*/
+#ifndef LESSTIF_VERSION
+/*
+ * Implement three dimensional shading of insensitive labels.
+ * By Martin Dalecki.
+ */
+
+#include <Xm/XmP.h>
+#include <Xm/LabelP.h>
+
+static XtExposeProc old_label_expose = NULL;
+
+static void label_expose __ARGS((Widget _w, XEvent *_event, Region _region));
+
+ static void
+label_expose(_w, _event, _region)
+ Widget _w;
+ XEvent *_event;
+ Region _region;
+{
+ GC insensitiveGC;
+ XmLabelWidget lw = (XmLabelWidget)_w;
+ unsigned char label_type = XmSTRING;
+
+ XtVaGetValues(_w, XmNlabelType, &label_type, (XtPointer)0);
+
+ if (XtIsSensitive(_w) || label_type != XmSTRING)
+ (*old_label_expose)(_w, _event, _region);
+ else
+ {
+ XGCValues values;
+ XtGCMask mask;
+ XtGCMask dynamic;
+ XFontStruct *fs;
+
+ _XmFontListGetDefaultFont(lw->label.font, &fs);
+
+ /* FIXME: we should be doing the whole drawing ourself here. */
+ insensitiveGC = lw->label.insensitive_GC;
+
+ mask = GCForeground | GCBackground | GCGraphicsExposures;
+ dynamic = GCClipMask | GCClipXOrigin | GCClipYOrigin;
+ values.graphics_exposures = False;
+
+ if (fs != 0)
+ {
+ mask |= GCFont;
+ values.font = fs->fid;
+ }
+
+ if (lw->primitive.top_shadow_pixmap != None
+ && lw->primitive.top_shadow_pixmap != XmUNSPECIFIED_PIXMAP)
+ {
+ mask |= GCFillStyle | GCTile;
+ values.fill_style = FillTiled;
+ values.tile = lw->primitive.top_shadow_pixmap;
+ }
+
+ lw->label.TextRect.x += 1;
+ lw->label.TextRect.y += 1;
+ if (lw->label._acc_text != 0)
+ {
+ lw->label.acc_TextRect.x += 1;
+ lw->label.acc_TextRect.y += 1;
+ }
+
+ values.foreground = lw->primitive.top_shadow_color;
+ values.background = lw->core.background_pixel;
+
+ lw->label.insensitive_GC =
+ XtAllocateGC((Widget) lw, 0, mask, &values, dynamic, 0);
+ (*old_label_expose)(_w, _event, _region);
+ XtReleaseGC(_w, lw->label.insensitive_GC);
+
+ lw->label.TextRect.x -= 1;
+ lw->label.TextRect.y -= 1;
+ if (lw->label._acc_text != 0)
+ {
+ lw->label.acc_TextRect.x -= 1;
+ lw->label.acc_TextRect.y -= 1;
+ }
+
+ values.foreground = lw->primitive.bottom_shadow_color;
+ values.background = lw->core.background_pixel;
+
+ lw->label.insensitive_GC =
+ XtAllocateGC((Widget) lw, 0, mask, &values, dynamic, 0);
+ (*old_label_expose)(_w, _event, _region);
+ XtReleaseGC(_w, lw->label.insensitive_GC);
+
+ lw->label.insensitive_GC = insensitiveGC;
+ }
+}
+#endif
+
+
/*
* Create all the motif widgets necessary.
*/
void
gui_x11_create_widgets()
{
+#ifndef LESSTIF_VERSION
+ /*
+ * Install the 3D shade effect drawing routines.
+ */
+ if (old_label_expose == NULL)
+ {
+ old_label_expose = xmLabelWidgetClass->core_class.expose;
+ xmLabelWidgetClass->core_class.expose = label_expose;
+ }
+#endif
+
/*
* Start out by adding the configured border width into the border offset
*/
@@ -329,9 +431,7 @@ gui_x11_set_back_color()
* Manage dialog centered on pointer. This could be used by the Athena code as
* well.
*/
-static void manage_centered __ARGS((Widget dialog_child));
-
-static void
+ void
manage_centered(dialog_child)
Widget dialog_child;
{
@@ -855,16 +955,15 @@ gui_mch_add_menu_item(menu, idx)
xms = XmStringCreate((char *)menu->dname, STRING_TAG);
XtSetArg(args[n], XmNlabelString, xms); n++;
-#ifndef FEAT_SUN_WORKSHOP
-
/* Without shadows one can't sense whatever the button has been
* pressed or not! However we wan't to save a bit of space...
+ * Need the highlightThickness to see the focus.
*/
- XtSetArg(args[n], XmNhighlightThickness, 0); n++;
+ XtSetArg(args[n], XmNhighlightThickness, 1); n++;
XtSetArg(args[n], XmNhighlightOnEnter, True); n++;
XtSetArg(args[n], XmNmarginWidth, 0); n++;
XtSetArg(args[n], XmNmarginHeight, 0); n++;
-#endif
+
if (menu->image == 0)
{
XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
@@ -1384,7 +1483,6 @@ gui_mch_create_scrollbar(sb, orient)
int n;
n = 0;
- XtSetArg(args[n], XmNshadowThickness, 1); n++;
XtSetArg(args[n], XmNminimum, 0); n++;
XtSetArg(args[n], XmNorientation,
(orient == SBAR_VERT) ? XmVERTICAL : XmHORIZONTAL); n++;
@@ -1484,6 +1582,219 @@ gui_x11_get_wid()
return(XtWindow(textArea));
}
+/*
+ * Look for a widget in the widget tree w, with a mnemonic matching keycode.
+ * When one is found, simulate a button press on that widget and give it the
+ * keyboard focus. If the mnemonic is on a label, look in the userData field
+ * of the label to see if it points to another widget, and give that the focus.
+ */
+ static void
+do_mnemonic(Widget w, unsigned int keycode)
+{
+ WidgetList children;
+ int numChildren, i;
+ Boolean isMenu;
+ KeySym mnemonic = '\0';
+ char mneString[2];
+ Widget userData;
+ unsigned char rowColType;
+
+ if (XtIsComposite(w))
+ {
+ if (XtClass(w) == xmRowColumnWidgetClass)
+ {
+ XtVaGetValues(w, XmNrowColumnType, &rowColType, 0);
+ isMenu = (rowColType != (unsigned char)XmWORK_AREA);
+ }
+ else
+ isMenu = False;
+ if (!isMenu)
+ {
+ XtVaGetValues(w, XmNchildren, &children, XmNnumChildren,
+ &numChildren, 0);
+ for (i = 0; i < numChildren; i++)
+ do_mnemonic(children[i], keycode);
+ }
+ }
+ else
+ {
+ XtVaGetValues(w, XmNmnemonic, &mnemonic, 0);
+ if (mnemonic != '\0')
+ {
+ mneString[0] = mnemonic;
+ mneString[1] = '\0';
+ if (XKeysymToKeycode(XtDisplay(XtParent(w)),
+ XStringToKeysym(mneString)) == keycode)
+ {
+ if (XtClass(w) == xmLabelWidgetClass
+ || XtClass(w) == xmLabelGadgetClass)
+ {
+ XtVaGetValues(w, XmNuserData, &userData, 0);
+ if (userData != NULL && XtIsWidget(userData))
+ XmProcessTraversal(userData, XmTRAVERSE_CURRENT);
+ }
+ else
+ {
+ XKeyPressedEvent keyEvent;
+
+ XmProcessTraversal(w, XmTRAVERSE_CURRENT);
+
+ memset((char *) &keyEvent, 0, sizeof(XKeyPressedEvent));
+ keyEvent.type = KeyPress;
+ keyEvent.serial = 1;
+ keyEvent.send_event = True;
+ keyEvent.display = XtDisplay(w);
+ keyEvent.window = XtWindow(w);
+ XtCallActionProc(w, "Activate", (XEvent *) & keyEvent,
+ NULL, 0);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Callback routine for dialog mnemonic processing.
+ */
+/*ARGSUSED*/
+ static void
+mnemonic_event(Widget w, XtPointer call_data, XKeyEvent *event)
+{
+ do_mnemonic(w, event->keycode);
+}
+
+
+/*
+ * Search the widget tree under w for widgets with mnemonics. When found, add
+ * a passive grab to the dialog widget for the mnemonic character, thus
+ * directing mnemonic events to the dialog widget.
+ */
+ static void
+add_mnemonic_grabs(Widget dialog, Widget w)
+{
+ char mneString[2];
+ WidgetList children;
+ int numChildren, i;
+ Boolean isMenu;
+ KeySym mnemonic = '\0';
+ unsigned char rowColType;
+
+ if (XtIsComposite(w))
+ {
+ if (XtClass(w) == xmRowColumnWidgetClass)
+ {
+ XtVaGetValues(w, XmNrowColumnType, &rowColType, 0);
+ isMenu = (rowColType != (unsigned char)XmWORK_AREA);
+ }
+ else
+ isMenu = False;
+ if (!isMenu)
+ {
+ XtVaGetValues(w, XmNchildren, &children, XmNnumChildren,
+ &numChildren, 0);
+ for (i = 0; i < numChildren; i++)
+ add_mnemonic_grabs(dialog, children[i]);
+ }
+ }
+ else
+ {
+ XtVaGetValues(w, XmNmnemonic, &mnemonic, 0);
+ if (mnemonic != '\0')
+ {
+ mneString[0] = mnemonic;
+ mneString[1] = '\0';
+ XtGrabKey(dialog, XKeysymToKeycode(XtDisplay(dialog),
+ XStringToKeysym(mneString)),
+ Mod1Mask, True, GrabModeAsync, GrabModeAsync);
+ }
+ }
+}
+
+/*
+ * Add a handler for mnemonics in a dialog. Motif itself only handles
+ * mnemonics in menus. Mnemonics added or changed after this call will be
+ * ignored.
+ *
+ * To add a mnemonic to a text field or list, set the XmNmnemonic resource on
+ * the appropriate label and set the XmNuserData resource of the label to the
+ * widget to get the focus when the mnemonic is typed.
+ */
+ static void
+activate_dialog_mnemonics(Widget dialog)
+{
+ if (!dialog)
+ return;
+
+ XtAddEventHandler(dialog, KeyPressMask, False,
+ (XtEventHandler) mnemonic_event, (XtPointer) NULL);
+ add_mnemonic_grabs(dialog, dialog);
+}
+
+/*
+ * Removes the event handler and key-grabs for dialog mnemonic handling.
+ */
+ static void
+suppress_dialog_mnemonics(Widget dialog)
+{
+ if (!dialog)
+ return;
+
+ XtUngrabKey(dialog, AnyKey, Mod1Mask);
+ XtRemoveEventHandler(dialog, KeyPressMask, False,
+ (XtEventHandler) mnemonic_event, (XtPointer) NULL);
+}
+
+#if defined(FEAT_BROWSE) || defined(FEAT_GUI_DIALOG)
+static void set_fontlist __ARGS((Widget wg));
+
+/*
+ * Use the 'guifont' or 'guifontset' as a fontlist for a dialog widget.
+ */
+ static void
+set_fontlist(id)
+ Widget id;
+{
+ XmFontList fl;
+
+#ifdef FONTSET_ALWAYS
+ if (gui.fontset != NOFONTSET) {
+ fl = gui_motif_fontset2fontlist((XFontSet *)&gui.fontset);
+ if (fl != NULL)
+ {
+ if (XtIsManaged(id))
+ {
+ XtUnmanageChild(id);
+ XtVaSetValues(id, XmNfontList, fl, NULL);
+ /* We should force the widget to recalculate it's
+ * geometry now. */
+ XtManageChild(id);
+ }
+ else
+ XtVaSetValues(id, XmNfontList, fl, NULL);
+ XmFontListFree(fl);
+ }
+ }
+#else
+ if (gui.norm_font != NOFONT) {
+ fl = gui_motif_create_fontlist((XFontStruct *)gui.norm_font);
+ if (fl != NULL)
+ {
+ if (XtIsManaged(id))
+ {
+ XtUnmanageChild(id);
+ XtVaSetValues(id, XmNfontList, fl, NULL);
+ /* We should force the widget to recalculate it's
+ * geometry now. */
+ XtManageChild(id);
+ }
+ else
+ XtVaSetValues(id, XmNfontList, fl, NULL);
+ XmFontListFree(fl);
+ }
+ }
+#endif
+}
+#endif
#if defined(FEAT_BROWSE) || defined(PROTO)
@@ -1517,29 +1828,67 @@ static void DialogAcceptCB __ARGS((Widget, XtPointer, XtPointer));
* - equalize the messages between different GUI implementations as far as
* possible.
*/
-static void set_predefined_label __ARGS((Widget parent, String name, char * new_label));
+static void set_predefined_label __ARGS((Widget parent, String name, char *new_label));
static void
set_predefined_label(parent, name, new_label)
- Widget parent;
- String name;
- char * new_label;
+ Widget parent;
+ String name;
+ char *new_label;
{
- XmString str;
- Widget w;
+ XmString str;
+ Widget w;
+ char_u *p, *next;
+ KeySym mnemonic = NUL;
w = XtNameToWidget(parent, name);
if (!w)
return;
- str = XmStringCreate(new_label, STRING_TAG);
+ p = vim_strsave((char_u *)new_label);
+ if (p == NULL)
+ return;
+ for (next = p; *next; ++next)
+ {
+ if (*next == DLG_HOTKEY_CHAR)
+ {
+ int len = STRLEN(next);
- if (str)
+ if (len > 0)
+ {
+ mch_memmove(next, next + 1, len);
+ mnemonic = next[0];
+ }
+ }
+ }
+
+ str = XmStringCreate((char *)p, STRING_TAG);
+ vim_free(p);
+
+ if (str != NULL)
{
- XtVaSetValues(w, XmNlabelString, str, NULL);
+ XtVaSetValues(w,
+ XmNlabelString, str,
+ XmNmnemonic, mnemonic,
+ NULL);
XmStringFree(str);
}
+ gui_motif_menu_fontlist(w);
+}
+
+static void
+set_predefined_fontlist(parent, name)
+ Widget parent;
+ String name;
+{
+ Widget w;
+ w = XtNameToWidget(parent, name);
+
+ if (!w)
+ return;
+
+ set_fontlist(w);
}
/*
@@ -1561,7 +1910,12 @@ gui_mch_browse(saving, title, dflt, ext, initdir, filter)
char_u *pattern;
char_u *tofree = NULL;
- dialog_wgt = XmCreateFileSelectionDialog(vimShell, (char *)title, NULL, 0);
+ /* There a difference between the resource name and value, Therefore, we
+ * avoid to (ab-)use the (maybe internationalized!) dialog title as a
+ * dialog name.
+ */
+
+ dialog_wgt = XmCreateFileSelectionDialog(vimShell, "browseDialog", NULL, 0);
if (initdir == NULL || *initdir == NUL)
{
@@ -1614,15 +1968,21 @@ gui_mch_browse(saving, title, dflt, ext, initdir, filter)
XmNdialogTitle, XmRString, (char *)title, STRLEN(title) + 1,
NULL);
- set_predefined_label(dialog_wgt, "Apply", _("Filter"));
- set_predefined_label(dialog_wgt, "Cancel", _("Cancel"));
+ set_predefined_label(dialog_wgt, "Apply", _("&Filter"));
+ set_predefined_label(dialog_wgt, "Cancel", _("&Cancel"));
set_predefined_label(dialog_wgt, "Dir", _("Directories"));
set_predefined_label(dialog_wgt, "FilterLabel", _("Filter"));
- set_predefined_label(dialog_wgt, "Help", _("Help"));
+ set_predefined_label(dialog_wgt, "Help", _("&Help"));
set_predefined_label(dialog_wgt, "Items", _("Files"));
- set_predefined_label(dialog_wgt, "OK", _("OK"));
+ set_predefined_label(dialog_wgt, "OK", _("&OK"));
set_predefined_label(dialog_wgt, "Selection", _("Selection"));
+ /* This is to save us from silly external settings using not fixed with
+ * fonts for file selection.
+ */
+ set_predefined_fontlist(dialog_wgt, "DirListSW.DirList");
+ set_predefined_fontlist(dialog_wgt, "ItemsListSW.ItemsList");
+
gui_motif_menu_colors(dialog_wgt);
if (gui.scroll_bg_pixel != INVALCOLOR)
XtVaSetValues(dialog_wgt, XmNtroughColor, gui.scroll_bg_pixel, NULL);
@@ -1634,6 +1994,7 @@ gui_mch_browse(saving, title, dflt, ext, initdir, filter)
(unsigned char)XmDIALOG_HELP_BUTTON));
manage_centered(dialog_wgt);
+ activate_dialog_mnemonics(dialog_wgt);
/* sit in a loop until the dialog box has gone away */
do
@@ -1642,6 +2003,7 @@ gui_mch_browse(saving, title, dflt, ext, initdir, filter)
(XtInputMask)XtIMAll);
} while (XtIsManaged(dialog_wgt));
+ suppress_dialog_mnemonics(dialog_wgt);
XtDestroyWidget(dialog_wgt);
vim_free(tofree);
@@ -1746,31 +2108,6 @@ butproc(w, client_data, call_data)
dialogStatus = (int)(long)client_data + 1;
}
-static void gui_motif_set_fontlist __ARGS((Widget wg));
-
-/*
- * Use the 'guifont' or 'guifontset' as a fontlist for a dialog widget.
- */
- static void
-gui_motif_set_fontlist(wg)
- Widget wg;
-{
- XmFontList fl;
-
- fl =
-#ifdef FEAT_XFONTSET
- gui.fontset != NOFONTSET ?
- gui_motif_fontset2fontlist((XFontSet *)&gui.fontset)
- :
-#endif
- gui_motif_create_fontlist((XFontStruct *)gui.norm_font);
- if (fl != NULL)
- {
- XtVaSetValues(wg, XmNfontList, fl, NULL);
- XmFontListFree(fl);
- }
-}
-
#ifdef HAVE_XPM
static Widget create_pixmap_label(Widget parent, String name, char **data, ArgList args, Cardinal arg);
@@ -1853,6 +2190,7 @@ gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
XtAppContext app;
XmString label;
int butcount;
+ Widget w;
Widget dialogform = NULL;
Widget form = NULL;
Widget dialogtextfield = NULL;
@@ -1913,10 +2251,20 @@ gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
p = buts;
for (butcount = 0; *p; ++butcount)
{
+ KeySym mnemonic = NUL;
+
for (next = p; *next; ++next)
{
if (*next == DLG_HOTKEY_CHAR)
- mch_memmove(next, next + 1, STRLEN(next));
+ {
+ int len = STRLEN(next);
+
+ if (len > 0)
+ {
+ mch_memmove(next, next + 1, len);
+ mnemonic = next[0];
+ }
+ }
if (*next == DLG_BUTTON_SEP)
{
*next++ = NUL;
@@ -1930,12 +2278,14 @@ gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
buttons[butcount] = XtVaCreateManagedWidget("button",
xmPushButtonWidgetClass, dialogform,
XmNlabelString, label,
+ XmNmnemonic, mnemonic,
XmNbottomAttachment, XmATTACH_FORM,
XmNbottomOffset, 4,
XmNshowAsDefault, butcount == dfltbutton - 1,
XmNdefaultButtonShadowThickness, 1,
NULL);
XmStringFree(label);
+ gui_motif_menu_fontlist(buttons[butcount]);
/* Layout properly. */
@@ -2041,7 +2391,7 @@ gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
XmNbottomAttachment, XmATTACH_FORM,
NULL);
- gui_motif_set_fontlist(dialogtextfield);
+ set_fontlist(dialogtextfield);
XmTextFieldSetString(dialogtextfield, (char *)textfield);
XtManageChild(dialogtextfield);
XtAddEventHandler(dialogtextfield, KeyPressMask, False,
@@ -2093,13 +2443,19 @@ gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
XtManageChild(dialogpixmap);
#endif
- /* Create the dialog message. */
- label = XmStringLtoRCreate((char *)message, STRING_TAG);
+ /* Create the dialog message.
+ * Since LessTif is apparently having problems with the creation of
+ * properly localized string, we use LtoR here. The symptom is that the
+ * string sill not show properly in multiple lines as it does in native
+ * Motif.
+ */
+ label = XmStringCreateLtoR((char *)message, STRING_TAG);
if (label == NULL)
return -1;
- (void)XtVaCreateManagedWidget("dialogMessage",
+ w = XtVaCreateManagedWidget("dialogMessage",
xmLabelGadgetClass, form,
XmNlabelString, label,
+ XmNalignment, XmALIGNMENT_BEGINNING,
XmNtopAttachment, XmATTACH_FORM,
XmNtopOffset, 8,
#ifdef HAVE_XPM
@@ -2115,6 +2471,7 @@ gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
XmNbottomOffset, 8,
NULL);
XmStringFree(label);
+ set_fontlist(w);
if (textfield != NULL)
{
@@ -2149,6 +2506,7 @@ gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
NULL);
manage_centered(dialogform);
+ activate_dialog_mnemonics(dialogform);
if (textfield != NULL && *textfield != NUL)
{
@@ -2185,6 +2543,7 @@ gui_mch_dialog(type, title, message, button_names, dfltbutton, textfield)
}
}
+ suppress_dialog_mnemonics(dialogform);
XtDestroyWidget(dialogform);
return dialogStatus;
@@ -2246,8 +2605,11 @@ gui_mch_set_footer(s)
XmString xms;
xms = XmStringCreate((char *)s, STRING_TAG);
- XtVaSetValues(footer, XmNlabelString, xms, NULL);
- XmStringFree(xms);
+ if (xms != NULL)
+ {
+ XtVaSetValues(footer, XmNlabelString, xms, NULL);
+ XmStringFree(xms);
+ }
}
#endif
@@ -2522,14 +2884,15 @@ gui_motif_scroll_colors(id)
XtVaSetValues(id, XmNforeground, gui.scroll_fg_pixel, NULL);
}
-#ifdef FEAT_MENU
/*
* Set the fontlist for Widget "id" to use gui.menu_fontset or gui.menu_font.
*/
- static void
+/*ARGSUSED*/
+ void
gui_motif_menu_fontlist(id)
Widget id;
{
+#ifdef FEAT_MENU
#ifdef FONTSET_ALWAYS
if (gui.menu_fontset != NOFONTSET)
{
@@ -2573,9 +2936,9 @@ gui_motif_menu_fontlist(id)
}
}
#endif
+#endif
}
-#endif
/*
* We don't create it twice for the sake of speed.
@@ -2617,8 +2980,10 @@ find_replace_destroy_callback(w, client_data, call_data)
{
SharedFindReplace *cd = (SharedFindReplace *)client_data;
- if (cd != NULL)
+ if (cd != NULL) {
+ /* suppress_dialog_mnemonics(cd->dialog); */
cd->dialog = (Widget)0;
+ }
}
/*ARGSUSED*/
@@ -2719,6 +3084,48 @@ find_replace_keypress(w, frdp, event)
}
static void
+set_label(w, label)
+ Widget w;
+ char_u *label;
+{
+ XmString str;
+ char_u *p, *next;
+ KeySym mnemonic = NUL;
+
+ if (!w)
+ return;
+
+ p = vim_strsave(label);
+ if (p == NULL)
+ return;
+ for (next = p; *next; ++next)
+ {
+ if (*next == DLG_HOTKEY_CHAR)
+ {
+ int len = STRLEN(next);
+
+ if (len > 0)
+ {
+ mch_memmove(next, next + 1, len);
+ mnemonic = next[0];
+ }
+ }
+ }
+
+ str = XmStringCreateSimple((char *)p);
+ vim_free(p);
+ if (str)
+ {
+ XtVaSetValues(w,
+ XmNlabelString, str,
+ XmNmnemonic, mnemonic,
+ NULL);
+ XmStringFree(str);
+ }
+ gui_motif_menu_fontlist(w);
+}
+
+ static void
find_replace_dialog_create(arg, do_replace)
char_u *arg;
int do_replace;
@@ -2746,6 +3153,8 @@ find_replace_dialog_create(arg, do_replace)
/* If the dialog already exists, just raise it. */
if (frdp->dialog)
{
+ gui_motif_synch_fonts();
+
/* If the window is already up, just pop it to the top */
if (XtIsManaged(frdp->dialog))
XMapRaised(XtDisplay(frdp->dialog),
@@ -2789,16 +3198,14 @@ find_replace_dialog_create(arg, do_replace)
XmNbottomOffset, 4,
NULL);
- str = XmStringCreateSimple(_("Find Next"));
frdp->find = XtVaCreateManagedWidget("findButton",
xmPushButtonWidgetClass, button_form,
- XmNlabelString, str,
XmNsensitive, True,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
- XmStringFree(str);
+ set_label(frdp->find, _("Find &Next"));
XtAddCallback(frdp->find, XmNactivateCallback,
find_replace_callback,
@@ -2806,57 +3213,50 @@ find_replace_dialog_create(arg, do_replace)
if (do_replace)
{
- str = XmStringCreateSimple(_("Replace"));
frdp->replace = XtVaCreateManagedWidget("replaceButton",
xmPushButtonWidgetClass, button_form,
- XmNlabelString, str,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, frdp->find,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
- XmStringFree(str);
+ set_label(frdp->replace, _("&Replace"));
XtAddCallback(frdp->replace, XmNactivateCallback,
find_replace_callback, (XtPointer)FRD_REPLACE);
- str = XmStringCreateSimple(_("Replace All"));
frdp->all = XtVaCreateManagedWidget("replaceAllButton",
xmPushButtonWidgetClass, button_form,
- XmNlabelString, str,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, frdp->replace,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
- XmStringFree(str);
+ set_label(frdp->all, _("Replace &All"));
XtAddCallback(frdp->all, XmNactivateCallback,
find_replace_callback, (XtPointer)FRD_REPLACEALL);
- str = XmStringCreateSimple(_("Undo"));
frdp->undo = XtVaCreateManagedWidget("undoButton",
xmPushButtonWidgetClass, button_form,
- XmNlabelString, str,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, frdp->all,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
- XmStringFree(str);
+ set_label(frdp->undo, _("&Undo"));
XtAddCallback(frdp->undo, XmNactivateCallback,
find_replace_callback, (XtPointer)FRD_UNDO);
}
- str = XmStringCreateSimple(_("Cancel"));
frdp->cancel = XtVaCreateManagedWidget("closeButton",
xmPushButtonWidgetClass, button_form,
- XmNlabelString, str,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
NULL);
- XmStringFree(str);
+ set_label(frdp->cancel, _("&Cancel"));
XtAddCallback(frdp->cancel, XmNactivateCallback,
find_replace_dismiss_callback, frdp);
+ gui_motif_menu_fontlist(frdp->cancel);
XtManageChild(button_form);
@@ -2894,6 +3294,7 @@ find_replace_dialog_create(arg, do_replace)
XmNtopOffset, 4,
NULL);
XmStringFree(str);
+ gui_motif_menu_fontlist(label_what);
frdp->what = XtVaCreateManagedWidget("whatText",
xmTextFieldWidgetClass, input_form,
@@ -2928,6 +3329,7 @@ find_replace_dialog_create(arg, do_replace)
XmNbottomAttachment, XmATTACH_FORM,
NULL);
XmStringFree(str);
+ gui_motif_menu_fontlist(label_with);
/*
* Make the entry activation only change the input focus onto the
@@ -2975,6 +3377,7 @@ find_replace_dialog_create(arg, do_replace)
{
Widget radio_box;
+ Widget w;
frame = XtVaCreateWidget("directionFrame",
xmFrameWidgetClass, frdp->dialog,
@@ -2988,13 +3391,14 @@ find_replace_dialog_create(arg, do_replace)
NULL);
str = XmStringCreateSimple(_("Direction"));
- (void)XtVaCreateManagedWidget("directionFrameLabel",
+ w = XtVaCreateManagedWidget("directionFrameLabel",
xmLabelGadgetClass, frame,
XmNlabelString, str,
XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
XmNchildType, XmFRAME_TITLE_CHILD,
NULL);
XmStringFree(str);
+ gui_motif_menu_fontlist(w);
radio_box = XmCreateRadioBox(frame, "radioBox",
(ArgList)NULL, 0);
@@ -3006,6 +3410,7 @@ find_replace_dialog_create(arg, do_replace)
XmNset, False,
NULL);
XmStringFree(str);
+ gui_motif_menu_fontlist(frdp->up);
str = XmStringCreateSimple(_("Down"));
frdp->down = XtVaCreateManagedWidget("downRadioButton",
@@ -3014,6 +3419,7 @@ find_replace_dialog_create(arg, do_replace)
XmNset, True,
NULL);
XmStringFree(str);
+ gui_motif_menu_fontlist(frdp->down);
XtManageChild(radio_box);
XtManageChild(frame);
@@ -3057,6 +3463,8 @@ find_replace_dialog_create(arg, do_replace)
XmNset, mcase,
NULL);
XmStringFree(str);
+ gui_motif_menu_fontlist(frdp->wword);
+ gui_motif_menu_fontlist(frdp->mcase);
XtManageChild(toggle_form);
@@ -3064,7 +3472,10 @@ find_replace_dialog_create(arg, do_replace)
XmTextFieldSetString(frdp->what, (char *)entry_text);
vim_free(entry_text);
- XtManageChild(frdp->dialog);
+ gui_motif_synch_fonts();
+
+ manage_centered(frdp->dialog);
+ activate_dialog_mnemonics(frdp->dialog);
XmProcessTraversal(frdp->what, XmTRAVERSE_CURRENT);
}
@@ -3088,3 +3499,40 @@ gui_mch_replace_dialog(eap)
find_replace_dialog_create(eap->arg, TRUE);
}
+
+/*
+ * Synchronize all gui elements, which are dependant upon the
+ * main text font used. Those are in esp. the find/replace dialogs.
+ * If you don't understand why this should be needed, please try to
+ * search for "pięść" in iso8859-2.
+ */
+ void
+gui_motif_synch_fonts(void)
+{
+ SharedFindReplace *frdp;
+ int do_replace;
+ XFontStruct *font;
+ XmFontList font_list;
+
+ /* FIXME: Unless we find out how to create a XmFontList from a XFontSet,
+ * we just give up here on font synchronization. */
+ font = (XFontStruct *)gui.norm_font;
+ if (font == NULL)
+ return;
+
+ font_list = gui_motif_create_fontlist(font);
+
+ /* OK this loop is a bit tricky... */
+ for (do_replace = 0; do_replace <= 1; ++do_replace)
+ {
+ frdp = (do_replace) ? (&repl_widgets) : (&find_widgets);
+ if (frdp->dialog)
+ {
+ XtVaSetValues(frdp->what, XmNfontList, font_list, NULL);
+ if (do_replace)
+ XtVaSetValues(frdp->with, XmNfontList, font_list, NULL);
+ }
+ }
+
+ XmFontListFree(font_list);
+}
diff --git a/src/gui_photon.c b/src/gui_photon.c
index b7c92df3d..9223a40ec 100644
--- a/src/gui_photon.c
+++ b/src/gui_photon.c
@@ -3047,6 +3047,7 @@ gui_mch_get_font(char_u *vim_font_name, int report_error)
return( FAIL );
}
+#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return the name of font "font" in allocated memory.
* Don't know how to get the actual name, thus use the provided name.
@@ -3060,6 +3061,7 @@ gui_mch_get_fontname(font, name)
return NULL;
return vim_strsave(name);
}
+#endif
void
gui_mch_set_font(GuiFont font)
diff --git a/src/gui_riscos.c b/src/gui_riscos.c
index 7c9555e60..f9784a241 100644
--- a/src/gui_riscos.c
+++ b/src/gui_riscos.c
@@ -1052,6 +1052,7 @@ gui_mch_get_font(name, giveErrorIfMissing)
return handle;
}
+#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return the name of font "font" in allocated memory.
* Don't know how to get the actual name, thus use the provided name.
@@ -1065,6 +1066,7 @@ gui_mch_get_fontname(font, name)
return NULL;
return vim_strsave(name);
}
+#endif
/*
* Set the current text font.
diff --git a/src/gui_w48.c b/src/gui_w48.c
index b3948ce31..77cc24dbe 100644
--- a/src/gui_w48.c
+++ b/src/gui_w48.c
@@ -1249,6 +1249,7 @@ gui_mch_get_font(
return font;
}
+#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return the name of font "font" in allocated memory.
* Don't know how to get the actual name, thus use the provided name.
@@ -1262,6 +1263,7 @@ gui_mch_get_fontname(font, name)
return NULL;
return vim_strsave(name);
}
+#endif
void
gui_mch_free_font(GuiFont font)
diff --git a/src/gui_xmdlg.c b/src/gui_xmdlg.c
new file mode 100644
index 000000000..3f1bd554f
--- /dev/null
+++ b/src/gui_xmdlg.c
@@ -0,0 +1,1287 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI/Motif support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * (C) 2001 by Marcin Dalecki <dalecki@evision.ag>
+ *
+ * Implementation of dialogue functions for the Motif GUI variant.
+ */
+
+#include <Xm/Form.h>
+#include <Xm/PushBG.h>
+#include <Xm/Text.h>
+#include <Xm/TextF.h>
+#include <Xm/Label.h>
+#include <Xm/Frame.h>
+#include <Xm/LabelG.h>
+#include <Xm/ToggleBG.h>
+#include <Xm/SeparatoG.h>
+#include <Xm/DialogS.h>
+#include <Xm/List.h>
+#include <Xm/RowColumn.h>
+#include <Xm/AtomMgr.h>
+#include <Xm/Protocols.h>
+
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/StringDefs.h>
+#include <X11/Intrinsic.h>
+
+#include "vim.h"
+
+extern Widget vimShell;
+
+#ifdef FEAT_MENU
+# define apply_fontlist(w) gui_motif_menu_fontlist(w)
+#else
+# define apply_fontlist(w)
+#endif
+
+/****************************************************************************
+ * Font selection dialogue implementation.
+ */
+
+static char wild[3] = "*";
+
+/*
+ * FIXME: This is a generic function, which should be used throughout the whole
+ * application.
+ *
+ * Add close_callback, which will be called when the user selects close from
+ * the window menu. The close menu item usually activates f.kill which sends a
+ * WM_DELETE_WINDOW protocol request for the window.
+ */
+
+ static void
+add_cancel_action(Widget shell, XtCallbackProc close_callback, void *arg)
+{
+ static Atom wmp_atom = 0;
+ static Atom dw_atom = 0;
+ Display *display = XtDisplay(shell);
+
+ /* deactivate the built-in delete response of killing the application */
+ XtVaSetValues(shell, XmNdeleteResponse, XmDO_NOTHING, 0);
+
+ /* add a delete window protocol callback instead */
+ if (!dw_atom)
+ {
+ wmp_atom = XmInternAtom(display, "WM_PROTOCOLS", True);
+ dw_atom = XmInternAtom(display, "WM_DELETE_WINDOW", True);
+ }
+ XmAddProtocolCallback(shell, wmp_atom, dw_atom, close_callback, arg);
+}
+
+#define MAX_FONTS 65535
+#define MAX_FONT_NAME_LEN 256
+#define MAX_ENTRIES_IN_LIST 5000
+#define MAX_DISPLAY_SIZE 150
+#define TEMP_BUF_SIZE 256
+
+enum ListSpecifier
+{
+ ENCODING,
+ NAME,
+ STYLE,
+ SIZE,
+ NONE
+};
+
+typedef struct _SharedFontSelData
+{
+ Widget dialog;
+ Widget ok;
+ Widget cancel;
+ Widget encoding_pulldown;
+ Widget encoding_menu;
+ Widget list[NONE];
+ Widget name;
+ Widget sample;
+ char **names; /* font name array of arrays */
+ int num; /* number of font names */
+ String sel[NONE]; /* selection category */
+ Boolean in_pixels; /* toggle state - size in pixels */
+ char *font_name; /* current font name */
+ XFontStruct *old; /* font data structure for sample display */
+ XmFontList old_list; /* font data structure for sample display */
+ Boolean exit; /* used for program exit control */
+} SharedFontSelData;
+
+/*
+ * Checking access to the font name array for validity.
+ */
+ static char *
+fn(SharedFontSelData *data, int i)
+{
+ /* Assertion checks: */
+ if (data->num < 0)
+ abort();
+ if (i >= data->num)
+ i = data->num - 1;
+ if (i < 0)
+ i = 0;
+
+ return data->names[i];
+}
+
+/*
+ * Get a specific substring from a font name.
+ */
+ static void
+get_part(char *in, int pos, char *out)
+{
+ int i;
+ int j;
+
+ *out = '\0';
+
+ for (i = 0; (pos > 0) && (in[i] != '\0'); ++i)
+ if (in[i] == '-')
+ pos--;
+
+ if (in[i] == '\0')
+ return;
+
+ for (j = 0; (in[i] != '-') && (in[i] != '\0'); ++i, ++j)
+ out[j] = in[i];
+ out[j] = '\0';
+}
+
+/*
+ * Given a font name this function returns the part used in the first
+ * scroll list.
+ */
+ static void
+name_part(char *font, char *buf)
+{
+ char buf2[TEMP_BUF_SIZE];
+ char buf3[TEMP_BUF_SIZE];
+
+ get_part(font, 2, buf2);
+ get_part(font, 1, buf3);
+
+ if (strlen(buf3))
+ sprintf(buf, "%s (%s)", buf2, buf3);
+ else
+ sprintf(buf, "%s", buf2);
+}
+
+/*
+ * Given a font name this function returns the part used in the second scroll list.
+ */
+ static void
+style_part(char *font, char *buf)
+{
+ char buf2[TEMP_BUF_SIZE];
+ char buf3[TEMP_BUF_SIZE];
+
+ get_part(font, 3, buf3);
+ get_part(font, 5, buf2);
+
+ if (!strcmp(buf2, "normal") && !strcmp(buf2, "Normal")
+ && !strcmp(buf2, "NORMAL"))
+ sprintf(buf, "%s %s", buf3, buf2);
+ else
+ strcpy(buf, buf3);
+
+ get_part(font, 6, buf2);
+
+ if (buf2[0] != '\0')
+ sprintf(buf3, "%s %s", buf, buf2);
+ else
+ strcpy(buf3, buf);
+
+ get_part(font, 4, buf2);
+
+ if (!strcmp(buf2, "o") || !strcmp(buf2, "O"))
+ sprintf(buf, "%s oblique", buf3);
+ else if (!strcmp(buf2, "i") || !strcmp(buf2, "I"))
+ sprintf(buf, "%s italic", buf3);
+
+ if (!strcmp(buf, " "))
+ strcpy(buf, "-");
+}
+
+/*
+ * Given a font name this function returns the part used in the third
+ * scroll list.
+ */
+ static void
+size_part(char *font, char *buf, int inPixels)
+{
+ int size;
+ float temp;
+
+ *buf = '\0';
+
+ if (inPixels)
+ {
+ get_part(font, 7, buf);
+ if (strlen(buf) > 0)
+ {
+ size = atoi(buf);
+ sprintf(buf, "%3d", size);
+ }
+ }
+ else
+ {
+ get_part(font, 8, buf);
+ if (strlen(buf) > 0)
+ {
+ size = atoi(buf);
+ temp = (float)size / 10.0;
+ size = temp;
+ if (buf[strlen(buf) - 1] == '0')
+ sprintf(buf, "%3d", size);
+ else
+ sprintf(buf, "%4.1f", temp);
+ }
+ }
+}
+
+/*
+ * Given a font name this function returns the part used in the choice menu.
+ */
+ static void
+encoding_part(char *font, char *buf)
+{
+ char buf1[TEMP_BUF_SIZE];
+ char buf2[TEMP_BUF_SIZE];
+
+ *buf = '\0';
+
+ get_part(font, 13, buf1);
+ get_part(font, 14, buf2);
+
+ if (strlen(buf1) > 0 && strlen(buf2))
+ sprintf(buf, "%s-%s", buf1, buf2);
+ if (!strcmp(buf, " "))
+ strcpy(buf, "-");
+}
+
+/*
+ * Inserts a string into correct sorted position in a list.
+ */
+ static void
+add_to_list(char **buf, char *item, int *count)
+{
+ int i;
+ int j;
+
+ if (*count == MAX_ENTRIES_IN_LIST)
+ return;
+
+ /* avoid duplication */
+ for (i = 0; i < *count; ++i)
+ {
+ if (!strcmp(buf[i], item))
+ return;
+ }
+
+ /* find order place, but make sure that wild card comes first */
+ if (!strcmp(item, wild))
+ i = 0;
+ else
+ for (i = 0; i < *count; ++i)
+ if (strcmp(buf[i], item) > 0 && strcmp(buf[i], wild))
+ break;
+
+ /* now insert the item */
+ for (j = *count; j > i; --j)
+ buf[j] = buf[j-1];
+ buf[i] = XtNewString(item);
+
+ ++(*count);
+}
+
+/*
+ * True if the font matches some field.
+ */
+ static Boolean
+match(SharedFontSelData *data, enum ListSpecifier l, int i)
+{
+ char buf[TEMP_BUF_SIZE];
+
+ /* An empty selection or a wild card matches anything.
+ */
+ if (!data->sel[l] || !strcmp(data->sel[l], wild))
+ return True;
+
+ /* chunk out the desired part... */
+ switch (l)
+ {
+ case ENCODING:
+ encoding_part(fn(data, i), buf);
+ break;
+
+ case NAME:
+ name_part(fn(data, i), buf);
+ break;
+
+ case STYLE:
+ style_part(fn(data, i), buf);
+ break;
+
+ case SIZE:
+ size_part(fn(data, i), buf, data->in_pixels);
+ break;
+ default:
+ ;
+ }
+
+ /* ...and chew it now */
+
+ return !strcmp(buf, data->sel[l]);
+}
+
+ static Boolean
+proportional(char *font)
+{
+ char buf[TEMP_BUF_SIZE];
+
+ get_part(font, 11, buf);
+
+ return !strcmp(buf, "p") || !strcmp(buf, "P");
+}
+
+
+static void encoding_callback(Widget w, SharedFontSelData *data,
+ XtPointer dummy);
+
+/*
+ * Parse through the fontlist data and set up the three scroll lists. The fix
+ * parameter can be used to exclude a list from any changes. This is used for
+ * updates after selections caused by the users actions.
+ */
+ static void
+fill_lists(enum ListSpecifier fix, SharedFontSelData *data)
+{
+ char *list[NONE][MAX_ENTRIES_IN_LIST];
+ int count[NONE];
+ char buf[TEMP_BUF_SIZE];
+ XmString items[MAX_ENTRIES_IN_LIST];
+ int i;
+ int index;
+
+ for (index = (int)ENCODING; index < (int)NONE; ++index)
+ count[index] = 0;
+
+ /* First we insert the wild char into every single list. */
+ if (fix != ENCODING)
+ add_to_list(list[ENCODING], wild, &count[ENCODING]);
+ if (fix != NAME)
+ add_to_list(list[NAME], wild, &count[NAME]);
+ if (fix != STYLE)
+ add_to_list(list[STYLE], wild, &count[STYLE]);
+ if (fix != SIZE)
+ add_to_list(list[SIZE], wild, &count[SIZE]);
+
+ for (i = 0; i < data->num && i < MAX_ENTRIES_IN_LIST; i++)
+ {
+ if (proportional(fn(data, i)))
+ continue;
+
+ if (fix != ENCODING
+ && match(data, NAME, i)
+ && match(data, STYLE, i)
+ && match(data, SIZE, i))
+ {
+ encoding_part(fn(data, i), buf);
+ add_to_list(list[ENCODING], buf, &count[ENCODING]);
+ }
+
+ if (fix != NAME
+ && match(data, ENCODING, i)
+ && match(data, STYLE, i)
+ && match(data, SIZE, i))
+ {
+ name_part(fn(data, i), buf);
+ add_to_list(list[NAME], buf, &count[NAME]);
+ }
+
+ if (fix != STYLE
+ && match(data, ENCODING, i)
+ && match(data, NAME, i)
+ && match(data, SIZE, i))
+ {
+ style_part(fn(data, i), buf);
+ add_to_list(list[STYLE], buf, &count[STYLE]);
+ }
+
+ if (fix != SIZE
+ && match(data, ENCODING, i)
+ && match(data, NAME, i)
+ && match(data, STYLE, i))
+ {
+ size_part(fn(data, i), buf, data->in_pixels);
+ add_to_list(list[SIZE], buf, &count[SIZE]);
+ }
+ }
+
+ /*
+ * And now do the preselection in all lists where there was one:
+ */
+
+ if (fix != ENCODING)
+ {
+ Cardinal n_items;
+ WidgetList children;
+ Widget selected_button = 0;
+
+ /* Get and update the current button list. */
+ XtVaGetValues(data->encoding_pulldown,
+ XmNchildren, &children,
+ XmNnumChildren, &n_items,
+ NULL);
+
+ for (i = 0; i < count[ENCODING]; ++i)
+ {
+ Widget button;
+
+ items[i] = XmStringCreateLocalized(list[ENCODING][i]);
+
+ if (i < n_items)
+ {
+ /* recycle old button */
+ XtVaSetValues(children[i],
+ XmNlabelString, items[i],
+ XmNuserData, i,
+ NULL);
+ button = children[i];
+ }
+ else
+ {
+ /* create a new button */
+ button = XtVaCreateManagedWidget("button",
+ xmPushButtonGadgetClass,
+ data->encoding_pulldown,
+ XmNlabelString, items[i],
+ XmNuserData, i,
+ NULL);
+ XtAddCallback(button, XmNactivateCallback,
+ (XtCallbackProc) encoding_callback, (XtPointer) data);
+ XtManageChild(button);
+ }
+
+ if (data->sel[ENCODING])
+ {
+ if (!strcmp(data->sel[ENCODING], list[ENCODING][i]))
+ selected_button = button;
+ }
+ XtFree(list[ENCODING][i]);
+ }
+
+ /* Destroy all the outstandig menu items.
+ */
+ for (i = count[ENCODING]; i < n_items; ++i)
+ {
+ XtUnmanageChild(children[i]);
+ XtDestroyWidget(children[i]);
+ }
+
+ /* Preserve the current selection visually.
+ */
+ if (selected_button)
+ {
+ XtVaSetValues(data->encoding_menu,
+ XmNmenuHistory, selected_button,
+ NULL);
+ }
+
+ for (i = 0; i < count[ENCODING]; ++i)
+ XmStringFree(items[i]);
+ }
+
+ /*
+ * Now loop trough the remaining lists and set them up.
+ */
+ for (index = (int)NAME; index < (int)NONE; ++index)
+ {
+ Widget w;
+
+ if (fix == (enum ListSpecifier)index)
+ continue;
+
+ switch ((enum ListSpecifier)index)
+ {
+ case NAME:
+ w = data->list[NAME];
+ break;
+ case STYLE:
+ w = data->list[STYLE];
+ break;
+ case SIZE:
+ w = data->list[SIZE];
+ break;
+ default:
+ w = (Widget)0; /* for lint */
+ }
+
+ for (i = 0; i < count[index]; ++i)
+ {
+ items[i] = XmStringCreateLocalized(list[index][i]);
+ XtFree(list[index][i]);
+ }
+ XmListDeleteAllItems(w);
+ XmListAddItems(w, items, count[index], 1);
+ if (data->sel[index])
+ {
+ XmStringFree(items[0]);
+ items[0] = XmStringCreateLocalized(data->sel[index]);
+ XmListSelectItem(w, items[0], False);
+ XmListSetBottomItem(w, items[0]);
+ }
+ for (i = 0; i < count[index]; ++i)
+ XmStringFree(items[i]);
+ }
+}
+
+/*ARGSUSED*/
+ static void
+stoggle_callback(Widget w,
+ SharedFontSelData *data,
+ XmToggleButtonCallbackStruct *call_data)
+{
+ int i, do_sel;
+ char newSize[10];
+ XmString str;
+
+ if (call_data->reason != (int)XmCR_VALUE_CHANGED)
+ return;
+
+ do_sel = (data->sel[SIZE] != NULL) && strcmp(data->sel[SIZE], wild);
+
+ for (i = 0; do_sel && (i < data->num); i++)
+ if (match(data, ENCODING, i)
+ && match(data, NAME, i)
+ && match(data, STYLE, i)
+ && match(data, SIZE, i))
+ {
+ size_part(fn(data, i), newSize, !data->in_pixels);
+ break;
+ }
+
+ data->in_pixels = !data->in_pixels;
+
+ if (data->sel[SIZE])
+ XtFree(data->sel[SIZE]);
+ data->sel[SIZE] = NULL;
+ fill_lists(NONE, data);
+
+ if (do_sel)
+ {
+ str = XmStringCreateLocalized(newSize);
+ XmListSelectItem(data->list[SIZE], str, True);
+ XmListSetBottomItem(data->list[SIZE], str);
+ XmStringFree(str);
+ }
+}
+
+/*
+ * Show the currently selected font in the sample text label.
+ */
+ static void
+display_sample(SharedFontSelData *data)
+{
+ Arg args[2];
+ int n;
+ XFontStruct * font;
+ XmFontList font_list;
+ Display * display;
+ XmString str;
+
+ display = XtDisplay(data->dialog);
+ font = XLoadQueryFont(display, data->font_name);
+ font_list = gui_motif_create_fontlist(font);
+
+ n = 0;
+ str = XmStringCreateLocalized("AaBbZzYy 0123456789");
+ XtSetArg(args[n], XmNlabelString, str); n++;
+ XtSetArg(args[n], XmNfontList, font_list); n++;
+
+ XtSetValues(data->sample, args, n);
+ XmStringFree(str);
+
+ if (data->old)
+ {
+ XFreeFont(display, data->old);
+ XmFontListFree(data->old_list);
+ }
+ data->old = font;
+ data->old_list = font_list;
+}
+
+
+ static Boolean
+do_choice(Widget w,
+ SharedFontSelData *data,
+ XmListCallbackStruct *call_data,
+ enum ListSpecifier which)
+{
+ char *sel;
+
+ XmStringGetLtoR(call_data->item, XmSTRING_DEFAULT_CHARSET, &sel);
+
+ if (!data->sel[which])
+ data->sel[which] = XtNewString(sel);
+ else
+ {
+ XtFree(data->sel[which]);
+ if (!strcmp(data->sel[which], sel))
+ {
+ /* unselecting current selection */
+ data->sel[which] = NULL;
+ if (w)
+ XmListDeselectItem(w, call_data->item);
+ }
+ else
+ data->sel[which] = XtNewString(sel);
+ }
+ XtFree(sel);
+
+ fill_lists(which, data);
+
+ /* If there is a font selection, we display it. */
+ if (data->sel[ENCODING]
+ && data->sel[NAME]
+ && data->sel[STYLE]
+ && data->sel[SIZE]
+ && strcmp(data->sel[ENCODING], wild)
+ && strcmp(data->sel[NAME], wild)
+ && strcmp(data->sel[STYLE], wild)
+ && strcmp(data->sel[SIZE], wild))
+ {
+ int i;
+
+ if (data->font_name)
+ XtFree(data->font_name);
+ data->font_name = NULL;
+
+ for (i = 0; i < data->num; i++)
+ {
+ if (match(data, ENCODING, i)
+ && match(data, NAME, i)
+ && match(data, STYLE, i)
+ && match(data, SIZE, i))
+ {
+ data->font_name = XtNewString(fn(data, i));
+ break;
+ }
+ }
+
+ if (data->font_name)
+ {
+ XmTextSetString(data->name, data->font_name);
+ display_sample(data);
+ }
+ else
+ do_dialog(VIM_ERROR,
+ (char_u *)_("Error"),
+ (char_u *)_("Invalid font specification"),
+ (char_u *)_("&Dismiss"), 1, NULL);
+
+ return True;
+ }
+ else
+ {
+ int n;
+ XmString str;
+ Arg args[4];
+ char *msg = _("no specific match");
+
+ n = 0;
+ str = XmStringCreateLocalized(msg);
+ XtSetArg(args[n], XmNlabelString, str); ++n;
+ XtSetValues(data->sample, args, n);
+ apply_fontlist(data->sample);
+ XmTextSetString(data->name, msg);
+ XmStringFree(str);
+
+ return False;
+ }
+}
+
+/*ARGSUSED*/
+ static void
+encoding_callback(Widget w,
+ SharedFontSelData *data,
+ XtPointer dummy)
+{
+ XmString str;
+ XmListCallbackStruct fake_data;
+
+ XtVaGetValues(w, XmNlabelString, &str, NULL);
+
+ if (!str)
+ return;
+
+ fake_data.item = str;
+
+ do_choice(0, data, &fake_data, ENCODING);
+}
+
+ static void
+name_callback(Widget w,
+ SharedFontSelData *data,
+ XmListCallbackStruct *call_data)
+{
+ do_choice(w, data, call_data, NAME);
+}
+
+ static void
+style_callback(Widget w,
+ SharedFontSelData *data,
+ XmListCallbackStruct *call_data)
+{
+ do_choice(w, data, call_data, STYLE);
+}
+
+ static void
+size_callback(Widget w,
+ SharedFontSelData *data,
+ XmListCallbackStruct *call_data)
+{
+ do_choice(w, data, call_data, SIZE);
+}
+
+/*ARGSUSED*/
+ static void
+cancel_callback(Widget w,
+ SharedFontSelData *data,
+ XmListCallbackStruct *call_data)
+{
+ if (data->sel[ENCODING])
+ {
+ XtFree(data->sel[ENCODING]);
+ data->sel[ENCODING] = NULL;
+ }
+ if (data->sel[NAME])
+ {
+ XtFree(data->sel[NAME]);
+ data->sel[NAME] = NULL;
+ }
+ if (data->sel[STYLE])
+ {
+ XtFree(data->sel[STYLE]);
+ data->sel[STYLE] = NULL;
+ }
+ if (data->sel[SIZE])
+ {
+ XtFree(data->sel[SIZE]);
+ data->sel[SIZE] = NULL;
+ }
+
+ if (data->font_name)
+ XtFree(data->font_name);
+ data->font_name = NULL;
+
+ data->num = 0;
+ XFreeFontNames(data->names);
+ data->names = NULL;
+ data->exit = True;
+}
+
+/*ARGSUSED*/
+ static void
+ok_callback(Widget w,
+ SharedFontSelData *data,
+ XmPushButtonCallbackStruct *call_data)
+{
+ char *pattern;
+ char **name;
+ int i;
+
+ pattern = XmTextGetString(data->name);
+ name = XListFonts(XtDisplay(data->dialog), pattern, 1, &i);
+ XtFree(pattern);
+
+ if (i != 1)
+ {
+ do_dialog(VIM_ERROR,
+ (char_u *)_("Error"),
+ (char_u *)_("Invalid font specification"),
+ (char_u *)_("&Dismiss"), 1, NULL);
+ XFreeFontNames(name);
+ }
+ else
+ {
+ if (data->font_name)
+ XtFree(data->font_name);
+ data->font_name = XtNewString(name[0]);
+
+ if (data->sel[ENCODING])
+ {
+ XtFree(data->sel[ENCODING]);
+ data->sel[ENCODING] = NULL;
+ }
+ if (data->sel[NAME])
+ {
+ XtFree(data->sel[NAME]);
+ data->sel[NAME] = NULL;
+ }
+ if (data->sel[STYLE])
+ {
+ XtFree(data->sel[STYLE]);
+ data->sel[STYLE] = NULL;
+ }
+ if (data->sel[SIZE])
+ {
+ XtFree(data->sel[SIZE]);
+ data->sel[SIZE] = NULL;
+ }
+
+ XFreeFontNames(name);
+
+ data->num = 0;
+ XFreeFontNames(data->names);
+ data->names = NULL;
+ data->exit = True;
+ }
+}
+
+/*
+ * Returns pointer to an ASCII character string that contains the name of the
+ * selected font (in X format for naming fonts); it is the users responsibility
+ * to free the space allocated to this string.
+ */
+ char_u *
+gui_xm_select_font(char_u *current)
+{
+ static SharedFontSelData _data;
+
+ Widget parent;
+ Widget form;
+ Widget separator;
+ Widget sub_form;
+ Widget size_toggle;
+ Widget name;
+ Widget disp_frame;
+ Widget frame;
+ Arg args[64];
+ int n;
+ XmString str;
+ char big_font[MAX_FONT_NAME_LEN];
+ SharedFontSelData *data;
+
+ data = &_data;
+
+ parent = vimShell;
+ data->names = XListFonts(XtDisplay(parent), "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
+ MAX_FONTS, &data->num);
+
+ /*
+ * Find the name of the biggest font less than the given limit
+ * MAX_DISPLAY_SIZE used to set up the initial height of the display
+ * widget.
+ */
+
+ {
+ int i;
+ int max;
+ int index = 0;
+ int size;
+ char str[128];
+
+ for (i = 0, max = 0; i < data->num; i++)
+ {
+ get_part(fn(data, i), 7, str);
+ size = atoi(str);
+ if ((size > max) && (size < MAX_DISPLAY_SIZE))
+ {
+ index = i;
+ max = size;
+ }
+ }
+ strcpy(big_font, fn(data, index));
+ }
+ data->old = XLoadQueryFont(XtDisplay(parent), big_font);
+ data->old_list = gui_motif_create_fontlist(data->old);
+
+ /* Set the title of the Dialog window. */
+ data->dialog = XmCreateDialogShell(parent, "fontSelector", NULL, 0);
+ str = XmStringCreateLocalized(_("Vim - Font Selector"));
+
+ /* Create form popup dialog widget. */
+ form = XtVaCreateWidget("form",
+ xmFormWidgetClass, data->dialog,
+ XmNdialogTitle, str,
+ XmNautoUnmanage, False,
+ XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
+ NULL);
+ XmStringFree(str);
+
+ sub_form = XtVaCreateManagedWidget("subForm",
+ xmFormWidgetClass, form,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 4,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNrightOffset, 4,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 4,
+ XmNorientation, XmVERTICAL,
+ NULL);
+
+ data->ok = XtVaCreateManagedWidget(_("OK"),
+ xmPushButtonGadgetClass, sub_form,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 4,
+ NULL);
+ apply_fontlist(data->ok);
+
+ data->cancel = XtVaCreateManagedWidget(_("Cancel"),
+ xmPushButtonGadgetClass, sub_form,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_WIDGET,
+ XmNtopWidget, data->ok,
+ XmNtopOffset, 4,
+ XmNshowAsDefault, True,
+ NULL);
+ apply_fontlist(data->cancel);
+
+ /* Create the separator for beauty. */
+ n = 0;
+ XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
+ XtSetArg(args[n], XmNrightWidget, sub_form); n++;
+ XtSetArg(args[n], XmNrightOffset, 4); n++;
+ separator = XmCreateSeparatorGadget(form, "separator", args, n);
+ XtManageChild(separator);
+
+ /* Create font name text widget and the corresponding label. */
+ data->name = XtVaCreateManagedWidget("fontName",
+ xmTextWidgetClass, form,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNbottomOffset, 4,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNrightAttachment, XmATTACH_WIDGET,
+ XmNrightWidget, separator,
+ XmNrightOffset, 4,
+ XmNeditable, False,
+ XmNeditMode, XmSINGLE_LINE_EDIT,
+ XmNmaxLength, MAX_FONT_NAME_LEN,
+ XmNcolumns, 60,
+ NULL);
+
+ str = XmStringCreateLocalized(_("Name:"));
+ name = XtVaCreateManagedWidget("fontNameLabel",
+ xmLabelGadgetClass, form,
+ XmNlabelString, str,
+ XmNuserData, data->name,
+ XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
+ XmNleftWidget, data->name,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, data->name,
+ XmNtopOffset, 1,
+ NULL);
+ XmStringFree(str);
+ apply_fontlist(name);
+
+ /* create sample display label widget */
+ disp_frame = XtVaCreateManagedWidget("sampleFrame",
+ xmFrameWidgetClass, form,
+ XmNshadowType, XmSHADOW_ETCHED_IN,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, name,
+ XmNrightAttachment, XmATTACH_WIDGET,
+ XmNrightWidget, separator,
+ XmNrightOffset, 4,
+ XmNalignment, XmALIGNMENT_BEGINNING,
+ NULL);
+
+ data->sample = XtVaCreateManagedWidget("sampleLabel",
+ xmLabelWidgetClass, disp_frame,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_FORM,
+ XmNalignment, XmALIGNMENT_BEGINNING,
+ XmNrecomputeSize, False,
+ XmNfontList, data->old_list,
+ NULL);
+
+ /* create toggle button */
+ str = XmStringCreateLocalized(_("Show size in Points"));
+ size_toggle = XtVaCreateManagedWidget("sizeToggle",
+ xmToggleButtonGadgetClass, form,
+ XmNlabelString, str,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, disp_frame,
+ XmNbottomOffset, 4,
+ NULL);
+ XmStringFree(str);
+ apply_fontlist(size_toggle);
+ XtManageChild(size_toggle);
+
+ /* Encoding pulldown menu.
+ */
+
+ data->encoding_pulldown = XmCreatePulldownMenu(form,
+ "encodingPulldown", NULL, 0);
+ str = XmStringCreateLocalized(_("Encoding:"));
+ n = 0;
+ XtSetArg(args[n], XmNsubMenuId, data->encoding_pulldown); ++n;
+ XtSetArg(args[n], XmNlabelString, str); ++n;
+ XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); ++n;
+ XtSetArg(args[n], XmNleftOffset, 4); ++n;
+ XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); ++n;
+ XtSetArg(args[n], XmNbottomWidget, size_toggle); ++n;
+ XtSetArg(args[n], XmNbottomOffset, 4); ++n;
+ XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); ++n;
+ XtSetArg(args[n], XmNrightWidget, separator); ++n;
+ XtSetArg(args[n], XmNrightOffset, 4); ++n;
+ data->encoding_menu = XmCreateOptionMenu(form, "encodingMenu", args, n);
+ XmStringFree(str);
+ XmAddTabGroup(data->encoding_menu);
+
+ /*
+ * Create scroll list widgets in a separate subform used to manage the
+ * different sizes of the lists.
+ */
+
+ sub_form = XtVaCreateManagedWidget("subForm",
+ xmFormWidgetClass, form,
+ XmNbottomAttachment, XmATTACH_WIDGET,
+ XmNbottomWidget, data->encoding_menu,
+ XmNbottomOffset, 4,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNleftOffset, 4,
+ XmNrightAttachment, XmATTACH_WIDGET,
+ XmNrightWidget, separator,
+ XmNrightOffset, 4,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNtopOffset, 2,
+ XmNorientation, XmVERTICAL,
+ NULL);
+
+ /* font list */
+ frame = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, sub_form,
+ XmNshadowThickness, 0,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_FORM,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 50,
+ NULL);
+
+ str = XmStringCreateLocalized(_("Font:"));
+ name = XtVaCreateManagedWidget("nameListLabel", xmLabelGadgetClass, frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNchildVerticalAlignment, XmALIGNMENT_CENTER,
+ XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
+ XmNlabelString, str,
+ NULL);
+ XmStringFree(str);
+ apply_fontlist(name);
+
+ n = 0;
+ XtSetArg(args[n], XmNvisibleItemCount, 8); ++n;
+ XtSetArg(args[n], XmNresizable, True); ++n;
+ XtSetArg(args[n], XmNlistSizePolicy, XmCONSTANT); ++n;
+ XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); ++n;
+#ifdef LESSTIF_VERSION
+ XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); ++n;
+#endif
+ data->list[NAME] = XmCreateScrolledList(frame, "fontList", args, n);
+ XtVaSetValues(name, XmNuserData, data->list[NAME], NULL);
+
+ /* style list */
+ frame = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, sub_form,
+ XmNshadowThickness, 0,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 50,
+ XmNleftOffset, 4,
+ XmNrightAttachment, XmATTACH_POSITION,
+ XmNrightPosition, 80,
+ NULL);
+
+ str = XmStringCreateLocalized(_("Style:"));
+ name = XtVaCreateManagedWidget("styleListLabel", xmLabelWidgetClass, frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNchildVerticalAlignment, XmALIGNMENT_CENTER,
+ XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
+ XmNlabelString, str,
+ NULL);
+ XmStringFree(str);
+ apply_fontlist(name);
+
+ n = 0;
+ XtSetArg(args[n], XmNvisibleItemCount, 8); ++n;
+ XtSetArg(args[n], XmNresizable, True); ++n;
+ XtSetArg(args[n], XmNlistSizePolicy, XmCONSTANT); ++n;
+ XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); ++n;
+#ifdef LESSTIF_VERSION
+ XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); ++n;
+#endif
+ data->list[STYLE] = XmCreateScrolledList(frame, "styleList", args, n);
+ XtVaSetValues(name, XmNuserData, data->list[STYLE], NULL);
+
+ /* size list */
+ frame = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, sub_form,
+ XmNshadowThickness, 0,
+ XmNtopAttachment, XmATTACH_FORM,
+ XmNbottomAttachment, XmATTACH_FORM,
+ XmNleftAttachment, XmATTACH_POSITION,
+ XmNleftPosition, 80,
+ XmNleftOffset, 4,
+ XmNrightAttachment, XmATTACH_FORM,
+ NULL);
+
+ str = XmStringCreateLocalized(_("Size:"));
+ name = XtVaCreateManagedWidget("sizeListLabel", xmLabelGadgetClass, frame,
+ XmNchildType, XmFRAME_TITLE_CHILD,
+ XmNchildVerticalAlignment, XmALIGNMENT_CENTER,
+ XmNchildHorizontalAlignment, XmALIGNMENT_BEGINNING,
+ XmNlabelString, str,
+ NULL);
+ XmStringFree(str);
+ apply_fontlist(name);
+
+ n = 0;
+ XtSetArg(args[n], XmNvisibleItemCount, 8); ++n;
+ XtSetArg(args[n], XmNresizable, True); ++n;
+ XtSetArg(args[n], XmNlistSizePolicy, XmCONSTANT); ++n;
+ XtSetArg(args[n], XmNvisualPolicy, XmVARIABLE); ++n;
+#ifdef LESSTIF_VERSION
+ XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); ++n;
+#endif
+ data->list[SIZE] = XmCreateScrolledList(frame, "sizeList", args, n);
+ XtVaSetValues(name, XmNuserData, data->list[SIZE], NULL);
+
+ /* update form widgets cancel button */
+ XtVaSetValues(form, XmNcancelButton, data->cancel, NULL);
+
+ XtAddCallback(size_toggle, XmNvalueChangedCallback,
+ (XtCallbackProc)stoggle_callback, (XtPointer)data);
+ XtAddCallback(data->list[NAME], XmNbrowseSelectionCallback,
+ (XtCallbackProc)name_callback, (XtPointer)data);
+ XtAddCallback(data->list[STYLE], XmNbrowseSelectionCallback,
+ (XtCallbackProc)style_callback, (XtPointer)data);
+ XtAddCallback(data->list[SIZE], XmNbrowseSelectionCallback,
+ (XtCallbackProc)size_callback, (XtPointer)data);
+ XtAddCallback(data->ok, XmNactivateCallback,
+ (XtCallbackProc)ok_callback, (XtPointer)data);
+ XtAddCallback(data->cancel, XmNactivateCallback,
+ (XtCallbackProc)cancel_callback, (XtPointer)data);
+
+ XmProcessTraversal(data->list[NAME], XmTRAVERSE_CURRENT);
+
+ /* setup tabgroups */
+
+ XmAddTabGroup(data->list[NAME]);
+ XmAddTabGroup(data->list[STYLE]);
+ XmAddTabGroup(data->list[SIZE]);
+ XmAddTabGroup(size_toggle);
+ XmAddTabGroup(data->name);
+ XmAddTabGroup(data->ok);
+ XmAddTabGroup(data->cancel);
+
+ add_cancel_action(data->dialog, (XtCallbackProc)cancel_callback, data);
+
+ /* Preset selection data. */
+
+ data->exit = False;
+ data->in_pixels= True;
+ data->sel[ENCODING] = NULL;
+ data->sel[NAME] = NULL;
+ data->sel[STYLE] = NULL;
+ data->sel[SIZE] = NULL;
+ data->font_name = NULL;
+
+ /* set up current font parameters */
+ if (current && current[0] != '\0')
+ {
+ int i;
+ char **names;
+
+ names = XListFonts(XtDisplay(form), (char *) current, 1, &i);
+
+ if (i != 0)
+ {
+ char name[TEMP_BUF_SIZE];
+ char style[TEMP_BUF_SIZE];
+ char size[TEMP_BUF_SIZE];
+ char encoding[TEMP_BUF_SIZE];
+ char *found;
+
+ found = names[0];
+
+ name_part(found, name);
+ style_part(found, style);
+ size_part(found, size, data->in_pixels);
+ encoding_part(found, encoding);
+
+ if (strlen(name) > 0
+ && strlen(style) > 0
+ && strlen(size) > 0
+ && strlen(encoding) > 0)
+ {
+ data->sel[NAME] = XtNewString(name);
+ data->sel[STYLE] = XtNewString(style);
+ data->sel[SIZE] = XtNewString(size);
+ data->sel[ENCODING] = XtNewString(encoding);
+ data->font_name = XtNewString(names[0]);
+ display_sample(data);
+ XmTextSetString(data->name, data->font_name);
+ }
+ else
+ {
+ /* We can't preset a symbolic name, which isn't a full font
+ * description. Therefore we just behave the same way as if the
+ * user didn't have selected anything thus far.
+ *
+ * Unfortunately there is no known way to expand an abbreviated
+ * font name.
+ */
+
+ data->font_name = NULL;
+ }
+ }
+ XFreeFontNames(names);
+ }
+
+ fill_lists(NONE, data);
+
+ /* Unfortunately LessTif doesn't align the list widget's properly. I don't
+ * have currently any idea how to fix this problem.
+ */
+ XtManageChild(data->list[NAME]);
+ XtManageChild(data->list[STYLE]);
+ XtManageChild(data->list[SIZE]);
+ XtManageChild(data->encoding_menu);
+ manage_centered(form);
+
+ /* modal event loop */
+ while (!data->exit)
+ XtAppProcessEvent(XtWidgetToApplicationContext(data->dialog),
+ (XtInputMask)XtIMAll);
+
+ XtDestroyWidget(data->dialog);
+
+ if (data->old)
+ {
+ XFreeFont(XtDisplay(data->dialog), data->old);
+ XmFontListFree(data->old_list);
+ }
+
+ gui_motif_synch_fonts();
+
+ return (char_u *) data->font_name;
+}
diff --git a/src/misc2.c b/src/misc2.c
index 30e1a1f01..db091b5bc 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -107,9 +107,9 @@ coladvance(wcol)
if (wcol == MAXCOL || rc == FAIL)
curwin->w_valid &= ~VALID_VIRTCOL;
- else
+ else if (*ml_get_cursor() != TAB)
{
- /* Virtcol is valid */
+ /* Virtcol is valid when not on a TAB */
curwin->w_valid |= VALID_VIRTCOL;
curwin->w_virtcol = wcol;
}
diff --git a/src/proto.h b/src/proto.h
index 4c52d4bb8..77ea826c7 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -194,6 +194,7 @@ extern char_u *vimpty_getenv __ARGS((const char_u *string)); /* from pty.c */
# endif
# ifdef FEAT_GUI_MOTIF
# include "gui_motif.pro"
+# include "gui_xmdlg.pro"
# endif
# ifdef FEAT_GUI_ATHENA
# include "gui_athena.pro"
diff --git a/src/proto/gui_xmdlg.pro b/src/proto/gui_xmdlg.pro
new file mode 100644
index 000000000..4f88c2ff1
--- /dev/null
+++ b/src/proto/gui_xmdlg.pro
@@ -0,0 +1,3 @@
+/* gui_xmdlg.c */
+char_u *gui_xm_select_font __ARGS((char_u *current));
+/* vim: set ft=c : */
diff --git a/src/workshop.c b/src/workshop.c
index 10f4ea796..a80575f24 100644
--- a/src/workshop.c
+++ b/src/workshop.c
@@ -15,10 +15,10 @@
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
+#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
-#include <sys/types.h>
#include <sys/socket.h>
#ifdef HAVE_LIBGEN_H
# include <libgen.h>