]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 7.4.1364 v7.4.1364
authorBram Moolenaar <Bram@vim.org>
Sat, 20 Feb 2016 12:55:06 +0000 (13:55 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 20 Feb 2016 12:55:06 +0000 (13:55 +0100)
Problem:    The Win 16 code is not maintained and unused.
Solution:   Remove the Win 16 support.

25 files changed:
Filelist
src/Make_cyg_ming.mak
src/Make_mvc.mak
src/Make_w16.mak [deleted file]
src/Makefile
src/eval.c
src/feature.h
src/gui.c
src/gui_w16.c [deleted file]
src/gui_w32.c
src/gui_w48.c [deleted file]
src/guiw16rc.h [deleted file]
src/misc2.c
src/option.c
src/os_msdos.c
src/os_mswin.c
src/os_win16.c [deleted file]
src/os_win16.h [deleted file]
src/proto.h
src/proto/gui_w16.pro [deleted file]
src/version.c
src/vim.h
src/vim16.def [deleted file]
src/vim16.rc [deleted file]
src/winclip.c

index e0eb8826d4c4853bf2f110858289fa07e8341489..ddbce267f7758f3143c0a9b73e55424b6120aea9 100644 (file)
--- 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 \
index 8dc7d003ca9e2239be1567ffd7aeb237fac57678..f6ab0dbbf220e7914efdc085d4bd9c97fccaed72 100644 (file)
@@ -860,7 +860,7 @@ $(OUTDIR)/ex_docmd.o:       ex_docmd.c $(INCL) ex_cmds.h
 $(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
index f1b17148c2e497ad89b9e34d9959b97f54661a32..0843d25c42c83afbc8c9cf116f326ce52ea6a9a2 100644 (file)
@@ -1175,7 +1175,7 @@ $(OUTDIR)/gui.obj:        $(OUTDIR) gui.c  $(INCL) $(GUI_INCL)
 
 $(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)
 
diff --git a/src/Make_w16.mak b/src/Make_w16.mak
deleted file mode 100644 (file)
index 04ec663..0000000
+++ /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
index 8985e40f42b116b307b0a160057f7b95fa5b1e86..13c7bc6041865e662443e12e83a0f74dc2e58419 100644 (file)
@@ -1336,7 +1336,7 @@ CARBONGUI_TESTARG = VIMPROG=../$(APPDIR)/Contents/MacOS/$(VIMTARGET)
 
 # 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 \
index 8afd52e0b4e22f325a0ed91e5d153e0c0fab502c..017decc4af1ee39bd4897bbf1ef877c22702aff1 100644 (file)
@@ -13235,9 +13235,6 @@ f_has(typval_T *argvars, typval_T *rettv)
 #ifdef VMS
        "vms",
 #endif
-#ifdef WIN16
-       "win16",
-#endif
 #ifdef WIN32
        "win32",
 #endif
index ca01b064ca5b8b1f6388d98ad7cefeafdb4b36c5..d7679e090c3404ebbd8c4d348f56dafd6d7af066 100644 (file)
  *
  * 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
  * 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
 
     && (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
index d6b9eb1960620190f26cf0628181c407ab1b4d2a..f7ec508e3cf29489a35ddbe6e663fa94175dbc24 100644 (file)
--- 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 UNUSED)
     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 UNUSED)
                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 UNUSED)
                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);
diff --git a/src/gui_w16.c b/src/gui_w16.c
deleted file mode 100644 (file)
index a0a3996..0000000
+++ /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
index feeb6d402cb650c34e9c00029cd30b91d6957578..5129c5fbcb0a30fe97511d9a6aec5953de84c002 100644 (file)
@@ -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 "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;
+}
+
+
 /*
- * Include the common stuff for MS-Windows GUI.
+ * 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.
  */
-#include "gui_w48.c"
+/*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);
diff --git a/src/gui_w48.c b/src/gui_w48.c
deleted file mode 100644 (file)
index eff3f3f..0000000
+++ /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;
-}
diff --git a/src/guiw16rc.h b/src/guiw16rc.h
deleted file mode 100644 (file)
index 1e55200..0000000
+++ /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)
index 7f33ffa55206a81544beaf0b752eb044130fbd2c..9cfb118179dd18c416fac0c663d611e3ef4bb2f0 100644 (file)
@@ -1400,7 +1400,7 @@ vim_strsave_shellescape(char_u *string, int do_special, int do_newline)
     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, int do_special, int do_newline)
        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, int do_special, int do_newline)
 
        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, int do_special, int do_newline)
        }
 
        /* 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
index 6554fcd01653be2dd550f24da59c556e83ae65e5..6645cb2efdbdab9bc688d1410c02206e480e22e6 100644 (file)
@@ -2296,14 +2296,10 @@ static struct vimoption
 # if defined(MSDOS)
                            (char_u *)"command",
 # else
-#  if defined(WIN16)
-                           (char_u *)"command.com",
-#  else
-#   if defined(WIN3264)
+#  if defined(WIN3264)
                            (char_u *)"",       /* set in set_init_1() */
-#   else
+#  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 *)"",
index 840f654fb48e0dcfac2983739d786e388ad3a8d8..5596e346da34ad9bcf5071163ce63bd82101d045 100644 (file)
 # 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
index 3a5922b452edc7811d9d0e2c9629a2e4969cb322..46b3780c4945761409a5e28b7fa92abebffe8331 100644 (file)
 /*
  * 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 *psettings)
 
     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 page_line)
     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;
diff --git a/src/os_win16.c b/src/os_win16.c
deleted file mode 100644 (file)
index 92367ee..0000000
+++ /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;
-}
diff --git a/src/os_win16.h b/src/os_win16.h
deleted file mode 100644 (file)
index 4c26772..0000000
+++ /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)
index 1f68b219e819cb3c68001d69cac9e0a212caf193..a7b7838eb671d704eac5d19e747276e149bd9389 100644 (file)
 # 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"
diff --git a/src/proto/gui_w16.pro b/src/proto/gui_w16.pro
deleted file mode 100644 (file)
index 0a0c496..0000000
+++ /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 : */
index d2ae1ae6d3a239b762db52185a22a5ff195ecd96..38d6a1d56b4b7f8c622062f8cf57d5f331ba43b4 100644 (file)
@@ -747,6 +747,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1364,
 /**/
     1363,
 /**/
@@ -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"));
index 52eebab25a6cbd08598ddd005db20a3d81505847..97155d2b75a71c3b7bae33518a4c0682e527878a 100644 (file)
--- 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
 #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 */
 # 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;         /* long should be 32 bits or more */
 # 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
diff --git a/src/vim16.def b/src/vim16.def
deleted file mode 100644 (file)
index c982c0f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-CODE PRELOAD EXECUTEONLY
-DATA MULTIPLE SHARED
-DESCRIPTION 'Vim 7.4'
-STACKSIZE 16000
-HEAPSIZE 10000
diff --git a/src/vim16.rc b/src/vim16.rc
deleted file mode 100644 (file)
index 00395e8..0000000
+++ /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
index 8ab723f9388a38c753bc35db3555915c0c431c18..880e2c600d8a8e0b1eaadb7ed3e8d5accc1bad55 100644 (file)
  * 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"