changeset 8140:563c923b1584 v7.4.1364

commit https://github.com/vim/vim/commit/cf7164a088664961e7d70dd100c5874dc5ceb293 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Feb 20 13:55:06 2016 +0100 patch 7.4.1364 Problem: The Win 16 code is not maintained and unused. Solution: Remove the Win 16 support.
author Christian Brabandt <cb@256bit.org>
date Sat, 20 Feb 2016 14:00:06 +0100
parents 2b0d471e04f7
children 894b78ff8a1d
files Filelist src/Make_cyg_ming.mak src/Make_mvc.mak src/Make_w16.mak src/Makefile src/eval.c src/feature.h src/gui.c src/gui_w16.c src/gui_w32.c src/gui_w48.c src/guiw16rc.h src/misc2.c src/option.c src/os_msdos.c src/os_mswin.c src/os_win16.c src/os_win16.h src/proto.h src/proto/gui_w16.pro src/version.c src/vim.h src/vim16.def src/vim16.rc src/winclip.c
diffstat 25 files changed, 4124 insertions(+), 6869 deletions(-) [+]
line wrap: on
line diff
--- a/Filelist
+++ b/Filelist
@@ -300,7 +300,6 @@ SRC_DOS =	\
 		src/Make_dvc.mak \
 		src/Make_ming.mak \
 		src/Make_mvc.mak \
-		src/Make_w16.mak \
 		src/bigvim.bat \
 		src/bigvim64.bat \
 		src/msvcsetup.bat \
@@ -314,10 +313,7 @@ SRC_DOS =	\
 		src/glbl_ime.h \
 		src/gui_dwrite.cpp \
 		src/gui_dwrite.h \
-		src/gui_w16.c \
 		src/gui_w32.c \
-		src/gui_w48.c \
-		src/guiw16rc.h \
 		src/gui_w32_rc.h \
 		src/if_ole.cpp \
 		src/if_ole.h \
@@ -329,16 +325,12 @@ SRC_DOS =	\
 		src/os_msdos.h \
 		src/os_w32dll.c \
 		src/os_w32exe.c \
-		src/os_win16.c \
 		src/os_win32.c \
 		src/os_mswin.c \
-		src/os_win16.h \
 		src/os_win32.h \
-		src/proto/gui_w16.pro \
 		src/proto/gui_w32.pro \
 		src/proto/if_ole.pro \
 		src/proto/os_msdos.pro \
-		src/proto/os_win16.pro \
 		src/proto/os_win32.pro \
 		src/proto/os_mswin.pro \
 		src/testdir/Make_dos.mak \
@@ -349,8 +341,6 @@ SRC_DOS =	\
 		src/vim.rc \
 		src/vimio.h \
 		src/gvim.exe.mnf \
-		src/vim16.def \
-		src/vim16.rc \
 		src/vimrun.c \
 		src/vimtbar.h \
 		src/xpm_w32.c \
@@ -390,7 +380,6 @@ SRC_DOS_BIN =	\
 		src/VisVim/Res/*.bmp \
 		src/tearoff.bmp \
 		src/tools.bmp \
-		src/tools16.bmp \
 		src/vim*.ico \
 		src/vim.tlb \
 		src/vimtbar.lib \
--- a/src/Make_cyg_ming.mak
+++ b/src/Make_cyg_ming.mak
@@ -860,7 +860,7 @@ INCL = vim.h feature.h os_win32.h os_dos
 $(OUTDIR)/ex_eval.o:	ex_eval.c $(INCL) ex_cmds.h
 	$(CC) -c $(CFLAGS) ex_eval.c -o $(OUTDIR)/ex_eval.o
 
-$(OUTDIR)/gui_w32.o:	gui_w32.c gui_w48.c $(INCL)
+$(OUTDIR)/gui_w32.o:	gui_w32.c $(INCL)
 	$(CC) -c $(CFLAGS) gui_w32.c -o $(OUTDIR)/gui_w32.o
 
 $(OUTDIR)/gui_dwrite.o:	gui_dwrite.cpp $(INCL) gui_dwrite.h
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -1175,7 +1175,7 @@ testclean:
 
 $(OUTDIR)/gui_beval.obj:	$(OUTDIR) gui_beval.c $(INCL) $(GUI_INCL)
 
-$(OUTDIR)/gui_w32.obj:	$(OUTDIR) gui_w32.c gui_w48.c $(INCL) $(GUI_INCL)
+$(OUTDIR)/gui_w32.obj:	$(OUTDIR) gui_w32.c $(INCL) $(GUI_INCL)
 
 $(OUTDIR)/gui_dwrite.obj:	$(OUTDIR) gui_dwrite.cpp $(INCL) $(GUI_INCL)
 
deleted file mode 100644
--- a/src/Make_w16.mak
+++ /dev/null
@@ -1,204 +0,0 @@
-#
-# Borland C++ 5.0[12] makefile for vim, 16-bit windows gui version
-# By Vince Negri
-#
-# NOTE: THIS IS OLD AND PROBABLY NO LONGER WORKS.
-#
-# *************************************************************
-# * WARNING!
-# * This was originally produced by the IDE, but has since been
-# * modified to make it work properly. Adjust with care!
-# * In particular, leave LinkerLocalOptsAtW16_gvim16dexe alone
-# * unless you are a guru.
-# *************************************************************
-#
-# Look for BOR below and either pass a different value or
-# adjust the path as required. For example
-#   make -fMake_w16.mak -DBOR=C:\PF\Borland\BC5.01 -B BccW16.cfg
-#   make -fMake_w16.mak
-# Note: $(BOR) is effectively ignored unless BccW16.cfg is rebuilt.
-#
-# Does not compile with Borland C++ 4.51 Walter Briscoe 2003-02-24
-# "out of memory" from compiler if gvim16 wildly wrong. WFB 2003-03-04
-#
-# vim16.def must be a DOS-formatted file. (\r\n line endings.)
-# It is a UNIX-formatted file (\n line endings) in vim-*-extra.tar.gz
-
-.AUTODEPEND
-
-#
-# Borland C++ tools
-#
-IMPLIB  = Implib
-BCC     = Bcc +BccW16.cfg
-TLINK   = TLink
-TLIB    = TLib
-BRC     = Brc
-TASM    = Tasm
-#
-# IDE macros
-#
-
-#
-# Options
-#
-!ifndef BOR
-BOR = D:\BC5
-!endif
-
-# !ifndef INTDIR is lethal considering CLEAN below. WFB 2003-03-13
-INTDIR=w16
-
-#  /Twe Make the target a Windows .EXE with explicit functions exportable +
-#  /x   Map file off
-#  /l   Include source line numbers in object map files`
-#  /c   case sensitive link
-#  /C   Case-sensitive exports and imports (16-bit only)
-#  /k   Produce "No Stack" warning.
-#  /Oa  Minimise segment alignment
-#  /Oc  Minimise Chain fixes
-#  /Oi  Minimise Iterated data
-#  /Or  Minimise resource alignment
-#  /P   -P=x  Code pack size
-#  /V   Windows version for application
-#  /L   Folder to search for library files
-LinkerLocalOptsAtW16_gvim16dexe =/Twe/x/l/c/C/k/Or/Oc/Oa/Oi/P=65535/V3.10
-
-CompInheritOptsAt_gvim16dexe = \
-   -I$(BOR)\INCLUDE;PROTO;. \
-   -DFEAT_GUI;FEAT_GUI_MSWIN;FEAT_GUI_W16;MSWIN;WIN16;MSWIN16_FASTTEXT \
-   -DFEAT_TOOLBAR;WIN16_3DLOOK
-
-#
-# Dependency List
-#
-Dep_Gvim16 = \
-   gvim16.exe
-
-ObjFiles = \
-   $(INTDIR)\buffer.obj\
-   $(INTDIR)\charset.obj\
-   $(INTDIR)\diff.obj\
-   $(INTDIR)\digraph.obj\
-   $(INTDIR)\edit.obj\
-   $(INTDIR)\eval.obj\
-   $(INTDIR)\ex_cmds.obj\
-   $(INTDIR)\ex_cmds2.obj\
-   $(INTDIR)\ex_docmd.obj\
-   $(INTDIR)\ex_eval.obj\
-   $(INTDIR)\ex_getln.obj\
-   $(INTDIR)\fileio.obj\
-   $(INTDIR)\fold.obj\
-   $(INTDIR)\getchar.obj\
-   $(INTDIR)\hardcopy.obj\
-   $(INTDIR)\hashtab.obj\
-   $(INTDIR)\gui.obj\
-   $(INTDIR)\gui_w16.obj\
-   $(INTDIR)\main.obj\
-   $(INTDIR)\mark.obj\
-   $(INTDIR)\mbyte.obj\
-   $(INTDIR)\memfile.obj\
-   $(INTDIR)\memline.obj\
-   $(INTDIR)\menu.obj\
-   $(INTDIR)\message.obj\
-   $(INTDIR)\misc1.obj\
-   $(INTDIR)\misc2.obj\
-   $(INTDIR)\move.obj\
-   $(INTDIR)\normal.obj\
-   $(INTDIR)\ops.obj\
-   $(INTDIR)\option.obj\
-   $(INTDIR)\os_win16.obj\
-   $(INTDIR)\os_msdos.obj\
-   $(INTDIR)\os_mswin.obj\
-   $(INTDIR)\winclip.obj\
-   $(INTDIR)\popupmnu.obj\
-   $(INTDIR)\quickfix.obj\
-   $(INTDIR)\regexp.obj\
-   $(INTDIR)\screen.obj\
-   $(INTDIR)\search.obj\
-   $(INTDIR)\spell.obj\
-   $(INTDIR)\syntax.obj\
-   $(INTDIR)\tag.obj\
-   $(INTDIR)\term.obj\
-   $(INTDIR)\ui.obj\
-   $(INTDIR)\undo.obj\
-   $(INTDIR)\version.obj\
-   $(INTDIR)\window.obj
-
-Dep_gvim16dexe = \
-   vimtbar.lib\
-   vim16.def\
-   $(INTDIR)\vim16.res\
-   $(ObjFiles)
-
-# Without the following, the implicit rule in BUILTINS.MAK is picked up
-# for a rule for .c.obj rather than the local implicit rule
-.SUFFIXES
-.SUFFIXES .c .obj
-.path.c = .
-
-# -P-	Force C++ compilation off
-# -c	Compilation only
-# -n    Place .OBJ files
-{.}.c{$(INTDIR)}.obj:
-  $(BCC) -P- -c -n$(INTDIR)\ {$< }
-
-Gvim16 : BccW16.cfg $(Dep_Gvim16)
-  echo MakeNode
-
-gvim16.exe : $(Dep_gvim16dexe)
-  $(TLINK)   $(LinkerLocalOptsAtW16_gvim16dexe) @&&|
-c0wl.obj $(ObjFiles)
-|,$*,,vimtbar ctl3dv2 import cwl, vim16.def,$(INTDIR)\vim16.res
-
-# Force objects to be built if $(BOR) changes
-$(ObjFiles) : Make_w16.mak BccW16.cfg
-
-$(INTDIR)\vim16.res : vim16.rc
-  $(BRC) -R @&&|
-  $(CompInheritOptsAt_gvim16dexe) -fo$*.res $?
-|
-
-
-# Compiler configuration file
-# There is no rule for $(INTDIR) as make always says it does not exist
-BccW16.cfg :
-	-@if not exist $(INTDIR)\$(NULL) mkdir $(INTDIR)
-	Copy &&|
--3		; Generate 80386 protected-mode compatible instructions
--a		; Byte alignment
--dc		; Move string literals from data segment to code segment
--ff		; Fast floating point
--H		; Generate and use precompiled headers
--H=$(INTDIR)\gvim16.csm	; gvim16.csm is the precompiled header filename
--k-		; No standard stack frame
--ml		; Large memory model
--OW		; Suppress the inc bp/dec bp on windows far functions
--O1		; Generate smallest possible code
--O2		; Generate fastest possible code (overrides prior -O1 control)
--pr		; Fastcall calling convention passing parameters in registers
--R-		; Exclude browser information in generated .OBJ files
--v-		; Turn off source debugging
--vi		; Turn inline function expansion on
--WE		; Only __far _export functions are exported
--w		; Display warnings
--w-par		; Suppress: Parameter 'parameter' is never used
--w-pch		; Cannot create pre-compiled header: initialized data in header
--w-sig		; identifier' declared but never used
--w-ucp		; Mixing pointers to different 'char' types
--wuse		; 'identifier' declared but never used
- $(CompInheritOptsAt_gvim16dexe)
-| $@
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-DEL_TREE = rmdir /s /q
-!ELSE
-NULL=nul
-DEL_TREE = deltree /y
-!ENDIF
-
-CLEAN:
-	-@if exist $(INTDIR)\$(NULL) $(DEL_TREE) $(INTDIR)
-	-@if exist BccW16.cfg erase BccW16.cfg
-	-@if exist gvim16.exe erase gvim16.exe
--- a/src/Makefile
+++ b/src/Makefile
@@ -1336,7 +1336,7 @@ CARBONGUI_TESTARG = VIMPROG=../$(APPDIR)
 
 # All GUI files
 ALL_GUI_SRC  = gui.c gui_gtk.c gui_gtk_f.c gui_motif.c gui_xmdlg.c gui_xmebw.c gui_athena.c gui_gtk_x11.c gui_x11.c gui_at_sb.c gui_at_fs.c pty.c
-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_photon.pro
+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_w32.pro gui_photon.pro
 
 # }}}
 
@@ -1715,7 +1715,7 @@ PRO_AUTO = \
 # Resources used for the Mac are in one directory.
 RSRC_DIR = os_mac_rsrc
 
-PRO_MANUAL = os_amiga.pro os_msdos.pro os_win16.pro os_win32.pro \
+PRO_MANUAL = os_amiga.pro os_msdos.pro os_win32.pro \
 	os_mswin.pro winclip.pro os_beos.pro os_vms.pro $(PERL_PRO)
 
 # Default target is making the executable and tools
@@ -1868,20 +1868,16 @@ os_msdos.pro: os_msdos.c
 	$(CPROTO) -DMSDOS -UHAVE_CONFIG_H $< > proto/$@
 	echo "/* vim: set ft=c : */" >> proto/$@
 
-os_win16.pro: os_win16.c
-	$(CPROTO) -DWIN16 -UHAVE_CONFIG_H $< > proto/$@
-	echo "/* vim: set ft=c : */" >> proto/$@
-
 os_win32.pro: os_win32.c
 	$(CPROTO) -DWIN32 -UHAVE_CONFIG_H $< > proto/$@
 	echo "/* vim: set ft=c : */" >> proto/$@
 
 os_mswin.pro: os_mswin.c
-	$(CPROTO) -DWIN16 -DWIN32 -UHAVE_CONFIG_H $< > proto/$@
+	$(CPROTO) -DWIN32 -UHAVE_CONFIG_H $< > proto/$@
 	echo "/* vim: set ft=c : */" >> proto/$@
 
 winclip.pro: winclip.c
-	$(CPROTO) -DWIN16 -DWIN32 -UHAVE_CONFIG_H $< > proto/$@
+	$(CPROTO) -DWIN32 -UHAVE_CONFIG_H $< > proto/$@
 	echo "/* vim: set ft=c : */" >> proto/$@
 
 os_beos.pro: os_beos.c
@@ -2025,6 +2021,7 @@ test_arglist \
 	test_menu \
 	test_perl \
 	test_quickfix \
+	test_reltime \
 	test_searchpos \
 	test_set \
 	test_sort \
--- a/src/eval.c
+++ b/src/eval.c
@@ -13235,9 +13235,6 @@ f_has(typval_T *argvars, typval_T *rettv
 #ifdef VMS
 	"vms",
 #endif
-#ifdef WIN16
-	"win16",
-#endif
 #ifdef WIN32
 	"win32",
 #endif
--- a/src/feature.h
+++ b/src/feature.h
@@ -320,7 +320,7 @@
  *
  * Disabled for EBCDIC as it requires multibyte.
  */
-#if defined(FEAT_BIG) && !defined(WIN16) && VIM_SIZEOF_INT >= 4 && !defined(EBCDIC)
+#if defined(FEAT_BIG) && VIM_SIZEOF_INT >= 4 && !defined(EBCDIC)
 # define FEAT_ARABIC
 #endif
 #ifdef FEAT_ARABIC
@@ -624,8 +624,7 @@
  * Multibyte support doesn't work on z/OS Unix currently.
  */
 #if (defined(FEAT_NORMAL) || defined(FEAT_GUI_GTK) || defined(FEAT_ARABIC)) \
-	&& !defined(FEAT_MBYTE) && !defined(WIN16) \
-	&& VIM_SIZEOF_INT >= 4 && !defined(EBCDIC)
+	&& !defined(FEAT_MBYTE) && VIM_SIZEOF_INT >= 4 && !defined(EBCDIC)
 # define FEAT_MBYTE
 #endif
 
@@ -763,7 +762,7 @@
     && (defined(FEAT_GUI_GTK) \
 	|| (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \
 	|| defined(FEAT_GUI_MAC) \
-	|| (defined(FEAT_GUI_MSWIN) && !defined(WIN16) \
+	|| (defined(FEAT_GUI_MSWIN) \
 	    && (!defined(_MSC_VER) || _MSC_VER > 1020)))
 # define FEAT_GUI_TABLINE
 #endif
--- a/src/gui.c
+++ b/src/gui.c
@@ -2184,7 +2184,7 @@ gui_outstr_nowrap(
     guicolor_T	fg_color;
     guicolor_T	bg_color;
     guicolor_T	sp_color;
-#if !defined(MSWIN16_FASTTEXT) && !defined(FEAT_GUI_GTK)
+#if !defined(FEAT_GUI_GTK)
     GuiFont	font = NOFONT;
 # ifdef FEAT_MBYTE
     GuiFont	wide_font = NOFONT;
@@ -2241,7 +2241,7 @@ gui_outstr_nowrap(
 	highlight_mask = gui.highlight_mask;
     hl_mask_todo = highlight_mask;
 
-#if !defined(MSWIN16_FASTTEXT) && !defined(FEAT_GUI_GTK)
+#if !defined(FEAT_GUI_GTK)
     /* Set the font */
     if (aep != NULL && aep->ae_u.gui.font != NOFONT)
 	font = aep->ae_u.gui.font;
@@ -2358,11 +2358,9 @@ gui_outstr_nowrap(
 	clip_may_clear_selection(gui.row, gui.row);
 
 
-#ifndef MSWIN16_FASTTEXT
     /* If there's no bold font, then fake it */
     if (hl_mask_todo & (HL_BOLD | HL_STANDOUT))
 	draw_flags |= DRAW_BOLD;
-#endif
 
     /*
      * When drawing bold or italic characters the spill-over from the left
@@ -2383,11 +2381,7 @@ gui_outstr_nowrap(
 	draw_flags |= DRAW_UNDERL;
 #else
     /* Do we underline the text? */
-    if ((hl_mask_todo & HL_UNDERLINE)
-# ifndef MSWIN16_FASTTEXT
-	    || (hl_mask_todo & HL_ITALIC)
-# endif
-       )
+    if ((hl_mask_todo & HL_UNDERLINE) || (hl_mask_todo & HL_ITALIC))
 	draw_flags |= DRAW_UNDERL;
 #endif
     /* Do we undercurl the text? */
@@ -3338,7 +3332,7 @@ gui_init_which_components(char_u *oldval
     static int	prev_footer = -1;
     int		using_footer = FALSE;
 #endif
-#if defined(FEAT_MENU) && !defined(WIN16)
+#if defined(FEAT_MENU)
     static int	prev_tearoff = -1;
     int		using_tearoff = FALSE;
 #endif
@@ -3415,7 +3409,7 @@ gui_init_which_components(char_u *oldval
 		break;
 #endif
 	    case GO_TEAROFF:
-#if defined(FEAT_MENU) && !defined(WIN16)
+#if defined(FEAT_MENU)
 		using_tearoff = TRUE;
 #endif
 		break;
@@ -3522,7 +3516,7 @@ gui_init_which_components(char_u *oldval
 		fix_size = TRUE;
 	}
 #endif
-#if defined(FEAT_MENU) && !defined(WIN16) && !(defined(WIN3264) && !defined(FEAT_TEAROFF))
+#if defined(FEAT_MENU) && !(defined(WIN3264) && !defined(FEAT_TEAROFF))
 	if (using_tearoff != prev_tearoff)
 	{
 	    gui_mch_toggle_tearoffs(using_tearoff);
deleted file mode 100644
--- a/src/gui_w16.c
+++ /dev/null
@@ -1,1564 +0,0 @@
-/* vi:set ts=8 sts=4 sw=4:
- *
- * VIM - Vi IMproved		by Bram Moolenaar
- *				GUI 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.
- */
-/*
- * gui_w16.c
- *
- * GUI support for Microsoft Windows 3.1x
- *
- * George V. Reilly <george@reilly.org> wrote the original Win32 GUI.
- * Robert Webb reworked it to use the existing GUI stuff and added menu,
- * scrollbars, etc.
- *
- * Vince Negri then butchered the code to get it compiling for
- * 16-bit windows.
- *
- */
-
-/* Win16 doesn't use the "W" methods. */
-#define pDispatchMessage DispatchMessage
-#define pGetMessage GetMessage
-#define pIsDialogMessage IsDialogMessage
-#define pPeekMessage PeekMessage
-
-/*
- * Include the common stuff for MS-Windows GUI.
- */
-#include "gui_w48.c"
-
-#include "guiw16rc.h"
-
-/* Undocumented Windows Message - not even defined in some SDK headers */
-#define WM_EXITSIZEMOVE			0x0232
-
-
-#ifdef FEAT_TOOLBAR
-# define CMD_TB_BASE (99)
-# include <vimtbar.h>
-#endif
-
-#ifdef PROTO
-# define WINAPI
-#endif
-
-#define HANDLE_WM_DROPFILES(hwnd, wParam, lParam, fn) \
-    ((fn)((hwnd), (HDROP)(wParam)), 0L)
-
-
-/* Local variables: */
-
-#ifdef FEAT_MENU
-static UINT	s_menu_id = 100;
-#endif
-
-
-#define VIM_NAME	"vim"
-#define VIM_CLASS	"Vim"
-
-#define DLG_ALLOC_SIZE 16 * 1024
-
-/*
- * stuff for dialogs, menus, tearoffs etc.
- */
-#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
-static BOOL CALLBACK dialog_callback(HWND, UINT, WPARAM, LPARAM);
-
-static LPWORD
-add_dialog_element(
-	LPWORD p,
-	DWORD lStyle,
-	WORD x,
-	WORD y,
-	WORD w,
-	WORD h,
-	WORD Id,
-	BYTE clss,
-	const char *caption);
-
-static int dialog_default_button = -1;
-#endif
-
-static void get_dialog_font_metrics(void);
-
-#ifdef FEAT_TOOLBAR
-static void initialise_toolbar(void);
-#endif
-
-
-#ifdef FEAT_MENU
-/*
- * Figure out how high the menu bar is at the moment.
- */
-    static int
-gui_mswin_get_menu_height(
-    int	    fix_window)	    /* If TRUE, resize window if menu height changed */
-{
-    static int	old_menu_height = -1;
-
-    int	    num;
-    int	    menu_height;
-
-    if (gui.menu_is_active)
-	num = GetMenuItemCount(s_menuBar);
-    else
-	num = 0;
-
-    if (num == 0)
-	menu_height = 0;
-    else if (gui.starting)
-	menu_height = GetSystemMetrics(SM_CYMENU);
-    else
-    {
-	RECT r1, r2;
-	int frameht = GetSystemMetrics(SM_CYFRAME);
-	int capht = GetSystemMetrics(SM_CYCAPTION);
-
-	/*	get window rect of s_hwnd
-		 * get client rect of s_hwnd
-		 * get cap height
-		 * subtract from window rect, the sum of client height,
-		 * (if not maximized)frame thickness, and caption height.
-	 */
-	GetWindowRect(s_hwnd, &r1);
-	GetClientRect(s_hwnd, &r2);
-	menu_height = r1.bottom - r1.top - (r2.bottom-r2.top +
-			       2 * frameht * (!IsZoomed(s_hwnd)) + capht);
-    }
-
-    if (fix_window && menu_height != old_menu_height)
-    {
-	old_menu_height = menu_height;
-	gui_set_shellsize(FALSE, FALSE, RESIZE_VERT);
-    }
-
-    return menu_height;
-}
-#endif /*FEAT_MENU*/
-
-
-/*
- * Even though we have _DuringSizing() which makes the rubber band a valid
- * size, we need this for when the user maximises the window.
- * TODO: Doesn't seem to adjust the width though for some reason.
- */
-    static BOOL
-_OnWindowPosChanging(
-    HWND hwnd,
-    LPWINDOWPOS lpwpos)
-{
-
-    if (!IsIconic(hwnd) && !(lpwpos->flags & SWP_NOSIZE))
-    {
-	gui_mswin_get_valid_dimensions(lpwpos->cx, lpwpos->cy,
-				     &lpwpos->cx, &lpwpos->cy);
-    }
-    return 0;
-}
-
-
-
-
-
-    static LRESULT CALLBACK
-_WndProc(
-    HWND hwnd,
-    UINT uMsg,
-    WPARAM wParam,
-    LPARAM lParam)
-{
-    /*
-    TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
-	  hwnd, uMsg, wParam, lParam);
-    */
-
-    HandleMouseHide(uMsg, lParam);
-
-    s_uMsg = uMsg;
-    s_wParam = wParam;
-    s_lParam = lParam;
-
-    switch (uMsg)
-    {
-	HANDLE_MSG(hwnd, WM_DEADCHAR,	_OnDeadChar);
-	HANDLE_MSG(hwnd, WM_SYSDEADCHAR, _OnDeadChar);
-	/* HANDLE_MSG(hwnd, WM_ACTIVATE,    _OnActivate); */
-	HANDLE_MSG(hwnd, WM_CHAR,	_OnChar);
-	HANDLE_MSG(hwnd, WM_CLOSE,	_OnClose);
-	/* HANDLE_MSG(hwnd, WM_COMMAND,	_OnCommand); */
-	HANDLE_MSG(hwnd, WM_DESTROY,	_OnDestroy);
-	HANDLE_MSG(hwnd, WM_DROPFILES,	_OnDropFiles);
-	HANDLE_MSG(hwnd, WM_HSCROLL,	_OnScroll);
-	HANDLE_MSG(hwnd, WM_KILLFOCUS,	_OnKillFocus);
-#ifdef FEAT_MENU
-	HANDLE_MSG(hwnd, WM_COMMAND,	_OnMenu);
-#endif
-	/* HANDLE_MSG(hwnd, WM_MOVE,	    _OnMove); */
-	/* HANDLE_MSG(hwnd, WM_NCACTIVATE,  _OnNCActivate); */
-	HANDLE_MSG(hwnd, WM_SETFOCUS,	_OnSetFocus);
-	HANDLE_MSG(hwnd, WM_SIZE,	_OnSize);
-	/* HANDLE_MSG(hwnd, WM_SYSCOMMAND,  _OnSysCommand); */
-	/* HANDLE_MSG(hwnd, WM_SYSKEYDOWN,  _OnAltKey); */
-	HANDLE_MSG(hwnd, WM_VSCROLL,	_OnScroll);
-	HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGING,	_OnWindowPosChanging);
-	HANDLE_MSG(hwnd, WM_ACTIVATEAPP, _OnActivateApp);
-
-    case WM_QUERYENDSESSION:	/* System wants to go down. */
-	gui_shell_closed();	/* Will exit when no changed buffers. */
-	return FALSE;		/* Do NOT allow system to go down. */
-
-    case WM_ENDSESSION:
-	if (wParam)	/* system only really goes down when wParam is TRUE */
-	    _OnEndSession();
-	break;
-
-    case WM_SYSCHAR:
-	/*
-	 * if 'winaltkeys' is "no", or it's "menu" and it's not a menu
-	 * shortcut key, handle like a typed ALT key, otherwise call Windows
-	 * ALT key handling.
-	 */
-#ifdef FEAT_MENU
-	if (	!gui.menu_is_active
-		|| p_wak[0] == 'n'
-		|| (p_wak[0] == 'm' && !gui_is_menu_shortcut((int)wParam))
-		)
-#endif
-	    return HANDLE_WM_SYSCHAR((hwnd), (wParam), (lParam), (_OnSysChar));
-#ifdef FEAT_MENU
-	else
-	    return MyWindowProc(hwnd, uMsg, wParam, lParam);
-#endif
-
-    case WM_SYSKEYUP:
-#ifdef FEAT_MENU
-	/* Only when menu is active, ALT key is used for that. */
-	if (gui.menu_is_active)
-	{
-	    return MyWindowProc(hwnd, uMsg, wParam, lParam);
-	}
-	else
-#endif
-	    return 0;
-
-#if defined(MENUHINTS) && defined(FEAT_MENU)
-    case WM_MENUSELECT:
-	if (((UINT) LOWORD(lParam)
-		    & (0xffff ^ (MF_MOUSESELECT + MF_BITMAP + MF_POPUP)))
-		== MF_HILITE
-		&& (State & CMDLINE) == 0)
-	{
-	    UINT idButton;
-	    int	idx;
-	    vimmenu_T *pMenu;
-
-	    idButton = (UINT)LOWORD(wParam);
-	    pMenu = gui_mswin_find_menu(root_menu, idButton);
-	    if (pMenu)
-	    {
-		idx = MENU_INDEX_TIP;
-		msg_clr_cmdline();
-		if (pMenu->strings[idx])
-		    msg(pMenu->strings[idx]);
-		else
-		    msg("");
-		setcursor();
-		out_flush();
-	    }
-	}
-	break;
-#endif
-    case WM_NCHITTEST:
-	{
-	    LRESULT	result;
-	    int x, y;
-	    int xPos = GET_X_LPARAM(lParam);
-
-	    result = MyWindowProc(hwnd, uMsg, wParam, lParam);
-	    if (result == HTCLIENT)
-	    {
-		(void)gui_mch_get_winpos(&x, &y);
-		xPos -= x;
-
-		if (xPos < 48) /*<VN> TODO should use system metric?*/
-		    return HTBOTTOMLEFT;
-		else
-		    return HTBOTTOMRIGHT;
-		}
-	    else
-		return result;
-	}
-	/* break; */
-    default:
-#ifdef MSWIN_FIND_REPLACE
-	if (uMsg == s_findrep_msg && s_findrep_msg != 0)
-	{
-	    _OnFindRepl();
-	}
-#endif
-	return MyWindowProc(hwnd, uMsg, wParam, lParam);
-    }
-
-    return 1;
-}
-
-
-
-/*
- * End of call-back routines
- */
-
-
-/*
- * Parse the GUI related command-line arguments.  Any arguments used are
- * deleted from argv, and *argc is decremented accordingly.  This is called
- * when vim is started, whether or not the GUI has been started.
- */
-    void
-gui_mch_prepare(int *argc, char **argv)
-{
-    /* No special args for win16 GUI at the moment. */
-
-}
-
-/*
- * Initialise the GUI.	Create all the windows, set up all the call-backs
- * etc.
- */
-    int
-gui_mch_init(void)
-{
-    const char szVimWndClass[] = VIM_CLASS;
-    const char szTextAreaClass[] = "VimTextArea";
-    WNDCLASS wndclass;
-
-#ifdef WIN16_3DLOOK
-    Ctl3dRegister(s_hinst);
-    Ctl3dAutoSubclass(s_hinst);
-#endif
-
-    /* Display any pending error messages */
-    display_errors();
-
-    gui.scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
-    gui.scrollbar_height = GetSystemMetrics(SM_CYHSCROLL);
-#ifdef FEAT_MENU
-    gui.menu_height = 0;	/* Windows takes care of this */
-#endif
-    gui.border_width = 0;
-
-    gui.currBgColor = INVALCOLOR;
-
-    s_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
-
-    if (GetClassInfo(s_hinst, szVimWndClass, &wndclass) == 0) {
-	wndclass.style = 0;
-	wndclass.lpfnWndProc = _WndProc;
-	wndclass.cbClsExtra = 0;
-	wndclass.cbWndExtra = 0;
-	wndclass.hInstance = s_hinst;
-	wndclass.hIcon = LoadIcon(wndclass.hInstance, MAKEINTRESOURCE(IDR_VIM));
-	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
-	wndclass.hbrBackground = s_brush;
-	wndclass.lpszMenuName = NULL;
-	wndclass.lpszClassName = szVimWndClass;
-
-    if ((
-#ifdef GLOBAL_IME
-	atom =
-#endif
-		RegisterClass(&wndclass)) == 0)
-	    return FAIL;
-    }
-
-    s_hwnd = CreateWindow(
-	szVimWndClass, "Vim MSWindows GUI",
-	WS_OVERLAPPEDWINDOW,
-	gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
-	gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
-	100,				/* Any value will do */
-	100,				/* Any value will do */
-	NULL, NULL,
-	s_hinst, NULL);
-
-    if (s_hwnd == NULL)
-	return FAIL;
-
-#ifdef GLOBAL_IME
-    global_ime_init(atom, s_hwnd);
-#endif
-
-    /* Create the text area window */
-    if (GetClassInfo(s_hinst, szTextAreaClass, &wndclass) == 0) {
-	wndclass.style = CS_OWNDC;
-	wndclass.lpfnWndProc = _TextAreaWndProc;
-	wndclass.cbClsExtra = 0;
-	wndclass.cbWndExtra = 0;
-	wndclass.hInstance = s_hinst;
-	wndclass.hIcon = NULL;
-	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
-	wndclass.hbrBackground = NULL;
-	wndclass.lpszMenuName = NULL;
-	wndclass.lpszClassName = szTextAreaClass;
-
-	if (RegisterClass(&wndclass) == 0)
-	    return FAIL;
-    }
-    s_textArea = CreateWindow(
-	szTextAreaClass, "Vim text area",
-	WS_CHILD | WS_VISIBLE, 0, 0,
-	100,				/* Any value will do for now */
-	100,				/* Any value will do for now */
-	s_hwnd, NULL,
-	s_hinst, NULL);
-
-    if (s_textArea == NULL)
-	return FAIL;
-
-#ifdef FEAT_MENU
-    s_menuBar = CreateMenu();
-#endif
-    s_hdc = GetDC(s_textArea);
-
-#ifdef MSWIN16_FASTTEXT
-    SetBkMode(s_hdc, OPAQUE);
-#endif
-
-    DragAcceptFiles(s_hwnd, TRUE);
-
-    /* Do we need to bother with this? */
-    /* m_fMouseAvail = GetSystemMetrics(SM_MOUSEPRESENT); */
-
-    /* Get background/foreground colors from the system */
-    gui_mch_def_colors();
-
-    /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
-     * file) */
-    set_normal_colors();
-
-    /*
-     * Check that none of the colors are the same as the background color.
-     * Then store the current values as the defaults.
-     */
-    gui_check_colors();
-    gui.def_norm_pixel = gui.norm_pixel;
-    gui.def_back_pixel = gui.back_pixel;
-
-    /* Get the colors for the highlight groups (gui_check_colors() might have
-     * changed them) */
-    highlight_gui_started();
-
-    /*
-     * Start out by adding the configured border width into the border offset
-     */
-    gui.border_offset = gui.border_width;
-
-
-    /*
-     * compute a couple of metrics used for the dialogs
-     */
-    get_dialog_font_metrics();
-#ifdef FEAT_TOOLBAR
-    /*
-     * Create the toolbar
-     */
-    initialise_toolbar();
-#endif
-#ifdef MSWIN_FIND_REPLACE
-    /*
-     * Initialise the dialog box stuff
-     */
-    s_findrep_msg = RegisterWindowMessage(FINDMSGSTRING);
-
-    /* Initialise the struct */
-    s_findrep_struct.lStructSize = sizeof(s_findrep_struct);
-    s_findrep_struct.lpstrFindWhat = alloc(MSWIN_FR_BUFSIZE);
-    s_findrep_struct.lpstrFindWhat[0] = NUL;
-    s_findrep_struct.lpstrReplaceWith = alloc(MSWIN_FR_BUFSIZE);
-    s_findrep_struct.lpstrReplaceWith[0] = NUL;
-    s_findrep_struct.wFindWhatLen = MSWIN_FR_BUFSIZE;
-    s_findrep_struct.wReplaceWithLen = MSWIN_FR_BUFSIZE;
-#endif
-
-    return OK;
-}
-
-
-/*
- * Set the size of the window to the given width and height in pixels.
- */
-    void
-gui_mch_set_shellsize(int width, int height,
-	int min_width, int min_height, int base_width, int base_height,
-	int direction)
-{
-    RECT	workarea_rect;
-    int		win_width, win_height;
-    int		win_xpos, win_ypos;
-    WINDOWPLACEMENT wndpl;
-
-    /* try to keep window completely on screen */
-    /* get size of the screen work area - use SM_CYFULLSCREEN
-     * instead of SM_CYSCREEN so that we don't overlap the
-     * taskbar if someone fires us up on Win95/NT */
-    workarea_rect.left = 0;
-    workarea_rect.top = 0;
-    workarea_rect.right = GetSystemMetrics(SM_CXSCREEN);
-    workarea_rect.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
-
-    /* get current position of our window */
-    wndpl.length = sizeof(WINDOWPLACEMENT);
-    GetWindowPlacement(s_hwnd, &wndpl);
-    if (wndpl.showCmd == SW_SHOWNORMAL)
-    {
-	win_xpos = wndpl.rcNormalPosition.left;
-	win_ypos = wndpl.rcNormalPosition.top;
-    }
-    else
-    {
-	win_xpos = workarea_rect.left;
-	win_ypos = workarea_rect.top;
-    }
-
-    /* compute the size of the outside of the window */
-    win_width = width + GetSystemMetrics(SM_CXFRAME) * 2;
-    win_height = height + GetSystemMetrics(SM_CYFRAME) * 2
-			+ GetSystemMetrics(SM_CYCAPTION)
-#ifdef FEAT_MENU
-			+ gui_mswin_get_menu_height(FALSE)
-#endif
-			;
-
-    /* if the window is going off the screen, move it on to the screen */
-    if ((direction & RESIZE_HOR) && win_xpos + win_width > workarea_rect.right)
-	win_xpos = workarea_rect.right - win_width;
-
-    if ((direction & RESIZE_HOR) && win_xpos < workarea_rect.left)
-	win_xpos = workarea_rect.left;
-
-    if ((direction & RESIZE_VERT)
-			       && win_ypos + win_height > workarea_rect.bottom)
-	win_ypos = workarea_rect.bottom - win_height;
-
-    if ((direction & RESIZE_VERT) && win_ypos < workarea_rect.top)
-	win_ypos = workarea_rect.top;
-
-    /* set window position */
-    SetWindowPos(s_hwnd, NULL, win_xpos, win_ypos, win_width, win_height,
-		 SWP_NOZORDER | SWP_NOACTIVATE);
-
-#ifdef FEAT_MENU
-    /* Menu may wrap differently now */
-    gui_mswin_get_menu_height(!gui.starting);
-#endif
-}
-
-    void
-gui_mch_set_scrollbar_thumb(
-    scrollbar_T     *sb,
-    long	    val,
-    long	    size,
-    long	    max)
-{
-    sb->scroll_shift = 0;
-    while (max > 32767)
-    {
-	max = (max + 1) >> 1;
-	val  >>= 1;
-	size >>= 1;
-	++sb->scroll_shift;
-    }
-
-    if (sb->scroll_shift > 0)
-	++size;
-
-    SetScrollRange(sb->id, SB_CTL, 0, (int) max, FALSE);
-    SetScrollPos(sb->id, SB_CTL, (int) val, TRUE);
-}
-
-
-/*
- * Set the current text font.
- */
-    void
-gui_mch_set_font(GuiFont font)
-{
-    gui.currFont = font;
-    SelectFont(s_hdc, gui.currFont);
-}
-
-/*
- * Set the current text foreground color.
- */
-    void
-gui_mch_set_fg_color(guicolor_T color)
-{
-    gui.currFgColor = color;
-    SetTextColor(s_hdc, gui.currFgColor);
-}
-
-/*
- * Set the current text background color.
- */
-    void
-gui_mch_set_bg_color(guicolor_T color)
-{
-    if (gui.currBgColor == color)
-	return;
-
-    gui.currBgColor = color;
-    SetBkColor(s_hdc, gui.currBgColor);
-}
-
-/*
- * Set the current text special color.
- */
-    void
-gui_mch_set_sp_color(guicolor_T color)
-{
-    /* TODO */
-}
-
-
-
-    void
-gui_mch_draw_string(
-    int		row,
-    int		col,
-    char_u	*text,
-    int		len,
-    int		flags)
-{
-#ifndef MSWIN16_FASTTEXT
-    static int	*padding = NULL;
-    static int	pad_size = 0;
-    int		i;
-#endif
-    HPEN	hpen, old_pen;
-    int		y;
-
-#ifndef MSWIN16_FASTTEXT
-    /*
-     * Italic and bold text seems to have an extra row of pixels at the bottom
-     * (below where the bottom of the character should be).  If we draw the
-     * characters with a solid background, the top row of pixels in the
-     * character below will be overwritten.  We can fix this by filling in the
-     * background ourselves, to the correct character proportions, and then
-     * writing the character in transparent mode.  Still have a problem when
-     * the character is "_", which gets written on to the character below.
-     * New fix: set gui.char_ascent to -1.  This shifts all characters up one
-     * pixel in their slots, which fixes the problem with the bottom row of
-     * pixels.	We still need this code because otherwise the top row of pixels
-     * becomes a problem. - webb.
-     */
-    HBRUSH	hbr;
-    RECT	rc;
-
-    if (!(flags & DRAW_TRANSP))
-    {
-	/*
-	 * Clear background first.
-	 * Note: FillRect() excludes right and bottom of rectangle.
-	 */
-	rc.left = FILL_X(col);
-	rc.top = FILL_Y(row);
-#ifdef FEAT_MBYTE
-	if (has_mbyte)
-	{
-	    /* Compute the length in display cells. */
-	    rc.right = FILL_X(col + mb_string2cells(text, len));
-	}
-	else
-#endif
-	    rc.right = FILL_X(col + len);
-	rc.bottom = FILL_Y(row + 1);
-	hbr = CreateSolidBrush(gui.currBgColor);
-	FillRect(s_hdc, &rc, hbr);
-	DeleteBrush(hbr);
-
-	SetBkMode(s_hdc, TRANSPARENT);
-
-	/*
-	 * When drawing block cursor, prevent inverted character spilling
-	 * over character cell (can happen with bold/italic)
-	 */
-	if (flags & DRAW_CURSOR)
-	{
-	    pcliprect = &rc;
-	    foptions = ETO_CLIPPED;
-	}
-    }
-#else
-    /*
-     * Alternative: write the characters in opaque mode, since we have blocked
-     * bold or italic fonts.
-     */
-    /* The OPAQUE mode and backcolour have already been set */
-#endif
-    /* The forecolor and font have already been set */
-
-#ifndef MSWIN16_FASTTEXT
-
-    if (pad_size != Columns || padding == NULL || padding[0] != gui.char_width)
-    {
-	vim_free(padding);
-	pad_size = Columns;
-
-	padding = (int *)alloc(pad_size * sizeof(int));
-	if (padding != NULL)
-	    for (i = 0; i < pad_size; i++)
-		padding[i] = gui.char_width;
-    }
-#endif
-
-    /*
-     * We have to provide the padding argument because italic and bold versions
-     * of fixed-width fonts are often one pixel or so wider than their normal
-     * versions.
-     * No check for DRAW_BOLD, Windows will have done it already.
-     */
-#ifndef MSWIN16_FASTTEXT
-    ExtTextOut(s_hdc, TEXT_X(col), TEXT_Y(row), 0, NULL,
-						     (char *)text, len, padding);
-#else
-    TextOut(s_hdc, TEXT_X(col), TEXT_Y(row), (char *)text, len);
-#endif
-
-    if (flags & DRAW_UNDERL)
-    {
-	hpen = CreatePen(PS_SOLID, 1, gui.currFgColor);
-	old_pen = SelectObject(s_hdc, hpen);
-	/* When p_linespace is 0, overwrite the bottom row of pixels.
-	 * Otherwise put the line just below the character. */
-	y = FILL_Y(row + 1) - 1;
-#ifndef MSWIN16_FASTTEXT
-	if (p_linespace > 1)
-	    y -= p_linespace - 1;
-#endif
-	MoveToEx(s_hdc, FILL_X(col), y, NULL);
-	/* Note: LineTo() excludes the last pixel in the line. */
-	LineTo(s_hdc, FILL_X(col + len), y);
-	DeleteObject(SelectObject(s_hdc, old_pen));
-    }
-}
-
-
-/*
- * Output routines.
- */
-
-/* Flush any output to the screen */
-    void
-gui_mch_flush(void)
-{
-    /* Is anything needed here? */
-}
-
-    static void
-clear_rect(RECT *rcp)
-{
-    /* Use trick for fast rect clear */
-    gui_mch_set_bg_color(gui.back_pixel);
-    ExtTextOut(s_hdc, 0, 0, ETO_CLIPPED | ETO_OPAQUE, rcp, NULL, 0, NULL);
-}
-
-
-    void
-gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
-{
-
-    *screen_w = GetSystemMetrics(SM_CXFULLSCREEN)
-	      - GetSystemMetrics(SM_CXFRAME) * 2;
-    /* FIXME: dirty trick: Because the gui_get_base_height() doesn't include
-     * the menubar for MSwin, we subtract it from the screen height, so that
-     * the window size can be made to fit on the screen. */
-    *screen_h = GetSystemMetrics(SM_CYFULLSCREEN)
-	      - GetSystemMetrics(SM_CYFRAME) * 2
-#ifdef FEAT_MENU
-	      - gui_mswin_get_menu_height(FALSE)
-#endif
-	      ;
-}
-
-
-#if defined(FEAT_MENU) || defined(PROTO)
-/*
- * Add a sub menu to the menu bar.
- */
-    void
-gui_mch_add_menu(
-    vimmenu_T	*menu,
-    int		pos)
-{
-    vimmenu_T	*parent = menu->parent;
-
-    menu->submenu_id = CreatePopupMenu();
-    menu->id = s_menu_id++;
-
-    if (menu_is_menubar(menu->name))
-    {
-	InsertMenu((parent == NULL) ? s_menuBar : parent->submenu_id,
-		(UINT)pos, MF_POPUP | MF_STRING | MF_BYPOSITION,
-		(UINT)menu->submenu_id,  menu->name);
-    }
-
-    /* Fix window size if menu may have wrapped */
-    if (parent == NULL)
-	gui_mswin_get_menu_height(!gui.starting);
-}
-
-    void
-gui_mch_show_popupmenu(vimmenu_T *menu)
-{
-    POINT mp;
-
-    (void)GetCursorPos((LPPOINT)&mp);
-    gui_mch_show_popupmenu_at(menu, (int)mp.x, (int)mp.y);
-}
-
-    void
-gui_make_popup(char_u *path_name, int mouse_pos)
-{
-    vimmenu_T	*menu = gui_find_menu(path_name);
-
-    if (menu != NULL)
-    {
-	/* Find the position of the current cursor */
-	DWORD	temp_p;
-	POINT	p;
-	temp_p = GetDCOrg(s_hdc);
-	p.x = LOWORD(temp_p);
-	p.y = HIWORD(temp_p);
-	if (mouse_pos)
-	{
-	    int	mx, my;
-
-	    gui_mch_getmouse(&mx, &my);
-	    p.x += mx;
-	    p.y += my;
-	}
-	else if (curwin != NULL)
-	{
-	    p.x += TEXT_X(W_WINCOL(curwin) + curwin->w_wcol + 1);
-	    p.y += TEXT_Y(W_WINROW(curwin) + curwin->w_wrow + 1);
-	}
-	msg_scroll = FALSE;
-	gui_mch_show_popupmenu_at(menu, (int)p.x, (int)p.y);
-    }
-}
-
-/*
- * Add a menu item to a menu
- */
-    void
-gui_mch_add_menu_item(
-    vimmenu_T	*menu,
-    int		idx)
-{
-    vimmenu_T	*parent = menu->parent;
-
-    menu->id = s_menu_id++;
-    menu->submenu_id = NULL;
-
-#ifdef FEAT_TOOLBAR
-    if (menu_is_toolbar(parent->name))
-    {
-	TBBUTTON newtb;
-
-	vim_memset(&newtb, 0, sizeof(newtb));
-	if (menu_is_separator(menu->name))
-	{
-	    newtb.iBitmap = 0;
-	    newtb.fsStyle = TBSTYLE_SEP;
-	}
-	else
-	{
-	    if (menu->iconidx >= TOOLBAR_BITMAP_COUNT)
-		newtb.iBitmap = -1;
-	    else
-		newtb.iBitmap = menu->iconidx;
-	    newtb.fsStyle = TBSTYLE_BUTTON;
-	}
-	newtb.idCommand = menu->id;
-	newtb.fsState = TBSTATE_ENABLED;
-	SendMessage(s_toolbarhwnd, TB_INSERTBUTTON, (WPARAM)idx,
-							     (LPARAM)&newtb);
-	menu->submenu_id = (HMENU)-1;
-    }
-    else
-#endif
-    {
-	InsertMenu(parent->submenu_id, (UINT)idx,
-		(menu_is_separator(menu->name) ? MF_SEPARATOR : MF_STRING)
-							      | MF_BYPOSITION,
-		(UINT)menu->id, menu->name);
-    }
-}
-
-/*
- * Destroy the machine specific menu widget.
- */
-    void
-gui_mch_destroy_menu(vimmenu_T *menu)
-{
-    UINT i, j;
-    char pants[80]; /*<VN> hack*/
-#ifdef FEAT_TOOLBAR
-    /*
-     * is this a toolbar button?
-     */
-    if (menu->submenu_id == (HMENU)-1)
-    {
-	int iButton;
-
-	iButton = SendMessage(s_toolbarhwnd, TB_COMMANDTOINDEX, (WPARAM)menu->id, 0);
-	SendMessage(s_toolbarhwnd, TB_DELETEBUTTON, (WPARAM)iButton, 0);
-    }
-    else
-#endif
-    {
-	/*
-	 * negri: horrible API bug when running 16-bit programs under Win9x or
-	 * NT means that we can't use MF_BYCOMMAND for menu items which have
-	 * submenus, including the top-level headings. We have to find the menu
-	 * item and use MF_BYPOSITION instead. :-p
-	 */
-    if (menu->parent != NULL
-	    && menu_is_popup(menu->parent->dname)
-	    && menu->parent->submenu_id != NULL)
-	RemoveMenu(menu->parent->submenu_id, menu->id, MF_BYCOMMAND);
-    else if (menu->submenu_id == NULL)
-	RemoveMenu(s_menuBar, menu->id, MF_BYCOMMAND);
-    else if (menu->parent != NULL)
-    {
-	i = GetMenuItemCount(menu->parent->submenu_id);
-	for (j = 0; j < i; ++j)
-	{
-	    GetMenuString(menu->parent->submenu_id, j,
-		    pants, 80, MF_BYPOSITION);
-	    if (strcmp(pants, menu->name) == 0)
-	    {
-		RemoveMenu(menu->parent->submenu_id, j, MF_BYPOSITION);
-		break;
-	    }
-	}
-    }
-    else
-    {
-	i = GetMenuItemCount(s_menuBar);
-	for (j = 0; j < i; ++j)
-	{
-	    GetMenuString(s_menuBar, j, pants, 80, MF_BYPOSITION);
-	    if (strcmp(pants, menu->name) == 0)
-	    {
-		RemoveMenu(s_menuBar, j, MF_BYPOSITION);
-		break;
-	    }
-	}
-    }
-
-    if (menu->submenu_id != NULL)
-	DestroyMenu(menu->submenu_id);
-    }
-    DrawMenuBar(s_hwnd);
-}
-
-
-/*
- * Make a menu either grey or not grey.
- */
-    void
-gui_mch_menu_grey(
-    vimmenu_T *menu,
-    int	    grey)
-{
-#ifdef FEAT_TOOLBAR
-    /*
-     * is this a toolbar button?
-     */
-    if (menu->submenu_id == (HMENU)-1)
-    {
-	SendMessage(s_toolbarhwnd, TB_ENABLEBUTTON,
-	    (WPARAM)menu->id, (LPARAM) MAKELONG((grey ? FALSE : TRUE), 0) );
-    }
-    else
-#endif
-    if (grey)
-	EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_GRAYED);
-    else
-	EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED);
-
-}
-
-
-#endif /*FEAT_MENU*/
-
-
-/* define some macros used to make the dialogue creation more readable */
-
-#define add_string(s) strcpy((LPSTR)p, s); (LPSTR)p += (strlen((LPSTR)p) + 1)
-#define add_word(x)		*p++ = (x)
-#define add_byte(x)		*((LPSTR)p)++ = (x)
-#define add_long(x)		*((LPDWORD)p)++ = (x)
-
-#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
-/*
- * stuff for dialogs
- */
-
-/*
- * The callback routine used by all the dialogs.  Very simple.  First,
- * acknowledges the INITDIALOG message so that Windows knows to do standard
- * dialog stuff (Return = default, Esc = cancel....) Second, if a button is
- * pressed, return that button's ID - IDCANCEL (2), which is the button's
- * number.
- */
-	 static BOOL CALLBACK
-dialog_callback(
-	 HWND hwnd,
-	 UINT message,
-	 WPARAM wParam,
-	 LPARAM lParam)
-{
-    if (message == WM_INITDIALOG)
-    {
-	CenterWindow(hwnd, GetWindow(hwnd, GW_OWNER));
-	/* Set focus to the dialog.  Set the default button, if specified. */
-	(void)SetFocus(hwnd);
-	if (dialog_default_button > IDCANCEL)
-	    (void)SetFocus(GetDlgItem(hwnd, dialog_default_button));
-//	if (dialog_default_button > 0)
-//	    (void)SetFocus(GetDlgItem(hwnd, dialog_default_button + IDCANCEL));
-	return FALSE;
-    }
-
-    if (message == WM_COMMAND)
-    {
-	int	button = LOWORD(wParam);
-
-	/* Don't end the dialog if something was selected that was
-	 * not a button.
-	 */
-	if (button >= DLG_NONBUTTON_CONTROL)
-	    return TRUE;
-
-	/* If the edit box exists, copy the string. */
-	if (s_textfield != NULL)
-	    GetDlgItemText(hwnd, DLG_NONBUTTON_CONTROL + 2,
-							 s_textfield, IOSIZE);
-
-	/*
-	 * Need to check for IDOK because if the user just hits Return to
-	 * accept the default value, some reason this is what we get.
-	 */
-	if (button == IDOK)
-	    EndDialog(hwnd, dialog_default_button);
-	else
-	    EndDialog(hwnd, button - IDCANCEL);
-	return TRUE;
-    }
-
-    if ((message == WM_SYSCOMMAND) && (wParam == SC_CLOSE))
-    {
-	EndDialog(hwnd, 0);
-	return TRUE;
-    }
-    return FALSE;
-}
-
-/*
- * Create a dialog dynamically from the parameter strings.
- * type		= type of dialog (question, alert, etc.)
- * title	= dialog title. may be NULL for default title.
- * message	= text to display. Dialog sizes to accommodate it.
- * buttons	= '\n' separated list of button captions, default first.
- * dfltbutton	= number of default button.
- *
- * This routine returns 1 if the first button is pressed,
- *			2 for the second, etc.
- *
- *			0 indicates Esc was pressed.
- *			-1 for unexpected error
- *
- * If stubbing out this fn, return 1.
- */
-
-static const char_u dlg_icons[] = /* must match names in resource file */
-{
-    IDR_VIM,
-    IDR_VIM_ERROR,
-    IDR_VIM_ALERT,
-    IDR_VIM_INFO,
-    IDR_VIM_QUESTION
-};
-
-    int
-gui_mch_dialog(
-    int		 type,
-    char_u	*title,
-    char_u	*message,
-    char_u	*buttons,
-    int		 dfltbutton,
-    char_u	*textfield,
-    int		ex_cmd)
-{
-    FARPROC	dp;
-    LPWORD	p, pnumitems;
-    int		numButtons;
-    int		*buttonWidths, *buttonPositions;
-    int		buttonYpos;
-    int		nchar, i;
-    DWORD	lStyle;
-    int		dlgwidth = 0;
-    int		dlgheight;
-    int		editboxheight;
-    int		horizWidth;
-    int		msgheight;
-    char_u	*pstart;
-    char_u	*pend;
-    char_u	*tbuffer;
-    RECT	rect;
-    HWND	hwnd;
-    HDC		hdc;
-    HFONT	oldFont;
-    TEXTMETRIC	fontInfo;
-    int		fontHeight;
-    int		textWidth, minButtonWidth, messageWidth;
-    int		maxDialogWidth;
-    int		vertical;
-    int		dlgPaddingX;
-    int		dlgPaddingY;
-    HGLOBAL	hglbDlgTemp;
-
-#ifndef NO_CONSOLE
-    /* Don't output anything in silent mode ("ex -s") */
-    if (silent_mode)
-	return dfltbutton;   /* return default option */
-#endif
-
-    /* If there is no window yet, open it. */
-    if (s_hwnd == NULL && gui_mch_init() == FAIL)
-	return dfltbutton;
-
-    if ((type < 0) || (type > VIM_LAST_TYPE))
-	type = 0;
-
-    /* allocate some memory for dialog template */
-    /* TODO should compute this really*/
-
-    hglbDlgTemp = GlobalAlloc(GHND,  DLG_ALLOC_SIZE);
-    if (hglbDlgTemp == NULL)
-	return -1;
-
-    p = (LPWORD) GlobalLock(hglbDlgTemp);
-
-    if (p == NULL)
-	return -1;
-
-    /*
-     * make a copy of 'buttons' to fiddle with it.  compiler grizzles because
-     * vim_strsave() doesn't take a const arg (why not?), so cast away the
-     * const.
-     */
-    tbuffer = vim_strsave(buttons);
-    if (tbuffer == NULL)
-	return -1;
-
-    --dfltbutton;   /* Change from one-based to zero-based */
-
-    /* Count buttons */
-    numButtons = 1;
-    for (i = 0; tbuffer[i] != '\0'; i++)
-    {
-	if (tbuffer[i] == DLG_BUTTON_SEP)
-	    numButtons++;
-    }
-    if (dfltbutton >= numButtons)
-	dfltbutton = 0;
-
-    /* Allocate array to hold the width of each button */
-    buttonWidths = (int *) lalloc(numButtons * sizeof(int), TRUE);
-    if (buttonWidths == NULL)
-	return -1;
-
-    /* Allocate array to hold the X position of each button */
-    buttonPositions = (int *) lalloc(numButtons * sizeof(int), TRUE);
-    if (buttonPositions == NULL)
-	return -1;
-
-    /*
-     * Calculate how big the dialog must be.
-     */
-    hwnd = GetDesktopWindow();
-    hdc = GetWindowDC(hwnd);
-    oldFont = SelectFont(hdc, GetStockObject(SYSTEM_FONT));
-    dlgPaddingX = DLG_OLD_STYLE_PADDING_X;
-    dlgPaddingY = DLG_OLD_STYLE_PADDING_Y;
-
-    GetTextMetrics(hdc, &fontInfo);
-    fontHeight = fontInfo.tmHeight;
-
-    /* Minimum width for horizontal button */
-    minButtonWidth = GetTextWidth(hdc, "Cancel", 6);
-
-    /* Maximum width of a dialog, if possible */
-    GetWindowRect(s_hwnd, &rect);
-    maxDialogWidth = rect.right - rect.left
-		     - GetSystemMetrics(SM_CXFRAME) * 2;
-    if (maxDialogWidth < DLG_MIN_MAX_WIDTH)
-	maxDialogWidth = DLG_MIN_MAX_WIDTH;
-
-    /* Set dlgwidth to width of message */
-    pstart = message;
-    messageWidth = 0;
-    msgheight = 0;
-    do
-    {
-	pend = vim_strchr(pstart, DLG_BUTTON_SEP);
-	if (pend == NULL)
-	    pend = pstart + STRLEN(pstart);	/* Last line of message. */
-	msgheight += fontHeight;
-	textWidth = GetTextWidth(hdc, pstart, pend - pstart);
-	if (textWidth > messageWidth)
-	    messageWidth = textWidth;
-	pstart = pend + 1;
-    } while (*pend != NUL);
-    dlgwidth = messageWidth;
-
-    /* Add width of icon to dlgwidth, and some space */
-    dlgwidth += DLG_ICON_WIDTH + 3 * dlgPaddingX;
-
-    if (msgheight < DLG_ICON_HEIGHT)
-	msgheight = DLG_ICON_HEIGHT;
-
-    /*
-     * Check button names.  A long one will make the dialog wider.
-     */
-	 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
-    if (!vertical)
-    {
-	// Place buttons horizontally if they fit.
-	horizWidth = dlgPaddingX;
-	pstart = tbuffer;
-	i = 0;
-	do
-	{
-	    pend = vim_strchr(pstart, DLG_BUTTON_SEP);
-	    if (pend == NULL)
-		pend = pstart + STRLEN(pstart);	// Last button name.
-	    textWidth = GetTextWidth(hdc, pstart, pend - pstart);
-	    if (textWidth < minButtonWidth)
-		textWidth = minButtonWidth;
-	    textWidth += dlgPaddingX;	    /* Padding within button */
-	    buttonWidths[i] = textWidth;
-	    buttonPositions[i++] = horizWidth;
-	    horizWidth += textWidth + dlgPaddingX; /* Pad between buttons */
-	    pstart = pend + 1;
-	} while (*pend != NUL);
-
-	if (horizWidth > maxDialogWidth)
-	    vertical = TRUE;	// Too wide to fit on the screen.
-	else if (horizWidth > dlgwidth)
-	    dlgwidth = horizWidth;
-    }
-
-    if (vertical)
-    {
-	// Stack buttons vertically.
-	pstart = tbuffer;
-	do
-	{
-	    pend = vim_strchr(pstart, DLG_BUTTON_SEP);
-	    if (pend == NULL)
-		pend = pstart + STRLEN(pstart);	// Last button name.
-	    textWidth = GetTextWidth(hdc, pstart, pend - pstart);
-	    textWidth += dlgPaddingX;		/* Padding within button */
-	    textWidth += DLG_VERT_PADDING_X * 2; /* Padding around button */
-	    if (textWidth > dlgwidth)
-		dlgwidth = textWidth;
-	    pstart = pend + 1;
-	} while (*pend != NUL);
-    }
-
-    if (dlgwidth < DLG_MIN_WIDTH)
-	dlgwidth = DLG_MIN_WIDTH;	/* Don't allow a really thin dialog!*/
-
-    /* start to fill in the dlgtemplate information.  addressing by WORDs */
-    lStyle = DS_MODALFRAME | WS_CAPTION | WS_VISIBLE ;
-
-    add_long(lStyle);
-    pnumitems = p;	/*save where the number of items must be stored*/
-    add_byte(0);	// NumberOfItems(will change later)
-    add_word(10);	// x
-    add_word(10);	// y
-    add_word(PixelToDialogX(dlgwidth));
-
-    // Dialog height.
-    if (vertical)
-	dlgheight = msgheight + 2 * dlgPaddingY +
-			      DLG_VERT_PADDING_Y + 2 * fontHeight * numButtons;
-    else
-	dlgheight = msgheight + 3 * dlgPaddingY + 2 * fontHeight;
-
-    // Dialog needs to be taller if contains an edit box.
-    editboxheight = fontHeight + dlgPaddingY + 4 * DLG_VERT_PADDING_Y;
-    if (textfield != NULL)
-	dlgheight += editboxheight;
-
-    add_word(PixelToDialogY(dlgheight));
-
-    add_byte(0);	//menu
-    add_byte(0);	//class
-
-    /* copy the title of the dialog */
-    add_string(title ? title : ("Vim"VIM_VERSION_MEDIUM));
-
-    buttonYpos = msgheight + 2 * dlgPaddingY;
-
-    if (textfield != NULL)
-	buttonYpos += editboxheight;
-
-    pstart = tbuffer; //dflt_text
-    horizWidth = (dlgwidth - horizWidth) / 2;	/* Now it's X offset */
-    for (i = 0; i < numButtons; i++)
-    {
-	/* get end of this button. */
-	for (	pend = pstart;
-		*pend && (*pend != DLG_BUTTON_SEP);
-		pend++)
-	    ;
-
-	if (*pend)
-	    *pend = '\0';
-
-	/*
-	 * NOTE:
-	 * setting the BS_DEFPUSHBUTTON style doesn't work because Windows sets
-	 * the focus to the first tab-able button and in so doing makes that
-	 * the default!! Grrr.  Workaround: Make the default button the only
-	 * one with WS_TABSTOP style. Means user can't tab between buttons, but
-	 * he/she can use arrow keys.
-	 *
-	 * NOTE (Thore): Setting BS_DEFPUSHBUTTON works fine when it's the
-	 * first one, so I changed the correct button to be this style. This
-	 * is necessary because when an edit box is added, we need a button to
-	 * be default.  The edit box will be the default control, and when the
-	 * user presses enter from the edit box we want the default button to
-	 * be pressed.
-	 */
-	if (vertical)
-	{
-	    p = add_dialog_element(p,
-		    ((i == dfltbutton || dfltbutton < 0) && textfield != NULL
-			    ?  BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
-		    PixelToDialogX(DLG_VERT_PADDING_X),
-		    PixelToDialogY(buttonYpos /* TBK */
-				   + 2 * fontHeight * i),
-		    PixelToDialogX(dlgwidth - 2 * DLG_VERT_PADDING_X),
-		    (WORD)(PixelToDialogY(2 * fontHeight) - 1),
-		    (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
-	}
-	else
-	{
-	    p = add_dialog_element(p,
-		    ((i == dfltbutton || dfltbutton < 0) && textfield != NULL
-			     ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON) | WS_TABSTOP,
-		    PixelToDialogX(horizWidth + buttonPositions[i]),
-		    PixelToDialogY(buttonYpos), /* TBK */
-		    PixelToDialogX(buttonWidths[i]),
-		    (WORD)(PixelToDialogY(2 * fontHeight) - 1),
-		    (WORD)(IDCANCEL + 1 + i), (BYTE)0x80, pstart);
-	}
-
-	pstart = pend + 1;	/*next button*/
-
-    }
-    *pnumitems += numButtons;
-
-    /* Vim icon */
-    p = add_dialog_element(p, SS_ICON,
-	    PixelToDialogX(dlgPaddingX),
-	    PixelToDialogY(dlgPaddingY),
-	    PixelToDialogX(DLG_ICON_WIDTH),
-	    PixelToDialogY(DLG_ICON_HEIGHT),
-	    DLG_NONBUTTON_CONTROL + 0, (BYTE)0x82,
-	    &dlg_icons[type]);
-
-
-    /* Dialog message */
-    p = add_dialog_element(p, SS_LEFT,
-	    PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
-	    PixelToDialogY(dlgPaddingY),
-	    (WORD)(PixelToDialogX(messageWidth) + 1),
-	    PixelToDialogY(msgheight),
-	    DLG_NONBUTTON_CONTROL + 1, (BYTE)0x82, message);
-
-    /* Edit box */
-    if (textfield != NULL)
-    {
-	p = add_dialog_element(p, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP | WS_BORDER,
-		PixelToDialogX(2 * dlgPaddingX),
-		PixelToDialogY(2 * dlgPaddingY + msgheight),
-		PixelToDialogX(dlgwidth - 4 * dlgPaddingX),
-		PixelToDialogY(fontHeight + dlgPaddingY),
-		DLG_NONBUTTON_CONTROL + 2, (BYTE)0x81, textfield);
-	*pnumitems += 1;
-    }
-
-    *pnumitems += 2;
-
-    SelectFont(hdc, oldFont);
-    ReleaseDC(hwnd, hdc);
-    dp = MakeProcInstance((FARPROC)dialog_callback, s_hinst);
-
-
-    /* Let the dialog_callback() function know which button to make default
-     * If we have an edit box, make that the default. We also need to tell
-     * dialog_callback() if this dialog contains an edit box or not. We do
-     * this by setting s_textfield if it does.
-     */
-    if (textfield != NULL)
-    {
-	dialog_default_button = DLG_NONBUTTON_CONTROL + 2;
-	s_textfield = textfield;
-    }
-    else
-    {
-	dialog_default_button = IDCANCEL + 1 + dfltbutton;
-	s_textfield = NULL;
-    }
-
-    /*show the dialog box modally and get a return value*/
-    nchar = DialogBoxIndirect(
-	    s_hinst,
-	    (HGLOBAL) hglbDlgTemp,
-	    s_hwnd,
-	    (DLGPROC)dp);
-
-    FreeProcInstance( dp );
-    GlobalUnlock(hglbDlgTemp);
-    GlobalFree(hglbDlgTemp);
-    vim_free(tbuffer);
-    vim_free(buttonWidths);
-    vim_free(buttonPositions);
-
-
-    return nchar;
-}
-
-/*
- * Put a simple element (basic class) onto a dialog template in memory.
- * return a pointer to where the next item should be added.
- *
- * parameters:
- *  lStyle = additional style flags
- *  x,y = x & y positions IN DIALOG UNITS
- *  w,h = width and height IN DIALOG UNITS
- *  Id	= ID used in messages
- *  clss  = class ID, e.g 0x80 for a button, 0x82 for a static
- *  caption = usually text or resource name
- *
- *  TODO: use the length information noted here to enable the dialog creation
- *  routines to work out more exactly how much memory they need to alloc.
- */
-    static LPWORD
-add_dialog_element(
-    LPWORD p,
-    DWORD lStyle,
-    WORD x,
-    WORD y,
-    WORD w,
-    WORD h,
-    WORD Id,
-    BYTE clss,
-    const char *caption)
-{
-
-    lStyle = lStyle | WS_VISIBLE | WS_CHILD;
-
-    add_word(x);
-    add_word(y);
-    add_word(w);
-    add_word(h);
-    add_word(Id);
-    add_long(lStyle);
-    add_byte(clss);
-    if (((lStyle & SS_ICON) != 0) && (clss == 0x82))
-    {
-	/* Use resource ID */
-	add_byte(0xff);
-	add_byte(*caption);
-    }
-    else
-	add_string(caption);
-
-    add_byte(0);    //# of extra bytes following
-
-
-    return p;
-}
-
-#undef add_byte
-#undef add_string
-#undef add_long
-#undef add_word
-
-#endif /* FEAT_GUI_DIALOG */
-
-    static void
-get_dialog_font_metrics(void)
-{
-    DWORD	    dlgFontSize;
-	dlgFontSize = GetDialogBaseUnits();	/* fall back to big old system*/
-	s_dlgfntwidth = LOWORD(dlgFontSize);
-	s_dlgfntheight = HIWORD(dlgFontSize);
-}
-
-
-#if defined(FEAT_TOOLBAR) || defined(PROTO)
-
-/* cproto fails on missing include files */
-#ifndef PROTO
-# include "gui_w3~1.h"
-#endif
-
-/*
- * Create the toolbar, initially unpopulated.
- *  (just like the menu, there are no defaults, it's all
- *  set up through menu.vim)
- */
-    static void
-initialise_toolbar(void)
-{
-    s_toolbarhwnd = CreateToolbar(
-		    s_hwnd,
-		    WS_CHILD | WS_VISIBLE,
-		    CMD_TB_BASE, /*<vn>*/
-		    31,			//number of images in initial bitmap
-		    s_hinst,
-		    IDR_TOOLBAR1,	// id of initial bitmap
-		    NULL,
-		    0			// initial number of buttons
-		    );
-
-    gui_mch_show_toolbar(vim_strchr(p_go, GO_TOOLBAR) != NULL);
-}
-#endif
-
-#if defined(FEAT_OLE) || defined(FEAT_EVAL) || defined(PROTO)
-/*
- * Make the GUI window come to the foreground.
- */
-    void
-gui_mch_set_foreground(void)
-{
-    if (IsIconic(s_hwnd))
-	 SendMessage(s_hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
-    SetActiveWindow(s_hwnd);
-}
-#endif
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -10,7 +10,7 @@
 /*
  * Windows GUI.
  *
- * GUI support for Microsoft Windows.  Win32 initially; maybe Win16 later
+ * GUI support for Microsoft Windows, aka Win32.  Also for Win64.
  *
  * George V. Reilly <george@reilly.org> wrote the original Win32 GUI.
  * Robert Webb reworked it to use the existing GUI stuff and added menu,
@@ -185,10 +185,4095 @@ gui_mch_set_rendering_options(char_u *s)
    ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
 #endif
 
-/*
- * Include the common stuff for MS-Windows GUI.
- */
-#include "gui_w48.c"
+
+#include "version.h"	/* used by dialog box routine for default title */
+#ifdef DEBUG
+# include <tchar.h>
+#endif
+
+/* cproto fails on missing include files */
+#ifndef PROTO
+
+#ifndef __MINGW32__
+# include <shellapi.h>
+#endif
+#if defined(FEAT_TOOLBAR) || defined(FEAT_BEVAL) || defined(FEAT_GUI_TABLINE)
+# include <commctrl.h>
+#endif
+#include <windowsx.h>
+
+#ifdef GLOBAL_IME
+# include "glbl_ime.h"
+#endif
+
+#endif /* PROTO */
+
+#ifdef FEAT_MENU
+# define MENUHINTS		/* show menu hints in command line */
+#endif
+
+/* Some parameters for dialog boxes.  All in pixels. */
+#define DLG_PADDING_X		10
+#define DLG_PADDING_Y		10
+#define DLG_OLD_STYLE_PADDING_X	5
+#define DLG_OLD_STYLE_PADDING_Y	5
+#define DLG_VERT_PADDING_X	4	/* For vertical buttons */
+#define DLG_VERT_PADDING_Y	4
+#define DLG_ICON_WIDTH		34
+#define DLG_ICON_HEIGHT		34
+#define DLG_MIN_WIDTH		150
+#define DLG_FONT_NAME		"MS Sans Serif"
+#define DLG_FONT_POINT_SIZE	8
+#define DLG_MIN_MAX_WIDTH	400
+#define DLG_MIN_MAX_HEIGHT	400
+
+#define DLG_NONBUTTON_CONTROL	5000	/* First ID of non-button controls */
+
+#ifndef WM_XBUTTONDOWN /* For Win2K / winME ONLY */
+# define WM_XBUTTONDOWN		0x020B
+# define WM_XBUTTONUP		0x020C
+# define WM_XBUTTONDBLCLK	0x020D
+# define MK_XBUTTON1		0x0020
+# define MK_XBUTTON2		0x0040
+#endif
+
+#ifdef PROTO
+/*
+ * Define a few things for generating prototypes.  This is just to avoid
+ * syntax errors, the defines do not need to be correct.
+ */
+# define APIENTRY
+# define CALLBACK
+# define CONST
+# define FAR
+# define NEAR
+# define _cdecl
+typedef int BOOL;
+typedef int BYTE;
+typedef int DWORD;
+typedef int WCHAR;
+typedef int ENUMLOGFONT;
+typedef int FINDREPLACE;
+typedef int HANDLE;
+typedef int HBITMAP;
+typedef int HBRUSH;
+typedef int HDROP;
+typedef int INT;
+typedef int LOGFONT[];
+typedef int LPARAM;
+typedef int LPCREATESTRUCT;
+typedef int LPCSTR;
+typedef int LPCTSTR;
+typedef int LPRECT;
+typedef int LPSTR;
+typedef int LPWINDOWPOS;
+typedef int LPWORD;
+typedef int LRESULT;
+typedef int HRESULT;
+# undef MSG
+typedef int MSG;
+typedef int NEWTEXTMETRIC;
+typedef int OSVERSIONINFO;
+typedef int PWORD;
+typedef int RECT;
+typedef int UINT;
+typedef int WORD;
+typedef int WPARAM;
+typedef int POINT;
+typedef void *HINSTANCE;
+typedef void *HMENU;
+typedef void *HWND;
+typedef void *HDC;
+typedef void VOID;
+typedef int LPNMHDR;
+typedef int LONG;
+typedef int WNDPROC;
+#endif
+
+#ifndef GET_X_LPARAM
+# define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+#endif
+
+static void _OnPaint( HWND hwnd);
+static void clear_rect(RECT *rcp);
+
+static WORD		s_dlgfntheight;		/* height of the dialog font */
+static WORD		s_dlgfntwidth;		/* width of the dialog font */
+
+#ifdef FEAT_MENU
+static HMENU		s_menuBar = NULL;
+#endif
+#ifdef FEAT_TEAROFF
+static void rebuild_tearoff(vimmenu_T *menu);
+static HBITMAP	s_htearbitmap;	    /* bitmap used to indicate tearoff */
+#endif
+
+/* Flag that is set while processing a message that must not be interrupted by
+ * processing another message. */
+static int		s_busy_processing = FALSE;
+
+static int		destroying = FALSE;	/* call DestroyWindow() ourselves */
+
+#ifdef MSWIN_FIND_REPLACE
+static UINT		s_findrep_msg = 0;	/* set in gui_w[16/32].c */
+static FINDREPLACE	s_findrep_struct;
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+static FINDREPLACEW	s_findrep_struct_w;
+# endif
+static HWND		s_findrep_hwnd = NULL;
+static int		s_findrep_is_find;	/* TRUE for find dialog, FALSE
+						   for find/replace dialog */
+#endif
+
+static HINSTANCE	s_hinst = NULL;
+#if !defined(FEAT_SNIFF) && !defined(FEAT_GUI)
+static
+#endif
+HWND			s_hwnd = NULL;
+static HDC		s_hdc = NULL;
+static HBRUSH	s_brush = NULL;
+
+#ifdef FEAT_TOOLBAR
+static HWND		s_toolbarhwnd = NULL;
+static WNDPROC		s_toolbar_wndproc = NULL;
+#endif
+
+#ifdef FEAT_GUI_TABLINE
+static HWND		s_tabhwnd = NULL;
+static WNDPROC		s_tabline_wndproc = NULL;
+static int		showing_tabline = 0;
+#endif
+
+static WPARAM		s_wParam = 0;
+static LPARAM		s_lParam = 0;
+
+static HWND		s_textArea = NULL;
+static UINT		s_uMsg = 0;
+
+static char_u		*s_textfield; /* Used by dialogs to pass back strings */
+
+static int		s_need_activate = FALSE;
+
+/* This variable is set when waiting for an event, which is the only moment
+ * scrollbar dragging can be done directly.  It's not allowed while commands
+ * are executed, because it may move the cursor and that may cause unexpected
+ * problems (e.g., while ":s" is working).
+ */
+static int allow_scrollbar = FALSE;
+
+#ifdef GLOBAL_IME
+# define MyTranslateMessage(x) global_ime_TranslateMessage(x)
+#else
+# define MyTranslateMessage(x) TranslateMessage(x)
+#endif
+
+#if (defined(WIN3264) && defined(FEAT_MBYTE)) || defined(GLOBAL_IME)
+  /* use of WindowProc depends on wide_WindowProc */
+# define MyWindowProc vim_WindowProc
+#else
+  /* use ordinary WindowProc */
+# define MyWindowProc DefWindowProc
+#endif
+
+extern int current_font_height;	    /* this is in os_mswin.c */
+
+static struct
+{
+    UINT    key_sym;
+    char_u  vim_code0;
+    char_u  vim_code1;
+} special_keys[] =
+{
+    {VK_UP,		'k', 'u'},
+    {VK_DOWN,		'k', 'd'},
+    {VK_LEFT,		'k', 'l'},
+    {VK_RIGHT,		'k', 'r'},
+
+    {VK_F1,		'k', '1'},
+    {VK_F2,		'k', '2'},
+    {VK_F3,		'k', '3'},
+    {VK_F4,		'k', '4'},
+    {VK_F5,		'k', '5'},
+    {VK_F6,		'k', '6'},
+    {VK_F7,		'k', '7'},
+    {VK_F8,		'k', '8'},
+    {VK_F9,		'k', '9'},
+    {VK_F10,		'k', ';'},
+
+    {VK_F11,		'F', '1'},
+    {VK_F12,		'F', '2'},
+    {VK_F13,		'F', '3'},
+    {VK_F14,		'F', '4'},
+    {VK_F15,		'F', '5'},
+    {VK_F16,		'F', '6'},
+    {VK_F17,		'F', '7'},
+    {VK_F18,		'F', '8'},
+    {VK_F19,		'F', '9'},
+    {VK_F20,		'F', 'A'},
+
+    {VK_F21,		'F', 'B'},
+#ifdef FEAT_NETBEANS_INTG
+    {VK_PAUSE,		'F', 'B'},	/* Pause == F21 (see gui_gtk_x11.c) */
+#endif
+    {VK_F22,		'F', 'C'},
+    {VK_F23,		'F', 'D'},
+    {VK_F24,		'F', 'E'},	/* winuser.h defines up to F24 */
+
+    {VK_HELP,		'%', '1'},
+    {VK_BACK,		'k', 'b'},
+    {VK_INSERT,		'k', 'I'},
+    {VK_DELETE,		'k', 'D'},
+    {VK_HOME,		'k', 'h'},
+    {VK_END,		'@', '7'},
+    {VK_PRIOR,		'k', 'P'},
+    {VK_NEXT,		'k', 'N'},
+    {VK_PRINT,		'%', '9'},
+    {VK_ADD,		'K', '6'},
+    {VK_SUBTRACT,	'K', '7'},
+    {VK_DIVIDE,		'K', '8'},
+    {VK_MULTIPLY,	'K', '9'},
+    {VK_SEPARATOR,	'K', 'A'},	/* Keypad Enter */
+    {VK_DECIMAL,	'K', 'B'},
+
+    {VK_NUMPAD0,	'K', 'C'},
+    {VK_NUMPAD1,	'K', 'D'},
+    {VK_NUMPAD2,	'K', 'E'},
+    {VK_NUMPAD3,	'K', 'F'},
+    {VK_NUMPAD4,	'K', 'G'},
+    {VK_NUMPAD5,	'K', 'H'},
+    {VK_NUMPAD6,	'K', 'I'},
+    {VK_NUMPAD7,	'K', 'J'},
+    {VK_NUMPAD8,	'K', 'K'},
+    {VK_NUMPAD9,	'K', 'L'},
+
+    /* Keys that we want to be able to use any modifier with: */
+    {VK_SPACE,		' ', NUL},
+    {VK_TAB,		TAB, NUL},
+    {VK_ESCAPE,		ESC, NUL},
+    {NL,		NL, NUL},
+    {CAR,		CAR, NUL},
+
+    /* End of list marker: */
+    {0,			0, 0}
+};
+
+/* Local variables */
+static int	s_button_pending = -1;
+
+/* s_getting_focus is set when we got focus but didn't see mouse-up event yet,
+ * so don't reset s_button_pending. */
+static int	s_getting_focus = FALSE;
+
+static int	s_x_pending;
+static int	s_y_pending;
+static UINT	s_kFlags_pending;
+static UINT	s_wait_timer = 0;   /* Timer for get char from user */
+static int	s_timed_out = FALSE;
+static int	dead_key = 0;	/* 0: no dead key, 1: dead key pressed */
+
+#ifdef WIN3264
+static OSVERSIONINFO os_version;    /* like it says.  Init in gui_mch_init() */
+#endif
+
+#ifdef FEAT_BEVAL
+/* balloon-eval WM_NOTIFY_HANDLER */
+static void Handle_WM_Notify(HWND hwnd, LPNMHDR pnmh);
+static void TrackUserActivity(UINT uMsg);
+#endif
+
+/*
+ * For control IME.
+ *
+ * These LOGFONT used for IME.
+ */
+#ifdef FEAT_MBYTE
+# ifdef USE_IM_CONTROL
+/* holds LOGFONT for 'guifontwide' if available, otherwise 'guifont' */
+static LOGFONT norm_logfont;
+/* holds LOGFONT for 'guifont' always. */
+static LOGFONT sub_logfont;
+# endif
+#endif
+
+#ifdef FEAT_MBYTE_IME
+static LRESULT _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData);
+#endif
+
+#if defined(FEAT_BROWSE)
+static char_u *convert_filter(char_u *s);
+#endif
+
+#ifdef DEBUG_PRINT_ERROR
+/*
+ * Print out the last Windows error message
+ */
+    static void
+print_windows_error(void)
+{
+    LPVOID  lpMsgBuf;
+
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+		  NULL, GetLastError(),
+		  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		  (LPTSTR) &lpMsgBuf, 0, NULL);
+    TRACE1("Error: %s\n", lpMsgBuf);
+    LocalFree(lpMsgBuf);
+}
+#endif
+
+/*
+ * Cursor blink functions.
+ *
+ * This is a simple state machine:
+ * BLINK_NONE	not blinking at all
+ * BLINK_OFF	blinking, cursor is not shown
+ * BLINK_ON	blinking, cursor is shown
+ */
+
+#define BLINK_NONE  0
+#define BLINK_OFF   1
+#define BLINK_ON    2
+
+static int		blink_state = BLINK_NONE;
+static long_u		blink_waittime = 700;
+static long_u		blink_ontime = 400;
+static long_u		blink_offtime = 250;
+static UINT		blink_timer = 0;
+
+    void
+gui_mch_set_blinking(long wait, long on, long off)
+{
+    blink_waittime = wait;
+    blink_ontime = on;
+    blink_offtime = off;
+}
+
+/* ARGSUSED */
+    static VOID CALLBACK
+_OnBlinkTimer(
+    HWND hwnd,
+    UINT uMsg,
+    UINT idEvent,
+    DWORD dwTime)
+{
+    MSG msg;
+
+    /*
+    TRACE2("Got timer event, id %d, blink_timer %d\n", idEvent, blink_timer);
+    */
+
+    KillTimer(NULL, idEvent);
+
+    /* Eat spurious WM_TIMER messages */
+    while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
+	;
+
+    if (blink_state == BLINK_ON)
+    {
+	gui_undraw_cursor();
+	blink_state = BLINK_OFF;
+	blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_offtime,
+						    (TIMERPROC)_OnBlinkTimer);
+    }
+    else
+    {
+	gui_update_cursor(TRUE, FALSE);
+	blink_state = BLINK_ON;
+	blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
+							 (TIMERPROC)_OnBlinkTimer);
+    }
+}
+
+    static void
+gui_mswin_rm_blink_timer(void)
+{
+    MSG msg;
+
+    if (blink_timer != 0)
+    {
+	KillTimer(NULL, blink_timer);
+	/* Eat spurious WM_TIMER messages */
+	while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
+	    ;
+	blink_timer = 0;
+    }
+}
+
+/*
+ * Stop the cursor blinking.  Show the cursor if it wasn't shown.
+ */
+    void
+gui_mch_stop_blink(void)
+{
+    gui_mswin_rm_blink_timer();
+    if (blink_state == BLINK_OFF)
+	gui_update_cursor(TRUE, FALSE);
+    blink_state = BLINK_NONE;
+}
+
+/*
+ * Start the cursor blinking.  If it was already blinking, this restarts the
+ * waiting time and shows the cursor.
+ */
+    void
+gui_mch_start_blink(void)
+{
+    gui_mswin_rm_blink_timer();
+
+    /* Only switch blinking on if none of the times is zero */
+    if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
+    {
+	blink_timer = (UINT)SetTimer(NULL, 0, (UINT)blink_waittime,
+						    (TIMERPROC)_OnBlinkTimer);
+	blink_state = BLINK_ON;
+	gui_update_cursor(TRUE, FALSE);
+    }
+}
+
+/*
+ * Call-back routines.
+ */
+
+/*ARGSUSED*/
+    static VOID CALLBACK
+_OnTimer(
+    HWND hwnd,
+    UINT uMsg,
+    UINT idEvent,
+    DWORD dwTime)
+{
+    MSG msg;
+
+    /*
+    TRACE2("Got timer event, id %d, s_wait_timer %d\n", idEvent, s_wait_timer);
+    */
+    KillTimer(NULL, idEvent);
+    s_timed_out = TRUE;
+
+    /* Eat spurious WM_TIMER messages */
+    while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
+	;
+    if (idEvent == s_wait_timer)
+	s_wait_timer = 0;
+}
+
+/*ARGSUSED*/
+    static void
+_OnDeadChar(
+    HWND hwnd,
+    UINT ch,
+    int cRepeat)
+{
+    dead_key = 1;
+}
+
+/*
+ * Convert Unicode character "ch" to bytes in "string[slen]".
+ * When "had_alt" is TRUE the ALT key was included in "ch".
+ * Return the length.
+ */
+    static int
+char_to_string(int ch, char_u *string, int slen, int had_alt)
+{
+    int		len;
+    int		i;
+#ifdef FEAT_MBYTE
+    WCHAR	wstring[2];
+    char_u	*ws = NULL;;
+
+    if (os_version.dwPlatformId != VER_PLATFORM_WIN32_NT)
+    {
+	/* On Windows 95/98 we apparently get the character in the active
+	 * codepage, not in UCS-2.  If conversion is needed convert it to
+	 * UCS-2 first. */
+	if ((int)GetACP() == enc_codepage)
+	    len = 0;	    /* no conversion required */
+	else
+	{
+	    string[0] = ch;
+	    len = MultiByteToWideChar(GetACP(), 0, (LPCSTR)string,
+		    1, wstring, 2);
+	}
+    }
+    else
+    {
+	wstring[0] = ch;
+	len = 1;
+    }
+
+    if (len > 0)
+    {
+	/* "ch" is a UTF-16 character.  Convert it to a string of bytes.  When
+	 * "enc_codepage" is non-zero use the standard Win32 function,
+	 * otherwise use our own conversion function (e.g., for UTF-8). */
+	if (enc_codepage > 0)
+	{
+	    len = WideCharToMultiByte(enc_codepage, 0, wstring, len,
+					       (LPSTR)string, slen, 0, NULL);
+	    /* If we had included the ALT key into the character but now the
+	     * upper bit is no longer set, that probably means the conversion
+	     * failed.  Convert the original character and set the upper bit
+	     * afterwards. */
+	    if (had_alt && len == 1 && ch >= 0x80 && string[0] < 0x80)
+	    {
+		wstring[0] = ch & 0x7f;
+		len = WideCharToMultiByte(enc_codepage, 0, wstring, len,
+					       (LPSTR)string, slen, 0, NULL);
+		if (len == 1) /* safety check */
+		    string[0] |= 0x80;
+	    }
+	}
+	else
+	{
+	    len = 1;
+	    ws = utf16_to_enc(wstring, &len);
+	    if (ws == NULL)
+		len = 0;
+	    else
+	    {
+		if (len > slen)	/* just in case */
+		    len = slen;
+		mch_memmove(string, ws, len);
+		vim_free(ws);
+	    }
+	}
+    }
+
+    if (len == 0)
+#endif
+    {
+	string[0] = ch;
+	len = 1;
+    }
+
+    for (i = 0; i < len; ++i)
+	if (string[i] == CSI && len <= slen - 2)
+	{
+	    /* Insert CSI as K_CSI. */
+	    mch_memmove(string + i + 3, string + i + 1, len - i - 1);
+	    string[++i] = KS_EXTRA;
+	    string[++i] = (int)KE_CSI;
+	    len += 2;
+	}
+
+    return len;
+}
+
+/*
+ * Key hit, add it to the input buffer.
+ */
+/*ARGSUSED*/
+    static void
+_OnChar(
+    HWND hwnd,
+    UINT ch,
+    int cRepeat)
+{
+    char_u	string[40];
+    int		len = 0;
+
+    dead_key = 0;
+
+    len = char_to_string(ch, string, 40, FALSE);
+    if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts)
+    {
+	trash_input_buf();
+	got_int = TRUE;
+    }
+
+    add_to_input_buf(string, len);
+}
+
+/*
+ * Alt-Key hit, add it to the input buffer.
+ */
+/*ARGSUSED*/
+    static void
+_OnSysChar(
+    HWND hwnd,
+    UINT cch,
+    int cRepeat)
+{
+    char_u	string[40]; /* Enough for multibyte character */
+    int		len;
+    int		modifiers;
+    int		ch = cch;   /* special keys are negative */
+
+    dead_key = 0;
+
+    /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */
+
+    /* OK, we have a character key (given by ch) which was entered with the
+     * ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
+     * that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless
+     * CAPSLOCK is pressed) at this point.
+     */
+    modifiers = MOD_MASK_ALT;
+    if (GetKeyState(VK_SHIFT) & 0x8000)
+	modifiers |= MOD_MASK_SHIFT;
+    if (GetKeyState(VK_CONTROL) & 0x8000)
+	modifiers |= MOD_MASK_CTRL;
+
+    ch = simplify_key(ch, &modifiers);
+    /* remove the SHIFT modifier for keys where it's already included, e.g.,
+     * '(' and '*' */
+    if (ch < 0x100 && !isalpha(ch) && isprint(ch))
+	modifiers &= ~MOD_MASK_SHIFT;
+
+    /* Interpret the ALT key as making the key META, include SHIFT, etc. */
+    ch = extract_modifiers(ch, &modifiers);
+    if (ch == CSI)
+	ch = K_CSI;
+
+    len = 0;
+    if (modifiers)
+    {
+	string[len++] = CSI;
+	string[len++] = KS_MODIFIER;
+	string[len++] = modifiers;
+    }
+
+    if (IS_SPECIAL((int)ch))
+    {
+	string[len++] = CSI;
+	string[len++] = K_SECOND((int)ch);
+	string[len++] = K_THIRD((int)ch);
+    }
+    else
+    {
+	/* Although the documentation isn't clear about it, we assume "ch" is
+	 * a Unicode character. */
+	len += char_to_string(ch, string + len, 40 - len, TRUE);
+    }
+
+    add_to_input_buf(string, len);
+}
+
+    static void
+_OnMouseEvent(
+    int button,
+    int x,
+    int y,
+    int repeated_click,
+    UINT keyFlags)
+{
+    int vim_modifiers = 0x0;
+
+    s_getting_focus = FALSE;
+
+    if (keyFlags & MK_SHIFT)
+	vim_modifiers |= MOUSE_SHIFT;
+    if (keyFlags & MK_CONTROL)
+	vim_modifiers |= MOUSE_CTRL;
+    if (GetKeyState(VK_MENU) & 0x8000)
+	vim_modifiers |= MOUSE_ALT;
+
+    gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers);
+}
+
+/*ARGSUSED*/
+    static void
+_OnMouseButtonDown(
+    HWND hwnd,
+    BOOL fDoubleClick,
+    int x,
+    int y,
+    UINT keyFlags)
+{
+    static LONG	s_prevTime = 0;
+
+    LONG    currentTime = GetMessageTime();
+    int	    button = -1;
+    int	    repeated_click;
+
+    /* Give main window the focus: this is so the cursor isn't hollow. */
+    (void)SetFocus(s_hwnd);
+
+    if (s_uMsg == WM_LBUTTONDOWN || s_uMsg == WM_LBUTTONDBLCLK)
+	button = MOUSE_LEFT;
+    else if (s_uMsg == WM_MBUTTONDOWN || s_uMsg == WM_MBUTTONDBLCLK)
+	button = MOUSE_MIDDLE;
+    else if (s_uMsg == WM_RBUTTONDOWN || s_uMsg == WM_RBUTTONDBLCLK)
+	button = MOUSE_RIGHT;
+    else if (s_uMsg == WM_XBUTTONDOWN || s_uMsg == WM_XBUTTONDBLCLK)
+    {
+#ifndef GET_XBUTTON_WPARAM
+# define GET_XBUTTON_WPARAM(wParam)	(HIWORD(wParam))
+#endif
+	button = ((GET_XBUTTON_WPARAM(s_wParam) == 1) ? MOUSE_X1 : MOUSE_X2);
+    }
+    else if (s_uMsg == WM_CAPTURECHANGED)
+    {
+	/* on W95/NT4, somehow you get in here with an odd Msg
+	 * if you press one button while holding down the other..*/
+	if (s_button_pending == MOUSE_LEFT)
+	    button = MOUSE_RIGHT;
+	else
+	    button = MOUSE_LEFT;
+    }
+    if (button >= 0)
+    {
+	repeated_click = ((int)(currentTime - s_prevTime) < p_mouset);
+
+	/*
+	 * Holding down the left and right buttons simulates pushing the middle
+	 * button.
+	 */
+	if (repeated_click
+		&& ((button == MOUSE_LEFT && s_button_pending == MOUSE_RIGHT)
+		    || (button == MOUSE_RIGHT
+					  && s_button_pending == MOUSE_LEFT)))
+	{
+	    /*
+	     * Hmm, gui.c will ignore more than one button down at a time, so
+	     * pretend we let go of it first.
+	     */
+	    gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, 0x0);
+	    button = MOUSE_MIDDLE;
+	    repeated_click = FALSE;
+	    s_button_pending = -1;
+	    _OnMouseEvent(button, x, y, repeated_click, keyFlags);
+	}
+	else if ((repeated_click)
+		|| (mouse_model_popup() && (button == MOUSE_RIGHT)))
+	{
+	    if (s_button_pending > -1)
+	    {
+		    _OnMouseEvent(s_button_pending, x, y, FALSE, keyFlags);
+		    s_button_pending = -1;
+	    }
+	    /* TRACE("Button down at x %d, y %d\n", x, y); */
+	    _OnMouseEvent(button, x, y, repeated_click, keyFlags);
+	}
+	else
+	{
+	    /*
+	     * If this is the first press (i.e. not a multiple click) don't
+	     * action immediately, but store and wait for:
+	     * i) button-up
+	     * ii) mouse move
+	     * iii) another button press
+	     * before using it.
+	     * This enables us to make left+right simulate middle button,
+	     * without left or right being actioned first.  The side-effect is
+	     * that if you click and hold the mouse without dragging, the
+	     * cursor doesn't move until you release the button. In practice
+	     * this is hardly a problem.
+	     */
+	    s_button_pending = button;
+	    s_x_pending = x;
+	    s_y_pending = y;
+	    s_kFlags_pending = keyFlags;
+	}
+
+	s_prevTime = currentTime;
+    }
+}
+
+/*ARGSUSED*/
+    static void
+_OnMouseMoveOrRelease(
+    HWND hwnd,
+    int x,
+    int y,
+    UINT keyFlags)
+{
+    int button;
+
+    s_getting_focus = FALSE;
+    if (s_button_pending > -1)
+    {
+	/* Delayed action for mouse down event */
+	_OnMouseEvent(s_button_pending, s_x_pending,
+					s_y_pending, FALSE, s_kFlags_pending);
+	s_button_pending = -1;
+    }
+    if (s_uMsg == WM_MOUSEMOVE)
+    {
+	/*
+	 * It's only a MOUSE_DRAG if one or more mouse buttons are being held
+	 * down.
+	 */
+	if (!(keyFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON
+						| MK_XBUTTON1 | MK_XBUTTON2)))
+	{
+	    gui_mouse_moved(x, y);
+	    return;
+	}
+
+	/*
+	 * While button is down, keep grabbing mouse move events when
+	 * the mouse goes outside the window
+	 */
+	SetCapture(s_textArea);
+	button = MOUSE_DRAG;
+	/* TRACE("  move at x %d, y %d\n", x, y); */
+    }
+    else
+    {
+	ReleaseCapture();
+	button = MOUSE_RELEASE;
+	/* TRACE("  up at x %d, y %d\n", x, y); */
+    }
+
+    _OnMouseEvent(button, x, y, FALSE, keyFlags);
+}
+
+#ifdef FEAT_MENU
+/*
+ * Find the vimmenu_T with the given id
+ */
+    static vimmenu_T *
+gui_mswin_find_menu(
+    vimmenu_T	*pMenu,
+    int		id)
+{
+    vimmenu_T	*pChildMenu;
+
+    while (pMenu)
+    {
+	if (pMenu->id == (UINT)id)
+	    break;
+	if (pMenu->children != NULL)
+	{
+	    pChildMenu = gui_mswin_find_menu(pMenu->children, id);
+	    if (pChildMenu)
+	    {
+		pMenu = pChildMenu;
+		break;
+	    }
+	}
+	pMenu = pMenu->next;
+    }
+    return pMenu;
+}
+
+/*ARGSUSED*/
+    static void
+_OnMenu(
+    HWND	hwnd,
+    int		id,
+    HWND	hwndCtl,
+    UINT	codeNotify)
+{
+    vimmenu_T	*pMenu;
+
+    pMenu = gui_mswin_find_menu(root_menu, id);
+    if (pMenu)
+	gui_menu_cb(pMenu);
+}
+#endif
+
+#ifdef MSWIN_FIND_REPLACE
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+/*
+ * copy useful data from structure LPFINDREPLACE to structure LPFINDREPLACEW
+ */
+    static void
+findrep_atow(LPFINDREPLACEW lpfrw, LPFINDREPLACE lpfr)
+{
+    WCHAR *wp;
+
+    lpfrw->hwndOwner = lpfr->hwndOwner;
+    lpfrw->Flags = lpfr->Flags;
+
+    wp = enc_to_utf16((char_u *)lpfr->lpstrFindWhat, NULL);
+    wcsncpy(lpfrw->lpstrFindWhat, wp, lpfrw->wFindWhatLen - 1);
+    vim_free(wp);
+
+    /* the field "lpstrReplaceWith" doesn't need to be copied */
+}
+
+/*
+ * copy useful data from structure LPFINDREPLACEW to structure LPFINDREPLACE
+ */
+    static void
+findrep_wtoa(LPFINDREPLACE lpfr, LPFINDREPLACEW lpfrw)
+{
+    char_u *p;
+
+    lpfr->Flags = lpfrw->Flags;
+
+    p = utf16_to_enc((short_u*)lpfrw->lpstrFindWhat, NULL);
+    vim_strncpy((char_u *)lpfr->lpstrFindWhat, p, lpfr->wFindWhatLen - 1);
+    vim_free(p);
+
+    p = utf16_to_enc((short_u*)lpfrw->lpstrReplaceWith, NULL);
+    vim_strncpy((char_u *)lpfr->lpstrReplaceWith, p, lpfr->wReplaceWithLen - 1);
+    vim_free(p);
+}
+# endif
+
+/*
+ * Handle a Find/Replace window message.
+ */
+    static void
+_OnFindRepl(void)
+{
+    int	    flags = 0;
+    int	    down;
+
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+    /* If the OS is Windows NT, and 'encoding' differs from active codepage:
+     * convert text from wide string. */
+    if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+			&& enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+    {
+	findrep_wtoa(&s_findrep_struct, &s_findrep_struct_w);
+    }
+# endif
+
+    if (s_findrep_struct.Flags & FR_DIALOGTERM)
+	/* Give main window the focus back. */
+	(void)SetFocus(s_hwnd);
+
+    if (s_findrep_struct.Flags & FR_FINDNEXT)
+    {
+	flags = FRD_FINDNEXT;
+
+	/* Give main window the focus back: this is so the cursor isn't
+	 * hollow. */
+	(void)SetFocus(s_hwnd);
+    }
+    else if (s_findrep_struct.Flags & FR_REPLACE)
+    {
+	flags = FRD_REPLACE;
+
+	/* Give main window the focus back: this is so the cursor isn't
+	 * hollow. */
+	(void)SetFocus(s_hwnd);
+    }
+    else if (s_findrep_struct.Flags & FR_REPLACEALL)
+    {
+	flags = FRD_REPLACEALL;
+    }
+
+    if (flags != 0)
+    {
+	/* Call the generic GUI function to do the actual work. */
+	if (s_findrep_struct.Flags & FR_WHOLEWORD)
+	    flags |= FRD_WHOLE_WORD;
+	if (s_findrep_struct.Flags & FR_MATCHCASE)
+	    flags |= FRD_MATCH_CASE;
+	down = (s_findrep_struct.Flags & FR_DOWN) != 0;
+	gui_do_findrepl(flags, (char_u *)s_findrep_struct.lpstrFindWhat,
+			     (char_u *)s_findrep_struct.lpstrReplaceWith, down);
+    }
+}
+#endif
+
+    static void
+HandleMouseHide(UINT uMsg, LPARAM lParam)
+{
+    static LPARAM last_lParam = 0L;
+
+    /* We sometimes get a mousemove when the mouse didn't move... */
+    if (uMsg == WM_MOUSEMOVE || uMsg == WM_NCMOUSEMOVE)
+    {
+	if (lParam == last_lParam)
+	    return;
+	last_lParam = lParam;
+    }
+
+    /* Handle specially, to centralise coding. We need to be sure we catch all
+     * possible events which should cause us to restore the cursor (as it is a
+     * shared resource, we take full responsibility for it).
+     */
+    switch (uMsg)
+    {
+    case WM_KEYUP:
+    case WM_CHAR:
+	/*
+	 * blank out the pointer if necessary
+	 */
+	if (p_mh)
+	    gui_mch_mousehide(TRUE);
+	break;
+
+    case WM_SYSKEYUP:	 /* show the pointer when a system-key is pressed */
+    case WM_SYSCHAR:
+    case WM_MOUSEMOVE:	 /* show the pointer on any mouse action */
+    case WM_LBUTTONDOWN:
+    case WM_LBUTTONUP:
+    case WM_MBUTTONDOWN:
+    case WM_MBUTTONUP:
+    case WM_RBUTTONDOWN:
+    case WM_RBUTTONUP:
+    case WM_XBUTTONDOWN:
+    case WM_XBUTTONUP:
+    case WM_NCMOUSEMOVE:
+    case WM_NCLBUTTONDOWN:
+    case WM_NCLBUTTONUP:
+    case WM_NCMBUTTONDOWN:
+    case WM_NCMBUTTONUP:
+    case WM_NCRBUTTONDOWN:
+    case WM_NCRBUTTONUP:
+    case WM_KILLFOCUS:
+	/*
+	 * if the pointer is currently hidden, then we should show it.
+	 */
+	gui_mch_mousehide(FALSE);
+	break;
+    }
+}
+
+    static LRESULT CALLBACK
+_TextAreaWndProc(
+    HWND hwnd,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam)
+{
+    /*
+    TRACE("TextAreaWndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
+	  hwnd, uMsg, wParam, lParam);
+    */
+
+    HandleMouseHide(uMsg, lParam);
+
+    s_uMsg = uMsg;
+    s_wParam = wParam;
+    s_lParam = lParam;
+
+#ifdef FEAT_BEVAL
+    TrackUserActivity(uMsg);
+#endif
+
+    switch (uMsg)
+    {
+	HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK,_OnMouseButtonDown);
+	HANDLE_MSG(hwnd, WM_LBUTTONDOWN,_OnMouseButtonDown);
+	HANDLE_MSG(hwnd, WM_LBUTTONUP,	_OnMouseMoveOrRelease);
+	HANDLE_MSG(hwnd, WM_MBUTTONDBLCLK,_OnMouseButtonDown);
+	HANDLE_MSG(hwnd, WM_MBUTTONDOWN,_OnMouseButtonDown);
+	HANDLE_MSG(hwnd, WM_MBUTTONUP,	_OnMouseMoveOrRelease);
+	HANDLE_MSG(hwnd, WM_MOUSEMOVE,	_OnMouseMoveOrRelease);
+	HANDLE_MSG(hwnd, WM_PAINT,	_OnPaint);
+	HANDLE_MSG(hwnd, WM_RBUTTONDBLCLK,_OnMouseButtonDown);
+	HANDLE_MSG(hwnd, WM_RBUTTONDOWN,_OnMouseButtonDown);
+	HANDLE_MSG(hwnd, WM_RBUTTONUP,	_OnMouseMoveOrRelease);
+	HANDLE_MSG(hwnd, WM_XBUTTONDBLCLK,_OnMouseButtonDown);
+	HANDLE_MSG(hwnd, WM_XBUTTONDOWN,_OnMouseButtonDown);
+	HANDLE_MSG(hwnd, WM_XBUTTONUP,	_OnMouseMoveOrRelease);
+
+#ifdef FEAT_BEVAL
+	case WM_NOTIFY: Handle_WM_Notify(hwnd, (LPNMHDR)lParam);
+	    return TRUE;
+#endif
+	default:
+	    return MyWindowProc(hwnd, uMsg, wParam, lParam);
+    }
+}
+
+#if (defined(WIN3264) && defined(FEAT_MBYTE)) \
+	|| defined(GLOBAL_IME) \
+	|| defined(PROTO)
+# ifdef PROTO
+typedef int WINAPI;
+# endif
+
+    LRESULT WINAPI
+vim_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+# ifdef GLOBAL_IME
+    return global_ime_DefWindowProc(hwnd, message, wParam, lParam);
+# else
+    if (wide_WindowProc)
+	return DefWindowProcW(hwnd, message, wParam, lParam);
+    return DefWindowProc(hwnd, message, wParam, lParam);
+#endif
+}
+#endif
+
+/*
+ * Called when the foreground or background color has been changed.
+ */
+    void
+gui_mch_new_colors(void)
+{
+    /* nothing to do? */
+}
+
+/*
+ * Set the colors to their default values.
+ */
+    void
+gui_mch_def_colors(void)
+{
+    gui.norm_pixel = GetSysColor(COLOR_WINDOWTEXT);
+    gui.back_pixel = GetSysColor(COLOR_WINDOW);
+    gui.def_norm_pixel = gui.norm_pixel;
+    gui.def_back_pixel = gui.back_pixel;
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+    int
+gui_mch_open(void)
+{
+#ifndef SW_SHOWDEFAULT
+# define SW_SHOWDEFAULT 10	/* Borland 5.0 doesn't have it */
+#endif
+    /* Actually open the window, if not already visible
+     * (may be done already in gui_mch_set_shellsize) */
+    if (!IsWindowVisible(s_hwnd))
+	ShowWindow(s_hwnd, SW_SHOWDEFAULT);
+
+#ifdef MSWIN_FIND_REPLACE
+    /* Init replace string here, so that we keep it when re-opening the
+     * dialog. */
+    s_findrep_struct.lpstrReplaceWith[0] = NUL;
+#endif
+
+    return OK;
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+    int
+gui_mch_get_winpos(int *x, int *y)
+{
+    RECT    rect;
+
+    GetWindowRect(s_hwnd, &rect);
+    *x = rect.left;
+    *y = rect.top;
+    return OK;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+    void
+gui_mch_set_winpos(int x, int y)
+{
+    SetWindowPos(s_hwnd, NULL, x, y, 0, 0,
+		 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+}
+    void
+gui_mch_set_text_area_pos(int x, int y, int w, int h)
+{
+    static int oldx = 0;
+    static int oldy = 0;
+
+    SetWindowPos(s_textArea, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE);
+
+#ifdef FEAT_TOOLBAR
+    if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
+	SendMessage(s_toolbarhwnd, WM_SIZE,
+	      (WPARAM)0, (LPARAM)(w + ((long)(TOOLBAR_BUTTON_HEIGHT+8)<<16)));
+#endif
+#if defined(FEAT_GUI_TABLINE)
+    if (showing_tabline)
+    {
+	int	top = 0;
+	RECT	rect;
+
+# ifdef FEAT_TOOLBAR
+	if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
+	    top = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
+# endif
+	GetClientRect(s_hwnd, &rect);
+	MoveWindow(s_tabhwnd, 0, top, rect.right, gui.tabline_height, TRUE);
+    }
+#endif
+
+    /* When side scroll bar is unshown, the size of window will change.
+     * then, the text area move left or right. thus client rect should be
+     * forcedly redrawn. (Yasuhiro Matsumoto) */
+    if (oldx != x || oldy != y)
+    {
+	InvalidateRect(s_hwnd, NULL, FALSE);
+	oldx = x;
+	oldy = y;
+    }
+}
+
+
+/*
+ * Scrollbar stuff:
+ */
+
+    void
+gui_mch_enable_scrollbar(
+    scrollbar_T     *sb,
+    int		    flag)
+{
+    ShowScrollBar(sb->id, SB_CTL, flag);
+
+    /* TODO: When the window is maximized, the size of the window stays the
+     * same, thus the size of the text area changes.  On Win98 it's OK, on Win
+     * NT 4.0 it's not... */
+}
+
+    void
+gui_mch_set_scrollbar_pos(
+    scrollbar_T *sb,
+    int		x,
+    int		y,
+    int		w,
+    int		h)
+{
+    SetWindowPos(sb->id, NULL, x, y, w, h,
+			      SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
+}
+
+    void
+gui_mch_create_scrollbar(
+    scrollbar_T *sb,
+    int		orient)	/* SBAR_VERT or SBAR_HORIZ */
+{
+    sb->id = CreateWindow(
+	"SCROLLBAR", "Scrollbar",
+	WS_CHILD | ((orient == SBAR_VERT) ? SBS_VERT : SBS_HORZ), 0, 0,
+	10,				/* Any value will do for now */
+	10,				/* Any value will do for now */
+	s_hwnd, NULL,
+	s_hinst, NULL);
+}
+
+/*
+ * Find the scrollbar with the given hwnd.
+ */
+	 static scrollbar_T *
+gui_mswin_find_scrollbar(HWND hwnd)
+{
+    win_T	*wp;
+
+    if (gui.bottom_sbar.id == hwnd)
+	return &gui.bottom_sbar;
+    FOR_ALL_WINDOWS(wp)
+    {
+	if (wp->w_scrollbars[SBAR_LEFT].id == hwnd)
+	    return &wp->w_scrollbars[SBAR_LEFT];
+	if (wp->w_scrollbars[SBAR_RIGHT].id == hwnd)
+	    return &wp->w_scrollbars[SBAR_RIGHT];
+    }
+    return NULL;
+}
+
+/*
+ * Get the character size of a font.
+ */
+    static void
+GetFontSize(GuiFont font)
+{
+    HWND    hwnd = GetDesktopWindow();
+    HDC	    hdc = GetWindowDC(hwnd);
+    HFONT   hfntOld = SelectFont(hdc, (HFONT)font);
+    TEXTMETRIC tm;
+
+    GetTextMetrics(hdc, &tm);
+    gui.char_width = tm.tmAveCharWidth + tm.tmOverhang;
+
+    gui.char_height = tm.tmHeight + p_linespace;
+
+    SelectFont(hdc, hfntOld);
+
+    ReleaseDC(hwnd, hdc);
+}
+
+/*
+ * Adjust gui.char_height (after 'linespace' was changed).
+ */
+    int
+gui_mch_adjust_charheight(void)
+{
+    GetFontSize(gui.norm_font);
+    return OK;
+}
+
+    static GuiFont
+get_font_handle(LOGFONT *lf)
+{
+    HFONT   font = NULL;
+
+    /* Load the font */
+    font = CreateFontIndirect(lf);
+
+    if (font == NULL)
+	return NOFONT;
+
+    return (GuiFont)font;
+}
+
+    static int
+pixels_to_points(int pixels, int vertical)
+{
+    int		points;
+    HWND	hwnd;
+    HDC		hdc;
+
+    hwnd = GetDesktopWindow();
+    hdc = GetWindowDC(hwnd);
+
+    points = MulDiv(pixels, 72,
+		    GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX));
+
+    ReleaseDC(hwnd, hdc);
+
+    return points;
+}
+
+    GuiFont
+gui_mch_get_font(
+    char_u	*name,
+    int		giveErrorIfMissing)
+{
+    LOGFONT	lf;
+    GuiFont	font = NOFONT;
+
+    if (get_logfont(&lf, name, NULL, giveErrorIfMissing) == OK)
+	font = get_font_handle(&lf);
+    if (font == NOFONT && giveErrorIfMissing)
+	EMSG2(_(e_font), name);
+    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.
+ */
+/*ARGSUSED*/
+    char_u *
+gui_mch_get_fontname(GuiFont font, char_u *name)
+{
+    if (name == NULL)
+	return NULL;
+    return vim_strsave(name);
+}
+#endif
+
+    void
+gui_mch_free_font(GuiFont font)
+{
+    if (font)
+	DeleteObject((HFONT)font);
+}
+
+    static int
+hex_digit(int c)
+{
+    if (VIM_ISDIGIT(c))
+	return c - '0';
+    c = TOLOWER_ASC(c);
+    if (c >= 'a' && c <= 'f')
+	return c - 'a' + 10;
+    return -1000;
+}
+/*
+ * Return the Pixel value (color) for the given color name.
+ * Return INVALCOLOR for error.
+ */
+    guicolor_T
+gui_mch_get_color(char_u *name)
+{
+    typedef struct guicolor_tTable
+    {
+	char	    *name;
+	COLORREF    color;
+    } guicolor_tTable;
+
+    static guicolor_tTable table[] =
+    {
+	{"Black",		RGB(0x00, 0x00, 0x00)},
+	{"DarkGray",		RGB(0xA9, 0xA9, 0xA9)},
+	{"DarkGrey",		RGB(0xA9, 0xA9, 0xA9)},
+	{"Gray",		RGB(0xC0, 0xC0, 0xC0)},
+	{"Grey",		RGB(0xC0, 0xC0, 0xC0)},
+	{"LightGray",		RGB(0xD3, 0xD3, 0xD3)},
+	{"LightGrey",		RGB(0xD3, 0xD3, 0xD3)},
+	{"Gray10",		RGB(0x1A, 0x1A, 0x1A)},
+	{"Grey10",		RGB(0x1A, 0x1A, 0x1A)},
+	{"Gray20",		RGB(0x33, 0x33, 0x33)},
+	{"Grey20",		RGB(0x33, 0x33, 0x33)},
+	{"Gray30",		RGB(0x4D, 0x4D, 0x4D)},
+	{"Grey30",		RGB(0x4D, 0x4D, 0x4D)},
+	{"Gray40",		RGB(0x66, 0x66, 0x66)},
+	{"Grey40",		RGB(0x66, 0x66, 0x66)},
+	{"Gray50",		RGB(0x7F, 0x7F, 0x7F)},
+	{"Grey50",		RGB(0x7F, 0x7F, 0x7F)},
+	{"Gray60",		RGB(0x99, 0x99, 0x99)},
+	{"Grey60",		RGB(0x99, 0x99, 0x99)},
+	{"Gray70",		RGB(0xB3, 0xB3, 0xB3)},
+	{"Grey70",		RGB(0xB3, 0xB3, 0xB3)},
+	{"Gray80",		RGB(0xCC, 0xCC, 0xCC)},
+	{"Grey80",		RGB(0xCC, 0xCC, 0xCC)},
+	{"Gray90",		RGB(0xE5, 0xE5, 0xE5)},
+	{"Grey90",		RGB(0xE5, 0xE5, 0xE5)},
+	{"White",		RGB(0xFF, 0xFF, 0xFF)},
+	{"DarkRed",		RGB(0x80, 0x00, 0x00)},
+	{"Red",			RGB(0xFF, 0x00, 0x00)},
+	{"LightRed",		RGB(0xFF, 0xA0, 0xA0)},
+	{"DarkBlue",		RGB(0x00, 0x00, 0x80)},
+	{"Blue",		RGB(0x00, 0x00, 0xFF)},
+	{"LightBlue",		RGB(0xAD, 0xD8, 0xE6)},
+	{"DarkGreen",		RGB(0x00, 0x80, 0x00)},
+	{"Green",		RGB(0x00, 0xFF, 0x00)},
+	{"LightGreen",		RGB(0x90, 0xEE, 0x90)},
+	{"DarkCyan",		RGB(0x00, 0x80, 0x80)},
+	{"Cyan",		RGB(0x00, 0xFF, 0xFF)},
+	{"LightCyan",		RGB(0xE0, 0xFF, 0xFF)},
+	{"DarkMagenta",		RGB(0x80, 0x00, 0x80)},
+	{"Magenta",		RGB(0xFF, 0x00, 0xFF)},
+	{"LightMagenta",	RGB(0xFF, 0xA0, 0xFF)},
+	{"Brown",		RGB(0x80, 0x40, 0x40)},
+	{"Yellow",		RGB(0xFF, 0xFF, 0x00)},
+	{"LightYellow",		RGB(0xFF, 0xFF, 0xE0)},
+	{"DarkYellow",		RGB(0xBB, 0xBB, 0x00)},
+	{"SeaGreen",		RGB(0x2E, 0x8B, 0x57)},
+	{"Orange",		RGB(0xFF, 0xA5, 0x00)},
+	{"Purple",		RGB(0xA0, 0x20, 0xF0)},
+	{"SlateBlue",		RGB(0x6A, 0x5A, 0xCD)},
+	{"Violet",		RGB(0xEE, 0x82, 0xEE)},
+    };
+
+    typedef struct SysColorTable
+    {
+	char	    *name;
+	int	    color;
+    } SysColorTable;
+
+    static SysColorTable sys_table[] =
+    {
+#ifdef WIN3264
+	{"SYS_3DDKSHADOW", COLOR_3DDKSHADOW},
+	{"SYS_3DHILIGHT", COLOR_3DHILIGHT},
+#ifndef __MINGW32__
+	{"SYS_3DHIGHLIGHT", COLOR_3DHIGHLIGHT},
+#endif
+	{"SYS_BTNHILIGHT", COLOR_BTNHILIGHT},
+	{"SYS_BTNHIGHLIGHT", COLOR_BTNHIGHLIGHT},
+	{"SYS_3DLIGHT", COLOR_3DLIGHT},
+	{"SYS_3DSHADOW", COLOR_3DSHADOW},
+	{"SYS_DESKTOP", COLOR_DESKTOP},
+	{"SYS_INFOBK", COLOR_INFOBK},
+	{"SYS_INFOTEXT", COLOR_INFOTEXT},
+	{"SYS_3DFACE", COLOR_3DFACE},
+#endif
+	{"SYS_BTNFACE", COLOR_BTNFACE},
+	{"SYS_BTNSHADOW", COLOR_BTNSHADOW},
+	{"SYS_ACTIVEBORDER", COLOR_ACTIVEBORDER},
+	{"SYS_ACTIVECAPTION", COLOR_ACTIVECAPTION},
+	{"SYS_APPWORKSPACE", COLOR_APPWORKSPACE},
+	{"SYS_BACKGROUND", COLOR_BACKGROUND},
+	{"SYS_BTNTEXT", COLOR_BTNTEXT},
+	{"SYS_CAPTIONTEXT", COLOR_CAPTIONTEXT},
+	{"SYS_GRAYTEXT", COLOR_GRAYTEXT},
+	{"SYS_HIGHLIGHT", COLOR_HIGHLIGHT},
+	{"SYS_HIGHLIGHTTEXT", COLOR_HIGHLIGHTTEXT},
+	{"SYS_INACTIVEBORDER", COLOR_INACTIVEBORDER},
+	{"SYS_INACTIVECAPTION", COLOR_INACTIVECAPTION},
+	{"SYS_INACTIVECAPTIONTEXT", COLOR_INACTIVECAPTIONTEXT},
+	{"SYS_MENU", COLOR_MENU},
+	{"SYS_MENUTEXT", COLOR_MENUTEXT},
+	{"SYS_SCROLLBAR", COLOR_SCROLLBAR},
+	{"SYS_WINDOW", COLOR_WINDOW},
+	{"SYS_WINDOWFRAME", COLOR_WINDOWFRAME},
+	{"SYS_WINDOWTEXT", COLOR_WINDOWTEXT}
+    };
+
+    int		    r, g, b;
+    int		    i;
+
+    if (name[0] == '#' && STRLEN(name) == 7)
+    {
+	/* Name is in "#rrggbb" format */
+	r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
+	g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
+	b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
+	if (r < 0 || g < 0 || b < 0)
+	    return INVALCOLOR;
+	return RGB(r, g, b);
+    }
+    else
+    {
+	/* Check if the name is one of the colors we know */
+	for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
+	    if (STRICMP(name, table[i].name) == 0)
+		return table[i].color;
+    }
+
+    /*
+     * Try to look up a system colour.
+     */
+    for (i = 0; i < sizeof(sys_table) / sizeof(sys_table[0]); i++)
+	if (STRICMP(name, sys_table[i].name) == 0)
+	    return GetSysColor(sys_table[i].color);
+
+    /*
+     * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
+     */
+    {
+#define LINE_LEN 100
+	FILE	*fd;
+	char	line[LINE_LEN];
+	char_u	*fname;
+
+	fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
+	if (fname == NULL)
+	    return INVALCOLOR;
+
+	fd = mch_fopen((char *)fname, "rt");
+	vim_free(fname);
+	if (fd == NULL)
+	    return INVALCOLOR;
+
+	while (!feof(fd))
+	{
+	    int	    len;
+	    int	    pos;
+	    char    *color;
+
+	    fgets(line, LINE_LEN, fd);
+	    len = (int)STRLEN(line);
+
+	    if (len <= 1 || line[len-1] != '\n')
+		continue;
+
+	    line[len-1] = '\0';
+
+	    i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
+	    if (i != 3)
+		continue;
+
+	    color = line + pos;
+
+	    if (STRICMP(color, name) == 0)
+	    {
+		fclose(fd);
+		return (guicolor_T) RGB(r, g, b);
+	    }
+	}
+
+	fclose(fd);
+    }
+
+    return INVALCOLOR;
+}
+/*
+ * Return OK if the key with the termcap name "name" is supported.
+ */
+    int
+gui_mch_haskey(char_u *name)
+{
+    int i;
+
+    for (i = 0; special_keys[i].vim_code1 != NUL; i++)
+	if (name[0] == special_keys[i].vim_code0 &&
+					 name[1] == special_keys[i].vim_code1)
+	    return OK;
+    return FAIL;
+}
+
+    void
+gui_mch_beep(void)
+{
+    MessageBeep(MB_OK);
+}
+/*
+ * Invert a rectangle from row r, column c, for nr rows and nc columns.
+ */
+    void
+gui_mch_invert_rectangle(
+    int	    r,
+    int	    c,
+    int	    nr,
+    int	    nc)
+{
+    RECT    rc;
+
+    /*
+     * Note: InvertRect() excludes right and bottom of rectangle.
+     */
+    rc.left = FILL_X(c);
+    rc.top = FILL_Y(r);
+    rc.right = rc.left + nc * gui.char_width;
+    rc.bottom = rc.top + nr * gui.char_height;
+    InvertRect(s_hdc, &rc);
+}
+
+/*
+ * Iconify the GUI window.
+ */
+    void
+gui_mch_iconify(void)
+{
+    ShowWindow(s_hwnd, SW_MINIMIZE);
+}
+
+/*
+ * Draw a cursor without focus.
+ */
+    void
+gui_mch_draw_hollow_cursor(guicolor_T color)
+{
+    HBRUSH  hbr;
+    RECT    rc;
+
+    /*
+     * Note: FrameRect() excludes right and bottom of rectangle.
+     */
+    rc.left = FILL_X(gui.col);
+    rc.top = FILL_Y(gui.row);
+    rc.right = rc.left + gui.char_width;
+#ifdef FEAT_MBYTE
+    if (mb_lefthalve(gui.row, gui.col))
+	rc.right += gui.char_width;
+#endif
+    rc.bottom = rc.top + gui.char_height;
+    hbr = CreateSolidBrush(color);
+    FrameRect(s_hdc, &rc, hbr);
+    DeleteBrush(hbr);
+}
+/*
+ * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
+ * color "color".
+ */
+    void
+gui_mch_draw_part_cursor(
+    int		w,
+    int		h,
+    guicolor_T	color)
+{
+    HBRUSH	hbr;
+    RECT	rc;
+
+    /*
+     * Note: FillRect() excludes right and bottom of rectangle.
+     */
+    rc.left =
+#ifdef FEAT_RIGHTLEFT
+		/* vertical line should be on the right of current point */
+		CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+#endif
+		    FILL_X(gui.col);
+    rc.top = FILL_Y(gui.row) + gui.char_height - h;
+    rc.right = rc.left + w;
+    rc.bottom = rc.top + h;
+    hbr = CreateSolidBrush(color);
+    FillRect(s_hdc, &rc, hbr);
+    DeleteBrush(hbr);
+}
+
+
+/*
+ * Generates a VK_SPACE when the internal dead_key flag is set to output the
+ * dead key's nominal character and re-post the original message.
+ */
+    static void
+outputDeadKey_rePost(MSG originalMsg)
+{
+    static MSG deadCharExpel;
+
+    if (!dead_key)
+	return;
+
+    dead_key = 0;
+
+    /* Make Windows generate the dead key's character */
+    deadCharExpel.message = originalMsg.message;
+    deadCharExpel.hwnd    = originalMsg.hwnd;
+    deadCharExpel.wParam  = VK_SPACE;
+
+    MyTranslateMessage(&deadCharExpel);
+
+    /* re-generate the current character free of the dead char influence */
+    PostMessage(originalMsg.hwnd, originalMsg.message, originalMsg.wParam,
+							  originalMsg.lParam);
+}
+
+
+/*
+ * Process a single Windows message.
+ * If one is not available we hang until one is.
+ */
+    static void
+process_message(void)
+{
+    MSG		msg;
+    UINT	vk = 0;		/* Virtual key */
+    char_u	string[40];
+    int		i;
+    int		modifiers = 0;
+    int		key;
+#ifdef FEAT_MENU
+    static char_u k10[] = {K_SPECIAL, 'k', ';', 0};
+#endif
+
+    pGetMessage(&msg, NULL, 0, 0);
+
+#ifdef FEAT_OLE
+    /* Look after OLE Automation commands */
+    if (msg.message == WM_OLE)
+    {
+	char_u *str = (char_u *)msg.lParam;
+	if (str == NULL || *str == NUL)
+	{
+	    /* Message can't be ours, forward it.  Fixes problem with Ultramon
+	     * 3.0.4 */
+	    pDispatchMessage(&msg);
+	}
+	else
+	{
+	    add_to_input_buf(str, (int)STRLEN(str));
+	    vim_free(str);  /* was allocated in CVim::SendKeys() */
+	}
+	return;
+    }
+#endif
+
+#ifdef FEAT_CHANNEL
+    if (msg.message == WM_NETBEANS)
+    {
+	int	    what;
+	channel_T   *channel = channel_fd2channel((sock_T)msg.wParam, &what);
+
+	if (channel != NULL)
+	{
+	    /* Disable error messages, they can mess up the display and throw
+	     * an exception. */
+	    ++emsg_off;
+	    channel_read(channel, what, "process_message");
+	    --emsg_off;
+	}
+	return;
+    }
+#endif
+
+#ifdef FEAT_SNIFF
+    if (sniff_request_waiting && want_sniff_request)
+    {
+	static char_u bytes[3] = {CSI, (char_u)KS_EXTRA, (char_u)KE_SNIFF};
+	add_to_input_buf(bytes, 3); /* K_SNIFF */
+	sniff_request_waiting = 0;
+	want_sniff_request = 0;
+	/* request is handled in normal.c */
+    }
+    if (msg.message == WM_USER)
+    {
+	MyTranslateMessage(&msg);
+	pDispatchMessage(&msg);
+	return;
+    }
+#endif
+
+#ifdef MSWIN_FIND_REPLACE
+    /* Don't process messages used by the dialog */
+    if (s_findrep_hwnd != NULL && pIsDialogMessage(s_findrep_hwnd, &msg))
+    {
+	HandleMouseHide(msg.message, msg.lParam);
+	return;
+    }
+#endif
+
+    /*
+     * Check if it's a special key that we recognise.  If not, call
+     * TranslateMessage().
+     */
+    if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
+    {
+	vk = (int) msg.wParam;
+
+	/*
+	 * Handle dead keys in special conditions in other cases we let Windows
+	 * handle them and do not interfere.
+	 *
+	 * The dead_key flag must be reset on several occasions:
+	 * - in _OnChar() (or _OnSysChar()) as any dead key was necessarily
+	 *   consumed at that point (This is when we let Windows combine the
+	 *   dead character on its own)
+	 *
+	 * - Before doing something special such as regenerating keypresses to
+	 *   expel the dead character as this could trigger an infinite loop if
+	 *   for some reason MyTranslateMessage() do not trigger a call
+	 *   immediately to _OnChar() (or _OnSysChar()).
+	 */
+	if (dead_key)
+	{
+	    /*
+	     * If a dead key was pressed and the user presses VK_SPACE,
+	     * VK_BACK, or VK_ESCAPE it means that he actually wants to deal
+	     * with the dead char now, so do nothing special and let Windows
+	     * handle it.
+	     *
+	     * Note that VK_SPACE combines with the dead_key's character and
+	     * only one WM_CHAR will be generated by TranslateMessage(), in
+	     * the two other cases two WM_CHAR will be generated: the dead
+	     * char and VK_BACK or VK_ESCAPE. That is most likely what the
+	     * user expects.
+	     */
+	    if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE))
+	    {
+		dead_key = 0;
+		MyTranslateMessage(&msg);
+		return;
+	    }
+	    /* In modes where we are not typing, dead keys should behave
+	     * normally */
+	    else if (!(get_real_state() & (INSERT | CMDLINE | SELECTMODE)))
+	    {
+		outputDeadKey_rePost(msg);
+		return;
+	    }
+	}
+
+	/* Check for CTRL-BREAK */
+	if (vk == VK_CANCEL)
+	{
+	    trash_input_buf();
+	    got_int = TRUE;
+	    string[0] = Ctrl_C;
+	    add_to_input_buf(string, 1);
+	}
+
+	for (i = 0; special_keys[i].key_sym != 0; i++)
+	{
+	    /* ignore VK_SPACE when ALT key pressed: system menu */
+	    if (special_keys[i].key_sym == vk
+		    && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000)))
+	    {
+		/*
+		 * Behave as exected if we have a dead key and the special key
+		 * is a key that would normally trigger the dead key nominal
+		 * character output (such as a NUMPAD printable character or
+		 * the TAB key, etc...).
+		 */
+		if (dead_key && (special_keys[i].vim_code0 == 'K'
+						|| vk == VK_TAB || vk == CAR))
+		{
+		    outputDeadKey_rePost(msg);
+		    return;
+		}
+
+#ifdef FEAT_MENU
+		/* Check for <F10>: Windows selects the menu.  When <F10> is
+		 * mapped we want to use the mapping instead. */
+		if (vk == VK_F10
+			&& gui.menu_is_active
+			&& check_map(k10, State, FALSE, TRUE, FALSE,
+							  NULL, NULL) == NULL)
+		    break;
+#endif
+		if (GetKeyState(VK_SHIFT) & 0x8000)
+		    modifiers |= MOD_MASK_SHIFT;
+		/*
+		 * Don't use caps-lock as shift, because these are special keys
+		 * being considered here, and we only want letters to get
+		 * shifted -- webb
+		 */
+		/*
+		if (GetKeyState(VK_CAPITAL) & 0x0001)
+		    modifiers ^= MOD_MASK_SHIFT;
+		*/
+		if (GetKeyState(VK_CONTROL) & 0x8000)
+		    modifiers |= MOD_MASK_CTRL;
+		if (GetKeyState(VK_MENU) & 0x8000)
+		    modifiers |= MOD_MASK_ALT;
+
+		if (special_keys[i].vim_code1 == NUL)
+		    key = special_keys[i].vim_code0;
+		else
+		    key = TO_SPECIAL(special_keys[i].vim_code0,
+						   special_keys[i].vim_code1);
+		key = simplify_key(key, &modifiers);
+		if (key == CSI)
+		    key = K_CSI;
+
+		if (modifiers)
+		{
+		    string[0] = CSI;
+		    string[1] = KS_MODIFIER;
+		    string[2] = modifiers;
+		    add_to_input_buf(string, 3);
+		}
+
+		if (IS_SPECIAL(key))
+		{
+		    string[0] = CSI;
+		    string[1] = K_SECOND(key);
+		    string[2] = K_THIRD(key);
+		    add_to_input_buf(string, 3);
+		}
+		else
+		{
+		    int	len;
+
+		    /* Handle "key" as a Unicode character. */
+		    len = char_to_string(key, string, 40, FALSE);
+		    add_to_input_buf(string, len);
+		}
+		break;
+	    }
+	}
+	if (special_keys[i].key_sym == 0)
+	{
+	    /* Some keys need C-S- where they should only need C-.
+	     * Ignore 0xff, Windows XP sends it when NUMLOCK has changed since
+	     * system startup (Helmut Stiegler, 2003 Oct 3). */
+	    if (vk != 0xff
+		    && (GetKeyState(VK_CONTROL) & 0x8000)
+		    && !(GetKeyState(VK_SHIFT) & 0x8000)
+		    && !(GetKeyState(VK_MENU) & 0x8000))
+	    {
+		/* CTRL-6 is '^'; Japanese keyboard maps '^' to vk == 0xDE */
+		if (vk == '6' || MapVirtualKey(vk, 2) == (UINT)'^')
+		{
+		    string[0] = Ctrl_HAT;
+		    add_to_input_buf(string, 1);
+		}
+		/* vk == 0xBD AZERTY for CTRL-'-', but CTRL-[ for * QWERTY! */
+		else if (vk == 0xBD)	/* QWERTY for CTRL-'-' */
+		{
+		    string[0] = Ctrl__;
+		    add_to_input_buf(string, 1);
+		}
+		/* CTRL-2 is '@'; Japanese keyboard maps '@' to vk == 0xC0 */
+		else if (vk == '2' || MapVirtualKey(vk, 2) == (UINT)'@')
+		{
+		    string[0] = Ctrl_AT;
+		    add_to_input_buf(string, 1);
+		}
+		else
+		    MyTranslateMessage(&msg);
+	    }
+	    else
+		MyTranslateMessage(&msg);
+	}
+    }
+#ifdef FEAT_MBYTE_IME
+    else if (msg.message == WM_IME_NOTIFY)
+	_OnImeNotify(msg.hwnd, (DWORD)msg.wParam, (DWORD)msg.lParam);
+    else if (msg.message == WM_KEYUP && im_get_status())
+	/* added for non-MS IME (Yasuhiro Matsumoto) */
+	MyTranslateMessage(&msg);
+#endif
+#if !defined(FEAT_MBYTE_IME) && defined(GLOBAL_IME)
+/* GIME_TEST */
+    else if (msg.message == WM_IME_STARTCOMPOSITION)
+    {
+	POINT point;
+
+	global_ime_set_font(&norm_logfont);
+	point.x = FILL_X(gui.col);
+	point.y = FILL_Y(gui.row);
+	MapWindowPoints(s_textArea, s_hwnd, &point, 1);
+	global_ime_set_position(&point);
+    }
+#endif
+
+#ifdef FEAT_MENU
+    /* Check for <F10>: Default effect is to select the menu.  When <F10> is
+     * mapped we need to stop it here to avoid strange effects (e.g., for the
+     * key-up event) */
+    if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE,
+							  NULL, NULL) == NULL)
+#endif
+	pDispatchMessage(&msg);
+}
+
+/*
+ * Catch up with any queued events.  This may put keyboard input into the
+ * input buffer, call resize call-backs, trigger timers etc.  If there is
+ * nothing in the event queue (& no timers pending), then we return
+ * immediately.
+ */
+    void
+gui_mch_update(void)
+{
+    MSG	    msg;
+
+    if (!s_busy_processing)
+	while (pPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
+						  && !vim_is_input_buf_full())
+	    process_message();
+}
+
+/*
+ * GUI input routine called by gui_wait_for_chars().  Waits for a character
+ * from the keyboard.
+ *  wtime == -1	    Wait forever.
+ *  wtime == 0	    This should never happen.
+ *  wtime > 0	    Wait wtime milliseconds for a character.
+ * Returns OK if a character was found to be available within the given time,
+ * or FAIL otherwise.
+ */
+    int
+gui_mch_wait_for_chars(int wtime)
+{
+    MSG		msg;
+    int		focus;
+
+    s_timed_out = FALSE;
+
+    if (wtime > 0)
+    {
+	/* Don't do anything while processing a (scroll) message. */
+	if (s_busy_processing)
+	    return FAIL;
+	s_wait_timer = (UINT)SetTimer(NULL, 0, (UINT)wtime,
+							 (TIMERPROC)_OnTimer);
+    }
+
+    allow_scrollbar = TRUE;
+
+    focus = gui.in_focus;
+    while (!s_timed_out)
+    {
+	/* Stop or start blinking when focus changes */
+	if (gui.in_focus != focus)
+	{
+	    if (gui.in_focus)
+		gui_mch_start_blink();
+	    else
+		gui_mch_stop_blink();
+	    focus = gui.in_focus;
+	}
+
+	if (s_need_activate)
+	{
+#ifdef WIN32
+	    (void)SetForegroundWindow(s_hwnd);
+#else
+	    (void)SetActiveWindow(s_hwnd);
+#endif
+	    s_need_activate = FALSE;
+	}
+
+#ifdef MESSAGE_QUEUE
+	parse_queued_messages();
+#endif
+
+#ifdef FEAT_CHANNEL
+	channel_handle_events();
+#endif
+
+	/*
+	 * Don't use gui_mch_update() because then we will spin-lock until a
+	 * char arrives, instead we use GetMessage() to hang until an
+	 * event arrives.  No need to check for input_buf_full because we are
+	 * returning as soon as it contains a single char -- webb
+	 */
+	process_message();
+
+	if (input_available())
+	{
+	    if (s_wait_timer != 0 && !s_timed_out)
+	    {
+		KillTimer(NULL, s_wait_timer);
+
+		/* Eat spurious WM_TIMER messages */
+		while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
+		    ;
+		s_wait_timer = 0;
+	    }
+	    allow_scrollbar = FALSE;
+
+	    /* Clear pending mouse button, the release event may have been
+	     * taken by the dialog window.  But don't do this when getting
+	     * focus, we need the mouse-up event then. */
+	    if (!s_getting_focus)
+		s_button_pending = -1;
+
+	    return OK;
+	}
+    }
+    allow_scrollbar = FALSE;
+    return FAIL;
+}
+
+/*
+ * Clear a rectangular region of the screen from text pos (row1, col1) to
+ * (row2, col2) inclusive.
+ */
+    void
+gui_mch_clear_block(
+    int		row1,
+    int		col1,
+    int		row2,
+    int		col2)
+{
+    RECT	rc;
+
+    /*
+     * Clear one extra pixel at the far right, for when bold characters have
+     * spilled over to the window border.
+     * Note: FillRect() excludes right and bottom of rectangle.
+     */
+    rc.left = FILL_X(col1);
+    rc.top = FILL_Y(row1);
+    rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
+    rc.bottom = FILL_Y(row2 + 1);
+    clear_rect(&rc);
+}
+
+/*
+ * Clear the whole text window.
+ */
+    void
+gui_mch_clear_all(void)
+{
+    RECT    rc;
+
+    rc.left = 0;
+    rc.top = 0;
+    rc.right = Columns * gui.char_width + 2 * gui.border_width;
+    rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
+    clear_rect(&rc);
+}
+/*
+ * Menu stuff.
+ */
+
+    void
+gui_mch_enable_menu(int flag)
+{
+#ifdef FEAT_MENU
+    SetMenu(s_hwnd, flag ? s_menuBar : NULL);
+#endif
+}
+
+/*ARGSUSED*/
+    void
+gui_mch_set_menu_pos(
+    int	    x,
+    int	    y,
+    int	    w,
+    int	    h)
+{
+    /* It will be in the right place anyway */
+}
+
+#if defined(FEAT_MENU) || defined(PROTO)
+/*
+ * Make menu item hidden or not hidden
+ */
+    void
+gui_mch_menu_hidden(
+    vimmenu_T	*menu,
+    int		hidden)
+{
+    /*
+     * This doesn't do what we want.  Hmm, just grey the menu items for now.
+     */
+    /*
+    if (hidden)
+	EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_DISABLED);
+    else
+	EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED);
+    */
+    gui_mch_menu_grey(menu, hidden);
+}
+
+/*
+ * This is called after setting all the menus to grey/hidden or not.
+ */
+    void
+gui_mch_draw_menubar(void)
+{
+    DrawMenuBar(s_hwnd);
+}
+#endif /*FEAT_MENU*/
+
+#ifndef PROTO
+void
+#ifdef VIMDLL
+_export
+#endif
+_cdecl
+SaveInst(HINSTANCE hInst)
+{
+    s_hinst = hInst;
+}
+#endif
+
+/*
+ * Return the RGB value of a pixel as a long.
+ */
+    long_u
+gui_mch_get_rgb(guicolor_T pixel)
+{
+    return (GetRValue(pixel) << 16) + (GetGValue(pixel) << 8)
+							   + GetBValue(pixel);
+}
+
+#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
+/* Convert pixels in X to dialog units */
+    static WORD
+PixelToDialogX(int numPixels)
+{
+    return (WORD)((numPixels * 4) / s_dlgfntwidth);
+}
+
+/* Convert pixels in Y to dialog units */
+    static WORD
+PixelToDialogY(int numPixels)
+{
+    return (WORD)((numPixels * 8) / s_dlgfntheight);
+}
+
+/* Return the width in pixels of the given text in the given DC. */
+    static int
+GetTextWidth(HDC hdc, char_u *str, int len)
+{
+    SIZE    size;
+
+    GetTextExtentPoint(hdc, (LPCSTR)str, len, &size);
+    return size.cx;
+}
+
+#ifdef FEAT_MBYTE
+/*
+ * Return the width in pixels of the given text in the given DC, taking care
+ * of 'encoding' to active codepage conversion.
+ */
+    static int
+GetTextWidthEnc(HDC hdc, char_u *str, int len)
+{
+    SIZE	size;
+    WCHAR	*wstr;
+    int		n;
+    int		wlen = len;
+
+    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+    {
+	/* 'encoding' differs from active codepage: convert text and use wide
+	 * function */
+	wstr = enc_to_utf16(str, &wlen);
+	if (wstr != NULL)
+	{
+	    n = GetTextExtentPointW(hdc, wstr, wlen, &size);
+	    vim_free(wstr);
+	    if (n)
+		return size.cx;
+	}
+    }
+
+    return GetTextWidth(hdc, str, len);
+}
+#else
+# define GetTextWidthEnc(h, s, l) GetTextWidth((h), (s), (l))
+#endif
+
+/*
+ * A quick little routine that will center one window over another, handy for
+ * dialog boxes.  Taken from the Win32SDK samples.
+ */
+    static BOOL
+CenterWindow(
+    HWND hwndChild,
+    HWND hwndParent)
+{
+    RECT    rChild, rParent;
+    int     wChild, hChild, wParent, hParent;
+    int     wScreen, hScreen, xNew, yNew;
+    HDC     hdc;
+
+    GetWindowRect(hwndChild, &rChild);
+    wChild = rChild.right - rChild.left;
+    hChild = rChild.bottom - rChild.top;
+
+    /* If Vim is minimized put the window in the middle of the screen. */
+    if (hwndParent == NULL || IsMinimized(hwndParent))
+	SystemParametersInfo(SPI_GETWORKAREA, 0, &rParent, 0);
+    else
+	GetWindowRect(hwndParent, &rParent);
+    wParent = rParent.right - rParent.left;
+    hParent = rParent.bottom - rParent.top;
+
+    hdc = GetDC(hwndChild);
+    wScreen = GetDeviceCaps (hdc, HORZRES);
+    hScreen = GetDeviceCaps (hdc, VERTRES);
+    ReleaseDC(hwndChild, hdc);
+
+    xNew = rParent.left + ((wParent - wChild) /2);
+    if (xNew < 0)
+    {
+	xNew = 0;
+    }
+    else if ((xNew+wChild) > wScreen)
+    {
+	xNew = wScreen - wChild;
+    }
+
+    yNew = rParent.top	+ ((hParent - hChild) /2);
+    if (yNew < 0)
+	yNew = 0;
+    else if ((yNew+hChild) > hScreen)
+	yNew = hScreen - hChild;
+
+    return SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0,
+						   SWP_NOSIZE | SWP_NOZORDER);
+}
+#endif /* FEAT_GUI_DIALOG */
+
+void
+gui_mch_activate_window(void)
+{
+    (void)SetActiveWindow(s_hwnd);
+}
+
+#if defined(FEAT_TOOLBAR) || defined(PROTO)
+    void
+gui_mch_show_toolbar(int showit)
+{
+    if (s_toolbarhwnd == NULL)
+	return;
+
+    if (showit)
+    {
+# ifdef FEAT_MBYTE
+#  ifndef TB_SETUNICODEFORMAT
+    /* For older compilers.  We assume this never changes. */
+#   define TB_SETUNICODEFORMAT 0x2005
+#  endif
+	/* Enable/disable unicode support */
+	int uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage);
+	SendMessage(s_toolbarhwnd, TB_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0);
+# endif
+	ShowWindow(s_toolbarhwnd, SW_SHOW);
+    }
+    else
+	ShowWindow(s_toolbarhwnd, SW_HIDE);
+}
+
+/* Then number of bitmaps is fixed.  Exit is missing! */
+#define TOOLBAR_BITMAP_COUNT 31
+
+#endif
+
+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
+    static void
+add_tabline_popup_menu_entry(HMENU pmenu, UINT item_id, char_u *item_text)
+{
+#ifdef FEAT_MBYTE
+    WCHAR	*wn = NULL;
+    int		n;
+
+    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+    {
+	/* 'encoding' differs from active codepage: convert menu name
+	 * and use wide function */
+	wn = enc_to_utf16(item_text, NULL);
+	if (wn != NULL)
+	{
+	    MENUITEMINFOW	infow;
+
+	    infow.cbSize = sizeof(infow);
+	    infow.fMask = MIIM_TYPE | MIIM_ID;
+	    infow.wID = item_id;
+	    infow.fType = MFT_STRING;
+	    infow.dwTypeData = wn;
+	    infow.cch = (UINT)wcslen(wn);
+	    n = InsertMenuItemW(pmenu, item_id, FALSE, &infow);
+	    vim_free(wn);
+	    if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+		/* Failed, try using non-wide function. */
+		wn = NULL;
+	}
+    }
+
+    if (wn == NULL)
+#endif
+    {
+	MENUITEMINFO	info;
+
+	info.cbSize = sizeof(info);
+	info.fMask = MIIM_TYPE | MIIM_ID;
+	info.wID = item_id;
+	info.fType = MFT_STRING;
+	info.dwTypeData = (LPTSTR)item_text;
+	info.cch = (UINT)STRLEN(item_text);
+	InsertMenuItem(pmenu, item_id, FALSE, &info);
+    }
+}
+
+    static void
+show_tabline_popup_menu(void)
+{
+    HMENU	    tab_pmenu;
+    long	    rval;
+    POINT	    pt;
+
+    /* When ignoring events don't show the menu. */
+    if (hold_gui_events
+# ifdef FEAT_CMDWIN
+	    || cmdwin_type != 0
+# endif
+       )
+	return;
+
+    tab_pmenu = CreatePopupMenu();
+    if (tab_pmenu == NULL)
+	return;
+
+    if (first_tabpage->tp_next != NULL)
+	add_tabline_popup_menu_entry(tab_pmenu,
+				TABLINE_MENU_CLOSE, (char_u *)_("Close tab"));
+    add_tabline_popup_menu_entry(tab_pmenu,
+				TABLINE_MENU_NEW, (char_u *)_("New tab"));
+    add_tabline_popup_menu_entry(tab_pmenu,
+				TABLINE_MENU_OPEN, (char_u *)_("Open tab..."));
+
+    GetCursorPos(&pt);
+    rval = TrackPopupMenuEx(tab_pmenu, TPM_RETURNCMD, pt.x, pt.y, s_tabhwnd,
+									NULL);
+
+    DestroyMenu(tab_pmenu);
+
+    /* Add the string cmd into input buffer */
+    if (rval > 0)
+    {
+	TCHITTESTINFO htinfo;
+	int idx;
+
+	if (ScreenToClient(s_tabhwnd, &pt) == 0)
+	    return;
+
+	htinfo.pt.x = pt.x;
+	htinfo.pt.y = pt.y;
+	idx = TabCtrl_HitTest(s_tabhwnd, &htinfo);
+	if (idx == -1)
+	    idx = 0;
+	else
+	    idx += 1;
+
+	send_tabline_menu_event(idx, (int)rval);
+    }
+}
+
+/*
+ * Show or hide the tabline.
+ */
+    void
+gui_mch_show_tabline(int showit)
+{
+    if (s_tabhwnd == NULL)
+	return;
+
+    if (!showit != !showing_tabline)
+    {
+	if (showit)
+	    ShowWindow(s_tabhwnd, SW_SHOW);
+	else
+	    ShowWindow(s_tabhwnd, SW_HIDE);
+	showing_tabline = showit;
+    }
+}
+
+/*
+ * Return TRUE when tabline is displayed.
+ */
+    int
+gui_mch_showing_tabline(void)
+{
+    return s_tabhwnd != NULL && showing_tabline;
+}
+
+/*
+ * Update the labels of the tabline.
+ */
+    void
+gui_mch_update_tabline(void)
+{
+    tabpage_T	*tp;
+    TCITEM	tie;
+    int		nr = 0;
+    int		curtabidx = 0;
+    int		tabadded = 0;
+#ifdef FEAT_MBYTE
+    static int	use_unicode = FALSE;
+    int		uu;
+    WCHAR	*wstr = NULL;
+#endif
+
+    if (s_tabhwnd == NULL)
+	return;
+
+#if defined(FEAT_MBYTE)
+# ifndef CCM_SETUNICODEFORMAT
+    /* For older compilers.  We assume this never changes. */
+#  define CCM_SETUNICODEFORMAT 0x2005
+# endif
+    uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage);
+    if (uu != use_unicode)
+    {
+	/* Enable/disable unicode support */
+	SendMessage(s_tabhwnd, CCM_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0);
+	use_unicode = uu;
+    }
+#endif
+
+    tie.mask = TCIF_TEXT;
+    tie.iImage = -1;
+
+    /* Disable redraw for tab updates to eliminate O(N^2) draws. */
+    SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)FALSE, 0);
+
+    /* Add a label for each tab page.  They all contain the same text area. */
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
+    {
+	if (tp == curtab)
+	    curtabidx = nr;
+
+	if (nr >= TabCtrl_GetItemCount(s_tabhwnd))
+	{
+	    /* Add the tab */
+	    tie.pszText = "-Empty-";
+	    TabCtrl_InsertItem(s_tabhwnd, nr, &tie);
+	    tabadded = 1;
+	}
+
+	get_tabline_label(tp, FALSE);
+	tie.pszText = (LPSTR)NameBuff;
+#ifdef FEAT_MBYTE
+	wstr = NULL;
+	if (use_unicode)
+	{
+	    /* Need to go through Unicode. */
+	    wstr = enc_to_utf16(NameBuff, NULL);
+	    if (wstr != NULL)
+	    {
+		TCITEMW		tiw;
+
+		tiw.mask = TCIF_TEXT;
+		tiw.iImage = -1;
+		tiw.pszText = wstr;
+		SendMessage(s_tabhwnd, TCM_SETITEMW, (WPARAM)nr, (LPARAM)&tiw);
+		vim_free(wstr);
+	    }
+	}
+	if (wstr == NULL)
+#endif
+	{
+	    TabCtrl_SetItem(s_tabhwnd, nr, &tie);
+	}
+    }
+
+    /* Remove any old labels. */
+    while (nr < TabCtrl_GetItemCount(s_tabhwnd))
+	TabCtrl_DeleteItem(s_tabhwnd, nr);
+
+    if (!tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx)
+	TabCtrl_SetCurSel(s_tabhwnd, curtabidx);
+
+    /* Re-enable redraw and redraw. */
+    SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)TRUE, 0);
+    RedrawWindow(s_tabhwnd, NULL, NULL,
+		    RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
+
+    if (tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx)
+	TabCtrl_SetCurSel(s_tabhwnd, curtabidx);
+}
+
+/*
+ * Set the current tab to "nr".  First tab is 1.
+ */
+    void
+gui_mch_set_curtab(int nr)
+{
+    if (s_tabhwnd == NULL)
+	return;
+
+    if (TabCtrl_GetCurSel(s_tabhwnd) != nr - 1)
+	TabCtrl_SetCurSel(s_tabhwnd, nr - 1);
+}
+
+#endif
+
+/*
+ * ":simalt" command.
+ */
+    void
+ex_simalt(exarg_T *eap)
+{
+    char_u *keys = eap->arg;
+
+    PostMessage(s_hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)0);
+    while (*keys)
+    {
+	if (*keys == '~')
+	    *keys = ' ';	    /* for showing system menu */
+	PostMessage(s_hwnd, WM_CHAR, (WPARAM)*keys, (LPARAM)0);
+	keys++;
+    }
+}
+
+/*
+ * Create the find & replace dialogs.
+ * You can't have both at once: ":find" when replace is showing, destroys
+ * the replace dialog first, and the other way around.
+ */
+#ifdef MSWIN_FIND_REPLACE
+    static void
+initialise_findrep(char_u *initial_string)
+{
+    int		wword = FALSE;
+    int		mcase = !p_ic;
+    char_u	*entry_text;
+
+    /* Get the search string to use. */
+    entry_text = get_find_dialog_text(initial_string, &wword, &mcase);
+
+    s_findrep_struct.hwndOwner = s_hwnd;
+    s_findrep_struct.Flags = FR_DOWN;
+    if (mcase)
+	s_findrep_struct.Flags |= FR_MATCHCASE;
+    if (wword)
+	s_findrep_struct.Flags |= FR_WHOLEWORD;
+    if (entry_text != NULL && *entry_text != NUL)
+	vim_strncpy((char_u *)s_findrep_struct.lpstrFindWhat, entry_text,
+					   s_findrep_struct.wFindWhatLen - 1);
+    vim_free(entry_text);
+}
+#endif
+
+    static void
+set_window_title(HWND hwnd, char *title)
+{
+#ifdef FEAT_MBYTE
+    if (title != NULL && enc_codepage >= 0 && enc_codepage != (int)GetACP())
+    {
+	WCHAR	*wbuf;
+	int	n;
+
+	/* Convert the title from 'encoding' to UTF-16. */
+	wbuf = (WCHAR *)enc_to_utf16((char_u *)title, NULL);
+	if (wbuf != NULL)
+	{
+	    n = SetWindowTextW(hwnd, wbuf);
+	    vim_free(wbuf);
+	    if (n != 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+		return;
+	    /* Retry with non-wide function (for Windows 98). */
+	}
+    }
+#endif
+    (void)SetWindowText(hwnd, (LPCSTR)title);
+}
+
+    void
+gui_mch_find_dialog(exarg_T *eap)
+{
+#ifdef MSWIN_FIND_REPLACE
+    if (s_findrep_msg != 0)
+    {
+	if (IsWindow(s_findrep_hwnd) && !s_findrep_is_find)
+	    DestroyWindow(s_findrep_hwnd);
+
+	if (!IsWindow(s_findrep_hwnd))
+	{
+	    initialise_findrep(eap->arg);
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+	    /* If the OS is Windows NT, and 'encoding' differs from active
+	     * codepage: convert text and use wide function. */
+	    if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+		    && enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+	    {
+		findrep_atow(&s_findrep_struct_w, &s_findrep_struct);
+		s_findrep_hwnd = FindTextW(
+					(LPFINDREPLACEW) &s_findrep_struct_w);
+	    }
+	    else
+# endif
+		s_findrep_hwnd = FindText((LPFINDREPLACE) &s_findrep_struct);
+	}
+
+	set_window_title(s_findrep_hwnd,
+			       _("Find string (use '\\\\' to find  a '\\')"));
+	(void)SetFocus(s_findrep_hwnd);
+
+	s_findrep_is_find = TRUE;
+    }
+#endif
+}
+
+
+    void
+gui_mch_replace_dialog(exarg_T *eap)
+{
+#ifdef MSWIN_FIND_REPLACE
+    if (s_findrep_msg != 0)
+    {
+	if (IsWindow(s_findrep_hwnd) && s_findrep_is_find)
+	    DestroyWindow(s_findrep_hwnd);
+
+	if (!IsWindow(s_findrep_hwnd))
+	{
+	    initialise_findrep(eap->arg);
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+	    if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+		    && enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+	    {
+		findrep_atow(&s_findrep_struct_w, &s_findrep_struct);
+		s_findrep_hwnd = ReplaceTextW(
+					(LPFINDREPLACEW) &s_findrep_struct_w);
+	    }
+	    else
+# endif
+		s_findrep_hwnd = ReplaceText(
+					   (LPFINDREPLACE) &s_findrep_struct);
+	}
+
+	set_window_title(s_findrep_hwnd,
+			    _("Find & Replace (use '\\\\' to find  a '\\')"));
+	(void)SetFocus(s_findrep_hwnd);
+
+	s_findrep_is_find = FALSE;
+    }
+#endif
+}
+
+
+/*
+ * Set visibility of the pointer.
+ */
+    void
+gui_mch_mousehide(int hide)
+{
+    if (hide != gui.pointer_hidden)
+    {
+	ShowCursor(!hide);
+	gui.pointer_hidden = hide;
+    }
+}
+
+#ifdef FEAT_MENU
+    static void
+gui_mch_show_popupmenu_at(vimmenu_T *menu, int x, int y)
+{
+    /* Unhide the mouse, we don't get move events here. */
+    gui_mch_mousehide(FALSE);
+
+    (void)TrackPopupMenu(
+	(HMENU)menu->submenu_id,
+	TPM_LEFTALIGN | TPM_LEFTBUTTON,
+	x, y,
+	(int)0,	    /*reserved param*/
+	s_hwnd,
+	NULL);
+    /*
+     * NOTE: The pop-up menu can eat the mouse up event.
+     * We deal with this in normal.c.
+     */
+}
+#endif
+
+/*
+ * Got a message when the system will go down.
+ */
+    static void
+_OnEndSession(void)
+{
+    getout_preserve_modified(1);
+}
+
+/*
+ * Get this message when the user clicks on the cross in the top right corner
+ * of a Windows95 window.
+ */
+/*ARGSUSED*/
+    static void
+_OnClose(
+    HWND hwnd)
+{
+    gui_shell_closed();
+}
+
+/*
+ * Get a message when the window is being destroyed.
+ */
+    static void
+_OnDestroy(
+    HWND hwnd)
+{
+    if (!destroying)
+	_OnClose(hwnd);
+}
+
+    static void
+_OnPaint(
+    HWND hwnd)
+{
+    if (!IsMinimized(hwnd))
+    {
+	PAINTSTRUCT ps;
+
+	out_flush();	    /* make sure all output has been processed */
+	(void)BeginPaint(hwnd, &ps);
+#if defined(FEAT_DIRECTX)
+	if (IS_ENABLE_DIRECTX())
+	    DWriteContext_BeginDraw(s_dwc);
+#endif
+
+#ifdef FEAT_MBYTE
+	/* prevent multi-byte characters from misprinting on an invalid
+	 * rectangle */
+	if (has_mbyte)
+	{
+	    RECT rect;
+
+	    GetClientRect(hwnd, &rect);
+	    ps.rcPaint.left = rect.left;
+	    ps.rcPaint.right = rect.right;
+	}
+#endif
+
+	if (!IsRectEmpty(&ps.rcPaint))
+	{
+#if defined(FEAT_DIRECTX)
+	    if (IS_ENABLE_DIRECTX())
+		DWriteContext_BindDC(s_dwc, s_hdc, &ps.rcPaint);
+#endif
+	    gui_redraw(ps.rcPaint.left, ps.rcPaint.top,
+		    ps.rcPaint.right - ps.rcPaint.left + 1,
+		    ps.rcPaint.bottom - ps.rcPaint.top + 1);
+	}
+
+#if defined(FEAT_DIRECTX)
+	if (IS_ENABLE_DIRECTX())
+	    DWriteContext_EndDraw(s_dwc);
+#endif
+	EndPaint(hwnd, &ps);
+    }
+}
+
+/*ARGSUSED*/
+    static void
+_OnSize(
+    HWND hwnd,
+    UINT state,
+    int cx,
+    int cy)
+{
+    if (!IsMinimized(hwnd))
+    {
+	gui_resize_shell(cx, cy);
+
+#ifdef FEAT_MENU
+	/* Menu bar may wrap differently now */
+	gui_mswin_get_menu_height(TRUE);
+#endif
+    }
+}
+
+    static void
+_OnSetFocus(
+    HWND hwnd,
+    HWND hwndOldFocus)
+{
+    gui_focus_change(TRUE);
+    s_getting_focus = TRUE;
+    (void)MyWindowProc(hwnd, WM_SETFOCUS, (WPARAM)hwndOldFocus, 0);
+}
+
+    static void
+_OnKillFocus(
+    HWND hwnd,
+    HWND hwndNewFocus)
+{
+    gui_focus_change(FALSE);
+    s_getting_focus = FALSE;
+    (void)MyWindowProc(hwnd, WM_KILLFOCUS, (WPARAM)hwndNewFocus, 0);
+}
+
+/*
+ * Get a message when the user switches back to vim
+ */
+    static LRESULT
+_OnActivateApp(
+    HWND hwnd,
+    BOOL fActivate,
+    DWORD dwThreadId)
+{
+    /* we call gui_focus_change() in _OnSetFocus() */
+    /* gui_focus_change((int)fActivate); */
+    return MyWindowProc(hwnd, WM_ACTIVATEAPP, fActivate, (DWORD)dwThreadId);
+}
+
+#if defined(FEAT_WINDOWS) || defined(PROTO)
+    void
+gui_mch_destroy_scrollbar(scrollbar_T *sb)
+{
+    DestroyWindow(sb->id);
+}
+#endif
+
+/*
+ * Get current mouse coordinates in text window.
+ */
+    void
+gui_mch_getmouse(int *x, int *y)
+{
+    RECT rct;
+    POINT mp;
+
+    (void)GetWindowRect(s_textArea, &rct);
+    (void)GetCursorPos((LPPOINT)&mp);
+    *x = (int)(mp.x - rct.left);
+    *y = (int)(mp.y - rct.top);
+}
+
+/*
+ * Move mouse pointer to character at (x, y).
+ */
+    void
+gui_mch_setmouse(int x, int y)
+{
+    RECT rct;
+
+    (void)GetWindowRect(s_textArea, &rct);
+    (void)SetCursorPos(x + gui.border_offset + rct.left,
+		       y + gui.border_offset + rct.top);
+}
+
+    static void
+gui_mswin_get_valid_dimensions(
+    int w,
+    int h,
+    int *valid_w,
+    int *valid_h)
+{
+    int	    base_width, base_height;
+
+    base_width = gui_get_base_width()
+	+ (GetSystemMetrics(SM_CXFRAME) +
+	   GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
+    base_height = gui_get_base_height()
+	+ (GetSystemMetrics(SM_CYFRAME) +
+	   GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
+	+ GetSystemMetrics(SM_CYCAPTION)
+#ifdef FEAT_MENU
+	+ gui_mswin_get_menu_height(FALSE)
+#endif
+	;
+    *valid_w = base_width +
+		    ((w - base_width) / gui.char_width) * gui.char_width;
+    *valid_h = base_height +
+		    ((h - base_height) / gui.char_height) * gui.char_height;
+}
+
+    void
+gui_mch_flash(int msec)
+{
+    RECT    rc;
+
+    /*
+     * Note: InvertRect() excludes right and bottom of rectangle.
+     */
+    rc.left = 0;
+    rc.top = 0;
+    rc.right = gui.num_cols * gui.char_width;
+    rc.bottom = gui.num_rows * gui.char_height;
+    InvertRect(s_hdc, &rc);
+    gui_mch_flush();			/* make sure it's displayed */
+
+    ui_delay((long)msec, TRUE);	/* wait for a few msec */
+
+    InvertRect(s_hdc, &rc);
+}
+
+/*
+ * Return flags used for scrolling.
+ * The SW_INVALIDATE is required when part of the window is covered or
+ * off-screen. Refer to MS KB Q75236.
+ */
+    static int
+get_scroll_flags(void)
+{
+    HWND	hwnd;
+    RECT	rcVim, rcOther, rcDest;
+
+    GetWindowRect(s_hwnd, &rcVim);
+
+    /* Check if the window is partly above or below the screen.  We don't care
+     * about partly left or right of the screen, it is not relevant when
+     * scrolling up or down. */
+    if (rcVim.top < 0 || rcVim.bottom > GetSystemMetrics(SM_CYFULLSCREEN))
+	return SW_INVALIDATE;
+
+    /* Check if there is an window (partly) on top of us. */
+    for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; )
+	if (IsWindowVisible(hwnd))
+	{
+	    GetWindowRect(hwnd, &rcOther);
+	    if (IntersectRect(&rcDest, &rcVim, &rcOther))
+		return SW_INVALIDATE;
+	}
+    return 0;
+}
+
+/*
+ * On some Intel GPUs, the regions drawn just prior to ScrollWindowEx()
+ * may not be scrolled out properly.
+ * For gVim, when _OnScroll() is repeated, the character at the
+ * previous cursor position may be left drawn after scroll.
+ * The problem can be avoided by calling GetPixel() to get a pixel in
+ * the region before ScrollWindowEx().
+ */
+    static void
+intel_gpu_workaround(void)
+{
+    GetPixel(s_hdc, FILL_X(gui.col), FILL_Y(gui.row));
+}
+
+/*
+ * Delete the given number of lines from the given row, scrolling up any
+ * text further down within the scroll region.
+ */
+    void
+gui_mch_delete_lines(
+    int	    row,
+    int	    num_lines)
+{
+    RECT	rc;
+
+    intel_gpu_workaround();
+
+    rc.left = FILL_X(gui.scroll_region_left);
+    rc.right = FILL_X(gui.scroll_region_right + 1);
+    rc.top = FILL_Y(row);
+    rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
+
+    ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
+				    &rc, &rc, NULL, NULL, get_scroll_flags());
+
+    UpdateWindow(s_textArea);
+    /* This seems to be required to avoid the cursor disappearing when
+     * scrolling such that the cursor ends up in the top-left character on
+     * the screen...   But why?  (Webb) */
+    /* It's probably fixed by disabling drawing the cursor while scrolling. */
+    /* gui.cursor_is_valid = FALSE; */
+
+    gui_clear_block(gui.scroll_region_bot - num_lines + 1,
+						       gui.scroll_region_left,
+	gui.scroll_region_bot, gui.scroll_region_right);
+}
+
+/*
+ * Insert the given number of lines before the given row, scrolling down any
+ * following text within the scroll region.
+ */
+    void
+gui_mch_insert_lines(
+    int		row,
+    int		num_lines)
+{
+    RECT	rc;
+
+    intel_gpu_workaround();
+
+    rc.left = FILL_X(gui.scroll_region_left);
+    rc.right = FILL_X(gui.scroll_region_right + 1);
+    rc.top = FILL_Y(row);
+    rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
+    /* The SW_INVALIDATE is required when part of the window is covered or
+     * off-screen.  How do we avoid it when it's not needed? */
+    ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
+				    &rc, &rc, NULL, NULL, get_scroll_flags());
+
+    UpdateWindow(s_textArea);
+
+    gui_clear_block(row, gui.scroll_region_left,
+				row + num_lines - 1, gui.scroll_region_right);
+}
+
+
+/*ARGSUSED*/
+    void
+gui_mch_exit(int rc)
+{
+#if defined(FEAT_DIRECTX)
+    DWriteContext_Close(s_dwc);
+    DWrite_Final();
+    s_dwc = NULL;
+#endif
+
+    ReleaseDC(s_textArea, s_hdc);
+    DeleteObject(s_brush);
+
+#ifdef FEAT_TEAROFF
+    /* Unload the tearoff bitmap */
+    (void)DeleteObject((HGDIOBJ)s_htearbitmap);
+#endif
+
+    /* Destroy our window (if we have one). */
+    if (s_hwnd != NULL)
+    {
+	destroying = TRUE;	/* ignore WM_DESTROY message now */
+	DestroyWindow(s_hwnd);
+    }
+
+#ifdef GLOBAL_IME
+    global_ime_end();
+#endif
+}
+
+    static char_u *
+logfont2name(LOGFONT lf)
+{
+    char	*p;
+    char	*res;
+    char	*charset_name;
+    char	*font_name = lf.lfFaceName;
+
+    charset_name = charset_id2name((int)lf.lfCharSet);
+#ifdef FEAT_MBYTE
+    /* Convert a font name from the current codepage to 'encoding'.
+     * TODO: Use Wide APIs (including LOGFONTW) instead of ANSI APIs. */
+    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+    {
+	int	len;
+	acp_to_enc((char_u *)lf.lfFaceName, (int)strlen(lf.lfFaceName),
+						(char_u **)&font_name, &len);
+    }
+#endif
+    res = (char *)alloc((unsigned)(strlen(font_name) + 20
+		    + (charset_name == NULL ? 0 : strlen(charset_name) + 2)));
+    if (res != NULL)
+    {
+	p = res;
+	/* make a normal font string out of the lf thing:*/
+	sprintf((char *)p, "%s:h%d", font_name, pixels_to_points(
+			 lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight, TRUE));
+	while (*p)
+	{
+	    if (*p == ' ')
+		*p = '_';
+	    ++p;
+	}
+	if (lf.lfItalic)
+	    STRCAT(p, ":i");
+	if (lf.lfWeight >= FW_BOLD)
+	    STRCAT(p, ":b");
+	if (lf.lfUnderline)
+	    STRCAT(p, ":u");
+	if (lf.lfStrikeOut)
+	    STRCAT(p, ":s");
+	if (charset_name != NULL)
+	{
+	    STRCAT(p, ":c");
+	    STRCAT(p, charset_name);
+	}
+    }
+
+#ifdef FEAT_MBYTE
+    if (font_name != lf.lfFaceName)
+	vim_free(font_name);
+#endif
+    return (char_u *)res;
+}
+
+
+#ifdef FEAT_MBYTE_IME
+/*
+ * Set correct LOGFONT to IME.  Use 'guifontwide' if available, otherwise use
+ * 'guifont'
+ */
+    static void
+update_im_font(void)
+{
+    LOGFONT	lf_wide;
+
+    if (p_guifontwide != NULL && *p_guifontwide != NUL
+	    && gui.wide_font != NOFONT
+	    && GetObject((HFONT)gui.wide_font, sizeof(lf_wide), &lf_wide))
+	norm_logfont = lf_wide;
+    else
+	norm_logfont = sub_logfont;
+    im_set_font(&norm_logfont);
+}
+#endif
+
+#ifdef FEAT_MBYTE
+/*
+ * Handler of gui.wide_font (p_guifontwide) changed notification.
+ */
+    void
+gui_mch_wide_font_changed(void)
+{
+    LOGFONT lf;
+
+# ifdef FEAT_MBYTE_IME
+    update_im_font();
+# endif
+
+    gui_mch_free_font(gui.wide_ital_font);
+    gui.wide_ital_font = NOFONT;
+    gui_mch_free_font(gui.wide_bold_font);
+    gui.wide_bold_font = NOFONT;
+    gui_mch_free_font(gui.wide_boldital_font);
+    gui.wide_boldital_font = NOFONT;
+
+    if (gui.wide_font
+	&& GetObject((HFONT)gui.wide_font, sizeof(lf), &lf))
+    {
+	if (!lf.lfItalic)
+	{
+	    lf.lfItalic = TRUE;
+	    gui.wide_ital_font = get_font_handle(&lf);
+	    lf.lfItalic = FALSE;
+	}
+	if (lf.lfWeight < FW_BOLD)
+	{
+	    lf.lfWeight = FW_BOLD;
+	    gui.wide_bold_font = get_font_handle(&lf);
+	    if (!lf.lfItalic)
+	    {
+		lf.lfItalic = TRUE;
+		gui.wide_boldital_font = get_font_handle(&lf);
+	    }
+	}
+    }
+}
+#endif
+
+/*
+ * Initialise vim to use the font with the given name.
+ * Return FAIL if the font could not be loaded, OK otherwise.
+ */
+/*ARGSUSED*/
+    int
+gui_mch_init_font(char_u *font_name, int fontset)
+{
+    LOGFONT	lf;
+    GuiFont	font = NOFONT;
+    char_u	*p;
+
+    /* Load the font */
+    if (get_logfont(&lf, font_name, NULL, TRUE) == OK)
+	font = get_font_handle(&lf);
+    if (font == NOFONT)
+	return FAIL;
+
+    if (font_name == NULL)
+	font_name = (char_u *)lf.lfFaceName;
+#if defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME)
+    norm_logfont = lf;
+    sub_logfont = lf;
+#endif
+#ifdef FEAT_MBYTE_IME
+    update_im_font();
+#endif
+    gui_mch_free_font(gui.norm_font);
+    gui.norm_font = font;
+    current_font_height = lf.lfHeight;
+    GetFontSize(font);
+
+    p = logfont2name(lf);
+    if (p != NULL)
+    {
+	hl_set_font_name(p);
+
+	/* When setting 'guifont' to "*" replace it with the actual font name.
+	 * */
+	if (STRCMP(font_name, "*") == 0 && STRCMP(p_guifont, "*") == 0)
+	{
+	    vim_free(p_guifont);
+	    p_guifont = p;
+	}
+	else
+	    vim_free(p);
+    }
+
+    gui_mch_free_font(gui.ital_font);
+    gui.ital_font = NOFONT;
+    gui_mch_free_font(gui.bold_font);
+    gui.bold_font = NOFONT;
+    gui_mch_free_font(gui.boldital_font);
+    gui.boldital_font = NOFONT;
+
+    if (!lf.lfItalic)
+    {
+	lf.lfItalic = TRUE;
+	gui.ital_font = get_font_handle(&lf);
+	lf.lfItalic = FALSE;
+    }
+    if (lf.lfWeight < FW_BOLD)
+    {
+	lf.lfWeight = FW_BOLD;
+	gui.bold_font = get_font_handle(&lf);
+	if (!lf.lfItalic)
+	{
+	    lf.lfItalic = TRUE;
+	    gui.boldital_font = get_font_handle(&lf);
+	}
+    }
+
+    return OK;
+}
+
+#ifndef WPF_RESTORETOMAXIMIZED
+# define WPF_RESTORETOMAXIMIZED 2   /* just in case someone doesn't have it */
+#endif
+
+/*
+ * Return TRUE if the GUI window is maximized, filling the whole screen.
+ */
+    int
+gui_mch_maximized(void)
+{
+    WINDOWPLACEMENT wp;
+
+    wp.length = sizeof(WINDOWPLACEMENT);
+    if (GetWindowPlacement(s_hwnd, &wp))
+	return wp.showCmd == SW_SHOWMAXIMIZED
+	    || (wp.showCmd == SW_SHOWMINIMIZED
+		    && wp.flags == WPF_RESTORETOMAXIMIZED);
+
+    return 0;
+}
+
+/*
+ * Called when the font changed while the window is maximized.  Compute the
+ * new Rows and Columns.  This is like resizing the window.
+ */
+    void
+gui_mch_newfont(void)
+{
+    RECT	rect;
+
+    GetWindowRect(s_hwnd, &rect);
+    if (win_socket_id == 0)
+    {
+	gui_resize_shell(rect.right - rect.left
+	    - (GetSystemMetrics(SM_CXFRAME) +
+	       GetSystemMetrics(SM_CXPADDEDBORDER)) * 2,
+	    rect.bottom - rect.top
+	    - (GetSystemMetrics(SM_CYFRAME) +
+	       GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
+	    - GetSystemMetrics(SM_CYCAPTION)
+#ifdef FEAT_MENU
+	    - gui_mswin_get_menu_height(FALSE)
+#endif
+	);
+    }
+    else
+    {
+	/* Inside another window, don't use the frame and border. */
+	gui_resize_shell(rect.right - rect.left,
+	    rect.bottom - rect.top
+#ifdef FEAT_MENU
+			- gui_mswin_get_menu_height(FALSE)
+#endif
+	);
+    }
+}
+
+/*
+ * Set the window title
+ */
+/*ARGSUSED*/
+    void
+gui_mch_settitle(
+    char_u  *title,
+    char_u  *icon)
+{
+    set_window_title(s_hwnd, (title == NULL ? "VIM" : (char *)title));
+}
+
+#ifdef FEAT_MOUSESHAPE
+/* Table for shape IDCs.  Keep in sync with the mshape_names[] table in
+ * misc2.c! */
+static LPCSTR mshape_idcs[] =
+{
+    IDC_ARROW,			/* arrow */
+    MAKEINTRESOURCE(0),		/* blank */
+    IDC_IBEAM,			/* beam */
+    IDC_SIZENS,			/* updown */
+    IDC_SIZENS,			/* udsizing */
+    IDC_SIZEWE,			/* leftright */
+    IDC_SIZEWE,			/* lrsizing */
+    IDC_WAIT,			/* busy */
+#ifdef WIN3264
+    IDC_NO,			/* no */
+#else
+    IDC_ICON,			/* no */
+#endif
+    IDC_ARROW,			/* crosshair */
+    IDC_ARROW,			/* hand1 */
+    IDC_ARROW,			/* hand2 */
+    IDC_ARROW,			/* pencil */
+    IDC_ARROW,			/* question */
+    IDC_ARROW,			/* right-arrow */
+    IDC_UPARROW,		/* up-arrow */
+    IDC_ARROW			/* last one */
+};
+
+    void
+mch_set_mouse_shape(int shape)
+{
+    LPCSTR idc;
+
+    if (shape == MSHAPE_HIDE)
+	ShowCursor(FALSE);
+    else
+    {
+	if (shape >= MSHAPE_NUMBERED)
+	    idc = IDC_ARROW;
+	else
+	    idc = mshape_idcs[shape];
+#ifdef SetClassLongPtr
+	SetClassLongPtr(s_textArea, GCLP_HCURSOR, (__int3264)(LONG_PTR)LoadCursor(NULL, idc));
+#else
+# ifdef WIN32
+	SetClassLong(s_textArea, GCL_HCURSOR, (long_u)LoadCursor(NULL, idc));
+# else /* Win16 */
+	SetClassWord(s_textArea, GCW_HCURSOR, (WORD)LoadCursor(NULL, idc));
+# endif
+#endif
+	if (!p_mh)
+	{
+	    POINT mp;
+
+	    /* Set the position to make it redrawn with the new shape. */
+	    (void)GetCursorPos((LPPOINT)&mp);
+	    (void)SetCursorPos(mp.x, mp.y);
+	    ShowCursor(TRUE);
+	}
+    }
+}
+#endif
+
+#ifdef FEAT_BROWSE
+/*
+ * The file browser exists in two versions: with "W" uses wide characters,
+ * without "W" the current codepage.  When FEAT_MBYTE is defined and on
+ * Windows NT/2000/XP the "W" functions are used.
+ */
+
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+/*
+ * Wide version of convert_filter().
+ */
+    static WCHAR *
+convert_filterW(char_u *s)
+{
+    char_u *tmp;
+    int len;
+    WCHAR *res;
+
+    tmp = convert_filter(s);
+    if (tmp == NULL)
+	return NULL;
+    len = (int)STRLEN(s) + 3;
+    res = enc_to_utf16(tmp, &len);
+    vim_free(tmp);
+    return res;
+}
+
+/*
+ * Wide version of gui_mch_browse().  Keep in sync!
+ */
+    static char_u *
+gui_mch_browseW(
+	int saving,
+	char_u *title,
+	char_u *dflt,
+	char_u *ext,
+	char_u *initdir,
+	char_u *filter)
+{
+    /* We always use the wide function.  This means enc_to_utf16() must work,
+     * otherwise it fails miserably! */
+    OPENFILENAMEW	fileStruct;
+    WCHAR		fileBuf[MAXPATHL];
+    WCHAR		*wp;
+    int			i;
+    WCHAR		*titlep = NULL;
+    WCHAR		*extp = NULL;
+    WCHAR		*initdirp = NULL;
+    WCHAR		*filterp;
+    char_u		*p;
+
+    if (dflt == NULL)
+	fileBuf[0] = NUL;
+    else
+    {
+	wp = enc_to_utf16(dflt, NULL);
+	if (wp == NULL)
+	    fileBuf[0] = NUL;
+	else
+	{
+	    for (i = 0; wp[i] != NUL && i < MAXPATHL - 1; ++i)
+		fileBuf[i] = wp[i];
+	    fileBuf[i] = NUL;
+	    vim_free(wp);
+	}
+    }
+
+    /* Convert the filter to Windows format. */
+    filterp = convert_filterW(filter);
+
+    vim_memset(&fileStruct, 0, sizeof(OPENFILENAMEW));
+#ifdef OPENFILENAME_SIZE_VERSION_400
+    /* be compatible with Windows NT 4.0 */
+    /* TODO: what to use for OPENFILENAMEW??? */
+    fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+#else
+    fileStruct.lStructSize = sizeof(fileStruct);
+#endif
+
+    if (title != NULL)
+	titlep = enc_to_utf16(title, NULL);
+    fileStruct.lpstrTitle = titlep;
+
+    if (ext != NULL)
+	extp = enc_to_utf16(ext, NULL);
+    fileStruct.lpstrDefExt = extp;
+
+    fileStruct.lpstrFile = fileBuf;
+    fileStruct.nMaxFile = MAXPATHL;
+    fileStruct.lpstrFilter = filterp;
+    fileStruct.hwndOwner = s_hwnd;		/* main Vim window is owner*/
+    /* has an initial dir been specified? */
+    if (initdir != NULL && *initdir != NUL)
+    {
+	/* Must have backslashes here, no matter what 'shellslash' says */
+	initdirp = enc_to_utf16(initdir, NULL);
+	if (initdirp != NULL)
+	{
+	    for (wp = initdirp; *wp != NUL; ++wp)
+		if (*wp == '/')
+		    *wp = '\\';
+	}
+	fileStruct.lpstrInitialDir = initdirp;
+    }
+
+    /*
+     * TODO: Allow selection of multiple files.  Needs another arg to this
+     * function to ask for it, and need to use OFN_ALLOWMULTISELECT below.
+     * Also, should we use OFN_FILEMUSTEXIST when opening?  Vim can edit on
+     * files that don't exist yet, so I haven't put it in.  What about
+     * OFN_PATHMUSTEXIST?
+     * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog.
+     */
+    fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY);
+#ifdef FEAT_SHORTCUT
+    if (curbuf->b_p_bin)
+	fileStruct.Flags |= OFN_NODEREFERENCELINKS;
+#endif
+    if (saving)
+    {
+	if (!GetSaveFileNameW(&fileStruct))
+	    return NULL;
+    }
+    else
+    {
+	if (!GetOpenFileNameW(&fileStruct))
+	    return NULL;
+    }
+
+    vim_free(filterp);
+    vim_free(initdirp);
+    vim_free(titlep);
+    vim_free(extp);
+
+    /* Convert from UCS2 to 'encoding'. */
+    p = utf16_to_enc(fileBuf, NULL);
+    if (p != NULL)
+	/* when out of memory we get garbage for non-ASCII chars */
+	STRCPY(fileBuf, p);
+    vim_free(p);
+
+    /* Give focus back to main window (when using MDI). */
+    SetFocus(s_hwnd);
+
+    /* Shorten the file name if possible */
+    return vim_strsave(shorten_fname1((char_u *)fileBuf));
+}
+# endif /* FEAT_MBYTE */
+
+
+/*
+ * Convert the string s to the proper format for a filter string by replacing
+ * the \t and \n delimiters with \0.
+ * Returns the converted string in allocated memory.
+ *
+ * Keep in sync with convert_filterW() above!
+ */
+    static char_u *
+convert_filter(char_u *s)
+{
+    char_u	*res;
+    unsigned	s_len = (unsigned)STRLEN(s);
+    unsigned	i;
+
+    res = alloc(s_len + 3);
+    if (res != NULL)
+    {
+	for (i = 0; i < s_len; ++i)
+	    if (s[i] == '\t' || s[i] == '\n')
+		res[i] = '\0';
+	    else
+		res[i] = s[i];
+	res[s_len] = NUL;
+	/* Add two extra NULs to make sure it's properly terminated. */
+	res[s_len + 1] = NUL;
+	res[s_len + 2] = NUL;
+    }
+    return res;
+}
+
+/*
+ * Select a directory.
+ */
+    char_u *
+gui_mch_browsedir(char_u *title, char_u *initdir)
+{
+    /* We fake this: Use a filter that doesn't select anything and a default
+     * file name that won't be used. */
+    return gui_mch_browse(0, title, (char_u *)_("Not Used"), NULL,
+			      initdir, (char_u *)_("Directory\t*.nothing\n"));
+}
+
+/*
+ * Pop open a file browser and return the file selected, in allocated memory,
+ * or NULL if Cancel is hit.
+ *  saving  - TRUE if the file will be saved to, FALSE if it will be opened.
+ *  title   - Title message for the file browser dialog.
+ *  dflt    - Default name of file.
+ *  ext     - Default extension to be added to files without extensions.
+ *  initdir - directory in which to open the browser (NULL = current dir)
+ *  filter  - Filter for matched files to choose from.
+ *
+ * Keep in sync with gui_mch_browseW() above!
+ */
+    char_u *
+gui_mch_browse(
+	int saving,
+	char_u *title,
+	char_u *dflt,
+	char_u *ext,
+	char_u *initdir,
+	char_u *filter)
+{
+    OPENFILENAME	fileStruct;
+    char_u		fileBuf[MAXPATHL];
+    char_u		*initdirp = NULL;
+    char_u		*filterp;
+    char_u		*p;
+
+# if defined(FEAT_MBYTE) && defined(WIN3264)
+    if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)
+	return gui_mch_browseW(saving, title, dflt, ext, initdir, filter);
+# endif
+
+    if (dflt == NULL)
+	fileBuf[0] = NUL;
+    else
+	vim_strncpy(fileBuf, dflt, MAXPATHL - 1);
+
+    /* Convert the filter to Windows format. */
+    filterp = convert_filter(filter);
+
+    vim_memset(&fileStruct, 0, sizeof(OPENFILENAME));
+#ifdef OPENFILENAME_SIZE_VERSION_400
+    /* be compatible with Windows NT 4.0 */
+    fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+#else
+    fileStruct.lStructSize = sizeof(fileStruct);
+#endif
+
+    fileStruct.lpstrTitle = (LPSTR)title;
+    fileStruct.lpstrDefExt = (LPSTR)ext;
+
+    fileStruct.lpstrFile = (LPSTR)fileBuf;
+    fileStruct.nMaxFile = MAXPATHL;
+    fileStruct.lpstrFilter = (LPSTR)filterp;
+    fileStruct.hwndOwner = s_hwnd;		/* main Vim window is owner*/
+    /* has an initial dir been specified? */
+    if (initdir != NULL && *initdir != NUL)
+    {
+	/* Must have backslashes here, no matter what 'shellslash' says */
+	initdirp = vim_strsave(initdir);
+	if (initdirp != NULL)
+	    for (p = initdirp; *p != NUL; ++p)
+		if (*p == '/')
+		    *p = '\\';
+	fileStruct.lpstrInitialDir = (LPSTR)initdirp;
+    }
+
+    /*
+     * TODO: Allow selection of multiple files.  Needs another arg to this
+     * function to ask for it, and need to use OFN_ALLOWMULTISELECT below.
+     * Also, should we use OFN_FILEMUSTEXIST when opening?  Vim can edit on
+     * files that don't exist yet, so I haven't put it in.  What about
+     * OFN_PATHMUSTEXIST?
+     * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog.
+     */
+    fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY);
+#ifdef FEAT_SHORTCUT
+    if (curbuf->b_p_bin)
+	fileStruct.Flags |= OFN_NODEREFERENCELINKS;
+#endif
+    if (saving)
+    {
+	if (!GetSaveFileName(&fileStruct))
+	    return NULL;
+    }
+    else
+    {
+	if (!GetOpenFileName(&fileStruct))
+	    return NULL;
+    }
+
+    vim_free(filterp);
+    vim_free(initdirp);
+
+    /* Give focus back to main window (when using MDI). */
+    SetFocus(s_hwnd);
+
+    /* Shorten the file name if possible */
+    return vim_strsave(shorten_fname1((char_u *)fileBuf));
+}
+#endif /* FEAT_BROWSE */
+
+/*ARGSUSED*/
+    static void
+_OnDropFiles(
+    HWND hwnd,
+    HDROP hDrop)
+{
+#ifdef FEAT_WINDOWS
+#ifdef WIN3264
+# define BUFPATHLEN _MAX_PATH
+# define DRAGQVAL 0xFFFFFFFF
+#else
+# define BUFPATHLEN MAXPATHL
+# define DRAGQVAL 0xFFFF
+#endif
+#ifdef FEAT_MBYTE
+    WCHAR   wszFile[BUFPATHLEN];
+#endif
+    char    szFile[BUFPATHLEN];
+    UINT    cFiles = DragQueryFile(hDrop, DRAGQVAL, NULL, 0);
+    UINT    i;
+    char_u  **fnames;
+    POINT   pt;
+    int_u   modifiers = 0;
+
+    /* TRACE("_OnDropFiles: %d files dropped\n", cFiles); */
+
+    /* Obtain dropped position */
+    DragQueryPoint(hDrop, &pt);
+    MapWindowPoints(s_hwnd, s_textArea, &pt, 1);
+
+    reset_VIsual();
+
+    fnames = (char_u **)alloc(cFiles * sizeof(char_u *));
+
+    if (fnames != NULL)
+	for (i = 0; i < cFiles; ++i)
+	{
+#ifdef FEAT_MBYTE
+	    if (DragQueryFileW(hDrop, i, wszFile, BUFPATHLEN) > 0)
+		fnames[i] = utf16_to_enc(wszFile, NULL);
+	    else
+#endif
+	    {
+		DragQueryFile(hDrop, i, szFile, BUFPATHLEN);
+		fnames[i] = vim_strsave((char_u *)szFile);
+	    }
+	}
+
+    DragFinish(hDrop);
+
+    if (fnames != NULL)
+    {
+	if ((GetKeyState(VK_SHIFT) & 0x8000) != 0)
+	    modifiers |= MOUSE_SHIFT;
+	if ((GetKeyState(VK_CONTROL) & 0x8000) != 0)
+	    modifiers |= MOUSE_CTRL;
+	if ((GetKeyState(VK_MENU) & 0x8000) != 0)
+	    modifiers |= MOUSE_ALT;
+
+	gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles);
+
+	s_need_activate = TRUE;
+    }
+#endif
+}
+
+/*ARGSUSED*/
+    static int
+_OnScroll(
+    HWND hwnd,
+    HWND hwndCtl,
+    UINT code,
+    int pos)
+{
+    static UINT	prev_code = 0;   /* code of previous call */
+    scrollbar_T *sb, *sb_info;
+    long	val;
+    int		dragging = FALSE;
+    int		dont_scroll_save = dont_scroll;
+#ifndef WIN3264
+    int		nPos;
+#else
+    SCROLLINFO	si;
+
+    si.cbSize = sizeof(si);
+    si.fMask = SIF_POS;
+#endif
+
+    sb = gui_mswin_find_scrollbar(hwndCtl);
+    if (sb == NULL)
+	return 0;
+
+    if (sb->wp != NULL)		/* Left or right scrollbar */
+    {
+	/*
+	 * Careful: need to get scrollbar info out of first (left) scrollbar
+	 * for window, but keep real scrollbar too because we must pass it to
+	 * gui_drag_scrollbar().
+	 */
+	sb_info = &sb->wp->w_scrollbars[0];
+    }
+    else	    /* Bottom scrollbar */
+	sb_info = sb;
+    val = sb_info->value;
+
+    switch (code)
+    {
+	case SB_THUMBTRACK:
+	    val = pos;
+	    dragging = TRUE;
+	    if (sb->scroll_shift > 0)
+		val <<= sb->scroll_shift;
+	    break;
+	case SB_LINEDOWN:
+	    val++;
+	    break;
+	case SB_LINEUP:
+	    val--;
+	    break;
+	case SB_PAGEDOWN:
+	    val += (sb_info->size > 2 ? sb_info->size - 2 : 1);
+	    break;
+	case SB_PAGEUP:
+	    val -= (sb_info->size > 2 ? sb_info->size - 2 : 1);
+	    break;
+	case SB_TOP:
+	    val = 0;
+	    break;
+	case SB_BOTTOM:
+	    val = sb_info->max;
+	    break;
+	case SB_ENDSCROLL:
+	    if (prev_code == SB_THUMBTRACK)
+	    {
+		/*
+		 * "pos" only gives us 16-bit data.  In case of large file,
+		 * use GetScrollPos() which returns 32-bit.  Unfortunately it
+		 * is not valid while the scrollbar is being dragged.
+		 */
+		val = GetScrollPos(hwndCtl, SB_CTL);
+		if (sb->scroll_shift > 0)
+		    val <<= sb->scroll_shift;
+	    }
+	    break;
+
+	default:
+	    /* TRACE("Unknown scrollbar event %d\n", code); */
+	    return 0;
+    }
+    prev_code = code;
+
+#ifdef WIN3264
+    si.nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val;
+    SetScrollInfo(hwndCtl, SB_CTL, &si, TRUE);
+#else
+    nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val;
+    SetScrollPos(hwndCtl, SB_CTL, nPos, TRUE);
+#endif
+
+    /*
+     * When moving a vertical scrollbar, move the other vertical scrollbar too.
+     */
+    if (sb->wp != NULL)
+    {
+	scrollbar_T *sba = sb->wp->w_scrollbars;
+	HWND    id = sba[ (sb == sba + SBAR_LEFT) ? SBAR_RIGHT : SBAR_LEFT].id;
+
+#ifdef WIN3264
+	SetScrollInfo(id, SB_CTL, &si, TRUE);
+#else
+	SetScrollPos(id, SB_CTL, nPos, TRUE);
+#endif
+    }
+
+    /* Don't let us be interrupted here by another message. */
+    s_busy_processing = TRUE;
+
+    /* When "allow_scrollbar" is FALSE still need to remember the new
+     * position, but don't actually scroll by setting "dont_scroll". */
+    dont_scroll = !allow_scrollbar;
+
+    gui_drag_scrollbar(sb, val, dragging);
+
+    s_busy_processing = FALSE;
+    dont_scroll = dont_scroll_save;
+
+    return 0;
+}
+
+
+/*
+ * Get command line arguments.
+ * Use "prog" as the name of the program and "cmdline" as the arguments.
+ * Copy the arguments to allocated memory.
+ * Return the number of arguments (including program name).
+ * Return pointers to the arguments in "argvp".  Memory is allocated with
+ * malloc(), use free() instead of vim_free().
+ * Return pointer to buffer in "tofree".
+ * Returns zero when out of memory.
+ */
+/*ARGSUSED*/
+    int
+get_cmd_args(char *prog, char *cmdline, char ***argvp, char **tofree)
+{
+    int		i;
+    char	*p;
+    char	*progp;
+    char	*pnew = NULL;
+    char	*newcmdline;
+    int		inquote;
+    int		argc;
+    char	**argv = NULL;
+    int		round;
+
+    *tofree = NULL;
+
+#ifdef FEAT_MBYTE
+    /* Try using the Unicode version first, it takes care of conversion when
+     * 'encoding' is changed. */
+    argc = get_cmd_argsW(&argv);
+    if (argc != 0)
+	goto done;
+#endif
+
+    /* Handle the program name.  Remove the ".exe" extension, and find the 1st
+     * non-space. */
+    p = strrchr(prog, '.');
+    if (p != NULL)
+	*p = NUL;
+    for (progp = prog; *progp == ' '; ++progp)
+	;
+
+    /* The command line is copied to allocated memory, so that we can change
+     * it.  Add the size of the string, the separating NUL and a terminating
+     * NUL. */
+    newcmdline = malloc(STRLEN(cmdline) + STRLEN(progp) + 2);
+    if (newcmdline == NULL)
+	return 0;
+
+    /*
+     * First round: count the number of arguments ("pnew" == NULL).
+     * Second round: produce the arguments.
+     */
+    for (round = 1; round <= 2; ++round)
+    {
+	/* First argument is the program name. */
+	if (pnew != NULL)
+	{
+	    argv[0] = pnew;
+	    strcpy(pnew, progp);
+	    pnew += strlen(pnew);
+	    *pnew++ = NUL;
+	}
+
+	/*
+	 * Isolate each argument and put it in argv[].
+	 */
+	p = cmdline;
+	argc = 1;
+	while (*p != NUL)
+	{
+	    inquote = FALSE;
+	    if (pnew != NULL)
+		argv[argc] = pnew;
+	    ++argc;
+	    while (*p != NUL && (inquote || (*p != ' ' && *p != '\t')))
+	    {
+		/* Backslashes are only special when followed by a double
+		 * quote. */
+		i = (int)strspn(p, "\\");
+		if (p[i] == '"')
+		{
+		    /* Halve the number of backslashes. */
+		    if (i > 1 && pnew != NULL)
+		    {
+			vim_memset(pnew, '\\', i / 2);
+			pnew += i / 2;
+		    }
+
+		    /* Even nr of backslashes toggles quoting, uneven copies
+		     * the double quote. */
+		    if ((i & 1) == 0)
+			inquote = !inquote;
+		    else if (pnew != NULL)
+			*pnew++ = '"';
+		    p += i + 1;
+		}
+		else if (i > 0)
+		{
+		    /* Copy span of backslashes unmodified. */
+		    if (pnew != NULL)
+		    {
+			vim_memset(pnew, '\\', i);
+			pnew += i;
+		    }
+		    p += i;
+		}
+		else
+		{
+		    if (pnew != NULL)
+			*pnew++ = *p;
+#ifdef FEAT_MBYTE
+		    /* Can't use mb_* functions, because 'encoding' is not
+		     * initialized yet here. */
+		    if (IsDBCSLeadByte(*p))
+		    {
+			++p;
+			if (pnew != NULL)
+			    *pnew++ = *p;
+		    }
+#endif
+		    ++p;
+		}
+	    }
+
+	    if (pnew != NULL)
+		*pnew++ = NUL;
+	    while (*p == ' ' || *p == '\t')
+		++p;		    /* advance until a non-space */
+	}
+
+	if (round == 1)
+	{
+	    argv = (char **)malloc((argc + 1) * sizeof(char *));
+	    if (argv == NULL )
+	    {
+		free(newcmdline);
+		return 0;		   /* malloc error */
+	    }
+	    pnew = newcmdline;
+	    *tofree = newcmdline;
+	}
+    }
+
+#ifdef FEAT_MBYTE
+done:
+#endif
+    argv[argc] = NULL;		/* NULL-terminated list */
+    *argvp = argv;
+    return argc;
+}
 
 #ifdef FEAT_XPM_W32
 # include "xpm_w32.h"
@@ -1692,10 +5777,6 @@ gui_mch_init(void)
 #endif
     s_hdc = GetDC(s_textArea);
 
-#ifdef MSWIN16_FASTTEXT
-    SetBkMode(s_hdc, OPAQUE);
-#endif
-
 #ifdef FEAT_WINDOWS
     DragAcceptFiles(s_hwnd, TRUE);
 #endif
@@ -2410,7 +6491,6 @@ gui_mch_draw_string(
     int		font_is_ttf_or_vector = 0;
 #endif
 
-#ifndef MSWIN16_FASTTEXT
     /*
      * Italic and bold text seems to have an extra row of pixels at the bottom
      * (below where the bottom of the character should be).  If we draw the
@@ -2484,15 +6564,6 @@ gui_mch_draw_string(
 	    foptions = ETO_CLIPPED;
 	}
     }
-#else
-    /*
-     * The alternative would be to write the characters in opaque mode, but
-     * when the text is not exactly the same proportions as normal text, too
-     * big or too little a rectangle gets drawn for the background.
-     */
-    SetBkMode(s_hdc, OPAQUE);
-    SetBkColor(s_hdc, gui.currBgColor);
-#endif
     SetTextColor(s_hdc, gui.currFgColor);
     SelectFont(s_hdc, gui.currFont);
 
@@ -2677,10 +6748,8 @@ gui_mch_draw_string(
 	/* When p_linespace is 0, overwrite the bottom row of pixels.
 	 * Otherwise put the line just below the character. */
 	y = FILL_Y(row + 1) - 1;
-#ifndef MSWIN16_FASTTEXT
 	if (p_linespace > 1)
 	    y -= p_linespace - 1;
-#endif
 	MoveToEx(s_hdc, FILL_X(col), y, NULL);
 	/* Note: LineTo() excludes the last pixel in the line. */
 	LineTo(s_hdc, FILL_X(col + len), y);
deleted file mode 100644
--- a/src/gui_w48.c
+++ /dev/null
@@ -1,4155 +0,0 @@
-/* vi:set ts=8 sts=4 sw=4:
- *
- * VIM - Vi IMproved		by Bram Moolenaar
- *				GUI 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.
- */
-/*
- * gui_w48.c:  This file is included in gui_w16.c and gui_w32.c.
- *
- * GUI support for Microsoft Windows (Win16 + Win32 = Win48 :-)
- *
- * The combined efforts of:
- * George V. Reilly <george@reilly.org>
- * Robert Webb
- * Vince Negri
- * ...and contributions from many others
- *
- */
-
-#include "vim.h"
-#include "version.h"	/* used by dialog box routine for default title */
-#ifdef DEBUG
-# include <tchar.h>
-#endif
-
-/* cproto fails on missing include files */
-#ifndef PROTO
-
-#ifndef __MINGW32__
-# include <shellapi.h>
-#endif
-#if defined(FEAT_TOOLBAR) || defined(FEAT_BEVAL) || defined(FEAT_GUI_TABLINE)
-# include <commctrl.h>
-#endif
-#ifdef WIN16
-# include <commdlg.h>
-# include <shellapi.h>
-# ifdef WIN16_3DLOOK
-#  include <ctl3d.h>
-# endif
-#endif
-#include <windowsx.h>
-
-#ifdef GLOBAL_IME
-# include "glbl_ime.h"
-#endif
-
-#endif /* PROTO */
-
-#ifdef FEAT_MENU
-# define MENUHINTS		/* show menu hints in command line */
-#endif
-
-/* Some parameters for dialog boxes.  All in pixels. */
-#define DLG_PADDING_X		10
-#define DLG_PADDING_Y		10
-#define DLG_OLD_STYLE_PADDING_X	5
-#define DLG_OLD_STYLE_PADDING_Y	5
-#define DLG_VERT_PADDING_X	4	/* For vertical buttons */
-#define DLG_VERT_PADDING_Y	4
-#define DLG_ICON_WIDTH		34
-#define DLG_ICON_HEIGHT		34
-#define DLG_MIN_WIDTH		150
-#define DLG_FONT_NAME		"MS Sans Serif"
-#define DLG_FONT_POINT_SIZE	8
-#define DLG_MIN_MAX_WIDTH	400
-#define DLG_MIN_MAX_HEIGHT	400
-
-#define DLG_NONBUTTON_CONTROL	5000	/* First ID of non-button controls */
-
-#ifndef WM_XBUTTONDOWN /* For Win2K / winME ONLY */
-# define WM_XBUTTONDOWN		0x020B
-# define WM_XBUTTONUP		0x020C
-# define WM_XBUTTONDBLCLK	0x020D
-# define MK_XBUTTON1		0x0020
-# define MK_XBUTTON2		0x0040
-#endif
-
-#ifdef PROTO
-/*
- * Define a few things for generating prototypes.  This is just to avoid
- * syntax errors, the defines do not need to be correct.
- */
-# define APIENTRY
-# define CALLBACK
-# define CONST
-# define FAR
-# define NEAR
-# define _cdecl
-typedef int BOOL;
-typedef int BYTE;
-typedef int DWORD;
-typedef int WCHAR;
-typedef int ENUMLOGFONT;
-typedef int FINDREPLACE;
-typedef int HANDLE;
-typedef int HBITMAP;
-typedef int HBRUSH;
-typedef int HDROP;
-typedef int INT;
-typedef int LOGFONT[];
-typedef int LPARAM;
-typedef int LPCREATESTRUCT;
-typedef int LPCSTR;
-typedef int LPCTSTR;
-typedef int LPRECT;
-typedef int LPSTR;
-typedef int LPWINDOWPOS;
-typedef int LPWORD;
-typedef int LRESULT;
-typedef int HRESULT;
-# undef MSG
-typedef int MSG;
-typedef int NEWTEXTMETRIC;
-typedef int OSVERSIONINFO;
-typedef int PWORD;
-typedef int RECT;
-typedef int UINT;
-typedef int WORD;
-typedef int WPARAM;
-typedef int POINT;
-typedef void *HINSTANCE;
-typedef void *HMENU;
-typedef void *HWND;
-typedef void *HDC;
-typedef void VOID;
-typedef int LPNMHDR;
-typedef int LONG;
-typedef int WNDPROC;
-#endif
-
-#ifndef GET_X_LPARAM
-# define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
-#endif
-
-static void _OnPaint( HWND hwnd);
-static void clear_rect(RECT *rcp);
-
-static WORD		s_dlgfntheight;		/* height of the dialog font */
-static WORD		s_dlgfntwidth;		/* width of the dialog font */
-
-#ifdef FEAT_MENU
-static HMENU		s_menuBar = NULL;
-#endif
-#ifdef FEAT_TEAROFF
-static void rebuild_tearoff(vimmenu_T *menu);
-static HBITMAP	s_htearbitmap;	    /* bitmap used to indicate tearoff */
-#endif
-
-/* Flag that is set while processing a message that must not be interrupted by
- * processing another message. */
-static int		s_busy_processing = FALSE;
-
-static int		destroying = FALSE;	/* call DestroyWindow() ourselves */
-
-#ifdef MSWIN_FIND_REPLACE
-static UINT		s_findrep_msg = 0;	/* set in gui_w[16/32].c */
-static FINDREPLACE	s_findrep_struct;
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-static FINDREPLACEW	s_findrep_struct_w;
-# endif
-static HWND		s_findrep_hwnd = NULL;
-static int		s_findrep_is_find;	/* TRUE for find dialog, FALSE
-						   for find/replace dialog */
-#endif
-
-static HINSTANCE	s_hinst = NULL;
-#if !defined(FEAT_SNIFF) && !defined(FEAT_GUI)
-static
-#endif
-HWND			s_hwnd = NULL;
-static HDC		s_hdc = NULL;
-static HBRUSH	s_brush = NULL;
-
-#ifdef FEAT_TOOLBAR
-static HWND		s_toolbarhwnd = NULL;
-static WNDPROC		s_toolbar_wndproc = NULL;
-#endif
-
-#ifdef FEAT_GUI_TABLINE
-static HWND		s_tabhwnd = NULL;
-static WNDPROC		s_tabline_wndproc = NULL;
-static int		showing_tabline = 0;
-#endif
-
-static WPARAM		s_wParam = 0;
-static LPARAM		s_lParam = 0;
-
-static HWND		s_textArea = NULL;
-static UINT		s_uMsg = 0;
-
-static char_u		*s_textfield; /* Used by dialogs to pass back strings */
-
-static int		s_need_activate = FALSE;
-
-/* This variable is set when waiting for an event, which is the only moment
- * scrollbar dragging can be done directly.  It's not allowed while commands
- * are executed, because it may move the cursor and that may cause unexpected
- * problems (e.g., while ":s" is working).
- */
-static int allow_scrollbar = FALSE;
-
-#ifdef GLOBAL_IME
-# define MyTranslateMessage(x) global_ime_TranslateMessage(x)
-#else
-# define MyTranslateMessage(x) TranslateMessage(x)
-#endif
-
-#if (defined(WIN3264) && defined(FEAT_MBYTE)) || defined(GLOBAL_IME)
-  /* use of WindowProc depends on wide_WindowProc */
-# define MyWindowProc vim_WindowProc
-#else
-  /* use ordinary WindowProc */
-# define MyWindowProc DefWindowProc
-#endif
-
-extern int current_font_height;	    /* this is in os_mswin.c */
-
-static struct
-{
-    UINT    key_sym;
-    char_u  vim_code0;
-    char_u  vim_code1;
-} special_keys[] =
-{
-    {VK_UP,		'k', 'u'},
-    {VK_DOWN,		'k', 'd'},
-    {VK_LEFT,		'k', 'l'},
-    {VK_RIGHT,		'k', 'r'},
-
-    {VK_F1,		'k', '1'},
-    {VK_F2,		'k', '2'},
-    {VK_F3,		'k', '3'},
-    {VK_F4,		'k', '4'},
-    {VK_F5,		'k', '5'},
-    {VK_F6,		'k', '6'},
-    {VK_F7,		'k', '7'},
-    {VK_F8,		'k', '8'},
-    {VK_F9,		'k', '9'},
-    {VK_F10,		'k', ';'},
-
-    {VK_F11,		'F', '1'},
-    {VK_F12,		'F', '2'},
-    {VK_F13,		'F', '3'},
-    {VK_F14,		'F', '4'},
-    {VK_F15,		'F', '5'},
-    {VK_F16,		'F', '6'},
-    {VK_F17,		'F', '7'},
-    {VK_F18,		'F', '8'},
-    {VK_F19,		'F', '9'},
-    {VK_F20,		'F', 'A'},
-
-    {VK_F21,		'F', 'B'},
-#ifdef FEAT_NETBEANS_INTG
-    {VK_PAUSE,		'F', 'B'},	/* Pause == F21 (see gui_gtk_x11.c) */
-#endif
-    {VK_F22,		'F', 'C'},
-    {VK_F23,		'F', 'D'},
-    {VK_F24,		'F', 'E'},	/* winuser.h defines up to F24 */
-
-    {VK_HELP,		'%', '1'},
-    {VK_BACK,		'k', 'b'},
-    {VK_INSERT,		'k', 'I'},
-    {VK_DELETE,		'k', 'D'},
-    {VK_HOME,		'k', 'h'},
-    {VK_END,		'@', '7'},
-    {VK_PRIOR,		'k', 'P'},
-    {VK_NEXT,		'k', 'N'},
-    {VK_PRINT,		'%', '9'},
-    {VK_ADD,		'K', '6'},
-    {VK_SUBTRACT,	'K', '7'},
-    {VK_DIVIDE,		'K', '8'},
-    {VK_MULTIPLY,	'K', '9'},
-    {VK_SEPARATOR,	'K', 'A'},	/* Keypad Enter */
-    {VK_DECIMAL,	'K', 'B'},
-
-    {VK_NUMPAD0,	'K', 'C'},
-    {VK_NUMPAD1,	'K', 'D'},
-    {VK_NUMPAD2,	'K', 'E'},
-    {VK_NUMPAD3,	'K', 'F'},
-    {VK_NUMPAD4,	'K', 'G'},
-    {VK_NUMPAD5,	'K', 'H'},
-    {VK_NUMPAD6,	'K', 'I'},
-    {VK_NUMPAD7,	'K', 'J'},
-    {VK_NUMPAD8,	'K', 'K'},
-    {VK_NUMPAD9,	'K', 'L'},
-
-    /* Keys that we want to be able to use any modifier with: */
-    {VK_SPACE,		' ', NUL},
-    {VK_TAB,		TAB, NUL},
-    {VK_ESCAPE,		ESC, NUL},
-    {NL,		NL, NUL},
-    {CAR,		CAR, NUL},
-
-    /* End of list marker: */
-    {0,			0, 0}
-};
-
-/* Local variables */
-static int	s_button_pending = -1;
-
-/* s_getting_focus is set when we got focus but didn't see mouse-up event yet,
- * so don't reset s_button_pending. */
-static int	s_getting_focus = FALSE;
-
-static int	s_x_pending;
-static int	s_y_pending;
-static UINT	s_kFlags_pending;
-static UINT	s_wait_timer = 0;   /* Timer for get char from user */
-static int	s_timed_out = FALSE;
-static int	dead_key = 0;	/* 0: no dead key, 1: dead key pressed */
-
-#ifdef WIN3264
-static OSVERSIONINFO os_version;    /* like it says.  Init in gui_mch_init() */
-#endif
-
-#ifdef FEAT_BEVAL
-/* balloon-eval WM_NOTIFY_HANDLER */
-static void Handle_WM_Notify(HWND hwnd, LPNMHDR pnmh);
-static void TrackUserActivity(UINT uMsg);
-#endif
-
-/*
- * For control IME.
- *
- * These LOGFONT used for IME.
- */
-#ifdef FEAT_MBYTE
-# ifdef USE_IM_CONTROL
-/* holds LOGFONT for 'guifontwide' if available, otherwise 'guifont' */
-static LOGFONT norm_logfont;
-/* holds LOGFONT for 'guifont' always. */
-static LOGFONT sub_logfont;
-# endif
-#endif
-
-#ifdef FEAT_MBYTE_IME
-static LRESULT _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData);
-#endif
-
-#if defined(FEAT_BROWSE)
-static char_u *convert_filter(char_u *s);
-#endif
-
-#ifdef DEBUG_PRINT_ERROR
-/*
- * Print out the last Windows error message
- */
-    static void
-print_windows_error(void)
-{
-    LPVOID  lpMsgBuf;
-
-    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-		  NULL, GetLastError(),
-		  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		  (LPTSTR) &lpMsgBuf, 0, NULL);
-    TRACE1("Error: %s\n", lpMsgBuf);
-    LocalFree(lpMsgBuf);
-}
-#endif
-
-/*
- * Cursor blink functions.
- *
- * This is a simple state machine:
- * BLINK_NONE	not blinking at all
- * BLINK_OFF	blinking, cursor is not shown
- * BLINK_ON	blinking, cursor is shown
- */
-
-#define BLINK_NONE  0
-#define BLINK_OFF   1
-#define BLINK_ON    2
-
-static int		blink_state = BLINK_NONE;
-static long_u		blink_waittime = 700;
-static long_u		blink_ontime = 400;
-static long_u		blink_offtime = 250;
-static UINT		blink_timer = 0;
-
-    void
-gui_mch_set_blinking(long wait, long on, long off)
-{
-    blink_waittime = wait;
-    blink_ontime = on;
-    blink_offtime = off;
-}
-
-/* ARGSUSED */
-    static VOID CALLBACK
-_OnBlinkTimer(
-    HWND hwnd,
-    UINT uMsg,
-    UINT idEvent,
-    DWORD dwTime)
-{
-    MSG msg;
-
-    /*
-    TRACE2("Got timer event, id %d, blink_timer %d\n", idEvent, blink_timer);
-    */
-
-    KillTimer(NULL, idEvent);
-
-    /* Eat spurious WM_TIMER messages */
-    while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
-	;
-
-    if (blink_state == BLINK_ON)
-    {
-	gui_undraw_cursor();
-	blink_state = BLINK_OFF;
-	blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_offtime,
-						    (TIMERPROC)_OnBlinkTimer);
-    }
-    else
-    {
-	gui_update_cursor(TRUE, FALSE);
-	blink_state = BLINK_ON;
-	blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
-							 (TIMERPROC)_OnBlinkTimer);
-    }
-}
-
-    static void
-gui_mswin_rm_blink_timer(void)
-{
-    MSG msg;
-
-    if (blink_timer != 0)
-    {
-	KillTimer(NULL, blink_timer);
-	/* Eat spurious WM_TIMER messages */
-	while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
-	    ;
-	blink_timer = 0;
-    }
-}
-
-/*
- * Stop the cursor blinking.  Show the cursor if it wasn't shown.
- */
-    void
-gui_mch_stop_blink(void)
-{
-    gui_mswin_rm_blink_timer();
-    if (blink_state == BLINK_OFF)
-	gui_update_cursor(TRUE, FALSE);
-    blink_state = BLINK_NONE;
-}
-
-/*
- * Start the cursor blinking.  If it was already blinking, this restarts the
- * waiting time and shows the cursor.
- */
-    void
-gui_mch_start_blink(void)
-{
-    gui_mswin_rm_blink_timer();
-
-    /* Only switch blinking on if none of the times is zero */
-    if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
-    {
-	blink_timer = (UINT)SetTimer(NULL, 0, (UINT)blink_waittime,
-						    (TIMERPROC)_OnBlinkTimer);
-	blink_state = BLINK_ON;
-	gui_update_cursor(TRUE, FALSE);
-    }
-}
-
-/*
- * Call-back routines.
- */
-
-/*ARGSUSED*/
-    static VOID CALLBACK
-_OnTimer(
-    HWND hwnd,
-    UINT uMsg,
-    UINT idEvent,
-    DWORD dwTime)
-{
-    MSG msg;
-
-    /*
-    TRACE2("Got timer event, id %d, s_wait_timer %d\n", idEvent, s_wait_timer);
-    */
-    KillTimer(NULL, idEvent);
-    s_timed_out = TRUE;
-
-    /* Eat spurious WM_TIMER messages */
-    while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
-	;
-    if (idEvent == s_wait_timer)
-	s_wait_timer = 0;
-}
-
-/*ARGSUSED*/
-    static void
-_OnDeadChar(
-    HWND hwnd,
-    UINT ch,
-    int cRepeat)
-{
-    dead_key = 1;
-}
-
-/*
- * Convert Unicode character "ch" to bytes in "string[slen]".
- * When "had_alt" is TRUE the ALT key was included in "ch".
- * Return the length.
- */
-    static int
-char_to_string(int ch, char_u *string, int slen, int had_alt)
-{
-    int		len;
-    int		i;
-#ifdef FEAT_MBYTE
-    WCHAR	wstring[2];
-    char_u	*ws = NULL;;
-
-    if (os_version.dwPlatformId != VER_PLATFORM_WIN32_NT)
-    {
-	/* On Windows 95/98 we apparently get the character in the active
-	 * codepage, not in UCS-2.  If conversion is needed convert it to
-	 * UCS-2 first. */
-	if ((int)GetACP() == enc_codepage)
-	    len = 0;	    /* no conversion required */
-	else
-	{
-	    string[0] = ch;
-	    len = MultiByteToWideChar(GetACP(), 0, (LPCSTR)string,
-		    1, wstring, 2);
-	}
-    }
-    else
-    {
-	wstring[0] = ch;
-	len = 1;
-    }
-
-    if (len > 0)
-    {
-	/* "ch" is a UTF-16 character.  Convert it to a string of bytes.  When
-	 * "enc_codepage" is non-zero use the standard Win32 function,
-	 * otherwise use our own conversion function (e.g., for UTF-8). */
-	if (enc_codepage > 0)
-	{
-	    len = WideCharToMultiByte(enc_codepage, 0, wstring, len,
-					       (LPSTR)string, slen, 0, NULL);
-	    /* If we had included the ALT key into the character but now the
-	     * upper bit is no longer set, that probably means the conversion
-	     * failed.  Convert the original character and set the upper bit
-	     * afterwards. */
-	    if (had_alt && len == 1 && ch >= 0x80 && string[0] < 0x80)
-	    {
-		wstring[0] = ch & 0x7f;
-		len = WideCharToMultiByte(enc_codepage, 0, wstring, len,
-					       (LPSTR)string, slen, 0, NULL);
-		if (len == 1) /* safety check */
-		    string[0] |= 0x80;
-	    }
-	}
-	else
-	{
-	    len = 1;
-	    ws = utf16_to_enc(wstring, &len);
-	    if (ws == NULL)
-		len = 0;
-	    else
-	    {
-		if (len > slen)	/* just in case */
-		    len = slen;
-		mch_memmove(string, ws, len);
-		vim_free(ws);
-	    }
-	}
-    }
-
-    if (len == 0)
-#endif
-    {
-	string[0] = ch;
-	len = 1;
-    }
-
-    for (i = 0; i < len; ++i)
-	if (string[i] == CSI && len <= slen - 2)
-	{
-	    /* Insert CSI as K_CSI. */
-	    mch_memmove(string + i + 3, string + i + 1, len - i - 1);
-	    string[++i] = KS_EXTRA;
-	    string[++i] = (int)KE_CSI;
-	    len += 2;
-	}
-
-    return len;
-}
-
-/*
- * Key hit, add it to the input buffer.
- */
-/*ARGSUSED*/
-    static void
-_OnChar(
-    HWND hwnd,
-    UINT ch,
-    int cRepeat)
-{
-    char_u	string[40];
-    int		len = 0;
-
-    dead_key = 0;
-
-    len = char_to_string(ch, string, 40, FALSE);
-    if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts)
-    {
-	trash_input_buf();
-	got_int = TRUE;
-    }
-
-    add_to_input_buf(string, len);
-}
-
-/*
- * Alt-Key hit, add it to the input buffer.
- */
-/*ARGSUSED*/
-    static void
-_OnSysChar(
-    HWND hwnd,
-    UINT cch,
-    int cRepeat)
-{
-    char_u	string[40]; /* Enough for multibyte character */
-    int		len;
-    int		modifiers;
-    int		ch = cch;   /* special keys are negative */
-
-    dead_key = 0;
-
-    /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */
-
-    /* OK, we have a character key (given by ch) which was entered with the
-     * ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
-     * that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless
-     * CAPSLOCK is pressed) at this point.
-     */
-    modifiers = MOD_MASK_ALT;
-    if (GetKeyState(VK_SHIFT) & 0x8000)
-	modifiers |= MOD_MASK_SHIFT;
-    if (GetKeyState(VK_CONTROL) & 0x8000)
-	modifiers |= MOD_MASK_CTRL;
-
-    ch = simplify_key(ch, &modifiers);
-    /* remove the SHIFT modifier for keys where it's already included, e.g.,
-     * '(' and '*' */
-    if (ch < 0x100 && !isalpha(ch) && isprint(ch))
-	modifiers &= ~MOD_MASK_SHIFT;
-
-    /* Interpret the ALT key as making the key META, include SHIFT, etc. */
-    ch = extract_modifiers(ch, &modifiers);
-    if (ch == CSI)
-	ch = K_CSI;
-
-    len = 0;
-    if (modifiers)
-    {
-	string[len++] = CSI;
-	string[len++] = KS_MODIFIER;
-	string[len++] = modifiers;
-    }
-
-    if (IS_SPECIAL((int)ch))
-    {
-	string[len++] = CSI;
-	string[len++] = K_SECOND((int)ch);
-	string[len++] = K_THIRD((int)ch);
-    }
-    else
-    {
-	/* Although the documentation isn't clear about it, we assume "ch" is
-	 * a Unicode character. */
-	len += char_to_string(ch, string + len, 40 - len, TRUE);
-    }
-
-    add_to_input_buf(string, len);
-}
-
-    static void
-_OnMouseEvent(
-    int button,
-    int x,
-    int y,
-    int repeated_click,
-    UINT keyFlags)
-{
-    int vim_modifiers = 0x0;
-
-    s_getting_focus = FALSE;
-
-    if (keyFlags & MK_SHIFT)
-	vim_modifiers |= MOUSE_SHIFT;
-    if (keyFlags & MK_CONTROL)
-	vim_modifiers |= MOUSE_CTRL;
-    if (GetKeyState(VK_MENU) & 0x8000)
-	vim_modifiers |= MOUSE_ALT;
-
-    gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers);
-}
-
-/*ARGSUSED*/
-    static void
-_OnMouseButtonDown(
-    HWND hwnd,
-    BOOL fDoubleClick,
-    int x,
-    int y,
-    UINT keyFlags)
-{
-    static LONG	s_prevTime = 0;
-
-    LONG    currentTime = GetMessageTime();
-    int	    button = -1;
-    int	    repeated_click;
-
-    /* Give main window the focus: this is so the cursor isn't hollow. */
-    (void)SetFocus(s_hwnd);
-
-    if (s_uMsg == WM_LBUTTONDOWN || s_uMsg == WM_LBUTTONDBLCLK)
-	button = MOUSE_LEFT;
-    else if (s_uMsg == WM_MBUTTONDOWN || s_uMsg == WM_MBUTTONDBLCLK)
-	button = MOUSE_MIDDLE;
-    else if (s_uMsg == WM_RBUTTONDOWN || s_uMsg == WM_RBUTTONDBLCLK)
-	button = MOUSE_RIGHT;
-#ifndef WIN16 /*<VN>*/
-    else if (s_uMsg == WM_XBUTTONDOWN || s_uMsg == WM_XBUTTONDBLCLK)
-    {
-#ifndef GET_XBUTTON_WPARAM
-# define GET_XBUTTON_WPARAM(wParam)	(HIWORD(wParam))
-#endif
-	button = ((GET_XBUTTON_WPARAM(s_wParam) == 1) ? MOUSE_X1 : MOUSE_X2);
-    }
-    else if (s_uMsg == WM_CAPTURECHANGED)
-    {
-	/* on W95/NT4, somehow you get in here with an odd Msg
-	 * if you press one button while holding down the other..*/
-	if (s_button_pending == MOUSE_LEFT)
-	    button = MOUSE_RIGHT;
-	else
-	    button = MOUSE_LEFT;
-    }
-#endif
-    if (button >= 0)
-    {
-	repeated_click = ((int)(currentTime - s_prevTime) < p_mouset);
-
-	/*
-	 * Holding down the left and right buttons simulates pushing the middle
-	 * button.
-	 */
-	if (repeated_click
-		&& ((button == MOUSE_LEFT && s_button_pending == MOUSE_RIGHT)
-		    || (button == MOUSE_RIGHT
-					  && s_button_pending == MOUSE_LEFT)))
-	{
-	    /*
-	     * Hmm, gui.c will ignore more than one button down at a time, so
-	     * pretend we let go of it first.
-	     */
-	    gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, 0x0);
-	    button = MOUSE_MIDDLE;
-	    repeated_click = FALSE;
-	    s_button_pending = -1;
-	    _OnMouseEvent(button, x, y, repeated_click, keyFlags);
-	}
-	else if ((repeated_click)
-		|| (mouse_model_popup() && (button == MOUSE_RIGHT)))
-	{
-	    if (s_button_pending > -1)
-	    {
-		    _OnMouseEvent(s_button_pending, x, y, FALSE, keyFlags);
-		    s_button_pending = -1;
-	    }
-	    /* TRACE("Button down at x %d, y %d\n", x, y); */
-	    _OnMouseEvent(button, x, y, repeated_click, keyFlags);
-	}
-	else
-	{
-	    /*
-	     * If this is the first press (i.e. not a multiple click) don't
-	     * action immediately, but store and wait for:
-	     * i) button-up
-	     * ii) mouse move
-	     * iii) another button press
-	     * before using it.
-	     * This enables us to make left+right simulate middle button,
-	     * without left or right being actioned first.  The side-effect is
-	     * that if you click and hold the mouse without dragging, the
-	     * cursor doesn't move until you release the button. In practice
-	     * this is hardly a problem.
-	     */
-	    s_button_pending = button;
-	    s_x_pending = x;
-	    s_y_pending = y;
-	    s_kFlags_pending = keyFlags;
-	}
-
-	s_prevTime = currentTime;
-    }
-}
-
-/*ARGSUSED*/
-    static void
-_OnMouseMoveOrRelease(
-    HWND hwnd,
-    int x,
-    int y,
-    UINT keyFlags)
-{
-    int button;
-
-    s_getting_focus = FALSE;
-    if (s_button_pending > -1)
-    {
-	/* Delayed action for mouse down event */
-	_OnMouseEvent(s_button_pending, s_x_pending,
-					s_y_pending, FALSE, s_kFlags_pending);
-	s_button_pending = -1;
-    }
-    if (s_uMsg == WM_MOUSEMOVE)
-    {
-	/*
-	 * It's only a MOUSE_DRAG if one or more mouse buttons are being held
-	 * down.
-	 */
-	if (!(keyFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON
-						| MK_XBUTTON1 | MK_XBUTTON2)))
-	{
-	    gui_mouse_moved(x, y);
-	    return;
-	}
-
-	/*
-	 * While button is down, keep grabbing mouse move events when
-	 * the mouse goes outside the window
-	 */
-	SetCapture(s_textArea);
-	button = MOUSE_DRAG;
-	/* TRACE("  move at x %d, y %d\n", x, y); */
-    }
-    else
-    {
-	ReleaseCapture();
-	button = MOUSE_RELEASE;
-	/* TRACE("  up at x %d, y %d\n", x, y); */
-    }
-
-    _OnMouseEvent(button, x, y, FALSE, keyFlags);
-}
-
-#ifdef FEAT_MENU
-/*
- * Find the vimmenu_T with the given id
- */
-    static vimmenu_T *
-gui_mswin_find_menu(
-    vimmenu_T	*pMenu,
-    int		id)
-{
-    vimmenu_T	*pChildMenu;
-
-    while (pMenu)
-    {
-	if (pMenu->id == (UINT)id)
-	    break;
-	if (pMenu->children != NULL)
-	{
-	    pChildMenu = gui_mswin_find_menu(pMenu->children, id);
-	    if (pChildMenu)
-	    {
-		pMenu = pChildMenu;
-		break;
-	    }
-	}
-	pMenu = pMenu->next;
-    }
-    return pMenu;
-}
-
-/*ARGSUSED*/
-    static void
-_OnMenu(
-    HWND	hwnd,
-    int		id,
-    HWND	hwndCtl,
-    UINT	codeNotify)
-{
-    vimmenu_T	*pMenu;
-
-    pMenu = gui_mswin_find_menu(root_menu, id);
-    if (pMenu)
-	gui_menu_cb(pMenu);
-}
-#endif
-
-#ifdef MSWIN_FIND_REPLACE
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-/*
- * copy useful data from structure LPFINDREPLACE to structure LPFINDREPLACEW
- */
-    static void
-findrep_atow(LPFINDREPLACEW lpfrw, LPFINDREPLACE lpfr)
-{
-    WCHAR *wp;
-
-    lpfrw->hwndOwner = lpfr->hwndOwner;
-    lpfrw->Flags = lpfr->Flags;
-
-    wp = enc_to_utf16((char_u *)lpfr->lpstrFindWhat, NULL);
-    wcsncpy(lpfrw->lpstrFindWhat, wp, lpfrw->wFindWhatLen - 1);
-    vim_free(wp);
-
-    /* the field "lpstrReplaceWith" doesn't need to be copied */
-}
-
-/*
- * copy useful data from structure LPFINDREPLACEW to structure LPFINDREPLACE
- */
-    static void
-findrep_wtoa(LPFINDREPLACE lpfr, LPFINDREPLACEW lpfrw)
-{
-    char_u *p;
-
-    lpfr->Flags = lpfrw->Flags;
-
-    p = utf16_to_enc((short_u*)lpfrw->lpstrFindWhat, NULL);
-    vim_strncpy((char_u *)lpfr->lpstrFindWhat, p, lpfr->wFindWhatLen - 1);
-    vim_free(p);
-
-    p = utf16_to_enc((short_u*)lpfrw->lpstrReplaceWith, NULL);
-    vim_strncpy((char_u *)lpfr->lpstrReplaceWith, p, lpfr->wReplaceWithLen - 1);
-    vim_free(p);
-}
-# endif
-
-/*
- * Handle a Find/Replace window message.
- */
-    static void
-_OnFindRepl(void)
-{
-    int	    flags = 0;
-    int	    down;
-
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-    /* If the OS is Windows NT, and 'encoding' differs from active codepage:
-     * convert text from wide string. */
-    if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
-			&& enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-    {
-	findrep_wtoa(&s_findrep_struct, &s_findrep_struct_w);
-    }
-# endif
-
-    if (s_findrep_struct.Flags & FR_DIALOGTERM)
-	/* Give main window the focus back. */
-	(void)SetFocus(s_hwnd);
-
-    if (s_findrep_struct.Flags & FR_FINDNEXT)
-    {
-	flags = FRD_FINDNEXT;
-
-	/* Give main window the focus back: this is so the cursor isn't
-	 * hollow. */
-	(void)SetFocus(s_hwnd);
-    }
-    else if (s_findrep_struct.Flags & FR_REPLACE)
-    {
-	flags = FRD_REPLACE;
-
-	/* Give main window the focus back: this is so the cursor isn't
-	 * hollow. */
-	(void)SetFocus(s_hwnd);
-    }
-    else if (s_findrep_struct.Flags & FR_REPLACEALL)
-    {
-	flags = FRD_REPLACEALL;
-    }
-
-    if (flags != 0)
-    {
-	/* Call the generic GUI function to do the actual work. */
-	if (s_findrep_struct.Flags & FR_WHOLEWORD)
-	    flags |= FRD_WHOLE_WORD;
-	if (s_findrep_struct.Flags & FR_MATCHCASE)
-	    flags |= FRD_MATCH_CASE;
-	down = (s_findrep_struct.Flags & FR_DOWN) != 0;
-	gui_do_findrepl(flags, (char_u *)s_findrep_struct.lpstrFindWhat,
-			     (char_u *)s_findrep_struct.lpstrReplaceWith, down);
-    }
-}
-#endif
-
-    static void
-HandleMouseHide(UINT uMsg, LPARAM lParam)
-{
-    static LPARAM last_lParam = 0L;
-
-    /* We sometimes get a mousemove when the mouse didn't move... */
-    if (uMsg == WM_MOUSEMOVE || uMsg == WM_NCMOUSEMOVE)
-    {
-	if (lParam == last_lParam)
-	    return;
-	last_lParam = lParam;
-    }
-
-    /* Handle specially, to centralise coding. We need to be sure we catch all
-     * possible events which should cause us to restore the cursor (as it is a
-     * shared resource, we take full responsibility for it).
-     */
-    switch (uMsg)
-    {
-    case WM_KEYUP:
-    case WM_CHAR:
-	/*
-	 * blank out the pointer if necessary
-	 */
-	if (p_mh)
-	    gui_mch_mousehide(TRUE);
-	break;
-
-    case WM_SYSKEYUP:	 /* show the pointer when a system-key is pressed */
-    case WM_SYSCHAR:
-    case WM_MOUSEMOVE:	 /* show the pointer on any mouse action */
-    case WM_LBUTTONDOWN:
-    case WM_LBUTTONUP:
-    case WM_MBUTTONDOWN:
-    case WM_MBUTTONUP:
-    case WM_RBUTTONDOWN:
-    case WM_RBUTTONUP:
-    case WM_XBUTTONDOWN:
-    case WM_XBUTTONUP:
-    case WM_NCMOUSEMOVE:
-    case WM_NCLBUTTONDOWN:
-    case WM_NCLBUTTONUP:
-    case WM_NCMBUTTONDOWN:
-    case WM_NCMBUTTONUP:
-    case WM_NCRBUTTONDOWN:
-    case WM_NCRBUTTONUP:
-    case WM_KILLFOCUS:
-	/*
-	 * if the pointer is currently hidden, then we should show it.
-	 */
-	gui_mch_mousehide(FALSE);
-	break;
-    }
-}
-
-    static LRESULT CALLBACK
-_TextAreaWndProc(
-    HWND hwnd,
-    UINT uMsg,
-    WPARAM wParam,
-    LPARAM lParam)
-{
-    /*
-    TRACE("TextAreaWndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
-	  hwnd, uMsg, wParam, lParam);
-    */
-
-    HandleMouseHide(uMsg, lParam);
-
-    s_uMsg = uMsg;
-    s_wParam = wParam;
-    s_lParam = lParam;
-
-#ifdef FEAT_BEVAL
-    TrackUserActivity(uMsg);
-#endif
-
-    switch (uMsg)
-    {
-	HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK,_OnMouseButtonDown);
-	HANDLE_MSG(hwnd, WM_LBUTTONDOWN,_OnMouseButtonDown);
-	HANDLE_MSG(hwnd, WM_LBUTTONUP,	_OnMouseMoveOrRelease);
-	HANDLE_MSG(hwnd, WM_MBUTTONDBLCLK,_OnMouseButtonDown);
-	HANDLE_MSG(hwnd, WM_MBUTTONDOWN,_OnMouseButtonDown);
-	HANDLE_MSG(hwnd, WM_MBUTTONUP,	_OnMouseMoveOrRelease);
-	HANDLE_MSG(hwnd, WM_MOUSEMOVE,	_OnMouseMoveOrRelease);
-	HANDLE_MSG(hwnd, WM_PAINT,	_OnPaint);
-	HANDLE_MSG(hwnd, WM_RBUTTONDBLCLK,_OnMouseButtonDown);
-	HANDLE_MSG(hwnd, WM_RBUTTONDOWN,_OnMouseButtonDown);
-	HANDLE_MSG(hwnd, WM_RBUTTONUP,	_OnMouseMoveOrRelease);
-#ifndef WIN16 /*<VN>*/
-	HANDLE_MSG(hwnd, WM_XBUTTONDBLCLK,_OnMouseButtonDown);
-	HANDLE_MSG(hwnd, WM_XBUTTONDOWN,_OnMouseButtonDown);
-	HANDLE_MSG(hwnd, WM_XBUTTONUP,	_OnMouseMoveOrRelease);
-#endif
-
-#ifdef FEAT_BEVAL
-	case WM_NOTIFY: Handle_WM_Notify(hwnd, (LPNMHDR)lParam);
-	    return TRUE;
-#endif
-	default:
-	    return MyWindowProc(hwnd, uMsg, wParam, lParam);
-    }
-}
-
-#if (defined(WIN3264) && defined(FEAT_MBYTE)) \
-	|| defined(GLOBAL_IME) \
-	|| defined(PROTO)
-# ifdef PROTO
-typedef int WINAPI;
-# endif
-
-    LRESULT WINAPI
-vim_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-# ifdef GLOBAL_IME
-    return global_ime_DefWindowProc(hwnd, message, wParam, lParam);
-# else
-    if (wide_WindowProc)
-	return DefWindowProcW(hwnd, message, wParam, lParam);
-    return DefWindowProc(hwnd, message, wParam, lParam);
-#endif
-}
-#endif
-
-/*
- * Called when the foreground or background color has been changed.
- */
-    void
-gui_mch_new_colors(void)
-{
-    /* nothing to do? */
-}
-
-/*
- * Set the colors to their default values.
- */
-    void
-gui_mch_def_colors(void)
-{
-    gui.norm_pixel = GetSysColor(COLOR_WINDOWTEXT);
-    gui.back_pixel = GetSysColor(COLOR_WINDOW);
-    gui.def_norm_pixel = gui.norm_pixel;
-    gui.def_back_pixel = gui.back_pixel;
-}
-
-/*
- * Open the GUI window which was created by a call to gui_mch_init().
- */
-    int
-gui_mch_open(void)
-{
-#ifndef SW_SHOWDEFAULT
-# define SW_SHOWDEFAULT 10	/* Borland 5.0 doesn't have it */
-#endif
-    /* Actually open the window, if not already visible
-     * (may be done already in gui_mch_set_shellsize) */
-    if (!IsWindowVisible(s_hwnd))
-	ShowWindow(s_hwnd, SW_SHOWDEFAULT);
-
-#ifdef MSWIN_FIND_REPLACE
-    /* Init replace string here, so that we keep it when re-opening the
-     * dialog. */
-    s_findrep_struct.lpstrReplaceWith[0] = NUL;
-#endif
-
-    return OK;
-}
-
-/*
- * Get the position of the top left corner of the window.
- */
-    int
-gui_mch_get_winpos(int *x, int *y)
-{
-    RECT    rect;
-
-    GetWindowRect(s_hwnd, &rect);
-    *x = rect.left;
-    *y = rect.top;
-    return OK;
-}
-
-/*
- * Set the position of the top left corner of the window to the given
- * coordinates.
- */
-    void
-gui_mch_set_winpos(int x, int y)
-{
-    SetWindowPos(s_hwnd, NULL, x, y, 0, 0,
-		 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
-}
-    void
-gui_mch_set_text_area_pos(int x, int y, int w, int h)
-{
-    static int oldx = 0;
-    static int oldy = 0;
-
-    SetWindowPos(s_textArea, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE);
-
-#ifdef FEAT_TOOLBAR
-    if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
-	SendMessage(s_toolbarhwnd, WM_SIZE,
-	      (WPARAM)0, (LPARAM)(w + ((long)(TOOLBAR_BUTTON_HEIGHT+8)<<16)));
-#endif
-#if defined(FEAT_GUI_TABLINE)
-    if (showing_tabline)
-    {
-	int	top = 0;
-	RECT	rect;
-
-# ifdef FEAT_TOOLBAR
-	if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
-	    top = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
-# endif
-	GetClientRect(s_hwnd, &rect);
-	MoveWindow(s_tabhwnd, 0, top, rect.right, gui.tabline_height, TRUE);
-    }
-#endif
-
-    /* When side scroll bar is unshown, the size of window will change.
-     * then, the text area move left or right. thus client rect should be
-     * forcedly redrawn. (Yasuhiro Matsumoto) */
-    if (oldx != x || oldy != y)
-    {
-	InvalidateRect(s_hwnd, NULL, FALSE);
-	oldx = x;
-	oldy = y;
-    }
-}
-
-
-/*
- * Scrollbar stuff:
- */
-
-    void
-gui_mch_enable_scrollbar(
-    scrollbar_T     *sb,
-    int		    flag)
-{
-    ShowScrollBar(sb->id, SB_CTL, flag);
-
-    /* TODO: When the window is maximized, the size of the window stays the
-     * same, thus the size of the text area changes.  On Win98 it's OK, on Win
-     * NT 4.0 it's not... */
-}
-
-    void
-gui_mch_set_scrollbar_pos(
-    scrollbar_T *sb,
-    int		x,
-    int		y,
-    int		w,
-    int		h)
-{
-    SetWindowPos(sb->id, NULL, x, y, w, h,
-			      SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
-}
-
-    void
-gui_mch_create_scrollbar(
-    scrollbar_T *sb,
-    int		orient)	/* SBAR_VERT or SBAR_HORIZ */
-{
-    sb->id = CreateWindow(
-	"SCROLLBAR", "Scrollbar",
-	WS_CHILD | ((orient == SBAR_VERT) ? SBS_VERT : SBS_HORZ), 0, 0,
-	10,				/* Any value will do for now */
-	10,				/* Any value will do for now */
-	s_hwnd, NULL,
-	s_hinst, NULL);
-}
-
-/*
- * Find the scrollbar with the given hwnd.
- */
-	 static scrollbar_T *
-gui_mswin_find_scrollbar(HWND hwnd)
-{
-    win_T	*wp;
-
-    if (gui.bottom_sbar.id == hwnd)
-	return &gui.bottom_sbar;
-    FOR_ALL_WINDOWS(wp)
-    {
-	if (wp->w_scrollbars[SBAR_LEFT].id == hwnd)
-	    return &wp->w_scrollbars[SBAR_LEFT];
-	if (wp->w_scrollbars[SBAR_RIGHT].id == hwnd)
-	    return &wp->w_scrollbars[SBAR_RIGHT];
-    }
-    return NULL;
-}
-
-/*
- * Get the character size of a font.
- */
-    static void
-GetFontSize(GuiFont font)
-{
-    HWND    hwnd = GetDesktopWindow();
-    HDC	    hdc = GetWindowDC(hwnd);
-    HFONT   hfntOld = SelectFont(hdc, (HFONT)font);
-    TEXTMETRIC tm;
-
-    GetTextMetrics(hdc, &tm);
-    gui.char_width = tm.tmAveCharWidth + tm.tmOverhang;
-
-    gui.char_height = tm.tmHeight
-#ifndef MSWIN16_FASTTEXT
-				+ p_linespace
-#endif
-				;
-
-    SelectFont(hdc, hfntOld);
-
-    ReleaseDC(hwnd, hdc);
-}
-
-/*
- * Adjust gui.char_height (after 'linespace' was changed).
- */
-    int
-gui_mch_adjust_charheight(void)
-{
-    GetFontSize(gui.norm_font);
-    return OK;
-}
-
-    static GuiFont
-get_font_handle(LOGFONT *lf)
-{
-    HFONT   font = NULL;
-
-    /* Load the font */
-    font = CreateFontIndirect(lf);
-
-    if (font == NULL)
-	return NOFONT;
-
-    return (GuiFont)font;
-}
-
-    static int
-pixels_to_points(int pixels, int vertical)
-{
-    int		points;
-    HWND	hwnd;
-    HDC		hdc;
-
-    hwnd = GetDesktopWindow();
-    hdc = GetWindowDC(hwnd);
-
-    points = MulDiv(pixels, 72,
-		    GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX));
-
-    ReleaseDC(hwnd, hdc);
-
-    return points;
-}
-
-    GuiFont
-gui_mch_get_font(
-    char_u	*name,
-    int		giveErrorIfMissing)
-{
-    LOGFONT	lf;
-    GuiFont	font = NOFONT;
-
-    if (get_logfont(&lf, name, NULL, giveErrorIfMissing) == OK)
-	font = get_font_handle(&lf);
-    if (font == NOFONT && giveErrorIfMissing)
-	EMSG2(_(e_font), name);
-    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.
- */
-/*ARGSUSED*/
-    char_u *
-gui_mch_get_fontname(GuiFont font, char_u *name)
-{
-    if (name == NULL)
-	return NULL;
-    return vim_strsave(name);
-}
-#endif
-
-    void
-gui_mch_free_font(GuiFont font)
-{
-    if (font)
-	DeleteObject((HFONT)font);
-}
-
-    static int
-hex_digit(int c)
-{
-    if (VIM_ISDIGIT(c))
-	return c - '0';
-    c = TOLOWER_ASC(c);
-    if (c >= 'a' && c <= 'f')
-	return c - 'a' + 10;
-    return -1000;
-}
-/*
- * Return the Pixel value (color) for the given color name.
- * Return INVALCOLOR for error.
- */
-    guicolor_T
-gui_mch_get_color(char_u *name)
-{
-    typedef struct guicolor_tTable
-    {
-	char	    *name;
-	COLORREF    color;
-    } guicolor_tTable;
-
-    static guicolor_tTable table[] =
-    {
-	{"Black",		RGB(0x00, 0x00, 0x00)},
-	{"DarkGray",		RGB(0xA9, 0xA9, 0xA9)},
-	{"DarkGrey",		RGB(0xA9, 0xA9, 0xA9)},
-	{"Gray",		RGB(0xC0, 0xC0, 0xC0)},
-	{"Grey",		RGB(0xC0, 0xC0, 0xC0)},
-	{"LightGray",		RGB(0xD3, 0xD3, 0xD3)},
-	{"LightGrey",		RGB(0xD3, 0xD3, 0xD3)},
-	{"Gray10",		RGB(0x1A, 0x1A, 0x1A)},
-	{"Grey10",		RGB(0x1A, 0x1A, 0x1A)},
-	{"Gray20",		RGB(0x33, 0x33, 0x33)},
-	{"Grey20",		RGB(0x33, 0x33, 0x33)},
-	{"Gray30",		RGB(0x4D, 0x4D, 0x4D)},
-	{"Grey30",		RGB(0x4D, 0x4D, 0x4D)},
-	{"Gray40",		RGB(0x66, 0x66, 0x66)},
-	{"Grey40",		RGB(0x66, 0x66, 0x66)},
-	{"Gray50",		RGB(0x7F, 0x7F, 0x7F)},
-	{"Grey50",		RGB(0x7F, 0x7F, 0x7F)},
-	{"Gray60",		RGB(0x99, 0x99, 0x99)},
-	{"Grey60",		RGB(0x99, 0x99, 0x99)},
-	{"Gray70",		RGB(0xB3, 0xB3, 0xB3)},
-	{"Grey70",		RGB(0xB3, 0xB3, 0xB3)},
-	{"Gray80",		RGB(0xCC, 0xCC, 0xCC)},
-	{"Grey80",		RGB(0xCC, 0xCC, 0xCC)},
-	{"Gray90",		RGB(0xE5, 0xE5, 0xE5)},
-	{"Grey90",		RGB(0xE5, 0xE5, 0xE5)},
-	{"White",		RGB(0xFF, 0xFF, 0xFF)},
-	{"DarkRed",		RGB(0x80, 0x00, 0x00)},
-	{"Red",			RGB(0xFF, 0x00, 0x00)},
-	{"LightRed",		RGB(0xFF, 0xA0, 0xA0)},
-	{"DarkBlue",		RGB(0x00, 0x00, 0x80)},
-	{"Blue",		RGB(0x00, 0x00, 0xFF)},
-	{"LightBlue",		RGB(0xAD, 0xD8, 0xE6)},
-	{"DarkGreen",		RGB(0x00, 0x80, 0x00)},
-	{"Green",		RGB(0x00, 0xFF, 0x00)},
-	{"LightGreen",		RGB(0x90, 0xEE, 0x90)},
-	{"DarkCyan",		RGB(0x00, 0x80, 0x80)},
-	{"Cyan",		RGB(0x00, 0xFF, 0xFF)},
-	{"LightCyan",		RGB(0xE0, 0xFF, 0xFF)},
-	{"DarkMagenta",		RGB(0x80, 0x00, 0x80)},
-	{"Magenta",		RGB(0xFF, 0x00, 0xFF)},
-	{"LightMagenta",	RGB(0xFF, 0xA0, 0xFF)},
-	{"Brown",		RGB(0x80, 0x40, 0x40)},
-	{"Yellow",		RGB(0xFF, 0xFF, 0x00)},
-	{"LightYellow",		RGB(0xFF, 0xFF, 0xE0)},
-	{"DarkYellow",		RGB(0xBB, 0xBB, 0x00)},
-	{"SeaGreen",		RGB(0x2E, 0x8B, 0x57)},
-	{"Orange",		RGB(0xFF, 0xA5, 0x00)},
-	{"Purple",		RGB(0xA0, 0x20, 0xF0)},
-	{"SlateBlue",		RGB(0x6A, 0x5A, 0xCD)},
-	{"Violet",		RGB(0xEE, 0x82, 0xEE)},
-    };
-
-    typedef struct SysColorTable
-    {
-	char	    *name;
-	int	    color;
-    } SysColorTable;
-
-    static SysColorTable sys_table[] =
-    {
-#ifdef WIN3264
-	{"SYS_3DDKSHADOW", COLOR_3DDKSHADOW},
-	{"SYS_3DHILIGHT", COLOR_3DHILIGHT},
-#ifndef __MINGW32__
-	{"SYS_3DHIGHLIGHT", COLOR_3DHIGHLIGHT},
-#endif
-	{"SYS_BTNHILIGHT", COLOR_BTNHILIGHT},
-	{"SYS_BTNHIGHLIGHT", COLOR_BTNHIGHLIGHT},
-	{"SYS_3DLIGHT", COLOR_3DLIGHT},
-	{"SYS_3DSHADOW", COLOR_3DSHADOW},
-	{"SYS_DESKTOP", COLOR_DESKTOP},
-	{"SYS_INFOBK", COLOR_INFOBK},
-	{"SYS_INFOTEXT", COLOR_INFOTEXT},
-	{"SYS_3DFACE", COLOR_3DFACE},
-#endif
-	{"SYS_BTNFACE", COLOR_BTNFACE},
-	{"SYS_BTNSHADOW", COLOR_BTNSHADOW},
-	{"SYS_ACTIVEBORDER", COLOR_ACTIVEBORDER},
-	{"SYS_ACTIVECAPTION", COLOR_ACTIVECAPTION},
-	{"SYS_APPWORKSPACE", COLOR_APPWORKSPACE},
-	{"SYS_BACKGROUND", COLOR_BACKGROUND},
-	{"SYS_BTNTEXT", COLOR_BTNTEXT},
-	{"SYS_CAPTIONTEXT", COLOR_CAPTIONTEXT},
-	{"SYS_GRAYTEXT", COLOR_GRAYTEXT},
-	{"SYS_HIGHLIGHT", COLOR_HIGHLIGHT},
-	{"SYS_HIGHLIGHTTEXT", COLOR_HIGHLIGHTTEXT},
-	{"SYS_INACTIVEBORDER", COLOR_INACTIVEBORDER},
-	{"SYS_INACTIVECAPTION", COLOR_INACTIVECAPTION},
-	{"SYS_INACTIVECAPTIONTEXT", COLOR_INACTIVECAPTIONTEXT},
-	{"SYS_MENU", COLOR_MENU},
-	{"SYS_MENUTEXT", COLOR_MENUTEXT},
-	{"SYS_SCROLLBAR", COLOR_SCROLLBAR},
-	{"SYS_WINDOW", COLOR_WINDOW},
-	{"SYS_WINDOWFRAME", COLOR_WINDOWFRAME},
-	{"SYS_WINDOWTEXT", COLOR_WINDOWTEXT}
-    };
-
-    int		    r, g, b;
-    int		    i;
-
-    if (name[0] == '#' && STRLEN(name) == 7)
-    {
-	/* Name is in "#rrggbb" format */
-	r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
-	g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
-	b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
-	if (r < 0 || g < 0 || b < 0)
-	    return INVALCOLOR;
-	return RGB(r, g, b);
-    }
-    else
-    {
-	/* Check if the name is one of the colors we know */
-	for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
-	    if (STRICMP(name, table[i].name) == 0)
-		return table[i].color;
-    }
-
-    /*
-     * Try to look up a system colour.
-     */
-    for (i = 0; i < sizeof(sys_table) / sizeof(sys_table[0]); i++)
-	if (STRICMP(name, sys_table[i].name) == 0)
-	    return GetSysColor(sys_table[i].color);
-
-    /*
-     * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
-     */
-    {
-#define LINE_LEN 100
-	FILE	*fd;
-	char	line[LINE_LEN];
-	char_u	*fname;
-
-	fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
-	if (fname == NULL)
-	    return INVALCOLOR;
-
-	fd = mch_fopen((char *)fname, "rt");
-	vim_free(fname);
-	if (fd == NULL)
-	    return INVALCOLOR;
-
-	while (!feof(fd))
-	{
-	    int	    len;
-	    int	    pos;
-	    char    *color;
-
-	    fgets(line, LINE_LEN, fd);
-	    len = (int)STRLEN(line);
-
-	    if (len <= 1 || line[len-1] != '\n')
-		continue;
-
-	    line[len-1] = '\0';
-
-	    i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
-	    if (i != 3)
-		continue;
-
-	    color = line + pos;
-
-	    if (STRICMP(color, name) == 0)
-	    {
-		fclose(fd);
-		return (guicolor_T) RGB(r, g, b);
-	    }
-	}
-
-	fclose(fd);
-    }
-
-    return INVALCOLOR;
-}
-/*
- * Return OK if the key with the termcap name "name" is supported.
- */
-    int
-gui_mch_haskey(char_u *name)
-{
-    int i;
-
-    for (i = 0; special_keys[i].vim_code1 != NUL; i++)
-	if (name[0] == special_keys[i].vim_code0 &&
-					 name[1] == special_keys[i].vim_code1)
-	    return OK;
-    return FAIL;
-}
-
-    void
-gui_mch_beep(void)
-{
-    MessageBeep(MB_OK);
-}
-/*
- * Invert a rectangle from row r, column c, for nr rows and nc columns.
- */
-    void
-gui_mch_invert_rectangle(
-    int	    r,
-    int	    c,
-    int	    nr,
-    int	    nc)
-{
-    RECT    rc;
-
-    /*
-     * Note: InvertRect() excludes right and bottom of rectangle.
-     */
-    rc.left = FILL_X(c);
-    rc.top = FILL_Y(r);
-    rc.right = rc.left + nc * gui.char_width;
-    rc.bottom = rc.top + nr * gui.char_height;
-    InvertRect(s_hdc, &rc);
-}
-
-/*
- * Iconify the GUI window.
- */
-    void
-gui_mch_iconify(void)
-{
-    ShowWindow(s_hwnd, SW_MINIMIZE);
-}
-
-/*
- * Draw a cursor without focus.
- */
-    void
-gui_mch_draw_hollow_cursor(guicolor_T color)
-{
-    HBRUSH  hbr;
-    RECT    rc;
-
-    /*
-     * Note: FrameRect() excludes right and bottom of rectangle.
-     */
-    rc.left = FILL_X(gui.col);
-    rc.top = FILL_Y(gui.row);
-    rc.right = rc.left + gui.char_width;
-#ifdef FEAT_MBYTE
-    if (mb_lefthalve(gui.row, gui.col))
-	rc.right += gui.char_width;
-#endif
-    rc.bottom = rc.top + gui.char_height;
-    hbr = CreateSolidBrush(color);
-    FrameRect(s_hdc, &rc, hbr);
-    DeleteBrush(hbr);
-}
-/*
- * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
- * color "color".
- */
-    void
-gui_mch_draw_part_cursor(
-    int		w,
-    int		h,
-    guicolor_T	color)
-{
-    HBRUSH	hbr;
-    RECT	rc;
-
-    /*
-     * Note: FillRect() excludes right and bottom of rectangle.
-     */
-    rc.left =
-#ifdef FEAT_RIGHTLEFT
-		/* vertical line should be on the right of current point */
-		CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
-#endif
-		    FILL_X(gui.col);
-    rc.top = FILL_Y(gui.row) + gui.char_height - h;
-    rc.right = rc.left + w;
-    rc.bottom = rc.top + h;
-    hbr = CreateSolidBrush(color);
-    FillRect(s_hdc, &rc, hbr);
-    DeleteBrush(hbr);
-}
-
-
-/*
- * Generates a VK_SPACE when the internal dead_key flag is set to output the
- * dead key's nominal character and re-post the original message.
- */
-    static void
-outputDeadKey_rePost(MSG originalMsg)
-{
-    static MSG deadCharExpel;
-
-    if (!dead_key)
-	return;
-
-    dead_key = 0;
-
-    /* Make Windows generate the dead key's character */
-    deadCharExpel.message = originalMsg.message;
-    deadCharExpel.hwnd    = originalMsg.hwnd;
-    deadCharExpel.wParam  = VK_SPACE;
-
-    MyTranslateMessage(&deadCharExpel);
-
-    /* re-generate the current character free of the dead char influence */
-    PostMessage(originalMsg.hwnd, originalMsg.message, originalMsg.wParam,
-							  originalMsg.lParam);
-}
-
-
-/*
- * Process a single Windows message.
- * If one is not available we hang until one is.
- */
-    static void
-process_message(void)
-{
-    MSG		msg;
-    UINT	vk = 0;		/* Virtual key */
-    char_u	string[40];
-    int		i;
-    int		modifiers = 0;
-    int		key;
-#ifdef FEAT_MENU
-    static char_u k10[] = {K_SPECIAL, 'k', ';', 0};
-#endif
-
-    pGetMessage(&msg, NULL, 0, 0);
-
-#ifdef FEAT_OLE
-    /* Look after OLE Automation commands */
-    if (msg.message == WM_OLE)
-    {
-	char_u *str = (char_u *)msg.lParam;
-	if (str == NULL || *str == NUL)
-	{
-	    /* Message can't be ours, forward it.  Fixes problem with Ultramon
-	     * 3.0.4 */
-	    pDispatchMessage(&msg);
-	}
-	else
-	{
-	    add_to_input_buf(str, (int)STRLEN(str));
-	    vim_free(str);  /* was allocated in CVim::SendKeys() */
-	}
-	return;
-    }
-#endif
-
-#ifdef FEAT_CHANNEL
-    if (msg.message == WM_NETBEANS)
-    {
-	int	    what;
-	channel_T   *channel = channel_fd2channel((sock_T)msg.wParam, &what);
-
-	if (channel != NULL)
-	{
-	    /* Disable error messages, they can mess up the display and throw
-	     * an exception. */
-	    ++emsg_off;
-	    channel_read(channel, what, "process_message");
-	    --emsg_off;
-	}
-	return;
-    }
-#endif
-
-#ifdef FEAT_SNIFF
-    if (sniff_request_waiting && want_sniff_request)
-    {
-	static char_u bytes[3] = {CSI, (char_u)KS_EXTRA, (char_u)KE_SNIFF};
-	add_to_input_buf(bytes, 3); /* K_SNIFF */
-	sniff_request_waiting = 0;
-	want_sniff_request = 0;
-	/* request is handled in normal.c */
-    }
-    if (msg.message == WM_USER)
-    {
-	MyTranslateMessage(&msg);
-	pDispatchMessage(&msg);
-	return;
-    }
-#endif
-
-#ifdef MSWIN_FIND_REPLACE
-    /* Don't process messages used by the dialog */
-    if (s_findrep_hwnd != NULL && pIsDialogMessage(s_findrep_hwnd, &msg))
-    {
-	HandleMouseHide(msg.message, msg.lParam);
-	return;
-    }
-#endif
-
-    /*
-     * Check if it's a special key that we recognise.  If not, call
-     * TranslateMessage().
-     */
-    if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
-    {
-	vk = (int) msg.wParam;
-
-	/*
-	 * Handle dead keys in special conditions in other cases we let Windows
-	 * handle them and do not interfere.
-	 *
-	 * The dead_key flag must be reset on several occasions:
-	 * - in _OnChar() (or _OnSysChar()) as any dead key was necessarily
-	 *   consumed at that point (This is when we let Windows combine the
-	 *   dead character on its own)
-	 *
-	 * - Before doing something special such as regenerating keypresses to
-	 *   expel the dead character as this could trigger an infinite loop if
-	 *   for some reason MyTranslateMessage() do not trigger a call
-	 *   immediately to _OnChar() (or _OnSysChar()).
-	 */
-	if (dead_key)
-	{
-	    /*
-	     * If a dead key was pressed and the user presses VK_SPACE,
-	     * VK_BACK, or VK_ESCAPE it means that he actually wants to deal
-	     * with the dead char now, so do nothing special and let Windows
-	     * handle it.
-	     *
-	     * Note that VK_SPACE combines with the dead_key's character and
-	     * only one WM_CHAR will be generated by TranslateMessage(), in
-	     * the two other cases two WM_CHAR will be generated: the dead
-	     * char and VK_BACK or VK_ESCAPE. That is most likely what the
-	     * user expects.
-	     */
-	    if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE))
-	    {
-		dead_key = 0;
-		MyTranslateMessage(&msg);
-		return;
-	    }
-	    /* In modes where we are not typing, dead keys should behave
-	     * normally */
-	    else if (!(get_real_state() & (INSERT | CMDLINE | SELECTMODE)))
-	    {
-		outputDeadKey_rePost(msg);
-		return;
-	    }
-	}
-
-	/* Check for CTRL-BREAK */
-	if (vk == VK_CANCEL)
-	{
-	    trash_input_buf();
-	    got_int = TRUE;
-	    string[0] = Ctrl_C;
-	    add_to_input_buf(string, 1);
-	}
-
-	for (i = 0; special_keys[i].key_sym != 0; i++)
-	{
-	    /* ignore VK_SPACE when ALT key pressed: system menu */
-	    if (special_keys[i].key_sym == vk
-		    && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000)))
-	    {
-		/*
-		 * Behave as exected if we have a dead key and the special key
-		 * is a key that would normally trigger the dead key nominal
-		 * character output (such as a NUMPAD printable character or
-		 * the TAB key, etc...).
-		 */
-		if (dead_key && (special_keys[i].vim_code0 == 'K'
-						|| vk == VK_TAB || vk == CAR))
-		{
-		    outputDeadKey_rePost(msg);
-		    return;
-		}
-
-#ifdef FEAT_MENU
-		/* Check for <F10>: Windows selects the menu.  When <F10> is
-		 * mapped we want to use the mapping instead. */
-		if (vk == VK_F10
-			&& gui.menu_is_active
-			&& check_map(k10, State, FALSE, TRUE, FALSE,
-							  NULL, NULL) == NULL)
-		    break;
-#endif
-		if (GetKeyState(VK_SHIFT) & 0x8000)
-		    modifiers |= MOD_MASK_SHIFT;
-		/*
-		 * Don't use caps-lock as shift, because these are special keys
-		 * being considered here, and we only want letters to get
-		 * shifted -- webb
-		 */
-		/*
-		if (GetKeyState(VK_CAPITAL) & 0x0001)
-		    modifiers ^= MOD_MASK_SHIFT;
-		*/
-		if (GetKeyState(VK_CONTROL) & 0x8000)
-		    modifiers |= MOD_MASK_CTRL;
-		if (GetKeyState(VK_MENU) & 0x8000)
-		    modifiers |= MOD_MASK_ALT;
-
-		if (special_keys[i].vim_code1 == NUL)
-		    key = special_keys[i].vim_code0;
-		else
-		    key = TO_SPECIAL(special_keys[i].vim_code0,
-						   special_keys[i].vim_code1);
-		key = simplify_key(key, &modifiers);
-		if (key == CSI)
-		    key = K_CSI;
-
-		if (modifiers)
-		{
-		    string[0] = CSI;
-		    string[1] = KS_MODIFIER;
-		    string[2] = modifiers;
-		    add_to_input_buf(string, 3);
-		}
-
-		if (IS_SPECIAL(key))
-		{
-		    string[0] = CSI;
-		    string[1] = K_SECOND(key);
-		    string[2] = K_THIRD(key);
-		    add_to_input_buf(string, 3);
-		}
-		else
-		{
-		    int	len;
-
-		    /* Handle "key" as a Unicode character. */
-		    len = char_to_string(key, string, 40, FALSE);
-		    add_to_input_buf(string, len);
-		}
-		break;
-	    }
-	}
-	if (special_keys[i].key_sym == 0)
-	{
-	    /* Some keys need C-S- where they should only need C-.
-	     * Ignore 0xff, Windows XP sends it when NUMLOCK has changed since
-	     * system startup (Helmut Stiegler, 2003 Oct 3). */
-	    if (vk != 0xff
-		    && (GetKeyState(VK_CONTROL) & 0x8000)
-		    && !(GetKeyState(VK_SHIFT) & 0x8000)
-		    && !(GetKeyState(VK_MENU) & 0x8000))
-	    {
-		/* CTRL-6 is '^'; Japanese keyboard maps '^' to vk == 0xDE */
-		if (vk == '6' || MapVirtualKey(vk, 2) == (UINT)'^')
-		{
-		    string[0] = Ctrl_HAT;
-		    add_to_input_buf(string, 1);
-		}
-		/* vk == 0xBD AZERTY for CTRL-'-', but CTRL-[ for * QWERTY! */
-		else if (vk == 0xBD)	/* QWERTY for CTRL-'-' */
-		{
-		    string[0] = Ctrl__;
-		    add_to_input_buf(string, 1);
-		}
-		/* CTRL-2 is '@'; Japanese keyboard maps '@' to vk == 0xC0 */
-		else if (vk == '2' || MapVirtualKey(vk, 2) == (UINT)'@')
-		{
-		    string[0] = Ctrl_AT;
-		    add_to_input_buf(string, 1);
-		}
-		else
-		    MyTranslateMessage(&msg);
-	    }
-	    else
-		MyTranslateMessage(&msg);
-	}
-    }
-#ifdef FEAT_MBYTE_IME
-    else if (msg.message == WM_IME_NOTIFY)
-	_OnImeNotify(msg.hwnd, (DWORD)msg.wParam, (DWORD)msg.lParam);
-    else if (msg.message == WM_KEYUP && im_get_status())
-	/* added for non-MS IME (Yasuhiro Matsumoto) */
-	MyTranslateMessage(&msg);
-#endif
-#if !defined(FEAT_MBYTE_IME) && defined(GLOBAL_IME)
-/* GIME_TEST */
-    else if (msg.message == WM_IME_STARTCOMPOSITION)
-    {
-	POINT point;
-
-	global_ime_set_font(&norm_logfont);
-	point.x = FILL_X(gui.col);
-	point.y = FILL_Y(gui.row);
-	MapWindowPoints(s_textArea, s_hwnd, &point, 1);
-	global_ime_set_position(&point);
-    }
-#endif
-
-#ifdef FEAT_MENU
-    /* Check for <F10>: Default effect is to select the menu.  When <F10> is
-     * mapped we need to stop it here to avoid strange effects (e.g., for the
-     * key-up event) */
-    if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE,
-							  NULL, NULL) == NULL)
-#endif
-	pDispatchMessage(&msg);
-}
-
-/*
- * Catch up with any queued events.  This may put keyboard input into the
- * input buffer, call resize call-backs, trigger timers etc.  If there is
- * nothing in the event queue (& no timers pending), then we return
- * immediately.
- */
-    void
-gui_mch_update(void)
-{
-    MSG	    msg;
-
-    if (!s_busy_processing)
-	while (pPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
-						  && !vim_is_input_buf_full())
-	    process_message();
-}
-
-/*
- * GUI input routine called by gui_wait_for_chars().  Waits for a character
- * from the keyboard.
- *  wtime == -1	    Wait forever.
- *  wtime == 0	    This should never happen.
- *  wtime > 0	    Wait wtime milliseconds for a character.
- * Returns OK if a character was found to be available within the given time,
- * or FAIL otherwise.
- */
-    int
-gui_mch_wait_for_chars(int wtime)
-{
-    MSG		msg;
-    int		focus;
-
-    s_timed_out = FALSE;
-
-    if (wtime > 0)
-    {
-	/* Don't do anything while processing a (scroll) message. */
-	if (s_busy_processing)
-	    return FAIL;
-	s_wait_timer = (UINT)SetTimer(NULL, 0, (UINT)wtime,
-							 (TIMERPROC)_OnTimer);
-    }
-
-    allow_scrollbar = TRUE;
-
-    focus = gui.in_focus;
-    while (!s_timed_out)
-    {
-	/* Stop or start blinking when focus changes */
-	if (gui.in_focus != focus)
-	{
-	    if (gui.in_focus)
-		gui_mch_start_blink();
-	    else
-		gui_mch_stop_blink();
-	    focus = gui.in_focus;
-	}
-
-	if (s_need_activate)
-	{
-#ifdef WIN32
-	    (void)SetForegroundWindow(s_hwnd);
-#else
-	    (void)SetActiveWindow(s_hwnd);
-#endif
-	    s_need_activate = FALSE;
-	}
-
-#ifdef MESSAGE_QUEUE
-	parse_queued_messages();
-#endif
-
-#ifdef FEAT_CHANNEL
-	channel_handle_events();
-#endif
-
-	/*
-	 * Don't use gui_mch_update() because then we will spin-lock until a
-	 * char arrives, instead we use GetMessage() to hang until an
-	 * event arrives.  No need to check for input_buf_full because we are
-	 * returning as soon as it contains a single char -- webb
-	 */
-	process_message();
-
-	if (input_available())
-	{
-	    if (s_wait_timer != 0 && !s_timed_out)
-	    {
-		KillTimer(NULL, s_wait_timer);
-
-		/* Eat spurious WM_TIMER messages */
-		while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
-		    ;
-		s_wait_timer = 0;
-	    }
-	    allow_scrollbar = FALSE;
-
-	    /* Clear pending mouse button, the release event may have been
-	     * taken by the dialog window.  But don't do this when getting
-	     * focus, we need the mouse-up event then. */
-	    if (!s_getting_focus)
-		s_button_pending = -1;
-
-	    return OK;
-	}
-    }
-    allow_scrollbar = FALSE;
-    return FAIL;
-}
-
-/*
- * Clear a rectangular region of the screen from text pos (row1, col1) to
- * (row2, col2) inclusive.
- */
-    void
-gui_mch_clear_block(
-    int		row1,
-    int		col1,
-    int		row2,
-    int		col2)
-{
-    RECT	rc;
-
-    /*
-     * Clear one extra pixel at the far right, for when bold characters have
-     * spilled over to the window border.
-     * Note: FillRect() excludes right and bottom of rectangle.
-     */
-    rc.left = FILL_X(col1);
-    rc.top = FILL_Y(row1);
-    rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
-    rc.bottom = FILL_Y(row2 + 1);
-    clear_rect(&rc);
-}
-
-/*
- * Clear the whole text window.
- */
-    void
-gui_mch_clear_all(void)
-{
-    RECT    rc;
-
-    rc.left = 0;
-    rc.top = 0;
-    rc.right = Columns * gui.char_width + 2 * gui.border_width;
-    rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
-    clear_rect(&rc);
-}
-/*
- * Menu stuff.
- */
-
-    void
-gui_mch_enable_menu(int flag)
-{
-#ifdef FEAT_MENU
-    SetMenu(s_hwnd, flag ? s_menuBar : NULL);
-#endif
-}
-
-/*ARGSUSED*/
-    void
-gui_mch_set_menu_pos(
-    int	    x,
-    int	    y,
-    int	    w,
-    int	    h)
-{
-    /* It will be in the right place anyway */
-}
-
-#if defined(FEAT_MENU) || defined(PROTO)
-/*
- * Make menu item hidden or not hidden
- */
-    void
-gui_mch_menu_hidden(
-    vimmenu_T	*menu,
-    int		hidden)
-{
-    /*
-     * This doesn't do what we want.  Hmm, just grey the menu items for now.
-     */
-    /*
-    if (hidden)
-	EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_DISABLED);
-    else
-	EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED);
-    */
-    gui_mch_menu_grey(menu, hidden);
-}
-
-/*
- * This is called after setting all the menus to grey/hidden or not.
- */
-    void
-gui_mch_draw_menubar(void)
-{
-    DrawMenuBar(s_hwnd);
-}
-#endif /*FEAT_MENU*/
-
-#ifndef PROTO
-void
-#ifdef VIMDLL
-_export
-#endif
-_cdecl
-SaveInst(HINSTANCE hInst)
-{
-    s_hinst = hInst;
-}
-#endif
-
-/*
- * Return the RGB value of a pixel as a long.
- */
-    long_u
-gui_mch_get_rgb(guicolor_T pixel)
-{
-    return (GetRValue(pixel) << 16) + (GetGValue(pixel) << 8)
-							   + GetBValue(pixel);
-}
-
-#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
-/* Convert pixels in X to dialog units */
-    static WORD
-PixelToDialogX(int numPixels)
-{
-    return (WORD)((numPixels * 4) / s_dlgfntwidth);
-}
-
-/* Convert pixels in Y to dialog units */
-    static WORD
-PixelToDialogY(int numPixels)
-{
-    return (WORD)((numPixels * 8) / s_dlgfntheight);
-}
-
-/* Return the width in pixels of the given text in the given DC. */
-    static int
-GetTextWidth(HDC hdc, char_u *str, int len)
-{
-    SIZE    size;
-
-    GetTextExtentPoint(hdc, (LPCSTR)str, len, &size);
-    return size.cx;
-}
-
-#ifdef FEAT_MBYTE
-/*
- * Return the width in pixels of the given text in the given DC, taking care
- * of 'encoding' to active codepage conversion.
- */
-    static int
-GetTextWidthEnc(HDC hdc, char_u *str, int len)
-{
-    SIZE	size;
-    WCHAR	*wstr;
-    int		n;
-    int		wlen = len;
-
-    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-    {
-	/* 'encoding' differs from active codepage: convert text and use wide
-	 * function */
-	wstr = enc_to_utf16(str, &wlen);
-	if (wstr != NULL)
-	{
-	    n = GetTextExtentPointW(hdc, wstr, wlen, &size);
-	    vim_free(wstr);
-	    if (n)
-		return size.cx;
-	}
-    }
-
-    return GetTextWidth(hdc, str, len);
-}
-#else
-# define GetTextWidthEnc(h, s, l) GetTextWidth((h), (s), (l))
-#endif
-
-/*
- * A quick little routine that will center one window over another, handy for
- * dialog boxes.  Taken from the Win32SDK samples.
- */
-    static BOOL
-CenterWindow(
-    HWND hwndChild,
-    HWND hwndParent)
-{
-    RECT    rChild, rParent;
-    int     wChild, hChild, wParent, hParent;
-    int     wScreen, hScreen, xNew, yNew;
-    HDC     hdc;
-
-    GetWindowRect(hwndChild, &rChild);
-    wChild = rChild.right - rChild.left;
-    hChild = rChild.bottom - rChild.top;
-
-    /* If Vim is minimized put the window in the middle of the screen. */
-    if (hwndParent == NULL || IsMinimized(hwndParent))
-    {
-#ifdef WIN16
-	rParent.left = 0;
-	rParent.top = 0;
-	rParent.right = GetSystemMetrics(SM_CXSCREEN);
-	rParent.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
-#else
-	SystemParametersInfo(SPI_GETWORKAREA, 0, &rParent, 0);
-#endif
-    }
-    else
-	GetWindowRect(hwndParent, &rParent);
-    wParent = rParent.right - rParent.left;
-    hParent = rParent.bottom - rParent.top;
-
-    hdc = GetDC(hwndChild);
-    wScreen = GetDeviceCaps (hdc, HORZRES);
-    hScreen = GetDeviceCaps (hdc, VERTRES);
-    ReleaseDC(hwndChild, hdc);
-
-    xNew = rParent.left + ((wParent - wChild) /2);
-    if (xNew < 0)
-    {
-	xNew = 0;
-    }
-    else if ((xNew+wChild) > wScreen)
-    {
-	xNew = wScreen - wChild;
-    }
-
-    yNew = rParent.top	+ ((hParent - hChild) /2);
-    if (yNew < 0)
-	yNew = 0;
-    else if ((yNew+hChild) > hScreen)
-	yNew = hScreen - hChild;
-
-    return SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0,
-						   SWP_NOSIZE | SWP_NOZORDER);
-}
-#endif /* FEAT_GUI_DIALOG */
-
-void
-gui_mch_activate_window(void)
-{
-    (void)SetActiveWindow(s_hwnd);
-}
-
-#if defined(FEAT_TOOLBAR) || defined(PROTO)
-    void
-gui_mch_show_toolbar(int showit)
-{
-    if (s_toolbarhwnd == NULL)
-	return;
-
-    if (showit)
-    {
-# ifdef FEAT_MBYTE
-#  ifndef TB_SETUNICODEFORMAT
-    /* For older compilers.  We assume this never changes. */
-#   define TB_SETUNICODEFORMAT 0x2005
-#  endif
-	/* Enable/disable unicode support */
-	int uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage);
-	SendMessage(s_toolbarhwnd, TB_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0);
-# endif
-	ShowWindow(s_toolbarhwnd, SW_SHOW);
-    }
-    else
-	ShowWindow(s_toolbarhwnd, SW_HIDE);
-}
-
-/* Then number of bitmaps is fixed.  Exit is missing! */
-#define TOOLBAR_BITMAP_COUNT 31
-
-#endif
-
-#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
-    static void
-add_tabline_popup_menu_entry(HMENU pmenu, UINT item_id, char_u *item_text)
-{
-#ifdef FEAT_MBYTE
-    WCHAR	*wn = NULL;
-    int		n;
-
-    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-    {
-	/* 'encoding' differs from active codepage: convert menu name
-	 * and use wide function */
-	wn = enc_to_utf16(item_text, NULL);
-	if (wn != NULL)
-	{
-	    MENUITEMINFOW	infow;
-
-	    infow.cbSize = sizeof(infow);
-	    infow.fMask = MIIM_TYPE | MIIM_ID;
-	    infow.wID = item_id;
-	    infow.fType = MFT_STRING;
-	    infow.dwTypeData = wn;
-	    infow.cch = (UINT)wcslen(wn);
-	    n = InsertMenuItemW(pmenu, item_id, FALSE, &infow);
-	    vim_free(wn);
-	    if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
-		/* Failed, try using non-wide function. */
-		wn = NULL;
-	}
-    }
-
-    if (wn == NULL)
-#endif
-    {
-	MENUITEMINFO	info;
-
-	info.cbSize = sizeof(info);
-	info.fMask = MIIM_TYPE | MIIM_ID;
-	info.wID = item_id;
-	info.fType = MFT_STRING;
-	info.dwTypeData = (LPTSTR)item_text;
-	info.cch = (UINT)STRLEN(item_text);
-	InsertMenuItem(pmenu, item_id, FALSE, &info);
-    }
-}
-
-    static void
-show_tabline_popup_menu(void)
-{
-    HMENU	    tab_pmenu;
-    long	    rval;
-    POINT	    pt;
-
-    /* When ignoring events don't show the menu. */
-    if (hold_gui_events
-# ifdef FEAT_CMDWIN
-	    || cmdwin_type != 0
-# endif
-       )
-	return;
-
-    tab_pmenu = CreatePopupMenu();
-    if (tab_pmenu == NULL)
-	return;
-
-    if (first_tabpage->tp_next != NULL)
-	add_tabline_popup_menu_entry(tab_pmenu,
-				TABLINE_MENU_CLOSE, (char_u *)_("Close tab"));
-    add_tabline_popup_menu_entry(tab_pmenu,
-				TABLINE_MENU_NEW, (char_u *)_("New tab"));
-    add_tabline_popup_menu_entry(tab_pmenu,
-				TABLINE_MENU_OPEN, (char_u *)_("Open tab..."));
-
-    GetCursorPos(&pt);
-    rval = TrackPopupMenuEx(tab_pmenu, TPM_RETURNCMD, pt.x, pt.y, s_tabhwnd,
-									NULL);
-
-    DestroyMenu(tab_pmenu);
-
-    /* Add the string cmd into input buffer */
-    if (rval > 0)
-    {
-	TCHITTESTINFO htinfo;
-	int idx;
-
-	if (ScreenToClient(s_tabhwnd, &pt) == 0)
-	    return;
-
-	htinfo.pt.x = pt.x;
-	htinfo.pt.y = pt.y;
-	idx = TabCtrl_HitTest(s_tabhwnd, &htinfo);
-	if (idx == -1)
-	    idx = 0;
-	else
-	    idx += 1;
-
-	send_tabline_menu_event(idx, (int)rval);
-    }
-}
-
-/*
- * Show or hide the tabline.
- */
-    void
-gui_mch_show_tabline(int showit)
-{
-    if (s_tabhwnd == NULL)
-	return;
-
-    if (!showit != !showing_tabline)
-    {
-	if (showit)
-	    ShowWindow(s_tabhwnd, SW_SHOW);
-	else
-	    ShowWindow(s_tabhwnd, SW_HIDE);
-	showing_tabline = showit;
-    }
-}
-
-/*
- * Return TRUE when tabline is displayed.
- */
-    int
-gui_mch_showing_tabline(void)
-{
-    return s_tabhwnd != NULL && showing_tabline;
-}
-
-/*
- * Update the labels of the tabline.
- */
-    void
-gui_mch_update_tabline(void)
-{
-    tabpage_T	*tp;
-    TCITEM	tie;
-    int		nr = 0;
-    int		curtabidx = 0;
-    int		tabadded = 0;
-#ifdef FEAT_MBYTE
-    static int	use_unicode = FALSE;
-    int		uu;
-    WCHAR	*wstr = NULL;
-#endif
-
-    if (s_tabhwnd == NULL)
-	return;
-
-#if defined(FEAT_MBYTE)
-# ifndef CCM_SETUNICODEFORMAT
-    /* For older compilers.  We assume this never changes. */
-#  define CCM_SETUNICODEFORMAT 0x2005
-# endif
-    uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage);
-    if (uu != use_unicode)
-    {
-	/* Enable/disable unicode support */
-	SendMessage(s_tabhwnd, CCM_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0);
-	use_unicode = uu;
-    }
-#endif
-
-    tie.mask = TCIF_TEXT;
-    tie.iImage = -1;
-
-    /* Disable redraw for tab updates to eliminate O(N^2) draws. */
-    SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)FALSE, 0);
-
-    /* Add a label for each tab page.  They all contain the same text area. */
-    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
-    {
-	if (tp == curtab)
-	    curtabidx = nr;
-
-	if (nr >= TabCtrl_GetItemCount(s_tabhwnd))
-	{
-	    /* Add the tab */
-	    tie.pszText = "-Empty-";
-	    TabCtrl_InsertItem(s_tabhwnd, nr, &tie);
-	    tabadded = 1;
-	}
-
-	get_tabline_label(tp, FALSE);
-	tie.pszText = (LPSTR)NameBuff;
-#ifdef FEAT_MBYTE
-	wstr = NULL;
-	if (use_unicode)
-	{
-	    /* Need to go through Unicode. */
-	    wstr = enc_to_utf16(NameBuff, NULL);
-	    if (wstr != NULL)
-	    {
-		TCITEMW		tiw;
-
-		tiw.mask = TCIF_TEXT;
-		tiw.iImage = -1;
-		tiw.pszText = wstr;
-		SendMessage(s_tabhwnd, TCM_SETITEMW, (WPARAM)nr, (LPARAM)&tiw);
-		vim_free(wstr);
-	    }
-	}
-	if (wstr == NULL)
-#endif
-	{
-	    TabCtrl_SetItem(s_tabhwnd, nr, &tie);
-	}
-    }
-
-    /* Remove any old labels. */
-    while (nr < TabCtrl_GetItemCount(s_tabhwnd))
-	TabCtrl_DeleteItem(s_tabhwnd, nr);
-
-    if (!tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx)
-	TabCtrl_SetCurSel(s_tabhwnd, curtabidx);
-
-    /* Re-enable redraw and redraw. */
-    SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)TRUE, 0);
-    RedrawWindow(s_tabhwnd, NULL, NULL,
-		    RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
-
-    if (tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx)
-	TabCtrl_SetCurSel(s_tabhwnd, curtabidx);
-}
-
-/*
- * Set the current tab to "nr".  First tab is 1.
- */
-    void
-gui_mch_set_curtab(int nr)
-{
-    if (s_tabhwnd == NULL)
-	return;
-
-    if (TabCtrl_GetCurSel(s_tabhwnd) != nr - 1)
-	TabCtrl_SetCurSel(s_tabhwnd, nr - 1);
-}
-
-#endif
-
-/*
- * ":simalt" command.
- */
-    void
-ex_simalt(exarg_T *eap)
-{
-    char_u *keys = eap->arg;
-
-    PostMessage(s_hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)0);
-    while (*keys)
-    {
-	if (*keys == '~')
-	    *keys = ' ';	    /* for showing system menu */
-	PostMessage(s_hwnd, WM_CHAR, (WPARAM)*keys, (LPARAM)0);
-	keys++;
-    }
-}
-
-/*
- * Create the find & replace dialogs.
- * You can't have both at once: ":find" when replace is showing, destroys
- * the replace dialog first, and the other way around.
- */
-#ifdef MSWIN_FIND_REPLACE
-    static void
-initialise_findrep(char_u *initial_string)
-{
-    int		wword = FALSE;
-    int		mcase = !p_ic;
-    char_u	*entry_text;
-
-    /* Get the search string to use. */
-    entry_text = get_find_dialog_text(initial_string, &wword, &mcase);
-
-    s_findrep_struct.hwndOwner = s_hwnd;
-    s_findrep_struct.Flags = FR_DOWN;
-    if (mcase)
-	s_findrep_struct.Flags |= FR_MATCHCASE;
-    if (wword)
-	s_findrep_struct.Flags |= FR_WHOLEWORD;
-    if (entry_text != NULL && *entry_text != NUL)
-	vim_strncpy((char_u *)s_findrep_struct.lpstrFindWhat, entry_text,
-					   s_findrep_struct.wFindWhatLen - 1);
-    vim_free(entry_text);
-}
-#endif
-
-    static void
-set_window_title(HWND hwnd, char *title)
-{
-#ifdef FEAT_MBYTE
-    if (title != NULL && enc_codepage >= 0 && enc_codepage != (int)GetACP())
-    {
-	WCHAR	*wbuf;
-	int	n;
-
-	/* Convert the title from 'encoding' to UTF-16. */
-	wbuf = (WCHAR *)enc_to_utf16((char_u *)title, NULL);
-	if (wbuf != NULL)
-	{
-	    n = SetWindowTextW(hwnd, wbuf);
-	    vim_free(wbuf);
-	    if (n != 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
-		return;
-	    /* Retry with non-wide function (for Windows 98). */
-	}
-    }
-#endif
-    (void)SetWindowText(hwnd, (LPCSTR)title);
-}
-
-    void
-gui_mch_find_dialog(exarg_T *eap)
-{
-#ifdef MSWIN_FIND_REPLACE
-    if (s_findrep_msg != 0)
-    {
-	if (IsWindow(s_findrep_hwnd) && !s_findrep_is_find)
-	    DestroyWindow(s_findrep_hwnd);
-
-	if (!IsWindow(s_findrep_hwnd))
-	{
-	    initialise_findrep(eap->arg);
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-	    /* If the OS is Windows NT, and 'encoding' differs from active
-	     * codepage: convert text and use wide function. */
-	    if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
-		    && enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-	    {
-		findrep_atow(&s_findrep_struct_w, &s_findrep_struct);
-		s_findrep_hwnd = FindTextW(
-					(LPFINDREPLACEW) &s_findrep_struct_w);
-	    }
-	    else
-# endif
-		s_findrep_hwnd = FindText((LPFINDREPLACE) &s_findrep_struct);
-	}
-
-	set_window_title(s_findrep_hwnd,
-			       _("Find string (use '\\\\' to find  a '\\')"));
-	(void)SetFocus(s_findrep_hwnd);
-
-	s_findrep_is_find = TRUE;
-    }
-#endif
-}
-
-
-    void
-gui_mch_replace_dialog(exarg_T *eap)
-{
-#ifdef MSWIN_FIND_REPLACE
-    if (s_findrep_msg != 0)
-    {
-	if (IsWindow(s_findrep_hwnd) && s_findrep_is_find)
-	    DestroyWindow(s_findrep_hwnd);
-
-	if (!IsWindow(s_findrep_hwnd))
-	{
-	    initialise_findrep(eap->arg);
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-	    if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
-		    && enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-	    {
-		findrep_atow(&s_findrep_struct_w, &s_findrep_struct);
-		s_findrep_hwnd = ReplaceTextW(
-					(LPFINDREPLACEW) &s_findrep_struct_w);
-	    }
-	    else
-# endif
-		s_findrep_hwnd = ReplaceText(
-					   (LPFINDREPLACE) &s_findrep_struct);
-	}
-
-	set_window_title(s_findrep_hwnd,
-			    _("Find & Replace (use '\\\\' to find  a '\\')"));
-	(void)SetFocus(s_findrep_hwnd);
-
-	s_findrep_is_find = FALSE;
-    }
-#endif
-}
-
-
-/*
- * Set visibility of the pointer.
- */
-    void
-gui_mch_mousehide(int hide)
-{
-    if (hide != gui.pointer_hidden)
-    {
-	ShowCursor(!hide);
-	gui.pointer_hidden = hide;
-    }
-}
-
-#ifdef FEAT_MENU
-    static void
-gui_mch_show_popupmenu_at(vimmenu_T *menu, int x, int y)
-{
-    /* Unhide the mouse, we don't get move events here. */
-    gui_mch_mousehide(FALSE);
-
-    (void)TrackPopupMenu(
-	(HMENU)menu->submenu_id,
-	TPM_LEFTALIGN | TPM_LEFTBUTTON,
-	x, y,
-	(int)0,	    /*reserved param*/
-	s_hwnd,
-	NULL);
-    /*
-     * NOTE: The pop-up menu can eat the mouse up event.
-     * We deal with this in normal.c.
-     */
-}
-#endif
-
-/*
- * Got a message when the system will go down.
- */
-    static void
-_OnEndSession(void)
-{
-    getout_preserve_modified(1);
-}
-
-/*
- * Get this message when the user clicks on the cross in the top right corner
- * of a Windows95 window.
- */
-/*ARGSUSED*/
-    static void
-_OnClose(
-    HWND hwnd)
-{
-    gui_shell_closed();
-}
-
-/*
- * Get a message when the window is being destroyed.
- */
-    static void
-_OnDestroy(
-    HWND hwnd)
-{
-#ifdef WIN16_3DLOOK
-    Ctl3dUnregister(s_hinst);
-#endif
-    if (!destroying)
-	_OnClose(hwnd);
-}
-
-    static void
-_OnPaint(
-    HWND hwnd)
-{
-    if (!IsMinimized(hwnd))
-    {
-	PAINTSTRUCT ps;
-
-	out_flush();	    /* make sure all output has been processed */
-	(void)BeginPaint(hwnd, &ps);
-#if defined(FEAT_DIRECTX)
-	if (IS_ENABLE_DIRECTX())
-	    DWriteContext_BeginDraw(s_dwc);
-#endif
-
-#ifdef FEAT_MBYTE
-	/* prevent multi-byte characters from misprinting on an invalid
-	 * rectangle */
-	if (has_mbyte)
-	{
-	    RECT rect;
-
-	    GetClientRect(hwnd, &rect);
-	    ps.rcPaint.left = rect.left;
-	    ps.rcPaint.right = rect.right;
-	}
-#endif
-
-	if (!IsRectEmpty(&ps.rcPaint))
-	{
-#if defined(FEAT_DIRECTX)
-	    if (IS_ENABLE_DIRECTX())
-		DWriteContext_BindDC(s_dwc, s_hdc, &ps.rcPaint);
-#endif
-	    gui_redraw(ps.rcPaint.left, ps.rcPaint.top,
-		    ps.rcPaint.right - ps.rcPaint.left + 1,
-		    ps.rcPaint.bottom - ps.rcPaint.top + 1);
-	}
-
-#if defined(FEAT_DIRECTX)
-	if (IS_ENABLE_DIRECTX())
-	    DWriteContext_EndDraw(s_dwc);
-#endif
-	EndPaint(hwnd, &ps);
-    }
-}
-
-/*ARGSUSED*/
-    static void
-_OnSize(
-    HWND hwnd,
-    UINT state,
-    int cx,
-    int cy)
-{
-    if (!IsMinimized(hwnd))
-    {
-	gui_resize_shell(cx, cy);
-
-#ifdef FEAT_MENU
-	/* Menu bar may wrap differently now */
-	gui_mswin_get_menu_height(TRUE);
-#endif
-    }
-}
-
-    static void
-_OnSetFocus(
-    HWND hwnd,
-    HWND hwndOldFocus)
-{
-    gui_focus_change(TRUE);
-    s_getting_focus = TRUE;
-    (void)MyWindowProc(hwnd, WM_SETFOCUS, (WPARAM)hwndOldFocus, 0);
-}
-
-    static void
-_OnKillFocus(
-    HWND hwnd,
-    HWND hwndNewFocus)
-{
-    gui_focus_change(FALSE);
-    s_getting_focus = FALSE;
-    (void)MyWindowProc(hwnd, WM_KILLFOCUS, (WPARAM)hwndNewFocus, 0);
-}
-
-/*
- * Get a message when the user switches back to vim
- */
-#ifdef WIN16
-    static BOOL
-#else
-    static LRESULT
-#endif
-_OnActivateApp(
-    HWND hwnd,
-    BOOL fActivate,
-#ifdef WIN16
-    HTASK dwThreadId
-#else
-    DWORD dwThreadId
-#endif
-	)
-{
-    /* we call gui_focus_change() in _OnSetFocus() */
-    /* gui_focus_change((int)fActivate); */
-    return MyWindowProc(hwnd, WM_ACTIVATEAPP, fActivate, (DWORD)dwThreadId);
-}
-
-#if defined(FEAT_WINDOWS) || defined(PROTO)
-    void
-gui_mch_destroy_scrollbar(scrollbar_T *sb)
-{
-    DestroyWindow(sb->id);
-}
-#endif
-
-/*
- * Get current mouse coordinates in text window.
- */
-    void
-gui_mch_getmouse(int *x, int *y)
-{
-    RECT rct;
-    POINT mp;
-
-    (void)GetWindowRect(s_textArea, &rct);
-    (void)GetCursorPos((LPPOINT)&mp);
-    *x = (int)(mp.x - rct.left);
-    *y = (int)(mp.y - rct.top);
-}
-
-/*
- * Move mouse pointer to character at (x, y).
- */
-    void
-gui_mch_setmouse(int x, int y)
-{
-    RECT rct;
-
-    (void)GetWindowRect(s_textArea, &rct);
-    (void)SetCursorPos(x + gui.border_offset + rct.left,
-		       y + gui.border_offset + rct.top);
-}
-
-    static void
-gui_mswin_get_valid_dimensions(
-    int w,
-    int h,
-    int *valid_w,
-    int *valid_h)
-{
-    int	    base_width, base_height;
-
-    base_width = gui_get_base_width()
-	+ (GetSystemMetrics(SM_CXFRAME) +
-	   GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
-    base_height = gui_get_base_height()
-	+ (GetSystemMetrics(SM_CYFRAME) +
-	   GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
-	+ GetSystemMetrics(SM_CYCAPTION)
-#ifdef FEAT_MENU
-	+ gui_mswin_get_menu_height(FALSE)
-#endif
-	;
-    *valid_w = base_width +
-		    ((w - base_width) / gui.char_width) * gui.char_width;
-    *valid_h = base_height +
-		    ((h - base_height) / gui.char_height) * gui.char_height;
-}
-
-    void
-gui_mch_flash(int msec)
-{
-    RECT    rc;
-
-    /*
-     * Note: InvertRect() excludes right and bottom of rectangle.
-     */
-    rc.left = 0;
-    rc.top = 0;
-    rc.right = gui.num_cols * gui.char_width;
-    rc.bottom = gui.num_rows * gui.char_height;
-    InvertRect(s_hdc, &rc);
-    gui_mch_flush();			/* make sure it's displayed */
-
-    ui_delay((long)msec, TRUE);	/* wait for a few msec */
-
-    InvertRect(s_hdc, &rc);
-}
-
-/*
- * Return flags used for scrolling.
- * The SW_INVALIDATE is required when part of the window is covered or
- * off-screen. Refer to MS KB Q75236.
- */
-    static int
-get_scroll_flags(void)
-{
-    HWND	hwnd;
-    RECT	rcVim, rcOther, rcDest;
-
-    GetWindowRect(s_hwnd, &rcVim);
-
-    /* Check if the window is partly above or below the screen.  We don't care
-     * about partly left or right of the screen, it is not relevant when
-     * scrolling up or down. */
-    if (rcVim.top < 0 || rcVim.bottom > GetSystemMetrics(SM_CYFULLSCREEN))
-	return SW_INVALIDATE;
-
-    /* Check if there is an window (partly) on top of us. */
-    for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; )
-	if (IsWindowVisible(hwnd))
-	{
-	    GetWindowRect(hwnd, &rcOther);
-	    if (IntersectRect(&rcDest, &rcVim, &rcOther))
-		return SW_INVALIDATE;
-	}
-    return 0;
-}
-
-/*
- * On some Intel GPUs, the regions drawn just prior to ScrollWindowEx()
- * may not be scrolled out properly.
- * For gVim, when _OnScroll() is repeated, the character at the
- * previous cursor position may be left drawn after scroll.
- * The problem can be avoided by calling GetPixel() to get a pixel in
- * the region before ScrollWindowEx().
- */
-    static void
-intel_gpu_workaround(void)
-{
-    GetPixel(s_hdc, FILL_X(gui.col), FILL_Y(gui.row));
-}
-
-/*
- * Delete the given number of lines from the given row, scrolling up any
- * text further down within the scroll region.
- */
-    void
-gui_mch_delete_lines(
-    int	    row,
-    int	    num_lines)
-{
-    RECT	rc;
-
-    intel_gpu_workaround();
-
-    rc.left = FILL_X(gui.scroll_region_left);
-    rc.right = FILL_X(gui.scroll_region_right + 1);
-    rc.top = FILL_Y(row);
-    rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
-
-    ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
-				    &rc, &rc, NULL, NULL, get_scroll_flags());
-
-    UpdateWindow(s_textArea);
-    /* This seems to be required to avoid the cursor disappearing when
-     * scrolling such that the cursor ends up in the top-left character on
-     * the screen...   But why?  (Webb) */
-    /* It's probably fixed by disabling drawing the cursor while scrolling. */
-    /* gui.cursor_is_valid = FALSE; */
-
-    gui_clear_block(gui.scroll_region_bot - num_lines + 1,
-						       gui.scroll_region_left,
-	gui.scroll_region_bot, gui.scroll_region_right);
-}
-
-/*
- * Insert the given number of lines before the given row, scrolling down any
- * following text within the scroll region.
- */
-    void
-gui_mch_insert_lines(
-    int		row,
-    int		num_lines)
-{
-    RECT	rc;
-
-    intel_gpu_workaround();
-
-    rc.left = FILL_X(gui.scroll_region_left);
-    rc.right = FILL_X(gui.scroll_region_right + 1);
-    rc.top = FILL_Y(row);
-    rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
-    /* The SW_INVALIDATE is required when part of the window is covered or
-     * off-screen.  How do we avoid it when it's not needed? */
-    ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
-				    &rc, &rc, NULL, NULL, get_scroll_flags());
-
-    UpdateWindow(s_textArea);
-
-    gui_clear_block(row, gui.scroll_region_left,
-				row + num_lines - 1, gui.scroll_region_right);
-}
-
-
-/*ARGSUSED*/
-    void
-gui_mch_exit(int rc)
-{
-#if defined(FEAT_DIRECTX)
-    DWriteContext_Close(s_dwc);
-    DWrite_Final();
-    s_dwc = NULL;
-#endif
-
-    ReleaseDC(s_textArea, s_hdc);
-    DeleteObject(s_brush);
-
-#ifdef FEAT_TEAROFF
-    /* Unload the tearoff bitmap */
-    (void)DeleteObject((HGDIOBJ)s_htearbitmap);
-#endif
-
-    /* Destroy our window (if we have one). */
-    if (s_hwnd != NULL)
-    {
-	destroying = TRUE;	/* ignore WM_DESTROY message now */
-	DestroyWindow(s_hwnd);
-    }
-
-#ifdef GLOBAL_IME
-    global_ime_end();
-#endif
-}
-
-    static char_u *
-logfont2name(LOGFONT lf)
-{
-    char	*p;
-    char	*res;
-    char	*charset_name;
-    char	*font_name = lf.lfFaceName;
-
-    charset_name = charset_id2name((int)lf.lfCharSet);
-#ifdef FEAT_MBYTE
-    /* Convert a font name from the current codepage to 'encoding'.
-     * TODO: Use Wide APIs (including LOGFONTW) instead of ANSI APIs. */
-    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-    {
-	int	len;
-	acp_to_enc((char_u *)lf.lfFaceName, (int)strlen(lf.lfFaceName),
-						(char_u **)&font_name, &len);
-    }
-#endif
-    res = (char *)alloc((unsigned)(strlen(font_name) + 20
-		    + (charset_name == NULL ? 0 : strlen(charset_name) + 2)));
-    if (res != NULL)
-    {
-	p = res;
-	/* make a normal font string out of the lf thing:*/
-	sprintf((char *)p, "%s:h%d", font_name, pixels_to_points(
-			 lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight, TRUE));
-	while (*p)
-	{
-	    if (*p == ' ')
-		*p = '_';
-	    ++p;
-	}
-#ifndef MSWIN16_FASTTEXT
-	if (lf.lfItalic)
-	    STRCAT(p, ":i");
-	if (lf.lfWeight >= FW_BOLD)
-	    STRCAT(p, ":b");
-#endif
-	if (lf.lfUnderline)
-	    STRCAT(p, ":u");
-	if (lf.lfStrikeOut)
-	    STRCAT(p, ":s");
-	if (charset_name != NULL)
-	{
-	    STRCAT(p, ":c");
-	    STRCAT(p, charset_name);
-	}
-    }
-
-#ifdef FEAT_MBYTE
-    if (font_name != lf.lfFaceName)
-	vim_free(font_name);
-#endif
-    return (char_u *)res;
-}
-
-
-#ifdef FEAT_MBYTE_IME
-/*
- * Set correct LOGFONT to IME.  Use 'guifontwide' if available, otherwise use
- * 'guifont'
- */
-    static void
-update_im_font(void)
-{
-    LOGFONT	lf_wide;
-
-    if (p_guifontwide != NULL && *p_guifontwide != NUL
-	    && gui.wide_font != NOFONT
-	    && GetObject((HFONT)gui.wide_font, sizeof(lf_wide), &lf_wide))
-	norm_logfont = lf_wide;
-    else
-	norm_logfont = sub_logfont;
-    im_set_font(&norm_logfont);
-}
-#endif
-
-#ifdef FEAT_MBYTE
-/*
- * Handler of gui.wide_font (p_guifontwide) changed notification.
- */
-    void
-gui_mch_wide_font_changed(void)
-{
-# ifndef MSWIN16_FASTTEXT
-    LOGFONT lf;
-# endif
-
-# ifdef FEAT_MBYTE_IME
-    update_im_font();
-# endif
-
-# ifndef MSWIN16_FASTTEXT
-    gui_mch_free_font(gui.wide_ital_font);
-    gui.wide_ital_font = NOFONT;
-    gui_mch_free_font(gui.wide_bold_font);
-    gui.wide_bold_font = NOFONT;
-    gui_mch_free_font(gui.wide_boldital_font);
-    gui.wide_boldital_font = NOFONT;
-
-    if (gui.wide_font
-	&& GetObject((HFONT)gui.wide_font, sizeof(lf), &lf))
-    {
-	if (!lf.lfItalic)
-	{
-	    lf.lfItalic = TRUE;
-	    gui.wide_ital_font = get_font_handle(&lf);
-	    lf.lfItalic = FALSE;
-	}
-	if (lf.lfWeight < FW_BOLD)
-	{
-	    lf.lfWeight = FW_BOLD;
-	    gui.wide_bold_font = get_font_handle(&lf);
-	    if (!lf.lfItalic)
-	    {
-		lf.lfItalic = TRUE;
-		gui.wide_boldital_font = get_font_handle(&lf);
-	    }
-	}
-    }
-# endif
-}
-#endif
-
-/*
- * Initialise vim to use the font with the given name.
- * Return FAIL if the font could not be loaded, OK otherwise.
- */
-/*ARGSUSED*/
-    int
-gui_mch_init_font(char_u *font_name, int fontset)
-{
-    LOGFONT	lf;
-    GuiFont	font = NOFONT;
-    char_u	*p;
-
-    /* Load the font */
-    if (get_logfont(&lf, font_name, NULL, TRUE) == OK)
-	font = get_font_handle(&lf);
-    if (font == NOFONT)
-	return FAIL;
-
-    if (font_name == NULL)
-	font_name = (char_u *)lf.lfFaceName;
-#if defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME)
-    norm_logfont = lf;
-    sub_logfont = lf;
-#endif
-#ifdef FEAT_MBYTE_IME
-    update_im_font();
-#endif
-    gui_mch_free_font(gui.norm_font);
-    gui.norm_font = font;
-    current_font_height = lf.lfHeight;
-    GetFontSize(font);
-
-    p = logfont2name(lf);
-    if (p != NULL)
-    {
-	hl_set_font_name(p);
-
-	/* When setting 'guifont' to "*" replace it with the actual font name.
-	 * */
-	if (STRCMP(font_name, "*") == 0 && STRCMP(p_guifont, "*") == 0)
-	{
-	    vim_free(p_guifont);
-	    p_guifont = p;
-	}
-	else
-	    vim_free(p);
-    }
-
-#ifndef MSWIN16_FASTTEXT
-    gui_mch_free_font(gui.ital_font);
-    gui.ital_font = NOFONT;
-    gui_mch_free_font(gui.bold_font);
-    gui.bold_font = NOFONT;
-    gui_mch_free_font(gui.boldital_font);
-    gui.boldital_font = NOFONT;
-
-    if (!lf.lfItalic)
-    {
-	lf.lfItalic = TRUE;
-	gui.ital_font = get_font_handle(&lf);
-	lf.lfItalic = FALSE;
-    }
-    if (lf.lfWeight < FW_BOLD)
-    {
-	lf.lfWeight = FW_BOLD;
-	gui.bold_font = get_font_handle(&lf);
-	if (!lf.lfItalic)
-	{
-	    lf.lfItalic = TRUE;
-	    gui.boldital_font = get_font_handle(&lf);
-	}
-    }
-#endif
-
-    return OK;
-}
-
-#ifndef WPF_RESTORETOMAXIMIZED
-# define WPF_RESTORETOMAXIMIZED 2   /* just in case someone doesn't have it */
-#endif
-
-/*
- * Return TRUE if the GUI window is maximized, filling the whole screen.
- */
-    int
-gui_mch_maximized(void)
-{
-    WINDOWPLACEMENT wp;
-
-    wp.length = sizeof(WINDOWPLACEMENT);
-    if (GetWindowPlacement(s_hwnd, &wp))
-	return wp.showCmd == SW_SHOWMAXIMIZED
-	    || (wp.showCmd == SW_SHOWMINIMIZED
-		    && wp.flags == WPF_RESTORETOMAXIMIZED);
-
-    return 0;
-}
-
-/*
- * Called when the font changed while the window is maximized.  Compute the
- * new Rows and Columns.  This is like resizing the window.
- */
-    void
-gui_mch_newfont(void)
-{
-    RECT	rect;
-
-    GetWindowRect(s_hwnd, &rect);
-    if (win_socket_id == 0)
-    {
-	gui_resize_shell(rect.right - rect.left
-	    - (GetSystemMetrics(SM_CXFRAME) +
-	       GetSystemMetrics(SM_CXPADDEDBORDER)) * 2,
-	    rect.bottom - rect.top
-	    - (GetSystemMetrics(SM_CYFRAME) +
-	       GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
-	    - GetSystemMetrics(SM_CYCAPTION)
-#ifdef FEAT_MENU
-	    - gui_mswin_get_menu_height(FALSE)
-#endif
-	);
-    }
-    else
-    {
-	/* Inside another window, don't use the frame and border. */
-	gui_resize_shell(rect.right - rect.left,
-	    rect.bottom - rect.top
-#ifdef FEAT_MENU
-			- gui_mswin_get_menu_height(FALSE)
-#endif
-	);
-    }
-}
-
-/*
- * Set the window title
- */
-/*ARGSUSED*/
-    void
-gui_mch_settitle(
-    char_u  *title,
-    char_u  *icon)
-{
-    set_window_title(s_hwnd, (title == NULL ? "VIM" : (char *)title));
-}
-
-#ifdef FEAT_MOUSESHAPE
-/* Table for shape IDCs.  Keep in sync with the mshape_names[] table in
- * misc2.c! */
-static LPCSTR mshape_idcs[] =
-{
-    IDC_ARROW,			/* arrow */
-    MAKEINTRESOURCE(0),		/* blank */
-    IDC_IBEAM,			/* beam */
-    IDC_SIZENS,			/* updown */
-    IDC_SIZENS,			/* udsizing */
-    IDC_SIZEWE,			/* leftright */
-    IDC_SIZEWE,			/* lrsizing */
-    IDC_WAIT,			/* busy */
-#ifdef WIN3264
-    IDC_NO,			/* no */
-#else
-    IDC_ICON,			/* no */
-#endif
-    IDC_ARROW,			/* crosshair */
-    IDC_ARROW,			/* hand1 */
-    IDC_ARROW,			/* hand2 */
-    IDC_ARROW,			/* pencil */
-    IDC_ARROW,			/* question */
-    IDC_ARROW,			/* right-arrow */
-    IDC_UPARROW,		/* up-arrow */
-    IDC_ARROW			/* last one */
-};
-
-    void
-mch_set_mouse_shape(int shape)
-{
-    LPCSTR idc;
-
-    if (shape == MSHAPE_HIDE)
-	ShowCursor(FALSE);
-    else
-    {
-	if (shape >= MSHAPE_NUMBERED)
-	    idc = IDC_ARROW;
-	else
-	    idc = mshape_idcs[shape];
-#ifdef SetClassLongPtr
-	SetClassLongPtr(s_textArea, GCLP_HCURSOR, (__int3264)(LONG_PTR)LoadCursor(NULL, idc));
-#else
-# ifdef WIN32
-	SetClassLong(s_textArea, GCL_HCURSOR, (long_u)LoadCursor(NULL, idc));
-# else /* Win16 */
-	SetClassWord(s_textArea, GCW_HCURSOR, (WORD)LoadCursor(NULL, idc));
-# endif
-#endif
-	if (!p_mh)
-	{
-	    POINT mp;
-
-	    /* Set the position to make it redrawn with the new shape. */
-	    (void)GetCursorPos((LPPOINT)&mp);
-	    (void)SetCursorPos(mp.x, mp.y);
-	    ShowCursor(TRUE);
-	}
-    }
-}
-#endif
-
-#ifdef FEAT_BROWSE
-/*
- * The file browser exists in two versions: with "W" uses wide characters,
- * without "W" the current codepage.  When FEAT_MBYTE is defined and on
- * Windows NT/2000/XP the "W" functions are used.
- */
-
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-/*
- * Wide version of convert_filter().
- */
-    static WCHAR *
-convert_filterW(char_u *s)
-{
-    char_u *tmp;
-    int len;
-    WCHAR *res;
-
-    tmp = convert_filter(s);
-    if (tmp == NULL)
-	return NULL;
-    len = (int)STRLEN(s) + 3;
-    res = enc_to_utf16(tmp, &len);
-    vim_free(tmp);
-    return res;
-}
-
-/*
- * Wide version of gui_mch_browse().  Keep in sync!
- */
-    static char_u *
-gui_mch_browseW(
-	int saving,
-	char_u *title,
-	char_u *dflt,
-	char_u *ext,
-	char_u *initdir,
-	char_u *filter)
-{
-    /* We always use the wide function.  This means enc_to_utf16() must work,
-     * otherwise it fails miserably! */
-    OPENFILENAMEW	fileStruct;
-    WCHAR		fileBuf[MAXPATHL];
-    WCHAR		*wp;
-    int			i;
-    WCHAR		*titlep = NULL;
-    WCHAR		*extp = NULL;
-    WCHAR		*initdirp = NULL;
-    WCHAR		*filterp;
-    char_u		*p;
-
-    if (dflt == NULL)
-	fileBuf[0] = NUL;
-    else
-    {
-	wp = enc_to_utf16(dflt, NULL);
-	if (wp == NULL)
-	    fileBuf[0] = NUL;
-	else
-	{
-	    for (i = 0; wp[i] != NUL && i < MAXPATHL - 1; ++i)
-		fileBuf[i] = wp[i];
-	    fileBuf[i] = NUL;
-	    vim_free(wp);
-	}
-    }
-
-    /* Convert the filter to Windows format. */
-    filterp = convert_filterW(filter);
-
-    vim_memset(&fileStruct, 0, sizeof(OPENFILENAMEW));
-#ifdef OPENFILENAME_SIZE_VERSION_400
-    /* be compatible with Windows NT 4.0 */
-    /* TODO: what to use for OPENFILENAMEW??? */
-    fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400;
-#else
-    fileStruct.lStructSize = sizeof(fileStruct);
-#endif
-
-    if (title != NULL)
-	titlep = enc_to_utf16(title, NULL);
-    fileStruct.lpstrTitle = titlep;
-
-    if (ext != NULL)
-	extp = enc_to_utf16(ext, NULL);
-    fileStruct.lpstrDefExt = extp;
-
-    fileStruct.lpstrFile = fileBuf;
-    fileStruct.nMaxFile = MAXPATHL;
-    fileStruct.lpstrFilter = filterp;
-    fileStruct.hwndOwner = s_hwnd;		/* main Vim window is owner*/
-    /* has an initial dir been specified? */
-    if (initdir != NULL && *initdir != NUL)
-    {
-	/* Must have backslashes here, no matter what 'shellslash' says */
-	initdirp = enc_to_utf16(initdir, NULL);
-	if (initdirp != NULL)
-	{
-	    for (wp = initdirp; *wp != NUL; ++wp)
-		if (*wp == '/')
-		    *wp = '\\';
-	}
-	fileStruct.lpstrInitialDir = initdirp;
-    }
-
-    /*
-     * TODO: Allow selection of multiple files.  Needs another arg to this
-     * function to ask for it, and need to use OFN_ALLOWMULTISELECT below.
-     * Also, should we use OFN_FILEMUSTEXIST when opening?  Vim can edit on
-     * files that don't exist yet, so I haven't put it in.  What about
-     * OFN_PATHMUSTEXIST?
-     * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog.
-     */
-    fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY);
-#ifdef FEAT_SHORTCUT
-    if (curbuf->b_p_bin)
-	fileStruct.Flags |= OFN_NODEREFERENCELINKS;
-#endif
-    if (saving)
-    {
-	if (!GetSaveFileNameW(&fileStruct))
-	    return NULL;
-    }
-    else
-    {
-	if (!GetOpenFileNameW(&fileStruct))
-	    return NULL;
-    }
-
-    vim_free(filterp);
-    vim_free(initdirp);
-    vim_free(titlep);
-    vim_free(extp);
-
-    /* Convert from UCS2 to 'encoding'. */
-    p = utf16_to_enc(fileBuf, NULL);
-    if (p != NULL)
-	/* when out of memory we get garbage for non-ASCII chars */
-	STRCPY(fileBuf, p);
-    vim_free(p);
-
-    /* Give focus back to main window (when using MDI). */
-    SetFocus(s_hwnd);
-
-    /* Shorten the file name if possible */
-    return vim_strsave(shorten_fname1((char_u *)fileBuf));
-}
-# endif /* FEAT_MBYTE */
-
-
-/*
- * Convert the string s to the proper format for a filter string by replacing
- * the \t and \n delimiters with \0.
- * Returns the converted string in allocated memory.
- *
- * Keep in sync with convert_filterW() above!
- */
-    static char_u *
-convert_filter(char_u *s)
-{
-    char_u	*res;
-    unsigned	s_len = (unsigned)STRLEN(s);
-    unsigned	i;
-
-    res = alloc(s_len + 3);
-    if (res != NULL)
-    {
-	for (i = 0; i < s_len; ++i)
-	    if (s[i] == '\t' || s[i] == '\n')
-		res[i] = '\0';
-	    else
-		res[i] = s[i];
-	res[s_len] = NUL;
-	/* Add two extra NULs to make sure it's properly terminated. */
-	res[s_len + 1] = NUL;
-	res[s_len + 2] = NUL;
-    }
-    return res;
-}
-
-/*
- * Select a directory.
- */
-    char_u *
-gui_mch_browsedir(char_u *title, char_u *initdir)
-{
-    /* We fake this: Use a filter that doesn't select anything and a default
-     * file name that won't be used. */
-    return gui_mch_browse(0, title, (char_u *)_("Not Used"), NULL,
-			      initdir, (char_u *)_("Directory\t*.nothing\n"));
-}
-
-/*
- * Pop open a file browser and return the file selected, in allocated memory,
- * or NULL if Cancel is hit.
- *  saving  - TRUE if the file will be saved to, FALSE if it will be opened.
- *  title   - Title message for the file browser dialog.
- *  dflt    - Default name of file.
- *  ext     - Default extension to be added to files without extensions.
- *  initdir - directory in which to open the browser (NULL = current dir)
- *  filter  - Filter for matched files to choose from.
- *
- * Keep in sync with gui_mch_browseW() above!
- */
-    char_u *
-gui_mch_browse(
-	int saving,
-	char_u *title,
-	char_u *dflt,
-	char_u *ext,
-	char_u *initdir,
-	char_u *filter)
-{
-    OPENFILENAME	fileStruct;
-    char_u		fileBuf[MAXPATHL];
-    char_u		*initdirp = NULL;
-    char_u		*filterp;
-    char_u		*p;
-
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-    if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)
-	return gui_mch_browseW(saving, title, dflt, ext, initdir, filter);
-# endif
-
-    if (dflt == NULL)
-	fileBuf[0] = NUL;
-    else
-	vim_strncpy(fileBuf, dflt, MAXPATHL - 1);
-
-    /* Convert the filter to Windows format. */
-    filterp = convert_filter(filter);
-
-    vim_memset(&fileStruct, 0, sizeof(OPENFILENAME));
-#ifdef OPENFILENAME_SIZE_VERSION_400
-    /* be compatible with Windows NT 4.0 */
-    fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400;
-#else
-    fileStruct.lStructSize = sizeof(fileStruct);
-#endif
-
-    fileStruct.lpstrTitle = (LPSTR)title;
-    fileStruct.lpstrDefExt = (LPSTR)ext;
-
-    fileStruct.lpstrFile = (LPSTR)fileBuf;
-    fileStruct.nMaxFile = MAXPATHL;
-    fileStruct.lpstrFilter = (LPSTR)filterp;
-    fileStruct.hwndOwner = s_hwnd;		/* main Vim window is owner*/
-    /* has an initial dir been specified? */
-    if (initdir != NULL && *initdir != NUL)
-    {
-	/* Must have backslashes here, no matter what 'shellslash' says */
-	initdirp = vim_strsave(initdir);
-	if (initdirp != NULL)
-	    for (p = initdirp; *p != NUL; ++p)
-		if (*p == '/')
-		    *p = '\\';
-	fileStruct.lpstrInitialDir = (LPSTR)initdirp;
-    }
-
-    /*
-     * TODO: Allow selection of multiple files.  Needs another arg to this
-     * function to ask for it, and need to use OFN_ALLOWMULTISELECT below.
-     * Also, should we use OFN_FILEMUSTEXIST when opening?  Vim can edit on
-     * files that don't exist yet, so I haven't put it in.  What about
-     * OFN_PATHMUSTEXIST?
-     * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog.
-     */
-    fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY);
-#ifdef FEAT_SHORTCUT
-    if (curbuf->b_p_bin)
-	fileStruct.Flags |= OFN_NODEREFERENCELINKS;
-#endif
-    if (saving)
-    {
-	if (!GetSaveFileName(&fileStruct))
-	    return NULL;
-    }
-    else
-    {
-	if (!GetOpenFileName(&fileStruct))
-	    return NULL;
-    }
-
-    vim_free(filterp);
-    vim_free(initdirp);
-
-    /* Give focus back to main window (when using MDI). */
-    SetFocus(s_hwnd);
-
-    /* Shorten the file name if possible */
-    return vim_strsave(shorten_fname1((char_u *)fileBuf));
-}
-#endif /* FEAT_BROWSE */
-
-/*ARGSUSED*/
-    static void
-_OnDropFiles(
-    HWND hwnd,
-    HDROP hDrop)
-{
-#ifdef FEAT_WINDOWS
-#ifdef WIN3264
-# define BUFPATHLEN _MAX_PATH
-# define DRAGQVAL 0xFFFFFFFF
-#else
-# define BUFPATHLEN MAXPATHL
-# define DRAGQVAL 0xFFFF
-#endif
-#ifdef FEAT_MBYTE
-    WCHAR   wszFile[BUFPATHLEN];
-#endif
-    char    szFile[BUFPATHLEN];
-    UINT    cFiles = DragQueryFile(hDrop, DRAGQVAL, NULL, 0);
-    UINT    i;
-    char_u  **fnames;
-    POINT   pt;
-    int_u   modifiers = 0;
-
-    /* TRACE("_OnDropFiles: %d files dropped\n", cFiles); */
-
-    /* Obtain dropped position */
-    DragQueryPoint(hDrop, &pt);
-    MapWindowPoints(s_hwnd, s_textArea, &pt, 1);
-
-    reset_VIsual();
-
-    fnames = (char_u **)alloc(cFiles * sizeof(char_u *));
-
-    if (fnames != NULL)
-	for (i = 0; i < cFiles; ++i)
-	{
-#ifdef FEAT_MBYTE
-	    if (DragQueryFileW(hDrop, i, wszFile, BUFPATHLEN) > 0)
-		fnames[i] = utf16_to_enc(wszFile, NULL);
-	    else
-#endif
-	    {
-		DragQueryFile(hDrop, i, szFile, BUFPATHLEN);
-		fnames[i] = vim_strsave((char_u *)szFile);
-	    }
-	}
-
-    DragFinish(hDrop);
-
-    if (fnames != NULL)
-    {
-	if ((GetKeyState(VK_SHIFT) & 0x8000) != 0)
-	    modifiers |= MOUSE_SHIFT;
-	if ((GetKeyState(VK_CONTROL) & 0x8000) != 0)
-	    modifiers |= MOUSE_CTRL;
-	if ((GetKeyState(VK_MENU) & 0x8000) != 0)
-	    modifiers |= MOUSE_ALT;
-
-	gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles);
-
-	s_need_activate = TRUE;
-    }
-#endif
-}
-
-/*ARGSUSED*/
-    static int
-_OnScroll(
-    HWND hwnd,
-    HWND hwndCtl,
-    UINT code,
-    int pos)
-{
-    static UINT	prev_code = 0;   /* code of previous call */
-    scrollbar_T *sb, *sb_info;
-    long	val;
-    int		dragging = FALSE;
-    int		dont_scroll_save = dont_scroll;
-#ifndef WIN3264
-    int		nPos;
-#else
-    SCROLLINFO	si;
-
-    si.cbSize = sizeof(si);
-    si.fMask = SIF_POS;
-#endif
-
-    sb = gui_mswin_find_scrollbar(hwndCtl);
-    if (sb == NULL)
-	return 0;
-
-    if (sb->wp != NULL)		/* Left or right scrollbar */
-    {
-	/*
-	 * Careful: need to get scrollbar info out of first (left) scrollbar
-	 * for window, but keep real scrollbar too because we must pass it to
-	 * gui_drag_scrollbar().
-	 */
-	sb_info = &sb->wp->w_scrollbars[0];
-    }
-    else	    /* Bottom scrollbar */
-	sb_info = sb;
-    val = sb_info->value;
-
-    switch (code)
-    {
-	case SB_THUMBTRACK:
-	    val = pos;
-	    dragging = TRUE;
-	    if (sb->scroll_shift > 0)
-		val <<= sb->scroll_shift;
-	    break;
-	case SB_LINEDOWN:
-	    val++;
-	    break;
-	case SB_LINEUP:
-	    val--;
-	    break;
-	case SB_PAGEDOWN:
-	    val += (sb_info->size > 2 ? sb_info->size - 2 : 1);
-	    break;
-	case SB_PAGEUP:
-	    val -= (sb_info->size > 2 ? sb_info->size - 2 : 1);
-	    break;
-	case SB_TOP:
-	    val = 0;
-	    break;
-	case SB_BOTTOM:
-	    val = sb_info->max;
-	    break;
-	case SB_ENDSCROLL:
-	    if (prev_code == SB_THUMBTRACK)
-	    {
-		/*
-		 * "pos" only gives us 16-bit data.  In case of large file,
-		 * use GetScrollPos() which returns 32-bit.  Unfortunately it
-		 * is not valid while the scrollbar is being dragged.
-		 */
-		val = GetScrollPos(hwndCtl, SB_CTL);
-		if (sb->scroll_shift > 0)
-		    val <<= sb->scroll_shift;
-	    }
-	    break;
-
-	default:
-	    /* TRACE("Unknown scrollbar event %d\n", code); */
-	    return 0;
-    }
-    prev_code = code;
-
-#ifdef WIN3264
-    si.nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val;
-    SetScrollInfo(hwndCtl, SB_CTL, &si, TRUE);
-#else
-    nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val;
-    SetScrollPos(hwndCtl, SB_CTL, nPos, TRUE);
-#endif
-
-    /*
-     * When moving a vertical scrollbar, move the other vertical scrollbar too.
-     */
-    if (sb->wp != NULL)
-    {
-	scrollbar_T *sba = sb->wp->w_scrollbars;
-	HWND    id = sba[ (sb == sba + SBAR_LEFT) ? SBAR_RIGHT : SBAR_LEFT].id;
-
-#ifdef WIN3264
-	SetScrollInfo(id, SB_CTL, &si, TRUE);
-#else
-	SetScrollPos(id, SB_CTL, nPos, TRUE);
-#endif
-    }
-
-    /* Don't let us be interrupted here by another message. */
-    s_busy_processing = TRUE;
-
-    /* When "allow_scrollbar" is FALSE still need to remember the new
-     * position, but don't actually scroll by setting "dont_scroll". */
-    dont_scroll = !allow_scrollbar;
-
-    gui_drag_scrollbar(sb, val, dragging);
-
-    s_busy_processing = FALSE;
-    dont_scroll = dont_scroll_save;
-
-    return 0;
-}
-
-
-/*
- * Get command line arguments.
- * Use "prog" as the name of the program and "cmdline" as the arguments.
- * Copy the arguments to allocated memory.
- * Return the number of arguments (including program name).
- * Return pointers to the arguments in "argvp".  Memory is allocated with
- * malloc(), use free() instead of vim_free().
- * Return pointer to buffer in "tofree".
- * Returns zero when out of memory.
- */
-/*ARGSUSED*/
-    int
-get_cmd_args(char *prog, char *cmdline, char ***argvp, char **tofree)
-{
-    int		i;
-    char	*p;
-    char	*progp;
-    char	*pnew = NULL;
-    char	*newcmdline;
-    int		inquote;
-    int		argc;
-    char	**argv = NULL;
-    int		round;
-
-    *tofree = NULL;
-
-#ifdef FEAT_MBYTE
-    /* Try using the Unicode version first, it takes care of conversion when
-     * 'encoding' is changed. */
-    argc = get_cmd_argsW(&argv);
-    if (argc != 0)
-	goto done;
-#endif
-
-    /* Handle the program name.  Remove the ".exe" extension, and find the 1st
-     * non-space. */
-    p = strrchr(prog, '.');
-    if (p != NULL)
-	*p = NUL;
-    for (progp = prog; *progp == ' '; ++progp)
-	;
-
-    /* The command line is copied to allocated memory, so that we can change
-     * it.  Add the size of the string, the separating NUL and a terminating
-     * NUL. */
-    newcmdline = malloc(STRLEN(cmdline) + STRLEN(progp) + 2);
-    if (newcmdline == NULL)
-	return 0;
-
-    /*
-     * First round: count the number of arguments ("pnew" == NULL).
-     * Second round: produce the arguments.
-     */
-    for (round = 1; round <= 2; ++round)
-    {
-	/* First argument is the program name. */
-	if (pnew != NULL)
-	{
-	    argv[0] = pnew;
-	    strcpy(pnew, progp);
-	    pnew += strlen(pnew);
-	    *pnew++ = NUL;
-	}
-
-	/*
-	 * Isolate each argument and put it in argv[].
-	 */
-	p = cmdline;
-	argc = 1;
-	while (*p != NUL)
-	{
-	    inquote = FALSE;
-	    if (pnew != NULL)
-		argv[argc] = pnew;
-	    ++argc;
-	    while (*p != NUL && (inquote || (*p != ' ' && *p != '\t')))
-	    {
-		/* Backslashes are only special when followed by a double
-		 * quote. */
-		i = (int)strspn(p, "\\");
-		if (p[i] == '"')
-		{
-		    /* Halve the number of backslashes. */
-		    if (i > 1 && pnew != NULL)
-		    {
-			vim_memset(pnew, '\\', i / 2);
-			pnew += i / 2;
-		    }
-
-		    /* Even nr of backslashes toggles quoting, uneven copies
-		     * the double quote. */
-		    if ((i & 1) == 0)
-			inquote = !inquote;
-		    else if (pnew != NULL)
-			*pnew++ = '"';
-		    p += i + 1;
-		}
-		else if (i > 0)
-		{
-		    /* Copy span of backslashes unmodified. */
-		    if (pnew != NULL)
-		    {
-			vim_memset(pnew, '\\', i);
-			pnew += i;
-		    }
-		    p += i;
-		}
-		else
-		{
-		    if (pnew != NULL)
-			*pnew++ = *p;
-#ifdef FEAT_MBYTE
-		    /* Can't use mb_* functions, because 'encoding' is not
-		     * initialized yet here. */
-		    if (IsDBCSLeadByte(*p))
-		    {
-			++p;
-			if (pnew != NULL)
-			    *pnew++ = *p;
-		    }
-#endif
-		    ++p;
-		}
-	    }
-
-	    if (pnew != NULL)
-		*pnew++ = NUL;
-	    while (*p == ' ' || *p == '\t')
-		++p;		    /* advance until a non-space */
-	}
-
-	if (round == 1)
-	{
-	    argv = (char **)malloc((argc + 1) * sizeof(char *));
-	    if (argv == NULL )
-	    {
-		free(newcmdline);
-		return 0;		   /* malloc error */
-	    }
-	    pnew = newcmdline;
-	    *tofree = newcmdline;
-	}
-    }
-
-#ifdef FEAT_MBYTE
-done:
-#endif
-    argv[argc] = NULL;		/* NULL-terminated list */
-    *argvp = argv;
-    return argc;
-}
deleted file mode 100644
--- a/src/guiw16rc.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-#define	IDR_VIM 150
-
-#define IDR_VIM_ERROR	151
-#define IDR_VIM_ALERT	152
-#define IDR_VIM_INFO	153
-#define IDR_VIM_QUESTION 154
-
-#define IDR_ICOBUDDYBASE			200
-
-#define IDR_ICOBUDDY_DEF1			(IDR_ICOBUDDYBASE + 3)
-#define IDR_ICOBUDDY_DEF2			(IDR_ICOBUDDYBASE + 0)
-#define IDR_ICOBUDDY_DEF3			(IDR_ICOBUDDYBASE + 1)
-#define IDR_ICOBUDDY_DEF4			(IDR_ICOBUDDYBASE + 2)
-
-#define IDR_ICOBUDDY_GRIN			(IDR_ICOBUDDYBASE + 4)
-#define IDR_ICOBUDDY_ALARM			(IDR_ICOBUDDYBASE + 5)
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -1400,7 +1400,7 @@ vim_strsave_shellescape(char_u *string, 
     length = (unsigned)STRLEN(string) + 3;  /* two quotes and a trailing NUL */
     for (p = string; *p != NUL; mb_ptr_adv(p))
     {
-# if defined(WIN32) || defined(WIN16) || defined(DOS)
+# if defined(WIN32) || defined(DOS)
 	if (!p_ssl)
 	{
 	    if (*p == '"')
@@ -1431,7 +1431,7 @@ vim_strsave_shellescape(char_u *string, 
 	d = escaped_string;
 
 	/* add opening quote */
-# if defined(WIN32) || defined(WIN16) || defined(DOS)
+# if defined(WIN32) || defined(DOS)
 	if (!p_ssl)
 	    *d++ = '"';
 	else
@@ -1440,7 +1440,7 @@ vim_strsave_shellescape(char_u *string, 
 
 	for (p = string; *p != NUL; )
 	{
-# if defined(WIN32) || defined(WIN16) || defined(DOS)
+# if defined(WIN32) || defined(DOS)
 	    if (!p_ssl)
 	    {
 		if (*p == '"')
@@ -1483,7 +1483,7 @@ vim_strsave_shellescape(char_u *string, 
 	}
 
 	/* add terminating quote and finish with a NUL */
-# if defined(WIN32) || defined(WIN16) || defined(DOS)
+# if defined(WIN32) || defined(DOS)
 	if (!p_ssl)
 	    *d++ = '"';
 	else
--- a/src/option.c
+++ b/src/option.c
@@ -2296,14 +2296,10 @@ static struct vimoption
 # if defined(MSDOS)
 			    (char_u *)"command",
 # else
-#  if defined(WIN16)
-			    (char_u *)"command.com",
+#  if defined(WIN3264)
+			    (char_u *)"",	/* set in set_init_1() */
 #  else
-#   if defined(WIN3264)
-			    (char_u *)"",	/* set in set_init_1() */
-#   else
 			    (char_u *)"sh",
-#   endif
 #  endif
 # endif
 #endif /* VMS */
@@ -2367,7 +2363,7 @@ static struct vimoption
     {"shellxescape", "sxe", P_STRING|P_VI_DEF|P_SECURE,
 			    (char_u *)&p_sxe, PV_NONE,
 			    {
-#if defined(MSDOS) || defined(WIN16) || defined(WIN3264)
+#if defined(MSDOS) || defined(WIN3264)
 			    (char_u *)"\"&|<>()@^",
 #else
 			    (char_u *)"",
--- a/src/os_msdos.c
+++ b/src/os_msdos.c
@@ -28,12 +28,6 @@
 # include <conio.h>
 #endif
 
-/*
- * MS-DOS only code, not used for Win16.
- */
-#ifndef WIN16
-
-
 #ifndef PROTO
 # include <bios.h>
 # ifdef DJGPP
@@ -2850,11 +2844,6 @@ Win16SetClipboardData(
 #endif	/* FEAT_CLIPBOARD */
 #endif /* DJGPP */
 
-/*
- * End of MS-DOS only code
- */
-#endif /* WIN16 */
-
 /* common MS-DOS and Win16 code follows */
 
     static int
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -10,28 +10,11 @@
 /*
  * os_mswin.c
  *
- * Routines common to both Win16 and Win32.
+ * Routines for Win32.
  */
 
-#ifdef WIN16
-# ifdef __BORLANDC__
-#  pragma warn -par
-#  pragma warn -ucp
-#  pragma warn -use
-#  pragma warn -aus
-# endif
-#endif
-
 #include "vim.h"
 
-#ifdef WIN16
-# define SHORT_FNAME		/* always 8.3 file name */
-/* cproto fails on missing include files */
-# ifndef PROTO
-#  include <dos.h>
-# endif
-# include <string.h>
-#endif
 #include <sys/types.h>
 #include <signal.h>
 #include <limits.h>
@@ -904,7 +887,6 @@ typedef int (*MYSTRPROCINT)(LPSTR);
 typedef int (*MYINTPROCINT)(int);
 # endif
 
-# ifndef WIN16
 /*
  * Check if a pointer points to a valid NUL terminated string.
  * Return the length of the string, including terminating NUL.
@@ -944,7 +926,6 @@ check_str_len(char_u *str)
 
     return 0;
 }
-# endif
 
 /*
  * Passed to do_in_runtimepath() to load a vim.ico file.
@@ -991,11 +972,7 @@ mch_libcall(
     BOOL fRunTimeLinkSuccess = FALSE;
 
     // Get a handle to the DLL module.
-# ifdef WIN16
-    hinstLib = LoadLibrary(libname);
-# else
     hinstLib = vimLoadLib((char *)libname);
-# endif
 
     // If the handle is valid, try to get the function address.
     if (hinstLib != NULL)
@@ -1034,15 +1011,7 @@ mch_libcall(
 	if (string_result == NULL)
 	    *number_result = retval_int;
 	else if (retval_str != NULL
-# ifdef WIN16
-		&& retval_str != (char_u *)1
-		&& retval_str != (char_u *)-1
-		&& !IsBadStringPtr(retval_str, INT_MAX)
-		&& (len = strlen(retval_str) + 1) > 0
-# else
-		&& (len = check_str_len(retval_str)) > 0
-# endif
-		)
+		&& (len = check_str_len(retval_str)) > 0)
 	{
 	    *string_result = lalloc((long_u)len, TRUE);
 	    if (*string_result != NULL)
@@ -1184,9 +1153,6 @@ mch_set_winpos(int x, int y)
 
 #if (defined(FEAT_PRINTER) && !defined(FEAT_POSTSCRIPT)) || defined(PROTO)
 
-# ifdef WIN16
-#  define TEXT(a) a
-# endif
 /*=================================================================
  * Win32 printer stuff
  */
@@ -1211,7 +1177,7 @@ static char_u		*prt_name = NULL;
 #define IDC_PRINTTEXT2		402
 #define IDC_PROGRESS		403
 
-#if !defined(FEAT_MBYTE) || defined(WIN16)
+#if !defined(FEAT_MBYTE)
 # define vimSetDlgItemText(h, i, s) SetDlgItemText(h, i, s)
 #else
     static BOOL
@@ -1456,23 +1422,13 @@ prt_get_cpl(void)
     int		dvoff;
     int		rev_offset;
     int		dpi;
-#ifdef WIN16
-    POINT	pagesize;
-#endif
 
     GetTextMetrics(prt_dlg.hDC, &prt_tm);
     prt_line_height = prt_tm.tmHeight + prt_tm.tmExternalLeading;
 
     hr	    = GetDeviceCaps(prt_dlg.hDC, HORZRES);
-#ifdef WIN16
-    Escape(prt_dlg.hDC, GETPHYSPAGESIZE, NULL, NULL, &pagesize);
-    phyw    = pagesize.x;
-    Escape(prt_dlg.hDC, GETPRINTINGOFFSET, NULL, NULL, &pagesize);
-    dvoff   = pagesize.x;
-#else
     phyw    = GetDeviceCaps(prt_dlg.hDC, PHYSICALWIDTH);
     dvoff   = GetDeviceCaps(prt_dlg.hDC, PHYSICALOFFSETX);
-#endif
     dpi	    = GetDeviceCaps(prt_dlg.hDC, LOGPIXELSX);
 
     rev_offset = phyw - (dvoff + hr);
@@ -1501,20 +1457,10 @@ prt_get_lpp(void)
     int rev_offset;
     int	bottom_margin;
     int	dpi;
-#ifdef WIN16
-    POINT pagesize;
-#endif
 
     vr	    = GetDeviceCaps(prt_dlg.hDC, VERTRES);
-#ifdef WIN16
-    Escape(prt_dlg.hDC, GETPHYSPAGESIZE, NULL, NULL, &pagesize);
-    phyw    = pagesize.y;
-    Escape(prt_dlg.hDC, GETPRINTINGOFFSET, NULL, NULL, &pagesize);
-    dvoff   = pagesize.y;
-#else
     phyw    = GetDeviceCaps(prt_dlg.hDC, PHYSICALHEIGHT);
     dvoff   = GetDeviceCaps(prt_dlg.hDC, PHYSICALOFFSETY);
-#endif
     dpi	    = GetDeviceCaps(prt_dlg.hDC, LOGPIXELSY);
 
     rev_offset = phyw - (dvoff + vr);
@@ -1741,12 +1687,6 @@ init_fail_dlg:
 
 	if (err)
 	{
-#ifdef WIN16
-	    char buf[20];
-
-	    sprintf(buf, "%ld", err);
-	    EMSG2(_("E238: Print error: %s"), buf);
-#else
 	    char_u *buf;
 
 	    /* I suspect FormatMessage() doesn't work for values returned by
@@ -1758,7 +1698,6 @@ init_fail_dlg:
 	    EMSG2(_("E238: Print error: %s"),
 				  buf == NULL ? (char_u *)_("Unknown") : buf);
 	    LocalFree((LPVOID)(buf));
-#endif
 	}
 	else
 	    msg_clr_eos(); /* Maybe canceled */
@@ -1778,11 +1717,7 @@ mch_print_begin(prt_settings_T *psetting
 
     hDlgPrint = CreateDialog(GetModuleHandle(NULL), TEXT("PrintDlgBox"),
 					     prt_dlg.hwndOwner, PrintDlgProc);
-#ifdef WIN16
-    Escape(prt_dlg.hDC, SETABORTPROC, 0, (LPSTR)AbortProc, NULL);
-#else
     SetAbortProc(prt_dlg.hDC, AbortProc);
-#endif
     wsprintf(szBuffer, _("Printing '%s'"), gettail(psettings->jobname));
     vimSetDlgItemText(hDlgPrint, IDC_PRINTTEXT1, (char_u *)szBuffer);
 
@@ -1845,10 +1780,10 @@ mch_print_start_line(int margin, int pag
     int
 mch_print_text_out(char_u *p, int len)
 {
-#if defined(FEAT_PROPORTIONAL_FONTS) || (defined(FEAT_MBYTE) && !defined(WIN16))
+#if defined(FEAT_PROPORTIONAL_FONTS) || defined(FEAT_MBYTE)
     SIZE	sz;
 #endif
-#if defined(FEAT_MBYTE) && !defined(WIN16)
+#if defined(FEAT_MBYTE)
     WCHAR	*wp = NULL;
     int		wlen = len;
 
@@ -1888,20 +1823,12 @@ mch_print_text_out(char_u *p, int len)
     return (prt_pos_x + prt_left_margin + prt_tm.tmAveCharWidth
 				     + prt_tm.tmOverhang > prt_right_margin);
 #else
-# ifdef WIN16
-    GetTextExtentPoint(prt_dlg.hDC, (LPCSTR)p, len, &sz);
-# else
     GetTextExtentPoint32(prt_dlg.hDC, (LPCSTR)p, len, &sz);
-# endif
     prt_pos_x += (sz.cx - prt_tm.tmOverhang);
     /* This is wrong when printing spaces for a TAB. */
     if (p[len] == NUL)
 	return FALSE;
-# ifdef WIN16
-    GetTextExtentPoint(prt_dlg.hDC, p + len, 1, &sz);
-# else
     GetTextExtentPoint32(prt_dlg.hDC, p + len, 1, &sz);
-# endif
     return (prt_pos_x + prt_left_margin + sz.cx > prt_right_margin);
 #endif
 }
@@ -3027,14 +2954,10 @@ get_logfont(
 		lf->lfWidth = points_to_pixels(p, &p, FALSE, (long_i)printer_dc);
 		break;
 	    case 'b':
-#ifndef MSWIN16_FASTTEXT
 		lf->lfWeight = FW_BOLD;
-#endif
 		break;
 	    case 'i':
-#ifndef MSWIN16_FASTTEXT
 		lf->lfItalic = TRUE;
-#endif
 		break;
 	    case 'u':
 		lf->lfUnderline = TRUE;
deleted file mode 100644
--- a/src/os_win16.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/* vi:set ts=8 sts=4 sw=4:
- *
- * VIM - Vi IMproved	by Bram Moolenaar
- *
- * 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.
- */
-/*
- * os_win16.c
- *
- * Win16 (Windows 3.1x) system-dependent routines.
- * Carved brutally from os_win32.c by Vince Negri <vn@aslnet.co.uk>
- */
-#ifdef __BORLANDC__
-# pragma warn -par
-# pragma warn -ucp
-# pragma warn -use
-# pragma warn -aus
-# pragma warn -obs
-#endif
-
-#include "vim.h"
-
-/* cproto fails on missing include files */
-#ifndef PROTO
-# include <dos.h>
-#endif
-
-#include <string.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <limits.h>
-
-#ifndef PROTO
-# include <process.h>
-
-# undef chdir
-# include <direct.h>
-# include <shellapi.h>	/* required for FindExecutable() */
-#endif
-
-
-/* Record all output and all keyboard & mouse input */
-/* #define MCH_WRITE_DUMP */
-
-#ifdef MCH_WRITE_DUMP
-FILE* fdDump = NULL;
-#endif
-
-
-/*
- * When generating prototypes for Win32 on Unix, these lines make the syntax
- * errors disappear.  They do not need to be correct.
- */
-#ifdef PROTO
-typedef int HANDLE;
-typedef int SMALL_RECT;
-typedef int COORD;
-typedef int SHORT;
-typedef int WORD;
-typedef int DWORD;
-typedef int BOOL;
-typedef int LPSTR;
-typedef int LPTSTR;
-typedef int KEY_EVENT_RECORD;
-typedef int MOUSE_EVENT_RECORD;
-# define WINAPI
-typedef int CONSOLE_CURSOR_INFO;
-typedef char * LPCSTR;
-# define WINBASEAPI
-typedef int INPUT_RECORD;
-# define _cdecl
-#endif
-
-#ifdef __BORLANDC__
-/* being a more ANSI compliant compiler, BorlandC doesn't define _stricoll:
- * but it does in BC 5.02! */
-# if __BORLANDC__ < 0x502
-int _stricoll(char *a, char *b);
-# endif
-#endif
-
-/* cproto doesn't create a prototype for main() */
-int _cdecl
-VimMain
-    (int argc, char **argv);
-static int (_cdecl *pmain)(int, char **);
-
-#ifndef PROTO
-void _cdecl SaveInst(HINSTANCE hInst);
-static void (_cdecl *pSaveInst)(HINSTANCE);
-
-int WINAPI
-WinMain(
-    HINSTANCE	hInstance,
-    HINSTANCE	hPrevInst,
-    LPSTR	lpszCmdLine,
-    int		nCmdShow)
-{
-    int		argc;
-    char	**argv;
-    char	*tofree;
-    char	prog[256];
-
-    /*
-     * Ron: added full path name so that the $VIM variable will get set to our
-     * startup path (so the .vimrc file can be found w/o a VIM env. var.)
-     * Remove the ".exe" extension, and find the 1st non-space.
-     */
-    GetModuleFileName(hInstance, prog, 255);
-    if (*prog != NUL)
-	exe_name = FullName_save((char_u *)prog, FALSE);
-
-    /* Separate the command line into arguments. */
-    argc = get_cmd_args(prog, (char *)lpszCmdLine, &argv, &tofree);
-    if (argc == 0)
-    {
-	/* Error message? */
-	return 0;
-    }
-
-    pSaveInst = SaveInst;
-    pmain = VimMain;
-    pSaveInst(hInstance);
-    pmain(argc, argv);
-
-    free(argv);
-    if (tofree != NULL)
-	free(tofree);
-
-    return 0;
-}
-#endif
-
-
-
-
-
-
-#ifdef FEAT_MOUSE
-
-/*
- * For the GUI the mouse handling is in gui_w32.c.
- */
-    void
-mch_setmouse(
-    int on)
-{
-}
-#endif /* FEAT_MOUSE */
-
-
-
-/*
- * GUI version of mch_init().
- */
-    void
-mch_init(void)
-{
-    extern int _fmode;
-
-
-    /* Let critical errors result in a failure, not in a dialog box.  Required
-     * for the timestamp test to work on removed floppies. */
-    SetErrorMode(SEM_FAILCRITICALERRORS);
-
-    _fmode = O_BINARY;		/* we do our own CR-LF translation */
-
-    /* Specify window size.  Is there a place to get the default from? */
-    Rows = 25;
-    Columns = 80;
-
-
-    set_option_value((char_u *)"grepprg", 0, (char_u *)"grep -n", 0);
-
-#ifdef FEAT_CLIPBOARD
-    clip_init(TRUE);
-
-    /*
-     * Vim's own clipboard format recognises whether the text is char, line,
-     * or rectangular block.  Only useful for copying between two Vims.
-     * "VimClipboard" was used for previous versions, using the first
-     * character to specify MCHAR, MLINE or MBLOCK.
-     */
-    clip_star.format = RegisterClipboardFormat("VimClipboard2");
-    clip_star.format_raw = RegisterClipboardFormat("VimRawBytes");
-#endif
-}
-
-
-
-/*
- * Do we have an interactive window?
- */
-    int
-mch_check_win(
-    int argc,
-    char **argv)
-{
-    return OK;	    /* GUI always has a tty */
-}
-
-
-/*
- * return process ID
- */
-    long
-mch_get_pid(void)
-{
-    return (long)GetCurrentTask();
-}
-
-
-/*
- * Specialised version of system().
- * This version proceeds as follows:
- *    1. Start the program with WinExec
- *    2. Wait for the module use count of the program to go to 0
- *	 (This is the best way of detecting the program has finished)
- */
-
-    static int
-mch_system(char *cmd, int options)
-{
-    DWORD		ret = 0;
-    UINT		wShowWindow;
-    UINT		h_module;
-    MSG			msg;
-    BOOL		again = TRUE;
-
-    /*
-     * It's nicer to run a filter command in a minimized window, but in
-     */
-    if (options & SHELL_DOOUT)
-	wShowWindow = SW_SHOWMINIMIZED;
-    else
-	wShowWindow = SW_SHOWNORMAL;
-
-    /* Now, run the command */
-    h_module = WinExec((LPCSTR)cmd, wShowWindow);
-
-    if (h_module < 32)
-    {
-	/*error*/
-	ret = -h_module;
-    }
-    else
-    {
-	/* Wait for the command to terminate before continuing */
-	while (GetModuleUsage((HINSTANCE)h_module) > 0 && again )
-	{
-	    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && again)
-	    {
-		if (msg.message == WM_QUIT)
-
-		{
-		    PostQuitMessage(msg.wParam);
-		    again = FALSE;
-		}
-		TranslateMessage(&msg);
-		DispatchMessage(&msg);
-	    }
-	}
-    }
-
-    return ret;
-}
-
-/*
- * Either execute a command by calling the shell or start a new shell
- */
-    int
-mch_call_shell(
-    char_u *cmd,
-    int options)	    /* SHELL_, see vim.h */
-{
-    int		x;
-    int		tmode = cur_tmode;
-
-    out_flush();
-
-
-#ifdef MCH_WRITE_DUMP
-    if (fdDump)
-    {
-	fprintf(fdDump, "mch_call_shell(\"%s\", %d)\n", cmd, options);
-	fflush(fdDump);
-    }
-#endif
-
-    /*
-     * Catch all deadly signals while running the external command, because a
-     * CTRL-C, Ctrl-Break or illegal instruction  might otherwise kill us.
-     */
-    signal(SIGINT, SIG_IGN);
-    signal(SIGILL, SIG_IGN);
-    signal(SIGFPE, SIG_IGN);
-    signal(SIGSEGV, SIG_IGN);
-    signal(SIGTERM, SIG_IGN);
-    signal(SIGABRT, SIG_IGN);
-
-    if (options & SHELL_COOKED)
-	settmode(TMODE_COOK);	/* set to normal mode */
-
-    if (cmd == NULL)
-    {
-	x = mch_system(p_sh, options);
-    }
-    else
-    {
-	/* we use "command" or "cmd" to start the shell; slow but easy */
-	char_u *newcmd;
-
-	newcmd = lalloc(
-		STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10, TRUE);
-	if (newcmd != NULL)
-	{
-	    if (STRNICMP(cmd, "start ", 6) == 0)
-	    {
-		sprintf((char *)newcmd, "%s\0", cmd+6);
-		if (WinExec((LPCSTR)newcmd, SW_SHOWNORMAL) > 31)
-		    x = 0;
-		else
-		    x = -1;
-	    }
-	    else
-	    {
-		sprintf((char *)newcmd, "%s%s %s %s",
-			"",
-			p_sh,
-			p_shcf,
-			cmd);
-		x = mch_system((char *)newcmd, options);
-	    }
-	    vim_free(newcmd);
-	}
-    }
-
-    if (tmode == TMODE_RAW)
-	settmode(TMODE_RAW);	/* set to raw mode */
-
-    if (x && !(options & SHELL_SILENT) && !emsg_silent)
-    {
-	smsg(_("shell returned %d"), x);
-	msg_putchar('\n');
-    }
-#ifdef FEAT_TITLE
-    resettitle();
-#endif
-
-    signal(SIGINT, SIG_DFL);
-    signal(SIGILL, SIG_DFL);
-    signal(SIGFPE, SIG_DFL);
-    signal(SIGSEGV, SIG_DFL);
-    signal(SIGTERM, SIG_DFL);
-    signal(SIGABRT, SIG_DFL);
-
-
-    return x;
-}
-
-
-/*
- * Delay for half a second.
- */
-    void
-mch_delay(
-    long    msec,
-    int	    ignoreinput)
-{
-#ifdef MUST_FIX
-    Sleep((int)msec);	    /* never wait for input */
-#endif
-}
-
-
-/*
- * check for an "interrupt signal": CTRL-break or CTRL-C
- */
-    void
-mch_breakcheck(void)
-{
-    /* never used */
-}
-
-
-/*
- * How much memory is available in Kbyte?
- */
-    long_u
-mch_avail_mem(
-    int special)
-{
-    return GetFreeSpace(0) >> 10;
-}
-
-
-/*
- * Like rename(), returns 0 upon success, non-zero upon failure.
- * Should probably set errno appropriately when errors occur.
- */
-    int
-mch_rename(
-    const char	*pszOldFile,
-    const char	*pszNewFile)
-{
-
-    /*
-     * No need to play tricks, this isn't rubbish like Windows 95 <g>
-     */
-    return rename(pszOldFile, pszNewFile);
-
-}
-
-/*
- * Get the default shell for the current hardware platform
- */
-    char*
-default_shell(void)
-{
-    char* psz = NULL;
-
-    psz = "command.com";
-
-    return psz;
-}
deleted file mode 100644
--- a/src/os_win16.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* vi:set ts=8 sts=4 sw=4:
- *
- * VIM - Vi IMproved	by Bram Moolenaar
- *
- * Do ":help uganda"  in Vim to read copying and usage conditions.
- * Do ":help credits" in Vim to see a list of people who contributed.
- */
-
-/*
- * Win16 (Windows 3.1x) machine-dependent things.
- */
-
-#include "os_dos.h"		/* common MS-DOS and Windows stuff */
-
-#define BINARY_FILE_IO
-#define USE_EXE_NAME		/* use argv[0] for $VIM */
-#define SYNC_DUP_CLOSE		/* sync() a file with dup() and close() */
-#define USE_TERM_CONSOLE
-#define HAVE_STRING_H
-#define HAVE_STRCSPN
-#define HAVE_STRICMP
-#define HAVE_STRNICMP
-#define HAVE_STRFTIME		/* guessed */
-#define HAVE_MEMSET
-#define USE_TMPNAM		/* use tmpnam() instead of mktemp() */
-#define HAVE_LOCALE_H
-#define HAVE_FCNTL_H
-#define HAVE_QSORT
-#define HAVE_ST_MODE		/* have stat.st_mode */
-#define HAVE_MATH_H
-//#define USE_FNAME_CASE	/* adjust case of file names */
-#ifndef FEAT_CLIPBOARD
-# define FEAT_CLIPBOARD		/* include clipboard support */
-#endif
-#if defined(__DATE__) && defined(__TIME__)
-# define HAVE_DATE_TIME
-#endif
-#define HAVE_AVAIL_MEM
-
-#define SHORT_FNAME		/* always 8.3 file name */
-
-#define SMALL_MALLOC		/* 16 bit storage allocation */
-
-#ifdef __BORLANDC__
-# define HAVE_PUTENV		/* at least Bcc 5.2 has it */
-#endif
-
-#ifdef FEAT_GUI_W16
-# define NO_CONSOLE		/* don't included console-only code */
-#endif
-
-/* toupper() is not really broken, but it's very slow.	Probably because of
- * using unicode characters on Windows NT */
-#define BROKEN_TOUPPER
-
-#define FNAME_ILLEGAL "\"*?><|" /* illegal characters in a file name */
-
-#ifndef VIM_SIZEOF_INT
-# define VIM_SIZEOF_INT 2
-#endif
-
-typedef long off_t;
-
-#include <stdlib.h>
-#include <time.h>
-
-/* cproto fails on missing include files */
-#ifndef PROTO
-# include <dos.h>
-# include <dir.h>
-
-# ifndef STRICT
-#  define STRICT
-# endif
-# ifndef COBJMACROS
-#  define COBJMACROS	/* For OLE: Enable "friendlier" access to objects */
-# endif
-# include <windows.h>
-
-#endif /* PROTO */
-
-/*
- *  plenty of memory, use large buffers
- */
-#define CMDBUFFSIZE 1024	/* size of the command processing buffer */
-
-
-#define BASENAMELEN	(MAXPATHL-5)	/* length of base of file name */
-
-#ifndef DFLT_MAXMEM
-# define DFLT_MAXMEM	(256)    /* use up to 256K for a buffer*/
-#endif
-
-#ifndef DFLT_MAXMEMTOT
-# define DFLT_MAXMEMTOT	(5*1024)    /* use up to 5 Mbyte for Vim */
-#endif
-
-/*
- * Some simple debugging macros that look and behave a lot like their
- * namesakes in MFC.
- */
-
-#ifdef _DEBUG
-
-# if defined(_MSC_VER)	&&  (_MSC_VER >= 1000)
-   /* Use the new debugging tools in Visual C++ 4.x */
-#  include <crtdbg.h>
-#  define ASSERT(f) _ASSERT(f)
-# else
-#  include <assert.h>
-#  define ASSERT(f) assert(f)
-# endif
-
-# define TRACE			Trace
-# define TRACE0(sz)		Trace(_T("%s"), _T(sz))
-# define TRACE1(sz, p1)		Trace(_T(sz), p1)
-# define TRACE2(sz, p1, p2)	Trace(_T(sz), p1, p2)
-# define TRACE3(sz, p1, p2, p3) Trace(_T(sz), p1, p2, p3)
-
-/* In debug version, writes trace messages to debug stream */
-void __cdecl
-Trace(char *pszFormat, ...);
-
-#else /* !_DEBUG */
-
-  /* These macros should all compile away to nothing */
-# define ASSERT(f)		((void)0)
-# define TRACE			1 ? (void)0 : printf
-# define TRACE0(sz)
-# define TRACE1(sz, p1)
-# define TRACE2(sz, p1, p2)
-# define TRACE3(sz, p1, p2, p3)
-
-#endif /* !_DEBUG */
-
-
-#define ASSERT_POINTER(p, type) \
-    ASSERT(((p) != NULL)  &&  IsValidAddress((p), sizeof(type), FALSE))
-
-#define ASSERT_NULL_OR_POINTER(p, type) \
-    ASSERT(((p) == NULL)  ||  IsValidAddress((p), sizeof(type), FALSE))
-
-#define mch_setenv(name, val, x) setenv(name, val, x)
--- a/src/proto.h
+++ b/src/proto.h
@@ -38,17 +38,9 @@
 # if defined(UNIX) || defined(__EMX__) || defined(VMS)
 #  include "os_unix.pro"
 # endif
-# if defined(MSDOS) || defined(WIN16)
+# if defined(MSDOS)
 #  include "os_msdos.pro"
 # endif
-# ifdef WIN16
-   typedef LPSTR LPWSTR;
-   typedef LPCSTR LPCWSTR;
-   typedef int LPBOOL;
-#  include "os_win16.pro"
-#  include "os_mswin.pro"
-#  include "winclip.pro"
-# endif
 # ifdef WIN3264
 #  include "os_win32.pro"
 #  include "os_mswin.pro"
deleted file mode 100644
--- a/src/proto/gui_w16.pro
+++ /dev/null
@@ -1,80 +0,0 @@
-/* gui_w16.c */
-void gui_mch_set_blinking(long wait, long on, long off);
-void gui_mch_stop_blink(void);
-void gui_mch_start_blink(void);
-LRESULT WINAPI vim_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
-void gui_mch_new_colors(void);
-void gui_mch_def_colors(void);
-int gui_mch_open(void);
-int gui_mch_get_winpos(int *x, int *y);
-void gui_mch_set_winpos(int x, int y);
-void gui_mch_set_text_area_pos(int x, int y, int w, int h);
-void gui_mch_enable_scrollbar(scrollbar_T *sb, int flag);
-void gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h);
-void gui_mch_create_scrollbar(scrollbar_T *sb, int orient);
-int gui_mch_adjust_charheight(void);
-GuiFont gui_mch_get_font(char_u *name, int giveErrorIfMissing);
-char_u *gui_mch_get_fontname(GuiFont font, char_u *name);
-void gui_mch_free_font(GuiFont font);
-guicolor_T gui_mch_get_color(char_u *name);
-int gui_mch_haskey(char_u *name);
-void gui_mch_beep(void);
-void gui_mch_invert_rectangle(int r, int c, int nr, int nc);
-void gui_mch_iconify(void);
-void gui_mch_draw_hollow_cursor(guicolor_T color);
-void gui_mch_draw_part_cursor(int w, int h, guicolor_T color);
-void gui_mch_update(void);
-int gui_mch_wait_for_chars(int wtime);
-void gui_mch_clear_block(int row1, int col1, int row2, int col2);
-void gui_mch_clear_all(void);
-void gui_mch_enable_menu(int flag);
-void gui_mch_set_menu_pos(int x, int y, int w, int h);
-void gui_mch_menu_hidden(vimmenu_T *menu, int hidden);
-void gui_mch_draw_menubar(void);
-long_u gui_mch_get_rgb(guicolor_T pixel);
-void gui_mch_activate_window(void);
-void gui_mch_show_toolbar(int showit);
-void gui_mch_show_tabline(int showit);
-int gui_mch_showing_tabline(void);
-void gui_mch_update_tabline(void);
-void gui_mch_set_curtab(int nr);
-void ex_simalt(exarg_T *eap);
-void gui_mch_find_dialog(exarg_T *eap);
-void gui_mch_replace_dialog(exarg_T *eap);
-void gui_mch_mousehide(int hide);
-void gui_mch_destroy_scrollbar(scrollbar_T *sb);
-void gui_mch_getmouse(int *x, int *y);
-void gui_mch_setmouse(int x, int y);
-void gui_mch_flash(int msec);
-void gui_mch_delete_lines(int row, int num_lines);
-void gui_mch_insert_lines(int row, int num_lines);
-void gui_mch_exit(int rc);
-void gui_mch_wide_font_changed(void);
-int gui_mch_init_font(char_u *font_name, int fontset);
-int gui_mch_maximized(void);
-void gui_mch_newfont(void);
-void gui_mch_settitle(char_u *title, char_u *icon);
-void mch_set_mouse_shape(int shape);
-char_u *gui_mch_browsedir(char_u *title, char_u *initdir);
-char_u *gui_mch_browse(int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter);
-int get_cmd_args(char *prog, char *cmdline, char ***argvp, char **tofree);
-void gui_mch_prepare(int *argc, char **argv);
-int gui_mch_init(void);
-void gui_mch_set_shellsize(int width, int height, int min_width, int min_height, int base_width, int base_height, int direction);
-void gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max);
-void gui_mch_set_font(GuiFont font);
-void gui_mch_set_fg_color(guicolor_T color);
-void gui_mch_set_bg_color(guicolor_T color);
-void gui_mch_set_sp_color(guicolor_T color);
-void gui_mch_draw_string(int row, int col, char_u *text, int len, int flags);
-void gui_mch_flush(void);
-void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h);
-void gui_mch_add_menu(vimmenu_T *menu, int pos);
-void gui_mch_show_popupmenu(vimmenu_T *menu);
-void gui_make_popup(char_u *path_name, int mouse_pos);
-void gui_mch_add_menu_item(vimmenu_T *menu, int idx);
-void gui_mch_destroy_menu(vimmenu_T *menu);
-void gui_mch_menu_grey(vimmenu_T *menu, int grey);
-int gui_mch_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd);
-void gui_mch_set_foreground(void);
-/* vim: set ft=c : */
--- a/src/version.c
+++ b/src/version.c
@@ -748,6 +748,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1364,
+/**/
     1363,
 /**/
     1362,
@@ -3638,9 +3640,6 @@ list_version(void)
 #  endif
 # endif
 #endif
-#ifdef WIN16
-    MSG_PUTS(_("\nMS-Windows 16-bit version"));
-#endif
 #ifdef MSDOS
 # ifdef DJGPP
     MSG_PUTS(_("\n32-bit MS-DOS version"));
--- a/src/vim.h
+++ b/src/vim.h
@@ -27,7 +27,7 @@
 # endif
 #endif
 
-#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64) \
+#if defined(MSDOS) || defined(WIN32) || defined(_WIN64) \
 	|| defined(__EMX__)
 # include "vimio.h"
 #endif
@@ -150,7 +150,7 @@
 #if defined(FEAT_GUI_W32) || defined(FEAT_GUI_W16)
 # define FEAT_GUI_MSWIN
 #endif
-#if defined(WIN16) || defined(WIN32) || defined(_WIN64)
+#if defined(WIN32) || defined(_WIN64)
 # define MSWIN
 #endif
 /* Practically everything is common to both Win32 and Win64 */
@@ -308,10 +308,6 @@
 # include "os_msdos.h"
 #endif
 
-#ifdef WIN16
-# include "os_win16.h"
-#endif
-
 #ifdef WIN3264
 # include "os_win32.h"
 #endif
@@ -471,7 +467,7 @@ typedef unsigned long u8char_T;	    /* l
 # include <sys/stat.h>
 #endif
 
-#if defined(HAVE_ERRNO_H) || defined(DJGPP) || defined(WIN16) \
+#if defined(HAVE_ERRNO_H) || defined(DJGPP) \
 	|| defined(WIN32) || defined(_WIN64) || defined(__EMX__)
 # include <errno.h>
 #endif
deleted file mode 100644
--- a/src/vim16.def
+++ /dev/null
@@ -1,5 +0,0 @@
-CODE PRELOAD EXECUTEONLY
-DATA MULTIPLE SHARED
-DESCRIPTION 'Vim 7.4'
-STACKSIZE 16000
-HEAPSIZE 10000
deleted file mode 100644
--- a/src/vim16.rc
+++ /dev/null
@@ -1,81 +0,0 @@
-// vim:ts=8:sw=4:sts=4:
-//
-// VIM - Vi IMproved	by Bram Moolenaar
-//
-// Do ":help uganda"  in Vim to read copying and usage conditions.
-// Do ":help credits" in Vim to see a list of people who contributed.
-
-// vim.rc
-//   Icon and version information for the Win32 version of Vim
-//   Must be in DOS format <CR><NL>!
-
-#include "version.h"
-#include "gui_w3~1.h"
-#include "guiw16rc.h"
-
-//
-// Icons
-//
-IDR_VIM ICON "VIM.ICO"
-
-#ifndef FEAT_TINY
-IDR_VIM_ERROR	ICON "VIM_ER~1.ICO"
-IDR_VIM_ALERT	ICON "VIM_AL~1.ICO"
-IDR_VIM_INFO	ICON "VIM_INFO.ICO"
-IDR_VIM_QUESTION ICON "VIM_QU~1.ICO"
-#endif
-
-//
-// Bitmaps
-//
-#ifdef FEAT_TOOLBAR
-IDR_TOOLBAR1	BITMAP  DISCARDABLE  "tools16.bmp"
-#endif
-//
-// Version
-//
-
-VS_VERSION_INFO		VERSIONINFO
-  FILEVERSION		VIM_VERSION_MAJOR,VIM_VERSION_MINOR,VIM_VERSION_BUILD,VIM_VERSION_PATCHLEVEL
-  PRODUCTVERSION	VIM_VERSION_MAJOR,VIM_VERSION_MINOR,VIM_VERSION_BUILD,VIM_VERSION_PATCHLEVEL
-  FILEFLAGSMASK		VS_FFI_FILEFLAGSMASK
-
-#if VIM_VERSION_PATCHLEVEL > 0
- #ifdef _DEBUG
-  FILEFLAGS		VS_FF_PRERELEASE | VS_FF_DEBUG | VS_FF_PATCHED
- #else
-  FILEFLAGS		VS_FF_PRERELEASE | VS_FF_PATCHED
- #endif
-#else
- #ifdef _DEBUG
-  FILEFLAGS		VS_FF_PRERELEASE | VS_FF_DEBUG
- #else
-  FILEFLAGS		VS_FF_PRERELEASE
- #endif
-#endif
-
-  FILEOS		VOS__WINDOWS32
-  FILETYPE		VFT_APP
-  FILESUBTYPE		0x0L
-BEGIN
-  BLOCK "StringFileInfo"
-  BEGIN
-    // 0x0409 == U.S. English; 0x04E4 => Windows Multilingual
-    BLOCK "040904E4"
-    BEGIN
-	VALUE "CompanyName",		"Vim Developers\0"
-	VALUE "FileDescription",	"Vi Improved - A Text Editor\0"
-	VALUE "FileVersion",		VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR  "\0"
-	VALUE "InternalName",		"VIM\0"
-	VALUE "LegalCopyright",		"Copyright \251 1996\0"
-	VALUE "LegalTrademarks",	"Vim\0"
-	VALUE "OriginalFilename",	"VIM.EXE\0"
-	VALUE "ProductName",		"Vim\0"
-	VALUE "ProductVersion",		VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR "\0"
-    END
-  END
-  BLOCK "VarFileInfo"
-  BEGIN
-	VALUE "Translation", 0x409, 0x4E4
-  END
-END
--- a/src/winclip.c
+++ b/src/winclip.c
@@ -14,15 +14,6 @@
  * Also used by Cygwin, using os_unix.c.
  */
 
-#ifdef WIN16
-# ifdef __BORLANDC__
-#  pragma warn -par
-#  pragma warn -ucp
-#  pragma warn -use
-#  pragma warn -aus
-# endif
-#endif
-
 #include "vimio.h"
 #include "vim.h"