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

📄 fileio.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
		    fileformat = default_fileformat();

		/* if editing a new file: may set p_tx and p_ff */
		if (newfile)
		    set_fileformat(fileformat);
	    }
	}

	/*
	 * This loop is executed once for every character read.
	 * Keep it fast!
	 */
	if (fileformat == EOL_MAC)
	{
	    --ptr;
	    while (++ptr, --size >= 0)
	    {
		/* catch most common case first */
		if ((c = *ptr) != NUL && c != CR && c != NL)
		    continue;
		if (c == NUL)
		    *ptr = NL;	/* NULs are replaced by newlines! */
		else
		{
		    if (skip_count == 0)
		    {
			if (c == NL)
			{
			    /*
			     * Reading in Mac format, but a NL found!
			     * When 'fileformats' includes "unix" or "dos",
			     * delete all the lines read so far and start all
			     * over again.  Otherwise give an error message
			     * later.
			     */
			    if (ff_error == EOL_UNKNOWN)
			    {
				if ((try_dos || try_unix)
					&& !read_stdin
					&& lseek(fd, (off_t)0L, SEEK_SET) == 0)
				{
				    while (lnum > from)
					ml_delete(lnum--, FALSE);
				    if (!try_unix || ptr[-1] == NUL)
					fileformat = EOL_DOS;
				    else
					fileformat = EOL_UNIX;
				    if (newfile)
					set_fileformat(fileformat);
				    goto retry;
				}
				else
				    ff_error = EOL_MAC;
			    }
			}
			*ptr = NUL;	    /* end of line */
			len = ptr - line_start + 1;
			if (ml_append(lnum, line_start, len, newfile) == FAIL)
			{
			    error = TRUE;
			    break;
			}
			++lnum;
			if (--read_count == 0)
			{
			    error = TRUE;	    /* break loop */
			    line_start = ptr;	/* nothing left to write */
			    break;
			}
		    }
		    else
			--skip_count;
		    line_start = ptr + 1;
		}
	    }
	}
	else
	{
	    --ptr;
	    while (++ptr, --size >= 0)
	    {
		if ((c = *ptr) != NUL && c != NL)  /* catch most common case */
		    continue;
		if (c == NUL)
		    *ptr = NL;	/* NULs are replaced by newlines! */
		else
		{
		    if (skip_count == 0)
		    {
			*ptr = NUL;		/* end of line */
			len = ptr - line_start + 1;
			if (fileformat == EOL_DOS)
			{
			    if (ptr[-1] == CR)	/* remove CR */
			    {
				ptr[-1] = NUL;
				--len;
			    }
			    /*
			     * Reading in Dos format, but no CR-LF found!
			     * When 'fileformats' includes "unix", delete all
			     * the lines read so far and start all over again.
			     * Otherwise give an error message later.
			     */
			    else if (ff_error != EOL_DOS)
			    {
				if (	   try_unix
					&& !read_stdin
					&& lseek(fd, (off_t)0L, SEEK_SET) == 0)
				{
				    while (lnum > from)
					ml_delete(lnum--, FALSE);
				    fileformat = EOL_UNIX;
				    if (newfile)
					set_fileformat(EOL_UNIX);
				    goto retry;
				}
				else
				    ff_error = EOL_DOS;
			    }
			}
			if (ml_append(lnum, line_start, len, newfile) == FAIL)
			{
			    error = TRUE;
			    break;
			}
			++lnum;
			if (--read_count == 0)
			{
			    error = TRUE;	    /* break loop */
			    line_start = ptr;	/* nothing left to write */
			    break;
			}
		    }
		    else
			--skip_count;
		    line_start = ptr + 1;
		}
	    }
	}
	linerest = ptr - line_start;
	ui_breakcheck();
    }

    /* not an error, max. number of lines reached */
    if (error && read_count == 0)
	error = FALSE;

    /*
     * If we get EOF in the middle of a line, note the fact and
     * complete the line ourselves.
     * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
     */
    if (!error && !got_int && linerest != 0 &&
	    !(!curbuf->b_p_bin && fileformat == EOL_DOS &&
		    *line_start == Ctrl('Z') && ptr == line_start + 1))
    {
	if (newfile)		    /* remember for when writing */
	    curbuf->b_p_eol = FALSE;
	*ptr = NUL;
	if (ml_append(lnum, line_start,
			(colnr_t)(ptr - line_start + 1), newfile) == FAIL)
	    error = TRUE;
	else
	    read_no_eol_lnum = ++lnum;
    }
    if (lnum != from && !newfile)   /* added at least one line */
	changed();

    invalidate_botline();	    /* need to recompute w_botline */
    changed_line_abv_curs();	    /* need to recompute cursor posn */
    if (newfile)
	curbuf->b_start_ffc = *curbuf->b_p_ff;	/* remember 'fileformat' */

    close(fd);			    /* errors are ignored */
    vim_free(buffer);

    --no_wait_return;		    /* may wait for return now */

    /*
     * In recovery mode everything but autocommands are skipped.
     */
    if (!recoverymode)
    {
	/* need to delete the last line, which comes from the empty buffer */
	if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
	{
	    ml_delete(curbuf->b_ml.ml_line_count, FALSE);
	    --linecnt;
	}
	linecnt = curbuf->b_ml.ml_line_count - linecnt;
	if (filesize == 0)
	    linecnt = 0;
	if (!newfile)
	    mark_adjust(from + 1, (linenr_t)MAXLNUM, (long)linecnt, 0L);

	/*
	 * If we were reading from the same terminal as where messages go,
	 * the screen will have been messed up.
	 * Switch on raw mode now and clear the screen.
	 */
	if (read_stdin)
	{
	    settmode(TMODE_RAW);	    /* set to raw mode */
	    starttermcap();
	    screenclear();
	}

	if (got_int)
	{
	    filemess(curbuf, fname, e_interr, 0);
	    msg_scroll = msg_save;
#ifdef VIMINFO
	    check_marks_read();
#endif
	    return OK;		/* an interrupt isn't really an error */
	}

	if (!filtering)
	{
	    msg_add_fname(curbuf, fname);   /* fname in IObuff with quotes */
	    c = FALSE;

#ifdef UNIX
# ifdef S_ISFIFO
	    if (S_ISFIFO(perm))			    /* fifo or socket */
	    {
		STRCAT(IObuff, "[fifo/socket]");
		c = TRUE;
	    }
# else
#  ifdef S_IFIFO
	    if ((perm & S_IFMT) == S_IFIFO)	    /* fifo */
	    {
		STRCAT(IObuff, "[fifo]");
		c = TRUE;
	    }
#  endif
#  ifdef S_IFSOCK
	    if ((perm & S_IFMT) == S_IFSOCK)	    /* or socket */
	    {
		STRCAT(IObuff, "[socket]");
		c = TRUE;
	    }
#  endif
# endif
#endif
	    if (curbuf->b_p_ro)
	    {
		STRCAT(IObuff, shortmess(SHM_RO) ? "[RO]" : "[readonly]");
		c = TRUE;
	    }
	    if (read_no_eol_lnum)
	    {
		msg_add_eol();
		c = TRUE;
	    }
	    if (ff_error == EOL_DOS)
	    {
		STRCAT(IObuff, "[CR missing]");
		c = TRUE;
	    }
	    if (ff_error == EOL_MAC)
	    {
		STRCAT(IObuff, "[NL found]");
		c = TRUE;
	    }
	    if (split)
	    {
		STRCAT(IObuff, "[long lines split]");
		c = TRUE;
	    }
	    if (error)
	    {
		STRCAT(IObuff, "[READ ERRORS]");
		c = TRUE;
	    }
	    if (msg_add_fileformat(fileformat))
		c = TRUE;
	    msg_add_lines(c, (long)linecnt, filesize);
	    msg_trunc_attr(IObuff, FALSE, 0);
	}

	if (error && newfile)	/* with errors we should not write the file */
	    curbuf->b_p_ro = TRUE;

	u_clearline();	    /* cannot use "U" command after adding lines */

	/*
	 * In Ex mode: cursor at last new line.
	 * Otherwise: cursor at first new line.
	 */
	if (exmode_active)
	    curwin->w_cursor.lnum = from + linecnt;
	else
	    curwin->w_cursor.lnum = from + 1;
	check_cursor_lnum();
	beginline(BL_WHITE | BL_FIX);	    /* on first non-blank */

	/*
	 * Set '[ and '] marks to the newly read lines.
	 */
	curbuf->b_op_start.lnum = from + 1;
	curbuf->b_op_start.col = 0;
	curbuf->b_op_end.lnum = from + linecnt;
	curbuf->b_op_end.col = 0;
    }
    msg_scroll = msg_save;

#ifdef VIMINFO
    /*
     * Get the marks before executing autocommands, so they can be used there.
     */
    check_marks_read();
#endif

#ifdef AUTOCMD
    {
	int m = msg_scroll;
	int n = msg_scrolled;

	/*
	 * Trick: We remember if the last line of the read didn't have
	 * an eol for when writing it again.  This is required for
	 * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
	 */
	write_no_eol_lnum = read_no_eol_lnum;

	/*
	 * The output from the autocommands should not overwrite anything and
	 * should not be overwritten: Set msg_scroll, restore its value if no
	 * output was done.
	 */
	msg_scroll = TRUE;
	if (filtering)
	    apply_autocmds(EVENT_FILTERREADPOST, NULL, fname, FALSE, curbuf);
	else if (read_stdin)
	    apply_autocmds(EVENT_STDINREADPOST, NULL, fname, FALSE, curbuf);
	else if (newfile)
	    apply_autocmds(EVENT_BUFREADPOST, NULL, fname, FALSE, curbuf);
	else
	    apply_autocmds(EVENT_FILEREADPOST, fname, fname, FALSE, NULL);
	if (msg_scrolled == n)
	    msg_scroll = m;
    }
#endif

    if (recoverymode && error)
	return FAIL;
    return OK;
}

#ifdef VIMINFO
    static void
check_marks_read()
{
    if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0)
    {
	read_viminfo(NULL, FALSE, TRUE, FALSE);
	curbuf->b_marks_read = TRUE;
    }
}
#endif

#ifdef UNIX
    static void
set_file_time(fname, atime, mtime)
    char_u  *fname;
    time_t  atime;	    /* access time */
    time_t  mtime;	    /* modification time */
{
# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
#  include <utime.h>

    struct utimbuf  buf;

    buf.actime	= atime;
    buf.modtime	= mtime;
    (void)utime((char *)fname, &buf);
# else
#  if defined(HAVE_UTIMES)

    struct timeval  tvp[2];

    tvp[0].tv_sec   = atime;
    tvp[0].tv_usec  = 0;
    tvp[1].tv_sec   = mtime;
    tvp[1].tv_usec  = 0;
#   ifdef NeXT
    (void)utimes((char *)fname, tvp);
#   else
    (void)utimes((char *)fname, &tvp);
#   endif
#  endif
# endif
}
#endif /* UNIX */

/*
 * buf_write() - write to file 'fname' lines 'start' through 'end'
 *
 * We do our own buffering here because fwrite() is so slow.
 *
 * If forceit is true, we don't care for errors when attempting backups (jw).
 * In case of an error everything possible is done to restore the original file.
 * But when forceit is TRUE, we risk loosing it.
 * When reset_changed is TRUE and start == 1 and end ==
 * curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
 *
 * This function must NOT use NameBuff (because it's called by autowrite()).
 *
 * return FAIL for failure, OK otherwise
 */
    int
buf_write(buf, fname, sfname, start, end, append, forceit,
						      reset_changed, filtering)
    BUF		    *buf;
    char_u	    *fname;
    char_u	    *sfname;
    linenr_t	    start, end;
    int		    append;
    int		    forceit;
    int		    reset_changed;
    int		    filtering;
{
    int		    fd;
    char_u	    *backup = NULL;
    char_u	    *ffname;
#ifdef AUTOCMD
    BUF		    *save_buf;
#endif
    char_u	    *s;
    char_u	    *ptr;
    char_u	    c;
    int		    len;
    linenr_t	    lnum;
    long	    nchars;
    char_u	    *errmsg = NULL;
    char_u	    *buffer;
    char_u	    smallbuf[SMBUFSIZE];
    char_u	    *backup_ext;
    int		    bufsize;
    long	    perm;		    /* file permissions */
    int		    retval = OK;
    int		    newfile = FALSE;	    /* TRUE if file doesn't exist yet */
    int		    msg_save = msg_scroll;
    int		    overwriting;	    /* TRUE if writing over original */
    int		    no_eol = FALSE;	    /* no end-of-line written */
#if defined(UNIX) || defined(__EMX__XX)	    /*XXX fix me sometime? */
    struct stat	    st_old;
    int		    made_writable = FALSE;  /* 'w' bit has been set */
#endif
#ifdef AMIGA
    BPTR	    flock;
#endif
#ifdef VMS
    char_u	    *cp, nfname[MAXPATHL];
#endif
					    /* writing everything */
    int		    whole = (start == 1 && end == buf->b_ml.ml_line_count);
#ifdef AUTOCMD
    linenr_t	    old_line_count = buf->b_ml.ml_line_count;
#endif
    int		    attr;
    int		    fileformat = get_fileformat(buf);

    if (fname == NULL || *fname == NUL)	    /* safety check */
	return FAIL;

    /*
     * If there is no file name yet, use the one for the written file.
     * b_notedited is set to reflect this (in case the write fails).
     * Don't do this when the write is for a filter command.
     * Only do this when 'cpoptions' contains the 'f' flag.
     */
    if (reset_changed && whole && buf == curbuf &&
				   curbuf->b_ffname == NULL && !filtering &&
					vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
    {
	if (setfname(fname, sfname, FALSE) == OK)
	    curbuf->b_notedited = TRUE;
    }

    if (sfname == NULL)
	sfname = fname;
    /*
     * For Unix: Use the short file name whenever possible.
     * Avoids problems with networks and when directory names are changed.
     * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
     * another directory, which we don't detect
     */
    ffname = fname;			    /* remember full fname */
#ifdef UNIX
    fname = sfname;
#endif

	/* make sure we have a valid backup extension to use */
    if (*p_bex == NUL)
#ifdef RISCOS
	backup_ext = (char_u *)"/bak";
#else
	backup_ext = (char_u *)".bak";
#endif

⌨️ 快捷键说明

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