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

📄 ex_cmds.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
	    *p++ = ' '; /* not really needed? Not with sh, ksh or bash */
	    sprintf((char *)p, (char *)p_srr, (char *)otmp);
	}
	else
	    sprintf((char *)IObuff + STRLEN(IObuff),
#ifndef RISCOS
		    " %s%s",	/* " %s %s" causes problems on Amiga */
#else
		    " %s %s",	/* But is needed for RISC OS */
#endif
		    (char *)p_srr, (char *)otmp);
    }

    windgoto((int)Rows - 1, 0);
    cursor_on();

    /*
     * When not redirecting the output the command can write anything to the
     * screen. If 'shellredir' is equal to ">", screen may be messed up by
     * stderr output of external command. Clear the screen later.
     * If do_in is FALSE, this could be something like ":r !cat", which may
     * also mess up the screen, clear it later.
     */
    if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
	must_redraw = CLEAR;
    else
	redraw_later(NOT_VALID);

    /*
     * When call_shell() fails wait_return() is called to give the user a
     * chance to read the error messages. Otherwise errors are ignored, so you
     * can see the error messages from the command that appear on stdout; use
     * 'u' to fix the text
     * Switch to cooked mode when not redirecting stdin, avoids that something
     * like ":r !cat" hangs.
     * Pass on the SHELL_DOOUT flag when the output is being redirected.
     */
    if (call_shell(IObuff, SHELL_FILTER | SHELL_COOKED |
					  (do_out ? SHELL_DOOUT : 0)))
    {
	must_redraw = CLEAR;
	wait_return(FALSE);
    }

    need_check_timestamps = TRUE;

    if (do_out)
    {
	if (u_save((linenr_t)(line2), (linenr_t)(line2 + 1)) == FAIL)
	{
	    goto error;
	}
	if (readfile(otmp, NULL, line2, (linenr_t)0, (linenr_t)MAXLNUM,
							 READ_FILTER) == FAIL)
	{
	    msg_putchar('\n');
	    emsg2(e_notread, otmp);
	    goto error;
	}
#ifdef AUTOCMD
	if (curbuf != old_curbuf)
	    goto filterend;
#endif

	if (do_in)
	{
	    /*
	     * Put cursor on first filtered line for ":range!cmd".
	     * Adjust '[ and '] (set by buf_write()).
	     */
	    curwin->w_cursor.lnum = line1;
	    del_lines(linecount, TRUE, TRUE);
	    curbuf->b_op_start.lnum -= linecount;	/* adjust '[ */
	    curbuf->b_op_end.lnum -= linecount;		/* adjust '] */
	    write_lnum_adjust(-linecount);		/* adjust last line
							   for next write */
	}
	else
	{
	    /*
	     * Put cursor on last new line for ":r !cmd".
	     */
	    curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
	    linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
	}
	beginline(BL_WHITE | BL_FIX);	    /* cursor on first non-blank */
	--no_wait_return;

	if (linecount > p_report)
	{
	    if (do_in)
	    {
		sprintf((char *)msg_buf, "%ld lines filtered", (long)linecount);
		if (msg(msg_buf) && !msg_scroll)
		{
		    keep_msg = msg_buf;	    /* display message after redraw */
		    keep_msg_attr = 0;
		}
	    }
	    else
		msgmore((long)linecount);
	}
    }
    else
    {
error:
	/* put cursor back in same position for ":w !cmd" */
	curwin->w_cursor = cursor_save;
	--no_wait_return;
	wait_return(FALSE);
    }

filterend:

#ifdef AUTOCMD
    if (curbuf != old_curbuf)
    {
	--no_wait_return;
	EMSG("*Filter* Autocommands must not change current buffer");
    }
#endif
    if (itmp != NULL)
	mch_remove(itmp);
    if (otmp != NULL)
	mch_remove(otmp);
    vim_free(itmp);
    vim_free(otmp);
}

#ifdef VIMINFO

static int no_viminfo __ARGS((void));
static int  viminfo_errcnt;

    static int
no_viminfo()
{
    /* "vim -i NONE" does not read or write a viminfo file */
    return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
}

/*
 * Report an error for reading a viminfo file.
 * Count the number of errors.	When there are more than 10, return TRUE.
 */
    int
viminfo_error(message, line)
    char    *message;
    char_u  *line;
{
    sprintf((char *)IObuff, "viminfo: %s in line: ", message);
    STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
    emsg(IObuff);
    if (++viminfo_errcnt >= 10)
    {
	EMSG("viminfo: Too many errors, skipping rest of file");
	return TRUE;
    }
    return FALSE;
}

/*
 * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
 * set are not over-written unless force is TRUE. -- webb
 */
    int
read_viminfo(file, want_info, want_marks, forceit)
    char_u  *file;
    int	    want_info;
    int	    want_marks;
    int	    forceit;
{
    FILE    *fp;

    if (no_viminfo())
	return FAIL;

    file = viminfo_filename(file);	    /* may set to default if NULL */
    if ((fp = fopen((char *)file, READBIN)) == NULL)
	return FAIL;

    if (p_verbose > 0)
	smsg((char_u *)"Reading viminfo file \"%s\"%s%s", file,
		    want_info ? " info" : "",
		    want_marks ? " marks" : "");

    viminfo_errcnt = 0;
    do_viminfo(fp, NULL, want_info, want_marks, forceit);

    fclose(fp);

    return OK;
}

/*
 * write_viminfo() -- Write the viminfo file.  The old one is read in first so
 * that effectively a merge of current info and old info is done.  This allows
 * multiple vims to run simultaneously, without losing any marks etc.  If
 * forceit is TRUE, then the old file is not read in, and only internal info is
 * written to the file. -- webb
 */
    void
write_viminfo(file, forceit)
    char_u  *file;
    int	    forceit;
{
    FILE	    *fp_in = NULL;	/* input viminfo file, if any */
    FILE	    *fp_out = NULL;	/* output viminfo file */
    char_u	    *tempname = NULL;	/* name of temp viminfo file */
    struct stat	    st_new;		/* stat() of potential new file */
    char_u	    *wp;
#ifdef UNIX
    int		    shortname = FALSE;	/* use 8.3 file name */
    mode_t	    umask_save;
    struct stat	    st_old;		/* stat() of existing viminfo file */
#endif

    if (no_viminfo())
	return;

    file = viminfo_filename(file);	/* may set to default if NULL */
    file = vim_strsave(file);		/* make a copy, don't want NameBuff */

    if (file != NULL)
    {
	fp_in = fopen((char *)file, READBIN);
	if (fp_in == NULL)
	{
	    /* if it does exist, but we can't read it, don't try writing */
	    if (stat((char *)file, &st_new) == 0)
		goto end;
#ifdef UNIX
	    /*
	     * For Unix we create the .viminfo non-accessible for others,
	     * because it may contain text from non-accessible documents.
	     */
	    umask_save = umask(077);
#endif
	    fp_out = fopen((char *)file, WRITEBIN);
#ifdef UNIX
	    (void)umask(umask_save);
#endif
	}
	else
	{
	    /*
	     * There is an existing viminfo file.  Create a temporary file to
	     * write the new viminfo into, in the same directory as the
	     * existing viminfo file, which will be renamed later.
	     */
#ifdef UNIX
	    /*
	     * For Unix we check the owner of the file.  It's not very nice to
	     * overwrite a user's viminfo file after a "su root", with a
	     * viminfo file that the user can't read.
	     */
	    st_old.st_dev = st_old.st_ino = 0;
	    st_old.st_mode = 0600;
	    if (stat((char *)file, &st_old) == 0 && getuid() &&
		    !(st_old.st_uid == getuid()
			    ? (st_old.st_mode & 0200)
			    : (st_old.st_gid == getgid()
				    ? (st_old.st_mode & 0020)
				    : (st_old.st_mode & 0002))))
	    {
		int	tt;

		/* avoid a wait_return for this message, it's annoying */
		tt = msg_didany;
		EMSG2("Viminfo file is not writable: %s", file);
		msg_didany = tt;
		goto end;
	    }
#endif

	    /*
	     * Make tempname.
	     * May try twice: Once normal and once with shortname set, just in
	     * case somebody puts his viminfo file in an 8.3 filesystem.
	     */
	    for (;;)
	    {
		tempname = buf_modname(
#ifdef UNIX
					shortname,
#else
# ifdef SHORT_FNAME
					TRUE,
# else
#  ifdef USE_GUI_WIN32
					gui_is_win32s(),
#  else
					FALSE,
#  endif
# endif
#endif
					file,
#ifdef VMS
					(char_u *)"-tmp",
#else
# ifdef RISCOS
					(char_u *)"/tmp",
# else
					(char_u *)".tmp",
# endif
#endif
					FALSE);
		if (tempname == NULL)		/* out of memory */
		    break;

		/*
		 * Check if tempfile already exists.  Never overwrite an
		 * existing file!
		 */
		if (stat((char *)tempname, &st_new) == 0)
		{
#ifdef UNIX
		    /*
		     * Check if tempfile is same as original file.  May happen
		     * when modname gave the same file back.  E.g.  silly
		     * link, or file name-length reached.  Try again with
		     * shortname set.
		     */
		    if (!shortname && st_new.st_dev == st_old.st_dev &&
			    st_new.st_ino == st_old.st_ino)
		    {
			vim_free(tempname);
			tempname = NULL;
			shortname = TRUE;
			continue;
		    }
#endif
		    /*
		     * Try another name.  Change one character, just before
		     * the extension.  This should also work for an 8.3
		     * file name, when after adding the extension it still is
		     * the same file as the original.
		     */
		    wp = tempname + STRLEN(tempname) - 5;
		    if (wp < gettail(tempname))	    /* empty file name? */
			wp = gettail(tempname);
		    for (*wp = 'z'; stat((char *)tempname, &st_new) == 0; --*wp)
		    {
			/*
			 * They all exist?  Must be something wrong! Don't
			 * write the viminfo file then.
			 */
			if (*wp == 'a')
			{
			    vim_free(tempname);
			    tempname = NULL;
			    break;
			}
		    }
		}
		break;
	    }

	    if (tempname != NULL)
	    {
		fp_out = fopen((char *)tempname, WRITEBIN);

		/*
		 * If we can't create in the same directory, try creating a
		 * "normal" temp file.
		 */
		if (fp_out == NULL)
		{
		    vim_free(tempname);
		    if ((tempname = vim_tempname('o')) != NULL)
			fp_out = fopen((char *)tempname, WRITEBIN);
		}
#ifdef UNIX
		/*
		 * Set file protection same as original file, but strip s-bit
		 * and make sure the owner can read/write it.
		 */
		if (fp_out != NULL)
		{
		    (void)mch_setperm(tempname,
				      (long)((st_old.st_mode & 0777) | 0600));
		    /* this only works for root: */
		    (void)chown((char *)tempname, st_old.st_uid, st_old.st_gid);
		}
#endif
	    }
	}
    }

    /*
     * Check if the new viminfo file can be written to.
     */
    if (file == NULL || fp_out == NULL)
    {
	EMSG2("Can't write viminfo file %s!", file == NULL ? (char_u *)"" :
					      fp_in == NULL ? file : tempname);
	if (fp_in != NULL)
	    fclose(fp_in);
	goto end;
    }

    if (p_verbose > 0)
	smsg((char_u *)"Writing viminfo file \"%s\"", file);

    viminfo_errcnt = 0;
    do_viminfo(fp_in, fp_out, !forceit, !forceit, FALSE);

    fclose(fp_out);	    /* errors are ignored !? */
    if (fp_in != NULL)
    {
	fclose(fp_in);
	/*
	 * In case of an error, don't overwrite the original viminfo file.
	 */
	if (viminfo_errcnt || vim_rename(tempname, file) == -1)
	    mch_remove(tempname);
    }
end:
    vim_free(file);
    vim_free(tempname);
}

/*
 * Get the viminfo file name to use.
 * If "file" is given and not empty, use it (has already been expanded by
 * cmdline functions).
 * Otherwise use "-i file_name", value from 'viminfo' or the default, and
 * expand environment variables.
 */
    static char_u *
viminfo_filename(file)
    char_u	*file;
{
    if (file == NULL || *file == NUL)
    {
	if (use_viminfo != NULL)
	    file = use_viminfo;
	else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
	{
#ifdef VIMINFO_FILE2
	    /* don't use $HOME when not defined (turned into "c:/"!). */
	    if (mch_getenv((char_u *)"HOME") == NULL)
	    {
		/* don't use $VIM when not available. */
		expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
		if (STRCMP("$VIM", NameBuff) != 0)  /* $VIM was expanded */
		    file = (char_u *)VIMINFO_FILE2;
		else
		    file = (char_u *)VIMINFO_FILE;
	    }
	    else
#endif
		file = (char_u *)VIMINFO_FILE;
	}
	expand_env(file, NameBuff, MAXPATHL);
	return NameBuff;
    }
    return file;
}

/*
 * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
 */
    static void
do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
    FILE    *fp_in;
    FILE    *fp_out;
    int	    want_info;
    int	    want_marks;
    int	    force_read;
{
    int	    count = 0;
    int	    eof = FALSE;
    char_u  *line;

    if ((line = alloc(LSIZE)) == NULL)
	return;

    if (fp_in != NULL)
    {
	if (want_info)
	    eof = read_viminfo_up_to_marks(line, fp_in, force_read,
							      fp_out != NULL);
	else
	    /* Skip info, find start of marks */
	    while (!(eof = vim_fgets(line, LSIZE, fp_in)) && line[0] != '>')
		;
    }
    if (fp_out != NULL)
    {
	/* Write the info: */
	fprintf(fp_out, "# This viminfo file was generated by vim\n");
	fprintf(fp_out, "# You may edit it if you're careful!\n\n");
	write_viminfo_search_pattern(fp_out);
	write_viminfo_sub_string(fp_out);
	write_viminfo_history(fp_out);
	write_viminfo_registers(fp_out);
	write_viminfo_filemarks(fp_out);
	write_viminfo_bufferlist(fp_out);
	count = write_viminfo_marks(fp_out);
    }
    if (fp_in != NULL && want_marks)
	copy_viminfo_marks(line, fp_in, fp_out, count, eof);
    vim_free(line);
}

/*
 * read_viminfo_up_to_marks() -- Only called from do_viminfo().  Reads in the
 * first part of the viminfo file which contains everything but the marks that
 * are local to a file.  Returns TRUE when end-of-file is reached. -- webb
 */
    static int
read_viminfo_up_to_marks(line, fp, forceit, writing)
    char_u  *line;
    FILE    *fp;
    int	    forceit;
    int	    writing;
{
    int	    eof;

⌨️ 快捷键说明

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