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

📄 gui.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -