📄 gui.c
字号:
if (attr > HL_ALL)
aep = syn_gui_attr2entry(attr);
if (aep != NULL)
{
attr = aep->ae_attr;
if (cfg < 0)
cfg = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color
: aep->ae_u.gui.fg_color) - 1;
if (cbg < 0)
cbg = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color
: aep->ae_u.gui.bg_color) - 1;
}
if (cfg < 0)
cfg = (attr & HL_INVERSE) ? gui.back_pixel : gui.norm_pixel;
if (cbg < 0)
cbg = (attr & HL_INVERSE) ? gui.norm_pixel : gui.back_pixel;
attr &= ~HL_INVERSE;
if (cattr & HL_INVERSE)
{
cc = cbg;
cbg = cfg;
cfg = cc;
}
cattr &= ~HL_INVERSE;
/*
* When we don't have window focus, draw a hollow cursor.
*/
if (!gui.in_focus)
{
gui_mch_draw_hollow_cursor(cbg);
return;
}
old_hl_mask = gui.highlight_mask;
if (cursor_table[idx].shape == SHAPE_BLOCK)
{
/*
* Draw the text character with the cursor colors. Use the
* character attributes plus the cursor attributes.
*/
gui.highlight_mask = (cattr | attr);
gui_outstr_nowrap(LinePointers[gui.row] + gui.col, 1,
GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0);
}
else
{
/*
* First draw the partial cursor, then overwrite with the text
* character, using a transparant background.
*/
if (cursor_table[idx].shape == SHAPE_VER)
{
cur_height = gui.char_height;
cur_width = (gui.char_width * cursor_table[idx].percentage
+ 99) / 100;
}
else
{
cur_height = (gui.char_height * cursor_table[idx].percentage
+ 99) / 100;
cur_width = gui.char_width;
}
gui_mch_draw_part_cursor(cur_width, cur_height, cbg);
#ifndef USE_GUI_WIN32 /* doesn't seem to work for Win32 */
gui.highlight_mask = *(LinePointers[gui.row] + gui.col
+ screen_Columns);
gui_outstr_nowrap(LinePointers[gui.row] + gui.col, 1,
GUI_MON_TRS_CURSOR | GUI_MON_NOCLEAR,
(GuiColor)0, (GuiColor)0, 0);
#endif
}
gui.highlight_mask = old_hl_mask;
}
}
void
gui_position_menu()
{
if (gui.menu_is_active && gui.in_use)
gui_mch_set_menu_pos(0, 0, gui.menu_width, gui.menu_height);
}
/*
* Position the various GUI components (text area, menu). The vertical
* scrollbars are NOT handled here. See gui_update_scrollbars().
*/
/* ARGSUSED */
static void
gui_position_components(total_width, total_height)
int total_width;
int total_height;
{
int text_area_x;
int text_area_y;
int text_area_width;
int text_area_height;
gui.menu_width = total_width;
text_area_x = 0;
if (gui.which_scrollbars[SBAR_LEFT])
text_area_x += gui.scrollbar_width;
#ifdef USE_GUI_WIN32
if (vim_strchr(p_guioptions, GO_TOOLBAR) != NULL)
text_area_y = TOOLBAR_BUTTON_HEIGHT + 12;
else
#endif
text_area_y = 0;
if (gui.menu_is_active)
text_area_y += gui.menu_height;
text_area_width = gui.num_cols * gui.char_width + gui.border_offset * 2;
text_area_height = gui.num_rows * gui.char_height + gui.border_offset * 2;
gui_mch_set_text_area_pos(text_area_x,
text_area_y,
text_area_width,
text_area_height);
gui_position_menu();
if (gui.which_scrollbars[SBAR_BOTTOM])
gui_mch_set_scrollbar_pos(&gui.bottom_sbar,
text_area_x,
text_area_y + text_area_height,
text_area_width,
gui.scrollbar_height);
gui.left_sbar_x = 0;
gui.right_sbar_x = text_area_x + text_area_width;
}
int
gui_get_base_width()
{
int base_width;
base_width = 2 * gui.border_offset;
if (gui.which_scrollbars[SBAR_LEFT])
base_width += gui.scrollbar_width;
if (gui.which_scrollbars[SBAR_RIGHT])
base_width += gui.scrollbar_width;
return base_width;
}
int
gui_get_base_height()
{
int base_height;
base_height = 2 * gui.border_offset;
if (gui.which_scrollbars[SBAR_BOTTOM])
base_height += gui.scrollbar_height;
if (gui.menu_is_active)
base_height += gui.menu_height;
#ifdef USE_GUI_WIN32
if (vim_strchr(p_guioptions, GO_TOOLBAR) != NULL)
base_height += (TOOLBAR_BUTTON_HEIGHT+12);
#endif
return base_height;
}
/*
* Should be called after the GUI window has been resized. Its arguments are
* the new width and height of the window in pixels.
*/
void
gui_resize_window(pixel_width, pixel_height)
int pixel_width;
int pixel_height;
{
if (!gui.window_created)
return;
#ifdef USE_GUI_BEOS
vim_lock_screen();
#endif
/* Flush pending output before redrawing */
out_flush();
gui.num_cols = (pixel_width - gui_get_base_width()) / gui.char_width;
gui.num_rows = (pixel_height - gui_get_base_height()) / gui.char_height;
gui_position_components(pixel_width, pixel_height);
gui_reset_scroll_region();
/*
* At the "more" and ":confirm" prompt there is no redraw, put the cursor
* at the last line here (why does it have to be one row too low?).
*/
if (State == ASKMORE || State == CONFIRM)
gui.row = gui.num_rows;
if (gui.num_rows != screen_Rows || gui.num_cols != screen_Columns)
set_winsize(0, 0, FALSE);
#ifdef USE_GUI_BEOS
vim_unlock_screen();
#endif
gui_update_scrollbars(TRUE);
gui_update_cursor(FALSE, TRUE);
}
int
gui_get_winsize()
{
Rows = gui.num_rows;
Columns = gui.num_cols;
return OK;
}
/*
* Set the size of the window according to Rows and Columns.
*/
void
gui_set_winsize(fit_to_display)
int fit_to_display;
{
int base_width;
int base_height;
int width;
int height;
int min_width;
int min_height;
int screen_w;
int screen_h;
if (!gui.window_created)
return;
base_width = gui_get_base_width();
base_height = gui_get_base_height();
width = Columns * gui.char_width + base_width;
height = Rows * gui.char_height + base_height;
if (fit_to_display)
{
gui_mch_get_screen_dimensions(&screen_w, &screen_h);
if (width > screen_w)
{
Columns = (screen_w - base_width) / gui.char_width;
if (Columns < MIN_COLUMNS)
Columns = MIN_COLUMNS;
gui.num_cols = Columns;
gui_reset_scroll_region();
width = Columns * gui.char_width + base_width;
}
if (height > screen_h)
{
Rows = (screen_h - base_height) / gui.char_height;
if (Rows < MIN_LINES)
Rows = MIN_LINES;
gui.num_rows = Rows;
gui_reset_scroll_region();
height = Rows * gui.char_height + base_height;
}
}
min_width = base_width + MIN_COLUMNS * gui.char_width;
min_height = base_height + MIN_LINES * gui.char_height;
gui_mch_set_winsize(width, height, min_width, min_height,
base_width, base_height);
gui_position_components(width, height);
gui_update_scrollbars(TRUE);
}
/*
* Make scroll region cover whole screen.
*/
void
gui_reset_scroll_region()
{
gui.scroll_region_top = 0;
gui.scroll_region_bot = gui.num_rows - 1;
}
void
gui_start_highlight(mask)
int mask;
{
if (mask > HL_ALL) /* highlight code */
gui.highlight_mask = mask;
else /* mask */
gui.highlight_mask |= mask;
}
void
gui_stop_highlight(mask)
int mask;
{
if (mask > HL_ALL) /* highlight code */
gui.highlight_mask = HL_NORMAL;
else /* mask */
gui.highlight_mask &= ~mask;
}
/*
* Clear a rectangular region of the screen from text pos (row1, col1) to
* (row2, col2) inclusive.
*/
void
gui_clear_block(row1, col1, row2, col2)
int row1;
int col1;
int row2;
int col2;
{
/* Clear the selection if we are about to write over it */
clip_may_clear_selection(row1, row2);
gui_mch_clear_block(row1, col1, row2, col2);
/* Invalidate cursor if it was in this block */
if ( gui.cursor_row >= row1 && gui.cursor_row <= row2
&& gui.cursor_col >= col1 && gui.cursor_col <= col2)
gui.cursor_is_valid = FALSE;
}
/*
* Write code to update cursor shape later.
*/
void
gui_upd_cursor_shape()
{
OUT_STR("\033|s");
}
void
gui_write(s, len)
char_u *s;
int len;
{
char_u *p;
int arg1 = 0, arg2 = 0;
#ifdef RISCOS
int force = TRUE; /* JK230798, stop Vim being smart or our redraw speed will suffer */
#else
int force = FALSE; /* force cursor update */
#endif
/* #define DEBUG_GUI_WRITE */
#ifdef DEBUG_GUI_WRITE
{
int i;
char_u *str;
printf("gui_write(%d):\n ", len);
for (i = 0; i < len; i++)
if (s[i] == ESC)
{
if (i != 0)
printf("\n ");
printf("<ESC>");
}
else
{
str = transchar(s[i]);
if (str[0] && str[1])
printf("<%s>", (char *)str);
else
printf("%s", (char *)str);
}
printf("\n");
}
#endif
while (len)
{
if (s[0] == ESC && s[1] == '|')
{
p = s + 2;
if (isdigit(*p))
{
arg1 = getdigits(&p);
if (p > s + len)
break;
if (*p == ';')
{
++p;
arg2 = getdigits(&p);
if (p > s + len)
break;
}
}
switch (*p)
{
case 'C': /* Clear screen */
clip_scroll_selection(9999);
gui_mch_clear_all();
gui.cursor_is_valid = FALSE;
break;
case 'M': /* Move cursor */
gui_set_cursor(arg1, arg2);
break;
case 's': /* force cursor (shape) update */
force = TRUE;
break;
case 'R': /* Set scroll region */
if (arg1 < arg2)
{
gui.scroll_region_top = arg1;
gui.scroll_region_bot = arg2;
}
else
{
gui.scroll_region_top = arg2;
gui.scroll_region_bot = arg1;
}
break;
case 'd': /* Delete line */
gui_delete_lines(gui.row, 1);
break;
case 'D': /* Delete lines */
gui_delete_lines(gui.row, arg1);
break;
case 'i': /* Insert line */
gui_insert_lines(gui.row, 1);
break;
case 'I': /* Insert lines */
gui_insert_lines(gui.row, arg1);
break;
case '$': /* Clear to end-of-line */
gui_clear_block(gui.row, gui.col, gui.row,
(int)Columns - 1);
break;
case 'h': /* Turn on highlighting */
gui_start_highlight(arg1);
break;
case 'H': /* Turn off highlighting */
gui_stop_highlight(arg1);
break;
case 'f': /* flash the window (visual bell) */
gui_mch_flash();
break;
default:
p = s + 1; /* Skip the ESC */
break;
}
len -= ++p - s;
s = p;
}
else if (s[0] < 0x20) /* Ctrl character */
{
if (s[0] == '\n') /* NL */
{
gui.col = 0;
if (gui.row < gui.scroll_region_bot)
gui.row++;
else
gui_delete_lines(gui.scroll_region_top, 1);
}
else if (s[0] == '\r') /* CR */
{
gui.col = 0;
}
else if (s[0] == '\b') /* Backspace */
{
if (gui.col)
--gui.col;
}
else if (s[0] == Ctrl('L')) /* cursor-right */
{
++gui.col;
}
else if (s[0] == Ctrl('G')) /* Beep */
{
gui_mch_beep();
}
/* Other Ctrl character: shouldn't happen! */
--len; /* Skip this char */
++s;
}
else
{
p = s;
while (len && *p >= 0x20)
{
len--;
p++;
}
gui_outstr(s, p - s);
s = p;
}
}
gui_update_cursor(force, TRUE);
gui_update_scrollbars(FALSE);
/*
* We need to make sure this is cleared since Athena doesn't tell us when
* he is done dragging.
*/
#ifdef USE_GUI_ATHENA
gui.dragged_sb = SBAR_NONE;
#endif
if (vim_strchr(p_guioptions, GO_ASEL) != NULL)
clip_update_selection();
gui_mch_flush(); /* In case vim decides to take a nap */
}
static void
gui_outstr(s, len)
char_u *s;
int len;
{
int this_len;
if (len == 0)
return;
if (len < 0)
len = STRLEN(s);
while (gui.col + len > Columns)
{
this_len = Columns - gui.col;
gui_outstr_nowrap(s, this_len, GUI_MON_WRAP_CURSOR, (GuiColor)0,
(GuiColor)0, 0);
s += this_len;
len -= this_len;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -