⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gui_w32.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:

/*
 * Get a message when the user switches back to vim
 */
    static void
_OnActivateApp(
    HWND hwnd,
    BOOL fActivate,
    DWORD dwThreadId)
{
    /* When activated: Check if any file was modified outside of Vim. */
    if (fActivate)
	check_timestamps();
}

/*
 * Get a message when the the window is being destroyed.
 */
    static void
_OnDestroy(
    HWND hwnd)
{
    if (!destroying)
	_OnClose(hwnd);
}

    static void
_OnDropFiles(
    HWND hwnd,
    HDROP hDrop)
{
    char    szFile[_MAX_PATH];
    UINT    cFiles = DragQueryFile(hDrop, 0xFFFFFFFF, szFile, _MAX_PATH);
    UINT    i;
    char_u  *fname;
    char_u  **fnames;
    char_u  redo_dirs = FALSE;

    /* TRACE("_OnDropFiles: %d files dropped\n", cFiles); */

    /* reset_VIsual(); */
    if (VIsual_active)
    {
	end_visual_mode();
	VIsual_reselect = FALSE;
	update_curbuf(NOT_VALID);	/* delete the inversion */
    }

    fnames = (char_u **) alloc(cFiles * sizeof(char_u *));

    for (i = 0; i < cFiles; ++i)
    {
	DragQueryFile(hDrop, i, szFile, _MAX_PATH);
	/* TRACE("  dropped %2u: '%s'\n", i, szFile); */

	mch_dirname(IObuff, IOSIZE);
	fname = shorten_fname(szFile, IObuff);
	if (fname == NULL)
	    fname = szFile;
	fnames[i] = vim_strsave(fname);
    }

    /*
     * Handle dropping a directory on Vim.
     */
    if (cFiles == 1)
    {
	if (mch_isdir(fnames[0]))
	{
	    if (mch_chdir(fnames[0]) == 0)
	    {
		vim_free(fnames[0]);
		fnames[0] = NULL;
		redo_dirs = TRUE;
	    }
	}
    }

    DragFinish(hDrop);

    if (GetKeyState(VK_SHIFT) & 0x8000)
    {
	/* Shift held down, change to first file's directory */
	if (vim_chdirfile(fnames[0]) == 0)
	{
	    redo_dirs = TRUE;
	}
    }

    /* Handle the drop, by resetting the :args list */
    handle_drop(cFiles, fnames);

    if (redo_dirs)
	shorten_fnames();

    /* Update the screen display */
    update_screen(NOT_VALID);
    setcursor();
    out_flush();
}

    static void
_OnDeadChar(
    HWND hwnd,
    UINT ch,
    int cRepeat)
{
    dead_key = 1;
}

    static void
_OnChar(
    HWND hwnd,
    UINT ch,
    int cRepeat)
{
    char_u	string[1];

    /* TRACE("OnChar(%d, %c)\n", ch, ch); */

    string[0] = ch;
    if (string[0] == Ctrl('C') && !mapped_ctrl_c)
    {
	trash_input_buf();
	got_int = TRUE;
    }
    add_to_input_buf(string, 1);
}

    static void
_OnSysChar(
    HWND hwnd,
    UINT ch,
    int cRepeat)
{
    char_u	string[6]; /* Enough for maximum key sequence - see below */
    int		len;
    int		modifiers;

    /* 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 */
    if (modifiers & MOD_MASK_ALT)
    {
	ch |= 0x80;
	modifiers &= ~MOD_MASK_ALT;
    }

    len = 0;
    if (modifiers)
    {
	string[len++] = CSI;
	string[len++] = KS_MODIFIER;
	string[len++] = modifiers;
    }
    if (IS_SPECIAL(ch))
    {
	string[len++] = CSI;
	string[len++] = K_SECOND(ch);
	string[len++] = K_THIRD(ch);
    }
    else
	string[len++] = ch;
    add_to_input_buf(string, len);
}

    static void
_OnMouseEvent(
    int button,
    int x,
    int y,
    int repeated_click,
    UINT keyFlags)
{
    int vim_modifiers = 0x0;

    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);
}

    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;

    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;
    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;
    }

    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;
    }
}

    static void
_OnMouseMoveOrRelease(
    HWND hwnd,
    int x,
    int y,
    UINT keyFlags)
{
    int button;

    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)))
	{
	    gui_mouse_moved(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);
}

    static void
_OnPaint(
    HWND hwnd)
{
    if (!IsMinimized(hwnd))
    {
	PAINTSTRUCT ps;
	HDC hdc;


	out_flush();	    /* make sure all output has been processed */
	hdc = BeginPaint(hwnd, &ps);

#ifdef MULTI_BYTE
	/* prevent multi-byte characters from misprinting on an invalid
	 * rectangle */
	if (is_dbcs)
	{
	    RECT rect;

	    GetClientRect(hwnd, &rect);
	    ps.rcPaint.left = rect.left;
	    ps.rcPaint.right = rect.right;
	}
#endif

	if (!IsRectEmpty(&ps.rcPaint))
	    gui_redraw(ps.rcPaint.left, ps.rcPaint.top,
		    ps.rcPaint.right - ps.rcPaint.left + 1,
		    ps.rcPaint.bottom - ps.rcPaint.top + 1);
	EndPaint(hwnd, &ps);
    }
}

    static void
_OnSize(
    HWND hwnd,
    UINT state,
    int cx,
    int cy)
{
    if (!IsMinimized(hwnd))
    {
	gui_resize_window(cx, cy);

	/* Menu bar may wrap differently now */
	gui_w32_get_menu_height(TRUE);
    }
}

    static void
_OnSetFocus(
    HWND hwnd,
    HWND hwndOldFocus)
{
    gui_focus_change(TRUE);
}

    static void
_OnKillFocus(
    HWND hwnd,
    HWND hwndNewFocus)
{
    gui_focus_change(FALSE);
}

/*
 * Find the GuiMenu with the given id
 */
    static GuiMenu *
gui_w32_find_menu(
    GuiMenu *pMenu,
    int id)
{
    GuiMenu *pChildMenu;

    while (pMenu)
    {
	if (pMenu->id == (UINT)id) /* && pMenu->submenu_id == NULL) */
	    break;
	if (pMenu->children != NULL)
	{
	    pChildMenu = gui_w32_find_menu(pMenu->children, id);
	    if (pChildMenu)
	    {
		pMenu = pChildMenu;
		break;
	    }
	}
	pMenu = pMenu->next;
    }
    return pMenu;
}

    static void
_OnMenu(
    HWND hwnd,
    int id,
    HWND hwndCtl,
    UINT codeNotify)
{
    GuiMenu *pMenu;

    pMenu = gui_w32_find_menu(gui.root_menu, id);
    if (pMenu)
	gui_menu_cb(pMenu);
}

/*
 * Find the scrollbar with the given hwnd.
 */
    static GuiScrollbar *
gui_w32_find_scrollbar(HWND hwnd)
{
    WIN		*wp;

    if (gui.bottom_sbar.id == hwnd)
	return &gui.bottom_sbar;
    for (wp = firstwin; wp != NULL; wp = wp->w_next)
    {
	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;
}

    static int
_OnScroll(
    HWND hwnd,
    HWND hwndCtl,
    UINT code,
    int pos)
{
    GuiScrollbar *sb, *sb_info;
    int		val;
    int		dragging = FALSE;
    SCROLLINFO	si;
    WIN		*wp;

    sb = gui_w32_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:
	    /* TRACE("SB_THUMBTRACK, %d\n", pos); */
	    val = pos;
	    dragging = TRUE;
	    if (scroll_shift > 0)
		val <<= scroll_shift;
	    break;
	case SB_LINEDOWN:
	    /* TRACE("SB_LINEDOWN\n"); */
	    val++;
	    break;
	case SB_LINEUP:
	    /* TRACE("SB_LINEUP\n"); */
	    val--;
	    break;
	case SB_PAGEDOWN:
	    /* TRACE("SB_PAGEDOWN\n"); */
	    val += (sb_info->size > 2 ? sb_info->size - 2 : 1);
	    break;
	case SB_PAGEUP:
	    /* TRACE("SB_PAGEUP\n"); */
	    val -= (sb_info->size > 2 ? sb_info->size - 2 : 1);
	    break;
	case SB_TOP:
	    /* TRACE("SB_TOP\n"); */
	    val = 0;
	    break;
	case SB_BOTTOM:
	    /* TRACE("SB_BOTTOM\n"); */
	    val = sb_info->max;
	    break;
	case SB_ENDSCROLL:
	    /*
	     * "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.
	     */
	    /* TRACE("SB_ENDSCROLL\n"); */
	    val = GetScrollPos(hwndCtl, SB_CTL);
	    if (scroll_shift > 0)
		val <<= scroll_shift;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -