📄 fileio.c
字号:
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 + -