summaryrefslogtreecommitdiff
path: root/src/gui_w48.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui_w48.c')
-rw-r--r--src/gui_w48.c4155
1 files changed, 0 insertions, 4155 deletions
diff --git a/src/gui_w48.c b/src/gui_w48.c
deleted file mode 100644
index eff3f3f80..000000000
--- a/src/gui_w48.c
+++ /dev/null
@@ -1,4155 +0,0 @@
-/* vi:set ts=8 sts=4 sw=4:
- *
- * VIM - Vi IMproved by Bram Moolenaar
- * GUI support by Robert Webb
- *
- * Do ":help uganda" in Vim to read copying and usage conditions.
- * Do ":help credits" in Vim to see a list of people who contributed.
- * See README.txt for an overview of the Vim source code.
- */
-/*
- * gui_w48.c: This file is included in gui_w16.c and gui_w32.c.
- *
- * GUI support for Microsoft Windows (Win16 + Win32 = Win48 :-)
- *
- * The combined efforts of:
- * George V. Reilly <george@reilly.org>
- * Robert Webb
- * Vince Negri
- * ...and contributions from many others
- *
- */
-
-#include "vim.h"
-#include "version.h" /* used by dialog box routine for default title */
-#ifdef DEBUG
-# include <tchar.h>
-#endif
-
-/* cproto fails on missing include files */
-#ifndef PROTO
-
-#ifndef __MINGW32__
-# include <shellapi.h>
-#endif
-#if defined(FEAT_TOOLBAR) || defined(FEAT_BEVAL) || defined(FEAT_GUI_TABLINE)
-# include <commctrl.h>
-#endif
-#ifdef WIN16
-# include <commdlg.h>
-# include <shellapi.h>
-# ifdef WIN16_3DLOOK
-# include <ctl3d.h>
-# endif
-#endif
-#include <windowsx.h>
-
-#ifdef GLOBAL_IME
-# include "glbl_ime.h"
-#endif
-
-#endif /* PROTO */
-
-#ifdef FEAT_MENU
-# define MENUHINTS /* show menu hints in command line */
-#endif
-
-/* Some parameters for dialog boxes. All in pixels. */
-#define DLG_PADDING_X 10
-#define DLG_PADDING_Y 10
-#define DLG_OLD_STYLE_PADDING_X 5
-#define DLG_OLD_STYLE_PADDING_Y 5
-#define DLG_VERT_PADDING_X 4 /* For vertical buttons */
-#define DLG_VERT_PADDING_Y 4
-#define DLG_ICON_WIDTH 34
-#define DLG_ICON_HEIGHT 34
-#define DLG_MIN_WIDTH 150
-#define DLG_FONT_NAME "MS Sans Serif"
-#define DLG_FONT_POINT_SIZE 8
-#define DLG_MIN_MAX_WIDTH 400
-#define DLG_MIN_MAX_HEIGHT 400
-
-#define DLG_NONBUTTON_CONTROL 5000 /* First ID of non-button controls */
-
-#ifndef WM_XBUTTONDOWN /* For Win2K / winME ONLY */
-# define WM_XBUTTONDOWN 0x020B
-# define WM_XBUTTONUP 0x020C
-# define WM_XBUTTONDBLCLK 0x020D
-# define MK_XBUTTON1 0x0020
-# define MK_XBUTTON2 0x0040
-#endif
-
-#ifdef PROTO
-/*
- * Define a few things for generating prototypes. This is just to avoid
- * syntax errors, the defines do not need to be correct.
- */
-# define APIENTRY
-# define CALLBACK
-# define CONST
-# define FAR
-# define NEAR
-# define _cdecl
-typedef int BOOL;
-typedef int BYTE;
-typedef int DWORD;
-typedef int WCHAR;
-typedef int ENUMLOGFONT;
-typedef int FINDREPLACE;
-typedef int HANDLE;
-typedef int HBITMAP;
-typedef int HBRUSH;
-typedef int HDROP;
-typedef int INT;
-typedef int LOGFONT[];
-typedef int LPARAM;
-typedef int LPCREATESTRUCT;
-typedef int LPCSTR;
-typedef int LPCTSTR;
-typedef int LPRECT;
-typedef int LPSTR;
-typedef int LPWINDOWPOS;
-typedef int LPWORD;
-typedef int LRESULT;
-typedef int HRESULT;
-# undef MSG
-typedef int MSG;
-typedef int NEWTEXTMETRIC;
-typedef int OSVERSIONINFO;
-typedef int PWORD;
-typedef int RECT;
-typedef int UINT;
-typedef int WORD;
-typedef int WPARAM;
-typedef int POINT;
-typedef void *HINSTANCE;
-typedef void *HMENU;
-typedef void *HWND;
-typedef void *HDC;
-typedef void VOID;
-typedef int LPNMHDR;
-typedef int LONG;
-typedef int WNDPROC;
-#endif
-
-#ifndef GET_X_LPARAM
-# define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
-#endif
-
-static void _OnPaint( HWND hwnd);
-static void clear_rect(RECT *rcp);
-
-static WORD s_dlgfntheight; /* height of the dialog font */
-static WORD s_dlgfntwidth; /* width of the dialog font */
-
-#ifdef FEAT_MENU
-static HMENU s_menuBar = NULL;
-#endif
-#ifdef FEAT_TEAROFF
-static void rebuild_tearoff(vimmenu_T *menu);
-static HBITMAP s_htearbitmap; /* bitmap used to indicate tearoff */
-#endif
-
-/* Flag that is set while processing a message that must not be interrupted by
- * processing another message. */
-static int s_busy_processing = FALSE;
-
-static int destroying = FALSE; /* call DestroyWindow() ourselves */
-
-#ifdef MSWIN_FIND_REPLACE
-static UINT s_findrep_msg = 0; /* set in gui_w[16/32].c */
-static FINDREPLACE s_findrep_struct;
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-static FINDREPLACEW s_findrep_struct_w;
-# endif
-static HWND s_findrep_hwnd = NULL;
-static int s_findrep_is_find; /* TRUE for find dialog, FALSE
- for find/replace dialog */
-#endif
-
-static HINSTANCE s_hinst = NULL;
-#if !defined(FEAT_SNIFF) && !defined(FEAT_GUI)
-static
-#endif
-HWND s_hwnd = NULL;
-static HDC s_hdc = NULL;
-static HBRUSH s_brush = NULL;
-
-#ifdef FEAT_TOOLBAR
-static HWND s_toolbarhwnd = NULL;
-static WNDPROC s_toolbar_wndproc = NULL;
-#endif
-
-#ifdef FEAT_GUI_TABLINE
-static HWND s_tabhwnd = NULL;
-static WNDPROC s_tabline_wndproc = NULL;
-static int showing_tabline = 0;
-#endif
-
-static WPARAM s_wParam = 0;
-static LPARAM s_lParam = 0;
-
-static HWND s_textArea = NULL;
-static UINT s_uMsg = 0;
-
-static char_u *s_textfield; /* Used by dialogs to pass back strings */
-
-static int s_need_activate = FALSE;
-
-/* This variable is set when waiting for an event, which is the only moment
- * scrollbar dragging can be done directly. It's not allowed while commands
- * are executed, because it may move the cursor and that may cause unexpected
- * problems (e.g., while ":s" is working).
- */
-static int allow_scrollbar = FALSE;
-
-#ifdef GLOBAL_IME
-# define MyTranslateMessage(x) global_ime_TranslateMessage(x)
-#else
-# define MyTranslateMessage(x) TranslateMessage(x)
-#endif
-
-#if (defined(WIN3264) && defined(FEAT_MBYTE)) || defined(GLOBAL_IME)
- /* use of WindowProc depends on wide_WindowProc */
-# define MyWindowProc vim_WindowProc
-#else
- /* use ordinary WindowProc */
-# define MyWindowProc DefWindowProc
-#endif
-
-extern int current_font_height; /* this is in os_mswin.c */
-
-static struct
-{
- UINT key_sym;
- char_u vim_code0;
- char_u vim_code1;
-} special_keys[] =
-{
- {VK_UP, 'k', 'u'},
- {VK_DOWN, 'k', 'd'},
- {VK_LEFT, 'k', 'l'},
- {VK_RIGHT, 'k', 'r'},
-
- {VK_F1, 'k', '1'},
- {VK_F2, 'k', '2'},
- {VK_F3, 'k', '3'},
- {VK_F4, 'k', '4'},
- {VK_F5, 'k', '5'},
- {VK_F6, 'k', '6'},
- {VK_F7, 'k', '7'},
- {VK_F8, 'k', '8'},
- {VK_F9, 'k', '9'},
- {VK_F10, 'k', ';'},
-
- {VK_F11, 'F', '1'},
- {VK_F12, 'F', '2'},
- {VK_F13, 'F', '3'},
- {VK_F14, 'F', '4'},
- {VK_F15, 'F', '5'},
- {VK_F16, 'F', '6'},
- {VK_F17, 'F', '7'},
- {VK_F18, 'F', '8'},
- {VK_F19, 'F', '9'},
- {VK_F20, 'F', 'A'},
-
- {VK_F21, 'F', 'B'},
-#ifdef FEAT_NETBEANS_INTG
- {VK_PAUSE, 'F', 'B'}, /* Pause == F21 (see gui_gtk_x11.c) */
-#endif
- {VK_F22, 'F', 'C'},
- {VK_F23, 'F', 'D'},
- {VK_F24, 'F', 'E'}, /* winuser.h defines up to F24 */
-
- {VK_HELP, '%', '1'},
- {VK_BACK, 'k', 'b'},
- {VK_INSERT, 'k', 'I'},
- {VK_DELETE, 'k', 'D'},
- {VK_HOME, 'k', 'h'},
- {VK_END, '@', '7'},
- {VK_PRIOR, 'k', 'P'},
- {VK_NEXT, 'k', 'N'},
- {VK_PRINT, '%', '9'},
- {VK_ADD, 'K', '6'},
- {VK_SUBTRACT, 'K', '7'},
- {VK_DIVIDE, 'K', '8'},
- {VK_MULTIPLY, 'K', '9'},
- {VK_SEPARATOR, 'K', 'A'}, /* Keypad Enter */
- {VK_DECIMAL, 'K', 'B'},
-
- {VK_NUMPAD0, 'K', 'C'},
- {VK_NUMPAD1, 'K', 'D'},
- {VK_NUMPAD2, 'K', 'E'},
- {VK_NUMPAD3, 'K', 'F'},
- {VK_NUMPAD4, 'K', 'G'},
- {VK_NUMPAD5, 'K', 'H'},
- {VK_NUMPAD6, 'K', 'I'},
- {VK_NUMPAD7, 'K', 'J'},
- {VK_NUMPAD8, 'K', 'K'},
- {VK_NUMPAD9, 'K', 'L'},
-
- /* Keys that we want to be able to use any modifier with: */
- {VK_SPACE, ' ', NUL},
- {VK_TAB, TAB, NUL},
- {VK_ESCAPE, ESC, NUL},
- {NL, NL, NUL},
- {CAR, CAR, NUL},
-
- /* End of list marker: */
- {0, 0, 0}
-};
-
-/* Local variables */
-static int s_button_pending = -1;
-
-/* s_getting_focus is set when we got focus but didn't see mouse-up event yet,
- * so don't reset s_button_pending. */
-static int s_getting_focus = FALSE;
-
-static int s_x_pending;
-static int s_y_pending;
-static UINT s_kFlags_pending;
-static UINT s_wait_timer = 0; /* Timer for get char from user */
-static int s_timed_out = FALSE;
-static int dead_key = 0; /* 0: no dead key, 1: dead key pressed */
-
-#ifdef WIN3264
-static OSVERSIONINFO os_version; /* like it says. Init in gui_mch_init() */
-#endif
-
-#ifdef FEAT_BEVAL
-/* balloon-eval WM_NOTIFY_HANDLER */
-static void Handle_WM_Notify(HWND hwnd, LPNMHDR pnmh);
-static void TrackUserActivity(UINT uMsg);
-#endif
-
-/*
- * For control IME.
- *
- * These LOGFONT used for IME.
- */
-#ifdef FEAT_MBYTE
-# ifdef USE_IM_CONTROL
-/* holds LOGFONT for 'guifontwide' if available, otherwise 'guifont' */
-static LOGFONT norm_logfont;
-/* holds LOGFONT for 'guifont' always. */
-static LOGFONT sub_logfont;
-# endif
-#endif
-
-#ifdef FEAT_MBYTE_IME
-static LRESULT _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData);
-#endif
-
-#if defined(FEAT_BROWSE)
-static char_u *convert_filter(char_u *s);
-#endif
-
-#ifdef DEBUG_PRINT_ERROR
-/*
- * Print out the last Windows error message
- */
- static void
-print_windows_error(void)
-{
- LPVOID lpMsgBuf;
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf, 0, NULL);
- TRACE1("Error: %s\n", lpMsgBuf);
- LocalFree(lpMsgBuf);
-}
-#endif
-
-/*
- * Cursor blink functions.
- *
- * This is a simple state machine:
- * BLINK_NONE not blinking at all
- * BLINK_OFF blinking, cursor is not shown
- * BLINK_ON blinking, cursor is shown
- */
-
-#define BLINK_NONE 0
-#define BLINK_OFF 1
-#define BLINK_ON 2
-
-static int blink_state = BLINK_NONE;
-static long_u blink_waittime = 700;
-static long_u blink_ontime = 400;
-static long_u blink_offtime = 250;
-static UINT blink_timer = 0;
-
- void
-gui_mch_set_blinking(long wait, long on, long off)
-{
- blink_waittime = wait;
- blink_ontime = on;
- blink_offtime = off;
-}
-
-/* ARGSUSED */
- static VOID CALLBACK
-_OnBlinkTimer(
- HWND hwnd,
- UINT uMsg,
- UINT idEvent,
- DWORD dwTime)
-{
- MSG msg;
-
- /*
- TRACE2("Got timer event, id %d, blink_timer %d\n", idEvent, blink_timer);
- */
-
- KillTimer(NULL, idEvent);
-
- /* Eat spurious WM_TIMER messages */
- while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
- ;
-
- if (blink_state == BLINK_ON)
- {
- gui_undraw_cursor();
- blink_state = BLINK_OFF;
- blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_offtime,
- (TIMERPROC)_OnBlinkTimer);
- }
- else
- {
- gui_update_cursor(TRUE, FALSE);
- blink_state = BLINK_ON;
- blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
- (TIMERPROC)_OnBlinkTimer);
- }
-}
-
- static void
-gui_mswin_rm_blink_timer(void)
-{
- MSG msg;
-
- if (blink_timer != 0)
- {
- KillTimer(NULL, blink_timer);
- /* Eat spurious WM_TIMER messages */
- while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
- ;
- blink_timer = 0;
- }
-}
-
-/*
- * Stop the cursor blinking. Show the cursor if it wasn't shown.
- */
- void
-gui_mch_stop_blink(void)
-{
- gui_mswin_rm_blink_timer();
- if (blink_state == BLINK_OFF)
- gui_update_cursor(TRUE, FALSE);
- blink_state = BLINK_NONE;
-}
-
-/*
- * Start the cursor blinking. If it was already blinking, this restarts the
- * waiting time and shows the cursor.
- */
- void
-gui_mch_start_blink(void)
-{
- gui_mswin_rm_blink_timer();
-
- /* Only switch blinking on if none of the times is zero */
- if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
- {
- blink_timer = (UINT)SetTimer(NULL, 0, (UINT)blink_waittime,
- (TIMERPROC)_OnBlinkTimer);
- blink_state = BLINK_ON;
- gui_update_cursor(TRUE, FALSE);
- }
-}
-
-/*
- * Call-back routines.
- */
-
-/*ARGSUSED*/
- static VOID CALLBACK
-_OnTimer(
- HWND hwnd,
- UINT uMsg,
- UINT idEvent,
- DWORD dwTime)
-{
- MSG msg;
-
- /*
- TRACE2("Got timer event, id %d, s_wait_timer %d\n", idEvent, s_wait_timer);
- */
- KillTimer(NULL, idEvent);
- s_timed_out = TRUE;
-
- /* Eat spurious WM_TIMER messages */
- while (pPeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
- ;
- if (idEvent == s_wait_timer)
- s_wait_timer = 0;
-}
-
-/*ARGSUSED*/
- static void
-_OnDeadChar(
- HWND hwnd,
- UINT ch,
- int cRepeat)
-{
- dead_key = 1;
-}
-
-/*
- * Convert Unicode character "ch" to bytes in "string[slen]".
- * When "had_alt" is TRUE the ALT key was included in "ch".
- * Return the length.
- */
- static int
-char_to_string(int ch, char_u *string, int slen, int had_alt)
-{
- int len;
- int i;
-#ifdef FEAT_MBYTE
- WCHAR wstring[2];
- char_u *ws = NULL;;
-
- if (os_version.dwPlatformId != VER_PLATFORM_WIN32_NT)
- {
- /* On Windows 95/98 we apparently get the character in the active
- * codepage, not in UCS-2. If conversion is needed convert it to
- * UCS-2 first. */
- if ((int)GetACP() == enc_codepage)
- len = 0; /* no conversion required */
- else
- {
- string[0] = ch;
- len = MultiByteToWideChar(GetACP(), 0, (LPCSTR)string,
- 1, wstring, 2);
- }
- }
- else
- {
- wstring[0] = ch;
- len = 1;
- }
-
- if (len > 0)
- {
- /* "ch" is a UTF-16 character. Convert it to a string of bytes. When
- * "enc_codepage" is non-zero use the standard Win32 function,
- * otherwise use our own conversion function (e.g., for UTF-8). */
- if (enc_codepage > 0)
- {
- len = WideCharToMultiByte(enc_codepage, 0, wstring, len,
- (LPSTR)string, slen, 0, NULL);
- /* If we had included the ALT key into the character but now the
- * upper bit is no longer set, that probably means the conversion
- * failed. Convert the original character and set the upper bit
- * afterwards. */
- if (had_alt && len == 1 && ch >= 0x80 && string[0] < 0x80)
- {
- wstring[0] = ch & 0x7f;
- len = WideCharToMultiByte(enc_codepage, 0, wstring, len,
- (LPSTR)string, slen, 0, NULL);
- if (len == 1) /* safety check */
- string[0] |= 0x80;
- }
- }
- else
- {
- len = 1;
- ws = utf16_to_enc(wstring, &len);
- if (ws == NULL)
- len = 0;
- else
- {
- if (len > slen) /* just in case */
- len = slen;
- mch_memmove(string, ws, len);
- vim_free(ws);
- }
- }
- }
-
- if (len == 0)
-#endif
- {
- string[0] = ch;
- len = 1;
- }
-
- for (i = 0; i < len; ++i)
- if (string[i] == CSI && len <= slen - 2)
- {
- /* Insert CSI as K_CSI. */
- mch_memmove(string + i + 3, string + i + 1, len - i - 1);
- string[++i] = KS_EXTRA;
- string[++i] = (int)KE_CSI;
- len += 2;
- }
-
- return len;
-}
-
-/*
- * Key hit, add it to the input buffer.
- */
-/*ARGSUSED*/
- static void
-_OnChar(
- HWND hwnd,
- UINT ch,
- int cRepeat)
-{
- char_u string[40];
- int len = 0;
-
- dead_key = 0;
-
- len = char_to_string(ch, string, 40, FALSE);
- if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts)
- {
- trash_input_buf();
- got_int = TRUE;
- }
-
- add_to_input_buf(string, len);
-}
-
-/*
- * Alt-Key hit, add it to the input buffer.
- */
-/*ARGSUSED*/
- static void
-_OnSysChar(
- HWND hwnd,
- UINT cch,
- int cRepeat)
-{
- char_u string[40]; /* Enough for multibyte character */
- int len;
- int modifiers;
- int ch = cch; /* special keys are negative */
-
- dead_key = 0;
-
- /* TRACE("OnSysChar(%d, %c)\n", ch, ch); */
-
- /* OK, we have a character key (given by ch) which was entered with the
- * ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
- * that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless
- * CAPSLOCK is pressed) at this point.
- */
- modifiers = MOD_MASK_ALT;
- if (GetKeyState(VK_SHIFT) & 0x8000)
- modifiers |= MOD_MASK_SHIFT;
- if (GetKeyState(VK_CONTROL) & 0x8000)
- modifiers |= MOD_MASK_CTRL;
-
- ch = simplify_key(ch, &modifiers);
- /* remove the SHIFT modifier for keys where it's already included, e.g.,
- * '(' and '*' */
- if (ch < 0x100 && !isalpha(ch) && isprint(ch))
- modifiers &= ~MOD_MASK_SHIFT;
-
- /* Interpret the ALT key as making the key META, include SHIFT, etc. */
- ch = extract_modifiers(ch, &modifiers);
- if (ch == CSI)
- ch = K_CSI;
-
- len = 0;
- if (modifiers)
- {
- string[len++] = CSI;
- string[len++] = KS_MODIFIER;
- string[len++] = modifiers;
- }
-
- if (IS_SPECIAL((int)ch))
- {
- string[len++] = CSI;
- string[len++] = K_SECOND((int)ch);
- string[len++] = K_THIRD((int)ch);
- }
- else
- {
- /* Although the documentation isn't clear about it, we assume "ch" is
- * a Unicode character. */
- len += char_to_string(ch, string + len, 40 - len, TRUE);
- }
-
- add_to_input_buf(string, len);
-}
-
- static void
-_OnMouseEvent(
- int button,
- int x,
- int y,
- int repeated_click,
- UINT keyFlags)
-{
- int vim_modifiers = 0x0;
-
- s_getting_focus = FALSE;
-
- if (keyFlags & MK_SHIFT)
- vim_modifiers |= MOUSE_SHIFT;
- if (keyFlags & MK_CONTROL)
- vim_modifiers |= MOUSE_CTRL;
- if (GetKeyState(VK_MENU) & 0x8000)
- vim_modifiers |= MOUSE_ALT;
-
- gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers);
-}
-
-/*ARGSUSED*/
- static void
-_OnMouseButtonDown(
- HWND hwnd,
- BOOL fDoubleClick,
- int x,
- int y,
- UINT keyFlags)
-{
- static LONG s_prevTime = 0;
-
- LONG currentTime = GetMessageTime();
- int button = -1;
- int repeated_click;
-
- /* Give main window the focus: this is so the cursor isn't hollow. */
- (void)SetFocus(s_hwnd);
-
- if (s_uMsg == WM_LBUTTONDOWN || s_uMsg == WM_LBUTTONDBLCLK)
- button = MOUSE_LEFT;
- else if (s_uMsg == WM_MBUTTONDOWN || s_uMsg == WM_MBUTTONDBLCLK)
- button = MOUSE_MIDDLE;
- else if (s_uMsg == WM_RBUTTONDOWN || s_uMsg == WM_RBUTTONDBLCLK)
- button = MOUSE_RIGHT;
-#ifndef WIN16 /*<VN>*/
- else if (s_uMsg == WM_XBUTTONDOWN || s_uMsg == WM_XBUTTONDBLCLK)
- {
-#ifndef GET_XBUTTON_WPARAM
-# define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam))
-#endif
- button = ((GET_XBUTTON_WPARAM(s_wParam) == 1) ? MOUSE_X1 : MOUSE_X2);
- }
- else if (s_uMsg == WM_CAPTURECHANGED)
- {
- /* on W95/NT4, somehow you get in here with an odd Msg
- * if you press one button while holding down the other..*/
- if (s_button_pending == MOUSE_LEFT)
- button = MOUSE_RIGHT;
- else
- button = MOUSE_LEFT;
- }
-#endif
- if (button >= 0)
- {
- repeated_click = ((int)(currentTime - s_prevTime) < p_mouset);
-
- /*
- * Holding down the left and right buttons simulates pushing the middle
- * button.
- */
- if (repeated_click
- && ((button == MOUSE_LEFT && s_button_pending == MOUSE_RIGHT)
- || (button == MOUSE_RIGHT
- && s_button_pending == MOUSE_LEFT)))
- {
- /*
- * Hmm, gui.c will ignore more than one button down at a time, so
- * pretend we let go of it first.
- */
- gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, 0x0);
- button = MOUSE_MIDDLE;
- repeated_click = FALSE;
- s_button_pending = -1;
- _OnMouseEvent(button, x, y, repeated_click, keyFlags);
- }
- else if ((repeated_click)
- || (mouse_model_popup() && (button == MOUSE_RIGHT)))
- {
- if (s_button_pending > -1)
- {
- _OnMouseEvent(s_button_pending, x, y, FALSE, keyFlags);
- s_button_pending = -1;
- }
- /* TRACE("Button down at x %d, y %d\n", x, y); */
- _OnMouseEvent(button, x, y, repeated_click, keyFlags);
- }
- else
- {
- /*
- * If this is the first press (i.e. not a multiple click) don't
- * action immediately, but store and wait for:
- * i) button-up
- * ii) mouse move
- * iii) another button press
- * before using it.
- * This enables us to make left+right simulate middle button,
- * without left or right being actioned first. The side-effect is
- * that if you click and hold the mouse without dragging, the
- * cursor doesn't move until you release the button. In practice
- * this is hardly a problem.
- */
- s_button_pending = button;
- s_x_pending = x;
- s_y_pending = y;
- s_kFlags_pending = keyFlags;
- }
-
- s_prevTime = currentTime;
- }
-}
-
-/*ARGSUSED*/
- static void
-_OnMouseMoveOrRelease(
- HWND hwnd,
- int x,
- int y,
- UINT keyFlags)
-{
- int button;
-
- s_getting_focus = FALSE;
- if (s_button_pending > -1)
- {
- /* Delayed action for mouse down event */
- _OnMouseEvent(s_button_pending, s_x_pending,
- s_y_pending, FALSE, s_kFlags_pending);
- s_button_pending = -1;
- }
- if (s_uMsg == WM_MOUSEMOVE)
- {
- /*
- * It's only a MOUSE_DRAG if one or more mouse buttons are being held
- * down.
- */
- if (!(keyFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON
- | MK_XBUTTON1 | MK_XBUTTON2)))
- {
- gui_mouse_moved(x, y);
- return;
- }
-
- /*
- * While button is down, keep grabbing mouse move events when
- * the mouse goes outside the window
- */
- SetCapture(s_textArea);
- button = MOUSE_DRAG;
- /* TRACE(" move at x %d, y %d\n", x, y); */
- }
- else
- {
- ReleaseCapture();
- button = MOUSE_RELEASE;
- /* TRACE(" up at x %d, y %d\n", x, y); */
- }
-
- _OnMouseEvent(button, x, y, FALSE, keyFlags);
-}
-
-#ifdef FEAT_MENU
-/*
- * Find the vimmenu_T with the given id
- */
- static vimmenu_T *
-gui_mswin_find_menu(
- vimmenu_T *pMenu,
- int id)
-{
- vimmenu_T *pChildMenu;
-
- while (pMenu)
- {
- if (pMenu->id == (UINT)id)
- break;
- if (pMenu->children != NULL)
- {
- pChildMenu = gui_mswin_find_menu(pMenu->children, id);
- if (pChildMenu)
- {
- pMenu = pChildMenu;
- break;
- }
- }
- pMenu = pMenu->next;
- }
- return pMenu;
-}
-
-/*ARGSUSED*/
- static void
-_OnMenu(
- HWND hwnd,
- int id,
- HWND hwndCtl,
- UINT codeNotify)
-{
- vimmenu_T *pMenu;
-
- pMenu = gui_mswin_find_menu(root_menu, id);
- if (pMenu)
- gui_menu_cb(pMenu);
-}
-#endif
-
-#ifdef MSWIN_FIND_REPLACE
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-/*
- * copy useful data from structure LPFINDREPLACE to structure LPFINDREPLACEW
- */
- static void
-findrep_atow(LPFINDREPLACEW lpfrw, LPFINDREPLACE lpfr)
-{
- WCHAR *wp;
-
- lpfrw->hwndOwner = lpfr->hwndOwner;
- lpfrw->Flags = lpfr->Flags;
-
- wp = enc_to_utf16((char_u *)lpfr->lpstrFindWhat, NULL);
- wcsncpy(lpfrw->lpstrFindWhat, wp, lpfrw->wFindWhatLen - 1);
- vim_free(wp);
-
- /* the field "lpstrReplaceWith" doesn't need to be copied */
-}
-
-/*
- * copy useful data from structure LPFINDREPLACEW to structure LPFINDREPLACE
- */
- static void
-findrep_wtoa(LPFINDREPLACE lpfr, LPFINDREPLACEW lpfrw)
-{
- char_u *p;
-
- lpfr->Flags = lpfrw->Flags;
-
- p = utf16_to_enc((short_u*)lpfrw->lpstrFindWhat, NULL);
- vim_strncpy((char_u *)lpfr->lpstrFindWhat, p, lpfr->wFindWhatLen - 1);
- vim_free(p);
-
- p = utf16_to_enc((short_u*)lpfrw->lpstrReplaceWith, NULL);
- vim_strncpy((char_u *)lpfr->lpstrReplaceWith, p, lpfr->wReplaceWithLen - 1);
- vim_free(p);
-}
-# endif
-
-/*
- * Handle a Find/Replace window message.
- */
- static void
-_OnFindRepl(void)
-{
- int flags = 0;
- int down;
-
-# if defined(FEAT_MBYTE) && defined(WIN3264)
- /* If the OS is Windows NT, and 'encoding' differs from active codepage:
- * convert text from wide string. */
- if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
- && enc_codepage >= 0 && (int)GetACP() != enc_codepage)
- {
- findrep_wtoa(&s_findrep_struct, &s_findrep_struct_w);
- }
-# endif
-
- if (s_findrep_struct.Flags & FR_DIALOGTERM)
- /* Give main window the focus back. */
- (void)SetFocus(s_hwnd);
-
- if (s_findrep_struct.Flags & FR_FINDNEXT)
- {
- flags = FRD_FINDNEXT;
-
- /* Give main window the focus back: this is so the cursor isn't
- * hollow. */
- (void)SetFocus(s_hwnd);
- }
- else if (s_findrep_struct.Flags & FR_REPLACE)
- {
- flags = FRD_REPLACE;
-
- /* Give main window the focus back: this is so the cursor isn't
- * hollow. */
- (void)SetFocus(s_hwnd);
- }
- else if (s_findrep_struct.Flags & FR_REPLACEALL)
- {
- flags = FRD_REPLACEALL;
- }
-
- if (flags != 0)
- {
- /* Call the generic GUI function to do the actual work. */
- if (s_findrep_struct.Flags & FR_WHOLEWORD)
- flags |= FRD_WHOLE_WORD;
- if (s_findrep_struct.Flags & FR_MATCHCASE)
- flags |= FRD_MATCH_CASE;
- down = (s_findrep_struct.Flags & FR_DOWN) != 0;
- gui_do_findrepl(flags, (char_u *)s_findrep_struct.lpstrFindWhat,
- (char_u *)s_findrep_struct.lpstrReplaceWith, down);
- }
-}
-#endif
-
- static void
-HandleMouseHide(UINT uMsg, LPARAM lParam)
-{
- static LPARAM last_lParam = 0L;
-
- /* We sometimes get a mousemove when the mouse didn't move... */
- if (uMsg == WM_MOUSEMOVE || uMsg == WM_NCMOUSEMOVE)
- {
- if (lParam == last_lParam)
- return;
- last_lParam = lParam;
- }
-
- /* Handle specially, to centralise coding. We need to be sure we catch all
- * possible events which should cause us to restore the cursor (as it is a
- * shared resource, we take full responsibility for it).
- */
- switch (uMsg)
- {
- case WM_KEYUP:
- case WM_CHAR:
- /*
- * blank out the pointer if necessary
- */
- if (p_mh)
- gui_mch_mousehide(TRUE);
- break;
-
- case WM_SYSKEYUP: /* show the pointer when a system-key is pressed */
- case WM_SYSCHAR:
- case WM_MOUSEMOVE: /* show the pointer on any mouse action */
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- case WM_XBUTTONDOWN:
- case WM_XBUTTONUP:
- case WM_NCMOUSEMOVE:
- case WM_NCLBUTTONDOWN:
- case WM_NCLBUTTONUP:
- case WM_NCMBUTTONDOWN:
- case WM_NCMBUTTONUP:
- case WM_NCRBUTTONDOWN:
- case WM_NCRBUTTONUP:
- case WM_KILLFOCUS:
- /*
- * if the pointer is currently hidden, then we should show it.
- */
- gui_mch_mousehide(FALSE);
- break;
- }
-}
-
- static LRESULT CALLBACK
-_TextAreaWndProc(
- HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- /*
- TRACE("TextAreaWndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
- hwnd, uMsg, wParam, lParam);
- */
-
- HandleMouseHide(uMsg, lParam);
-
- s_uMsg = uMsg;
- s_wParam = wParam;
- s_lParam = lParam;
-
-#ifdef FEAT_BEVAL
- TrackUserActivity(uMsg);
-#endif
-
- switch (uMsg)
- {
- HANDLE_MSG(hwnd, WM_LBUTTONDBLCLK,_OnMouseButtonDown);
- HANDLE_MSG(hwnd, WM_LBUTTONDOWN,_OnMouseButtonDown);
- HANDLE_MSG(hwnd, WM_LBUTTONUP, _OnMouseMoveOrRelease);
- HANDLE_MSG(hwnd, WM_MBUTTONDBLCLK,_OnMouseButtonDown);
- HANDLE_MSG(hwnd, WM_MBUTTONDOWN,_OnMouseButtonDown);
- HANDLE_MSG(hwnd, WM_MBUTTONUP, _OnMouseMoveOrRelease);
- HANDLE_MSG(hwnd, WM_MOUSEMOVE, _OnMouseMoveOrRelease);
- HANDLE_MSG(hwnd, WM_PAINT, _OnPaint);
- HANDLE_MSG(hwnd, WM_RBUTTONDBLCLK,_OnMouseButtonDown);
- HANDLE_MSG(hwnd, WM_RBUTTONDOWN,_OnMouseButtonDown);
- HANDLE_MSG(hwnd, WM_RBUTTONUP, _OnMouseMoveOrRelease);
-#ifndef WIN16 /*<VN>*/
- HANDLE_MSG(hwnd, WM_XBUTTONDBLCLK,_OnMouseButtonDown);
- HANDLE_MSG(hwnd, WM_XBUTTONDOWN,_OnMouseButtonDown);
- HANDLE_MSG(hwnd, WM_XBUTTONUP, _OnMouseMoveOrRelease);
-#endif
-
-#ifdef FEAT_BEVAL
- case WM_NOTIFY: Handle_WM_Notify(hwnd, (LPNMHDR)lParam);
- return TRUE;
-#endif
- default:
- return MyWindowProc(hwnd, uMsg, wParam, lParam);
- }
-}
-
-#if (defined(WIN3264) && defined(FEAT_MBYTE)) \
- || defined(GLOBAL_IME) \
- || defined(PROTO)
-# ifdef PROTO
-typedef int WINAPI;
-# endif
-
- LRESULT WINAPI
-vim_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-# ifdef GLOBAL_IME
- return global_ime_DefWindowProc(hwnd, message, wParam, lParam);
-# else
- if (wide_WindowProc)
- return DefWindowProcW(hwnd, message, wParam, lParam);
- return DefWindowProc(hwnd, message, wParam, lParam);
-#endif
-}
-#endif
-
-/*
- * Called when the foreground or background color has been changed.
- */
- void
-gui_mch_new_colors(void)
-{
- /* nothing to do? */
-}
-
-/*
- * Set the colors to their default values.
- */
- void
-gui_mch_def_colors(void)
-{
- gui.norm_pixel = GetSysColor(COLOR_WINDOWTEXT);
- gui.back_pixel = GetSysColor(COLOR_WINDOW);
- gui.def_norm_pixel = gui.norm_pixel;
- gui.def_back_pixel = gui.back_pixel;
-}
-
-/*
- * Open the GUI window which was created by a call to gui_mch_init().
- */
- int
-gui_mch_open(void)
-{
-#ifndef SW_SHOWDEFAULT
-# define SW_SHOWDEFAULT 10 /* Borland 5.0 doesn't have it */
-#endif
- /* Actually open the window, if not already visible
- * (may be done already in gui_mch_set_shellsize) */
- if (!IsWindowVisible(s_hwnd))
- ShowWindow(s_hwnd, SW_SHOWDEFAULT);
-
-#ifdef MSWIN_FIND_REPLACE
- /* Init replace string here, so that we keep it when re-opening the
- * dialog. */
- s_findrep_struct.lpstrReplaceWith[0] = NUL;
-#endif
-
- return OK;
-}
-
-/*
- * Get the position of the top left corner of the window.
- */
- int
-gui_mch_get_winpos(int *x, int *y)
-{
- RECT rect;
-
- GetWindowRect(s_hwnd, &rect);
- *x = rect.left;
- *y = rect.top;
- return OK;
-}
-
-/*
- * Set the position of the top left corner of the window to the given
- * coordinates.
- */
- void
-gui_mch_set_winpos(int x, int y)
-{
- SetWindowPos(s_hwnd, NULL, x, y, 0, 0,
- SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
-}
- void
-gui_mch_set_text_area_pos(int x, int y, int w, int h)
-{
- static int oldx = 0;
- static int oldy = 0;
-
- SetWindowPos(s_textArea, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE);
-
-#ifdef FEAT_TOOLBAR
- if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
- SendMessage(s_toolbarhwnd, WM_SIZE,
- (WPARAM)0, (LPARAM)(w + ((long)(TOOLBAR_BUTTON_HEIGHT+8)<<16)));
-#endif
-#if defined(FEAT_GUI_TABLINE)
- if (showing_tabline)
- {
- int top = 0;
- RECT rect;
-
-# ifdef FEAT_TOOLBAR
- if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
- top = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
-# endif
- GetClientRect(s_hwnd, &rect);
- MoveWindow(s_tabhwnd, 0, top, rect.right, gui.tabline_height, TRUE);
- }
-#endif
-
- /* When side scroll bar is unshown, the size of window will change.
- * then, the text area move left or right. thus client rect should be
- * forcedly redrawn. (Yasuhiro Matsumoto) */
- if (oldx != x || oldy != y)
- {
- InvalidateRect(s_hwnd, NULL, FALSE);
- oldx = x;
- oldy = y;
- }
-}
-
-
-/*
- * Scrollbar stuff:
- */
-
- void
-gui_mch_enable_scrollbar(
- scrollbar_T *sb,
- int flag)
-{
- ShowScrollBar(sb->id, SB_CTL, flag);
-
- /* TODO: When the window is maximized, the size of the window stays the
- * same, thus the size of the text area changes. On Win98 it's OK, on Win
- * NT 4.0 it's not... */
-}
-
- void
-gui_mch_set_scrollbar_pos(
- scrollbar_T *sb,
- int x,
- int y,
- int w,
- int h)
-{
- SetWindowPos(sb->id, NULL, x, y, w, h,
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
-}
-
- void
-gui_mch_create_scrollbar(
- scrollbar_T *sb,
- int orient) /* SBAR_VERT or SBAR_HORIZ */
-{
- sb->id = CreateWindow(
- "SCROLLBAR", "Scrollbar",
- WS_CHILD | ((orient == SBAR_VERT) ? SBS_VERT : SBS_HORZ), 0, 0,
- 10, /* Any value will do for now */
- 10, /* Any value will do for now */
- s_hwnd, NULL,
- s_hinst, NULL);
-}
-
-/*
- * Find the scrollbar with the given hwnd.
- */
- static scrollbar_T *
-gui_mswin_find_scrollbar(HWND hwnd)
-{
- win_T *wp;
-
- if (gui.bottom_sbar.id == hwnd)
- return &gui.bottom_sbar;
- FOR_ALL_WINDOWS(wp)
- {
- if (wp->w_scrollbars[SBAR_LEFT].id == hwnd)
- return &wp->w_scrollbars[SBAR_LEFT];
- if (wp->w_scrollbars[SBAR_RIGHT].id == hwnd)
- return &wp->w_scrollbars[SBAR_RIGHT];
- }
- return NULL;
-}
-
-/*
- * Get the character size of a font.
- */
- static void
-GetFontSize(GuiFont font)
-{
- HWND hwnd = GetDesktopWindow();
- HDC hdc = GetWindowDC(hwnd);
- HFONT hfntOld = SelectFont(hdc, (HFONT)font);
- TEXTMETRIC tm;
-
- GetTextMetrics(hdc, &tm);
- gui.char_width = tm.tmAveCharWidth + tm.tmOverhang;
-
- gui.char_height = tm.tmHeight
-#ifndef MSWIN16_FASTTEXT
- + p_linespace
-#endif
- ;
-
- SelectFont(hdc, hfntOld);
-
- ReleaseDC(hwnd, hdc);
-}
-
-/*
- * Adjust gui.char_height (after 'linespace' was changed).
- */
- int
-gui_mch_adjust_charheight(void)
-{
- GetFontSize(gui.norm_font);
- return OK;
-}
-
- static GuiFont
-get_font_handle(LOGFONT *lf)
-{
- HFONT font = NULL;
-
- /* Load the font */
- font = CreateFontIndirect(lf);
-
- if (font == NULL)
- return NOFONT;
-
- return (GuiFont)font;
-}
-
- static int
-pixels_to_points(int pixels, int vertical)
-{
- int points;
- HWND hwnd;
- HDC hdc;
-
- hwnd = GetDesktopWindow();
- hdc = GetWindowDC(hwnd);
-
- points = MulDiv(pixels, 72,
- GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX));
-
- ReleaseDC(hwnd, hdc);
-
- return points;
-}
-
- GuiFont
-gui_mch_get_font(
- char_u *name,
- int giveErrorIfMissing)
-{
- LOGFONT lf;
- GuiFont font = NOFONT;
-
- if (get_logfont(&lf, name, NULL, giveErrorIfMissing) == OK)
- font = get_font_handle(&lf);
- if (font == NOFONT && giveErrorIfMissing)
- EMSG2(_(e_font), name);
- return font;
-}
-
-#if defined(FEAT_EVAL) || defined(PROTO)
-/*
- * Return the name of font "font" in allocated memory.
- * Don't know how to get the actual name, thus use the provided name.
- */
-/*ARGSUSED*/
- char_u *
-gui_mch_get_fontname(GuiFont font, char_u *name)
-{
- if (name == NULL)
- return NULL;
- return vim_strsave(name);
-}
-#endif
-
- void
-gui_mch_free_font(GuiFont font)
-{
- if (font)
- DeleteObject((HFONT)font);
-}
-
- static int
-hex_digit(int c)
-{
- if (VIM_ISDIGIT(c))
- return c - '0';
- c = TOLOWER_ASC(c);
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- return -1000;
-}
-/*
- * Return the Pixel value (color) for the given color name.
- * Return INVALCOLOR for error.
- */
- guicolor_T
-gui_mch_get_color(char_u *name)
-{
- typedef struct guicolor_tTable
- {
- char *name;
- COLORREF color;
- } guicolor_tTable;
-
- static guicolor_tTable table[] =
- {
- {"Black", RGB(0x00, 0x00, 0x00)},
- {"DarkGray", RGB(0xA9, 0xA9, 0xA9)},
- {"DarkGrey", RGB(0xA9, 0xA9, 0xA9)},
- {"Gray", RGB(0xC0, 0xC0, 0xC0)},
- {"Grey", RGB(0xC0, 0xC0, 0xC0)},
- {"LightGray", RGB(0xD3, 0xD3, 0xD3)},
- {"LightGrey", RGB(0xD3, 0xD3, 0xD3)},
- {"Gray10", RGB(0x1A, 0x1A, 0x1A)},
- {"Grey10", RGB(0x1A, 0x1A, 0x1A)},
- {"Gray20", RGB(0x33, 0x33, 0x33)},
- {"Grey20", RGB(0x33, 0x33, 0x33)},
- {"Gray30", RGB(0x4D, 0x4D, 0x4D)},
- {"Grey30", RGB(0x4D, 0x4D, 0x4D)},
- {"Gray40", RGB(0x66, 0x66, 0x66)},
- {"Grey40", RGB(0x66, 0x66, 0x66)},
- {"Gray50", RGB(0x7F, 0x7F, 0x7F)},
- {"Grey50", RGB(0x7F, 0x7F, 0x7F)},
- {"Gray60", RGB(0x99, 0x99, 0x99)},
- {"Grey60", RGB(0x99, 0x99, 0x99)},
- {"Gray70", RGB(0xB3, 0xB3, 0xB3)},
- {"Grey70", RGB(0xB3, 0xB3, 0xB3)},
- {"Gray80", RGB(0xCC, 0xCC, 0xCC)},
- {"Grey80", RGB(0xCC, 0xCC, 0xCC)},
- {"Gray90", RGB(0xE5, 0xE5, 0xE5)},
- {"Grey90", RGB(0xE5, 0xE5, 0xE5)},
- {"White", RGB(0xFF, 0xFF, 0xFF)},
- {"DarkRed", RGB(0x80, 0x00, 0x00)},
- {"Red", RGB(0xFF, 0x00, 0x00)},
- {"LightRed", RGB(0xFF, 0xA0, 0xA0)},
- {"DarkBlue", RGB(0x00, 0x00, 0x80)},
- {"Blue", RGB(0x00, 0x00, 0xFF)},
- {"LightBlue", RGB(0xAD, 0xD8, 0xE6)},
- {"DarkGreen", RGB(0x00, 0x80, 0x00)},
- {"Green", RGB(0x00, 0xFF, 0x00)},
- {"LightGreen", RGB(0x90, 0xEE, 0x90)},
- {"DarkCyan", RGB(0x00, 0x80, 0x80)},
- {"Cyan", RGB(0x00, 0xFF, 0xFF)},
- {"LightCyan", RGB(0xE0, 0xFF, 0xFF)},
- {"DarkMagenta", RGB(0x80, 0x00, 0x80)},
- {"Magenta", RGB(0xFF, 0x00, 0xFF)},
- {"LightMagenta", RGB(0xFF, 0xA0, 0xFF)},
- {"Brown", RGB(0x80, 0x40, 0x40)},
- {"Yellow", RGB(0xFF, 0xFF, 0x00)},
- {"LightYellow", RGB(0xFF, 0xFF, 0xE0)},
- {"DarkYellow", RGB(0xBB, 0xBB, 0x00)},
- {"SeaGreen", RGB(0x2E, 0x8B, 0x57)},
- {"Orange", RGB(0xFF, 0xA5, 0x00)},
- {"Purple", RGB(0xA0, 0x20, 0xF0)},
- {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)},
- {"Violet", RGB(0xEE, 0x82, 0xEE)},
- };
-
- typedef struct SysColorTable
- {
- char *name;
- int color;
- } SysColorTable;
-
- static SysColorTable sys_table[] =
- {
-#ifdef WIN3264
- {"SYS_3DDKSHADOW", COLOR_3DDKSHADOW},
- {"SYS_3DHILIGHT", COLOR_3DHILIGHT},
-#ifndef __MINGW32__
- {"SYS_3DHIGHLIGHT", COLOR_3DHIGHLIGHT},
-#endif
- {"SYS_BTNHILIGHT", COLOR_BTNHILIGHT},
- {"SYS_BTNHIGHLIGHT", COLOR_BTNHIGHLIGHT},
- {"SYS_3DLIGHT", COLOR_3DLIGHT},
- {"SYS_3DSHADOW", COLOR_3DSHADOW},
- {"SYS_DESKTOP", COLOR_DESKTOP},
- {"SYS_INFOBK", COLOR_INFOBK},
- {"SYS_INFOTEXT", COLOR_INFOTEXT},
- {"SYS_3DFACE", COLOR_3DFACE},
-#endif
- {"SYS_BTNFACE", COLOR_BTNFACE},
- {"SYS_BTNSHADOW", COLOR_BTNSHADOW},
- {"SYS_ACTIVEBORDER", COLOR_ACTIVEBORDER},
- {"SYS_ACTIVECAPTION", COLOR_ACTIVECAPTION},
- {"SYS_APPWORKSPACE", COLOR_APPWORKSPACE},
- {"SYS_BACKGROUND", COLOR_BACKGROUND},
- {"SYS_BTNTEXT", COLOR_BTNTEXT},
- {"SYS_CAPTIONTEXT", COLOR_CAPTIONTEXT},
- {"SYS_GRAYTEXT", COLOR_GRAYTEXT},
- {"SYS_HIGHLIGHT", COLOR_HIGHLIGHT},
- {"SYS_HIGHLIGHTTEXT", COLOR_HIGHLIGHTTEXT},
- {"SYS_INACTIVEBORDER", COLOR_INACTIVEBORDER},
- {"SYS_INACTIVECAPTION", COLOR_INACTIVECAPTION},
- {"SYS_INACTIVECAPTIONTEXT", COLOR_INACTIVECAPTIONTEXT},
- {"SYS_MENU", COLOR_MENU},
- {"SYS_MENUTEXT", COLOR_MENUTEXT},
- {"SYS_SCROLLBAR", COLOR_SCROLLBAR},
- {"SYS_WINDOW", COLOR_WINDOW},
- {"SYS_WINDOWFRAME", COLOR_WINDOWFRAME},
- {"SYS_WINDOWTEXT", COLOR_WINDOWTEXT}
- };
-
- int r, g, b;
- int i;
-
- if (name[0] == '#' && STRLEN(name) == 7)
- {
- /* Name is in "#rrggbb" format */
- r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
- g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
- b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
- if (r < 0 || g < 0 || b < 0)
- return INVALCOLOR;
- return RGB(r, g, b);
- }
- else
- {
- /* Check if the name is one of the colors we know */
- for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
- if (STRICMP(name, table[i].name) == 0)
- return table[i].color;
- }
-
- /*
- * Try to look up a system colour.
- */
- for (i = 0; i < sizeof(sys_table) / sizeof(sys_table[0]); i++)
- if (STRICMP(name, sys_table[i].name) == 0)
- return GetSysColor(sys_table[i].color);
-
- /*
- * Last attempt. Look in the file "$VIMRUNTIME/rgb.txt".
- */
- {
-#define LINE_LEN 100
- FILE *fd;
- char line[LINE_LEN];
- char_u *fname;
-
- fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
- if (fname == NULL)
- return INVALCOLOR;
-
- fd = mch_fopen((char *)fname, "rt");
- vim_free(fname);
- if (fd == NULL)
- return INVALCOLOR;
-
- while (!feof(fd))
- {
- int len;
- int pos;
- char *color;
-
- fgets(line, LINE_LEN, fd);
- len = (int)STRLEN(line);
-
- if (len <= 1 || line[len-1] != '\n')
- continue;
-
- line[len-1] = '\0';
-
- i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
- if (i != 3)
- continue;
-
- color = line + pos;
-
- if (STRICMP(color, name) == 0)
- {
- fclose(fd);
- return (guicolor_T) RGB(r, g, b);
- }
- }
-
- fclose(fd);
- }
-
- return INVALCOLOR;
-}
-/*
- * Return OK if the key with the termcap name "name" is supported.
- */
- int
-gui_mch_haskey(char_u *name)
-{
- int i;
-
- for (i = 0; special_keys[i].vim_code1 != NUL; i++)
- if (name[0] == special_keys[i].vim_code0 &&
- name[1] == special_keys[i].vim_code1)
- return OK;
- return FAIL;
-}
-
- void
-gui_mch_beep(void)
-{
- MessageBeep(MB_OK);
-}
-/*
- * Invert a rectangle from row r, column c, for nr rows and nc columns.
- */
- void
-gui_mch_invert_rectangle(
- int r,
- int c,
- int nr,
- int nc)
-{
- RECT rc;
-
- /*
- * Note: InvertRect() excludes right and bottom of rectangle.
- */
- rc.left = FILL_X(c);
- rc.top = FILL_Y(r);
- rc.right = rc.left + nc * gui.char_width;
- rc.bottom = rc.top + nr * gui.char_height;
- InvertRect(s_hdc, &rc);
-}
-
-/*
- * Iconify the GUI window.
- */
- void
-gui_mch_iconify(void)
-{
- ShowWindow(s_hwnd, SW_MINIMIZE);
-}
-
-/*
- * Draw a cursor without focus.
- */
- void
-gui_mch_draw_hollow_cursor(guicolor_T color)
-{
- HBRUSH hbr;
- RECT rc;
-
- /*
- * Note: FrameRect() excludes right and bottom of rectangle.
- */
- rc.left = FILL_X(gui.col);
- rc.top = FILL_Y(gui.row);
- rc.right = rc.left + gui.char_width;
-#ifdef FEAT_MBYTE
- if (mb_lefthalve(gui.row, gui.col))
- rc.right += gui.char_width;
-#endif
- rc.bottom = rc.top + gui.char_height;
- hbr = CreateSolidBrush(color);
- FrameRect(s_hdc, &rc, hbr);
- DeleteBrush(hbr);
-}
-/*
- * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
- * color "color".
- */
- void
-gui_mch_draw_part_cursor(
- int w,
- int h,
- guicolor_T color)
-{
- HBRUSH hbr;
- RECT rc;
-
- /*
- * Note: FillRect() excludes right and bottom of rectangle.
- */
- rc.left =
-#ifdef FEAT_RIGHTLEFT
- /* vertical line should be on the right of current point */
- CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
-#endif
- FILL_X(gui.col);
- rc.top = FILL_Y(gui.row) + gui.char_height - h;
- rc.right = rc.left + w;
- rc.bottom = rc.top + h;
- hbr = CreateSolidBrush(color);
- FillRect(s_hdc, &rc, hbr);
- DeleteBrush(hbr);
-}
-
-
-/*
- * Generates a VK_SPACE when the internal dead_key flag is set to output the
- * dead key's nominal character and re-post the original message.
- */
- static void
-outputDeadKey_rePost(MSG originalMsg)
-{
- static MSG deadCharExpel;
-
- if (!dead_key)
- return;
-
- dead_key = 0;
-
- /* Make Windows generate the dead key's character */
- deadCharExpel.message = originalMsg.message;
- deadCharExpel.hwnd = originalMsg.hwnd;
- deadCharExpel.wParam = VK_SPACE;
-
- MyTranslateMessage(&deadCharExpel);
-
- /* re-generate the current character free of the dead char influence */
- PostMessage(originalMsg.hwnd, originalMsg.message, originalMsg.wParam,
- originalMsg.lParam);
-}
-
-
-/*
- * Process a single Windows message.
- * If one is not available we hang until one is.
- */
- static void
-process_message(void)
-{
- MSG msg;
- UINT vk = 0; /* Virtual key */
- char_u string[40];
- int i;
- int modifiers = 0;
- int key;
-#ifdef FEAT_MENU
- static char_u k10[] = {K_SPECIAL, 'k', ';', 0};
-#endif
-
- pGetMessage(&msg, NULL, 0, 0);
-
-#ifdef FEAT_OLE
- /* Look after OLE Automation commands */
- if (msg.message == WM_OLE)
- {
- char_u *str = (char_u *)msg.lParam;
- if (str == NULL || *str == NUL)
- {
- /* Message can't be ours, forward it. Fixes problem with Ultramon
- * 3.0.4 */
- pDispatchMessage(&msg);
- }
- else
- {
- add_to_input_buf(str, (int)STRLEN(str));
- vim_free(str); /* was allocated in CVim::SendKeys() */
- }
- return;
- }
-#endif
-
-#ifdef FEAT_CHANNEL
- if (msg.message == WM_NETBEANS)
- {
- int what;
- channel_T *channel = channel_fd2channel((sock_T)msg.wParam, &what);
-
- if (channel != NULL)
- {
- /* Disable error messages, they can mess up the display and throw
- * an exception. */
- ++emsg_off;
- channel_read(channel, what, "process_message");
- --emsg_off;
- }
- return;
- }
-#endif
-
-#ifdef FEAT_SNIFF
- if (sniff_request_waiting && want_sniff_request)
- {
- static char_u bytes[3] = {CSI, (char_u)KS_EXTRA, (char_u)KE_SNIFF};
- add_to_input_buf(bytes, 3); /* K_SNIFF */
- sniff_request_waiting = 0;
- want_sniff_request = 0;
- /* request is handled in normal.c */
- }
- if (msg.message == WM_USER)
- {
- MyTranslateMessage(&msg);
- pDispatchMessage(&msg);
- return;
- }
-#endif
-
-#ifdef MSWIN_FIND_REPLACE
- /* Don't process messages used by the dialog */
- if (s_findrep_hwnd != NULL && pIsDialogMessage(s_findrep_hwnd, &msg))
- {
- HandleMouseHide(msg.message, msg.lParam);
- return;
- }
-#endif
-
- /*
- * Check if it's a special key that we recognise. If not, call
- * TranslateMessage().
- */
- if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
- {
- vk = (int) msg.wParam;
-
- /*
- * Handle dead keys in special conditions in other cases we let Windows
- * handle them and do not interfere.
- *
- * The dead_key flag must be reset on several occasions:
- * - in _OnChar() (or _OnSysChar()) as any dead key was necessarily
- * consumed at that point (This is when we let Windows combine the
- * dead character on its own)
- *
- * - Before doing something special such as regenerating keypresses to
- * expel the dead character as this could trigger an infinite loop if
- * for some reason MyTranslateMessage() do not trigger a call
- * immediately to _OnChar() (or _OnSysChar()).
- */
- if (dead_key)
- {
- /*
- * If a dead key was pressed and the user presses VK_SPACE,
- * VK_BACK, or VK_ESCAPE it means that he actually wants to deal
- * with the dead char now, so do nothing special and let Windows
- * handle it.
- *
- * Note that VK_SPACE combines with the dead_key's character and
- * only one WM_CHAR will be generated by TranslateMessage(), in
- * the two other cases two WM_CHAR will be generated: the dead
- * char and VK_BACK or VK_ESCAPE. That is most likely what the
- * user expects.
- */
- if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE))
- {
- dead_key = 0;
- MyTranslateMessage(&msg);
- return;
- }
- /* In modes where we are not typing, dead keys should behave
- * normally */
- else if (!(get_real_state() & (INSERT | CMDLINE | SELECTMODE)))
- {
- outputDeadKey_rePost(msg);
- return;
- }
- }
-
- /* Check for CTRL-BREAK */
- if (vk == VK_CANCEL)
- {
- trash_input_buf();
- got_int = TRUE;
- string[0] = Ctrl_C;
- add_to_input_buf(string, 1);
- }
-
- for (i = 0; special_keys[i].key_sym != 0; i++)
- {
- /* ignore VK_SPACE when ALT key pressed: system menu */
- if (special_keys[i].key_sym == vk
- && (vk != VK_SPACE || !(GetKeyState(VK_MENU) & 0x8000)))
- {
- /*
- * Behave as exected if we have a dead key and the special key
- * is a key that would normally trigger the dead key nominal
- * character output (such as a NUMPAD printable character or
- * the TAB key, etc...).
- */
- if (dead_key && (special_keys[i].vim_code0 == 'K'
- || vk == VK_TAB || vk == CAR))
- {
- outputDeadKey_rePost(msg);
- return;
- }
-
-#ifdef FEAT_MENU
- /* Check for <F10>: Windows selects the menu. When <F10> is
- * mapped we want to use the mapping instead. */
- if (vk == VK_F10
- && gui.menu_is_active
- && check_map(k10, State, FALSE, TRUE, FALSE,
- NULL, NULL) == NULL)
- break;
-#endif
- if (GetKeyState(VK_SHIFT) & 0x8000)
- modifiers |= MOD_MASK_SHIFT;
- /*
- * Don't use caps-lock as shift, because these are special keys
- * being considered here, and we only want letters to get
- * shifted -- webb
- */
- /*
- if (GetKeyState(VK_CAPITAL) & 0x0001)
- modifiers ^= MOD_MASK_SHIFT;
- */
- if (GetKeyState(VK_CONTROL) & 0x8000)
- modifiers |= MOD_MASK_CTRL;
- if (GetKeyState(VK_MENU) & 0x8000)
- modifiers |= MOD_MASK_ALT;
-
- if (special_keys[i].vim_code1 == NUL)
- key = special_keys[i].vim_code0;
- else
- key = TO_SPECIAL(special_keys[i].vim_code0,
- special_keys[i].vim_code1);
- key = simplify_key(key, &modifiers);
- if (key == CSI)
- key = K_CSI;
-
- if (modifiers)
- {
- string[0] = CSI;
- string[1] = KS_MODIFIER;
- string[2] = modifiers;
- add_to_input_buf(string, 3);
- }
-
- if (IS_SPECIAL(key))
- {
- string[0] = CSI;
- string[1] = K_SECOND(key);
- string[2] = K_THIRD(key);
- add_to_input_buf(string, 3);
- }
- else
- {
- int len;
-
- /* Handle "key" as a Unicode character. */
- len = char_to_string(key, string, 40, FALSE);
- add_to_input_buf(string, len);
- }
- break;
- }
- }
- if (special_keys[i].key_sym == 0)
- {
- /* Some keys need C-S- where they should only need C-.
- * Ignore 0xff, Windows XP sends it when NUMLOCK has changed since
- * system startup (Helmut Stiegler, 2003 Oct 3). */
- if (vk != 0xff
- && (GetKeyState(VK_CONTROL) & 0x8000)
- && !(GetKeyState(VK_SHIFT) & 0x8000)
- && !(GetKeyState(VK_MENU) & 0x8000))
- {
- /* CTRL-6 is '^'; Japanese keyboard maps '^' to vk == 0xDE */
- if (vk == '6' || MapVirtualKey(vk, 2) == (UINT)'^')
- {
- string[0] = Ctrl_HAT;
- add_to_input_buf(string, 1);
- }
- /* vk == 0xBD AZERTY for CTRL-'-', but CTRL-[ for * QWERTY! */
- else if (vk == 0xBD) /* QWERTY for CTRL-'-' */
- {
- string[0] = Ctrl__;
- add_to_input_buf(string, 1);
- }
- /* CTRL-2 is '@'; Japanese keyboard maps '@' to vk == 0xC0 */
- else if (vk == '2' || MapVirtualKey(vk, 2) == (UINT)'@')
- {
- string[0] = Ctrl_AT;
- add_to_input_buf(string, 1);
- }
- else
- MyTranslateMessage(&msg);
- }
- else
- MyTranslateMessage(&msg);
- }
- }
-#ifdef FEAT_MBYTE_IME
- else if (msg.message == WM_IME_NOTIFY)
- _OnImeNotify(msg.hwnd, (DWORD)msg.wParam, (DWORD)msg.lParam);
- else if (msg.message == WM_KEYUP && im_get_status())
- /* added for non-MS IME (Yasuhiro Matsumoto) */
- MyTranslateMessage(&msg);
-#endif
-#if !defined(FEAT_MBYTE_IME) && defined(GLOBAL_IME)
-/* GIME_TEST */
- else if (msg.message == WM_IME_STARTCOMPOSITION)
- {
- POINT point;
-
- global_ime_set_font(&norm_logfont);
- point.x = FILL_X(gui.col);
- point.y = FILL_Y(gui.row);
- MapWindowPoints(s_textArea, s_hwnd, &point, 1);
- global_ime_set_position(&point);
- }
-#endif
-
-#ifdef FEAT_MENU
- /* Check for <F10>: Default effect is to select the menu. When <F10> is
- * mapped we need to stop it here to avoid strange effects (e.g., for the
- * key-up event) */
- if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE,
- NULL, NULL) == NULL)
-#endif
- pDispatchMessage(&msg);
-}
-
-/*
- * Catch up with any queued events. This may put keyboard input into the
- * input buffer, call resize call-backs, trigger timers etc. If there is
- * nothing in the event queue (& no timers pending), then we return
- * immediately.
- */
- void
-gui_mch_update(void)
-{
- MSG msg;
-
- if (!s_busy_processing)
- while (pPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
- && !vim_is_input_buf_full())
- process_message();
-}
-
-/*
- * GUI input routine called by gui_wait_for_chars(). Waits for a character
- * from the keyboard.
- * wtime == -1 Wait forever.
- * wtime == 0 This should never happen.
- * wtime > 0 Wait wtime milliseconds for a character.
- * Returns OK if a character was found to be available within the given time,
- * or FAIL otherwise.
- */
- int
-gui_mch_wait_for_chars(int wtime)
-{
- MSG msg;
- int focus;
-
- s_timed_out = FALSE;
-
- if (wtime > 0)
- {
- /* Don't do anything while processing a (scroll) message. */
- if (s_busy_processing)
- return FAIL;
- s_wait_timer = (UINT)SetTimer(NULL, 0, (UINT)wtime,
- (TIMERPROC)_OnTimer);
- }
-
- allow_scrollbar = TRUE;
-
- focus = gui.in_focus;
- while (!s_timed_out)
- {
- /* Stop or start blinking when focus changes */
- if (gui.in_focus != focus)
- {
- if (gui.in_focus)
- gui_mch_start_blink();
- else
- gui_mch_stop_blink();
- focus = gui.in_focus;
- }
-
- if (s_need_activate)
- {
-#ifdef WIN32
- (void)SetForegroundWindow(s_hwnd);
-#else
- (void)SetActiveWindow(s_hwnd);
-#endif
- s_need_activate = FALSE;
- }
-
-#ifdef MESSAGE_QUEUE
- parse_queued_messages();
-#endif
-
-#ifdef FEAT_CHANNEL
- channel_handle_events();
-#endif
-
- /*
- * Don't use gui_mch_update() because then we will spin-lock until a
- * char arrives, instead we use GetMessage() to hang until an
- * event arrives. No need to check for input_buf_full because we are
- * returning as soon as it contains a single char -- webb
- */
- process_message();
-
- if (input_available())
- {
- if (s_wait_timer != 0 && !s_timed_out)
- {
- KillTimer(NULL, s_wait_timer);
-
- /* Eat spurious WM_TIMER messages */
- while (pPeekMessage(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
- ;
- s_wait_timer = 0;
- }
- allow_scrollbar = FALSE;
-
- /* Clear pending mouse button, the release event may have been
- * taken by the dialog window. But don't do this when getting
- * focus, we need the mouse-up event then. */
- if (!s_getting_focus)
- s_button_pending = -1;
-
- return OK;
- }
- }
- allow_scrollbar = FALSE;
- return FAIL;
-}
-
-/*
- * Clear a rectangular region of the screen from text pos (row1, col1) to
- * (row2, col2) inclusive.
- */
- void
-gui_mch_clear_block(
- int row1,
- int col1,
- int row2,
- int col2)
-{
- RECT rc;
-
- /*
- * Clear one extra pixel at the far right, for when bold characters have
- * spilled over to the window border.
- * Note: FillRect() excludes right and bottom of rectangle.
- */
- rc.left = FILL_X(col1);
- rc.top = FILL_Y(row1);
- rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
- rc.bottom = FILL_Y(row2 + 1);
- clear_rect(&rc);
-}
-
-/*
- * Clear the whole text window.
- */
- void
-gui_mch_clear_all(void)
-{
- RECT rc;
-
- rc.left = 0;
- rc.top = 0;
- rc.right = Columns * gui.char_width + 2 * gui.border_width;
- rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
- clear_rect(&rc);
-}
-/*
- * Menu stuff.
- */
-
- void
-gui_mch_enable_menu(int flag)
-{
-#ifdef FEAT_MENU
- SetMenu(s_hwnd, flag ? s_menuBar : NULL);
-#endif
-}
-
-/*ARGSUSED*/
- void
-gui_mch_set_menu_pos(
- int x,
- int y,
- int w,
- int h)
-{
- /* It will be in the right place anyway */
-}
-
-#if defined(FEAT_MENU) || defined(PROTO)
-/*
- * Make menu item hidden or not hidden
- */
- void
-gui_mch_menu_hidden(
- vimmenu_T *menu,
- int hidden)
-{
- /*
- * This doesn't do what we want. Hmm, just grey the menu items for now.
- */
- /*
- if (hidden)
- EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_DISABLED);
- else
- EnableMenuItem(s_menuBar, menu->id, MF_BYCOMMAND | MF_ENABLED);
- */
- gui_mch_menu_grey(menu, hidden);
-}
-
-/*
- * This is called after setting all the menus to grey/hidden or not.
- */
- void
-gui_mch_draw_menubar(void)
-{
- DrawMenuBar(s_hwnd);
-}
-#endif /*FEAT_MENU*/
-
-#ifndef PROTO
-void
-#ifdef VIMDLL
-_export
-#endif
-_cdecl
-SaveInst(HINSTANCE hInst)
-{
- s_hinst = hInst;
-}
-#endif
-
-/*
- * Return the RGB value of a pixel as a long.
- */
- long_u
-gui_mch_get_rgb(guicolor_T pixel)
-{
- return (GetRValue(pixel) << 16) + (GetGValue(pixel) << 8)
- + GetBValue(pixel);
-}
-
-#if defined(FEAT_GUI_DIALOG) || defined(PROTO)
-/* Convert pixels in X to dialog units */
- static WORD
-PixelToDialogX(int numPixels)
-{
- return (WORD)((numPixels * 4) / s_dlgfntwidth);
-}
-
-/* Convert pixels in Y to dialog units */
- static WORD
-PixelToDialogY(int numPixels)
-{
- return (WORD)((numPixels * 8) / s_dlgfntheight);
-}
-
-/* Return the width in pixels of the given text in the given DC. */
- static int
-GetTextWidth(HDC hdc, char_u *str, int len)
-{
- SIZE size;
-
- GetTextExtentPoint(hdc, (LPCSTR)str, len, &size);
- return size.cx;
-}
-
-#ifdef FEAT_MBYTE
-/*
- * Return the width in pixels of the given text in the given DC, taking care
- * of 'encoding' to active codepage conversion.
- */
- static int
-GetTextWidthEnc(HDC hdc, char_u *str, int len)
-{
- SIZE size;
- WCHAR *wstr;
- int n;
- int wlen = len;
-
- if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
- {
- /* 'encoding' differs from active codepage: convert text and use wide
- * function */
- wstr = enc_to_utf16(str, &wlen);
- if (wstr != NULL)
- {
- n = GetTextExtentPointW(hdc, wstr, wlen, &size);
- vim_free(wstr);
- if (n)
- return size.cx;
- }
- }
-
- return GetTextWidth(hdc, str, len);
-}
-#else
-# define GetTextWidthEnc(h, s, l) GetTextWidth((h), (s), (l))
-#endif
-
-/*
- * A quick little routine that will center one window over another, handy for
- * dialog boxes. Taken from the Win32SDK samples.
- */
- static BOOL
-CenterWindow(
- HWND hwndChild,
- HWND hwndParent)
-{
- RECT rChild, rParent;
- int wChild, hChild, wParent, hParent;
- int wScreen, hScreen, xNew, yNew;
- HDC hdc;
-
- GetWindowRect(hwndChild, &rChild);
- wChild = rChild.right - rChild.left;
- hChild = rChild.bottom - rChild.top;
-
- /* If Vim is minimized put the window in the middle of the screen. */
- if (hwndParent == NULL || IsMinimized(hwndParent))
- {
-#ifdef WIN16
- rParent.left = 0;
- rParent.top = 0;
- rParent.right = GetSystemMetrics(SM_CXSCREEN);
- rParent.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
-#else
- SystemParametersInfo(SPI_GETWORKAREA, 0, &rParent, 0);
-#endif
- }
- else
- GetWindowRect(hwndParent, &rParent);
- wParent = rParent.right - rParent.left;
- hParent = rParent.bottom - rParent.top;
-
- hdc = GetDC(hwndChild);
- wScreen = GetDeviceCaps (hdc, HORZRES);
- hScreen = GetDeviceCaps (hdc, VERTRES);
- ReleaseDC(hwndChild, hdc);
-
- xNew = rParent.left + ((wParent - wChild) /2);
- if (xNew < 0)
- {
- xNew = 0;
- }
- else if ((xNew+wChild) > wScreen)
- {
- xNew = wScreen - wChild;
- }
-
- yNew = rParent.top + ((hParent - hChild) /2);
- if (yNew < 0)
- yNew = 0;
- else if ((yNew+hChild) > hScreen)
- yNew = hScreen - hChild;
-
- return SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0,
- SWP_NOSIZE | SWP_NOZORDER);
-}
-#endif /* FEAT_GUI_DIALOG */
-
-void
-gui_mch_activate_window(void)
-{
- (void)SetActiveWindow(s_hwnd);
-}
-
-#if defined(FEAT_TOOLBAR) || defined(PROTO)
- void
-gui_mch_show_toolbar(int showit)
-{
- if (s_toolbarhwnd == NULL)
- return;
-
- if (showit)
- {
-# ifdef FEAT_MBYTE
-# ifndef TB_SETUNICODEFORMAT
- /* For older compilers. We assume this never changes. */
-# define TB_SETUNICODEFORMAT 0x2005
-# endif
- /* Enable/disable unicode support */
- int uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage);
- SendMessage(s_toolbarhwnd, TB_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0);
-# endif
- ShowWindow(s_toolbarhwnd, SW_SHOW);
- }
- else
- ShowWindow(s_toolbarhwnd, SW_HIDE);
-}
-
-/* Then number of bitmaps is fixed. Exit is missing! */
-#define TOOLBAR_BITMAP_COUNT 31
-
-#endif
-
-#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
- static void
-add_tabline_popup_menu_entry(HMENU pmenu, UINT item_id, char_u *item_text)
-{
-#ifdef FEAT_MBYTE
- WCHAR *wn = NULL;
- int n;
-
- if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
- {
- /* 'encoding' differs from active codepage: convert menu name
- * and use wide function */
- wn = enc_to_utf16(item_text, NULL);
- if (wn != NULL)
- {
- MENUITEMINFOW infow;
-
- infow.cbSize = sizeof(infow);
- infow.fMask = MIIM_TYPE | MIIM_ID;
- infow.wID = item_id;
- infow.fType = MFT_STRING;
- infow.dwTypeData = wn;
- infow.cch = (UINT)wcslen(wn);
- n = InsertMenuItemW(pmenu, item_id, FALSE, &infow);
- vim_free(wn);
- if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- /* Failed, try using non-wide function. */
- wn = NULL;
- }
- }
-
- if (wn == NULL)
-#endif
- {
- MENUITEMINFO info;
-
- info.cbSize = sizeof(info);
- info.fMask = MIIM_TYPE | MIIM_ID;
- info.wID = item_id;
- info.fType = MFT_STRING;
- info.dwTypeData = (LPTSTR)item_text;
- info.cch = (UINT)STRLEN(item_text);
- InsertMenuItem(pmenu, item_id, FALSE, &info);
- }
-}
-
- static void
-show_tabline_popup_menu(void)
-{
- HMENU tab_pmenu;
- long rval;
- POINT pt;
-
- /* When ignoring events don't show the menu. */
- if (hold_gui_events
-# ifdef FEAT_CMDWIN
- || cmdwin_type != 0
-# endif
- )
- return;
-
- tab_pmenu = CreatePopupMenu();
- if (tab_pmenu == NULL)
- return;
-
- if (first_tabpage->tp_next != NULL)
- add_tabline_popup_menu_entry(tab_pmenu,
- TABLINE_MENU_CLOSE, (char_u *)_("Close tab"));
- add_tabline_popup_menu_entry(tab_pmenu,
- TABLINE_MENU_NEW, (char_u *)_("New tab"));
- add_tabline_popup_menu_entry(tab_pmenu,
- TABLINE_MENU_OPEN, (char_u *)_("Open tab..."));
-
- GetCursorPos(&pt);
- rval = TrackPopupMenuEx(tab_pmenu, TPM_RETURNCMD, pt.x, pt.y, s_tabhwnd,
- NULL);
-
- DestroyMenu(tab_pmenu);
-
- /* Add the string cmd into input buffer */
- if (rval > 0)
- {
- TCHITTESTINFO htinfo;
- int idx;
-
- if (ScreenToClient(s_tabhwnd, &pt) == 0)
- return;
-
- htinfo.pt.x = pt.x;
- htinfo.pt.y = pt.y;
- idx = TabCtrl_HitTest(s_tabhwnd, &htinfo);
- if (idx == -1)
- idx = 0;
- else
- idx += 1;
-
- send_tabline_menu_event(idx, (int)rval);
- }
-}
-
-/*
- * Show or hide the tabline.
- */
- void
-gui_mch_show_tabline(int showit)
-{
- if (s_tabhwnd == NULL)
- return;
-
- if (!showit != !showing_tabline)
- {
- if (showit)
- ShowWindow(s_tabhwnd, SW_SHOW);
- else
- ShowWindow(s_tabhwnd, SW_HIDE);
- showing_tabline = showit;
- }
-}
-
-/*
- * Return TRUE when tabline is displayed.
- */
- int
-gui_mch_showing_tabline(void)
-{
- return s_tabhwnd != NULL && showing_tabline;
-}
-
-/*
- * Update the labels of the tabline.
- */
- void
-gui_mch_update_tabline(void)
-{
- tabpage_T *tp;
- TCITEM tie;
- int nr = 0;
- int curtabidx = 0;
- int tabadded = 0;
-#ifdef FEAT_MBYTE
- static int use_unicode = FALSE;
- int uu;
- WCHAR *wstr = NULL;
-#endif
-
- if (s_tabhwnd == NULL)
- return;
-
-#if defined(FEAT_MBYTE)
-# ifndef CCM_SETUNICODEFORMAT
- /* For older compilers. We assume this never changes. */
-# define CCM_SETUNICODEFORMAT 0x2005
-# endif
- uu = (enc_codepage >= 0 && (int)GetACP() != enc_codepage);
- if (uu != use_unicode)
- {
- /* Enable/disable unicode support */
- SendMessage(s_tabhwnd, CCM_SETUNICODEFORMAT, (WPARAM)uu, (LPARAM)0);
- use_unicode = uu;
- }
-#endif
-
- tie.mask = TCIF_TEXT;
- tie.iImage = -1;
-
- /* Disable redraw for tab updates to eliminate O(N^2) draws. */
- SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)FALSE, 0);
-
- /* Add a label for each tab page. They all contain the same text area. */
- for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
- {
- if (tp == curtab)
- curtabidx = nr;
-
- if (nr >= TabCtrl_GetItemCount(s_tabhwnd))
- {
- /* Add the tab */
- tie.pszText = "-Empty-";
- TabCtrl_InsertItem(s_tabhwnd, nr, &tie);
- tabadded = 1;
- }
-
- get_tabline_label(tp, FALSE);
- tie.pszText = (LPSTR)NameBuff;
-#ifdef FEAT_MBYTE
- wstr = NULL;
- if (use_unicode)
- {
- /* Need to go through Unicode. */
- wstr = enc_to_utf16(NameBuff, NULL);
- if (wstr != NULL)
- {
- TCITEMW tiw;
-
- tiw.mask = TCIF_TEXT;
- tiw.iImage = -1;
- tiw.pszText = wstr;
- SendMessage(s_tabhwnd, TCM_SETITEMW, (WPARAM)nr, (LPARAM)&tiw);
- vim_free(wstr);
- }
- }
- if (wstr == NULL)
-#endif
- {
- TabCtrl_SetItem(s_tabhwnd, nr, &tie);
- }
- }
-
- /* Remove any old labels. */
- while (nr < TabCtrl_GetItemCount(s_tabhwnd))
- TabCtrl_DeleteItem(s_tabhwnd, nr);
-
- if (!tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx)
- TabCtrl_SetCurSel(s_tabhwnd, curtabidx);
-
- /* Re-enable redraw and redraw. */
- SendMessage(s_tabhwnd, WM_SETREDRAW, (WPARAM)TRUE, 0);
- RedrawWindow(s_tabhwnd, NULL, NULL,
- RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
-
- if (tabadded && TabCtrl_GetCurSel(s_tabhwnd) != curtabidx)
- TabCtrl_SetCurSel(s_tabhwnd, curtabidx);
-}
-
-/*
- * Set the current tab to "nr". First tab is 1.
- */
- void
-gui_mch_set_curtab(int nr)
-{
- if (s_tabhwnd == NULL)
- return;
-
- if (TabCtrl_GetCurSel(s_tabhwnd) != nr - 1)
- TabCtrl_SetCurSel(s_tabhwnd, nr - 1);
-}
-
-#endif
-
-/*
- * ":simalt" command.
- */
- void
-ex_simalt(exarg_T *eap)
-{
- char_u *keys = eap->arg;
-
- PostMessage(s_hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)0);
- while (*keys)
- {
- if (*keys == '~')
- *keys = ' '; /* for showing system menu */
- PostMessage(s_hwnd, WM_CHAR, (WPARAM)*keys, (LPARAM)0);
- keys++;
- }
-}
-
-/*
- * Create the find & replace dialogs.
- * You can't have both at once: ":find" when replace is showing, destroys
- * the replace dialog first, and the other way around.
- */
-#ifdef MSWIN_FIND_REPLACE
- static void
-initialise_findrep(char_u *initial_string)
-{
- int wword = FALSE;
- int mcase = !p_ic;
- char_u *entry_text;
-
- /* Get the search string to use. */
- entry_text = get_find_dialog_text(initial_string, &wword, &mcase);
-
- s_findrep_struct.hwndOwner = s_hwnd;
- s_findrep_struct.Flags = FR_DOWN;
- if (mcase)
- s_findrep_struct.Flags |= FR_MATCHCASE;
- if (wword)
- s_findrep_struct.Flags |= FR_WHOLEWORD;
- if (entry_text != NULL && *entry_text != NUL)
- vim_strncpy((char_u *)s_findrep_struct.lpstrFindWhat, entry_text,
- s_findrep_struct.wFindWhatLen - 1);
- vim_free(entry_text);
-}
-#endif
-
- static void
-set_window_title(HWND hwnd, char *title)
-{
-#ifdef FEAT_MBYTE
- if (title != NULL && enc_codepage >= 0 && enc_codepage != (int)GetACP())
- {
- WCHAR *wbuf;
- int n;
-
- /* Convert the title from 'encoding' to UTF-16. */
- wbuf = (WCHAR *)enc_to_utf16((char_u *)title, NULL);
- if (wbuf != NULL)
- {
- n = SetWindowTextW(hwnd, wbuf);
- vim_free(wbuf);
- if (n != 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
- return;
- /* Retry with non-wide function (for Windows 98). */
- }
- }
-#endif
- (void)SetWindowText(hwnd, (LPCSTR)title);
-}
-
- void
-gui_mch_find_dialog(exarg_T *eap)
-{
-#ifdef MSWIN_FIND_REPLACE
- if (s_findrep_msg != 0)
- {
- if (IsWindow(s_findrep_hwnd) && !s_findrep_is_find)
- DestroyWindow(s_findrep_hwnd);
-
- if (!IsWindow(s_findrep_hwnd))
- {
- initialise_findrep(eap->arg);
-# if defined(FEAT_MBYTE) && defined(WIN3264)
- /* If the OS is Windows NT, and 'encoding' differs from active
- * codepage: convert text and use wide function. */
- if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
- && enc_codepage >= 0 && (int)GetACP() != enc_codepage)
- {
- findrep_atow(&s_findrep_struct_w, &s_findrep_struct);
- s_findrep_hwnd = FindTextW(
- (LPFINDREPLACEW) &s_findrep_struct_w);
- }
- else
-# endif
- s_findrep_hwnd = FindText((LPFINDREPLACE) &s_findrep_struct);
- }
-
- set_window_title(s_findrep_hwnd,
- _("Find string (use '\\\\' to find a '\\')"));
- (void)SetFocus(s_findrep_hwnd);
-
- s_findrep_is_find = TRUE;
- }
-#endif
-}
-
-
- void
-gui_mch_replace_dialog(exarg_T *eap)
-{
-#ifdef MSWIN_FIND_REPLACE
- if (s_findrep_msg != 0)
- {
- if (IsWindow(s_findrep_hwnd) && s_findrep_is_find)
- DestroyWindow(s_findrep_hwnd);
-
- if (!IsWindow(s_findrep_hwnd))
- {
- initialise_findrep(eap->arg);
-# if defined(FEAT_MBYTE) && defined(WIN3264)
- if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
- && enc_codepage >= 0 && (int)GetACP() != enc_codepage)
- {
- findrep_atow(&s_findrep_struct_w, &s_findrep_struct);
- s_findrep_hwnd = ReplaceTextW(
- (LPFINDREPLACEW) &s_findrep_struct_w);
- }
- else
-# endif
- s_findrep_hwnd = ReplaceText(
- (LPFINDREPLACE) &s_findrep_struct);
- }
-
- set_window_title(s_findrep_hwnd,
- _("Find & Replace (use '\\\\' to find a '\\')"));
- (void)SetFocus(s_findrep_hwnd);
-
- s_findrep_is_find = FALSE;
- }
-#endif
-}
-
-
-/*
- * Set visibility of the pointer.
- */
- void
-gui_mch_mousehide(int hide)
-{
- if (hide != gui.pointer_hidden)
- {
- ShowCursor(!hide);
- gui.pointer_hidden = hide;
- }
-}
-
-#ifdef FEAT_MENU
- static void
-gui_mch_show_popupmenu_at(vimmenu_T *menu, int x, int y)
-{
- /* Unhide the mouse, we don't get move events here. */
- gui_mch_mousehide(FALSE);
-
- (void)TrackPopupMenu(
- (HMENU)menu->submenu_id,
- TPM_LEFTALIGN | TPM_LEFTBUTTON,
- x, y,
- (int)0, /*reserved param*/
- s_hwnd,
- NULL);
- /*
- * NOTE: The pop-up menu can eat the mouse up event.
- * We deal with this in normal.c.
- */
-}
-#endif
-
-/*
- * Got a message when the system will go down.
- */
- static void
-_OnEndSession(void)
-{
- getout_preserve_modified(1);
-}
-
-/*
- * Get this message when the user clicks on the cross in the top right corner
- * of a Windows95 window.
- */
-/*ARGSUSED*/
- static void
-_OnClose(
- HWND hwnd)
-{
- gui_shell_closed();
-}
-
-/*
- * Get a message when the window is being destroyed.
- */
- static void
-_OnDestroy(
- HWND hwnd)
-{
-#ifdef WIN16_3DLOOK
- Ctl3dUnregister(s_hinst);
-#endif
- if (!destroying)
- _OnClose(hwnd);
-}
-
- static void
-_OnPaint(
- HWND hwnd)
-{
- if (!IsMinimized(hwnd))
- {
- PAINTSTRUCT ps;
-
- out_flush(); /* make sure all output has been processed */
- (void)BeginPaint(hwnd, &ps);
-#if defined(FEAT_DIRECTX)
- if (IS_ENABLE_DIRECTX())
- DWriteContext_BeginDraw(s_dwc);
-#endif
-
-#ifdef FEAT_MBYTE
- /* prevent multi-byte characters from misprinting on an invalid
- * rectangle */
- if (has_mbyte)
- {
- RECT rect;
-
- GetClientRect(hwnd, &rect);
- ps.rcPaint.left = rect.left;
- ps.rcPaint.right = rect.right;
- }
-#endif
-
- if (!IsRectEmpty(&ps.rcPaint))
- {
-#if defined(FEAT_DIRECTX)
- if (IS_ENABLE_DIRECTX())
- DWriteContext_BindDC(s_dwc, s_hdc, &ps.rcPaint);
-#endif
- gui_redraw(ps.rcPaint.left, ps.rcPaint.top,
- ps.rcPaint.right - ps.rcPaint.left + 1,
- ps.rcPaint.bottom - ps.rcPaint.top + 1);
- }
-
-#if defined(FEAT_DIRECTX)
- if (IS_ENABLE_DIRECTX())
- DWriteContext_EndDraw(s_dwc);
-#endif
- EndPaint(hwnd, &ps);
- }
-}
-
-/*ARGSUSED*/
- static void
-_OnSize(
- HWND hwnd,
- UINT state,
- int cx,
- int cy)
-{
- if (!IsMinimized(hwnd))
- {
- gui_resize_shell(cx, cy);
-
-#ifdef FEAT_MENU
- /* Menu bar may wrap differently now */
- gui_mswin_get_menu_height(TRUE);
-#endif
- }
-}
-
- static void
-_OnSetFocus(
- HWND hwnd,
- HWND hwndOldFocus)
-{
- gui_focus_change(TRUE);
- s_getting_focus = TRUE;
- (void)MyWindowProc(hwnd, WM_SETFOCUS, (WPARAM)hwndOldFocus, 0);
-}
-
- static void
-_OnKillFocus(
- HWND hwnd,
- HWND hwndNewFocus)
-{
- gui_focus_change(FALSE);
- s_getting_focus = FALSE;
- (void)MyWindowProc(hwnd, WM_KILLFOCUS, (WPARAM)hwndNewFocus, 0);
-}
-
-/*
- * Get a message when the user switches back to vim
- */
-#ifdef WIN16
- static BOOL
-#else
- static LRESULT
-#endif
-_OnActivateApp(
- HWND hwnd,
- BOOL fActivate,
-#ifdef WIN16
- HTASK dwThreadId
-#else
- DWORD dwThreadId
-#endif
- )
-{
- /* we call gui_focus_change() in _OnSetFocus() */
- /* gui_focus_change((int)fActivate); */
- return MyWindowProc(hwnd, WM_ACTIVATEAPP, fActivate, (DWORD)dwThreadId);
-}
-
-#if defined(FEAT_WINDOWS) || defined(PROTO)
- void
-gui_mch_destroy_scrollbar(scrollbar_T *sb)
-{
- DestroyWindow(sb->id);
-}
-#endif
-
-/*
- * Get current mouse coordinates in text window.
- */
- void
-gui_mch_getmouse(int *x, int *y)
-{
- RECT rct;
- POINT mp;
-
- (void)GetWindowRect(s_textArea, &rct);
- (void)GetCursorPos((LPPOINT)&mp);
- *x = (int)(mp.x - rct.left);
- *y = (int)(mp.y - rct.top);
-}
-
-/*
- * Move mouse pointer to character at (x, y).
- */
- void
-gui_mch_setmouse(int x, int y)
-{
- RECT rct;
-
- (void)GetWindowRect(s_textArea, &rct);
- (void)SetCursorPos(x + gui.border_offset + rct.left,
- y + gui.border_offset + rct.top);
-}
-
- static void
-gui_mswin_get_valid_dimensions(
- int w,
- int h,
- int *valid_w,
- int *valid_h)
-{
- int base_width, base_height;
-
- base_width = gui_get_base_width()
- + (GetSystemMetrics(SM_CXFRAME) +
- GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
- base_height = gui_get_base_height()
- + (GetSystemMetrics(SM_CYFRAME) +
- GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
- + GetSystemMetrics(SM_CYCAPTION)
-#ifdef FEAT_MENU
- + gui_mswin_get_menu_height(FALSE)
-#endif
- ;
- *valid_w = base_width +
- ((w - base_width) / gui.char_width) * gui.char_width;
- *valid_h = base_height +
- ((h - base_height) / gui.char_height) * gui.char_height;
-}
-
- void
-gui_mch_flash(int msec)
-{
- RECT rc;
-
- /*
- * Note: InvertRect() excludes right and bottom of rectangle.
- */
- rc.left = 0;
- rc.top = 0;
- rc.right = gui.num_cols * gui.char_width;
- rc.bottom = gui.num_rows * gui.char_height;
- InvertRect(s_hdc, &rc);
- gui_mch_flush(); /* make sure it's displayed */
-
- ui_delay((long)msec, TRUE); /* wait for a few msec */
-
- InvertRect(s_hdc, &rc);
-}
-
-/*
- * Return flags used for scrolling.
- * The SW_INVALIDATE is required when part of the window is covered or
- * off-screen. Refer to MS KB Q75236.
- */
- static int
-get_scroll_flags(void)
-{
- HWND hwnd;
- RECT rcVim, rcOther, rcDest;
-
- GetWindowRect(s_hwnd, &rcVim);
-
- /* Check if the window is partly above or below the screen. We don't care
- * about partly left or right of the screen, it is not relevant when
- * scrolling up or down. */
- if (rcVim.top < 0 || rcVim.bottom > GetSystemMetrics(SM_CYFULLSCREEN))
- return SW_INVALIDATE;
-
- /* Check if there is an window (partly) on top of us. */
- for (hwnd = s_hwnd; (hwnd = GetWindow(hwnd, GW_HWNDPREV)) != (HWND)0; )
- if (IsWindowVisible(hwnd))
- {
- GetWindowRect(hwnd, &rcOther);
- if (IntersectRect(&rcDest, &rcVim, &rcOther))
- return SW_INVALIDATE;
- }
- return 0;
-}
-
-/*
- * On some Intel GPUs, the regions drawn just prior to ScrollWindowEx()
- * may not be scrolled out properly.
- * For gVim, when _OnScroll() is repeated, the character at the
- * previous cursor position may be left drawn after scroll.
- * The problem can be avoided by calling GetPixel() to get a pixel in
- * the region before ScrollWindowEx().
- */
- static void
-intel_gpu_workaround(void)
-{
- GetPixel(s_hdc, FILL_X(gui.col), FILL_Y(gui.row));
-}
-
-/*
- * Delete the given number of lines from the given row, scrolling up any
- * text further down within the scroll region.
- */
- void
-gui_mch_delete_lines(
- int row,
- int num_lines)
-{
- RECT rc;
-
- intel_gpu_workaround();
-
- rc.left = FILL_X(gui.scroll_region_left);
- rc.right = FILL_X(gui.scroll_region_right + 1);
- rc.top = FILL_Y(row);
- rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
-
- ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
- &rc, &rc, NULL, NULL, get_scroll_flags());
-
- UpdateWindow(s_textArea);
- /* This seems to be required to avoid the cursor disappearing when
- * scrolling such that the cursor ends up in the top-left character on
- * the screen... But why? (Webb) */
- /* It's probably fixed by disabling drawing the cursor while scrolling. */
- /* gui.cursor_is_valid = FALSE; */
-
- gui_clear_block(gui.scroll_region_bot - num_lines + 1,
- gui.scroll_region_left,
- gui.scroll_region_bot, gui.scroll_region_right);
-}
-
-/*
- * Insert the given number of lines before the given row, scrolling down any
- * following text within the scroll region.
- */
- void
-gui_mch_insert_lines(
- int row,
- int num_lines)
-{
- RECT rc;
-
- intel_gpu_workaround();
-
- rc.left = FILL_X(gui.scroll_region_left);
- rc.right = FILL_X(gui.scroll_region_right + 1);
- rc.top = FILL_Y(row);
- rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
- /* The SW_INVALIDATE is required when part of the window is covered or
- * off-screen. How do we avoid it when it's not needed? */
- ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
- &rc, &rc, NULL, NULL, get_scroll_flags());
-
- UpdateWindow(s_textArea);
-
- gui_clear_block(row, gui.scroll_region_left,
- row + num_lines - 1, gui.scroll_region_right);
-}
-
-
-/*ARGSUSED*/
- void
-gui_mch_exit(int rc)
-{
-#if defined(FEAT_DIRECTX)
- DWriteContext_Close(s_dwc);
- DWrite_Final();
- s_dwc = NULL;
-#endif
-
- ReleaseDC(s_textArea, s_hdc);
- DeleteObject(s_brush);
-
-#ifdef FEAT_TEAROFF
- /* Unload the tearoff bitmap */
- (void)DeleteObject((HGDIOBJ)s_htearbitmap);
-#endif
-
- /* Destroy our window (if we have one). */
- if (s_hwnd != NULL)
- {
- destroying = TRUE; /* ignore WM_DESTROY message now */
- DestroyWindow(s_hwnd);
- }
-
-#ifdef GLOBAL_IME
- global_ime_end();
-#endif
-}
-
- static char_u *
-logfont2name(LOGFONT lf)
-{
- char *p;
- char *res;
- char *charset_name;
- char *font_name = lf.lfFaceName;
-
- charset_name = charset_id2name((int)lf.lfCharSet);
-#ifdef FEAT_MBYTE
- /* Convert a font name from the current codepage to 'encoding'.
- * TODO: Use Wide APIs (including LOGFONTW) instead of ANSI APIs. */
- if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
- {
- int len;
- acp_to_enc((char_u *)lf.lfFaceName, (int)strlen(lf.lfFaceName),
- (char_u **)&font_name, &len);
- }
-#endif
- res = (char *)alloc((unsigned)(strlen(font_name) + 20
- + (charset_name == NULL ? 0 : strlen(charset_name) + 2)));
- if (res != NULL)
- {
- p = res;
- /* make a normal font string out of the lf thing:*/
- sprintf((char *)p, "%s:h%d", font_name, pixels_to_points(
- lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight, TRUE));
- while (*p)
- {
- if (*p == ' ')
- *p = '_';
- ++p;
- }
-#ifndef MSWIN16_FASTTEXT
- if (lf.lfItalic)
- STRCAT(p, ":i");
- if (lf.lfWeight >= FW_BOLD)
- STRCAT(p, ":b");
-#endif
- if (lf.lfUnderline)
- STRCAT(p, ":u");
- if (lf.lfStrikeOut)
- STRCAT(p, ":s");
- if (charset_name != NULL)
- {
- STRCAT(p, ":c");
- STRCAT(p, charset_name);
- }
- }
-
-#ifdef FEAT_MBYTE
- if (font_name != lf.lfFaceName)
- vim_free(font_name);
-#endif
- return (char_u *)res;
-}
-
-
-#ifdef FEAT_MBYTE_IME
-/*
- * Set correct LOGFONT to IME. Use 'guifontwide' if available, otherwise use
- * 'guifont'
- */
- static void
-update_im_font(void)
-{
- LOGFONT lf_wide;
-
- if (p_guifontwide != NULL && *p_guifontwide != NUL
- && gui.wide_font != NOFONT
- && GetObject((HFONT)gui.wide_font, sizeof(lf_wide), &lf_wide))
- norm_logfont = lf_wide;
- else
- norm_logfont = sub_logfont;
- im_set_font(&norm_logfont);
-}
-#endif
-
-#ifdef FEAT_MBYTE
-/*
- * Handler of gui.wide_font (p_guifontwide) changed notification.
- */
- void
-gui_mch_wide_font_changed(void)
-{
-# ifndef MSWIN16_FASTTEXT
- LOGFONT lf;
-# endif
-
-# ifdef FEAT_MBYTE_IME
- update_im_font();
-# endif
-
-# ifndef MSWIN16_FASTTEXT
- gui_mch_free_font(gui.wide_ital_font);
- gui.wide_ital_font = NOFONT;
- gui_mch_free_font(gui.wide_bold_font);
- gui.wide_bold_font = NOFONT;
- gui_mch_free_font(gui.wide_boldital_font);
- gui.wide_boldital_font = NOFONT;
-
- if (gui.wide_font
- && GetObject((HFONT)gui.wide_font, sizeof(lf), &lf))
- {
- if (!lf.lfItalic)
- {
- lf.lfItalic = TRUE;
- gui.wide_ital_font = get_font_handle(&lf);
- lf.lfItalic = FALSE;
- }
- if (lf.lfWeight < FW_BOLD)
- {
- lf.lfWeight = FW_BOLD;
- gui.wide_bold_font = get_font_handle(&lf);
- if (!lf.lfItalic)
- {
- lf.lfItalic = TRUE;
- gui.wide_boldital_font = get_font_handle(&lf);
- }
- }
- }
-# endif
-}
-#endif
-
-/*
- * Initialise vim to use the font with the given name.
- * Return FAIL if the font could not be loaded, OK otherwise.
- */
-/*ARGSUSED*/
- int
-gui_mch_init_font(char_u *font_name, int fontset)
-{
- LOGFONT lf;
- GuiFont font = NOFONT;
- char_u *p;
-
- /* Load the font */
- if (get_logfont(&lf, font_name, NULL, TRUE) == OK)
- font = get_font_handle(&lf);
- if (font == NOFONT)
- return FAIL;
-
- if (font_name == NULL)
- font_name = (char_u *)lf.lfFaceName;
-#if defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME)
- norm_logfont = lf;
- sub_logfont = lf;
-#endif
-#ifdef FEAT_MBYTE_IME
- update_im_font();
-#endif
- gui_mch_free_font(gui.norm_font);
- gui.norm_font = font;
- current_font_height = lf.lfHeight;
- GetFontSize(font);
-
- p = logfont2name(lf);
- if (p != NULL)
- {
- hl_set_font_name(p);
-
- /* When setting 'guifont' to "*" replace it with the actual font name.
- * */
- if (STRCMP(font_name, "*") == 0 && STRCMP(p_guifont, "*") == 0)
- {
- vim_free(p_guifont);
- p_guifont = p;
- }
- else
- vim_free(p);
- }
-
-#ifndef MSWIN16_FASTTEXT
- gui_mch_free_font(gui.ital_font);
- gui.ital_font = NOFONT;
- gui_mch_free_font(gui.bold_font);
- gui.bold_font = NOFONT;
- gui_mch_free_font(gui.boldital_font);
- gui.boldital_font = NOFONT;
-
- if (!lf.lfItalic)
- {
- lf.lfItalic = TRUE;
- gui.ital_font = get_font_handle(&lf);
- lf.lfItalic = FALSE;
- }
- if (lf.lfWeight < FW_BOLD)
- {
- lf.lfWeight = FW_BOLD;
- gui.bold_font = get_font_handle(&lf);
- if (!lf.lfItalic)
- {
- lf.lfItalic = TRUE;
- gui.boldital_font = get_font_handle(&lf);
- }
- }
-#endif
-
- return OK;
-}
-
-#ifndef WPF_RESTORETOMAXIMIZED
-# define WPF_RESTORETOMAXIMIZED 2 /* just in case someone doesn't have it */
-#endif
-
-/*
- * Return TRUE if the GUI window is maximized, filling the whole screen.
- */
- int
-gui_mch_maximized(void)
-{
- WINDOWPLACEMENT wp;
-
- wp.length = sizeof(WINDOWPLACEMENT);
- if (GetWindowPlacement(s_hwnd, &wp))
- return wp.showCmd == SW_SHOWMAXIMIZED
- || (wp.showCmd == SW_SHOWMINIMIZED
- && wp.flags == WPF_RESTORETOMAXIMIZED);
-
- return 0;
-}
-
-/*
- * Called when the font changed while the window is maximized. Compute the
- * new Rows and Columns. This is like resizing the window.
- */
- void
-gui_mch_newfont(void)
-{
- RECT rect;
-
- GetWindowRect(s_hwnd, &rect);
- if (win_socket_id == 0)
- {
- gui_resize_shell(rect.right - rect.left
- - (GetSystemMetrics(SM_CXFRAME) +
- GetSystemMetrics(SM_CXPADDEDBORDER)) * 2,
- rect.bottom - rect.top
- - (GetSystemMetrics(SM_CYFRAME) +
- GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
- - GetSystemMetrics(SM_CYCAPTION)
-#ifdef FEAT_MENU
- - gui_mswin_get_menu_height(FALSE)
-#endif
- );
- }
- else
- {
- /* Inside another window, don't use the frame and border. */
- gui_resize_shell(rect.right - rect.left,
- rect.bottom - rect.top
-#ifdef FEAT_MENU
- - gui_mswin_get_menu_height(FALSE)
-#endif
- );
- }
-}
-
-/*
- * Set the window title
- */
-/*ARGSUSED*/
- void
-gui_mch_settitle(
- char_u *title,
- char_u *icon)
-{
- set_window_title(s_hwnd, (title == NULL ? "VIM" : (char *)title));
-}
-
-#ifdef FEAT_MOUSESHAPE
-/* Table for shape IDCs. Keep in sync with the mshape_names[] table in
- * misc2.c! */
-static LPCSTR mshape_idcs[] =
-{
- IDC_ARROW, /* arrow */
- MAKEINTRESOURCE(0), /* blank */
- IDC_IBEAM, /* beam */
- IDC_SIZENS, /* updown */
- IDC_SIZENS, /* udsizing */
- IDC_SIZEWE, /* leftright */
- IDC_SIZEWE, /* lrsizing */
- IDC_WAIT, /* busy */
-#ifdef WIN3264
- IDC_NO, /* no */
-#else
- IDC_ICON, /* no */
-#endif
- IDC_ARROW, /* crosshair */
- IDC_ARROW, /* hand1 */
- IDC_ARROW, /* hand2 */
- IDC_ARROW, /* pencil */
- IDC_ARROW, /* question */
- IDC_ARROW, /* right-arrow */
- IDC_UPARROW, /* up-arrow */
- IDC_ARROW /* last one */
-};
-
- void
-mch_set_mouse_shape(int shape)
-{
- LPCSTR idc;
-
- if (shape == MSHAPE_HIDE)
- ShowCursor(FALSE);
- else
- {
- if (shape >= MSHAPE_NUMBERED)
- idc = IDC_ARROW;
- else
- idc = mshape_idcs[shape];
-#ifdef SetClassLongPtr
- SetClassLongPtr(s_textArea, GCLP_HCURSOR, (__int3264)(LONG_PTR)LoadCursor(NULL, idc));
-#else
-# ifdef WIN32
- SetClassLong(s_textArea, GCL_HCURSOR, (long_u)LoadCursor(NULL, idc));
-# else /* Win16 */
- SetClassWord(s_textArea, GCW_HCURSOR, (WORD)LoadCursor(NULL, idc));
-# endif
-#endif
- if (!p_mh)
- {
- POINT mp;
-
- /* Set the position to make it redrawn with the new shape. */
- (void)GetCursorPos((LPPOINT)&mp);
- (void)SetCursorPos(mp.x, mp.y);
- ShowCursor(TRUE);
- }
- }
-}
-#endif
-
-#ifdef FEAT_BROWSE
-/*
- * The file browser exists in two versions: with "W" uses wide characters,
- * without "W" the current codepage. When FEAT_MBYTE is defined and on
- * Windows NT/2000/XP the "W" functions are used.
- */
-
-# if defined(FEAT_MBYTE) && defined(WIN3264)
-/*
- * Wide version of convert_filter().
- */
- static WCHAR *
-convert_filterW(char_u *s)
-{
- char_u *tmp;
- int len;
- WCHAR *res;
-
- tmp = convert_filter(s);
- if (tmp == NULL)
- return NULL;
- len = (int)STRLEN(s) + 3;
- res = enc_to_utf16(tmp, &len);
- vim_free(tmp);
- return res;
-}
-
-/*
- * Wide version of gui_mch_browse(). Keep in sync!
- */
- static char_u *
-gui_mch_browseW(
- int saving,
- char_u *title,
- char_u *dflt,
- char_u *ext,
- char_u *initdir,
- char_u *filter)
-{
- /* We always use the wide function. This means enc_to_utf16() must work,
- * otherwise it fails miserably! */
- OPENFILENAMEW fileStruct;
- WCHAR fileBuf[MAXPATHL];
- WCHAR *wp;
- int i;
- WCHAR *titlep = NULL;
- WCHAR *extp = NULL;
- WCHAR *initdirp = NULL;
- WCHAR *filterp;
- char_u *p;
-
- if (dflt == NULL)
- fileBuf[0] = NUL;
- else
- {
- wp = enc_to_utf16(dflt, NULL);
- if (wp == NULL)
- fileBuf[0] = NUL;
- else
- {
- for (i = 0; wp[i] != NUL && i < MAXPATHL - 1; ++i)
- fileBuf[i] = wp[i];
- fileBuf[i] = NUL;
- vim_free(wp);
- }
- }
-
- /* Convert the filter to Windows format. */
- filterp = convert_filterW(filter);
-
- vim_memset(&fileStruct, 0, sizeof(OPENFILENAMEW));
-#ifdef OPENFILENAME_SIZE_VERSION_400
- /* be compatible with Windows NT 4.0 */
- /* TODO: what to use for OPENFILENAMEW??? */
- fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400;
-#else
- fileStruct.lStructSize = sizeof(fileStruct);
-#endif
-
- if (title != NULL)
- titlep = enc_to_utf16(title, NULL);
- fileStruct.lpstrTitle = titlep;
-
- if (ext != NULL)
- extp = enc_to_utf16(ext, NULL);
- fileStruct.lpstrDefExt = extp;
-
- fileStruct.lpstrFile = fileBuf;
- fileStruct.nMaxFile = MAXPATHL;
- fileStruct.lpstrFilter = filterp;
- fileStruct.hwndOwner = s_hwnd; /* main Vim window is owner*/
- /* has an initial dir been specified? */
- if (initdir != NULL && *initdir != NUL)
- {
- /* Must have backslashes here, no matter what 'shellslash' says */
- initdirp = enc_to_utf16(initdir, NULL);
- if (initdirp != NULL)
- {
- for (wp = initdirp; *wp != NUL; ++wp)
- if (*wp == '/')
- *wp = '\\';
- }
- fileStruct.lpstrInitialDir = initdirp;
- }
-
- /*
- * TODO: Allow selection of multiple files. Needs another arg to this
- * function to ask for it, and need to use OFN_ALLOWMULTISELECT below.
- * Also, should we use OFN_FILEMUSTEXIST when opening? Vim can edit on
- * files that don't exist yet, so I haven't put it in. What about
- * OFN_PATHMUSTEXIST?
- * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog.
- */
- fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY);
-#ifdef FEAT_SHORTCUT
- if (curbuf->b_p_bin)
- fileStruct.Flags |= OFN_NODEREFERENCELINKS;
-#endif
- if (saving)
- {
- if (!GetSaveFileNameW(&fileStruct))
- return NULL;
- }
- else
- {
- if (!GetOpenFileNameW(&fileStruct))
- return NULL;
- }
-
- vim_free(filterp);
- vim_free(initdirp);
- vim_free(titlep);
- vim_free(extp);
-
- /* Convert from UCS2 to 'encoding'. */
- p = utf16_to_enc(fileBuf, NULL);
- if (p != NULL)
- /* when out of memory we get garbage for non-ASCII chars */
- STRCPY(fileBuf, p);
- vim_free(p);
-
- /* Give focus back to main window (when using MDI). */
- SetFocus(s_hwnd);
-
- /* Shorten the file name if possible */
- return vim_strsave(shorten_fname1((char_u *)fileBuf));
-}
-# endif /* FEAT_MBYTE */
-
-
-/*
- * Convert the string s to the proper format for a filter string by replacing
- * the \t and \n delimiters with \0.
- * Returns the converted string in allocated memory.
- *
- * Keep in sync with convert_filterW() above!
- */
- static char_u *
-convert_filter(char_u *s)
-{
- char_u *res;
- unsigned s_len = (unsigned)STRLEN(s);
- unsigned i;
-
- res = alloc(s_len + 3);
- if (res != NULL)
- {
- for (i = 0; i < s_len; ++i)
- if (s[i] == '\t' || s[i] == '\n')
- res[i] = '\0';
- else
- res[i] = s[i];
- res[s_len] = NUL;
- /* Add two extra NULs to make sure it's properly terminated. */
- res[s_len + 1] = NUL;
- res[s_len + 2] = NUL;
- }
- return res;
-}
-
-/*
- * Select a directory.
- */
- char_u *
-gui_mch_browsedir(char_u *title, char_u *initdir)
-{
- /* We fake this: Use a filter that doesn't select anything and a default
- * file name that won't be used. */
- return gui_mch_browse(0, title, (char_u *)_("Not Used"), NULL,
- initdir, (char_u *)_("Directory\t*.nothing\n"));
-}
-
-/*
- * Pop open a file browser and return the file selected, in allocated memory,
- * or NULL if Cancel is hit.
- * saving - TRUE if the file will be saved to, FALSE if it will be opened.
- * title - Title message for the file browser dialog.
- * dflt - Default name of file.
- * ext - Default extension to be added to files without extensions.
- * initdir - directory in which to open the browser (NULL = current dir)
- * filter - Filter for matched files to choose from.
- *
- * Keep in sync with gui_mch_browseW() above!
- */
- char_u *
-gui_mch_browse(
- int saving,
- char_u *title,
- char_u *dflt,
- char_u *ext,
- char_u *initdir,
- char_u *filter)
-{
- OPENFILENAME fileStruct;
- char_u fileBuf[MAXPATHL];
- char_u *initdirp = NULL;
- char_u *filterp;
- char_u *p;
-
-# if defined(FEAT_MBYTE) && defined(WIN3264)
- if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)
- return gui_mch_browseW(saving, title, dflt, ext, initdir, filter);
-# endif
-
- if (dflt == NULL)
- fileBuf[0] = NUL;
- else
- vim_strncpy(fileBuf, dflt, MAXPATHL - 1);
-
- /* Convert the filter to Windows format. */
- filterp = convert_filter(filter);
-
- vim_memset(&fileStruct, 0, sizeof(OPENFILENAME));
-#ifdef OPENFILENAME_SIZE_VERSION_400
- /* be compatible with Windows NT 4.0 */
- fileStruct.lStructSize = OPENFILENAME_SIZE_VERSION_400;
-#else
- fileStruct.lStructSize = sizeof(fileStruct);
-#endif
-
- fileStruct.lpstrTitle = (LPSTR)title;
- fileStruct.lpstrDefExt = (LPSTR)ext;
-
- fileStruct.lpstrFile = (LPSTR)fileBuf;
- fileStruct.nMaxFile = MAXPATHL;
- fileStruct.lpstrFilter = (LPSTR)filterp;
- fileStruct.hwndOwner = s_hwnd; /* main Vim window is owner*/
- /* has an initial dir been specified? */
- if (initdir != NULL && *initdir != NUL)
- {
- /* Must have backslashes here, no matter what 'shellslash' says */
- initdirp = vim_strsave(initdir);
- if (initdirp != NULL)
- for (p = initdirp; *p != NUL; ++p)
- if (*p == '/')
- *p = '\\';
- fileStruct.lpstrInitialDir = (LPSTR)initdirp;
- }
-
- /*
- * TODO: Allow selection of multiple files. Needs another arg to this
- * function to ask for it, and need to use OFN_ALLOWMULTISELECT below.
- * Also, should we use OFN_FILEMUSTEXIST when opening? Vim can edit on
- * files that don't exist yet, so I haven't put it in. What about
- * OFN_PATHMUSTEXIST?
- * Don't use OFN_OVERWRITEPROMPT, Vim has its own ":confirm" dialog.
- */
- fileStruct.Flags = (OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY);
-#ifdef FEAT_SHORTCUT
- if (curbuf->b_p_bin)
- fileStruct.Flags |= OFN_NODEREFERENCELINKS;
-#endif
- if (saving)
- {
- if (!GetSaveFileName(&fileStruct))
- return NULL;
- }
- else
- {
- if (!GetOpenFileName(&fileStruct))
- return NULL;
- }
-
- vim_free(filterp);
- vim_free(initdirp);
-
- /* Give focus back to main window (when using MDI). */
- SetFocus(s_hwnd);
-
- /* Shorten the file name if possible */
- return vim_strsave(shorten_fname1((char_u *)fileBuf));
-}
-#endif /* FEAT_BROWSE */
-
-/*ARGSUSED*/
- static void
-_OnDropFiles(
- HWND hwnd,
- HDROP hDrop)
-{
-#ifdef FEAT_WINDOWS
-#ifdef WIN3264
-# define BUFPATHLEN _MAX_PATH
-# define DRAGQVAL 0xFFFFFFFF
-#else
-# define BUFPATHLEN MAXPATHL
-# define DRAGQVAL 0xFFFF
-#endif
-#ifdef FEAT_MBYTE
- WCHAR wszFile[BUFPATHLEN];
-#endif
- char szFile[BUFPATHLEN];
- UINT cFiles = DragQueryFile(hDrop, DRAGQVAL, NULL, 0);
- UINT i;
- char_u **fnames;
- POINT pt;
- int_u modifiers = 0;
-
- /* TRACE("_OnDropFiles: %d files dropped\n", cFiles); */
-
- /* Obtain dropped position */
- DragQueryPoint(hDrop, &pt);
- MapWindowPoints(s_hwnd, s_textArea, &pt, 1);
-
- reset_VIsual();
-
- fnames = (char_u **)alloc(cFiles * sizeof(char_u *));
-
- if (fnames != NULL)
- for (i = 0; i < cFiles; ++i)
- {
-#ifdef FEAT_MBYTE
- if (DragQueryFileW(hDrop, i, wszFile, BUFPATHLEN) > 0)
- fnames[i] = utf16_to_enc(wszFile, NULL);
- else
-#endif
- {
- DragQueryFile(hDrop, i, szFile, BUFPATHLEN);
- fnames[i] = vim_strsave((char_u *)szFile);
- }
- }
-
- DragFinish(hDrop);
-
- if (fnames != NULL)
- {
- if ((GetKeyState(VK_SHIFT) & 0x8000) != 0)
- modifiers |= MOUSE_SHIFT;
- if ((GetKeyState(VK_CONTROL) & 0x8000) != 0)
- modifiers |= MOUSE_CTRL;
- if ((GetKeyState(VK_MENU) & 0x8000) != 0)
- modifiers |= MOUSE_ALT;
-
- gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles);
-
- s_need_activate = TRUE;
- }
-#endif
-}
-
-/*ARGSUSED*/
- static int
-_OnScroll(
- HWND hwnd,
- HWND hwndCtl,
- UINT code,
- int pos)
-{
- static UINT prev_code = 0; /* code of previous call */
- scrollbar_T *sb, *sb_info;
- long val;
- int dragging = FALSE;
- int dont_scroll_save = dont_scroll;
-#ifndef WIN3264
- int nPos;
-#else
- SCROLLINFO si;
-
- si.cbSize = sizeof(si);
- si.fMask = SIF_POS;
-#endif
-
- sb = gui_mswin_find_scrollbar(hwndCtl);
- if (sb == NULL)
- return 0;
-
- if (sb->wp != NULL) /* Left or right scrollbar */
- {
- /*
- * Careful: need to get scrollbar info out of first (left) scrollbar
- * for window, but keep real scrollbar too because we must pass it to
- * gui_drag_scrollbar().
- */
- sb_info = &sb->wp->w_scrollbars[0];
- }
- else /* Bottom scrollbar */
- sb_info = sb;
- val = sb_info->value;
-
- switch (code)
- {
- case SB_THUMBTRACK:
- val = pos;
- dragging = TRUE;
- if (sb->scroll_shift > 0)
- val <<= sb->scroll_shift;
- break;
- case SB_LINEDOWN:
- val++;
- break;
- case SB_LINEUP:
- val--;
- break;
- case SB_PAGEDOWN:
- val += (sb_info->size > 2 ? sb_info->size - 2 : 1);
- break;
- case SB_PAGEUP:
- val -= (sb_info->size > 2 ? sb_info->size - 2 : 1);
- break;
- case SB_TOP:
- val = 0;
- break;
- case SB_BOTTOM:
- val = sb_info->max;
- break;
- case SB_ENDSCROLL:
- if (prev_code == SB_THUMBTRACK)
- {
- /*
- * "pos" only gives us 16-bit data. In case of large file,
- * use GetScrollPos() which returns 32-bit. Unfortunately it
- * is not valid while the scrollbar is being dragged.
- */
- val = GetScrollPos(hwndCtl, SB_CTL);
- if (sb->scroll_shift > 0)
- val <<= sb->scroll_shift;
- }
- break;
-
- default:
- /* TRACE("Unknown scrollbar event %d\n", code); */
- return 0;
- }
- prev_code = code;
-
-#ifdef WIN3264
- si.nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val;
- SetScrollInfo(hwndCtl, SB_CTL, &si, TRUE);
-#else
- nPos = (sb->scroll_shift > 0) ? val >> sb->scroll_shift : val;
- SetScrollPos(hwndCtl, SB_CTL, nPos, TRUE);
-#endif
-
- /*
- * When moving a vertical scrollbar, move the other vertical scrollbar too.
- */
- if (sb->wp != NULL)
- {
- scrollbar_T *sba = sb->wp->w_scrollbars;
- HWND id = sba[ (sb == sba + SBAR_LEFT) ? SBAR_RIGHT : SBAR_LEFT].id;
-
-#ifdef WIN3264
- SetScrollInfo(id, SB_CTL, &si, TRUE);
-#else
- SetScrollPos(id, SB_CTL, nPos, TRUE);
-#endif
- }
-
- /* Don't let us be interrupted here by another message. */
- s_busy_processing = TRUE;
-
- /* When "allow_scrollbar" is FALSE still need to remember the new
- * position, but don't actually scroll by setting "dont_scroll". */
- dont_scroll = !allow_scrollbar;
-
- gui_drag_scrollbar(sb, val, dragging);
-
- s_busy_processing = FALSE;
- dont_scroll = dont_scroll_save;
-
- return 0;
-}
-
-
-/*
- * Get command line arguments.
- * Use "prog" as the name of the program and "cmdline" as the arguments.
- * Copy the arguments to allocated memory.
- * Return the number of arguments (including program name).
- * Return pointers to the arguments in "argvp". Memory is allocated with
- * malloc(), use free() instead of vim_free().
- * Return pointer to buffer in "tofree".
- * Returns zero when out of memory.
- */
-/*ARGSUSED*/
- int
-get_cmd_args(char *prog, char *cmdline, char ***argvp, char **tofree)
-{
- int i;
- char *p;
- char *progp;
- char *pnew = NULL;
- char *newcmdline;
- int inquote;
- int argc;
- char **argv = NULL;
- int round;
-
- *tofree = NULL;
-
-#ifdef FEAT_MBYTE
- /* Try using the Unicode version first, it takes care of conversion when
- * 'encoding' is changed. */
- argc = get_cmd_argsW(&argv);
- if (argc != 0)
- goto done;
-#endif
-
- /* Handle the program name. Remove the ".exe" extension, and find the 1st
- * non-space. */
- p = strrchr(prog, '.');
- if (p != NULL)
- *p = NUL;
- for (progp = prog; *progp == ' '; ++progp)
- ;
-
- /* The command line is copied to allocated memory, so that we can change
- * it. Add the size of the string, the separating NUL and a terminating
- * NUL. */
- newcmdline = malloc(STRLEN(cmdline) + STRLEN(progp) + 2);
- if (newcmdline == NULL)
- return 0;
-
- /*
- * First round: count the number of arguments ("pnew" == NULL).
- * Second round: produce the arguments.
- */
- for (round = 1; round <= 2; ++round)
- {
- /* First argument is the program name. */
- if (pnew != NULL)
- {
- argv[0] = pnew;
- strcpy(pnew, progp);
- pnew += strlen(pnew);
- *pnew++ = NUL;
- }
-
- /*
- * Isolate each argument and put it in argv[].
- */
- p = cmdline;
- argc = 1;
- while (*p != NUL)
- {
- inquote = FALSE;
- if (pnew != NULL)
- argv[argc] = pnew;
- ++argc;
- while (*p != NUL && (inquote || (*p != ' ' && *p != '\t')))
- {
- /* Backslashes are only special when followed by a double
- * quote. */
- i = (int)strspn(p, "\\");
- if (p[i] == '"')
- {
- /* Halve the number of backslashes. */
- if (i > 1 && pnew != NULL)
- {
- vim_memset(pnew, '\\', i / 2);
- pnew += i / 2;
- }
-
- /* Even nr of backslashes toggles quoting, uneven copies
- * the double quote. */
- if ((i & 1) == 0)
- inquote = !inquote;
- else if (pnew != NULL)
- *pnew++ = '"';
- p += i + 1;
- }
- else if (i > 0)
- {
- /* Copy span of backslashes unmodified. */
- if (pnew != NULL)
- {
- vim_memset(pnew, '\\', i);
- pnew += i;
- }
- p += i;
- }
- else
- {
- if (pnew != NULL)
- *pnew++ = *p;
-#ifdef FEAT_MBYTE
- /* Can't use mb_* functions, because 'encoding' is not
- * initialized yet here. */
- if (IsDBCSLeadByte(*p))
- {
- ++p;
- if (pnew != NULL)
- *pnew++ = *p;
- }
-#endif
- ++p;
- }
- }
-
- if (pnew != NULL)
- *pnew++ = NUL;
- while (*p == ' ' || *p == '\t')
- ++p; /* advance until a non-space */
- }
-
- if (round == 1)
- {
- argv = (char **)malloc((argc + 1) * sizeof(char *));
- if (argv == NULL )
- {
- free(newcmdline);
- return 0; /* malloc error */
- }
- pnew = newcmdline;
- *tofree = newcmdline;
- }
- }
-
-#ifdef FEAT_MBYTE
-done:
-#endif
- argv[argc] = NULL; /* NULL-terminated list */
- *argvp = argv;
- return argc;
-}