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

📄 screen.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
					   )
    {
#ifdef USE_GUI
	if (gui.in_use)
	{
	    char	buf[20];

	    sprintf(buf, "\033|%dH", screen_attr);	/* internal GUI code */
	    OUT_STR(buf);
	}
	else
#endif
	{
	    if (screen_attr > HL_ALL)			/* special HL attr. */
	    {
		struct attr_entry *aep;

		if (*T_CCO != NUL)
		{
		    /*
		     * Assume that t_me restores the original colors!
		     */
		    aep = syn_cterm_attr2entry(screen_attr);
		    if (aep != NULL && (aep->ae_u.cterm.fg_color ||
						    aep->ae_u.cterm.bg_color))
			do_ME = TRUE;
		}
		else
		{
		    aep = syn_term_attr2entry(screen_attr);
		    if (aep != NULL && aep->ae_u.term.stop != NULL)
		    {
			if (STRCMP(aep->ae_u.term.stop, T_ME) == 0)
			    do_ME = TRUE;
			else
			    out_str(aep->ae_u.term.stop);
		    }
		}
		if (aep == NULL)	    /* did ":syntax clear" */
		    screen_attr = 0;
		else
		    screen_attr = aep->ae_attr;
	    }

	    /*
	     * Often all ending-codes are equal to T_ME.  Avoid outputting the
	     * same sequence several times.
	     */
	    if (screen_attr & HL_STANDOUT)
	    {
		if (STRCMP(T_SE, T_ME) == 0)
		    do_ME = TRUE;
		else
		    out_str(T_SE);
	    }
	    if (screen_attr & HL_UNDERLINE)
	    {
		if (STRCMP(T_UE, T_ME) == 0)
		    do_ME = TRUE;
		else
		    out_str(T_UE);
	    }
	    if (screen_attr & HL_ITALIC)
	    {
		if (STRCMP(T_CZR, T_ME) == 0)
		    do_ME = TRUE;
		else
		    out_str(T_CZR);
	    }
	    if (do_ME || (screen_attr & HL_BOLD) || (screen_attr & HL_INVERSE))
		out_str(T_ME);

	    if (*T_CCO != NUL)
	    {
		/* set Normal cterm colors */
		if (cterm_normal_fg_color)
		    term_fg_color(cterm_normal_fg_color - 1);
		if (cterm_normal_bg_color)
		    term_bg_color(cterm_normal_bg_color - 1);
		if (cterm_normal_fg_bold)
		    out_str(T_MD);
	    }
	}
    }
    screen_attr = 0;
}

/*
 * Reset the colors for a cterm.  Used when leaving Vim.
 */
    void
reset_cterm_colors()
{
    if (*T_CCO != NUL)
    {
	/* set Normal cterm colors */
	if (cterm_normal_fg_color || cterm_normal_bg_color)
	    out_str(T_OP);
	if (cterm_normal_fg_bold)
	    out_str(T_ME);
    }
}

/*
 * put character '*p' on the screen at position 'row' and 'col'
 */
    static void
screen_char(p, row, col)
    char_u  *p;
    int	    row;
    int	    col;
{
    /*
     * Outputting the last character on the screen may scrollup the screen.
     * Don't to it!
     */
    if (col == Columns - 1 && row == Rows - 1)
	return;

    /*
     * Stop highlighting first, so it's easier to move the cursor.
     */
    if (screen_attr != *(p + Columns))
	screen_stop_highlight();

    windgoto(row, col);

    if (screen_attr != *(p + Columns))
	screen_start_highlight(*(p + Columns));

    out_char(*p);
    screen_cur_col++;
}

/*
 * Fill the screen from 'start_row' to 'end_row', from 'start_col' to 'end_col'
 * with character 'c1' in first column followed by 'c2' in the other columns.
 * Use attributes 'attr'.
 */
    void
screen_fill(start_row, end_row, start_col, end_col, c1, c2, attr)
    int	    start_row, end_row;
    int	    start_col, end_col;
    int	    c1, c2;
    int	    attr;
{
    int		    row;
    int		    col;
    char_u	    *screenp;
    char_u	    *attrp;
    int		    did_delete;
    int		    c;
    int		    norm_term;

    if (end_row > Rows)		    /* safety check */
	end_row = Rows;
    if (end_col > Columns)	    /* safety check */
	end_col = Columns;
    if (NextScreen == NULL ||
	    start_row >= end_row || start_col >= end_col)   /* nothing to do */
	return;

    /* it's a "normal" terminal when not in a GUI or cterm */
    norm_term = (
#ifdef USE_GUI
	    !gui.in_use &&
#endif
			    *T_CCO == NUL);
    for (row = start_row; row < end_row; ++row)
    {
	/*
	 * Try to use delete-line termcap code, when no attributes or in a
	 * "normal" terminal, where a bold/italic space is just a
	 * space.
	 */
	did_delete = FALSE;
	if (c2 == ' ' && end_col == Columns && *T_CE != NUL
		&& (attr == 0 || (norm_term && attr <= HL_ALL
		    && ((attr & ~(HL_BOLD | HL_ITALIC)) == 0))))
	{
	    /*
	     * check if we really need to clear something
	     */
	    col = start_col;
	    screenp = LinePointers[row] + start_col;
	    if (c1 != ' ')			/* don't clear first char */
	    {
		++col;
		++screenp;
	    }

	    /* skip blanks (used often, keep it fast!) */
	    attrp = screenp + Columns;
	    while (col < end_col && *screenp == ' ' && *attrp == 0)
	    {
		++col;
		++screenp;
		++attrp;
	    }
	    if (col < end_col)		/* something to be cleared */
	    {
		screen_stop_highlight();
		term_windgoto(row, col);/* clear rest of this screen line */
		out_str(T_CE);
		screen_start();		/* don't know where cursor is now */
		col = end_col - col;
		while (col--)		/* clear chars in NextScreen */
		{
		    *attrp++ = 0;
		    *screenp++ = ' ';
		}
	    }
	    did_delete = TRUE;		/* the chars are cleared now */
	}

	screenp = LinePointers[row] + start_col;
	c = c1;
	for (col = start_col; col < end_col; ++col)
	{
	    if (*screenp != c || *(screenp + Columns) != attr)
	    {
		*screenp = c;
		*(screenp + Columns) = attr;
		if (!did_delete || c != ' ')
		    screen_char(screenp, row, col);
	    }
	    ++screenp;
	    if (col == start_col)
	    {
		if (did_delete)
		    break;
		c = c2;
	    }
	}
	if (row == Rows - 1)		/* overwritten the command line */
	{
	    redraw_cmdline = TRUE;
	    if (c1 == ' ' && c2 == ' ')
		clear_cmdline = FALSE;	/* command line has been cleared */
	}
    }
}

/*
 * compute wp->w_botline. Can be called after wp->w_topline changed.
 */
    static void
comp_botline()
{
    int		n;
    linenr_t	lnum;
    int		done;

    /*
     * If w_cline_row is valid, start there.
     * Otherwise have to start at w_topline.
     */
    check_cursor_moved(curwin);
    if (curwin->w_valid & VALID_CROW)
    {
	lnum = curwin->w_cursor.lnum;
	done = curwin->w_cline_row;
    }
    else
    {
	lnum = curwin->w_topline;
	done = 0;
    }

    for ( ; lnum <= curwin->w_buffer->b_ml.ml_line_count; ++lnum)
    {
	n = plines(lnum);
	if (lnum == curwin->w_cursor.lnum)
	{
	    curwin->w_cline_row = done;
	    curwin->w_cline_height = n;
	    curwin->w_valid |= (VALID_CROW|VALID_CHEIGHT);
	}
	if (done + n > curwin->w_height)
	    break;
	done += n;
    }

    /* curwin->w_botline is the line that is just below the window */
    curwin->w_botline = lnum;
    curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;

    /*
     * Also set curwin->w_empty_rows, otherwise scroll_cursor_bot() won't work
     */
    if (done == 0)
	curwin->w_empty_rows = 0;	/* single line that doesn't fit */
    else
	curwin->w_empty_rows = curwin->w_height - done;
}

    void
screenalloc(clear)
    int	    clear;
{
    int		    new_row, old_row;
    WIN		    *wp;
    int		    outofmem = FALSE;
    int		    len;
    char_u	    *new_NextScreen;
    char_u	    **new_LinePointers;
    static int	    entered = FALSE;		/* avoid recursiveness */

    /*
     * Allocation of the screen buffers is done only when the size changes
     * and when Rows and Columns have been set and we have started doing full
     * screen stuff.
     */
    if ((NextScreen != NULL &&
			  Rows == screen_Rows && Columns == screen_Columns) ||
	    Rows == 0 || Columns == 0 || (!full_screen && NextScreen == NULL))
	return;

    /*
     * It's possible that we produce an out-of-memory message below, which
     * will cause this function to be called again.  To break the loop, just
     * return here.
     */
    if (entered)
	return;
    entered = TRUE;

#ifdef USE_GUI_BEOS
    vim_lock_screen();  /* be safe, put it here */
#endif

    comp_col();		/* recompute columns for shown command and ruler */

    /*
     * We're changing the size of the screen.
     * - Allocate new arrays for NextScreen.
     * - Move lines from the old arrays into the new arrays, clear extra
     *	 lines (unless the screen is going to be cleared).
     * - Free the old arrays.
     *
     * If anything fails, make NextScreen NULL, so we don't do anything!
     * Continuing with the old NextScreen may result in a crash, because the
     * size is wrong.
     */
    for (wp = firstwin; wp; wp = wp->w_next)
	win_free_lsize(wp);

    new_NextScreen =
	(char_u *)lalloc((long_u)((Rows + 1) * Columns * 2), FALSE);
    new_LinePointers =
	(char_u **)lalloc((long_u)(sizeof(char_u *) * Rows), FALSE);

    for (wp = firstwin; wp; wp = wp->w_next)
    {
	if (win_alloc_lsize(wp) == FAIL)
	{
	    outofmem = TRUE;
	    break;
	}
    }

    if (new_NextScreen == NULL || new_LinePointers == NULL || outofmem)
    {
	do_outofmem_msg();
	vim_free(new_NextScreen);
	new_NextScreen = NULL;
	vim_free(new_LinePointers);
	new_LinePointers = NULL;
    }
    else
    {
	for (new_row = 0; new_row < Rows; ++new_row)
	{
	    new_LinePointers[new_row] = new_NextScreen + new_row * Columns * 2;

	    /*
	     * If the screen is not going to be cleared, copy as much as
	     * possible from the old screen to the new one and clear the rest
	     * (used when resizing the window at the "--more--" prompt or when
	     * executing an external command, for the GUI).
	     */
	    if (!clear)
	    {
		lineclear(new_LinePointers[new_row]);
		old_row = new_row + (screen_Rows - Rows);
		if (old_row >= 0)
		{
		    if (screen_Columns < Columns)
			len = screen_Columns;
		    else
			len = Columns;
		    mch_memmove(new_LinePointers[new_row],
			    LinePointers[old_row], (size_t)len);
		    mch_memmove(new_LinePointers[new_row] + Columns,
			    LinePointers[old_row] + screen_Columns,
								 (size_t)len);
		}
	    }
	}
	current_LinePointer = new_NextScreen + Rows * Columns * 2;
    }

    vim_free(NextScreen);
    vim_free(LinePointers);
    NextScreen = new_NextScreen;
    LinePointers = new_LinePointers;

    must_redraw = CLEAR;	/* need to clear the screen later */
    if (clear)
	screenclear2();

#ifdef USE_GUI
    else if (gui.in_use && NextScreen != NULL && Rows != screen_Rows)
    {
	(void)gui_redraw_block(0, 0, (int)Rows - 1, (int)Columns - 1, 0);
	/*
	 * Adjust the position of the cursor, for when executing an external
	 * command.
	 */
	if (msg_row >= Rows)		    /* Rows got smaller */
	    msg_row = Rows - 1;		    /* put cursor at last row */
	else if (Rows > screen_Rows)	    /* Rows got bigger */
	    msg_row += Rows - screen_Rows;  /* put cursor in same place */
	if (msg_col >= Columns)		    /* Columns got smaller */
	    msg_col = Columns - 1;	    /* put cursor at last column */
    }
#endif

    screen_Rows = Rows;
    screen_Columns = Columns;
#ifdef USE_GUI_BEOS
    vim_unlock_screen();
#endif
    entered = FALSE;
}

    void
screenclear()
{
    check_for_delay(FALSE);
    screenalloc(FALSE);	    /* allocate screen buffers if size changed */
    screenclear2();	    /* clear the screen */
}

    static void
screenclear2()
{
    int	    i;

    if (starting || NextScreen == NULL)
	return;

    screen_stop_highlight();	/* don't want highlighting here */
    out_str(T_CL);		/* clear the display */

				/* blank out NextScreen */
    for (i = 0; i < Rows; ++i)
	lineclear(LinePointers[i]);

    screen_cleared = TRUE;	    /* can use contents of NextScreen now */

    win_rest_invalid(firstwin);
    clear_cmdline = FALSE;
    redraw_cmdline = TRUE;
    if (must_redraw == CLEAR)	    /* no need to clear again */
	must_redraw = NOT_VALID;
    compute_cmdrow();
    msg_row = cmdline_row;	    /* put cursor on last line for messages */
    msg_col = 0;
    screen_start();		    /* don't know where cursor is now */
    msg_scrolled = 0;		    /* can't scroll back */
    msg_didany = FALSE;
    msg_didout = FALSE;
}

/*
 * Clear one line in NextScreen.
 */
    static void
lineclear(p)
    char_u  *p;
{
    (void)vim_memset(p, ' ', (size_t)Columns);
    (void)vim_memset(p + Columns, 0, (size_t)Columns);
}

/*
 * Update curwin->w_topline and redraw if necessary.
 */
    void
update_topline_redraw()
{
    update_topline();
    if (must_redraw)
	update_screen(must_redraw);
}

/*
 * Update curwin->w_topline to move the cursor onto the screen.
 */
    void
update_topline()
{
    long	    line_count;
    int		    temp;
    linenr_t	    old_topline;

    if (!screen_valid(TRUE))
	return;

    old_topline = curwin->w_topline;

    /*
     * If the buffer is empty, always set topline to 1.
     */
    if (bufempty())		/* special case - file is empty */
    {
	if (curwin->w_topline != 1)
	    redraw_later(NOT_VALID);
	curwin->w_topline = 1;
	curwin->w_botline = 2;
	curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP;
    }

    /*
     * If the cursor is above the top of the window, scroll the window to put
    

⌨️ 快捷键说明

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