From afde13b62b8fa25dac4635d5caee8d088b937ee0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 28 Apr 2019 19:46:49 +0200 Subject: 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) --- src/gui_w32.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 154 insertions(+), 26 deletions(-) (limited to 'src/gui_w32.c') 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); -- cgit v1.2.1