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

📄 buffer.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 4 页
字号:
    }

    resettitle();
}

/*
 * Append (file 2 of 8) to 'buf', if editing more than one file.
 * Return TRUE if it was appended.
 */
    static int
append_arg_number(buf, add_file, maxlen)
    char_u  *buf;
    int	    add_file;		/* Add "file" before the arg number */
    int	    maxlen;		/* maximum nr of chars in buf */
{
    char_u	*p;

    if (arg_file_count <= 1)		/* nothing to do */
	return FALSE;

    p = buf + STRLEN(buf);	/* go to the end of the buffer */
    if (p - buf + 35 >= maxlen)	/* getting too long */
	return FALSE;
    *p++ = ' ';
    *p++ = '(';
    if (add_file)
    {
	STRCPY(p, "file ");
	p += 5;
    }
    sprintf((char *)p, curwin->w_arg_idx_invalid ? "(%d) of %d)" :
			  "%d of %d)", curwin->w_arg_idx + 1, arg_file_count);
    return TRUE;
}

/*
 * Put current window title back (used after calling a shell)
 */
    void
resettitle()
{
    mch_settitle(lasttitle, lasticon);
}

/*
 * If fname is not a full path, make it a full path.
 * Returns pointer to allocated memory (NULL for failure).
 */
    char_u  *
fix_fname(fname)
    char_u  *fname;
{
    /*
     * Force expanding the path always for Unix, because symbolic links may
     * mess up the full path name, even though it starts with a '/'.
     */
#ifdef UNIX
    return FullName_save(fname, TRUE);
#else
    if (!mch_isFullName(fname))
	return FullName_save(fname, FALSE);

    fname = vim_strsave(fname);

#ifdef USE_FNAME_CASE
# ifdef USE_LONG_FNAME
    if (USE_LONG_FNAME)
# endif
    {
	if (fname != NULL)
	    fname_case(fname);		/* set correct case for file name */
    }
#endif

    return fname;
#endif
}

/*
 * make ffname a full file name, set sfname to ffname if not NULL
 * ffname becomes a pointer to allocated memory (or NULL).
 */
    void
fname_expand(ffname, sfname)
    char_u	**ffname;
    char_u	**sfname;
{
    if (*ffname == NULL)	/* if no file name given, nothing to do */
	return;
    if (*sfname == NULL)	/* if no short file name given, use ffname */
	*sfname = *ffname;
    *ffname = fix_fname(*ffname);   /* expand to full path */
}

/*
 * do_arg_all(): Open up to 'count' windows, one for each argument.
 */
    void
do_arg_all(count, forceit)
    int	count;
    int	forceit;		/* hide buffers in current windows */
{
    int		i;
    WIN		*wp, *wpnext;
    char_u	*opened;	/* array of flags for which args are open */
    int		opened_len;	/* lenght of opened[] */
    int		use_firstwin = FALSE;	/* use first window for arglist */
    int		split_ret = OK;
    int		p_sb_save;
    int		p_ea_save;

    if (arg_file_count <= 0)
    {
	/* Don't give an error message.  We don't want it when the ":all"
	 * command is in the .vimrc. */
	return;
    }
    setpcmark();

    opened_len = arg_file_count;
    opened = alloc_clear((unsigned)opened_len);
    if (opened == NULL)
	return;

#ifdef USE_GUI
    need_mouse_correct = TRUE;
#endif

    /*
     * Try closing all windows that are not in the argument list.
     * When 'hidden' or "forceit" set the buffer becomes hidden.
     * Windows that have a changed buffer and can't be hidden won't be closed.
     */
    for (wp = firstwin; wp != NULL; wp = wpnext)
    {
	wpnext = wp->w_next;
	if (wp->w_buffer->b_ffname == NULL || wp->w_buffer->b_nwindows > 1)
	    i = arg_file_count;
	else
	{
	    /* check if the buffer in this window is in the arglist */
	    for (i = 0; i < arg_file_count; ++i)
	    {
		if (fullpathcmp(arg_files[i],
				     wp->w_buffer->b_ffname, TRUE) & FPC_SAME)
		{
		    if (i < opened_len)
			opened[i] = TRUE;
		    break;
		}
	    }
	}
	wp->w_arg_idx = i;

	if (i == arg_file_count)		/* close this window */
	{
	    if (p_hid || forceit || wp->w_buffer->b_nwindows > 1
						|| !buf_changed(wp->w_buffer))
	    {
		/* If the buffer was changed, and we would like to hide it,
		 * try autowriting. */
		if (!p_hid && wp->w_buffer->b_nwindows <= 1
						 && buf_changed(wp->w_buffer))
		{
		    autowrite(wp->w_buffer, FALSE);
#ifdef AUTOCMD
		    /* check if autocommands removed the window */
		    if (!win_valid(wp))
		    {
			wpnext = firstwin;	/* start all over... */
			continue;
		    }
#endif
		}
		if (firstwin == lastwin)	/* can't close last window */
		    use_firstwin = TRUE;
		else
		{
		    close_window(wp, !p_hid && !buf_changed(wp->w_buffer));
#ifdef AUTOCMD
		    /* check if autocommands removed the next window */
		    if (!win_valid(wpnext))
			wpnext = firstwin;	/* start all over... */
#endif
		}
	    }
	}
    }

    /*
     * Open a window for files in the argument list that don't have one.
     * arg_file_count may change while doing this, because of autocommands.
     */
    if (count > arg_file_count || count <= 0)
	count = arg_file_count;

#ifdef AUTOCMD
    /* Don't execute Win/Buf Enter/Leave autocommands here. */
    ++autocmd_no_enter;
    ++autocmd_no_leave;
#endif
    win_enter(lastwin, FALSE);
    for (i = 0; i < count && i < arg_file_count && !got_int; ++i)
    {
	if (i == arg_file_count - 1)
	    arg_had_last = TRUE;
	if (i < opened_len && opened[i])
	{
	    /* Move the already present window to below the current window */
	    if (curwin->w_arg_idx != i)
	    {
		for (wpnext = firstwin; wpnext != NULL; wpnext = wpnext->w_next)
		{
		    if (wpnext->w_arg_idx == i)
		    {
			win_move_after(wpnext, curwin);
			break;
		    }
		}
	    }
	}
	else if (split_ret == OK)
	{
	    if (!use_firstwin)		/* split current window */
	    {
		p_sb_save = p_sb;
		p_ea_save = p_ea;
		p_sb = TRUE;		/* put windows in order of arglist */
		p_ea = TRUE;		/* use space from all windows */
		split_ret = win_split(0, FALSE, TRUE);
		p_sb = p_sb_save;
		p_ea = p_ea_save;
		if (split_ret == FAIL)
		    continue;
	    }
#ifdef AUTOCMD
	    else    /* first window: do autocmd for leaving this buffer */
		--autocmd_no_leave;
#endif

	    curwin->w_arg_idx = i;
	    /* edit file i */
	    (void)do_ecmd(0, arg_files[i], NULL, NULL, (linenr_t)1,
		   ((p_hid || buf_changed(curwin->w_buffer)) ? ECMD_HIDE : 0)
							       + ECMD_OLDBUF);
#ifdef AUTOCMD
	    if (use_firstwin)
		++autocmd_no_leave;
#endif
	    use_firstwin = FALSE;
	}
	ui_breakcheck();
    }
#ifdef AUTOCMD
    --autocmd_no_enter;
#endif
    win_enter(firstwin, FALSE);			/* back to first window */
#ifdef AUTOCMD
    --autocmd_no_leave;
#endif
}

/*
 * do_buffer_all: Open a window for each buffer.
 *
 * 'count' is the maximum number of windows to open.
 * When 'all' is TRUE, also load inactive buffers.
 */
    void
do_buffer_all(count, all)
    int	    count;
    int	    all;
{
    BUF		*buf;
    WIN		*wp, *wpnext;
    int		split_ret = OK;
    int		p_sb_save;
    int		p_ea_save;
    int		open_wins = 0;

    setpcmark();

#ifdef USE_GUI
    need_mouse_correct = TRUE;
#endif

    /*
     * Close superfluous windows (two windows for the same buffer).
     */
    for (wp = firstwin; wp != NULL; wp = wpnext)
    {
	wpnext = wp->w_next;
	if (wp->w_buffer->b_nwindows > 1)
	{
	    close_window(wp, FALSE);
#ifdef AUTOCMD
	    wpnext = firstwin;	    /* just in case an autocommand does
				       something strange with windows */
	    open_wins = 0;
#endif
	}
	else
	    ++open_wins;
    }

    /*
     * Go through the buffer list.  When a buffer doesn't have a window yet,
     * open one.  Otherwise move the window to the right position.
     * Watch out for autocommands that delete buffers or windows!
     */
#ifdef AUTOCMD
    /* Don't execute Win/Buf Enter/Leave autocommands here. */
    ++autocmd_no_enter;
#endif
    win_enter(lastwin, FALSE);
#ifdef AUTOCMD
    ++autocmd_no_leave;
#endif
    for (buf = firstbuf; buf != NULL && open_wins < count; buf = buf->b_next)
    {
	/* Check if this buffer needs a window */
	if (!all && buf->b_ml.ml_mfp == NULL)
	    continue;

	/* Check if this buffer already has a window */
	for (wp = firstwin; wp != NULL; wp = wp->w_next)
	    if (wp->w_buffer == buf)
		break;
	/* If the buffer already has a window, move it */
	if (wp != NULL)
	    win_move_after(wp, curwin);
	else if (split_ret == OK)
	{
	    /* Split the window and put the buffer in it */
	    p_sb_save = p_sb;
	    p_ea_save = p_ea;
	    p_sb = TRUE;		/* put windows in order of arglist */
	    p_ea = TRUE;		/* use space from all windows */
	    split_ret = win_split(0, FALSE, TRUE);
	    ++open_wins;
	    p_sb = p_sb_save;
	    p_ea = p_ea_save;
	    if (split_ret == FAIL)
		continue;
	    (void)do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD,
							 (int)buf->b_fnum, 0);
#ifdef AUTOCMD
	    if (!buf_valid(buf))	/* autocommands deleted the buffer!!! */
		break;
#endif
	}

	ui_breakcheck();
	if (got_int)
	{
	    (void)vgetc();	/* only break the file loading, not the rest */
	    break;
	}
    }
#ifdef AUTOCMD
    --autocmd_no_enter;
#endif
    win_enter(firstwin, FALSE);		    /* back to first window */
#ifdef AUTOCMD
    --autocmd_no_leave;
#endif

    /*
     * Close superfluous windows.
     */
    for (wp = lastwin; open_wins > count; )
    {
	if (p_hid || !buf_changed(wp->w_buffer)
				      || autowrite(wp->w_buffer, FALSE) == OK)
	{
	    close_window(wp, !p_hid);
	    --open_wins;
	    wp = lastwin;
	}
	else
	{
	    wp = wp->w_prev;
	    if (wp == NULL)
		break;
	}
    }
}

/*
 * do_modelines() - process mode lines for the current file
 *
 * Returns immediately if the "ml" option isn't set.
 */
static int  chk_modeline __ARGS((linenr_t));

    void
do_modelines()
{
    linenr_t	    lnum;
    int		    nmlines;

    if (!curbuf->b_p_ml || (nmlines = (int)p_mls) == 0)
	return;

    for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count && lnum <= nmlines;
								       ++lnum)
	if (chk_modeline(lnum) == FAIL)
	    nmlines = 0;

    for (lnum = curbuf->b_ml.ml_line_count; lnum > 0 && lnum > nmlines &&
			  lnum > curbuf->b_ml.ml_line_count - nmlines; --lnum)
	if (chk_modeline(lnum) == FAIL)
	    nmlines = 0;
}

/*
 * chk_modeline() - check a single line for a mode string
 * Return FAIL if an error encountered.
 */
    static int
chk_modeline(lnum)
    linenr_t lnum;
{
    char_u	    *s;
    char_u	    *e;
    char_u	    *linecopy;		/* local copy of any modeline found */
    int		    prev;
    int		    end;
    int		    retval = OK;
    char_u	    *save_sourcing_name;

    prev = -1;
    for (s = ml_get(lnum); *s != NUL; ++s)
    {
	if (prev == -1 || vim_isspace(prev))
	{
	    if ((prev != -1 && STRNCMP(s, "ex:", (size_t)3) == 0) ||
			       STRNCMP(s, "vi:", (size_t)3) == 0 ||
			       STRNCMP(s, "vim:", (size_t)4) == 0)
		break;
	}
	prev = *s;
    }

    if (*s)
    {
	do				/* skip over "ex:", "vi:" or "vim:" */
	    ++s;
	while (s[-1] != ':');

	s = linecopy = vim_strsave(s);	/* copy the line, it will change */
	if (linecopy == NULL)
	    return FAIL;

	sourcing_lnum = lnum;		/* prepare for emsg() */
	save_sourcing_name = sourcing_name;
	sourcing_name = (char_u *)"modelines";

	end = FALSE;
	while (end == FALSE)
	{
	    s = skipwhite(s);
	    if (*s == NUL)
		break;

	    /*
	     * Find end of set command: ':' or end of line.
	     */
	    for (e = s; (*e != ':' || *(e - 1) == '\\') && *e != NUL; ++e)
		;
	    if (*e == NUL)
		end = TRUE;

	    /*
	     * If there is a "set" command, require a terminating ':' and
	     * ignore the stuff after the ':'.
	     * "vi:set opt opt opt: foo" -- foo not interpreted
	     * "vi:opt opt opt: foo" -- foo interpreted
	     */
	    if (STRNCMP(s, "set ", (size_t)4) == 0)
	    {
		if (*e != ':')		/* no terminating ':'? */
		    break;
		end = TRUE;
		s += 4;
	    }

	    *e = NUL;			/* truncate the set command */
	    if (do_set(s) == FAIL)	/* stop if error found */
	    {
		retval = FAIL;
		break;
	    }
	    s = e + 1;			/* advance to next part */
	}

	sourcing_lnum = 0;
	sourcing_name = save_sourcing_name;

	vim_free(linecopy);
    }
    return retval;
}

#ifdef VIMINFO
    int
read_viminfo_bufferlist(line, fp, writing)
    char_u	*line;
    FILE	*fp;
    int		writing;
{
    char_u	*tab;
    linenr_t	lnum;
    colnr_t	col;
    BUF		*buf;
    char_u	*sfname;

    /* don't read in if there are files on the command-line or if writing: */
    if (!writing && arg_file_count == 0 && find_viminfo_parameter('%') != NULL)
    {
	tab = vim_strchr(line + 1, '\t');
	lnum = 0;
	col = 0;
	if (tab != NULL)
	{
	    *tab++ = '\0';
	    lnum = atol((char *)tab);
	    tab = vim_strchr(tab, '\t');
	    if (tab != NULL)
		col = atoi((char *)tab + 1);
	}

	/* Expand "~/" in the file name at "line + 1" to a full path.
	 * Then try shortening it by comparing with the current directory */
	expand_env(line + 1, NameBuff, MAXPATHL);
	mch_dirname(IObuff, IOSIZE);
	sfname = shorten_fname(NameBuff, IObuff);
	if (sfname == NULL)
	    sfname = NameBuff;

	buf = buflist_new(NameBuff, sfname, (linenr_t)0, FALSE);
	if (buf != NULL)	/* just in case... */
	{
	    buf->b_last_cursor.lnum = lnum;
	    buf->b_last_cursor.col = col;
	    buflist_setfpos(buf, lnum, col);
	}
    }

    return vim_fgets(line, LSIZE, fp);
}

    void
write_viminfo_bufferlist(fp)
    FILE    *fp;
{
    BUF		*buf;
    WIN		*win;

    if (find_viminfo_parameter('%') == NULL)
	return;

    for (win = firstwin; win != NULL; win = win->w_next)
	set_last_cursor(win);

    fprintf(fp, "\n# Buffer list:\n");
    for (buf = firstbuf; buf != NULL ; buf = buf->b_next)
    {
	if (buf->b_fname == NULL || buf->b_help || removable(buf->b_ffname))
	    continue;

	home_replace(NULL, buf->b_ffname, NameBuff, MAXPATHL, TRUE);

	fprintf(fp, "%%%s\t%ld\t%d\n", NameBuff,
			(long)buf->b_last_cursor.lnum,
			buf->b_last_cursor.col);
    }
}
#endif

⌨️ 快捷键说明

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