changeset 16451:7ae2396cef62 v8.1.1230

patch 8.1.1230: a lot of code is shared between vim.exe and gvim.exe commit https://github.com/vim/vim/commit/afde13b62b8fa25dac4635d5caee8d088b937ee0 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Apr 28 19:46:49 2019 +0200 patch 8.1.1230: a lot of code is shared between vim.exe and gvim.exe Problem: A lot of code is shared between vim.exe and gvim.exe. Solution: Optionally put the shared code in vim.dll. (Ken Takata, closes #4287)
author Bram Moolenaar <Bram@vim.org>
date Sun, 28 Apr 2019 20:00:10 +0200
parents bf74bce807e8
children a311ea84a94c
files .gitignore Filelist nsis/gvim.nsi runtime/doc/gui_w32.txt src/Make_cyg_ming.mak src/Make_mvc.mak src/channel.c src/evalfunc.c src/ex_cmds.c src/ex_docmd.c src/feature.h src/fileio.c src/getchar.c src/globals.h src/gui.c src/gui.h src/gui_gtk_x11.c src/gui_w32.c src/if_mzsch.c src/main.c src/mbyte.c src/memline.c src/message.c src/misc2.c src/normal.c src/option.c src/os_mswin.c src/os_w32dll.c src/os_w32exe.c src/os_win32.c src/os_win32.h src/proto/gui.pro src/proto/gui_w32.pro src/proto/misc2.pro src/proto/os_mswin.pro src/proto/os_win32.pro src/syntax.c src/term.c src/terminal.c src/ui.c src/version.c src/vim.rc
diffstat 42 files changed, 1207 insertions(+), 473 deletions(-) [+]
line wrap: on
line diff
--- a/.gitignore
+++ b/.gitignore
@@ -33,6 +33,8 @@ src/auto/pathdef.c
 *.suo
 *.res
 *.RES
+vim*.dll
+vim*.lib
 src/if_perl.c
 src/pathdef.c
 src/Obj*/pathdef.c
--- a/Filelist
+++ b/Filelist
@@ -454,6 +454,7 @@ SRC_DOS =	\
 		src/iscygpty.h \
 		src/iid_ole.c \
 		src/os_dos.h \
+		src/os_w32dll.c \
 		src/os_w32exe.c \
 		src/os_win32.c \
 		src/os_mswin.c \
--- a/nsis/gvim.nsi
+++ b/nsis/gvim.nsi
@@ -322,6 +322,9 @@ Section "$(str_section_exe)" id_section_
 
 	SetOutPath $0
 	File /oname=gvim.exe ${VIMSRC}\gvim_ole.exe
+!if /FileExists "${VIMSRC}\vim${BIT}.dll"
+	File ${VIMSRC}\vim${BIT}.dll
+!endif
 	File /oname=install.exe ${VIMSRC}\installw32.exe
 	File /oname=uninstal.exe ${VIMSRC}\uninstalw32.exe
 	File ${VIMSRC}\vimrun.exe
--- a/runtime/doc/gui_w32.txt
+++ b/runtime/doc/gui_w32.txt
@@ -1,4 +1,4 @@
-*gui_w32.txt*   For Vim version 8.1.  Last change: 2017 Oct 27
+*gui_w32.txt*   For Vim version 8.1.  Last change: 2019 Apr 28
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -31,6 +31,17 @@ The GUI will always run in the Windows s
 return with a command prompt after starting gvim.  If not, you should use the
 "start" command: >
 	start gvim [options] file ..
+<							*E988*
+The console version with the |-g| option may also start the GUI by executing
+gvim.exe: >
+	vim -g [options] file ..
+To make this work, gvim.exe must exist in the same directory as the vim.exe,
+and this feature must be enabled at compile time.
+
+One may also use `:gui` from the console version.  However, this is an
+experimental feature and this feature must be enabled at compile time.
+It uses a session file to recreate the current state of the console Vim in the
+GUI Vim.
 
 Note: All fonts (bold, italic) must be of the same size!!!  If you don't do
 this, text will disappear or mess up the display.  Vim does not check the font
--- a/src/Make_cyg_ming.mak
+++ b/src/Make_cyg_ming.mak
@@ -36,7 +36,7 @@ FEATURES=HUGE
 DEBUG=no
 
 # set to yes to create a mapfile
-# MAP=yes
+#MAP=yes
 
 # set to SIZE for size, SPEED for speed, MAXSPEED for maximum optimization
 OPTIMIZE=MAXSPEED
@@ -44,6 +44,11 @@ OPTIMIZE=MAXSPEED
 # set to yes to make gvim, no for vim
 GUI=yes
 
+# set to yes to enable the DLL support (EXPERIMENTAL).
+# Creates vim{32,64}.dll, and stub gvim.exe and vim.exe.
+# "GUI" should be also set to "yes".
+#VIMDLL=yes
+
 # set to no if you do not want to use DirectWrite (DirectX)
 # MinGW-w64 is needed, and ARCH should be set to i686 or x86-64.
 DIRECTX=yes
@@ -687,7 +692,7 @@ else  # SPEED
 CFLAGS += -O2
 endif
 endif
-CFLAGS += -s
+LFLAGS += -s
 endif
 
 LIB = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomdlg32 -lcomctl32 -lnetapi32 -lversion
@@ -739,7 +744,6 @@ OBJ = \
 	$(OUTDIR)/ops.o \
 	$(OUTDIR)/option.o \
 	$(OUTDIR)/os_mswin.o \
-	$(OUTDIR)/os_w32exe.o \
 	$(OUTDIR)/os_win32.o \
 	$(OUTDIR)/pathdef.o \
 	$(OUTDIR)/popupmnu.o \
@@ -760,10 +764,17 @@ OBJ = \
 	$(OUTDIR)/usercmd.o \
 	$(OUTDIR)/userfunc.o \
 	$(OUTDIR)/version.o \
-	$(OUTDIR)/vimrc.o \
 	$(OUTDIR)/winclip.o \
 	$(OUTDIR)/window.o
 
+ifeq ($(VIMDLL),yes)
+OBJ += $(OUTDIR)/os_w32dll.o $(OUTDIR)/vimrcd.o
+EXEOBJC = $(OUTDIR)/os_w32exec.o $(OUTDIR)/vimrcc.o
+EXEOBJG = $(OUTDIR)/os_w32exeg.o $(OUTDIR)/vimrcg.o
+else
+OBJ += $(OUTDIR)/os_w32exe.o $(OUTDIR)/vimrc.o
+endif
+
 ifdef PERL
 OBJ += $(OUTDIR)/if_perl.o
 endif
@@ -870,16 +881,36 @@ endif
 
 LFLAGS += -municode
 
-ifeq ($(GUI),yes)
+ifeq ($(VIMDLL),yes)
+VIMEXE := vim$(DEBUG_SUFFIX).exe
+GVIMEXE := gvim$(DEBUG_SUFFIX).exe
+ ifeq ($(ARCH),x86-64)
+VIMDLLBASE := vim64$(DEBUG_SUFFIX)
+ else
+VIMDLLBASE := vim32$(DEBUG_SUFFIX)
+ endif
+TARGET = $(VIMDLLBASE).dll
+LFLAGS += -shared
+EXELFLAGS += -municode
+ ifneq ($(DEBUG),yes)
+EXELFLAGS += -s
+ endif
+DEFINES += $(DEF_GUI) -DVIMDLL
+OBJ += $(GUIOBJ) $(CUIOBJ)
+OUTDIR = dobj$(DEBUG_SUFFIX)$(MZSCHEME_SUFFIX)$(ARCH)
+MAIN_TARGET = $(GVIMEXE) $(VIMEXE) $(VIMDLLBASE).dll
+else ifeq ($(GUI),yes)
 TARGET := gvim$(DEBUG_SUFFIX).exe
 DEFINES += $(DEF_GUI)
 OBJ += $(GUIOBJ)
 LFLAGS += -mwindows
 OUTDIR = gobj$(DEBUG_SUFFIX)$(MZSCHEME_SUFFIX)$(ARCH)
+MAIN_TARGET = $(TARGET)
 else
 OBJ += $(CUIOBJ)
 TARGET := vim$(DEBUG_SUFFIX).exe
 OUTDIR = obj$(DEBUG_SUFFIX)$(MZSCHEME_SUFFIX)$(ARCH)
+MAIN_TARGET = $(TARGET)
 endif
 
 ifdef GETTEXT
@@ -955,7 +986,7 @@ ifeq (yes, $(MAP))
 LFLAGS += -Wl,-Map=$(TARGET).map
 endif
 
-all: $(TARGET) vimrun.exe xxd/xxd.exe tee/tee.exe install.exe uninstal.exe GvimExt/gvimext.dll
+all: $(MAIN_TARGET) vimrun.exe xxd/xxd.exe tee/tee.exe install.exe uninstal.exe GvimExt/gvimext.dll
 
 vimrun.exe: vimrun.c
 	$(CC) $(CFLAGS) -o vimrun.exe vimrun.c $(LIB)
@@ -966,8 +997,19 @@ install.exe: dosinst.c
 uninstal.exe: uninstal.c
 	$(CC) $(CFLAGS) -o uninstal.exe uninstal.c $(LIB)
 
+ifeq ($(VIMDLL),yes)
+$(TARGET): $(OUTDIR) $(OBJ)
+	$(LINK) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid -lgdi32 $(LUA_LIB) $(MZSCHEME_LIBDIR) $(MZSCHEME_LIB) $(PYTHONLIB) $(PYTHON3LIB) $(RUBYLIB)
+
+$(GVIMEXE): $(OUTDIR) $(EXEOBJG) $(VIMDLLBASE).dll
+	$(CC) -L. $(EXELFLAGS) -mwindows -o $@ $(EXEOBJG) -l$(VIMDLLBASE)
+
+$(VIMEXE): $(OUTDIR) $(EXEOBJC) $(VIMDLLBASE).dll
+	$(CC) -L. $(EXELFLAGS) -o $@ $(EXEOBJC) -l$(VIMDLLBASE)
+else
 $(TARGET): $(OUTDIR) $(OBJ)
 	$(LINK) $(CFLAGS) $(LFLAGS) -o $@ $(OBJ) $(LIB) -lole32 -luuid $(LUA_LIB) $(MZSCHEME_LIBDIR) $(MZSCHEME_LIB) $(PYTHONLIB) $(PYTHON3LIB) $(RUBYLIB)
+endif
 
 upx: exes
 	upx gvim.exe
@@ -996,7 +1038,7 @@ clean:
 	-$(DEL) $(OUTDIR)$(DIRSLASH)*.o
 	-$(DEL) $(OUTDIR)$(DIRSLASH)*.res
 	-rmdir $(OUTDIR)
-	-$(DEL) $(TARGET) vimrun.exe install.exe uninstal.exe
+	-$(DEL) $(MAIN_TARGET) vimrun.exe install.exe uninstal.exe
 	-$(DEL) pathdef.c
 ifdef PERL
 	-$(DEL) if_perl.c
@@ -1025,74 +1067,95 @@ CUI_INCL = iscygpty.h
 $(OUTDIR)/%.o : %.c $(INCL)
 	$(CC) -c $(CFLAGS) $< -o $@
 
-$(OUTDIR)/vimrc.o:	vim.rc version.h gui_w32_rc.h
+ifeq ($(VIMDLL),yes)
+$(OUTDIR)/vimrcc.o:	vim.rc gvim.exe.mnf version.h gui_w32_rc.h vim.ico
+	$(WINDRES) $(WINDRES_FLAGS) $(DEFINES) -UFEAT_GUI_MSWIN \
+	    --input-format=rc --output-format=coff -i vim.rc -o $@
+
+$(OUTDIR)/vimrcg.o:	vim.rc gvim.exe.mnf version.h gui_w32_rc.h vim.ico
 	$(WINDRES) $(WINDRES_FLAGS) $(DEFINES) \
 	    --input-format=rc --output-format=coff -i vim.rc -o $@
 
+$(OUTDIR)/vimrcd.o:	vim.rc version.h gui_w32_rc.h \
+			tools.bmp tearoff.bmp vim.ico vim_error.ico \
+			vim_alert.ico vim_info.ico vim_quest.ico
+	$(WINDRES) $(WINDRES_FLAGS) $(DEFINES) -DRCDLL -DVIMDLLBASE=\\\"$(VIMDLLBASE)\\\" \
+	    --input-format=rc --output-format=coff -i vim.rc -o $@
+else
+$(OUTDIR)/vimrc.o:	vim.rc gvim.exe.mnf version.h gui_w32_rc.h \
+			tools.bmp tearoff.bmp vim.ico vim_error.ico \
+			vim_alert.ico vim_info.ico vim_quest.ico
+	$(WINDRES) $(WINDRES_FLAGS) $(DEFINES) \
+	    --input-format=rc --output-format=coff -i vim.rc -o $@
+endif
+
 $(OUTDIR):
 	$(MKDIR) $(OUTDIR)
 
 $(OUTDIR)/gui_dwrite.o:	gui_dwrite.cpp $(INCL) gui_dwrite.h
-	$(CC) -c $(CFLAGS) $(CXXFLAGS) gui_dwrite.cpp -o $(OUTDIR)/gui_dwrite.o
+	$(CC) -c $(CFLAGS) $(CXXFLAGS) gui_dwrite.cpp -o $@
 
 $(OUTDIR)/gui.o:	gui.c $(INCL) $(GUI_INCL)
-	$(CC) -c $(CFLAGS) gui.c -o $(OUTDIR)/gui.o
+	$(CC) -c $(CFLAGS) gui.c -o $@
 
 $(OUTDIR)/beval.o:	beval.c $(INCL) $(GUI_INCL)
-	$(CC) -c $(CFLAGS) beval.c -o $(OUTDIR)/beval.o
+	$(CC) -c $(CFLAGS) beval.c -o $@
 
 $(OUTDIR)/gui_beval.o:	gui_beval.c $(INCL) $(GUI_INCL)
-	$(CC) -c $(CFLAGS) gui_beval.c -o $(OUTDIR)/gui_beval.o
+	$(CC) -c $(CFLAGS) gui_beval.c -o $@
 
 $(OUTDIR)/gui_w32.o:	gui_w32.c $(INCL) $(GUI_INCL)
-	$(CC) -c $(CFLAGS) gui_w32.c -o $(OUTDIR)/gui_w32.o
+	$(CC) -c $(CFLAGS) gui_w32.c -o $@
 
 $(OUTDIR)/if_cscope.o:	if_cscope.c $(INCL) if_cscope.h
-	$(CC) -c $(CFLAGS) if_cscope.c -o $(OUTDIR)/if_cscope.o
+	$(CC) -c $(CFLAGS) if_cscope.c -o $@
 
 $(OUTDIR)/if_mzsch.o:	if_mzsch.c $(INCL) $(MZSCHEME_INCL) $(MZ_EXTRA_DEP)
-	$(CC) -c $(CFLAGS) if_mzsch.c -o $(OUTDIR)/if_mzsch.o
+	$(CC) -c $(CFLAGS) if_mzsch.c -o $@
 
 mzscheme_base.c:
 	$(MZSCHEME)/mzc --c-mods mzscheme_base.c ++lib scheme/base
 
 # Remove -D__IID_DEFINED__ for newer versions of the w32api
 $(OUTDIR)/if_ole.o:	if_ole.cpp $(INCL) if_ole.h
-	$(CC) $(CFLAGS) $(CXXFLAGS) -c -o $(OUTDIR)/if_ole.o if_ole.cpp
+	$(CC) -c $(CFLAGS) $(CXXFLAGS) if_ole.cpp -o $@
 
 auto/if_perl.c:		if_perl.xs typemap
 	$(XSUBPP) -prototypes -typemap \
 	     $(PERLTYPEMAP) if_perl.xs -output $@
 
 $(OUTDIR)/if_perl.o:	auto/if_perl.c $(INCL)
-	$(CC) -c $(CFLAGS) auto/if_perl.c -o $(OUTDIR)/if_perl.o
+	$(CC) -c $(CFLAGS) auto/if_perl.c -o $@
 
 
 $(OUTDIR)/if_ruby.o:	if_ruby.c $(INCL)
 ifeq (16, $(RUBY))
-	$(CC) $(CFLAGS) -U_WIN32 -c -o $(OUTDIR)/if_ruby.o if_ruby.c
+	$(CC) $(CFLAGS) -U_WIN32 -c -o $@ if_ruby.c
 endif
 
 $(OUTDIR)/iscygpty.o:	iscygpty.c $(CUI_INCL)
 	$(CC) -c $(CFLAGS) iscygpty.c -o $(OUTDIR)/iscygpty.o -U_WIN32_WINNT -D_WIN32_WINNT=0x0600 -DUSE_DYNFILEID -DENABLE_STUB_IMPL
 
 $(OUTDIR)/main.o:	main.c $(INCL) $(CUI_INCL)
-	$(CC) -c $(CFLAGS) main.c -o $(OUTDIR)/main.o
+	$(CC) -c $(CFLAGS) main.c -o $@
 
 $(OUTDIR)/netbeans.o:	netbeans.c $(INCL) $(NBDEBUG_INCL) $(NBDEBUG_SRC)
-	$(CC) -c $(CFLAGS) netbeans.c -o $(OUTDIR)/netbeans.o
+	$(CC) -c $(CFLAGS) netbeans.c -o $@
+
+$(OUTDIR)/os_w32exec.o:	os_w32exe.c $(INCL)
+	$(CC) -c $(CFLAGS) -UFEAT_GUI_MSWIN os_w32exe.c -o $@
+
+$(OUTDIR)/os_w32exeg.o:	os_w32exe.c $(INCL)
+	$(CC) -c $(CFLAGS) os_w32exe.c -o $@
 
 $(OUTDIR)/os_win32.o:	os_win32.c $(INCL) $(MZSCHEME_INCL)
-	$(CC) -c $(CFLAGS) os_win32.c -o $(OUTDIR)/os_win32.o
+	$(CC) -c $(CFLAGS) os_win32.c -o $@
 
 $(OUTDIR)/regexp.o:	regexp.c regexp_nfa.c $(INCL)
-	$(CC) -c $(CFLAGS) regexp.c -o $(OUTDIR)/regexp.o
+	$(CC) -c $(CFLAGS) regexp.c -o $@
 
 $(OUTDIR)/terminal.o:	terminal.c $(INCL) $(TERM_DEPS)
-	$(CC) -c $(CFLAGS) terminal.c -o $(OUTDIR)/terminal.o
-
-$(OUTDIR)/textprop.o:	textprop.c $(INCL)
-	$(CC) -c $(CFLAGS) textprop.c -o $(OUTDIR)/textprop.o
+	$(CC) -c $(CFLAGS) terminal.c -o $@
 
 
 CCCTERM = $(CC) -c $(CFLAGS) -Ilibvterm/include -DINLINE="" \
@@ -1100,50 +1163,13 @@ CCCTERM = $(CC) -c $(CFLAGS) -Ilibvterm/
 	  -DIS_COMBINING_FUNCTION=utf_iscomposing_uint \
 	  -DWCWIDTH_FUNCTION=utf_uint2cells
 
-$(OUTDIR)/encoding.o: libvterm/src/encoding.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/encoding.c -o $@
-
-$(OUTDIR)/keyboard.o: libvterm/src/keyboard.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/keyboard.c -o $@
-
-$(OUTDIR)/mouse.o: libvterm/src/mouse.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/mouse.c -o $@
+$(OUTDIR)/%.o : libvterm/src/%.c $(TERM_DEPS)
+	$(CCCTERM) $< -o $@
 
-$(OUTDIR)/parser.o: libvterm/src/parser.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/parser.c -o $@
-
-$(OUTDIR)/pen.o: libvterm/src/pen.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/pen.c -o $@
-
-$(OUTDIR)/termscreen.o: libvterm/src/termscreen.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/termscreen.c -o $@
-
-$(OUTDIR)/state.o: libvterm/src/state.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/state.c -o $@
 
-$(OUTDIR)/unicode.o: libvterm/src/unicode.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/unicode.c -o $@
-
-$(OUTDIR)/vterm.o: libvterm/src/vterm.c $(TERM_DEPS)
-	$(CCCTERM) libvterm/src/vterm.c -o $@
-
-$(OUTDIR)/xdiffi.o: xdiff/xdiffi.c $(XDIFF_DEPS)
-	$(CC) -c $(CFLAGS) xdiff/xdiffi.c -o $(OUTDIR)/xdiffi.o
-
-$(OUTDIR)/xemit.o: xdiff/xemit.c $(XDIFF_DEPS)
-	$(CC) -c $(CFLAGS) xdiff/xemit.c -o $(OUTDIR)/xemit.o
+$(OUTDIR)/%.o : xdiff/%.c $(XDIFF_DEPS)
+	$(CC) -c $(CFLAGS) $< -o $@
 
-$(OUTDIR)/xprepare.o: xdiff/xprepare.c $(XDIFF_DEPS)
-	$(CC) -c $(CFLAGS) xdiff/xprepare.c -o $(OUTDIR)/xprepare.o
-
-$(OUTDIR)/xutils.o: xdiff/xutils.c $(XDIFF_DEPS)
-	$(CC) -c $(CFLAGS) xdiff/xutils.c -o $(OUTDIR)/xutils.o
-
-$(OUTDIR)/xhistogram.o: xdiff/xhistogram.c $(XDIFF_DEPS)
-	$(CC) -c $(CFLAGS) xdiff/xhistogram.c -o $(OUTDIR)/xhistogram.o
-
-$(OUTDIR)/xpatience.o: xdiff/xpatience.c $(XDIFF_DEPS)
-	$(CC) -c $(CFLAGS) xdiff/xpatience.c -o $(OUTDIR)/xpatience.o
 
 pathdef.c: $(INCL)
 ifneq (sh.exe, $(SHELL))
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -40,6 +40,12 @@
 #
 #       Terminal support: TERMINAL=yes (default is yes)
 #
+#	DLL support (EXPERIMENTAL): VIMDLL=yes (default is no)
+#	  Creates vim{32,64}.dll, and stub gvim.exe and vim.exe.
+#	  The shared codes between the GUI and the console are built into
+#	  the DLL.  This reduces the total file size and memory usage.
+#	  Also supports `vim -g` and the `:gui` command.
+#
 #	Lua interface:
 #	  LUA=[Path to Lua directory]
 #	  DYNAMIC_LUA=yes (to load the Lua DLL dynamically)
@@ -178,6 +184,10 @@
 
 TARGETOS = WINNT
 
+!if "$(VIMDLL)" == "yes"
+GUI = yes
+!endif
+
 !ifndef DIRECTX
 DIRECTX = $(GUI)
 !endif
@@ -185,7 +195,9 @@ DIRECTX = $(GUI)
 # Select one of eight object code directories, depends on GUI, OLE, DEBUG and
 # interfaces.
 # If you change something else, do "make clean" first!
-!if "$(GUI)" == "yes"
+!if "$(VIMDLL)" == "yes"
+OBJDIR = .\ObjD
+!elseif "$(GUI)" == "yes"
 OBJDIR = .\ObjG
 !else
 OBJDIR = .\ObjC
@@ -410,7 +422,7 @@ CHANNEL = $(GUI)
 !endif
 !endif
 
-# GUI sepcific features.
+# GUI specific features.
 !if "$(GUI)" == "yes"
 # Only allow NETBEANS for a GUI build and CHANNEL.
 !if "$(NETBEANS)" == "yes" && "$(CHANNEL)" == "yes"
@@ -461,7 +473,7 @@ XPM = no
 XPM_OBJ   = $(OBJDIR)/xpm_w32.obj
 XPM_DEFS  = -DFEAT_XPM_W32
 !if $(MSVC_MAJOR) >= 14
-# VC14 cannot use a library built by VC12 or eariler, because VC14 uses
+# VC14 cannot use a library built by VC12 or earlier, because VC14 uses
 # Universal CRT.
 XPM_LIB   = $(XPM)\lib-vc14\libXpm.lib
 !else
@@ -566,7 +578,7 @@ CPUARG =
 # VC<11 generates fp87 code by default
 !  if $(MSVC_MAJOR) < 11
 CPUARG =
-# VC>=11 needs explicit insturctions to generate fp87 code
+# VC>=11 needs explicit instructions to generate fp87 code
 !  else
 CPUARG = /arch:IA32
 !  endif
@@ -612,6 +624,17 @@ CPUARG = /arch:AVX2
 # Pass CPUARG to GvimExt, to avoid using version-dependent defaults
 MAKEFLAGS_GVIMEXT = $(MAKEFLAGS_GVIMEXT) CPUARG="$(CPUARG)"
 
+!if "$(VIMDLL)" == "yes"
+VIMDLLBASE = vim
+! if "$(ASSEMBLY_ARCHITECTURE)" == "i386"
+VIMDLLBASE = $(VIMDLLBASE)32
+! else
+VIMDLLBASE = $(VIMDLLBASE)64
+! endif
+! if "$(DEBUG)" == "yes"
+VIMDLLBASE = $(VIMDLLBASE)d
+! endif
+!endif
 
 LIBC =
 DEBUGINFO = /Zi
@@ -747,7 +770,6 @@ OBJ = \
 	$(OUTDIR)\ops.obj \
 	$(OUTDIR)\option.obj \
 	$(OUTDIR)\os_mswin.obj \
-	$(OUTDIR)\os_w32exe.obj \
 	$(OUTDIR)\os_win32.obj \
 	$(OUTDIR)\pathdef.obj \
 	$(OUTDIR)\popupmnu.obj \
@@ -769,7 +791,15 @@ OBJ = \
 	$(OUTDIR)\userfunc.obj \
 	$(OUTDIR)\winclip.obj \
 	$(OUTDIR)\window.obj \
-	$(OUTDIR)\vim.res
+
+!if "$(VIMDLL)" == "yes"
+OBJ = $(OBJ) $(OUTDIR)\os_w32dll.obj $(OUTDIR)\vimd.res
+EXEOBJC = $(OUTDIR)\os_w32exec.obj $(OUTDIR)\vimc.res
+EXEOBJG = $(OUTDIR)\os_w32exeg.obj $(OUTDIR)\vimg.res
+CFLAGS = $(CFLAGS) -DVIMDLL
+!else
+OBJ = $(OBJ) $(OUTDIR)\os_w32exe.obj $(OUTDIR)\vim.res
+!endif
 
 !if "$(OLE)" == "yes"
 CFLAGS = $(CFLAGS) -DFEAT_OLE
@@ -800,7 +830,15 @@ OBJ = $(OBJ) $(OUTDIR)\dimm_i.obj $(OUTD
 SUBSYSTEM = windows
 CFLAGS = $(CFLAGS) -DFEAT_GUI_MSWIN
 RCFLAGS = $(RCFLAGS) -DFEAT_GUI_MSWIN
+! if "$(VIMDLL)" == "yes"
+SUBSYSTEM_CON = console
+GVIM = g$(VIM)
+CUI_INCL = iscygpty.h
+CUI_OBJ = $(OUTDIR)\iscygpty.obj
+RCFLAGS = $(RCFLAGS) -DVIMDLL
+! else
 VIM = g$(VIM)
+! endif
 GUI_INCL = \
 	gui.h
 GUI_OBJ = \
@@ -839,6 +877,9 @@ XDIFF_DEPS = \
 !if "$(SUBSYSTEM_VER)" != ""
 SUBSYSTEM = $(SUBSYSTEM),$(SUBSYSTEM_VER)
 SUBSYSTEM_TOOLS = $(SUBSYSTEM_TOOLS),$(SUBSYSTEM_VER)
+! if "$(VIMDLL)" != "yes"
+SUBSYSTEM_CON = $(SUBSYSTEM_CON),$(SUBSYSTEM_VER)
+! endif
 # Pass SUBSYSTEM_VER to GvimExt and other tools
 MAKEFLAGS_GVIMEXT = $(MAKEFLAGS_GVIMEXT) SUBSYSTEM_VER=$(SUBSYSTEM_VER)
 MAKEFLAGS_TOOLS = $(MAKEFLAGS_TOOLS) SUBSYSTEM_VER=$(SUBSYSTEM_VER)
@@ -1174,7 +1215,11 @@ CFLAGS = $(CFLAGS) -DFEAT_$(FEATURES)
 # debug more conveniently (able to look at variables which are in registers)
 #
 CFLAGS = $(CFLAGS) /Fd$(OUTDIR)/ $(DEBUGINFO)
+!if "$(VIMDLL)" == "yes"
+LINK_PDB = /PDB:$(VIMDLLBASE).pdb -debug
+!else
 LINK_PDB = /PDB:$(VIM).pdb -debug
+!endif
 
 #
 # End extra feature include
@@ -1186,7 +1231,7 @@ CFLAGS_OUTDIR=$(CFLAGS) /Fo$(OUTDIR)/
 
 # Add /opt:ref to remove unreferenced functions and data even when /DEBUG is
 # added.
-conflags = /nologo /subsystem:$(SUBSYSTEM) /opt:ref
+conflags = /nologo /opt:ref
 
 PATHDEF_SRC = $(OUTDIR)\pathdef.c
 
@@ -1219,7 +1264,13 @@ LINKARGS1 = $(LINKARGS1) /LTCG:STATUS
 LINKARGS1 = $(LINKARGS1) /HIGHENTROPYVA:NO
 !endif
 
-all:	$(VIM).exe \
+!if "$(VIMDLL)" == "yes"
+MAIN_TARGET = $(GVIM).exe $(VIM).exe $(VIMDLLBASE).dll
+!else
+MAIN_TARGET = $(VIM).exe
+!endif
+
+all:	$(MAIN_TARGET) \
 	vimrun.exe \
 	install.exe \
 	uninstal.exe \
@@ -1227,17 +1278,41 @@ all:	$(VIM).exe \
 	tee/tee.exe \
 	GvimExt/gvimext.dll
 
+!if "$(VIMDLL)" == "yes"
+
+$(VIMDLLBASE).dll: $(OUTDIR) $(OBJ) $(XDIFF_OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) $(OLE_IDL) $(MZSCHEME_OBJ) \
+		$(LUA_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(PYTHON3_OBJ) $(RUBY_OBJ) $(TCL_OBJ) \
+		$(CSCOPE_OBJ) $(TERM_OBJ) $(NETBEANS_OBJ) $(CHANNEL_OBJ) $(XPM_OBJ) \
+		version.c version.h
+	$(CC) $(CFLAGS_OUTDIR) version.c
+	$(link) $(LINKARGS1) /dll -out:$(VIMDLLBASE).dll $(OBJ) $(XDIFF_OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) \
+		$(LUA_OBJ) $(MZSCHEME_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(PYTHON3_OBJ) $(RUBY_OBJ) \
+		$(TCL_OBJ) $(CSCOPE_OBJ) $(TERM_OBJ) $(NETBEANS_OBJ) $(CHANNEL_OBJ) \
+		$(XPM_OBJ) $(OUTDIR)\version.obj $(LINKARGS2)
+
+$(GVIM).exe: $(OUTDIR) $(EXEOBJG) $(VIMDLLBASE).dll
+	$(link) $(LINKARGS1) /subsystem:$(SUBSYSTEM) -out:$(GVIM).exe $(EXEOBJG) $(VIMDLLBASE).lib $(LIBC)
+	if exist $(GVIM).exe.manifest mt.exe -nologo -manifest $(GVIM).exe.manifest -updateresource:$(GVIM).exe;1
+
+$(VIM).exe: $(OUTDIR) $(EXEOBJC) $(VIMDLLBASE).dll
+	$(link) $(LINKARGS1) /subsystem:$(SUBSYSTEM_CON) -out:$(VIM).exe $(EXEOBJC) $(VIMDLLBASE).lib $(LIBC)
+	if exist $(VIM).exe.manifest mt.exe -nologo -manifest $(VIM).exe.manifest -updateresource:$(VIM).exe;1
+
+!else
+
 $(VIM).exe: $(OUTDIR) $(OBJ) $(XDIFF_OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) $(OLE_IDL) $(MZSCHEME_OBJ) \
 		$(LUA_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(PYTHON3_OBJ) $(RUBY_OBJ) $(TCL_OBJ) \
 		$(CSCOPE_OBJ) $(TERM_OBJ) $(NETBEANS_OBJ) $(CHANNEL_OBJ) $(XPM_OBJ) \
 		version.c version.h
 	$(CC) $(CFLAGS_OUTDIR) version.c
-	$(link) $(LINKARGS1) -out:$(VIM).exe $(OBJ) $(XDIFF_OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) \
+	$(link) $(LINKARGS1) /subsystem:$(SUBSYSTEM) -out:$(VIM).exe $(OBJ) $(XDIFF_OBJ) $(GUI_OBJ) $(CUI_OBJ) $(OLE_OBJ) \
 		$(LUA_OBJ) $(MZSCHEME_OBJ) $(PERL_OBJ) $(PYTHON_OBJ) $(PYTHON3_OBJ) $(RUBY_OBJ) \
 		$(TCL_OBJ) $(CSCOPE_OBJ) $(TERM_OBJ) $(NETBEANS_OBJ) $(CHANNEL_OBJ) \
 		$(XPM_OBJ) $(OUTDIR)\version.obj $(LINKARGS2)
 	if exist $(VIM).exe.manifest mt.exe -nologo -manifest $(VIM).exe.manifest -updateresource:$(VIM).exe;1
 
+!endif
+
 $(VIM): $(VIM).exe
 
 $(OUTDIR):
@@ -1287,6 +1362,15 @@ clean:
 	- if exist $(VIM).pdb del $(VIM).pdb
 	- if exist $(VIM).map del $(VIM).map
 	- if exist $(VIM).ncb del $(VIM).ncb
+!if "$(VIMDLL)" == "yes"
+	- if exist $(GVIM).exe del $(GVIM).exe
+	- if exist $(GVIM).map del $(GVIM).map
+	- if exist $(VIMDLLBASE).dll del $(VIMDLLBASE).dll
+	- if exist $(VIMDLLBASE).lib del $(VIMDLLBASE).lib
+	- if exist $(VIMDLLBASE).exp del $(VIMDLLBASE).exp
+	- if exist $(VIMDLLBASE).pdb del $(VIMDLLBASE).pdb
+	- if exist $(VIMDLLBASE).map del $(VIMDLLBASE).map
+!endif
 	- if exist vimrun.exe del vimrun.exe
 	- if exist install.exe del install.exe
 	- if exist uninstal.exe del uninstal.exe
@@ -1334,21 +1418,15 @@ testclean:
 ###########################################################################
 
 # Create a default rule for transforming .c files to .obj files in $(OUTDIR)
-# Batch compilation is supported by nmake 1.62 (part of VS 5.0) and later)
-!IF "$(_NMAKE_VER)" == ""
-.c{$(OUTDIR)/}.obj:
-!ELSE
 .c{$(OUTDIR)/}.obj::
-!ENDIF
+	$(CC) $(CFLAGS_OUTDIR) $<
+
+# Create a default rule for xdiff.
+{xdiff/}.c{$(OUTDIR)/}.obj::
 	$(CC) $(CFLAGS_OUTDIR) $<
 
 # Create a default rule for transforming .cpp files to .obj files in $(OUTDIR)
-# Batch compilation is supported by nmake 1.62 (part of VS 5.0) and later)
-!IF "$(_NMAKE_VER)" == ""
-.cpp{$(OUTDIR)/}.obj:
-!ELSE
 .cpp{$(OUTDIR)/}.obj::
-!ENDIF
 	$(CC) $(CFLAGS_OUTDIR) $<
 
 $(OUTDIR)/arabic.obj:	$(OUTDIR) arabic.c  $(INCL)
@@ -1376,22 +1454,16 @@ testclean:
 $(OUTDIR)/diff.obj:	$(OUTDIR) diff.c  $(INCL)
 
 $(OUTDIR)/xdiffi.obj:	$(OUTDIR) xdiff/xdiffi.c  $(XDIFF_DEPS)
-	$(CC) $(CFLAGS_OUTDIR) xdiff/xdiffi.c 
 
 $(OUTDIR)/xemit.obj:	$(OUTDIR) xdiff/xemit.c  $(XDIFF_DEPS)
-	$(CC) $(CFLAGS_OUTDIR) xdiff/xemit.c 
 
 $(OUTDIR)/xprepare.obj:	$(OUTDIR) xdiff/xprepare.c  $(XDIFF_DEPS)
-	$(CC) $(CFLAGS_OUTDIR) xdiff/xprepare.c 
 
 $(OUTDIR)/xutils.obj:	$(OUTDIR) xdiff/xutils.c  $(XDIFF_DEPS)
-	$(CC) $(CFLAGS_OUTDIR) xdiff/xutils.c 
 
 $(OUTDIR)/xhistogram.obj:	$(OUTDIR) xdiff/xhistogram.c  $(XDIFF_DEPS)
-	$(CC) $(CFLAGS_OUTDIR) xdiff/xhistogram.c 
 
 $(OUTDIR)/xpatience.obj:	$(OUTDIR) xdiff/xpatience.c  $(XDIFF_DEPS)
-	$(CC) $(CFLAGS_OUTDIR) xdiff/xpatience.c 
 
 $(OUTDIR)/digraph.obj:	$(OUTDIR) digraph.c  $(INCL)
 
@@ -1516,8 +1588,16 @@ lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).l
 
 $(OUTDIR)/os_win32.obj:	$(OUTDIR) os_win32.c  $(INCL) $(MZSCHEME_INCL)
 
+$(OUTDIR)/os_w32dll.obj:	$(OUTDIR) os_w32dll.c
+
 $(OUTDIR)/os_w32exe.obj:	$(OUTDIR) os_w32exe.c  $(INCL)
 
+$(OUTDIR)/os_w32exec.obj:	$(OUTDIR) os_w32exe.c  $(INCL)
+	$(CC) $(CFLAGS:-DFEAT_GUI_MSWIN=) /Fo$@ os_w32exe.c
+
+$(OUTDIR)/os_w32exeg.obj:	$(OUTDIR) os_w32exe.c  $(INCL)
+	$(CC) $(CFLAGS) /Fo$@ os_w32exe.c
+
 $(OUTDIR)/pathdef.obj:	$(OUTDIR) $(PATHDEF_SRC) $(INCL)
 	$(CC) $(CFLAGS_OUTDIR) $(PATHDEF_SRC)
 
@@ -1560,10 +1640,25 @@ lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).l
 $(OUTDIR)/xpm_w32.obj: $(OUTDIR) xpm_w32.c
 	$(CC) $(CFLAGS_OUTDIR) $(XPM_INC) xpm_w32.c
 
-$(OUTDIR)/vim.res:	$(OUTDIR) vim.rc gvim.exe.mnf version.h tools.bmp \
-				tearoff.bmp vim.ico vim_error.ico \
+!if "$(VIMDLL)" == "yes"
+$(OUTDIR)/vimc.res:	$(OUTDIR) vim.rc gvim.exe.mnf version.h gui_w32_rc.h \
+				vim.ico
+	$(RC) /nologo /l 0x409 /Fo$@ $(RCFLAGS:-DFEAT_GUI_MSWIN=) vim.rc
+
+$(OUTDIR)/vimg.res:	$(OUTDIR) vim.rc gvim.exe.mnf version.h gui_w32_rc.h \
+				vim.ico
+	$(RC) /nologo /l 0x409 /Fo$@ $(RCFLAGS) vim.rc
+
+$(OUTDIR)/vimd.res:	$(OUTDIR) vim.rc version.h gui_w32_rc.h \
+				tools.bmp tearoff.bmp vim.ico vim_error.ico \
 				vim_alert.ico vim_info.ico vim_quest.ico
-	$(RC) /nologo /l 0x409 /Fo$(OUTDIR)/vim.res $(RCFLAGS) vim.rc
+	$(RC) /nologo /l 0x409 /Fo$@ $(RCFLAGS) -DRCDLL -DVIMDLLBASE=\"$(VIMDLLBASE)\" vim.rc
+!else
+$(OUTDIR)/vim.res:	$(OUTDIR) vim.rc gvim.exe.mnf version.h gui_w32_rc.h \
+				tools.bmp tearoff.bmp vim.ico vim_error.ico \
+				vim_alert.ico vim_info.ico vim_quest.ico
+	$(RC) /nologo /l 0x409 /Fo$@ $(RCFLAGS) vim.rc
+!endif
 
 iid_ole.c if_ole.h vim.tlb: if_ole.idl
 	midl /nologo /error none /proxy nul /iid iid_ole.c /tlb vim.tlb \
@@ -1583,32 +1678,27 @@ CCCTERM = $(CC) $(CFLAGS) -Ilibvterm/inc
 	-DWCWIDTH_FUNCTION=utf_uint2cells \
 	-D_CRT_SECURE_NO_WARNINGS
 
+# Create a default rule for libvterm.
+{libvterm/src/}.c{$(OUTDIR)/}.obj::
+	$(CCCTERM) -Fo$(OUTDIR)/ $<
+
 $(OUTDIR)/encoding.obj: $(OUTDIR) libvterm/src/encoding.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/encoding.c
 
 $(OUTDIR)/keyboard.obj: $(OUTDIR) libvterm/src/keyboard.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/keyboard.c
 
 $(OUTDIR)/mouse.obj: $(OUTDIR) libvterm/src/mouse.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/mouse.c
 
 $(OUTDIR)/parser.obj: $(OUTDIR) libvterm/src/parser.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/parser.c
 
 $(OUTDIR)/pen.obj: $(OUTDIR) libvterm/src/pen.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/pen.c
 
 $(OUTDIR)/termscreen.obj: $(OUTDIR) libvterm/src/termscreen.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/termscreen.c
 
 $(OUTDIR)/state.obj: $(OUTDIR) libvterm/src/state.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/state.c
 
 $(OUTDIR)/unicode.obj: $(OUTDIR) libvterm/src/unicode.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/unicode.c
 
 $(OUTDIR)/vterm.obj: $(OUTDIR) libvterm/src/vterm.c $(TERM_DEPS)
-	$(CCCTERM) -Fo$@ libvterm/src/vterm.c
 
 
 # $CFLAGS may contain backslashes and double quotes, escape them both.
--- a/src/channel.c
+++ b/src/channel.c
@@ -5319,7 +5319,7 @@ job_still_useful(job_T *job)
     return job_need_end_check(job) || job_channel_still_useful(job);
 }
 
-#if defined(GUI_MAY_FORK) || defined(PROTO)
+#if defined(GUI_MAY_FORK) || defined(GUI_MAY_SPAWN) || defined(PROTO)
 /*
  * Return TRUE when there is any running job that we care about.
  */
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -4201,11 +4201,13 @@ f_foreground(typval_T *argvars UNUSED, t
 {
 #ifdef FEAT_GUI
     if (gui.in_use)
+    {
 	gui_mch_set_foreground();
-#else
-# ifdef MSWIN
+	return;
+    }
+#endif
+#if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
     win32_set_foreground();
-# endif
 #endif
 }
 
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -1537,7 +1537,7 @@ do_shell(
     int		flags)	/* may be SHELL_DOOUT when output is redirected */
 {
     buf_T	*buf;
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
     int		save_nwr;
 #endif
 #ifdef MSWIN
@@ -1636,32 +1636,37 @@ do_shell(
 	 * Otherwise there is probably text on the screen that the user wants
 	 * to read before redrawing, so call wait_return().
 	 */
-#ifndef FEAT_GUI_MSWIN
-	if (cmd == NULL
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
+# ifdef VIMDLL
+	if (!gui.in_use)
+# endif
+	{
+	    if (cmd == NULL
 # ifdef MSWIN
-		|| (keep_termcap && !need_wait_return)
+		    || (keep_termcap && !need_wait_return)
 # endif
-	   )
-	{
-	    if (msg_silent == 0)
-		redraw_later_clear();
-	    need_wait_return = FALSE;
-	}
-	else
-	{
-	    /*
-	     * If we switch screens when starttermcap() is called, we really
-	     * want to wait for "hit return to continue".
-	     */
-	    save_nwr = no_wait_return;
-	    if (swapping_screen())
-		no_wait_return = FALSE;
+	       )
+	    {
+		if (msg_silent == 0)
+		    redraw_later_clear();
+		need_wait_return = FALSE;
+	    }
+	    else
+	    {
+		/*
+		 * If we switch screens when starttermcap() is called, we
+		 * really want to wait for "hit return to continue".
+		 */
+		save_nwr = no_wait_return;
+		if (swapping_screen())
+		    no_wait_return = FALSE;
 # ifdef AMIGA
-	    wait_return(term_console ? -1 : msg_silent == 0);	/* see below */
+		wait_return(term_console ? -1 : msg_silent == 0); // see below
 # else
-	    wait_return(msg_silent == 0);
+		wait_return(msg_silent == 0);
 # endif
-	    no_wait_return = save_nwr;
+		no_wait_return = save_nwr;
+	    }
 	}
 #endif /* FEAT_GUI_MSWIN */
 
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -7756,7 +7756,10 @@ ex_winpos(exarg_T *eap)
     if (*arg == NUL)
     {
 # if defined(FEAT_GUI) || defined(MSWIN)
-#  ifdef FEAT_GUI
+#  ifdef VIMDLL
+	if (gui.in_use ? gui_mch_get_winpos(&x, &y) != FAIL :
+		mch_get_winpos(&x, &y) != FAIL)
+#  elif defined(FEAT_GUI)
 	if (gui.in_use && gui_mch_get_winpos(&x, &y) != FAIL)
 #  else
 	if (mch_get_winpos(&x, &y) != FAIL)
@@ -7789,13 +7792,12 @@ ex_winpos(exarg_T *eap)
 	    gui_win_x = x;
 	    gui_win_y = y;
 	}
-#  ifdef HAVE_TGETENT
+#  if defined(HAVE_TGETENT) || defined(VIMDLL)
 	else
 #  endif
-# else
-#  ifdef MSWIN
+# endif
+# if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
 	    mch_set_winpos(x, y);
-#  endif
 # endif
 # ifdef HAVE_TGETENT
 	if (*T_CWP)
@@ -8239,8 +8241,11 @@ ex_redraw(exarg_T *eap)
     if (need_maketitle)
 	maketitle();
 #endif
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
-    resize_console_buf();
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+# ifdef VIMDLL
+    if (!gui.in_use)
+# endif
+	resize_console_buf();
 #endif
     RedrawingDisabled = r;
     p_lz = p;
--- a/src/feature.h
+++ b/src/feature.h
@@ -712,7 +712,8 @@
  * there is no terminal version, and on Windows we can't figure out how to
  * fork one off with :gui.
  */
-#if defined(FEAT_GUI_MSWIN) || (defined(FEAT_GUI_MAC) && !defined(MACOS_X_DARWIN))
+#if (defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)) \
+	    || (defined(FEAT_GUI_MAC) && !defined(MACOS_X_DARWIN))
 # define ALWAYS_USE_GUI
 #endif
 
@@ -1138,8 +1139,8 @@
  * mouse shape		Adjust the shape of the mouse pointer to the mode.
  */
 #ifdef FEAT_NORMAL
-/* MS-DOS console and Win32 console can change cursor shape */
-# if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
+// Win32 console can change cursor shape
+# if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
 #  define MCH_CURSOR_SHAPE
 # endif
 # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \
@@ -1263,7 +1264,8 @@
  * +balloon_eval_term	Allow balloon expression evaluation in the terminal.
  */
 #if defined(FEAT_HUGE) && defined(FEAT_TIMERS) && \
-	(defined(UNIX) || defined(VMS) || (defined(MSWIN) && !defined(FEAT_GUI_MSWIN)))
+	(defined(UNIX) || defined(VMS) || \
+	 (defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))))
 # define FEAT_BEVAL_TERM
 #endif
 
@@ -1317,6 +1319,6 @@
 /*
  * +vtp: Win32 virtual console.
  */
-#if !defined(FEAT_GUI) && defined(MSWIN)
+#if (!defined(FEAT_GUI) || defined(VIMDLL)) && defined(MSWIN)
 # define FEAT_VTP
 #endif
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -792,7 +792,10 @@ readfile(
 	    if (!is_not_a_term())
 	    {
 #ifndef ALWAYS_USE_GUI
-		mch_msg(_("Vim: Reading from stdin...\n"));
+# ifdef VIMDLL
+		if (!gui.in_use)
+# endif
+		    mch_msg(_("Vim: Reading from stdin...\n"));
 #endif
 #ifdef FEAT_GUI
 		/* Also write a message in the GUI window, if there is one. */
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1626,7 +1626,11 @@ vgetc(void)
 #if defined(FEAT_GUI_MSWIN) && defined(FEAT_MENU) && defined(FEAT_TEAROFF)
 		// Handle K_TEAROFF here, the caller of vgetc() doesn't need to
 		// know that a menu was torn off
-		if (c == K_TEAROFF)
+		if (
+# ifdef VIMDLL
+		    gui.in_use &&
+# endif
+		    c == K_TEAROFF)
 		{
 		    char_u	name[200];
 		    int		i;
@@ -3113,6 +3117,7 @@ fix_input_buffer(char_u *buf, int len)
 	    p += 2;
 	    i -= 2;
 	}
+# ifndef MSWIN
 	/* When the GUI is not used CSI needs to be escaped. */
 	else if (!gui.in_use && p[0] == CSI)
 	{
@@ -3122,12 +3127,16 @@ fix_input_buffer(char_u *buf, int len)
 	    *p = (int)KE_CSI;
 	    len += 2;
 	}
+# endif
 	else
 #endif
 	if (p[0] == NUL || (p[0] == K_SPECIAL
 		    /* timeout may generate K_CURSORHOLD */
 		    && (i < 2 || p[1] != KS_EXTRA || p[2] != (int)KE_CURSORHOLD)
-#if defined(MSWIN) && !defined(FEAT_GUI)
+#if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
+# ifdef VIMDLL
+		    && !gui.in_use
+# endif
 		    /* Win32 console passes modifiers */
 		    && (i < 2 || p[1] != KS_MODIFIER)
 #endif
@@ -5232,20 +5241,21 @@ check_map(
 
 #if defined(MSWIN) || defined(MACOS_X)
 
-#define VIS_SEL	(VISUAL+SELECTMODE)	/* abbreviation */
+# define VIS_SEL	(VISUAL+SELECTMODE)	/* abbreviation */
 
 /*
  * Default mappings for some often used keys.
  */
-static struct initmap
+struct initmap
 {
     char_u	*arg;
     int		mode;
-} initmappings[] =
+};
+
+# ifdef FEAT_GUI_MSWIN
+/* Use the Windows (CUA) keybindings. (GUI) */
+static struct initmap initmappings[] =
 {
-#if defined(MSWIN)
-	/* Use the Windows (CUA) keybindings. */
-# ifdef FEAT_GUI
 	/* paste, copy and cut */
 	{(char_u *)"<S-Insert> \"*P", NORMAL},
 	{(char_u *)"<S-Insert> \"-d\"*P", VIS_SEL},
@@ -5255,7 +5265,13 @@ static struct initmap
 	{(char_u *)"<C-Del> \"*d", VIS_SEL},
 	{(char_u *)"<C-X> \"*d", VIS_SEL},
 	/* Missing: CTRL-C (cancel) and CTRL-V (block selection) */
-# else
+};
+# endif
+
+# if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
+/* Use the Windows (CUA) keybindings. (Console) */
+static struct initmap cinitmappings[] =
+{
 	{(char_u *)"\316w <C-Home>", NORMAL+VIS_SEL},
 	{(char_u *)"\316w <C-Home>", INSERT+CMDLINE},
 	{(char_u *)"\316u <C-End>", NORMAL+VIS_SEL},
@@ -5278,10 +5294,12 @@ static struct initmap
 	{(char_u *)"\316\327 d", VIS_SEL},	    /* SHIFT-Del is d */
 	{(char_u *)"\316\330 d", VIS_SEL},	    /* CTRL-Del is d */
 #  endif
+};
 # endif
-#endif
-
-#if defined(MACOS_X)
+
+# if defined(MACOS_X)
+static struct initmap initmappings[] =
+{
 	/* Use the Standard MacOS binding. */
 	/* paste, copy and cut */
 	{(char_u *)"<D-v> \"*P", NORMAL},
@@ -5290,8 +5308,8 @@ static struct initmap
 	{(char_u *)"<D-c> \"*y", VIS_SEL},
 	{(char_u *)"<D-x> \"*d", VIS_SEL},
 	{(char_u *)"<Backspace> \"-d", VIS_SEL},
-#endif
 };
+# endif
 
 # undef VIS_SEL
 #endif
@@ -5305,8 +5323,20 @@ init_mappings(void)
 #if defined(MSWIN) || defined(MACOS_X)
     int		i;
 
+# if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+#  ifdef VIMDLL
+    if (!gui.starting)
+#  endif
+    {
+	for (i = 0;
+		i < (int)(sizeof(cinitmappings) / sizeof(struct initmap)); ++i)
+	    add_map(cinitmappings[i].arg, cinitmappings[i].mode);
+    }
+# endif
+# if defined(FEAT_GUI_MSWIN) || defined(MACOS_X)
     for (i = 0; i < (int)(sizeof(initmappings) / sizeof(struct initmap)); ++i)
 	add_map(initmappings[i].arg, initmappings[i].mode);
+# endif
 #endif
 }
 
--- a/src/globals.h
+++ b/src/globals.h
@@ -1442,7 +1442,7 @@ EXTERN char e_nesting[]	INIT(= N_("E22: 
 EXTERN char e_noalt[]		INIT(= N_("E23: No alternate file"));
 EXTERN char e_noabbr[]	INIT(= N_("E24: No such abbreviation"));
 EXTERN char e_nobang[]	INIT(= N_("E477: No ! allowed"));
-#ifndef FEAT_GUI
+#if !defined(FEAT_GUI) || defined(VIMDLL)
 EXTERN char e_nogvim[]	INIT(= N_("E25: GUI cannot be used: Not enabled at compile time"));
 #endif
 #ifndef FEAT_RIGHTLEFT
@@ -1645,6 +1645,7 @@ EXTERN int *eval_lavars_used INIT(= NULL
 
 #ifdef MSWIN
 EXTERN int ctrl_break_was_pressed INIT(= FALSE);
+EXTERN HINSTANCE g_hinst INIT(= NULL);
 #endif
 
 #ifdef FEAT_TEXT_PROP
--- a/src/gui.c
+++ b/src/gui.c
@@ -65,10 +65,13 @@ static int disable_flush = 0;	/* If > 0,
  * recursive call.
  */
     void
-gui_start(void)
+gui_start(char_u *arg UNUSED)
 {
     char_u	*old_term;
     static int	recursive = 0;
+#ifdef GUI_MAY_SPAWN
+    char	*msg = NULL;
+#endif
 
     old_term = vim_strsave(T_NAME);
 
@@ -98,6 +101,22 @@ gui_start(void)
     }
     else
 #endif
+#ifdef GUI_MAY_SPAWN
+    if (gui.dospawn
+# ifdef EXPERIMENTAL_GUI_CMD
+	    && gui.dofork
+# endif
+	    && !vim_strchr(p_go, GO_FORG)
+	    && !anyBufIsChanged()
+# ifdef FEAT_JOB_CHANNEL
+	    && !job_any_running()
+# endif
+	    )
+    {
+	msg = gui_mch_do_spawn(arg);
+    }
+    else
+#endif
     {
 #ifdef FEAT_GUI_GTK
 	/* If there is 'f' in 'guioptions' and specify -g argument,
@@ -125,6 +144,10 @@ gui_start(void)
 #ifdef FEAT_TITLE
 	set_title_defaults();		/* set 'title' and 'icon' again */
 #endif
+#if defined(GUI_MAY_SPAWN) && defined(EXPERIMENTAL_GUI_CMD)
+	if (msg)
+	    emsg(msg);
+#endif
     }
 
     vim_free(old_term);
@@ -431,7 +454,7 @@ gui_init_check(void)
     gui.scrollbar_width = gui.scrollbar_height = SB_DEFAULT_WIDTH;
     gui.prev_wrap = -1;
 
-#ifdef ALWAYS_USE_GUI
+#if defined(ALWAYS_USE_GUI) || defined(VIMDLL)
     result = OK;
 #else
 # ifdef FEAT_GUI_GTK
@@ -4948,12 +4971,22 @@ ex_gui(exarg_T *eap)
     }
     if (!gui.in_use)
     {
+#if defined(VIMDLL) && !defined(EXPERIMENTAL_GUI_CMD)
+	emsg(_(e_nogvim));
+	return;
+#else
 	/* Clear the command.  Needed for when forking+exiting, to avoid part
 	 * of the argument ending up after the shell prompt. */
 	msg_clr_eos_force();
-	gui_start();
-#ifdef FEAT_JOB_CHANNEL
+# ifdef GUI_MAY_SPAWN
+	if (!ends_excmd(*eap->arg))
+	    gui_start(eap->arg);
+	else
+# endif
+	    gui_start(NULL);
+# ifdef FEAT_JOB_CHANNEL
 	channel_gui_register_all();
+# endif
 #endif
     }
     if (!ends_excmd(*eap->arg))
--- a/src/gui.h
+++ b/src/gui.h
@@ -237,6 +237,16 @@ typedef long	    guicolor_T;	/* handle f
 # endif
 #endif
 
+#ifdef VIMDLL
+// Use spawn when GUI is starting.
+# define GUI_MAY_SPAWN
+
+// Uncomment the next definition if you want to use the `:gui` command on
+// Windows.  It uses `:mksession` to inherit the session from vim.exe to
+// gvim.exe.  So, it doesn't work perfectly. (EXPERIMENTAL)
+//# define EXPERIMENTAL_GUI_CMD
+#endif
+
 typedef struct Gui
 {
     int		in_focus;	    /* Vim has input focus */
@@ -245,6 +255,9 @@ typedef struct Gui
     int		shell_created;	    /* Has the shell been created yet? */
     int		dying;		    /* Is vim dying? Then output to terminal */
     int		dofork;		    /* Use fork() when GUI is starting */
+#ifdef GUI_MAY_SPAWN
+    int		dospawn;	    /* Use spawn() when GUI is starting */
+#endif
     int		dragged_sb;	    /* Which scrollbar being dragged, if any? */
     win_T	*dragged_wp;	    /* Which WIN's sb being dragged, if any? */
     int		pointer_hidden;	    /* Is the mouse pointer hidden? */
--- a/src/gui_gtk_x11.c
+++ b/src/gui_gtk_x11.c
@@ -2315,75 +2315,6 @@ sm_client_check_changed_any(GnomeClient	
 }
 
 /*
- * Generate a script that can be used to restore the current editing session.
- * Save the value of v:this_session before running :mksession in order to make
- * automagic session save fully transparent.  Return TRUE on success.
- */
-    static int
-write_session_file(char_u *filename)
-{
-    char_u	    *escaped_filename;
-    char	    *mksession_cmdline;
-    unsigned int    save_ssop_flags;
-    int		    failed;
-
-    /*
-     * Build an ex command line to create a script that restores the current
-     * session if executed.  Escape the filename to avoid nasty surprises.
-     */
-    escaped_filename = vim_strsave_escaped(filename, escape_chars);
-    if (escaped_filename == NULL)
-	return FALSE;
-    mksession_cmdline = g_strconcat("mksession ", (char *)escaped_filename,
-									NULL);
-    vim_free(escaped_filename);
-
-    /*
-     * Use a reasonable hardcoded set of 'sessionoptions' flags to avoid
-     * unpredictable effects when the session is saved automatically.  Also,
-     * we definitely need SSOP_GLOBALS to be able to restore v:this_session.
-     * Don't use SSOP_BUFFERS to prevent the buffer list from becoming
-     * enormously large if the GNOME session feature is used regularly.
-     */
-    save_ssop_flags = ssop_flags;
-    ssop_flags = (SSOP_BLANK|SSOP_CURDIR|SSOP_FOLDS|SSOP_GLOBALS
-		  |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE|SSOP_TABPAGES);
-
-    do_cmdline_cmd((char_u *)"let Save_VV_this_session = v:this_session");
-    failed = (do_cmdline_cmd((char_u *)mksession_cmdline) == FAIL);
-    do_cmdline_cmd((char_u *)"let v:this_session = Save_VV_this_session");
-    do_unlet((char_u *)"Save_VV_this_session", TRUE);
-
-    ssop_flags = save_ssop_flags;
-    g_free(mksession_cmdline);
-
-    /*
-     * Reopen the file and append a command to restore v:this_session,
-     * as if this save never happened.	This is to avoid conflicts with
-     * the user's own sessions.  FIXME: It's probably less hackish to add
-     * a "stealth" flag to 'sessionoptions' -- gotta ask Bram.
-     */
-    if (!failed)
-    {
-	FILE *fd;
-
-	fd = open_exfile(filename, TRUE, APPENDBIN);
-
-	failed = (fd == NULL
-	       || put_line(fd, "let v:this_session = Save_VV_this_session") == FAIL
-	       || put_line(fd, "unlet Save_VV_this_session") == FAIL);
-
-	if (fd != NULL && fclose(fd) != 0)
-	    failed = TRUE;
-
-	if (failed)
-	    mch_remove(filename);
-    }
-
-    return !failed;
-}
-
-/*
  * "save_yourself" signal handler.  Initiate an interaction to ask the user
  * for confirmation if necessary.  Save the current editing session and tell
  * the session manager how to restart Vim.
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -320,7 +320,6 @@ static int		s_findrep_is_find;	// TRUE f
 						// for find/replace dialog
 #endif
 
-static HINSTANCE	s_hinst = NULL;
 #if !defined(FEAT_GUI)
 static
 #endif
@@ -1424,7 +1423,7 @@ gui_mch_create_scrollbar(
 	10,				/* Any value will do for now */
 	10,				/* Any value will do for now */
 	s_hwnd, NULL,
-	s_hinst, NULL);
+	g_hinst, NULL);
 }
 
 /*
@@ -2237,15 +2236,6 @@ gui_mch_draw_menubar(void)
 }
 #endif /*FEAT_MENU*/
 
-#ifndef PROTO
-void
-_cdecl
-SaveInst(HINSTANCE hInst)
-{
-    s_hinst = hInst;
-}
-#endif
-
 /*
  * Return the RGB value of a pixel as a long.
  */
@@ -4839,6 +4829,141 @@ ole_error(char *arg)
 }
 #endif
 
+#if defined(GUI_MAY_SPAWN) || defined(PROTO)
+    static char *
+gvim_error(void)
+{
+    char *msg = _("E988: GUI cannot be used. Cannot execute gvim.exe.");
+
+    if (starting)
+    {
+	mch_errmsg(msg);
+	mch_errmsg("\n");
+	mch_exit(2);
+    }
+    return msg;
+}
+
+    char *
+gui_mch_do_spawn(char_u *arg)
+{
+    int			len;
+# if defined(FEAT_SESSION) && defined(EXPERIMENTAL_GUI_CMD)
+    char_u		*session = NULL;
+    LPWSTR		tofree1 = NULL;
+# endif
+    WCHAR		name[MAX_PATH];
+    LPWSTR		cmd, newcmd = NULL, p, warg, tofree2 = NULL;
+    STARTUPINFOW	si = {sizeof(si)};
+    PROCESS_INFORMATION pi;
+
+    if (!GetModuleFileNameW(g_hinst, name, MAX_PATH))
+	goto error;
+    p = wcsrchr(name, L'\\');
+    if (p == NULL)
+	goto error;
+    // Replace the executable name from vim(d).exe to gvim(d).exe.
+# ifdef DEBUG
+    wcscpy(p + 1, L"gvimd.exe");
+# else
+    wcscpy(p + 1, L"gvim.exe");
+# endif
+
+# if defined(FEAT_SESSION) && defined(EXPERIMENTAL_GUI_CMD)
+    if (starting)
+# endif
+    {
+	// Pass the command line to the new process.
+	p = GetCommandLineW();
+	// Skip 1st argument.
+	while (*p && *p != L' ' && *p != L'\t')
+	{
+	    if (*p == L'"')
+	    {
+		while (*p && *p != L'"')
+		    ++p;
+		if (*p)
+		    ++p;
+	    }
+	    else
+		++p;
+	}
+	cmd = p;
+    }
+# if defined(FEAT_SESSION) && defined(EXPERIMENTAL_GUI_CMD)
+    else
+    {
+	// Create a session file and pass it to the new process.
+	LPWSTR	wsession;
+	char_u	*savebg;
+	int	ret;
+
+	session = vim_tempname('s', FALSE);
+	if (session == NULL)
+	    goto error;
+	savebg = p_bg;
+	p_bg = vim_strsave((char_u *)"light");	// Set 'bg' to "light".
+	ret = write_session_file(session);
+	vim_free(p_bg);
+	p_bg = savebg;
+	if (!ret)
+	    goto error;
+	wsession = enc_to_utf16(session, NULL);
+	if (wsession == NULL)
+	    goto error;
+	len = (int)wcslen(wsession) * 2 + 27 + 1;
+	cmd = (LPWSTR)alloc(len * (int)sizeof(WCHAR));
+	if (cmd == NULL)
+	{
+	    vim_free(wsession);
+	    goto error;
+	}
+	tofree1 = cmd;
+	_snwprintf(cmd, len, L" -S \"%s\" -c \"call delete('%s')\"",
+		wsession, wsession);
+	vim_free(wsession);
+    }
+# endif
+
+    // Check additional arguments to the `:gui` command.
+    if (arg != NULL)
+    {
+	warg = enc_to_utf16(arg, NULL);
+	if (warg == NULL)
+	    goto error;
+	tofree2 = warg;
+    }
+    else
+	warg = L"";
+
+    // Set up the new command line.
+    len = (int)wcslen(name) + (int)wcslen(cmd) + (int)wcslen(warg) + 4;
+    newcmd = (LPWSTR)alloc(len * (int)sizeof(WCHAR));
+    if (newcmd == NULL)
+	goto error;
+    _snwprintf(newcmd, len, L"\"%s\"%s %s", name, cmd, warg);
+
+    // Spawn a new GUI process.
+    if (!CreateProcessW(NULL, newcmd, NULL, NULL, TRUE, 0,
+		NULL, NULL, &si, &pi))
+	goto error;
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
+    mch_exit(0);
+
+error:
+# if defined(FEAT_SESSION) && defined(EXPERIMENTAL_GUI_CMD)
+    if (session)
+	mch_remove(session);
+    vim_free(session);
+    vim_free(tofree1);
+# endif
+    vim_free(newcmd);
+    vim_free(tofree2);
+    return gvim_error();
+}
+#endif
+
 /*
  * Parse the GUI related command-line arguments.  Any arguments used are
  * deleted from argv, and *argc is decremented accordingly.  This is called
@@ -4957,7 +5082,7 @@ gui_mch_init(void)
      * Load the tearoff bitmap
      */
 #ifdef FEAT_TEAROFF
-    s_htearbitmap = LoadBitmap(s_hinst, "IDB_TEAROFF");
+    s_htearbitmap = LoadBitmap(g_hinst, "IDB_TEAROFF");
 #endif
 
     gui.scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
@@ -4971,13 +5096,13 @@ gui_mch_init(void)
 
     /* First try using the wide version, so that we can use any title.
      * Otherwise only characters in the active codepage will work. */
-    if (GetClassInfoW(s_hinst, szVimWndClassW, &wndclassw) == 0)
+    if (GetClassInfoW(g_hinst, szVimWndClassW, &wndclassw) == 0)
     {
 	wndclassw.style = CS_DBLCLKS;
 	wndclassw.lpfnWndProc = _WndProc;
 	wndclassw.cbClsExtra = 0;
 	wndclassw.cbWndExtra = 0;
-	wndclassw.hInstance = s_hinst;
+	wndclassw.hInstance = g_hinst;
 	wndclassw.hIcon = LoadIcon(wndclassw.hInstance, "IDR_VIM");
 	wndclassw.hCursor = LoadCursor(NULL, IDC_ARROW);
 	wndclassw.hbrBackground = s_brush;
@@ -5011,7 +5136,7 @@ gui_mch_init(void)
 		100,				// Any value will do
 		100,				// Any value will do
 		vim_parent_hwnd, NULL,
-		s_hinst, NULL);
+		g_hinst, NULL);
 #ifdef HAVE_TRY_EXCEPT
 	}
 	__except(EXCEPTION_EXECUTE_HANDLER)
@@ -5043,7 +5168,7 @@ gui_mch_init(void)
 		100,				/* Any value will do */
 		100,				/* Any value will do */
 		NULL, NULL,
-		s_hinst, NULL);
+		g_hinst, NULL);
 	if (s_hwnd != NULL && win_socket_id != 0)
 	{
 	    SetParent(s_hwnd, (HWND)win_socket_id);
@@ -5062,13 +5187,13 @@ gui_mch_init(void)
 #endif
 
     /* Create the text area window */
-    if (GetClassInfoW(s_hinst, szTextAreaClassW, &wndclassw) == 0)
+    if (GetClassInfoW(g_hinst, szTextAreaClassW, &wndclassw) == 0)
     {
 	wndclassw.style = CS_OWNDC;
 	wndclassw.lpfnWndProc = _TextAreaWndProc;
 	wndclassw.cbClsExtra = 0;
 	wndclassw.cbWndExtra = 0;
-	wndclassw.hInstance = s_hinst;
+	wndclassw.hInstance = g_hinst;
 	wndclassw.hIcon = NULL;
 	wndclassw.hCursor = LoadCursor(NULL, IDC_ARROW);
 	wndclassw.hbrBackground = NULL;
@@ -5086,7 +5211,7 @@ gui_mch_init(void)
 	100,				// Any value will do for now
 	100,				// Any value will do for now
 	s_hwnd, NULL,
-	s_hinst, NULL);
+	g_hinst, NULL);
 
     if (s_textArea == NULL)
 	return FAIL;
@@ -6640,8 +6765,11 @@ gui_mch_dialog(
 
 #ifndef NO_CONSOLE
     /* Don't output anything in silent mode ("ex -s") */
-    if (silent_mode)
-	return dfltbutton;   /* return default option */
+# ifdef VIMDLL
+    if (!(gui.in_use || gui.starting))
+# endif
+	if (silent_mode)
+	    return dfltbutton;   /* return default option */
 #endif
 
     if (s_hwnd == NULL)
@@ -7050,7 +7178,7 @@ gui_mch_dialog(
 
     /* show the dialog box modally and get a return value */
     nchar = (int)DialogBoxIndirect(
-	    s_hinst,
+	    g_hinst,
 	    (LPDLGTEMPLATE)pdlgtemplate,
 	    s_hwnd,
 	    (DLGPROC)dialog_callback);
@@ -7644,7 +7772,7 @@ gui_mch_tearoff(
 
     /* show modelessly */
     the_menu->tearoff_handle = CreateDialogIndirectParam(
-	    s_hinst,
+	    g_hinst,
 	    (LPDLGTEMPLATE)pdlgtemplate,
 	    s_hwnd,
 	    (DLGPROC)tearoff_callback,
@@ -7689,7 +7817,7 @@ initialise_toolbar(void)
 		    WS_CHILD | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT,
 		    4000,		//any old big number
 		    31,			//number of images in initial bitmap
-		    s_hinst,
+		    g_hinst,
 		    IDR_TOOLBAR1,	// id of initial bitmap
 		    NULL,
 		    0,			// initial number of buttons
@@ -7790,7 +7918,7 @@ initialise_tabline(void)
     s_tabhwnd = CreateWindow(WC_TABCONTROL, "Vim tabline",
 	    WS_CHILD|TCS_FOCUSNEVER|TCS_TOOLTIPS,
 	    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
-	    CW_USEDEFAULT, s_hwnd, NULL, s_hinst, NULL);
+	    CW_USEDEFAULT, s_hwnd, NULL, g_hinst, NULL);
     s_tabline_wndproc = SubclassWindow(s_tabhwnd, tabline_wndproc);
 
     gui.tabline_height = TABLINE_HEIGHT;
@@ -8245,7 +8373,7 @@ make_tooltip(BalloonEval *beval, char *t
     beval->balloon = CreateWindowExW(WS_EX_TOPMOST, TOOLTIPS_CLASSW,
 	    NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
 	    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
-	    beval->target, NULL, s_hinst, NULL);
+	    beval->target, NULL, g_hinst, NULL);
 
     SetWindowPos(beval->balloon, HWND_TOPMOST, 0, 0, 0, 0,
 	    SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
--- a/src/if_mzsch.c
+++ b/src/if_mzsch.c
@@ -822,7 +822,7 @@ static EventLoopTimerRef timer_id = NULL
 static EventLoopTimerUPP timerUPP;
 #endif
 
-#ifndef FEAT_GUI_MSWIN /* Win32 console and Unix */
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL) /* Win32 console and Unix */
     void
 mzvim_check_threads(void)
 {
@@ -1775,9 +1775,11 @@ get_option(void *data, int argc, Scheme_
     case -2:
 	MZ_GC_UNREG();
 	raise_vim_exn(_("hidden option"));
+	/*NOTREACHED*/
     case -3:
 	MZ_GC_UNREG();
 	raise_vim_exn(_("unknown option"));
+	/*NOTREACHED*/
     }
     /* unreachable */
     return scheme_void;
--- a/src/main.c
+++ b/src/main.c
@@ -19,7 +19,7 @@
 # include <limits.h>
 #endif
 
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
 # include "iscygpty.h"
 #endif
 
@@ -95,6 +95,9 @@ static char_u *start_dir = NULL;	/* curr
 
 static int has_dash_c_arg = FALSE;
 
+# ifdef VIMDLL
+__declspec(dllexport)
+# endif
     int
 # ifdef MSWIN
 #  ifdef __BORLANDC__
@@ -174,6 +177,11 @@ main
 #endif
     common_init(&params);
 
+#ifdef VIMDLL
+    // Check if the current executable file is for the GUI subsystem.
+    gui.starting = mch_is_gui_executable();
+#endif
+
 #ifdef FEAT_CLIENTSERVER
     /*
      * Do the client-server stuff, unless "--servername ''" was used.
@@ -292,7 +300,8 @@ main
      * For GTK we can't be sure, but when started from the desktop it doesn't
      * make sense to try using a terminal.
      */
-#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
+#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \
+	|| defined(VIMDLL)
     if (gui.starting
 # ifdef FEAT_GUI_GTK
 	    && !isatty(2)
@@ -542,7 +551,7 @@ vim_main2(void)
 	    putchar('\n');
 #endif
 
-	gui_start();		/* will set full_screen to TRUE */
+	gui_start(NULL);		/* will set full_screen to TRUE */
 	TIME_MSG("starting GUI");
 
 	/* When running "evim" or "gvim -y" we need the menus, exit if we
@@ -851,8 +860,11 @@ vim_main2(void)
     }
 #endif
 
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
-    mch_set_winsize_now();	    /* Allow winsize changes from now on */
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+# ifdef VIMDLL
+    if (!gui.in_use)
+# endif
+	mch_set_winsize_now();	    /* Allow winsize changes from now on */
 #endif
 
 #if defined(FEAT_GUI)
@@ -1761,7 +1773,15 @@ parse_command_name(mparm_T *parmp)
 #ifdef FEAT_GUI
 	++initstr;
 #endif
+#ifdef GUI_MAY_SPAWN
+	gui.dospawn = FALSE;	// No need to spawn a new process.
+#endif
     }
+#ifdef GUI_MAY_SPAWN
+    else
+	gui.dospawn = TRUE;	// Not "gvim". Need to spawn gvim.exe.
+#endif
+
 
     if (STRNICMP(initstr, "view", 4) == 0)
     {
@@ -2181,7 +2201,7 @@ command_line_scan(mparm_T *parmp)
 
 	    case 'v':		/* "-v"  Vi-mode (as if called "vi") */
 		exmode_active = 0;
-#ifdef FEAT_GUI
+#if defined(FEAT_GUI) && !defined(VIMDLL)
 		gui.starting = FALSE;	/* don't start GUI */
 #endif
 		break;
@@ -2558,8 +2578,12 @@ check_tty(mparm_T *parmp)
 	    exit(1);
 	}
 #endif
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
-	if (is_cygpty_used())
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+	if (
+# ifdef VIMDLL
+	    !gui.starting &&
+# endif
+	    is_cygpty_used())
 	{
 # if defined(HAVE_BIND_TEXTDOMAIN_CODESET) \
 	&& defined(FEAT_GETTEXT)
@@ -3440,8 +3464,13 @@ usage(void)
     main_msg(_("--echo-wid\t\tMake gvim echo the Window ID on stdout"));
 #endif
 #ifdef FEAT_GUI_MSWIN
-    main_msg(_("-P <parent title>\tOpen Vim inside parent application"));
-    main_msg(_("--windowid <HWND>\tOpen Vim inside another win32 widget"));
+# ifdef VIMDLL
+    if (gui.starting)
+# endif
+    {
+	main_msg(_("-P <parent title>\tOpen Vim inside parent application"));
+	main_msg(_("--windowid <HWND>\tOpen Vim inside another win32 widget"));
+    }
 #endif
 
 #ifdef FEAT_GUI_GNOME
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -4392,7 +4392,7 @@ enc_alias_search(char_u *name)
 # include <langinfo.h>
 #endif
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 /*
  * Get the canonicalized encoding from the specified locale string "locale"
  * or from the environment variables LC_ALL, LC_CTYPE and LANG.
--- a/src/memline.c
+++ b/src/memline.c
@@ -4798,7 +4798,7 @@ findswapname(
 			// the messages displayed in the Vim window when
 			// loading a session from the .gvimrc file.
 			if (gui.starting && !gui.in_use)
-			    gui_start();
+			    gui_start(NULL);
 #endif
 			// Show info about the existing swap file.
 			attention_message(buf, fname);
--- a/src/message.c
+++ b/src/message.c
@@ -2563,8 +2563,12 @@ t_puts(
 msg_use_printf(void)
 {
     return (!msg_check_screen()
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+# ifdef VIMDLL
+	    || (!gui.in_use && !termcap_active)
+# else
 	    || !termcap_active
+# endif
 #endif
 	    || (swapping_screen() && !termcap_active)
 	       );
@@ -2940,15 +2944,10 @@ do_more_prompt(int typed_char)
 # undef mch_msg
 #endif
 
-/*
- * Give an error message.  To be used when the screen hasn't been initialized
- * yet.  When stderr can't be used, collect error messages until the GUI has
- * started and they can be displayed in a message box.
- */
-    void
-mch_errmsg(char *str)
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+    static void
+mch_errmsg_c(char *str)
 {
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
     int	    len = (int)STRLEN(str);
     DWORD   nwrite = 0;
     DWORD   mode = 0;
@@ -2966,34 +2965,57 @@ mch_errmsg(char *str)
     {
 	fprintf(stderr, "%s", str);
     }
-#else
+}
+#endif
+
+/*
+ * Give an error message.  To be used when the screen hasn't been initialized
+ * yet.  When stderr can't be used, collect error messages until the GUI has
+ * started and they can be displayed in a message box.
+ */
+    void
+mch_errmsg(char *str)
+{
+#if !defined(MSWIN) || defined(FEAT_GUI_MSWIN)
     int		len;
-
-# if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
+#endif
+
+#if (defined(UNIX) || defined(FEAT_GUI)) && (!defined(ALWAYS_USE_GUI) || !defined(VIMDLL))
     /* On Unix use stderr if it's a tty.
      * When not going to start the GUI also use stderr.
      * On Mac, when started from Finder, stderr is the console. */
     if (
-#  ifdef UNIX
-#   ifdef MACOS_X
+# ifdef UNIX
+#  ifdef MACOS_X
 	    (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
-#   else
+#  else
 	    isatty(2)
-#   endif
-#   ifdef FEAT_GUI
-	    ||
-#   endif
 #  endif
 #  ifdef FEAT_GUI
+	    ||
+#  endif
+# endif
+# ifdef FEAT_GUI
 	    !(gui.in_use || gui.starting)
-#  endif
+# endif
 	    )
     {
 	fprintf(stderr, "%s", str);
 	return;
     }
+#endif
+
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+# ifdef VIMDLL
+    if (!(gui.in_use || gui.starting))
 # endif
-
+    {
+	mch_errmsg_c(str);
+	return;
+    }
+#endif
+
+#if !defined(MSWIN) || defined(FEAT_GUI_MSWIN)
     /* avoid a delay for a message that isn't there */
     emsg_on_display = FALSE;
 
@@ -3028,15 +3050,10 @@ mch_errmsg(char *str)
 #endif
 }
 
-/*
- * Give a message.  To be used when the screen hasn't been initialized yet.
- * When there is no tty, collect messages until the GUI has started and they
- * can be displayed in a message box.
- */
-    void
-mch_msg(char *str)
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+    static void
+mch_msg_c(char *str)
 {
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
     int	    len = (int)STRLEN(str);
     DWORD   nwrite = 0;
     DWORD   mode;
@@ -3055,32 +3072,53 @@ mch_msg(char *str)
     {
 	printf("%s", str);
     }
-#else
-# if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI)
+}
+#endif
+
+/*
+ * Give a message.  To be used when the screen hasn't been initialized yet.
+ * When there is no tty, collect messages until the GUI has started and they
+ * can be displayed in a message box.
+ */
+    void
+mch_msg(char *str)
+{
+#if (defined(UNIX) || defined(FEAT_GUI)) && (!defined(ALWAYS_USE_GUI) || !defined(VIMDLL))
     /* On Unix use stdout if we have a tty.  This allows "vim -h | more" and
      * uses mch_errmsg() when started from the desktop.
      * When not going to start the GUI also use stdout.
      * On Mac, when started from Finder, stderr is the console. */
     if (
-#  ifdef UNIX
-#   ifdef MACOS_X
+# ifdef UNIX
+#  ifdef MACOS_X
 	    (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0)
-#   else
+#  else
 	    isatty(2)
-#    endif
-#   ifdef FEAT_GUI
+#   endif
+#  ifdef FEAT_GUI
 	    ||
-#   endif
 #  endif
-#  ifdef FEAT_GUI
+# endif
+# ifdef FEAT_GUI
 	    !(gui.in_use || gui.starting)
-#  endif
+# endif
 	    )
     {
 	printf("%s", str);
 	return;
     }
+#endif
+
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+# ifdef VIMDLL
+    if (!(gui.in_use || gui.starting))
 # endif
+    {
+	mch_msg_c(str);
+	return;
+    }
+#endif
+#if !defined(MSWIN) || defined(FEAT_GUI_MSWIN)
     mch_errmsg(str);
 #endif
 }
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -4650,3 +4650,80 @@ build_argv_from_list(list_T *l, char ***
 }
 # endif
 #endif
+
+#if defined(FEAT_SESSION) || defined(PROTO)
+/*
+ * Generate a script that can be used to restore the current editing session.
+ * Save the value of v:this_session before running :mksession in order to make
+ * automagic session save fully transparent.  Return TRUE on success.
+ */
+    int
+write_session_file(char_u *filename)
+{
+    char_u	    *escaped_filename;
+    char	    *mksession_cmdline;
+    unsigned int    save_ssop_flags;
+    int		    failed;
+
+    /*
+     * Build an ex command line to create a script that restores the current
+     * session if executed.  Escape the filename to avoid nasty surprises.
+     */
+    escaped_filename = vim_strsave_escaped(filename, escape_chars);
+    if (escaped_filename == NULL)
+	return FALSE;
+    mksession_cmdline = (char *)alloc(10 + (int)STRLEN(escaped_filename) + 1);
+    if (mksession_cmdline == NULL)
+    {
+	vim_free(escaped_filename);
+	return FALSE;
+    }
+    strcpy(mksession_cmdline, "mksession ");
+    STRCAT(mksession_cmdline, escaped_filename);
+    vim_free(escaped_filename);
+
+    /*
+     * Use a reasonable hardcoded set of 'sessionoptions' flags to avoid
+     * unpredictable effects when the session is saved automatically.  Also,
+     * we definitely need SSOP_GLOBALS to be able to restore v:this_session.
+     * Don't use SSOP_BUFFERS to prevent the buffer list from becoming
+     * enormously large if the GNOME session feature is used regularly.
+     */
+    save_ssop_flags = ssop_flags;
+    ssop_flags = (SSOP_BLANK|SSOP_CURDIR|SSOP_FOLDS|SSOP_GLOBALS
+		  |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE|SSOP_TABPAGES);
+
+    do_cmdline_cmd((char_u *)"let Save_VV_this_session = v:this_session");
+    failed = (do_cmdline_cmd((char_u *)mksession_cmdline) == FAIL);
+    do_cmdline_cmd((char_u *)"let v:this_session = Save_VV_this_session");
+    do_unlet((char_u *)"Save_VV_this_session", TRUE);
+
+    ssop_flags = save_ssop_flags;
+    vim_free(mksession_cmdline);
+
+    /*
+     * Reopen the file and append a command to restore v:this_session,
+     * as if this save never happened.	This is to avoid conflicts with
+     * the user's own sessions.  FIXME: It's probably less hackish to add
+     * a "stealth" flag to 'sessionoptions' -- gotta ask Bram.
+     */
+    if (!failed)
+    {
+	FILE *fd;
+
+	fd = open_exfile(filename, TRUE, APPENDBIN);
+
+	failed = (fd == NULL
+	       || put_line(fd, "let v:this_session = Save_VV_this_session") == FAIL
+	       || put_line(fd, "unlet Save_VV_this_session") == FAIL);
+
+	if (fd != NULL && fclose(fd) != 0)
+	    failed = TRUE;
+
+	if (failed)
+	    mch_remove(filename);
+    }
+
+    return !failed;
+}
+#endif
--- a/src/normal.c
+++ b/src/normal.c
@@ -5394,8 +5394,11 @@ nv_clear(cmdarg_T *cap)
 # endif
 #endif
 	redraw_later(CLEAR);
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
-	resize_console_buf();
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+# ifdef VIMDLL
+	if (!gui.in_use)
+# endif
+	    resize_console_buf();
 #endif
     }
 }
--- a/src/option.c
+++ b/src/option.c
@@ -3321,9 +3321,7 @@ set_init_1(int clean_arg)
     if (((p = mch_getenv((char_u *)"SHELL")) != NULL && *p != NUL)
 #if defined(MSWIN)
 	    || ((p = mch_getenv((char_u *)"COMSPEC")) != NULL && *p != NUL)
-# ifdef MSWIN
 	    || ((p = (char_u *)default_shell()) != NULL && *p != NUL)
-# endif
 #endif
 	    )
 	set_string_default_esc("sh", p, TRUE);
@@ -3673,10 +3671,14 @@ set_init_1(int clean_arg)
 	    }
 #endif
 
-#if defined(MSWIN) && !defined(FEAT_GUI)
+#if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
 	    /* Win32 console: When GetACP() returns a different value from
 	     * GetConsoleCP() set 'termencoding'. */
-	    if (GetACP() != GetConsoleCP())
+	    if (
+# ifdef VIMDLL
+	       (!gui.in_use && !gui.starting) &&
+# endif
+	        GetACP() != GetConsoleCP())
 	    {
 		char	buf[50];
 
@@ -6856,11 +6858,14 @@ did_set_string_option(
 	{
 	    out_str(T_ME);
 	    redraw_later(CLEAR);
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
 	    /* Since t_me has been set, this probably means that the user
 	     * wants to use this as default colors.  Need to reset default
 	     * background/foreground colors. */
-	    mch_set_normal_colors();
+# ifdef VIMDLL
+	    if (!gui.in_use && !gui.starting)
+# endif
+		mch_set_normal_colors();
 #endif
 	}
 	if (varp == &T_BE && termcap_active)
@@ -8838,7 +8843,11 @@ set_bool_option(
     {
 # ifdef FEAT_VTP
 	/* Do not turn on 'tgc' when 24-bit colors are not supported. */
-	if (!has_vtp_working())
+	if (
+#  ifdef VIMDLL
+	    !gui.in_use && !gui.starting &&
+#  endif
+	    !has_vtp_working())
 	{
 	    p_tgc = 0;
 	    return N_("E954: 24-bit colors are not supported on this environment");
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -129,7 +129,7 @@ typedef void VOID;
 FILE* fdDump = NULL;
 #endif
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 extern char g_szOrigTitle[];
 #endif
 
@@ -195,6 +195,17 @@ int _stricoll(char *a, char *b)
 #endif
 
 
+#ifndef PROTO
+/*
+ * Save the instance handle of the exe/dll.
+ */
+    void
+SaveInst(HINSTANCE hInst)
+{
+    g_hinst = hInst;
+}
+#endif
+
 #if defined(FEAT_GUI_MSWIN) || defined(PROTO)
 /*
  * GUI version of mch_exit().
@@ -202,7 +213,7 @@ int _stricoll(char *a, char *b)
  * Careful: mch_exit() may be called before mch_init()!
  */
     void
-mch_exit(int r)
+mch_exit_g(int r)
 {
     exiting = TRUE;
 
@@ -262,8 +273,12 @@ mch_early_init(void)
 mch_input_isatty(void)
 {
 #ifdef FEAT_GUI_MSWIN
-    return OK;	    /* GUI always has a tty */
-#else
+# ifdef VIMDLL
+    if (gui.in_use)
+# endif
+	return TRUE;	    /* GUI always has a tty */
+#endif
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
     if (isatty(read_cmd_fd))
 	return TRUE;
     return FALSE;
@@ -280,8 +295,15 @@ mch_settitle(
     char_u *icon)
 {
 # ifdef FEAT_GUI_MSWIN
-    gui_mch_settitle(title, icon);
-# else
+#  ifdef VIMDLL
+    if (gui.in_use)
+#  endif
+    {
+	gui_mch_settitle(title, icon);
+	return;
+    }
+# endif
+# if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
     if (title != NULL)
     {
 	WCHAR	*wp = enc_to_utf16(title, NULL);
@@ -307,8 +329,11 @@ mch_settitle(
     void
 mch_restore_title(int which UNUSED)
 {
-#ifndef FEAT_GUI_MSWIN
-    SetConsoleTitle(g_szOrigTitle);
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
+# ifdef VIMDLL
+    if (!gui.in_use)
+# endif
+	SetConsoleTitle(g_szOrigTitle);
 #endif
 }
 
@@ -554,7 +579,7 @@ vim_stat(const char *name, stat_T *stp)
     return n;
 }
 
-#if defined(FEAT_GUI_MSWIN) || defined(PROTO)
+#if (defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)) || defined(PROTO)
     void
 mch_settmode(int tmode UNUSED)
 {
@@ -596,44 +621,47 @@ mch_suspend(void)
 
 #if defined(USE_MCH_ERRMSG) || defined(PROTO)
 
-#ifdef display_errors
-# undef display_errors
-#endif
-
-#ifdef FEAT_GUI
+# ifdef display_errors
+#  undef display_errors
+# endif
+
 /*
  * Display the saved error message(s).
  */
     void
 display_errors(void)
 {
+# ifdef FEAT_GUI
     char *p;
 
-    if (error_ga.ga_data != NULL)
+#  ifdef VIMDLL
+    if (gui.in_use || gui.starting)
+#  endif
     {
-	/* avoid putting up a message box with blanks only */
-	for (p = (char *)error_ga.ga_data; *p; ++p)
-	    if (!isspace(*p))
-	    {
-		(void)gui_mch_dialog(
+	if (error_ga.ga_data != NULL)
+	{
+	    /* avoid putting up a message box with blanks only */
+	    for (p = (char *)error_ga.ga_data; *p; ++p)
+		if (!isspace(*p))
+		{
+		    (void)gui_mch_dialog(
 				     gui.starting ? VIM_INFO :
 					     VIM_ERROR,
 				     gui.starting ? (char_u *)_("Message") :
 					     (char_u *)_("Error"),
 				     (char_u *)p, (char_u *)_("&Ok"),
 					1, NULL, FALSE);
-		break;
-	    }
-	ga_clear(&error_ga);
+		    break;
+		}
+	    ga_clear(&error_ga);
+	}
+	return;
     }
+# endif
+# if !defined(FEAT_GUI) || defined(VIMDLL)
+    FlushFileBuffers(GetStdHandle(STD_ERROR_HANDLE));
+# endif
 }
-#else
-    void
-display_errors(void)
-{
-    FlushFileBuffers(GetStdHandle(STD_ERROR_HANDLE));
-}
-#endif
 #endif
 
 
@@ -717,7 +745,7 @@ mch_chdir(char *path)
 }
 
 
-#ifdef FEAT_GUI_MSWIN
+#if defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)
 /*
  * return non-zero if a character is available
  */
@@ -955,7 +983,7 @@ Trace(
 
 #endif //_DEBUG
 
-#if !defined(FEAT_GUI) || defined(PROTO)
+#if !defined(FEAT_GUI) || defined(VIMDLL) || defined(PROTO)
 # ifdef FEAT_TITLE
 extern HWND g_hWnd;	/* This is in os_win32.c. */
 # endif
@@ -1121,8 +1149,11 @@ PrintDlgProc(
 		VIM_CLEAR(prt_name);
 	    }
 	    EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE, MF_GRAYED);
-#ifndef FEAT_GUI
-	    BringWindowToTop(s_hwnd);
+#if !defined(FEAT_GUI) || defined(VIMDLL)
+# ifdef VIMDLL
+	    if (!gui.in_use)
+# endif
+		BringWindowToTop(s_hwnd);
 #endif
 	    return TRUE;
 
@@ -1155,7 +1186,7 @@ AbortProc(HDC hdcPrn UNUSED, int iCode U
     return !*bUserAbort;
 }
 
-#ifndef FEAT_GUI
+#if !defined(FEAT_GUI) || defined(VIMDLL)
 
     static UINT_PTR CALLBACK
 PrintHookProc(
@@ -1349,8 +1380,11 @@ mch_print_init(prt_settings_T *psettings
     bUserAbort = &(psettings->user_abort);
     vim_memset(&prt_dlg, 0, sizeof(PRINTDLGW));
     prt_dlg.lStructSize = sizeof(PRINTDLGW);
-#ifndef FEAT_GUI
-    GetConsoleHwnd();	    /* get value of s_hwnd */
+#if !defined(FEAT_GUI) || defined(VIMDLL)
+# ifdef VIMDLL
+    if (!gui.in_use)
+# endif
+	GetConsoleHwnd();	    /* get value of s_hwnd */
 #endif
     prt_dlg.hwndOwner = s_hwnd;
     prt_dlg.Flags = PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC;
@@ -1359,12 +1393,17 @@ mch_print_init(prt_settings_T *psettings
 	prt_dlg.hDevMode = stored_dm;
 	prt_dlg.hDevNames = stored_devn;
 	prt_dlg.lCustData = stored_nCopies; // work around bug in print dialog
-#ifndef FEAT_GUI
-	/*
-	 * Use hook to prevent console window being sent to back
-	 */
-	prt_dlg.lpfnPrintHook = PrintHookProc;
-	prt_dlg.Flags |= PD_ENABLEPRINTHOOK;
+#if !defined(FEAT_GUI) || defined(VIMDLL)
+# ifdef VIMDLL
+	if (!gui.in_use)
+# endif
+	{
+	    /*
+	     * Use hook to prevent console window being sent to back
+	     */
+	    prt_dlg.lpfnPrintHook = PrintHookProc;
+	    prt_dlg.Flags |= PD_ENABLEPRINTHOOK;
+	}
 #endif
 	prt_dlg.Flags |= stored_nFlags;
     }
@@ -1374,8 +1413,12 @@ mch_print_init(prt_settings_T *psettings
      * never show dialog if we are running over telnet
      */
     if (forceit
-#ifndef FEAT_GUI
+#if !defined(FEAT_GUI) || defined(VIMDLL)
+# ifdef VIMDLL
+	    || (!gui.in_use && !term_console)
+# else
 	    || !term_console
+# endif
 #endif
 	    )
     {
@@ -1548,7 +1591,7 @@ mch_print_begin(prt_settings_T *psetting
     char		szBuffer[300];
     WCHAR		*wp;
 
-    hDlgPrint = CreateDialog(GetModuleHandle(NULL), TEXT("PrintDlgBox"),
+    hDlgPrint = CreateDialog(g_hinst, TEXT("PrintDlgBox"),
 					     prt_dlg.hwndOwner, PrintDlgProc);
     SetAbortProc(prt_dlg.hDC, AbortProc);
     wsprintf(szBuffer, _("Printing '%s'"), gettail(psettings->jobname));
@@ -1568,7 +1611,10 @@ mch_print_begin(prt_settings_T *psetting
 
 #ifdef FEAT_GUI
     /* Give focus back to main window (when using MDI). */
-    SetFocus(s_hwnd);
+# ifdef VIMDLL
+    if (gui.in_use)
+# endif
+	SetFocus(s_hwnd);
 #endif
 
     return (ret > 0);
@@ -1927,16 +1973,14 @@ mch_resolve_path(char_u *fname, int repa
 }
 #endif
 
-#if (defined(FEAT_EVAL) && !defined(FEAT_GUI)) || defined(PROTO)
+#if (defined(FEAT_EVAL) && (!defined(FEAT_GUI) || defined(VIMDLL))) || defined(PROTO)
 /*
  * Bring ourselves to the foreground.  Does work if the OS doesn't allow it.
  */
     void
 win32_set_foreground(void)
 {
-# ifndef FEAT_GUI
     GetConsoleHwnd();	    /* get value of s_hwnd */
-# endif
     if (s_hwnd != 0)
 	SetForegroundWindow(s_hwnd);
 }
@@ -2078,8 +2122,11 @@ Messaging_WndProc(HWND hwnd, UINT msg, W
 
 # ifdef FEAT_GUI
 	    /* Wake up the main GUI loop. */
-	    if (s_hwnd != 0)
-		PostMessage(s_hwnd, WM_NULL, 0, 0);
+#  ifdef VIMDLL
+	    if (gui.in_use)
+#  endif
+		if (s_hwnd != 0)
+		    PostMessage(s_hwnd, WM_NULL, 0, 0);
 # endif
 	    return 1;
 
@@ -2145,8 +2192,11 @@ Messaging_WndProc(HWND hwnd, UINT msg, W
     {
 	/* When the message window is activated (brought to the foreground),
 	 * this actually applies to the text window. */
-#ifndef FEAT_GUI
-	GetConsoleHwnd();	    /* get value of s_hwnd */
+#if !defined(FEAT_GUI) || defined(VIMDLL)
+# ifdef VIMDLL
+	if (!gui.in_use)
+# endif
+	    GetConsoleHwnd();	    /* get value of s_hwnd */
 #endif
 	if (s_hwnd != 0)
 	{
@@ -2166,7 +2216,6 @@ Messaging_WndProc(HWND hwnd, UINT msg, W
 serverInitMessaging(void)
 {
     WNDCLASS wndclass;
-    HINSTANCE s_hinst;
 
     /* Clean up on exit */
     atexit(CleanUpMessaging);
@@ -2174,12 +2223,11 @@ serverInitMessaging(void)
     /* Register a window class - we only really care
      * about the window procedure
      */
-    s_hinst = (HINSTANCE)GetModuleHandle(0);
     wndclass.style = 0;
     wndclass.lpfnWndProc = Messaging_WndProc;
     wndclass.cbClsExtra = 0;
     wndclass.cbWndExtra = 0;
-    wndclass.hInstance = s_hinst;
+    wndclass.hInstance = g_hinst;
     wndclass.hIcon = NULL;
     wndclass.hCursor = NULL;
     wndclass.hbrBackground = NULL;
@@ -2194,7 +2242,7 @@ serverInitMessaging(void)
 			 WS_POPUPWINDOW | WS_CAPTION,
 			 CW_USEDEFAULT, CW_USEDEFAULT,
 			 100, 100, NULL, NULL,
-			 s_hinst, NULL);
+			 g_hinst, NULL);
 }
 
 /* Used by serverSendToVim() to find an alternate server name. */
@@ -2744,12 +2792,11 @@ static const LOGFONTW s_lfDefault =
     L"Fixedsys"	/* see _ReadVimIni */
 };
 
-/* Initialise the "current height" to -12 (same as s_lfDefault) just
- * in case the user specifies a font in "guifont" with no size before a font
- * with an explicit size has been set. This defaults the size to this value
- * (-12 equates to roughly 9pt).
- */
-int current_font_height = -12;		/* also used in gui_w48.c */
+// Initialise the "current height" to -12 (same as s_lfDefault) just
+// in case the user specifies a font in "guifont" with no size before a font
+// with an explicit size has been set. This defaults the size to this value
+// (-12 equates to roughly 9pt).
+int current_font_height = -12;		// also used in gui_w32.c
 
 /* Convert a string representing a point size into pixels. The string should
  * be a positive decimal number, with an optional decimal point (eg, "12", or
new file mode 100644
--- /dev/null
+++ b/src/os_w32dll.c
@@ -0,0 +1,27 @@
+/* vi:set ts=8 sts=4 sw=4 noet:
+ *
+ * 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.
+ */
+/*
+ * Windows GUI: main program (DLL) entry point:
+ *
+ * Ron Aaron <ronaharon@yahoo.com> wrote this and the DLL support code.
+ * Adapted by Ken Takata.
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+void SaveInst(HINSTANCE hInst);
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    if (fdwReason == DLL_PROCESS_ATTACH)
+	SaveInst(hinstDLL);
+    return TRUE;
+}
--- a/src/os_w32exe.c
+++ b/src/os_w32exe.c
@@ -22,8 +22,11 @@
 #endif
 
 // cproto doesn't create a prototype for VimMain()
+#ifdef VIMDLL
+__declspec(dllimport)
+#endif
 int _cdecl VimMain(int argc, char **argv);
-#ifdef FEAT_GUI
+#ifndef VIMDLL
 void _cdecl SaveInst(HINSTANCE hInst);
 #endif
 
@@ -40,8 +43,12 @@ wWinMain(
 wmain(int argc UNUSED, wchar_t **argv UNUSED)
 # endif
 {
-# ifdef FEAT_GUI
+# ifndef VIMDLL
+#  ifdef FEAT_GUI
     SaveInst(hInstance);
+#  else
+    SaveInst(GetModuleHandleW(NULL));
+#  endif
 # endif
     VimMain(0, NULL);
 
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -151,7 +151,7 @@ typedef int LPSECURITY_ATTRIBUTES;
 # define wcsicmp(a, b) wcscmpi((a), (b))
 #endif
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 /* Win32 Console handles for input and output */
 static HANDLE g_hConIn  = INVALID_HANDLE_VALUE;
 static HANDLE g_hConOut = INVALID_HANDLE_VALUE;
@@ -179,7 +179,8 @@ static void gotoxy(unsigned x, unsigned 
 static void standout(void);
 static int s_cursor_visible = TRUE;
 static int did_create_conin = FALSE;
-#else
+#endif
+#ifdef FEAT_GUI_MSWIN
 static int s_dont_use_vimrun = TRUE;
 static int need_vimrun_warning = FALSE;
 static char *vimrun_path = "vimrun ";
@@ -193,7 +194,7 @@ static int conpty_working = 0;
 static int conpty_stable = 0;
 static void vtp_flag_init();
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 static int vtp_working = 0;
 static void vtp_init();
 static void vtp_exit();
@@ -227,7 +228,7 @@ static void reset_console_color_rgb(void
 # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
 #endif
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 static int suppress_winsize = 1;	/* don't fiddle with console */
 #endif
 
@@ -235,7 +236,7 @@ static char_u *exe_path = NULL;
 
 static BOOL win8_or_later = FALSE;
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 /* Dynamic loading for portability */
 typedef struct _DYN_CONSOLE_SCREEN_BUFFER_INFOEX
 {
@@ -284,7 +285,7 @@ get_build_number(void)
     return ver;
 }
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 /*
  * Version of ReadConsoleInput() that works with IME.
  * Works around problems on Windows 8.
@@ -496,6 +497,28 @@ vimLoadLib(char *name)
     return dll;
 }
 
+#if defined(VIMDLL) || defined(PROTO)
+/*
+ * Check if the current executable file is for the GUI subsystem.
+ */
+    int
+mch_is_gui_executable(void)
+{
+    PBYTE		pImage = (PBYTE)GetModuleHandle(NULL);
+    PIMAGE_DOS_HEADER	pDOS = (PIMAGE_DOS_HEADER)pImage;
+    PIMAGE_NT_HEADERS	pPE;
+
+    if (pDOS->e_magic != IMAGE_DOS_SIGNATURE)
+	return FALSE;
+    pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew);
+    if (pPE->Signature != IMAGE_NT_SIGNATURE)
+	return FALSE;
+    if (pPE->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
+	return TRUE;
+    return FALSE;
+}
+#endif
+
 #if defined(DYNAMIC_ICONV) || defined(DYNAMIC_GETTEXT) || defined(PROTO)
 /*
  * Get related information about 'funcname' which is imported by 'hInst'.
@@ -816,7 +839,7 @@ PlatformId(void)
     }
 }
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 
 #define SHIFT  (SHIFT_PRESSED)
 #define CTRL   (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)
@@ -1116,7 +1139,7 @@ decode_key_event(
 /*
  * For the GUI the mouse handling is in gui_w32.c.
  */
-# ifdef FEAT_GUI_MSWIN
+# if defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)
     void
 mch_setmouse(int on UNUSED)
 {
@@ -1136,6 +1159,10 @@ mch_setmouse(int on)
 {
     DWORD cmodein;
 
+#  ifdef VIMDLL
+    if (gui.in_use)
+	return;
+#  endif
     if (!g_fMouseAvail)
 	return;
 
@@ -1454,6 +1481,11 @@ mch_update_cursor(void)
     int		idx;
     int		thickness;
 
+# ifdef VIMDLL
+    if (gui.in_use)
+	return;
+# endif
+
     /*
      * How the cursor is drawn depends on the current mode.
      */
@@ -1467,7 +1499,7 @@ mch_update_cursor(void)
 }
 #endif
 
-#ifndef FEAT_GUI_MSWIN	    /* this isn't used for the GUI */
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 /*
  * Handle FOCUS_EVENT.
  */
@@ -1677,13 +1709,16 @@ WaitForChar(long msec, int ignore_input)
     return FALSE;
 }
 
-#ifndef FEAT_GUI_MSWIN
 /*
  * return non-zero if a character is available
  */
     int
 mch_char_avail(void)
 {
+# ifdef VIMDLL
+    if (gui.in_use)
+	return TRUE;
+# endif
     return WaitForChar(0L, FALSE);
 }
 
@@ -1694,10 +1729,13 @@ mch_char_avail(void)
     int
 mch_check_messages(void)
 {
+#  ifdef VIMDLL
+    if (gui.in_use)
+	return TRUE;
+#  endif
     return WaitForChar(0L, TRUE);
 }
 # endif
-#endif
 
 /*
  * Create the console input.  Used when reading stdin doesn't work.
@@ -1779,7 +1817,7 @@ mch_inchar(
     long	time UNUSED,
     int		tb_change_cnt UNUSED)
 {
-#ifndef FEAT_GUI_MSWIN	    /* this isn't used for the GUI */
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 
     int		len;
     int		c;
@@ -1787,6 +1825,11 @@ mch_inchar(
     static char_u   typeahead[TYPEAHEADLEN];	/* previously typed bytes. */
     static int	    typeaheadlen = 0;
 
+# ifdef VIMDLL
+    if (gui.in_use)
+	return 0;
+# endif
+
     /* First use any typeahead that was kept because "buf" was too small. */
     if (typeaheadlen > 0)
 	goto theend;
@@ -2092,8 +2135,8 @@ bad_param_handler(const wchar_t *express
 /*
  * GUI version of mch_init().
  */
-    void
-mch_init(void)
+    static void
+mch_init_g(void)
 {
 #ifndef __MINGW32__
     extern int _fmode;
@@ -2160,7 +2203,9 @@ mch_init(void)
 }
 
 
-#else /* FEAT_GUI_MSWIN */
+#endif /* FEAT_GUI_MSWIN */
+
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 
 #define SRWIDTH(sr) ((sr).Right - (sr).Left + 1)
 #define SRHEIGHT(sr) ((sr).Bottom - (sr).Top + 1)
@@ -2442,11 +2487,6 @@ static ConsoleBuffer g_cbNonTermcap = { 
 static ConsoleBuffer g_cbTermcap = { 0 };
 
 #ifdef FEAT_TITLE
-#ifdef __BORLANDC__
-typedef HWND (__stdcall *GETCONSOLEWINDOWPROC)(VOID);
-#else
-typedef HWND (WINAPI *GETCONSOLEWINDOWPROC)(VOID);
-#endif
 char g_szOrigTitle[256] = { 0 };
 HWND g_hWnd = NULL;	/* also used in os_mswin.c */
 static HICON g_hOrigIconSmall = NULL;
@@ -2563,8 +2603,8 @@ static DWORD g_cmodeout = 0;
 /*
  * non-GUI version of mch_init().
  */
-    void
-mch_init(void)
+    static void
+mch_init_c(void)
 {
 #ifndef FEAT_RESTORE_ORIG_SCREEN
     CONSOLE_SCREEN_BUFFER_INFO csbi;
@@ -2660,8 +2700,8 @@ mch_init(void)
  * Shut down and exit with status `r'
  * Careful: mch_exit() may be called before mch_init()!
  */
-    void
-mch_exit(int r)
+    static void
+mch_exit_c(int r)
 {
     exiting = TRUE;
 
@@ -2711,6 +2751,36 @@ mch_exit(int r)
 }
 #endif /* !FEAT_GUI_MSWIN */
 
+    void
+mch_init(void)
+{
+#ifdef VIMDLL
+    if (gui.starting)
+	mch_init_g();
+    else
+	mch_init_c();
+#elif defined(FEAT_GUI_MSWIN)
+    mch_init_g();
+#else
+    mch_init_c();
+#endif
+}
+
+    void
+mch_exit(int r)
+{
+#ifdef VIMDLL
+    if (gui.starting || gui.in_use)
+	mch_exit_g(r);
+    else
+	mch_exit_c(r);
+#elif defined(FEAT_GUI_MSWIN)
+    mch_exit_g(r);
+#else
+    mch_exit_c(r);
+#endif
+}
+
 /*
  * Do we have an interactive window?
  */
@@ -2721,9 +2791,13 @@ mch_check_win(
 {
     get_exe_name();
 
-#ifdef FEAT_GUI_MSWIN
+#if defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)
     return OK;	    /* GUI always has a tty */
 #else
+# ifdef VIMDLL
+    if (gui.in_use)
+	return OK;
+# endif
     if (isatty(1))
 	return OK;
     return FAIL;
@@ -3446,7 +3520,7 @@ mch_free_acl(vim_acl_T acl)
 #endif
 }
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 
 /*
  * handler for ctrl-break, ctrl-c interrupts, and fatal events.
@@ -3516,6 +3590,10 @@ mch_settmode(int tmode)
     DWORD cmodeout;
     BOOL bEnableHandler;
 
+# ifdef VIMDLL
+    if (gui.in_use)
+	return;
+# endif
     GetConsoleMode(g_hConIn, &cmodein);
     GetConsoleMode(g_hConOut, &cmodeout);
     if (tmode == TMODE_RAW)
@@ -3528,7 +3606,7 @@ mch_settmode(int tmode)
 #endif
 	cmodeout &= ~(
 #ifdef FEAT_TERMGUICOLORS
-	    /* Do not turn off the ENABLE_PROCESSRD_OUTPUT flag when using
+	    /* Do not turn off the ENABLE_PROCESSED_OUTPUT flag when using
 	     * VTP. */
 	    ((vtp_working) ? 0 : ENABLE_PROCESSED_OUTPUT) |
 #else
@@ -3570,6 +3648,10 @@ mch_get_shellsize(void)
 {
     CONSOLE_SCREEN_BUFFER_INFO csbi;
 
+# ifdef VIMDLL
+    if (gui.in_use)
+	return OK;
+# endif
     if (!g_fTermcapMode && g_cbTermcap.IsValid)
     {
 	/*
@@ -3717,6 +3799,10 @@ mch_set_shellsize(void)
 {
     COORD coordScreen;
 
+# ifdef VIMDLL
+    if (gui.in_use)
+	return;
+# endif
     /* Don't change window size while still starting up */
     if (suppress_winsize != 0)
     {
@@ -3744,6 +3830,10 @@ mch_set_shellsize(void)
     void
 mch_new_shellsize(void)
 {
+# ifdef VIMDLL
+    if (gui.in_use)
+	return;
+# endif
     set_scroll_region(0, 0, Columns - 1, Rows - 1);
 }
 
@@ -4369,7 +4459,7 @@ mch_system_piped(char *cmd, int options)
 }
 
     static int
-mch_system(char *cmd, int options)
+mch_system_g(char *cmd, int options)
 {
     /* if we can pipe and the shelltemp option is off */
     if (!p_stmp)
@@ -4377,10 +4467,11 @@ mch_system(char *cmd, int options)
     else
 	return mch_system_classic(cmd, options);
 }
-#else
-
+#endif
+
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
     static int
-mch_system(char *cmd, int options)
+mch_system_c(char *cmd, int options)
 {
     int		ret;
     WCHAR	*wcmd;
@@ -4396,6 +4487,21 @@ mch_system(char *cmd, int options)
 
 #endif
 
+    static int
+mch_system(char *cmd, int options)
+{
+#ifdef VIMDLL
+    if (gui.in_use)
+	return mch_system_g(cmd, options);
+    else
+	return mch_system_c(cmd, options);
+#elif defined(FEAT_GUI_MSWIN)
+    return mch_system_g(cmd, options);
+#else
+    return mch_system_c(cmd, options);
+#endif
+}
+
 #if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
 /*
  * Use a terminal window to run a shell command in.
@@ -4527,7 +4633,11 @@ mch_call_shell(
 #endif
 #if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
     /* TODO: make the terminal window work with input or output redirected. */
-    if (vim_strchr(p_go, GO_TERMINAL) != NULL
+    if (
+# ifdef VIMDLL
+	gui.in_use &&
+# endif
+	vim_strchr(p_go, GO_TERMINAL) != NULL
 	 && (options & (SHELL_FILTER|SHELL_DOOUT|SHELL_WRITE|SHELL_READ)) == 0)
     {
 	/* Use a terminal window to run the command in. */
@@ -4679,7 +4789,10 @@ mch_call_shell(
 	    {
 		x = -1;
 #ifdef FEAT_GUI_MSWIN
-		emsg(_("E371: Command not found"));
+# ifdef VIMDLL
+		if (gui.in_use)
+# endif
+		    emsg(_("E371: Command not found"));
 #endif
 	    }
 
@@ -4699,7 +4812,7 @@ mch_call_shell(
 	{
 	    cmdlen = (
 #ifdef FEAT_GUI_MSWIN
-		(!p_stmp ? 0 : STRLEN(vimrun_path)) +
+		(gui.in_use ? (!p_stmp ? 0 : STRLEN(vimrun_path)) : 0) +
 #endif
 		STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10);
 
@@ -4707,7 +4820,11 @@ mch_call_shell(
 	    if (newcmd != NULL)
 	    {
 #if defined(FEAT_GUI_MSWIN)
-		if (need_vimrun_warning)
+		if (
+# ifdef VIMDLL
+		    gui.in_use &&
+# endif
+		    need_vimrun_warning)
 		{
 		    char *msg = _("VIMRUN.EXE not found in your $PATH.\n"
 			"External commands will not pause after completion.\n"
@@ -4722,7 +4839,11 @@ mch_call_shell(
 		    vim_free(wtitle);
 		    need_vimrun_warning = FALSE;
 		}
-		if (!s_dont_use_vimrun && p_stmp)
+		if (
+# ifdef VIMDLL
+		    gui.in_use &&
+# endif
+		    !s_dont_use_vimrun && p_stmp)
 		    /* Use vimrun to execute the command.  It opens a console
 		     * window, which can be closed without killing Vim. */
 		    vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s",
@@ -4746,7 +4867,8 @@ mch_call_shell(
     /* Print the return value, unless "vimrun" was used. */
     if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent
 #if defined(FEAT_GUI_MSWIN)
-		&& ((options & SHELL_DOOUT) || s_dont_use_vimrun || !p_stmp)
+	    && (gui.in_use ?
+		((options & SHELL_DOOUT) || s_dont_use_vimrun || !p_stmp) : 1)
 #endif
 	    )
     {
@@ -5278,7 +5400,7 @@ mch_clear_job(job_T *job)
 #endif
 
 
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
 
 /*
  * Start termcap mode
@@ -5397,7 +5519,7 @@ termcap_mode_end(void)
 #endif /* FEAT_GUI_MSWIN */
 
 
-#ifdef FEAT_GUI_MSWIN
+#if defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)
     void
 mch_write(
     char_u  *s UNUSED,
@@ -5694,7 +5816,7 @@ gotoxy(
 
 /*
  * Set the current text attribute = (foreground | background)
- * See ../doc/os_win32.txt for the numbers.
+ * See ../runtime/doc/os_win32.txt for the numbers.
  */
     static void
 textattr(WORD wAttr)
@@ -5924,6 +6046,11 @@ mch_write(
     char_u  *s,
     int	    len)
 {
+# ifdef VIMDLL
+    if (gui.in_use)
+	return;
+# endif
+
     s[len] = NUL;
 
     if (!term_console)
@@ -6222,9 +6349,16 @@ mch_delay(
     long    msec,
     int	    ignoreinput UNUSED)
 {
-#ifdef FEAT_GUI_MSWIN
+#if defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)
     Sleep((int)msec);	    /* never wait for input */
 #else /* Console */
+# ifdef VIMDLL
+    if (gui.in_use)
+    {
+	Sleep((int)msec);	    /* never wait for input */
+	return;
+    }
+# endif
     if (ignoreinput)
 # ifdef FEAT_MZSCHEME
 	if (mzthreads_allowed() && p_mzq > 0 && msec > p_mzq)
@@ -6286,13 +6420,16 @@ mch_remove(char_u *name)
     void
 mch_breakcheck(int force)
 {
-#ifndef FEAT_GUI_MSWIN	    /* never used */
-    if (g_fCtrlCPressed || g_fCBrkPressed)
-    {
-	ctrl_break_was_pressed = g_fCBrkPressed;
-	g_fCtrlCPressed = g_fCBrkPressed = FALSE;
-	got_int = TRUE;
-    }
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
+# ifdef VIMDLL
+    if (!gui.in_use)
+# endif
+	if (g_fCtrlCPressed || g_fCBrkPressed)
+	{
+	    ctrl_break_was_pressed = g_fCBrkPressed;
+	    g_fCtrlCPressed = g_fCBrkPressed = FALSE;
+	    got_int = TRUE;
+	}
 #endif
 }
 
@@ -6308,7 +6445,7 @@ mch_total_mem(int special UNUSED)
     MEMORYSTATUSEX  ms;
 
     /* Need to use GlobalMemoryStatusEx() when there is more memory than
-     * what fits in 32 bits. But it's not always available. */
+     * what fits in 32 bits. */
     ms.dwLength = sizeof(MEMORYSTATUSEX);
     GlobalMemoryStatusEx(&ms);
     if (ms.ullAvailVirtual < ms.ullTotalPhys)
@@ -7098,17 +7235,22 @@ mch_setenv(char *var, char *value, int x
 vtp_flag_init(void)
 {
     DWORD   ver = get_build_number();
-#ifndef FEAT_GUI_MSWIN
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL)
     DWORD   mode;
     HANDLE  out;
 
-    out = GetStdHandle(STD_OUTPUT_HANDLE);
-
-    vtp_working = (ver >= VTP_FIRST_SUPPORT_BUILD) ? 1 : 0;
-    GetConsoleMode(out, &mode);
-    mode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
-    if (SetConsoleMode(out, mode) == 0)
-	vtp_working = 0;
+# ifdef VIMDLL
+    if (!gui.in_use)
+# endif
+    {
+	out = GetStdHandle(STD_OUTPUT_HANDLE);
+
+	vtp_working = (ver >= VTP_FIRST_SUPPORT_BUILD) ? 1 : 0;
+	GetConsoleMode(out, &mode);
+	mode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
+	if (SetConsoleMode(out, mode) == 0)
+	    vtp_working = 0;
+    }
 #endif
 
     if (ver >= CONPTY_FIRST_SUPPORT_BUILD)
@@ -7118,7 +7260,7 @@ vtp_flag_init(void)
 
 }
 
-#if !defined(FEAT_GUI_MSWIN) || defined(PROTO)
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL) || defined(PROTO)
 
     static void
 vtp_init(void)
@@ -7343,7 +7485,7 @@ is_conpty_stable(void)
     return conpty_stable;
 }
 
-#if !defined(FEAT_GUI_MSWIN) || defined(PROTO)
+#if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL) || defined(PROTO)
     void
 resize_console_buf(void)
 {
--- a/src/os_win32.h
+++ b/src/os_win32.h
@@ -78,7 +78,7 @@
 
 #define HAVE_PUTENV		/* at least Bcc 5.2 and MSC have it */
 
-#ifdef FEAT_GUI_MSWIN
+#if defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)
 # define NO_CONSOLE		/* don't included console-only code */
 #endif
 
--- a/src/proto/gui.pro
+++ b/src/proto/gui.pro
@@ -1,5 +1,5 @@
 /* gui.c */
-void gui_start(void);
+void gui_start(char_u *arg);
 void gui_prepare(int *argc, char **argv);
 int gui_init_check(void);
 void gui_init(void);
--- a/src/proto/gui_w32.pro
+++ b/src/proto/gui_w32.pro
@@ -61,6 +61,7 @@ void mch_set_mouse_shape(int shape);
 char_u *gui_mch_browse(int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter);
 char_u *gui_mch_browsedir(char_u *title, char_u *initdir);
 void gui_mch_set_parent(char *title);
+char *gui_mch_do_spawn(char_u *arg);
 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);
--- a/src/proto/misc2.pro
+++ b/src/proto/misc2.pro
@@ -108,4 +108,5 @@ void parse_queued_messages(void);
 int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc);
 int build_argv_from_string(char_u *cmd, char ***argv, int *argc);
 int build_argv_from_list(list_T *l, char ***argv, int *argc);
+int write_session_file(char_u *filename);
 /* vim: set ft=c : */
--- a/src/proto/os_mswin.pro
+++ b/src/proto/os_mswin.pro
@@ -1,5 +1,5 @@
 /* os_mswin.c */
-void mch_exit(int r);
+void mch_exit_g(int r);
 void mch_early_init(void);
 int mch_input_isatty(void);
 void mch_settitle(char_u *title, char_u *icon);
--- a/src/proto/os_win32.pro
+++ b/src/proto/os_win32.pro
@@ -1,5 +1,6 @@
 /* os_win32.c */
 HINSTANCE vimLoadLib(char *name);
+int mch_is_gui_executable(void);
 HINSTANCE find_imported_module_by_funcname(HINSTANCE hInst, const char *funcname);
 void *get_dll_import_func(HINSTANCE hInst, const char *funcname);
 int dyn_libintl_init(void);
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -8280,6 +8280,13 @@ restore_cterm_colors(void)
      * background/foreground colors. */
     mch_set_normal_colors();
 #else
+# ifdef VIMDLL
+    if (!gui.in_use)
+    {
+	mch_set_normal_colors();
+	return;
+    }
+# endif
     cterm_normal_fg_color = 0;
     cterm_normal_fg_bold = 0;
     cterm_normal_bg_color = 0;
@@ -9823,7 +9830,7 @@ syn_id2colors(int hl_id, guicolor_T *fgp
 #endif
 
 #if (defined(MSWIN) \
-	&& !defined(FEAT_GUI_MSWIN) \
+	&& (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) \
 	&& defined(FEAT_TERMGUICOLORS)) || defined(PROTO)
     void
 syn_id2cterm_bg(int hl_id, int *fgp, int *bgp)
--- a/src/term.c
+++ b/src/term.c
@@ -4094,7 +4094,12 @@ add_termcode(char_u *name, char_u *strin
 #if defined(MSWIN) && !defined(FEAT_GUI)
     s = vim_strnsave(string, (int)STRLEN(string) + 1);
 #else
-    s = vim_strsave(string);
+# ifdef VIMDLL
+    if (!gui.in_use)
+	s = vim_strnsave(string, (int)STRLEN(string) + 1);
+    else
+# endif
+	s = vim_strsave(string);
 #endif
     if (s == NULL)
 	return;
@@ -4106,11 +4111,16 @@ add_termcode(char_u *name, char_u *strin
 	s[0] = term_7to8bit(string);
     }
 
-#if defined(MSWIN) && !defined(FEAT_GUI)
-    if (s[0] == K_NUL)
+#if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
+# ifdef VIMDLL
+    if (!gui.in_use)
+# endif
     {
-	STRMOVE(s + 1, s);
-	s[1] = 3;
+	if (s[0] == K_NUL)
+	{
+	    STRMOVE(s + 1, s);
+	    s[1] = 3;
+	}
     }
 #endif
 
@@ -6712,7 +6722,7 @@ translate_mapping(
 }
 #endif
 
-#if (defined(MSWIN) && !defined(FEAT_GUI)) || defined(PROTO)
+#if (defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))) || defined(PROTO)
 static char ksme_str[20];
 static char ksmr_str[20];
 static char ksmd_str[20];
@@ -6902,6 +6912,19 @@ hex_digit(int c)
     return 0x1ffffff;
 }
 
+# ifdef VIMDLL
+    static guicolor_T
+gui_adjust_rgb(guicolor_T c)
+{
+    if (gui.in_use)
+	return c;
+    else
+	return ((c & 0xff) << 16) | (c & 0x00ff00) | ((c >> 16) & 0xff);
+}
+# else
+#  define gui_adjust_rgb(c) (c)
+# endif
+
     guicolor_T
 gui_get_color_cmn(char_u *name)
 {
@@ -6973,13 +6996,13 @@ gui_get_color_cmn(char_u *name)
 		    ((hex_digit(name[5]) << 4) + hex_digit(name[6])));
 	if (color > 0xffffff)
 	    return INVALCOLOR;
-	return color;
+	return gui_adjust_rgb(color);
     }
 
     /* Check if the name is one of the colors we know */
     for (i = 0; i < (int)(sizeof(rgb_table) / sizeof(rgb_table[0])); i++)
 	if (STRICMP(name, rgb_table[i].color_name) == 0)
-	    return rgb_table[i].color;
+	    return gui_adjust_rgb(rgb_table[i].color);
 
     /*
      * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
@@ -7060,7 +7083,7 @@ gui_get_color_cmn(char_u *name)
 
     for (i = 0; i < size; i++)
 	if (STRICMP(name, colornames_table[i].color_name) == 0)
-	    return colornames_table[i].color;
+	    return gui_adjust_rgb(colornames_table[i].color);
 
     return INVALCOLOR;
 }
@@ -7072,11 +7095,11 @@ gui_get_rgb_color_cmn(int r, int g, int 
 
     if (color > 0xffffff)
 	return INVALCOLOR;
-    return color;
+    return gui_adjust_rgb(color);
 }
 #endif
 
-#if (defined(MSWIN) && !defined(FEAT_GUI_MSWIN)) || defined(FEAT_TERMINAL) \
+#if (defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))) || defined(FEAT_TERMINAL) \
 	|| defined(PROTO)
 static int cube_value[] = {
     0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -3553,7 +3553,7 @@ init_default_colors(term_T *term)
     }
     else
     {
-#if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
 	int tmp;
 #endif
 
@@ -3561,10 +3561,15 @@ init_default_colors(term_T *term)
 	if (cterm_normal_fg_color > 0)
 	{
 	    cterm_color2vterm(cterm_normal_fg_color - 1, fg);
-# if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
-	    tmp = fg->red;
-	    fg->red = fg->blue;
-	    fg->blue = tmp;
+# if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+#  ifdef VIMDLL
+	    if (!gui.in_use)
+#  endif
+	    {
+		tmp = fg->red;
+		fg->red = fg->blue;
+		fg->blue = tmp;
+	    }
 # endif
 	}
 # ifdef FEAT_TERMRESPONSE
@@ -3575,10 +3580,15 @@ init_default_colors(term_T *term)
 	if (cterm_normal_bg_color > 0)
 	{
 	    cterm_color2vterm(cterm_normal_bg_color - 1, bg);
-# if defined(MSWIN) && !defined(FEAT_GUI_MSWIN)
-	    tmp = bg->red;
-	    bg->red = bg->blue;
-	    bg->blue = tmp;
+# if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL))
+#  ifdef VIMDLL
+	    if (!gui.in_use)
+#  endif
+	    {
+		tmp = fg->red;
+		fg->red = fg->blue;
+		fg->blue = tmp;
+	    }
 # endif
 	}
 # ifdef FEAT_TERMRESPONSE
@@ -3887,7 +3897,7 @@ parse_csi(
 #endif
 	{
 	    // We roughly estimate the position of the terminal window inside
-	    // the Vim window by assuing a 10 x 7 character cell.
+	    // the Vim window by assuming a 10 x 7 character cell.
 	    x += wp->w_wincol * 7;
 	    y += W_WINROW(wp) * 10;
 	}
--- a/src/ui.c
+++ b/src/ui.c
@@ -643,7 +643,7 @@ ui_get_winpos(int *x, int *y, varnumber_
     if (gui.in_use)
 	return gui_mch_get_winpos(x, y);
 # endif
-# if defined(MSWIN) && !defined(FEAT_GUI)
+# if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
     return mch_get_winpos(x, y);
 # else
 #  if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
--- a/src/version.c
+++ b/src/version.c
@@ -768,6 +768,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1230,
+/**/
     1229,
 /**/
     1228,
@@ -3420,10 +3422,18 @@ list_version(void)
     msg(longVersion);
 #ifdef MSWIN
 # ifdef FEAT_GUI_MSWIN
-#  ifdef _WIN64
+#  ifdef VIMDLL
+#   ifdef _WIN64
+    msg_puts(_("\nMS-Windows 64-bit GUI/console version"));
+#   else
+    msg_puts(_("\nMS-Windows 32-bit GUI/console version"));
+#   endif
+#  else
+#   ifdef _WIN64
     msg_puts(_("\nMS-Windows 64-bit GUI version"));
-#  else
+#   else
     msg_puts(_("\nMS-Windows 32-bit GUI version"));
+#   endif
 #  endif
 #  ifdef FEAT_OLE
     msg_puts(_(" with OLE support"));
--- a/src/vim.rc
+++ b/src/vim.rc
@@ -23,7 +23,7 @@
 //
 IDR_VIM		ICON "vim.ico"
 
-#ifdef FEAT_GUI_MSWIN
+#if (defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)) || defined(RCDLL)
 IDR_VIM_ERROR	ICON "vim_error.ico"
 IDR_VIM_ALERT	ICON "vim_alert.ico"
 IDR_VIM_INFO	ICON "vim_info.ico"
@@ -34,7 +34,9 @@ IDR_VIM_QUESTION ICON "vim_quest.ico"
 //
 IDB_TEAROFF	BITMAP  DISCARDABLE  "tearoff.bmp"
 IDR_TOOLBAR1	BITMAP  DISCARDABLE  "tools.bmp"
+#endif // FEAT_GUI_MSWIN
 
+#ifndef RCDLL
 //
 // WinXP theme support
 //
@@ -46,7 +48,7 @@ IDR_TOOLBAR1	BITMAP  DISCARDABLE  "tools
 #endif
 
 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "gvim.exe.mnf"
-#endif // FEAT_GUI_MSWIN
+#endif // RCDLL
 
 //
 // Type Library
@@ -79,7 +81,11 @@ VS_VERSION_INFO		VERSIONINFO
 #endif
 
   FILEOS		VOS__WINDOWS32
+#ifdef RCDLL
+  FILETYPE		VFT_DLL
+#else
   FILETYPE		VFT_APP
+#endif
   FILESUBTYPE		0x0L
 BEGIN
   BLOCK "StringFileInfo"
@@ -93,7 +99,13 @@ BEGIN
 	VALUE "InternalName",		"VIM\0"
 	VALUE "LegalCopyright",		"Copyright \251 1996\0"
 	VALUE "LegalTrademarks",	"Vim\0"
-	VALUE "OriginalFilename",	"VIM.EXE\0"
+#ifdef VIMDLLBASE
+	VALUE "OriginalFilename",	VIMDLLBASE ".dll\0"
+#elif defined(FEAT_GUI_MSWIN)
+	VALUE "OriginalFilename",	"gvim.exe\0"
+#else
+	VALUE "OriginalFilename",	"vim.exe\0"
+#endif
 	VALUE "ProductName",		"Vim\0"
 	VALUE "ProductVersion",		VIM_VERSION_MAJOR_STR ", " VIM_VERSION_MINOR_STR ", " VIM_VERSION_BUILD_STR ", " VIM_VERSION_PATCHLEVEL_STR "\0"
     END
@@ -104,6 +116,7 @@ BEGIN
   END
 END
 
+#if !defined(VIMDLL) || defined(RCDLL)
 /*
  *  Printing Status Dialog (should only be used when FEAT_PRINTER is defined)
  */
@@ -121,3 +134,4 @@ BEGIN
     CTEXT	    "Initializing...",IDC_PROGRESS,24,38,157,9
     GROUPBOX	    "",IDC_BOX1,19,9,170,47
 END
+#endif