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