summaryrefslogtreecommitdiffstats
path: root/src/gui_w32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui_w32.c')
-rw-r--r--src/gui_w32.c4077
1 files changed, 4077 insertions, 0 deletions
diff --git a/src/gui_w32.c b/src/gui_w32.c
new file mode 100644
index 0000000000..df079538ac
--- /dev/null
+++ b/src/gui_w32.c
@@ -0,0 +1,4077 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ * GUI support by Robert Webb
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+/*
+ * Windows GUI.
+ *
+ * GUI support for Microsoft Windows. Win32 initially; maybe Win16 later
+ *
+ * George V. Reilly <george@reilly.org> wrote the original Win32 GUI.
+ * Robert Webb reworked it to use the existing GUI stuff and added menu,
+ * scrollbars, etc.
+ *
+ * Note: Clipboard stuff, for cutting and pasting text to other windows, is in
+ * os_win32.c. (It can also be done from the terminal version).
+ *
+ * TODO: Some of the function signatures ought to be updated for Win64;
+ * e.g., replace LONG with LONG_PTR, etc.
+ */
+
+/*
+ * These are new in Windows ME/XP, only defined in recent compilers.
+ */
+#ifndef HANDLE_WM_XBUTTONUP
+# define HANDLE_WM_XBUTTONUP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+#endif
+#ifndef HANDLE_WM_XBUTTONDOWN
+# define HANDLE_WM_XBUTTONDOWN(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), FALSE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+#endif
+#ifndef HANDLE_WM_XBUTTONDBLCLK
+# define HANDLE_WM_XBUTTONDBLCLK(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+#endif
+
+/*
+ * Include the common stuff for MS-Windows GUI.
+ */
+#include "gui_w48.c"
+
+#ifdef FEAT_XPM_W32
+# include "xpm_w32.h"
+#endif
+
+#ifdef PROTO
+# define WINAPI
+#endif
+
+#ifdef __MINGW32__
+/*
+ * Add a lot of missing defines.
+ * They are not always missing, we need the #ifndef's.
+ */
+# ifndef _cdecl
+# define _cdecl
+# endif
+# ifndef IsMinimized
+# define IsMinimized(hwnd) IsIconic(hwnd)
+# endif
+# ifndef IsMaximized
+# define IsMaximized(hwnd) IsZoomed(hwnd)
+# endif
+# ifndef SelectFont
+# define SelectFont(hdc, hfont) ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
+# endif
+# ifndef GetStockBrush
+# define GetStockBrush(i) ((HBRUSH)GetStockObject(i))
+# endif
+# ifndef DeleteBrush
+# define DeleteBrush(hbr) DeleteObject((HGDIOBJ)(HBRUSH)(hbr))
+# endif
+
+# ifndef HANDLE_WM_RBUTTONDBLCLK
+# define HANDLE_WM_RBUTTONDBLCLK(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_MBUTTONUP
+# define HANDLE_WM_MBUTTONUP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_MBUTTONDBLCLK
+# define HANDLE_WM_MBUTTONDBLCLK(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_LBUTTONDBLCLK
+# define HANDLE_WM_LBUTTONDBLCLK(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), TRUE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_RBUTTONDOWN
+# define HANDLE_WM_RBUTTONDOWN(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), FALSE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_MOUSEMOVE
+# define HANDLE_WM_MOUSEMOVE(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_RBUTTONUP
+# define HANDLE_WM_RBUTTONUP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_MBUTTONDOWN
+# define HANDLE_WM_MBUTTONDOWN(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), FALSE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_LBUTTONUP
+# define HANDLE_WM_LBUTTONUP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_LBUTTONDOWN
+# define HANDLE_WM_LBUTTONDOWN(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), FALSE, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam), (UINT)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_SYSCHAR
+# define HANDLE_WM_SYSCHAR(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (TCHAR)(wParam), (int)(short)LOWORD(lParam)), 0L)
+# endif
+# ifndef HANDLE_WM_ACTIVATEAPP
+# define HANDLE_WM_ACTIVATEAPP(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (BOOL)(wParam), (DWORD)(lParam)), 0L)
+# endif
+# ifndef HANDLE_WM_WINDOWPOSCHANGING
+# define HANDLE_WM_WINDOWPOSCHANGING(hwnd, wParam, lParam, fn) \
+ (LRESULT)(DWORD)(BOOL)(fn)((hwnd), (LPWINDOWPOS)(lParam))
+# endif
+# ifndef HANDLE_WM_VSCROLL
+# define HANDLE_WM_VSCROLL(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HWND)(lParam), (UINT)(LOWORD(wParam)), (int)(short)HIWORD(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_SETFOCUS
+# define HANDLE_WM_SETFOCUS(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HWND)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_KILLFOCUS
+# define HANDLE_WM_KILLFOCUS(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HWND)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_HSCROLL
+# define HANDLE_WM_HSCROLL(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HWND)(lParam), (UINT)(LOWORD(wParam)), (int)(short)HIWORD(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_DROPFILES
+# define HANDLE_WM_DROPFILES(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (HDROP)(wParam)), 0L)
+# endif
+# ifndef HANDLE_WM_CHAR
+# define HANDLE_WM_CHAR(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (TCHAR)(wParam), (int)(short)LOWORD(lParam)), 0L)
+# endif
+# ifndef HANDLE_WM_SYSDEADCHAR
+# define HANDLE_WM_SYSDEADCHAR(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (TCHAR)(wParam), (int)(short)LOWORD(lParam)), 0L)
+# endif
+# ifndef HANDLE_WM_DEADCHAR
+# define HANDLE_WM_DEADCHAR(hwnd, wParam, lParam, fn) \
+ ((fn)((hwnd), (TCHAR)(wParam), (int)(short)LOWORD(lParam)), 0L)
+# endif
+#endif /* __MINGW32__ */
+
+
+/* Some parameters for tearoff menus. All in pixels. */
+#define TEAROFF_PADDING_X 2
+#define TEAROFF_BUTTON_PAD_X 8
+#define TEAROFF_MIN_WIDTH 200
+#define TEAROFF_SUBMENU_LABEL ">>"
+#define TEAROFF_COLUMN_PADDING 3 // # spaces to pad column with.
+
+
+/* For the Intellimouse: */
+#ifndef WM_MOUSEWHEEL
+#define WM_MOUSEWHEEL 0x20a
+#endif
+
+
+#ifdef FEAT_BEVAL
+# define ID_BEVAL_TOOLTIP 200
+# define BEVAL_TEXT_LEN MAXPATHL
+
+static void make_tooltip __ARGS((BalloonEval *beval, char *text, POINT pt));
+static void delete_tooltip __ARGS((BalloonEval *beval));
+static VOID CALLBACK BevalTimerProc __ARGS((HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime));
+
+static BalloonEval *cur_beval = NULL;
+static UINT BevalTimerId = 0;
+static DWORD LastActivity = 0;
+#endif
+
+/* Local variables: */
+
+#ifdef FEAT_MENU
+static UINT s_menu_id = 100;
+
+/*
+ * Use the system font for dialogs and tear-off menus. Remove this line to
+ * use DLG_FONT_NAME.
+ */
+# define USE_SYSMENU_FONT
+#endif
+
+#define VIM_NAME "vim"
+#define VIM_CLASS "Vim"
+#define VIM_CLASSW L"Vim"
+
+/* Initial size for the dialog template. For gui_mch_dialog() it's fixed,
+ * thus there should be room for every dialog. For tearoffs it's made bigger
+ * when needed. */
+#define DLG_ALLOC_SIZE 16 * 1024
+
+/*
+ * stuff for dialogs, menus, tearoffs etc.
+ */
+static LRESULT APIENTRY dialog_callback(HWND, UINT, WPARAM, LPARAM);
+static LRESULT APIENTRY tearoff_callback(HWND, UINT, WPARAM, LPARAM);
+static PWORD
+add_dialog_element(
+ PWORD p,
+ DWORD lStyle,
+ WORD x,
+ WORD y,
+ WORD w,
+ WORD h,
+ WORD Id,
+ WORD clss,
+ const char *caption);
+static LPWORD lpwAlign(LPWORD);
+static int nCopyAnsiToWideChar(LPWORD, LPSTR);
+static void gui_mch_tearoff(char_u *title, vimmenu_T *menu, int initX, int initY);
+static void get_dialog_font_metrics(void);
+
+static int dialog_default_button = -1;
+
+/* Intellimouse support */
+static int mouse_scroll_lines = 0;
+static UINT msh_msgmousewheel = 0;
+
+static int s_usenewlook; /* emulate W95/NT4 non-bold dialogs */
+#ifdef FEAT_TOOLBAR
+static void initialise_toolbar(void);
+static int get_toolbar_bitmap(vimmenu_T *menu);
+#endif
+
+#ifdef FEAT_MBYTE_IME
+static LRESULT _OnImeComposition(HWND hwnd, WPARAM dbcs, LPARAM param);
+static char_u *GetResultStr(HWND hwnd, int GCS, int *lenp);
+#endif
+#if defined(FEAT_MBYTE_IME) && defined(DYNAMIC_IME)
+# ifdef NOIME
+typedef struct tagCOMPOSITIONFORM {
+ DWORD dwStyle;
+ POINT ptCurrentPos;
+ RECT rcArea;
+} COMPOSITIONFORM, *PCOMPOSITIONFORM, NEAR *NPCOMPOSITIONFORM, FAR *LPCOMPOSITIONFORM;
+typedef HANDLE HIMC;
+# endif
+
+HINSTANCE hLibImm = NULL;
+LONG (WINAPI *pImmGetCompositionStringA)(HIMC, DWORD, LPVOID, DWORD);
+LONG (WINAPI *pImmGetCompositionStringW)(HIMC, DWORD, LPVOID, DWORD);
+HIMC (WINAPI *pImmGetContext)(HWND);
+HIMC (WINAPI *pImmAssociateContext)(HWND, HIMC);
+BOOL (WINAPI *pImmReleaseContext)(HWND, HIMC);
+BOOL (WINAPI *pImmGetOpenStatus)(HIMC);
+BOOL (WINAPI *pImmSetOpenStatus)(HIMC, BOOL);
+BOOL (WINAPI *pImmGetCompositionFont)(HIMC, LPLOGFONTA);
+BOOL (WINAPI *pImmSetCompositionFont)(HIMC, LPLOGFONTA);
+BOOL (WINAPI *pImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
+BOOL (WINAPI *pImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
+static void dyn_imm_load(void);
+#else
+# define pImmGetCompositionStringA ImmGetCompositionStringA
+# define pImmGetCompositionStringW ImmGetCompositionStringW
+# define pImmGetContext ImmGetContext
+# define pImmAssociateContext ImmAssociateContext
+# define pImmReleaseContext ImmReleaseContext
+# define pImmGetOpenStatus ImmGetOpenStatus
+# define pImmSetOpenStatus ImmSetOpenStatus
+# define pImmGetCompositionFont ImmGetCompositionFontA
+# define pImmSetCompositionFont ImmSetCompositionFontA
+# define pImmSetCompositionWindow ImmSetCompositionWindow
+# define pImmGetConversionStatus ImmGetConversionStatus
+#endif
+
+#ifndef ETO_IGNORELANGUAGE
+# define ETO_IGNORELANGUAGE 0x1000
+#endif
+
+/* multi monitor support */
+typedef struct _MONITORINFOstruct
+{
+ DWORD cbSize;
+ RECT rcMonitor;
+ RECT rcWork;
+ DWORD dwFlags;
+} _MONITORINFO;
+
+typedef HANDLE _HMONITOR;
+typedef _HMONITOR (WINAPI *TMonitorFromWindow)(HWND, DWORD);
+typedef BOOL (WINAPI *TGetMonitorInfo)(_HMONITOR, _MONITORINFO *);
+
+static TMonitorFromWindow pMonitorFromWindow = NULL;
+static TGetMonitorInfo pGetMonitorInfo = NULL;
+static HANDLE user32_lib = NULL;
+#ifdef FEAT_NETBEANS_INTG
+int WSInitialized = FALSE; /* WinSock is initialized */
+#endif
+/*
+ * Return TRUE when running under Windows NT 3.x or Win32s, both of which have
+ * less fancy GUI APIs.
+ */
+ static int
+is_winnt_3(void)
+{
+ return ((os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion == 3)
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32s));
+}
+
+/*
+ * Return TRUE when running under Win32s.
+ */
+ int
+gui_is_win32s(void)
+{
+ return (os_version.dwPlatformId == VER_PLATFORM_WIN32s);
+}
+
+#ifdef FEAT_MENU
+/*
+ * Figure out how high the menu bar is at the moment.
+ */
+ static int
+gui_mswin_get_menu_height(
+ int fix_window) /* If TRUE, resize window if menu height changed */
+{
+ static int old_menu_height = -1;
+
+ RECT rc1, rc2;
+ int num;
+ int menu_height;
+
+ if (gui.menu_is_active)
+ num = GetMenuItemCount(s_menuBar);
+ else
+ num = 0;
+
+ if (num == 0)
+ menu_height = 0;
+ else
+ {
+ if (is_winnt_3()) /* for NT 3.xx */
+ {
+ if (gui.starting)
+ menu_height = GetSystemMetrics(SM_CYMENU);
+ else
+ {
+ RECT r1, r2;
+ int frameht = GetSystemMetrics(SM_CYFRAME);
+ int capht = GetSystemMetrics(SM_CYCAPTION);
+
+ /* get window rect of s_hwnd
+ * get client rect of s_hwnd
+ * get cap height
+ * subtract from window rect, the sum of client height,
+ * (if not maximized)frame thickness, and caption height.
+ */
+ GetWindowRect(s_hwnd, &r1);
+ GetClientRect(s_hwnd, &r2);
+ menu_height = r1.bottom - r1.top - (r2.bottom - r2.top
+ + 2 * frameht * (!IsZoomed(s_hwnd)) + capht);
+ }
+ }
+ else /* win95 and variants (NT 4.0, I guess) */
+ {
+ /*
+ * In case 'lines' is set in _vimrc/_gvimrc window width doesn't
+ * seem to have been set yet, so menu wraps in default window
+ * width which is very narrow. Instead just return height of a
+ * single menu item. Will still be wrong when the menu really
+ * should wrap over more than one line.
+ */
+ GetMenuItemRect(s_hwnd, s_menuBar, 0, &rc1);
+ if (gui.starting)
+ menu_height = rc1.bottom - rc1.top + 1;
+ else
+ {
+ GetMenuItemRect(s_hwnd, s_menuBar, num - 1, &rc2);
+ menu_height = rc2.bottom - rc1.top + 1;
+ }
+ }
+ }
+
+ if (fix_window && menu_height != old_menu_height)
+ {
+ old_menu_height = menu_height;
+ gui_set_shellsize(FALSE, FALSE);
+ }
+
+ return menu_height;
+}
+#endif /*FEAT_MENU*/
+
+
+/*
+ * Setup for the Intellimouse
+ */
+ static void
+init_mouse_wheel(void)
+{
+
+#ifndef SPI_GETWHEELSCROLLLINES
+# define SPI_GETWHEELSCROLLLINES 104
+#endif
+
+#define VMOUSEZ_CLASSNAME "MouseZ" /* hidden wheel window class */
+#define VMOUSEZ_TITLE "Magellan MSWHEEL" /* hidden wheel window title */
+#define VMSH_MOUSEWHEEL "MSWHEEL_ROLLMSG"
+#define VMSH_SCROLL_LINES "MSH_SCROLL_LINES_MSG"
+
+ HWND hdl_mswheel;
+ UINT msh_msgscrolllines;
+
+ msh_msgmousewheel = 0;
+ mouse_scroll_lines = 3; /* reasonable default */
+
+ if ((os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion >= 4)
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
+ && ((os_version.dwMajorVersion == 4
+ && os_version.dwMinorVersion >= 10)
+ || os_version.dwMajorVersion >= 5)))
+ {
+ /* if NT 4.0+ (or Win98) get scroll lines directly from system */
+ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
+ &mouse_scroll_lines, 0);
+ }
+ else if (os_version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion < 4))
+ { /*
+ * If Win95 or NT 3.51,
+ * try to find the hidden point32 window.
+ */
+ hdl_mswheel = FindWindow(VMOUSEZ_CLASSNAME, VMOUSEZ_TITLE);
+ if (hdl_mswheel)
+ {
+ msh_msgscrolllines = RegisterWindowMessage(VMSH_SCROLL_LINES);
+ if (msh_msgscrolllines)
+ {
+ mouse_scroll_lines = (int)SendMessage(hdl_mswheel,
+ msh_msgscrolllines, 0, 0);
+ msh_msgmousewheel = RegisterWindowMessage(VMSH_MOUSEWHEEL);
+ }
+ }
+ }
+}
+
+
+/* Intellimouse wheel handler */
+ static void
+_OnMouseWheel(
+ HWND hwnd,
+ short zDelta)
+{
+/* Treat a mouse wheel event as if it were a scroll request */
+ int i;
+ int size;
+ HWND hwndCtl;
+
+ if (curwin->w_scrollbars[SBAR_RIGHT].id != 0)
+ {
+ hwndCtl = curwin->w_scrollbars[SBAR_RIGHT].id;
+ size = curwin->w_scrollbars[SBAR_RIGHT].size;
+ }
+ else if (curwin->w_scrollbars[SBAR_LEFT].id != 0)
+ {
+ hwndCtl = curwin->w_scrollbars[SBAR_LEFT].id;
+ size = curwin->w_scrollbars[SBAR_LEFT].size;
+ }
+ else
+ return;
+
+ size = curwin->w_height;
+ if (mouse_scroll_lines == 0)
+ init_mouse_wheel();
+
+ if (mouse_scroll_lines > 0
+ && mouse_scroll_lines < (size > 2 ? size - 2 : 1))
+ {
+ for (i = mouse_scroll_lines; i > 0; --i)
+ _OnScroll(hwnd, hwndCtl, zDelta >= 0 ? SB_LINEUP : SB_LINEDOWN, 0);
+ }
+ else
+ _OnScroll(hwnd, hwndCtl, zDelta >= 0 ? SB_PAGEUP : SB_PAGEDOWN, 0);
+}
+
+#if 0 /* disabled, a gap appears below and beside the window, and the window
+ can be moved (in a strange way) */
+/*
+ * Even though we have _DuringSizing() which makes the rubber band a valid
+ * size, we need this for when the user maximises the window.
+ * TODO: Doesn't seem to adjust the width though for some reason.
+ */
+ static BOOL
+_OnWindowPosChanging(
+ HWND hwnd,
+ LPWINDOWPOS lpwpos)
+{
+ RECT workarea_rect;
+
+ if (!(lpwpos->flags & SWP_NOSIZE))
+ {
+ if (IsMaximized(hwnd)
+ && (os_version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
+ || (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && os_version.dwMajorVersion >= 4)))
+ {
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &workarea_rect, 0);
+ lpwpos->x = workarea_rect.left;
+ lpwpos->y = workarea_rect.top;
+ lpwpos->cx = workarea_rect.right - workarea_rect.left;
+ lpwpos->cy = workarea_rect.bottom - workarea_rect.top;
+ }
+ gui_mswin_get_valid_dimensions(lpwpos->cx, lpwpos->cy,
+ &lpwpos->cx, &lpwpos->cy);
+ }
+ return 0;
+}
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ static void
+_OnWindowPosChanged(
+ HWND hwnd,
+ const LPWINDOWPOS lpwpos)
+{
+ static int x = 0, y = 0, cx = 0, cy = 0;
+
+ if (WSInitialized && (lpwpos->x != x || lpwpos->y != y
+ || lpwpos->cx != cx || lpwpos->cy != cy))
+ {
+ x = lpwpos->x;
+ y = lpwpos->y;
+ cx = lpwpos->cx;
+ cy = lpwpos->cy;
+ netbeans_frame_moved(x, y);
+ }
+ /* Allow to send WM_SIZE and WM_MOVE */
+ FORWARD_WM_WINDOWPOSCHANGED(hwnd, lpwpos, MyWindowProc);
+}
+#endif
+
+ static int
+_DuringSizing(
+ HWND hwnd,
+ UINT fwSide,
+ LPRECT lprc)
+{
+ int w, h;
+ int valid_w, valid_h;
+ int w_offset, h_offset;
+
+ w = lprc->right - lprc->left;
+ h = lprc->bottom - lprc->top;
+ gui_mswin_get_valid_dimensions(w, h, &valid_w, &valid_h);
+ w_offset = w - valid_w;
+ h_offset = h - valid_h;
+
+ if (fwSide == WMSZ_LEFT || fwSide == WMSZ_TOPLEFT
+ || fwSide == WMSZ_BOTTOMLEFT)
+ lprc->left += w_offset;
+ else if (fwSide == WMSZ_RIGHT || fwSide == WMSZ_TOPRIGHT
+ || fwSide == WMSZ_BOTTOMRIGHT)
+ lprc->right -= w_offset;
+
+ if (fwSide == WMSZ_TOP || fwSide == WMSZ_TOPLEFT
+ || fwSide == WMSZ_TOPRIGHT)
+ lprc->top += h_offset;
+ else if (fwSide == WMSZ_BOTTOM || fwSide == WMSZ_BOTTOMLEFT
+ || fwSide == WMSZ_BOTTOMRIGHT)
+ lprc->bottom -= h_offset;
+ return TRUE;
+}
+
+
+
+ static LRESULT CALLBACK
+_WndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ /*
+ TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
+ hwnd, uMsg, wParam, lParam);
+ */
+
+ HandleMouseHide(uMsg, lParam);
+
+ s_uMsg = uMsg;
+ s_wParam = wParam;
+ s_lParam = lParam;
+
+ switch (uMsg)
+ {
+ HANDLE_MSG(hwnd, WM_DEADCHAR, _OnDeadChar);
+ HANDLE_MSG(hwnd, WM_SYSDEADCHAR, _OnDeadChar);
+ /* HANDLE_MSG(hwnd, WM_ACTIVATE, _OnActivate); */
+ HANDLE_MSG(hwnd, WM_CLOSE, _OnClose);
+ /* HANDLE_MSG(hwnd, WM_COMMAND, _OnCommand); */
+ HANDLE_MSG(hwnd, WM_DESTROY, _OnDestroy);
+ HANDLE_MSG(hwnd, WM_DROPFILES, _OnDropFiles);
+ HANDLE_MSG(hwnd, WM_HSCROLL, _OnScroll);
+ HANDLE_MSG(hwnd, WM_KILLFOCUS, _OnKillFocus);
+#ifdef FEAT_MENU
+ HANDLE_MSG(hwnd, WM_COMMAND, _OnMenu);
+#endif
+ /* HANDLE_MSG(hwnd, WM_MOVE, _OnMove); */
+ /* HANDLE_MSG(hwnd, WM_NCACTIVATE, _OnNCActivate); */
+ HANDLE_MSG(hwnd, WM_SETFOCUS, _OnSetFocus);
+ HANDLE_MSG(hwnd, WM_SIZE, _OnSize);
+ /* HANDLE_MSG(hwnd, WM_SYSCOMMAND, _OnSysCommand); */
+ /* HANDLE_MSG(hwnd, WM_SYSKEYDOWN, _OnAltKey); */
+ HANDLE_MSG(hwnd, WM_VSCROLL, _OnScroll);
+ // HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGING, _OnWindowPosChanging);
+ HANDLE_MSG(hwnd, WM_ACTIVATEAPP, _OnActivateApp);
+#ifdef FEAT_NETBEANS_INTG
+ HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGED, _OnWindowPosChanged);
+#endif
+
+ case WM_QUERYENDSESSION: /* System wants to go down. */
+ gui_shell_closed(); /* Will exit when no changed buffers. */
+ return FALSE; /* Do NOT allow system to go down. */
+
+ case WM_ENDSESSION:
+ if (wParam) /* system only really goes down when wParam is TRUE */
+ _OnEndSession();
+ break;
+
+ case WM_CHAR:
+ /* Don't use HANDLE_MSG() for WM_CHAR, it truncates wParam to a single
+ * byte while we want the UTF-16 character value. */
+ _OnChar(hwnd, wParam, (int)(short)LOWORD(lParam));
+ return 0L;
+
+ case WM_SYSCHAR:
+ /*
+ * if 'winaltkeys' is "no", or it's "menu" and it's not a menu
+ * shortcut key, handle like a typed ALT key, otherwise call Windows
+ * ALT key handling.
+ */
+#ifdef FEAT_MENU
+ if ( !gui.menu_is_active
+ || p_wak[0] == 'n'
+ || (p_wak[0] == 'm' && !gui_is_menu_shortcut((int)wParam))
+ )
+#endif
+ {
+ _OnSysChar(hwnd, wParam, (int)(short)LOWORD(lParam));
+ return 0L;
+ }
+#ifdef FEAT_MENU
+ else
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+#endif
+
+ case WM_SYSKEYUP:
+#ifdef FEAT_MENU
+ /* This used to be done only when menu is active: ALT key is used for
+ * that. But that caused problems when menu is disabled and using
+ * Alt-Tab-Esc: get into a strange state where no mouse-moved events
+ * are received, mouse pointer remains hidden. */
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+#else
+ return 0;
+#endif
+
+ case WM_SIZING: /* HANDLE_MSG doesn't seem to handle this one */
+ return _DuringSizing(hwnd, (UINT)wParam, (LPRECT)lParam);
+
+ case WM_MOUSEWHEEL:
+ _OnMouseWheel(hwnd, HIWORD(wParam));
+ break;
+
+#ifdef FEAT_TOOLBAR
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->code)
+ {
+ case TTN_NEEDTEXT:
+ {
+ LPTOOLTIPTEXT lpttt;
+ UINT idButton;
+ int idx;
+ vimmenu_T *pMenu;
+
+ lpttt = (LPTOOLTIPTEXT)lParam;
+ idButton = (UINT) lpttt->hdr.idFrom;
+ pMenu = gui_mswin_find_menu(root_menu, idButton);
+ if (pMenu)
+ {
+ idx = MENU_INDEX_TIP;
+ if (pMenu->strings[idx])
+ {
+ lpttt->hinst = NULL; /* string, not resource */
+ lpttt->lpszText = pMenu->strings[idx];
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+#if defined(MENUHINTS) && defined(FEAT_MENU)
+ case WM_MENUSELECT:
+ if (((UINT) HIWORD(wParam)
+ & (0xffff ^ (MF_MOUSESELECT + MF_BITMAP + MF_POPUP)))
+ == MF_HILITE
+ && (State & CMDLINE) == 0)
+ {
+ UINT idButton;
+ vimmenu_T *pMenu;
+ static int did_menu_tip = FALSE;
+
+ if (did_menu_tip)
+ {
+ msg_clr_cmdline();
+ setcursor();
+ out_flush();
+ did_menu_tip = FALSE;
+ }
+
+ idButton = (UINT)LOWORD(wParam);
+ pMenu = gui_mswin_find_menu(root_menu, idButton);
+ if (pMenu != NULL && pMenu->strings[MENU_INDEX_TIP] != 0
+ && GetMenuState(s_menuBar, pMenu->id, MF_BYCOMMAND) != -1)
+ {
+ msg(pMenu->strings[MENU_INDEX_TIP]);
+ setcursor();
+ out_flush();
+ did_menu_tip = TRUE;
+ }
+ }
+ break;
+#endif
+ case WM_NCHITTEST:
+ {
+ LRESULT result;
+ int x, y;
+ int xPos = GET_X_LPARAM(lParam);
+
+ result = MyWindowProc(hwnd, uMsg, wParam, lParam);
+ if (result == HTCLIENT)
+ {
+ gui_mch_get_winpos(&x, &y);
+ xPos -= x;
+
+ if (xPos < 48) /* <VN> TODO should use system metric? */
+ return HTBOTTOMLEFT;
+ else
+ return HTBOTTOMRIGHT;
+ }
+ else
+ return result;
+ }
+ /* break; notreached */
+
+#ifdef FEAT_MBYTE_IME
+ case WM_IME_NOTIFY:
+ if (!_OnImeNotify(hwnd, (DWORD)wParam, (DWORD)lParam))
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ break;
+ case WM_IME_COMPOSITION:
+ if (!_OnImeComposition(hwnd, wParam, lParam))
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ break;
+#endif
+
+ default:
+ if (uMsg == msh_msgmousewheel && msh_msgmousewheel != 0)
+ { /* handle MSH_MOUSEWHEEL messages for Intellimouse */
+ _OnMouseWheel(hwnd, HIWORD(wParam));
+ break;
+ }
+#ifdef MSWIN_FIND_REPLACE
+ else
+ if (uMsg == s_findrep_msg && s_findrep_msg != 0)
+ {
+ _OnFindRepl();
+ }
+#endif
+ return MyWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ return 1;
+}
+
+/*
+ * End of call-back routines
+ */
+
+/* parent window, if specified with -P */
+HWND vim_parent_hwnd = NULL;
+
+ static BOOL CALLBACK
+FindWindowTitle(HWND hwnd, LPARAM lParam)
+{
+ char buf[2048];
+ char *title = (char *)lParam;
+
+ if (GetWindowText(hwnd, buf, sizeof(buf)))
+ {
+ if (strstr(buf, title) != NULL)
+ {
+ /* Found it. Store the window ref. and quit searching. */
+ vim_parent_hwnd = FindWindowEx(hwnd, NULL, "MDIClient", NULL);
+ return FALSE;
+ }
+ }
+ return TRUE; /* continue searching */
+}
+
+/*
+ * Invoked for '-P "title"' argument: search for parent application to open
+ * our window in.
+ */
+ void
+gui_mch_set_parent(char *title)
+{
+ EnumWindows(FindWindowTitle, (LPARAM)title);
+ if (vim_parent_hwnd == NULL)
+ {
+ EMSG2(_("E671: Cannot find window title \"%s\""), title);
+ mch_exit(2);
+ }
+}
+
+ static void
+ole_error(char *arg)
+{
+ EMSG2(_("E243: Argument not supported: \"-%s\"; Use the OLE version."),
+ arg);
+}
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(int *argc, char **argv)
+{
+ int silent = FALSE;
+ int idx;
+
+ /* Check for special OLE command line parameters */
+ if ((*argc == 2 || *argc == 3) && (argv[1][0] == '-' || argv[1][0] == '/'))
+ {
+ /* Check for a "-silent" argument first. */
+ if (*argc == 3 && STRICMP(argv[1] + 1, "silent") == 0
+ && (argv[2][0] == '-' || argv[2][0] == '/'))
+ {
+ silent = TRUE;
+ idx = 2;
+ }
+ else
+ idx = 1;
+
+ /* Register Vim as an OLE Automation server */
+ if (STRICMP(argv[idx] + 1, "register") == 0)
+ {
+#ifdef FEAT_OLE
+ RegisterMe(silent);
+ mch_exit(0);
+#else
+ if (!silent)
+ ole_error("register");
+ mch_exit(2);
+#endif
+ }
+
+ /* Unregister Vim as an OLE Automation server */
+ if (STRICMP(argv[idx] + 1, "unregister") == 0)
+ {
+#ifdef FEAT_OLE
+ UnregisterMe(!silent);
+ mch_exit(0);
+#else
+ if (!silent)
+ ole_error("unregister");
+ mch_exit(2);
+#endif
+ }
+
+ /* Ignore an -embedding argument. It is only relevant if the
+ * application wants to treat the case when it is started manually
+ * differently from the case where it is started via automation (and
+ * we don't).
+ */
+ if (STRICMP(argv[idx] + 1, "embedding") == 0)
+ {
+#ifdef FEAT_OLE
+ *argc = 1;
+#else
+ ole_error("embedding");
+ mch_exit(2);
+#endif
+ }
+ }
+
+#ifdef FEAT_OLE
+ {
+ int bDoRestart = FALSE;
+
+ InitOLE(&bDoRestart);
+ /* automatically exit after registering */
+ if (bDoRestart)
+ mch_exit(0);
+ }
+#endif
+
+#ifdef FEAT_NETBEANS_INTG
+ {
+ /* stolen from gui_x11.x */
+ int arg;
+
+ for (arg = 1; arg < *argc; arg++)
+ if (strncmp("-nb", argv[arg], 3) == 0)
+ {
+ usingNetbeans++;
+ netbeansArg = argv[arg];
+ mch_memmove(&argv[arg], &argv[arg + 1],
+ (--*argc - arg) * sizeof(char *));
+ argv[*argc] = NULL;
+ break; /* enough? */
+ }
+
+ if (usingNetbeans)
+ {
+ WSADATA wsaData;
+ int wsaerr;
+
+ /* Init WinSock */
+ wsaerr = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ if (wsaerr == 0)
+ WSInitialized = TRUE;
+ }
+ }
+#endif
+
+ /* get the OS version info */
+ os_version.dwOSVersionInfoSize = sizeof(os_version);
+ GetVersionEx(&os_version); /* this call works on Win32s, Win95 and WinNT */
+
+ /* try and load the user32.dll library and get the entry points for
+ * multi-monitor-support. */
+ if ((user32_lib = LoadLibrary("User32.dll")) != NULL)
+ {
+ pMonitorFromWindow = (TMonitorFromWindow)GetProcAddress(user32_lib,
+ "MonitorFromWindow");
+
+ /* there are ...A and ...W version of GetMonitorInfo - looking at
+ * winuser.h, they have exactly the same declaration. */
+ pGetMonitorInfo = (TGetMonitorInfo)GetProcAddress(user32_lib,
+ "GetMonitorInfoA");
+ }
+}
+
+/*
+ * Initialise the GUI. Create all the windows, set up all the call-backs
+ * etc.
+ */
+ int
+gui_mch_init(void)
+{
+ const char szVimWndClass[] = VIM_CLASS;
+ const char szTextAreaClass[] = "VimTextArea";
+ WNDCLASS wndclass;
+#ifdef FEAT_MBYTE
+ const WCHAR szVimWndClassW[] = VIM_CLASSW;
+ WNDCLASSW wndclassw;
+#endif
+#ifdef GLOBAL_IME
+ ATOM atom;
+#endif
+
+ /* Display any pending error messages */
+ display_errors();
+
+ /* Return here if the window was already opened (happens when
+ * gui_mch_dialog() is called early). */
+ if (s_hwnd != NULL)
+ return OK;
+
+ /*
+ * Load the tearoff bitmap
+ */
+#ifdef FEAT_TEAROFF
+ s_htearbitmap = LoadBitmap(s_hinst, "IDB_TEAROFF");
+#endif
+
+ gui.scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
+ gui.scrollbar_height = GetSystemMetrics(SM_CYHSCROLL);
+#ifdef FEAT_MENU
+ gui.menu_height = 0; /* Windows takes care of this */
+#endif
+ gui.border_width = 0;
+
+ s_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+
+#ifdef FEAT_MBYTE
+ /* 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)
+ {
+ wndclassw.style = 0;
+ wndclassw.lpfnWndProc = _WndProc;
+ wndclassw.cbClsExtra = 0;
+ wndclassw.cbWndExtra = 0;
+ wndclassw.hInstance = s_hinst;
+ wndclassw.hIcon = LoadIcon(wndclassw.hInstance, "IDR_VIM");
+ wndclassw.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclassw.hbrBackground = s_brush;
+ wndclassw.lpszMenuName = NULL;
+ wndclassw.lpszClassName = szVimWndClassW;
+
+ if ((
+#ifdef GLOBAL_IME
+ atom =
+#endif
+ RegisterClassW(&wndclassw)) == 0)
+ {
+ if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ return FAIL;
+
+ /* Must be Windows 98, fall back to non-wide function. */
+ }
+ else
+ wide_WindowProc = TRUE;
+ }
+
+ if (!wide_WindowProc)
+#endif
+
+ if (GetClassInfo(s_hinst, szVimWndClass, &wndclass) == 0)
+ {
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = _WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = s_hinst;
+ wndclass.hIcon = LoadIcon(wndclass.hInstance, "IDR_VIM");
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = s_brush;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = szVimWndClass;
+
+ if ((
+#ifdef GLOBAL_IME
+ atom =
+#endif
+ RegisterClass(&wndclass)) == 0)
+ return FAIL;
+ }
+
+ if (vim_parent_hwnd != NULL)
+ {
+#ifdef HAVE_TRY_EXCEPT
+ __try
+ {
+#endif
+ /* Open inside the specified parent window.
+ * TODO: last argument should point to a CLIENTCREATESTRUCT
+ * structure. */
+ s_hwnd = CreateWindowEx(
+ WS_EX_MDICHILD,
+ szVimWndClass, "Vim MSWindows GUI",
+ WS_OVERLAPPEDWINDOW | WS_CHILD | WS_CLIPSIBLINGS | 0xC000,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+ gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
+ 100, /* Any value will do */
+ 100, /* Any value will do */
+ vim_parent_hwnd, NULL,
+ s_hinst, NULL);
+#ifdef HAVE_TRY_EXCEPT
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* NOP */
+ }
+#endif
+ if (s_hwnd == NULL)
+ {
+ EMSG(_("E672: Unable to open window inside MDI application"));
+ mch_exit(2);
+ }
+ }
+ else
+ /* Open toplevel window. */
+ s_hwnd = CreateWindow(
+ szVimWndClass, "Vim MSWindows GUI",
+ WS_OVERLAPPEDWINDOW,
+ gui_win_x == -1 ? CW_USEDEFAULT : gui_win_x,
+ gui_win_y == -1 ? CW_USEDEFAULT : gui_win_y,
+ 100, /* Any value will do */
+ 100, /* Any value will do */
+ NULL, NULL,
+ s_hinst, NULL);
+
+ if (s_hwnd == NULL)
+ return FAIL;
+
+#ifdef GLOBAL_IME
+ global_ime_init(atom, s_hwnd);
+#endif
+#if defined(FEAT_MBYTE_IME) && defined(DYNAMIC_IME)
+ dyn_imm_load();
+#endif
+
+ /* Create the text area window */
+ if (GetClassInfo(s_hinst, szTextAreaClass, &wndclass) == 0)
+ {
+ wndclass.style = CS_OWNDC;
+ wndclass.lpfnWndProc = _TextAreaWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = s_hinst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = szTextAreaClass;
+
+ if (RegisterClass(&wndclass) == 0)
+ return FAIL;
+ }
+ s_textArea = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ szTextAreaClass, "Vim text area",
+ WS_CHILD | WS_VISIBLE, 0, 0,
+ 100, /* Any value will do for now */
+ 100, /* Any value will do for now */
+ s_hwnd, NULL,
+ s_hinst, NULL);
+
+ if (s_textArea == NULL)
+ return FAIL;
+
+#ifdef FEAT_MENU
+ s_menuBar = CreateMenu();
+#endif
+ s_hdc = GetDC(s_textArea);
+
+#ifdef MSWIN16_FASTTEXT
+ SetBkMode(s_hdc, OPAQUE);
+#endif
+
+#ifdef FEAT_WINDOWS
+ DragAcceptFiles(s_hwnd, TRUE);
+#endif
+
+ /* Do we need to bother with this? */
+ /* m_fMouseAvail = GetSystemMetrics(SM_MOUSEPRESENT); */
+
+ /* Get background/foreground colors from the system */
+ gui_mch_def_colors();
+
+ /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
+ * file) */
+ set_normal_colors();
+
+ /*
+ * Check that none of the colors are the same as the background color.
+ * Then store the current values as the defaults.
+ */
+ gui_check_colors();
+ gui.def_norm_pixel = gui.norm_pixel;
+ gui.def_back_pixel = gui.back_pixel;
+
+ /* Get the colors for the highlight groups (gui_check_colors() might have
+ * changed them) */