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

📄 memline.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
			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 + -