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

📄 gui.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
    gui_outstr_nowrap(s, len, GUI_MON_WRAP_CURSOR, (GuiColor)0, (GuiColor)0, 0);
}

/*
 * Output the given string at the current cursor position.  If the string is
 * too long to fit on the line, then it is truncated.
 * "flags":
 * GUI_MON_WRAP_CURSOR may be used if the cursor position should be wrapped
 * when the end of the line is reached, however the string will still be
 * truncated and not continue on the next line.
 * GUI_MON_IS_CURSOR should only be used when this function is being called to
 * actually draw (an inverted) cursor.
 * GUI_MON_TRS_CURSOR is used to draw the cursor text with a transparant
 * background.
 */
    void
gui_outstr_nowrap(s, len, flags, fg, bg, back)
    char_u	*s;
    int		len;
    int		flags;
    GuiColor	fg, bg;	    /* colors for cursor */
    int		back;	    /* backup this many chars when using bold trick */
{
    long_u	    highlight_mask;
    GuiColor	    fg_color;
    GuiColor	    bg_color;
    GuiFont	    font;
    struct attr_entry *aep = NULL;
    int		    draw_flags;
    int		    col = gui.col;

    if (len == 0)
	return;

    if (len < 0)
	len = STRLEN(s);

    if (gui.highlight_mask > HL_ALL)
    {
	aep = syn_gui_attr2entry(gui.highlight_mask);
	if (aep == NULL)	    /* highlighting not set */
	    highlight_mask = 0;
	else
	    highlight_mask = aep->ae_attr;
    }
    else
	highlight_mask = gui.highlight_mask;

    /* Set the font */
    if (aep != NULL && aep->ae_u.gui.font != 0)
	font = aep->ae_u.gui.font;
    else
    {
	if ((highlight_mask & (HL_BOLD | HL_STANDOUT)) && gui.bold_font != 0)
	{
	    if ((highlight_mask & HL_ITALIC) && gui.boldital_font != 0)
		font = gui.boldital_font;
	    else
		font = gui.bold_font;
	}
	else if ((highlight_mask & HL_ITALIC) && gui.ital_font != 0)
	    font = gui.ital_font;
	else
	    font = gui.norm_font;
    }
    gui_mch_set_font(font);

    /* Set the color */
    bg_color = gui.back_pixel;
    if ((flags & GUI_MON_IS_CURSOR) && gui.in_focus)
    {
	fg_color = fg;
	bg_color = bg;
    }
    else if (aep != NULL)
    {
	fg_color = aep->ae_u.gui.fg_color;
	if (fg_color == 0)
	    fg_color = gui.norm_pixel;
	else
	    --fg_color;
	bg_color = aep->ae_u.gui.bg_color;
	if (bg_color == 0)
	    bg_color = gui.back_pixel;
	else
	    --bg_color;
    }
    else
	fg_color = gui.norm_pixel;

    if (highlight_mask & (HL_INVERSE | HL_STANDOUT))
    {
#if defined(AMIGA) || defined(RISCOS)
	gui_mch_set_colors(bg_color, fg_color);
#else
	gui_mch_set_fg_color(bg_color);
	gui_mch_set_bg_color(fg_color);
#endif
    }
    else
    {
#if defined(AMIGA) || defined(RISCOS)
	gui_mch_set_colors(fg_color, bg_color);
#else
	gui_mch_set_fg_color(fg_color);
	gui_mch_set_bg_color(bg_color);
#endif
    }

    /* Clear the selection if we are about to write over it */
    if (!(flags & GUI_MON_NOCLEAR))
	clip_may_clear_selection(gui.row, gui.row);

    draw_flags = 0;

    /* If there's no bold font, then fake it */
    if ((highlight_mask & (HL_BOLD | HL_STANDOUT)) &&
	    (gui.bold_font == 0 || (aep != NULL && aep->ae_u.gui.font != 0)))
    {
	draw_flags |= DRAW_BOLD;
	s -= back;
	len += back;
	col -= back;
    }

#ifdef RISCOS
    /* If there's no italic font, then fake it */
    if ((highlight_mask & HL_ITALIC) && gui.ital_font == 0)
	draw_flags |= DRAW_ITALIC;

    /* Do we underline the text? */
    if (highlight_mask & HL_UNDERLINE)
	draw_flags |= DRAW_UNDERL;
#else
    /* Do we underline the text? */
    if ((highlight_mask & HL_UNDERLINE) ||
	    ((highlight_mask & HL_ITALIC) && gui.ital_font == 0))
	draw_flags |= DRAW_UNDERL;
#endif

    /* Do we draw transparantly? */
    if ((flags & GUI_MON_TRS_CURSOR))
	draw_flags |= DRAW_TRANSP;

    /* Draw the text */
    gui_mch_draw_string(gui.row, col, s, len, draw_flags);

    /* May need to invert it when it's part of the selection (assumes len==1) */
    if (flags & GUI_MON_NOCLEAR)
	clip_may_redraw_selection(gui.row, col);

    if (!(flags & (GUI_MON_IS_CURSOR | GUI_MON_TRS_CURSOR)))
    {
	/* Invalidate the old physical cursor position if we wrote over it */
	if (gui.cursor_row == gui.row && gui.cursor_col >= col
		&& gui.cursor_col < col + len)
	    gui.cursor_is_valid = FALSE;

	/* Update the cursor position */
	gui.col = col + len;
	if ((flags & GUI_MON_WRAP_CURSOR) && gui.col >= Columns)
	{
	    gui.col = 0;
	    gui.row++;
	}
    }
}

/*
 * Un-draw the cursor.	Actually this just redraws the character at the given
 * position.  The character just before it too, for when it was in bold.
 */
    void
gui_undraw_cursor()
{
    if (gui.cursor_is_valid)
    {
	if (gui_redraw_block(gui.cursor_row, gui.cursor_col,
			      gui.cursor_row, gui.cursor_col, GUI_MON_NOCLEAR)
		&& gui.cursor_col > 0)
	    (void)gui_redraw_block(gui.cursor_row, gui.cursor_col - 1,
			 gui.cursor_row, gui.cursor_col - 1, GUI_MON_NOCLEAR);
    }
}

    void
gui_redraw(x, y, w, h)
    int	    x;
    int	    y;
    int	    w;
    int	    h;
{
    int	    row1, col1, row2, col2;

    row1 = Y_2_ROW(y);
    col1 = X_2_COL(x);
    row2 = Y_2_ROW(y + h - 1);
    col2 = X_2_COL(x + w - 1);

    (void)gui_redraw_block(row1, col1, row2, col2, 0);

    /*
     * We may need to redraw the cursor, but don't take it upon us to change
     * its location after a scroll.
     * (maybe be more strict even and test col too?)
     * These things may be outside the update/clipping region and reality may
     * not reflect Vims internal ideas if these operations are clipped away.
     */
    if (gui.row == gui.cursor_row)
	gui_update_cursor(FALSE, TRUE);

    if (clipboard.state != SELECT_CLEARED)
	clip_redraw_selection(x, y, w, h);
}

/*
 * Draw a rectangular block of characters, from row1 to row2 (inclusive) and
 * from col1 to col2 (inclusive).
 * Return TRUE when the character before the first drawn character has
 * different attributes (may have to be redrawn too).
 */
    int
gui_redraw_block(row1, col1, row2, col2, flags)
    int	    row1;
    int	    col1;
    int	    row2;
    int	    col2;
    int	    flags;	/* flags for gui_outstr_nowrap() */
{
    int	    old_row, old_col;
    long_u  old_hl_mask;
    char_u  *screenp, *attrp, first_attr;
    int	    idx, len;
    int	    back;
    int	    retval = FALSE;

    /* Don't try to update when NextScreen is not valid */
    if (!screen_cleared || NextScreen == NULL)
	return retval;

    /* Don't try to draw outside the window! */
    /* Check everything, strange values may be caused by big border width */
    col1 = check_col(col1);
    col2 = check_col(col2);
    row1 = check_row(row1);
    row2 = check_row(row2);

    /* Remember where our cursor was */
    old_row = gui.row;
    old_col = gui.col;
    old_hl_mask = gui.highlight_mask;

    for (gui.row = row1; gui.row <= row2; gui.row++)
    {
	gui.col = col1;
	screenp = LinePointers[gui.row] + gui.col;
	attrp = screenp + screen_Columns;
	len = col2 - col1 + 1;

	/* Find how many chars back this highlighting starts, or where a space
	 * is.  Needed for when the bold trick is used */
	for (back = 0; back < col1; ++back)
	    if (attrp[-1 - back] != attrp[0] || screenp[-1 - back] == ' ')
		break;
	retval = (col1 && attrp[-1] && back == 0);

	/* break it up in strings of characters with the same attributes */
	while (len > 0)
	{
	    first_attr = attrp[0];
	    for (idx = 0; len > 0 && attrp[idx] == first_attr; idx++)
		--len;
	    gui.highlight_mask = first_attr;
	    gui_outstr_nowrap(screenp, idx, flags,
					      (GuiColor)0, (GuiColor)0, back);
	    screenp += idx;
	    attrp += idx;
	    back = 0;
	}
    }

    /* Put the cursor back where it was */
    gui.row = old_row;
    gui.col = old_col;
    gui.highlight_mask = old_hl_mask;

    return retval;
}

    static void
gui_delete_lines(row, count)
    int	    row;
    int	    count;
{
    if (row == 0)
	clip_scroll_selection(count);
    gui_mch_delete_lines(row, count);
}

    static void
gui_insert_lines(row, count)
    int	    row;
    int	    count;
{
    if (row == 0)
	clip_scroll_selection(-count);
    gui_mch_insert_lines(row, count);
}

/*
 * Check bounds for column number
 */
    int
check_col(col)
    int	    col;
{
    if (col < 0)
	return 0;
    if (col >= (int)screen_Columns)
	return (int)screen_Columns - 1;
    return col;
}

/*
 * Check bounds for row number
 */
    int
check_row(row)
    int	    row;
{
    if (row < 0)
	return 0;
    if (row >= (int)screen_Rows)
	return (int)screen_Rows - 1;
    return row;
}

/*
 * The main GUI input routine.	Waits for a character from the keyboard.
 * wtime == -1	    Wait forever.
 * wtime == 0	    Don't wait.
 * 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_wait_for_chars(wtime)
    long    wtime;
{
    int	    retval;

    /*
     * If we're going to wait a bit, update the menus for the current
     * State.
     */
    if (wtime != 0)
	gui_update_menus(0);
    gui_mch_update();
    if (!vim_is_input_buf_empty())	/* Got char, return immediately */
	return OK;
    if (wtime == 0)	/* Don't wait for char */
	return FAIL;
    if (wtime > 0)
    {
	/* Blink when waiting for a character.	Probably only does something
	 * for showmatch() */
	gui_mch_start_blink();
	retval = gui_mch_wait_for_chars(wtime);
	gui_mch_stop_blink();
	return retval;
    }

    /*
     * While we are waiting indefenitely for a character, blink the cursor.
     */
    gui_mch_start_blink();
    if (gui_mch_wait_for_chars(p_ut) == OK)
	retval = OK;
    else
    {
	/*
	 * If no characters arrive within 'updatetime' milli-seconds, flush
	 * all the swap files to disk.
	 */
	updatescript(0);
	retval = gui_mch_wait_for_chars(-1L);
    }
    gui_mch_stop_blink();
    return retval;
}

/*
 * Generic mouse support function.  Add a mouse event to the input buffer with
 * the given properties.
 *  button	    --- may be any of MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT,
 *			MOUSE_DRAG, or MOUSE_RELEASE.
 *  x, y	    --- Coordinates of mouse in pixels.
 *  repeated_click  --- TRUE if this click comes only a short time after a
 *			previous click.
 *  modifiers	    --- Bit field which may be any of the following modifiers
 *			or'ed together: MOUSE_SHIFT | MOUSE_CTRL | MOUSE_ALT.
 * This function will ignore drag events where the mouse has not moved to a new
 * character.
 */
    void
gui_send_mouse_event(button, x, y, repeated_click, modifiers)
    int	    button;
    int	    x;
    int	    y;
    int	    repeated_click;
    int_u   modifiers;
{
    static int	    prev_row = 0, prev_col = 0;
    static int	    prev_button = -1;
    static int	    num_clicks = 1;
    char_u	    string[6];
    int		    row, col;

#ifdef USE_CLIPBOARD

    int		    checkfor;
    int		    did_clip = FALSE;

    /* If a clipboard selection is in progress, handle it */
    if (clipboard.state == SELECT_IN_PROGRESS)
    {
	clip_process_selection(button, x, y, repeated_click, modifiers);
	return;
    }

    /* Determine which mouse settings to look for based on the current mode */
    switch (get_real_state())
    {
	case NORMAL_BUSY:
	case OP_PENDING:
	case NORMAL:	    checkfor = MOUSE_NORMAL;	break;
	case VISUAL:	    checkfor = MOUSE_VISUAL;	break;
	case REPLACE:
	case INSERT:	    checkfor = MOUSE_INSERT;	break;
	case HITRETURN:	    checkfor = MOUSE_RETURN;	break;

	    /*
	     * On the command line, use the clipboard selection on all lines
	     * but the command line.  But not when pasting.
	     */
	case CMDLINE:
	    if (Y_2_ROW(y) < cmdline_row && button != MOUSE_MIDDLE)
		checkfor = ' ';
	    else
		checkfor = MOUSE_COMMAND;
	    break;

	default:
	    checkfor = ' ';
	    break;
    };

    /*
     * Allow clipboard selection of text on the command line in "normal"
     * modes.  Don't do this when dragging the status line, or extending a
     * Visual selection.
     */
    if ((State == NORMAL || State == NORMAL_BUSY
				       || State == INSERT || State == REPLACE)
	    && Y_2_ROW(y) >= gui.num_rows - p_ch
	    && button != MOUSE_DRAG)
	checkfor = ' ';

    /*
     * If the mouse settings say to not use the mouse, use the non-Visual mode
     * selection.  But if Visual is active, assume that only the Visual area
     * will be selected.
     * Exception: On the command line, both the selection is used and a mouse
     * key is send.
     */
    if (!mouse_has(checkfor) || checkfor == MOUSE_COMMAND)
    {
	/* Don't do non-visual selection in Visual mode. */
	if (VIsual_active)
	    return;

	/*
	 * When 'mousemodel' is "popup", shift-left is translated to right.
	 */
	if (mouse_model_popup())
	{
	    if (button == MOUSE_LEFT && (modifiers & MOUSE_SHIFT))
	    {
		button = MOUSE_RIGHT;
		modifiers &= ~ MOUSE_SHIFT;
	    }
	}

	/* If the selection is done, allow the right button to extend it.
	 * If the selection is cleared, allow the right button to start it
	 * from the cursor position. */
	if (button == MOUSE_RIGHT)
	{
	    if (clipboard.state == SELECT_CLEARED)
	    {
		if (State == CMDLINE)
		{
		    col = msg_col;
		    row = msg_row;
		}
		else
		{
		    col = curwin->w_wcol;
		    row = curwin->w_wrow + curwin->w_winpos;
		}
		clip_start_selection(MOUSE_LEFT, FILL_X(col), FILL_Y(row),
								    FALSE, 0);
	    }
	    clip_process_selection(button, x, y, repeated_click, modifiers);
	    did_clip = TRUE;
	}
	/* Allow the left button to start the selection */
	else if (button ==
# ifdef RISCOS
		/* Only start a drag on a drag event. Otherwise
		 * we don't get a release event.
		 */
		    MOUSE_DRAG
# else

⌨️ 快捷键说明

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