📄 gui_w32.c
字号:
break;
default:
/* TRACE("Unknown scrollbar event %d\n", code); */
return 0;
}
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
if (scroll_shift > 0)
si.nPos = val >> scroll_shift;
else
si.nPos = val;
SetScrollInfo(hwndCtl, SB_CTL, &si, TRUE);
/*
* When moving a vertical scrollbar, move the other vertical scrollbar too.
*/
if (sb->wp != NULL)
{
if (sb == &sb->wp->w_scrollbars[SBAR_LEFT])
SetScrollInfo(sb->wp->w_scrollbars[SBAR_RIGHT].id,
SB_CTL, &si, TRUE);
else
SetScrollInfo(sb->wp->w_scrollbars[SBAR_LEFT].id,
SB_CTL, &si, TRUE);
}
/*
* Scrollbars seem to grab focus and vim doesn't read the input queue until
* you stop dragging the scrollbar. We get here each time the scrollbar is
* dragged another pixel, but as far as the rest of vim goes, it thinks
* we're just hanging in the call to DispatchMessage() in
* process_message(). The DispatchMessage() call that hangs was passed a
* mouse button click event in the scrollbar window. -- webb.
*
* Solution: Do the scrolling right here. But only when allowed.
* Ignore the scrollbars while executing an external command or when there
* are still characters to be processed.
*/
if (dont_scroll || !termcap_active || !vim_is_input_buf_empty())
return 0;
if (dragging)
{
if (sb->wp == NULL)
gui.dragged_sb = SBAR_BOTTOM;
else if (sb == &sb->wp->w_scrollbars[SBAR_LEFT])
gui.dragged_sb = SBAR_LEFT;
else
gui.dragged_sb = SBAR_RIGHT;
gui.dragged_wp = sb->wp;
}
else
gui.dragged_sb = SBAR_NONE;
/* Vertical sbar info is kept in the first sbar (the left one) */
if (sb->wp != NULL)
sb = &sb->wp->w_scrollbars[0];
/*
* Check validity of value
*/
if (val < 0)
val = 0;
if (val > sb->max - sb->size + 1)
val = sb->max - sb->size + 1;
sb->value = val;
#ifdef RIGHTLEFT
if (sb->wp == NULL && curwin->w_p_rl)
{
val = sb->max + 1 - sb->size - val;
if (val < 0)
val = 0;
}
#endif
scrollbar_value = val;
if (sb->wp != NULL) /* vertical scrollbar */
{
current_scrollbar = 0;
for (wp = firstwin; wp != sb->wp && wp != NULL; wp = wp->w_next)
current_scrollbar++;
if (wp == NULL)
return 0;
if (State & NORMAL)
{
gui_do_scroll();
setcursor();
}
else if (State & INSERT)
{
ins_scroll();
setcursor();
}
else if (State & CMDLINE)
{
if (!msg_scrolled)
{
gui_do_scroll();
redrawcmdline();
}
}
}
else
{
colnr_t old_leftcol = curwin->w_leftcol;
if (State & NORMAL)
gui_do_horiz_scroll();
else if (State & INSERT)
ins_horscroll();
else if (State & CMDLINE)
{
if (!msg_scrolled)
{
gui_do_horiz_scroll();
redrawcmdline();
}
}
if (old_leftcol != curwin->w_leftcol)
{
updateWindow(curwin); /* update window, status line and cmdline */
setcursor();
}
}
out_flush();
return 0;
}
/*
* Setup for the Intellimouse
*/
static void
init_mouse_wheel(void)
{
#ifndef SPI_GETWHEELSCROLLLINES
# define SPI_GETWHEELSCROLLLINES 104
#endif
#define VMOUSEZ_CLASSNAME "MouseZ" /* hidden wheel window class */
#define VMOUSEZ_TITLE "Magellan MSWHEEL" /* hidden wheel window title */
#define VMSH_MOUSEWHEEL "MSWHEEL_ROLLMSG"
#define VMSH_SCROLL_LINES "MSH_SCROLL_LINES_MSG"
HWND hdl_mswheel;
UINT msh_msgscrolllines;
msh_msgmousewheel = 0;
mouse_scroll_lines = 3; /* reasonable default */
if (os_version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
|| (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
&& os_version.dwMajorVersion < 4))
{ /*
* If Win95 or NT 3.51,
* try to find the hidden point32 window.
*/
hdl_mswheel = FindWindow(VMOUSEZ_CLASSNAME, VMOUSEZ_TITLE);
if (hdl_mswheel)
{
msh_msgscrolllines = RegisterWindowMessage(VMSH_SCROLL_LINES);
if (msh_msgscrolllines)
{
mouse_scroll_lines = SendMessage(hdl_mswheel,
msh_msgscrolllines, 0, 0);
msh_msgmousewheel = RegisterWindowMessage(VMSH_MOUSEWHEEL);
}
}
}
else if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT
&& os_version.dwMajorVersion >= 4)
{
/* if NT 4.0 (or Win98) get scroll lines directly from system */
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
&mouse_scroll_lines, 0);
}
}
/* Intellimouse wheel handler */
static void
_OnMouseWheel(
HWND hwnd,
short zDelta)
{
/* Treat a mouse wheel event as if it were a scroll request */
int i;
int size;
HWND hwndCtl;
if (curwin->w_scrollbars[SBAR_RIGHT].id != 0)
{
hwndCtl = curwin->w_scrollbars[SBAR_RIGHT].id;
size = curwin->w_scrollbars[SBAR_RIGHT].size;
}
else if (curwin->w_scrollbars[SBAR_LEFT].id != 0)
{
hwndCtl = curwin->w_scrollbars[SBAR_LEFT].id;
size = curwin->w_scrollbars[SBAR_LEFT].size;
}
else
return;
size = curwin->w_height;
if (mouse_scroll_lines == 0)
init_mouse_wheel();
if (mouse_scroll_lines > 0
&& mouse_scroll_lines < (size > 2 ? size - 2 : 1))
{
for (i = mouse_scroll_lines; i > 0; --i)
_OnScroll(hwnd, hwndCtl, zDelta >= 0 ? SB_LINEUP : SB_LINEDOWN, 0);
}
else
_OnScroll(hwnd, hwndCtl, zDelta >= 0 ? SB_PAGEUP : SB_PAGEDOWN, 0);
}
/*
* Get current x mouse coordinate in text window.
* Return -1 when unknown.
*/
int
gui_mch_get_mouse_x(void)
{
RECT rct;
POINT mp;
if (GetWindowRect(s_textArea, &rct))
{
if (GetCursorPos((LPPOINT)&mp))
return (int)(mp.x - rct.left);
}
return -1;
}
/*
* Get current y mouse coordinate in text window.
* Return -1 when unknown.
*/
int
gui_mch_get_mouse_y(void)
{
RECT rct;
POINT mp;
if (GetWindowRect(s_textArea, &rct))
{
if (GetCursorPos((LPPOINT)&mp))
return (int)(mp.y - rct.top);
}
return -1;
}
/*
* Move mouse pointer to character at (x, y).
*/
void
gui_mch_setmouse(int x, int y)
{
RECT rct;
if (GetWindowRect(s_textArea, &rct))
(void)SetCursorPos(x + gui.border_offset + rct.left,
y + gui.border_offset + rct.top);
}
static void
gui_w32_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_CXSIZEFRAME) * 2;
base_height = gui_get_base_height()
+ GetSystemMetrics(SM_CYSIZEFRAME) * 2
+ GetSystemMetrics(SM_CYCAPTION)
+ gui_w32_get_menu_height(FALSE);
*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;
}
/*
* Even though we have _DuringSizing() which makes the rubber band a valid
* size, we need this for when the user maximises the window.
* TODO: Doesn't seem to adjust the width though for some reason.
*/
static BOOL
_OnWindowPosChanging(
HWND hwnd,
LPWINDOWPOS lpwpos)
{
if (!(lpwpos->flags & SWP_NOSIZE))
{
gui_w32_get_valid_dimensions(lpwpos->cx, lpwpos->cy,
&lpwpos->cx, &lpwpos->cy);
}
return 0;
}
static int
_DuringSizing(
HWND hwnd,
UINT fwSide,
LPRECT lprc)
{
int w, h;
int valid_w, valid_h;
int w_offset, h_offset;
w = lprc->right - lprc->left;
h = lprc->bottom - lprc->top;
gui_w32_get_valid_dimensions(w, h, &valid_w, &valid_h);
w_offset = w - valid_w;
h_offset = h - valid_h;
if (fwSide == WMSZ_LEFT || fwSide == WMSZ_TOPLEFT
|| fwSide == WMSZ_BOTTOMLEFT)
lprc->left += w_offset;
else if (fwSide == WMSZ_RIGHT || fwSide == WMSZ_TOPRIGHT
|| fwSide == WMSZ_BOTTOMRIGHT)
lprc->right -= w_offset;
if (fwSide == WMSZ_TOP || fwSide == WMSZ_TOPLEFT
|| fwSide == WMSZ_TOPRIGHT)
lprc->top += h_offset;
else if (fwSide == WMSZ_BOTTOM || fwSide == WMSZ_BOTTOMLEFT
|| fwSide == WMSZ_BOTTOMRIGHT)
lprc->bottom -= h_offset;
return TRUE;
}
/*
* Erase parts of the window that are not redrawn.
* Draw the rectangle just under the left and/or right scrollbars.
*/
static void
_OnEraseBG(HWND hwnd)
{
HDC hdc = GetDC(hwnd);
RECT rect, drect;
WIN *wp;
GetClientRect(hwnd, &rect);
/* Draw blank rectangles for hidden scrollbars */
for (wp = firstwin; wp; wp = wp->w_next)
{
if (wp->w_height == 0)
{
drect.top = rect.bottom - gui.char_height * (Rows - wp->w_winpos);
if (gui.which_scrollbars[SBAR_BOTTOM])
drect.top -= gui.scrollbar_height;
drect.bottom = drect.top + gui.char_height;
if (gui.which_scrollbars[SBAR_LEFT])
{
drect.left = 0;
drect.right = gui.scrollbar_width;
FillRect(hdc, &drect, GetSysColorBrush(COLOR_BTNFACE));
}
if (gui.which_scrollbars[SBAR_RIGHT])
{
drect.left = rect.right - gui.scrollbar_width;
drect.right = rect.right;
FillRect(hdc, &drect, GetSysColorBrush(COLOR_BTNFACE));
}
}
}
/* draw the rectangle below vertical scrollbars */
/* top of the rectangle is just below the last window */
drect.top = rect.bottom - gui.char_height
* (Rows - (lastwin->w_winpos + lastwin->w_height));
drect.top += lastwin->w_status_height * gui.char_height;
if (gui.which_scrollbars[SBAR_BOTTOM])
drect.top -= gui.scrollbar_height;
drect.bottom = rect.bottom;
if (gui.which_scrollbars[SBAR_LEFT])
{
drect.left = 0;
drect.right = gui.scrollbar_width;
FillRect(hdc, &drect, GetSysColorBrush(COLOR_BTNFACE));
}
if (gui.which_scrollbars[SBAR_RIGHT])
{
drect.left = rect.right - gui.scrollbar_width;
drect.right = rect.right;
FillRect(hdc, &drect, GetSysColorBrush(COLOR_BTNFACE));
}
ReleaseDC(hwnd, hdc);
}
static BOOL
_OnCreate (HWND hwnd, LPCREATESTRUCT lpcs)
{
#ifdef MULTI_BYTE
/* get system fixed font size*/
static const char ach[] = {'W', 'f', 'g', 'M'};
HDC hdc = GetWindowDC(hwnd);
HFONT hfntOld = SelectFont(hdc, GetStockObject(SYSTEM_FIXED_FONT));
SIZE siz;
GetTextExtentPoint(hdc, ach, sizeof(ach), &siz);
sysfixed_width = siz.cx / sizeof(ach);
/*
* Make characters one pixel higher, so that italic and bold fonts don't
* draw off the bottom of their character space. Also means that we can
* underline an underscore for normal text.
*/
sysfixed_height = siz.cy + 1;
/* TRACE("GetFontSize: h %d, w %d\n", gui.char_height, gui.char_width); */
SelectFont(hdc, hfntOld);
ReleaseDC(hwnd, hdc);
#endif
return 0;
}
#ifdef WIN32_FIND_REPLACE
/*
* Handle a Find/Replace window message.
*/
static void
_OnFindRepl(void)
{
char_u cmd[600]; //XXX kludge
/* Add a char before the command if needed */
if (State & INSERT)
cmd[0] = Ctrl('O');
else if ((State | NORMAL) == 0 && State != CONFIRM)
cmd[0] = ESC;
else
cmd[0] = NUL;
cmd[1] = NUL;
if (s_findrep_struct.Flags & FR_DIALOGTERM)
{
if (State == CONFIRM)
{
add_to_input_buf("q", 1);
}
return;
}
if (s_findrep_struct.Flags & FR_FINDNEXT)
{
if (State == CONFIRM)
{
STRCAT(cmd, "n");
}
else
{
if (s_findrep_struct.Flags & FR_DOWN)
STRCAT(cmd, "/");
else
STRCAT(cmd, "?");
if (s_findrep_struct.Flags & FR_WHOLEWORD)
STRCAT(cmd, "\\<");
STRCAT(cmd, s_findrep_struct.lpstrFindWhat);
if (s_findrep_struct.Flags & FR_WHOLEWORD)
STRCAT(cmd, "\\>");
STRCAT(cmd, "\r");
}
/*
* 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)
{
if (State == CONFIRM)
{
STRCAT(cmd, "y");
}
else
{
STRCAT(cmd, ":%sno/");
STRCAT(cmd, s_findrep_struct.lpstrFindWhat);
STRCAT(cmd, "/");
STRCAT(cmd, s_findrep_struct.lpstrReplaceWith);
STRCAT(cmd, "/gc\r");
}
/*
* Give main window the focus back: this is to allow
* handling of the confirmation y/n/a/q stuff.
*/
(void)SetFocus(s_hwnd);
}
else if (s_findrep_struct.Flags & FR_REPLACEALL)
{
if (State == CONFIRM)
{
STRCAT(cmd, "a");
}
else
{
STRCAT(cmd, ":%sno/");
STRCAT(cmd, s_findrep_struct.lpstrFindWhat);
STRCAT(cmd, "/");
STRCAT(cmd, s_findrep_struct.lpstrReplaceWith);
STRCAT(cmd, "/g\r");
}
}
if (*cmd)
add_to_input_buf(cmd, STRLEN(cmd));
}
#endif
static void
HandleMouseHide(UINT uMsg, LPARAM lParam)
{
static LPARAM last_lParam = 0L;
/* We sometimes get a mousemove when the mouse didn't move... */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -