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

📄 memline.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
		    msg_outtrans(b0.b0_hname);
		}

		if (*(b0.b0_uname) != NUL)
		{
		    MSG_PUTS("\n         user name: ");
		    msg_outtrans(b0.b0_uname);
		}

		if (char_to_long(b0.b0_pid) != 0L)
		{
		    MSG_PUTS("\n        process ID: ");
		    msg_outnum(char_to_long(b0.b0_pid));
#if defined(UNIX) || defined(__EMX__)
		    /* EMX kill() not working correctly, it seems */
		    if (kill((pid_t)char_to_long(b0.b0_pid), 0) == 0)
			MSG_PUTS(" (still running)");
#endif
		}

		if (b0_magic_wrong(&b0))
		{
#if defined(MSDOS) || defined(WIN32)
		    if (STRNCMP(b0.b0_hname, "PC ", 3) == 0)
			MSG_PUTS("\n         [not usable with this version of Vim]");
		    else
#endif
			MSG_PUTS("\n         [not usable on this computer]");
		}
	    }
	}
	else
	    MSG_PUTS("         [cannot be read]");
	close(fd);
    }
    else
	MSG_PUTS("         [cannot be opened]");
    msg_putchar('\n');
}

    static int
recov_file_names(names, path, prepend_dot)
    char_u	**names;
    char_u	*path;
    int		prepend_dot;
{
    int		num_names;

#ifdef SHORT_FNAME
    /*
     * (MS-DOS) always short names
     */
    names[0] = modname(path, (char_u *)".sw?", FALSE);
    num_names = 1;
#else /* !SHORT_FNAME */
    /*
     * (WIN32) never short names, but do prepend a dot.
     * (Not MS-DOS or WIN32) maybe short name, maybe not: Try both.
     * Only use the short name if it is different.
     */
    char_u	*p;
    int		i;
# ifndef WIN32
    int	    shortname = curbuf->b_shortname;

    curbuf->b_shortname = FALSE;
# endif

    num_names = 0;

    /*
     * May also add the file name with a dot prepended, for swap file in same
     * dir as original file.
     */
    if (prepend_dot)
    {
	names[num_names] = modname(path, (char_u *)".sw?", TRUE);
	if (names[num_names] == NULL)
	    goto end;
	++num_names;
    }

    /*
     * Form the normal swap file name pattern by appending ".sw?".
     */
#ifdef VMS
    names[num_names] = concat_fnames(path, (char_u *)"_sw%", FALSE);
#else
# ifdef RISCOS
    names[num_names] = concat_fnames(path, (char_u *)"_sw#", FALSE);
# else
    names[num_names] = concat_fnames(path, (char_u *)".sw?", FALSE);
# endif
#endif
    if (names[num_names] == NULL)
	goto end;
    if (num_names >= 1)	    /* check if we have the same name twice */
    {
	p = names[num_names - 1];
	i = STRLEN(names[num_names - 1]) - STRLEN(names[num_names]);
	if (i > 0)
	    p += i;	    /* file name has been expanded to full path */

	if (STRCMP(p, names[num_names]) != 0)
	    ++num_names;
	else
	    vim_free(names[num_names]);
    }
    else
	++num_names;

# ifndef WIN32
    /*
     * Also try with 'shortname' set, in case the file is on a DOS filesystem.
     */
    curbuf->b_shortname = TRUE;
#ifdef RISCOS
    names[num_names] = modname(path, (char_u *)"_sw#", FALSE);
#else
    names[num_names] = modname(path, (char_u *)".sw?", FALSE);
#endif
    if (names[num_names] == NULL)
	goto end;

    /*
     * Remove the one from 'shortname', if it's the same as with 'noshortname'.
     */
    p = names[num_names];
    i = STRLEN(names[num_names]) - STRLEN(names[num_names - 1]);
    if (i > 0)
	p += i;		/* file name has been expanded to full path */
    if (STRCMP(names[num_names - 1], p) == 0)
	vim_free(names[num_names]);
    else
	++num_names;
# endif

end:
# ifndef WIN32
    curbuf->b_shortname = shortname;
# endif

#endif /* !SHORT_FNAME */

    return num_names;
}

/*
 * sync all memlines
 *
 * If 'check_file' is TRUE, check if original file exists and was not changed.
 * If 'check_char' is TRUE, stop syncing when character becomes available, but
 * always sync at least one block.
 */
    void
ml_sync_all(check_file, check_char)
    int	    check_file;
    int	    check_char;
{
    BUF		    *buf;
    struct stat	    st;

    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
    {
	if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL)
	    continue;			    /* no file */

	ml_flush_line(buf);		    /* flush buffered line */
					    /* flush locked block */
	(void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);
	if (buf_changed(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp)
						     && buf->b_ffname != NULL)
	{
	    /*
	     * if original file does not exist anymore or has been changed
	     * call ml_preserve to get rid of all negative numbered blocks
	     */
	    if (stat((char *)buf->b_ffname, &st) == -1 ||
				st.st_mtime != buf->b_mtime_read)
	    {
		ml_preserve(buf, FALSE);
		need_check_timestamps = TRUE;	/* give message later */
	    }
	}
	if (buf->b_ml.ml_mfp->mf_dirty)
	{
	    (void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
					| (buf_changed(buf) ? MFS_FLUSH : 0));
	    if (check_char && ui_char_avail())	/* character available now */
		break;
	}
    }
}

/*
 * sync one buffer, including negative blocks
 *
 * after this all the blocks are in the swap file
 *
 * Used for the :preserve command and when the original file has been
 * changed or deleted.
 *
 * when message is TRUE the success of preserving is reported
 */
    void
ml_preserve(buf, message)
    BUF	    *buf;
    int	    message;
{
    BHDR	*hp;
    linenr_t	lnum;
    MEMFILE	*mfp = buf->b_ml.ml_mfp;
    int		status;

    if (mfp == NULL || mfp->mf_fname == NULL)
    {
	if (message)
	    EMSG("Cannot preserve, there is no swap file");
	return;
    }

    ml_flush_line(buf);				    /* flush buffered line */
    (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH); /* flush locked block */
    status = mf_sync(mfp, MFS_ALL | MFS_FLUSH);

    /* stack is invalid after mf_sync(.., MFS_ALL) */
    buf->b_ml.ml_stack_top = 0;

    /*
     * Some of the data blocks may have been changed from negative to
     * positive block number. In that case the pointer blocks need to be
     * updated.
     *
     * We don't know in which pointer block the references are, so we visit
     * all data blocks until there are no more translations to be done (or
     * we hit the end of the file, which can only happen in case a write fails,
     * e.g. when file system if full).
     * ml_find_line() does the work by translating the negative block numbers
     * when getting the first line of each data block.
     */
    if (mf_need_trans(mfp))
    {
	lnum = 1;
	while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count)
	{
	    hp = ml_find_line(buf, lnum, ML_FIND);
	    if (hp == NULL)
	    {
		status = FAIL;
		goto theend;
	    }
	    CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum");
	    lnum = buf->b_ml.ml_locked_high + 1;
	}
	(void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);	/* flush locked block */
	/* sync the updated pointer blocks */
	if (mf_sync(mfp, MFS_ALL | MFS_FLUSH) == FAIL)
	    status = FAIL;
	buf->b_ml.ml_stack_top = 0;	    /* stack is invalid now */
    }
theend:
    if (message)
    {
	if (status == OK)
	    MSG("File preserved");
	else
	    EMSG("Preserve failed");
    }
}

/*
 * get a pointer to a (read-only copy of a) line
 *
 * On failure an error message is given and IObuff is returned (to avoid
 * having to check for error everywhere).
 */
    char_u  *
ml_get(lnum)
    linenr_t	lnum;
{
    return ml_get_buf(curbuf, lnum, FALSE);
}

/*
 * ml_get_pos: get pointer to position 'pos'
 */
    char_u *
ml_get_pos(pos)
    FPOS    *pos;
{
    return (ml_get_buf(curbuf, pos->lnum, FALSE) + pos->col);
}

/*
 * ml_get_curline: get pointer to cursor line.
 */
    char_u *
ml_get_curline()
{
    return ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE);
}

/*
 * ml_get_cursor: get pointer to cursor position
 */
    char_u *
ml_get_cursor()
{
    return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) +
							curwin->w_cursor.col);
}

/*
 * get a pointer to a line in a specific buffer
 *
 * "will_change": if TRUE mark the buffer dirty (chars in the line will be
 * changed)
 * NOTE: For syntax highlighting, need to call syn_changed() when
 * update_screenline() is not used.
 */
    char_u  *
ml_get_buf(buf, lnum, will_change)
    BUF		*buf;
    linenr_t	lnum;
    int		will_change;		/* line will be changed */
{
    BHDR    *hp;
    DATA_BL *dp;
    char_u  *ptr;

    if (lnum > buf->b_ml.ml_line_count)	/* invalid line number */
    {
	EMSGN("ml_get: invalid lnum: %ld", lnum);
errorret:
	STRCPY(IObuff, "???");
	return IObuff;
    }
    if (lnum <= 0)			/* pretend line 0 is line 1 */
	lnum = 1;

    if (buf->b_ml.ml_mfp == NULL)	/* there are no lines */
	return (char_u *)"";

/*
 * See if it is the same line as requested last time.
 * Otherwise may need to flush last used line.
 */
    if (buf->b_ml.ml_line_lnum != lnum)
    {
	ml_flush_line(buf);

	/*
	 * Find the data block containing the line.
	 * This also fills the stack with the blocks from the root to the data
	 * block and releases any locked block.
	 */
	if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL)
	{
	    EMSGN("ml_get: cannot find line %ld", lnum);
	    goto errorret;
	}

	dp = (DATA_BL *)(hp->bh_data);

	ptr = (char_u *)dp + ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK);
	buf->b_ml.ml_line_ptr = ptr;
	buf->b_ml.ml_line_lnum = lnum;
	buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
    }
    if (will_change)
	buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);

    return buf->b_ml.ml_line_ptr;
}

/*
 * Check if a line that was just obtained by a call to ml_get
 * is in allocated memory.
 */
    int
ml_line_alloced()
{
    return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
}

/*
 * append a line after lnum (may be 0 to insert a line in front of the file)
 *
 *   newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum
 *		will be set for recovery
 *
 * return FAIL for failure, OK otherwise
 */
    int
ml_append(lnum, line, len, newfile)
    linenr_t	lnum;		/* append after this line (can be 0) */
    char_u	*line;		/* text of the new line */
    colnr_t	len;		/* length of new line, including NUL, or 0 */
    int		newfile;	/* flag, see above */
{
#ifdef SYNTAX_HL
    if (curbuf->b_syn_change_lnum > lnum + 1)
	curbuf->b_syn_change_lnum = lnum + 1;
#endif

    if (curbuf->b_ml.ml_line_lnum != 0)
	ml_flush_line(curbuf);
    return ml_append_int(curbuf, lnum, line, len, newfile, FALSE);
}

    static int
ml_append_int(buf, lnum, line, len, newfile, mark)
    BUF		*buf;
    linenr_t	lnum;		/* append after this line (can be 0) */
    char_u	*line;		/* text of the new line */
    colnr_t	len;		/* length of line, including NUL, or 0 */
    int		newfile;	/* flag, see above */
    int		mark;		/* mark the new line */
{
    int		i;
    int		line_count;	/* number of indexes in current block */
    int		offset;
    int		from, to;
    int		space_needed;	/* space needed for new line */
    int		page_size;
    int		page_count;
    int		db_idx;		/* index for lnum in data block */
    BHDR	*hp;
    MEMFILE	*mfp;
    DATA_BL	*dp;
    PTR_BL	*pp;
    IPTR	*ip;

					/* lnum out of range */
    if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL)
	return FAIL;

    if (lowest_marked && lowest_marked > lnum)
	lowest_marked = lnum + 1;

    if (len == 0)
	len = STRLEN(line) + 1;		/* space needed for the text */
    space_needed = len + INDEX_SIZE;	/* space needed for text + index */

    mfp = buf->b_ml.ml_mfp;
    page_size = mfp->mf_page_size;

/*
 * find the data block containing the previous line
 * This also fills the stack with the blocks from the root to the data block
 * This also releases any locked block.
 */
    if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_t)1 : lnum,
							  ML_INSERT)) == NULL)
	return FAIL;

    buf->b_ml.ml_flags &= ~ML_EMPTY;

    if (lnum == 0)		/* got line one instead, correct db_idx */
	db_idx = -1;		/* careful, it is negative! */
    else
	db_idx = lnum - buf->b_ml.ml_locked_low;
		/* get line count before the insertion */
    line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;

    dp = (DATA_BL *)(hp->bh_data);

/*
 * If

⌨️ 快捷键说明

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