📄 memline.c
字号:
ml_append(lnum++, (char_u *)"???LINE COUNT WRONG",
(colnr_t)0, TRUE);
}
}
if (pp->pb_count == 0)
{
ml_append(lnum++, (char_u *)"???EMPTY BLOCK",
(colnr_t)0, TRUE);
++error;
}
else if (idx < (int)pp->pb_count) /* go a block deeper */
{
if (pp->pb_pointer[idx].pe_bnum < 0)
{
/*
* Data block with negative block number.
* Try to read lines from the original file.
* This is slow, but it works.
*/
if (!cannot_open)
{
line_count = pp->pb_pointer[idx].pe_line_count;
if (readfile(curbuf->b_ffname, NULL, lnum,
pp->pb_pointer[idx].pe_old_lnum - 1,
line_count, 0) == FAIL)
cannot_open = TRUE;
else
lnum += line_count;
}
if (cannot_open)
{
++error;
ml_append(lnum++, (char_u *)"???LINES MISSING",
(colnr_t)0, TRUE);
}
++idx; /* get same block again for next index */
continue;
}
/*
* going one block deeper in the tree
*/
if ((top = ml_add_stack(buf)) < 0) /* new entry in stack */
{
++error;
break; /* out of memory */
}
ip = &(buf->b_ml.ml_stack[top]);
ip->ip_bnum = bnum;
ip->ip_index = idx;
bnum = pp->pb_pointer[idx].pe_bnum;
line_count = pp->pb_pointer[idx].pe_line_count;
page_count = pp->pb_pointer[idx].pe_page_count;
continue;
}
}
else /* not a pointer block */
{
dp = (DATA_BL *)(hp->bh_data);
if (dp->db_id != DATA_ID) /* block id wrong */
{
if (bnum == 1)
{
EMSG2("Block 1 ID wrong (%s not a .swp file?)",
mfp->mf_fname);
goto theend;
}
++error;
ml_append(lnum++, (char_u *)"???BLOCK MISSING",
(colnr_t)0, TRUE);
}
else
{
/*
* it is a data block
* Append all the lines in this block
*/
has_error = FALSE;
/*
* check length of block
* if wrong, use length in pointer block
*/
if (page_count * mfp->mf_page_size != dp->db_txt_end)
{
ml_append(lnum++, (char_u *)"??? from here until ???END lines may be messed up",
(colnr_t)0, TRUE);
++error;
has_error = TRUE;
dp->db_txt_end = page_count * mfp->mf_page_size;
}
/* make sure there is a NUL at the end of the block */
*((char_u *)dp + dp->db_txt_end - 1) = NUL;
/*
* check number of lines in block
* if wrong, use count in data block
*/
if (line_count != dp->db_line_count)
{
ml_append(lnum++, (char_u *)"??? from here until ???END lines may have been inserted/deleted",
(colnr_t)0, TRUE);
++error;
has_error = TRUE;
}
for (i = 0; i < dp->db_line_count; ++i)
{
txt_start = (dp->db_index[i] & DB_INDEX_MASK);
if (txt_start <= HEADER_SIZE ||
txt_start >= (int)dp->db_txt_end)
{
p = (char_u *)"???";
++error;
}
else
p = (char_u *)dp + txt_start;
ml_append(lnum++, p, (colnr_t)0, TRUE);
}
if (has_error)
ml_append(lnum++, (char_u *)"???END", (colnr_t)0, TRUE);
}
}
}
if (buf->b_ml.ml_stack_top == 0) /* finished */
break;
/*
* go one block up in the tree
*/
ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
bnum = ip->ip_bnum;
idx = ip->ip_index + 1; /* go to next index */
page_count = 1;
}
/*
* The dummy line from the empty buffer will now be after the last line in
* the buffer. Delete it.
*/
ml_delete(curbuf->b_ml.ml_line_count, FALSE);
curbuf->b_flags |= BF_RECOVERED;
recoverymode = FALSE;
if (got_int)
EMSG("Recovery Interrupted");
else if (error)
EMSG("Errors detected while recovering; look for lines starting with ???");
else
{
MSG("Recovery completed. You should check if everything is OK.");
MSG_PUTS("\n(You might want to write out this file under another name\n");
MSG_PUTS("and run diff with the original file to check for changes)\n");
MSG_PUTS("Delete the .swp file afterwards.\n\n");
cmdline_row = msg_row;
}
theend:
if (mfp != NULL)
{
if (hp != NULL)
mf_put(mfp, hp, FALSE, FALSE);
mf_close(mfp, FALSE); /* will also vim_free(mfp->mf_fname) */
}
vim_free(buf);
if (serious_error && called_from_main)
ml_close(curbuf, TRUE);
#ifdef AUTOCMD
else
apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, FALSE, curbuf);
#endif
return;
}
/*
* Find the names of swap files in current directory and the directory given
* with the 'directory' option.
*
* Used to:
* - list the swap files for "vim -r"
* - count the number of swap files when recovering
* - list the swap files when recovering
* - find the name of the n'th swap file when recovering
*/
int
recover_names(fname, list, nr)
char_u **fname; /* base for swap file name */
int list; /* when TRUE, list the swap file names */
int nr; /* when non-zero, return nr'th swap file name */
{
int num_names;
char_u *(names[6]);
char_u *tail;
char_u *p;
int num_files;
int file_count = 0;
char_u **files;
int i;
char_u *dirp;
char_u *dir_name;
if (list)
{
/* use msg() to start the scrolling properly */
msg((char_u *)"Swap files found:");
msg_putchar('\n');
}
expand_interactively = TRUE;
/*
* Do the loop for every directory in 'directory'.
* First allocate some memory to put the directory name in.
*/
dir_name = alloc((unsigned)STRLEN(p_dir) + 1);
dirp = p_dir;
while (dir_name != NULL && *dirp)
{
/*
* Isolate a directory name from *dirp and put it in dir_name (we know
* it is large enough, so use 31000 for length).
* Advance dirp to next directory name.
*/
(void)copy_option_part(&dirp, dir_name, 31000, ",");
if (dir_name[0] == '.' && dir_name[1] == NUL) /* check current dir */
{
if (fname == NULL || *fname == NULL)
{
#ifdef RISCOS
names[0] = vim_strsave((char_u *)"*_sw#");
#else
names[0] = vim_strsave((char_u *)"*.sw?");
#endif
#ifdef UNIX
/* for Unix names starting with a dot are special */
names[1] = vim_strsave((char_u *)".*.sw?");
names[2] = vim_strsave((char_u *)".sw?");
num_names = 3;
#else
# ifdef VMS
names[1] = vim_strsave((char_u *)".*_sw%");
num_names = 2;
# else
num_names = 1;
# endif
#endif
}
else
num_names = recov_file_names(names, *fname, TRUE);
}
else /* check directory dir_name */
{
if (fname == NULL || *fname == NULL)
{
#ifdef RISCOS
names[0] = concat_fnames(dir_name, (char_u *)"*_sw#", TRUE);
#else
names[0] = concat_fnames(dir_name, (char_u *)"*.sw?", TRUE);
#endif
#ifdef UNIX
/* for Unix names starting with a dot are special */
names[1] = concat_fnames(dir_name, (char_u *)".*.sw?", TRUE);
names[2] = concat_fnames(dir_name, (char_u *)".sw?", TRUE);
num_names = 3;
#else
#ifdef VMS
names[1] = concat_fnames(dir_name, (char_u *)".*_sw?", TRUE);
num_names = 2;
#else
num_names = 1;
#endif
#endif
}
else
{
tail = gettail(*fname);
tail = concat_fnames(dir_name, tail, TRUE);
if (tail == NULL)
num_names = 0;
else
{
num_names = recov_file_names(names, tail, FALSE);
vim_free(tail);
}
}
}
/* check for out-of-memory */
for (i = 0; i < num_names; ++i)
{
if (names[i] == NULL)
{
for (i = 0; i < num_names; ++i)
vim_free(names[i]);
num_names = 0;
}
}
if (num_names == 0)
num_files = 0;
else if (expand_wildcards(num_names, names, &num_files, &files,
EW_FILE) == FAIL)
num_files = 0;
/*
* When no swap file found, wildcard expansion might have failed (e.g.
* not able to execute the shell).
* Try finding a swap file by simply adding ".swp" to the file name.
*/
if (*dirp == NUL && file_count + num_files == 0
&& fname != NULL && *fname != NULL)
{
struct stat st;
char_u *swapname;
#if defined(VMS) || defined(RISCOS)
swapname = modname(*fname, (char_u *)"_swp", TRUE);
#else
swapname = modname(*fname, (char_u *)".swp", TRUE);
#endif
if (swapname != NULL)
{
if (stat((char *)swapname, &st) != -1) /* It exists! */
{
files = (char_u **)alloc((unsigned)sizeof(char_u *));
if (files != NULL)
{
files[0] = swapname;
swapname = NULL;
num_files = 1;
}
}
vim_free(swapname);
}
}
/*
* remove swapfile name of the current buffer, it must be ignored
*/
if (curbuf->b_ml.ml_mfp != NULL &&
(p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
{
for (i = 0; i < num_files; ++i)
if (fullpathcmp(p, files[i], TRUE) & FPC_SAME)
{
vim_free(files[i]);
--num_files;
for ( ; i < num_files; ++i)
files[i] = files[i + 1];
}
}
if (nr)
{
file_count += num_files;
if (nr <= file_count)
{
*fname = vim_strsave(files[nr - 1 + num_files - file_count]);
dirp = (char_u *)""; /* stop searching */
}
}
else if (list)
{
if (dir_name[0] == '.' && dir_name[1] == NUL)
{
if (fname == NULL || *fname == NULL)
MSG_PUTS(" In current directory:\n");
else
MSG_PUTS(" Using specified name:\n");
}
else
{
MSG_PUTS(" In directory ");
msg_home_replace(dir_name);
MSG_PUTS(":\n");
}
if (num_files)
{
for (i = 0; i < num_files; ++i)
{
/* print the swap file name */
msg_outnum((long)++file_count);
MSG_PUTS(". ");
msg_puts(gettail(files[i]));
msg_putchar('\n');
swapfile_info(files[i]);
}
}
else
MSG_PUTS(" -- none --\n");
out_flush();
}
else
file_count += num_files;
for (i = 0; i < num_names; ++i)
vim_free(names[i]);
FreeWild(num_files, files);
}
vim_free(dir_name);
expand_interactively = FALSE;
return file_count;
}
/*
* Give information about an existing swap file
*/
static void
swapfile_info(fname)
char_u *fname;
{
struct stat st;
int fd;
struct block0 b0;
time_t x;
/* print the swap file date */
if (stat((char *)fname, &st) != -1)
{
MSG_PUTS(" dated: ");
x = st.st_mtime; /* Manx C can't do &st.st_mtime */
MSG_PUTS(ctime(&x)); /* includes '\n' */
#ifdef UNIX
/* print name of owner of the file */
{
char_u uname[B0_UNAME_SIZE];
if (mch_get_uname(st.st_uid, uname, B0_UNAME_SIZE) == OK)
{
MSG_PUTS(" owned by: ");
msg_outtrans(uname);
msg_putchar('\n');
}
}
#endif
}
/*
* print the original file name
*/
fd = open((char *)fname, O_RDONLY | O_EXTRA
#ifndef macintosh
, 0
#endif
);
if (fd >= 0)
{
if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
{
if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0)
{
MSG_PUTS(" [from Vim version 3.0]");
}
else if (b0.b0_id[0] != BLOCK0_ID0 ||
b0.b0_id[1] != BLOCK0_ID1)
{
MSG_PUTS(" [is not a swap file]");
}
else
{
MSG_PUTS(" file name: ");
msg_outtrans(b0.b0_fname);
if (*(b0.b0_hname) != NUL)
{
MSG_PUTS("\n host name: ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -