📄 gui.c
字号:
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 + -