Beispiel #1
0
/*
 * ex_run_str --
 *	Set up a string of ex commands to run.
 *
 * PUBLIC: int ex_run_str(SCR *, char *, CHAR_T *, size_t, int, int);
 */
int
ex_run_str(SCR *sp, char *name, CHAR_T *str, size_t len, int ex_flags, int nocopy)
{
	GS *gp;
	EXCMD *ecp;

	gp = sp->gp;
	if (EXCMD_RUNNING(gp)) {
		CALLOC_RET(sp, ecp, 1, sizeof(EXCMD));
		SLIST_INSERT_HEAD(gp->ecq, ecp, q);
	} else
		ecp = &gp->excmd;

	F_INIT(ecp,
	    ex_flags ? E_BLIGNORE | E_NOAUTO | E_NOPRDEF | E_VLITONLY : 0);

	if (nocopy)
		ecp->cp = str;
	else
		if ((ecp->cp = v_wstrdup(sp, str, len)) == NULL)
			return (1);
	ecp->clen = len;

	if (name == NULL)
		ecp->if_name = NULL;
	else {
		if ((ecp->if_name = v_strdup(sp, name, strlen(name))) == NULL)
			return (1);
		ecp->if_lno = 1;
		F_SET(ecp, E_NAMEDISCARD);
	}

	return (0);
}
Beispiel #2
0
/*
 * v_screen_copy --
 *	Copy vi screen.
 *
 * PUBLIC: int v_screen_copy __P((SCR *, SCR *));
 */
int
v_screen_copy(SCR *orig, SCR *sp)
{
	VI_PRIVATE *ovip, *nvip;

	/* Create the private vi structure. */
	CALLOC_RET(orig, nvip, VI_PRIVATE *, 1, sizeof(VI_PRIVATE));
	sp->vi_private = nvip;

	/* Invalidate the line size cache. */
	VI_SCR_CFLUSH(nvip);

	if (orig == NULL) {
		nvip->csearchdir = CNOTSET;
	} else {
		ovip = VIP(orig);

		/* User can replay the last input, but nothing else. */
		if (ovip->rep_len != 0) {
			MALLOC_RET(orig, nvip->rep, EVENT *, ovip->rep_len);
			memmove(nvip->rep, ovip->rep, ovip->rep_len);
			nvip->rep_len = ovip->rep_len;
		}

		/* Copy the paragraph/section information. */
		if (ovip->ps != NULL && (nvip->ps =
		    v_strdup(sp, ovip->ps, strlen(ovip->ps))) == NULL)
			return (1);

		nvip->lastckey = ovip->lastckey;
		nvip->csearchdir = ovip->csearchdir;

		nvip->srows = ovip->srows;
	}
/*
 * ex_file -- :f[ile] [name]
 *	Change the file's name and display the status line.
 *
 * PUBLIC: int ex_file __P((SCR *, EXCMD *));
 */
int
ex_file(SCR *sp, EXCMD *cmdp)
{
	char *p;
	FREF *frp;
	const char *np;
	size_t nlen;

	NEEDFILE(sp, cmdp);

	switch (cmdp->argc) {
	case 0:
		break;
	case 1:
		frp = sp->frp;

		/* Make sure can allocate enough space. */
		INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, 
			    np, nlen);
		if ((p = v_strdup(sp, np, nlen - 1)) == NULL)
			return (1);

		/* If already have a file name, it becomes the alternate. */
		if (!F_ISSET(frp, FR_TMPFILE))
			set_alt_name(sp, frp->name);

		/* Free the previous name. */
		free(frp->name);
		frp->name = p;

		/*
		 * The file has a real name, it's no longer a temporary,
		 * clear the temporary file flags.
		 */
		F_CLR(frp, FR_TMPEXIT | FR_TMPFILE);

		/* Have to force a write if the file exists, next time. */
		F_SET(frp, FR_NAMECHANGE);

		/* Notify the screen. */
		(void)sp->gp->scr_rename(sp, sp->frp->name, 1);
		break;
	default:
		abort();
	}
	msgq_status(sp, sp->lno, MSTAT_SHOWLAST);
	return (0);
}
Beispiel #4
0
/*
 * ex_next -- :next [+cmd] [files]
 *	Edit the next file, optionally setting the list of files.
 *
 * !!!
 * The :next command behaved differently from the :rewind command in
 * historic vi.  See nvi/docs/autowrite for details, but the basic
 * idea was that it ignored the force flag if the autowrite flag was
 * set.  This implementation handles them all identically.
 *
 * PUBLIC: int ex_next __P((SCR *, EXCMD *));
 */
int
ex_next(SCR *sp, EXCMD *cmdp)
{
	ARGS **argv;
	FREF *frp;
	int noargs;
	char **ap;
	const CHAR_T *wp;
	size_t wlen;
	const char *np;
	size_t nlen;

	/* Check for file to move to. */
	if (cmdp->argc == 0 && (sp->cargv == NULL || sp->cargv[1] == NULL)) {
		msgq(sp, M_ERR, "111|No more files to edit");
		return (1);
	}

	if (F_ISSET(cmdp, E_NEWSCREEN)) {
		/* By default, edit the next file in the old argument list. */
		if (cmdp->argc == 0) {
			CHAR2INT(sp, sp->cargv[1], strlen(sp->cargv[1]) + 1,
					   wp, wlen);
			if (argv_exp0(sp, cmdp, wp, wlen - 1))
				return (1);
			return (ex_edit(sp, cmdp));
		}
		return (ex_N_next(sp, cmdp));
	}

	/* Check modification. */
	if (file_m1(sp,
	    FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
		return (1);

	/* Any arguments are a replacement file list. */
	if (cmdp->argc) {
		/* Free the current list. */
		if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
			for (ap = sp->argv; *ap != NULL; ++ap)
				free(*ap);
			free(sp->argv);
		}
		F_CLR(sp, SC_ARGNOFREE | SC_ARGRECOVER);
		sp->cargv = NULL;

		/* Create a new list. */
		CALLOC_RET(sp,
		    sp->argv, char **, cmdp->argc + 1, sizeof(char *));
		for (ap = sp->argv,
		    argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv) {
			INT2CHAR(sp, argv[0]->bp, argv[0]->len, np, nlen);
			if ((*ap = v_strdup(sp, np, nlen)) == NULL)
				return (1);
		}
		*ap = NULL;

		/* Switch to the first file. */
		sp->cargv = sp->argv;
		if ((frp = file_add(sp, *sp->cargv)) == NULL)
			return (1);
		noargs = 0;

		/* Display a file count with the welcome message. */
		F_SET(sp, SC_STATUS_CNT);
	} else {
		if ((frp = file_add(sp, sp->cargv[1])) == NULL)
Beispiel #5
0
/*
 * exwr --
 *	The guts of the ex write commands.
 */
static int
exwr(SCR *sp, EXCMD *cmdp, enum which cmd)
{
	MARK rm;
	int flags;
	char *name;
	CHAR_T *p = NULL;
	size_t nlen;
	char *n;
	int rc;
	EX_PRIVATE *exp;

	NEEDFILE(sp, cmdp);

	/* All write commands can have an associated '!'. */
	LF_INIT(FS_POSSIBLE);
	if (FL_ISSET(cmdp->iflags, E_C_FORCE))
		LF_SET(FS_FORCE);

	/* Skip any leading whitespace. */
	if (cmdp->argc != 0)
		for (p = cmdp->argv[0]->bp; *p != '\0' && cmdskip(*p); ++p);

	/* If "write !" it's a pipe to a utility. */
	if (cmdp->argc != 0 && cmd == WRITE && *p == '!') {
		/* Secure means no shell access. */
		if (O_ISSET(sp, O_SECURE)) {
			ex_wemsg(sp, cmdp->cmd->name, EXM_SECURE_F);
			return (1);
		}

		/* Expand the argument. */
		for (++p; *p && cmdskip(*p); ++p);
		if (*p == '\0') {
			ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
			return (1);
		}
		if (argv_exp1(sp, cmdp, p, STRLEN(p), 1))
			return (1);

		/* Set the last bang command */
		exp = EXP(sp);
		free(exp->lastbcomm);
		exp->lastbcomm = v_wstrdup(sp, cmdp->argv[1]->bp,
		    cmdp->argv[1]->len);

		/*
		 * Historically, vi waited after a write filter even if there
		 * wasn't any output from the command.  People complained when
		 * nvi waited only if there was output, wanting the visual cue
		 * that the program hadn't written anything.
		 */
		F_SET(sp, SC_EX_WAIT_YES);

		/*
		 * !!!
		 * Ignore the return cursor position, the cursor doesn't
		 * move.
		 */
		if (ex_filter(sp, cmdp, &cmdp->addr1,
		    &cmdp->addr2, &rm, cmdp->argv[1]->bp, FILTER_WRITE))
			return (1);

		/* Ex terminates with a bang, even if the command fails. */
		if (!F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_EX_SILENT))
			(void)ex_puts(sp, "!\n");

		return (0);
	}

	/* Set the FS_ALL flag if we're writing the entire file. */
	if (cmdp->addr1.lno <= 1 && !db_exist(sp, cmdp->addr2.lno + 1))
		LF_SET(FS_ALL);

	/* If "write >>" it's an append to a file. */
	if (cmdp->argc != 0 && cmd != XIT && p[0] == '>' && p[1] == '>') {
		LF_SET(FS_APPEND);

		/* Skip ">>" and whitespace. */
		for (p += 2; *p && cmdskip(*p); ++p);
	}

	/* If no other arguments, just write the file back. */
	if (cmdp->argc == 0 || *p == '\0')
		return (file_write(sp,
		    &cmdp->addr1, &cmdp->addr2, NULL, flags));

	/* Build an argv so we get an argument count and file expansion. */
	if (argv_exp2(sp, cmdp, p, STRLEN(p)))
		return (1);

	/*
	 *  0 args: impossible.
	 *  1 args: impossible (I hope).
	 *  2 args: read it.
	 * >2 args: object, too many args.
	 *
	 * The 1 args case depends on the argv_sexp() function refusing
	 * to return success without at least one non-blank character.
	 */
	switch (cmdp->argc) {
	case 0:
	case 1:
		abort();
		/* NOTREACHED */
	case 2:
		INT2CHAR(sp, cmdp->argv[1]->bp, cmdp->argv[1]->len+1,
			 n, nlen);
		name = v_strdup(sp, n, nlen - 1);

		/*
		 * !!!
		 * Historically, the read and write commands renamed
		 * "unnamed" files, or, if the file had a name, set
		 * the alternate file name.
		 */
		if (F_ISSET(sp->frp, FR_TMPFILE) &&
		    !F_ISSET(sp->frp, FR_EXNAMED)) {
			if ((n = v_strdup(sp, name, nlen - 1)) != NULL) {
				free(sp->frp->name);
				sp->frp->name = n;
			}
			/*
			 * The file has a real name, it's no longer a
			 * temporary, clear the temporary file flags.
			 *
			 * !!!
			 * If we're writing the whole file, FR_NAMECHANGE
			 * will be cleared by the write routine -- this is
			 * historic practice.
			 */
			F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
			F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);

			/* Notify the screen. */
			(void)sp->gp->scr_rename(sp, sp->frp->name, 1);
		} else
			set_alt_name(sp, name);
		break;
	default:
		INT2CHAR(sp, p, STRLEN(p) + 1, n, nlen);
		ex_emsg(sp, n, EXM_FILECOUNT);
		return (1);
	}

	rc = file_write(sp, &cmdp->addr1, &cmdp->addr2, name, flags);

	free(name);

	return rc;
}