summaryrefslogtreecommitdiff
path: root/src/gui_w32.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-04-28 19:46:49 +0200
committerBram Moolenaar <Bram@vim.org>2019-04-28 19:46:49 +0200
commitafde13b62b8fa25dac4635d5caee8d088b937ee0 (patch)
tree6a8b58aa58e180e55b2948e5d0bfdbc3d4692a49 /src/gui_w32.c
parentab4cece6053b0bfd604e15065227b94af873608b (diff)
downloadvim-git-afde13b62b8fa25dac4635d5caee8d088b937ee0.tar.gz
patch 8.1.1230: a lot of code is shared between vim.exe and gvim.exev8.1.1230
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)
Diffstat (limited to 'src/gui_w32.c')
-rw-r--r--src/gui_w32.c180
1 files changed, 154 insertions, 26 deletions
diff --git a/src/gui_w32.c b/src/gui_w32.c
index aac1398b3..1d4e0f74c 100644
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -320,7 +320,6 @@ static int s_findrep_is_find; // TRUE for find dialog, FALSE
// 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 *text, POINT pt)
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);