xref: /minix3/external/bsd/nvi/dist/ex/ex_args.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: ex_args.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc /*-
384d9c625SLionel Sambuc  * Copyright (c) 1991, 1993, 1994
484d9c625SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
584d9c625SLionel Sambuc  * Copyright (c) 1991, 1993, 1994, 1995, 1996
684d9c625SLionel Sambuc  *	Keith Bostic.  All rights reserved.
784d9c625SLionel Sambuc  *
884d9c625SLionel Sambuc  * See the LICENSE file for redistribution information.
984d9c625SLionel Sambuc  */
1084d9c625SLionel Sambuc 
1184d9c625SLionel Sambuc #include "config.h"
1284d9c625SLionel Sambuc 
13*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
14*0a6a1f1dSLionel Sambuc #if 0
1584d9c625SLionel Sambuc #ifndef lint
1684d9c625SLionel Sambuc static const char sccsid[] = "Id: ex_args.c,v 10.18 2001/06/25 15:19:14 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:14 ";
1784d9c625SLionel Sambuc #endif /* not lint */
18*0a6a1f1dSLionel Sambuc #else
19*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: ex_args.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
20*0a6a1f1dSLionel Sambuc #endif
2184d9c625SLionel Sambuc 
2284d9c625SLionel Sambuc #include <sys/types.h>
2384d9c625SLionel Sambuc #include <sys/queue.h>
2484d9c625SLionel Sambuc #include <sys/time.h>
2584d9c625SLionel Sambuc 
2684d9c625SLionel Sambuc #include <bitstring.h>
2784d9c625SLionel Sambuc #include <errno.h>
2884d9c625SLionel Sambuc #include <limits.h>
2984d9c625SLionel Sambuc #include <stdio.h>
3084d9c625SLionel Sambuc #include <stdlib.h>
3184d9c625SLionel Sambuc #include <string.h>
3284d9c625SLionel Sambuc 
3384d9c625SLionel Sambuc #include "../common/common.h"
3484d9c625SLionel Sambuc #include "../vi/vi.h"
3584d9c625SLionel Sambuc 
3684d9c625SLionel Sambuc static int ex_N_next __P((SCR *, EXCMD *));
3784d9c625SLionel Sambuc 
3884d9c625SLionel Sambuc /*
3984d9c625SLionel Sambuc  * ex_next -- :next [+cmd] [files]
4084d9c625SLionel Sambuc  *	Edit the next file, optionally setting the list of files.
4184d9c625SLionel Sambuc  *
4284d9c625SLionel Sambuc  * !!!
4384d9c625SLionel Sambuc  * The :next command behaved differently from the :rewind command in
4484d9c625SLionel Sambuc  * historic vi.  See nvi/docs/autowrite for details, but the basic
4584d9c625SLionel Sambuc  * idea was that it ignored the force flag if the autowrite flag was
4684d9c625SLionel Sambuc  * set.  This implementation handles them all identically.
4784d9c625SLionel Sambuc  *
4884d9c625SLionel Sambuc  * PUBLIC: int ex_next __P((SCR *, EXCMD *));
4984d9c625SLionel Sambuc  */
5084d9c625SLionel Sambuc int
ex_next(SCR * sp,EXCMD * cmdp)5184d9c625SLionel Sambuc ex_next(SCR *sp, EXCMD *cmdp)
5284d9c625SLionel Sambuc {
5384d9c625SLionel Sambuc 	ARGS **argv;
5484d9c625SLionel Sambuc 	FREF *frp;
5584d9c625SLionel Sambuc 	int noargs;
5684d9c625SLionel Sambuc 	char **ap;
5784d9c625SLionel Sambuc 	const CHAR_T *wp;
5884d9c625SLionel Sambuc 	size_t wlen;
5984d9c625SLionel Sambuc 	const char *np;
6084d9c625SLionel Sambuc 	size_t nlen;
6184d9c625SLionel Sambuc 
6284d9c625SLionel Sambuc 	/* Check for file to move to. */
6384d9c625SLionel Sambuc 	if (cmdp->argc == 0 && (sp->cargv == NULL || sp->cargv[1] == NULL)) {
6484d9c625SLionel Sambuc 		msgq(sp, M_ERR, "111|No more files to edit");
6584d9c625SLionel Sambuc 		return (1);
6684d9c625SLionel Sambuc 	}
6784d9c625SLionel Sambuc 
6884d9c625SLionel Sambuc 	if (F_ISSET(cmdp, E_NEWSCREEN)) {
6984d9c625SLionel Sambuc 		/* By default, edit the next file in the old argument list. */
7084d9c625SLionel Sambuc 		if (cmdp->argc == 0) {
7184d9c625SLionel Sambuc 			CHAR2INT(sp, sp->cargv[1], strlen(sp->cargv[1]) + 1,
7284d9c625SLionel Sambuc 					   wp, wlen);
7384d9c625SLionel Sambuc 			if (argv_exp0(sp, cmdp, wp, wlen - 1))
7484d9c625SLionel Sambuc 				return (1);
7584d9c625SLionel Sambuc 			return (ex_edit(sp, cmdp));
7684d9c625SLionel Sambuc 		}
7784d9c625SLionel Sambuc 		return (ex_N_next(sp, cmdp));
7884d9c625SLionel Sambuc 	}
7984d9c625SLionel Sambuc 
8084d9c625SLionel Sambuc 	/* Check modification. */
8184d9c625SLionel Sambuc 	if (file_m1(sp,
8284d9c625SLionel Sambuc 	    FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
8384d9c625SLionel Sambuc 		return (1);
8484d9c625SLionel Sambuc 
8584d9c625SLionel Sambuc 	/* Any arguments are a replacement file list. */
8684d9c625SLionel Sambuc 	if (cmdp->argc) {
8784d9c625SLionel Sambuc 		/* Free the current list. */
8884d9c625SLionel Sambuc 		if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
8984d9c625SLionel Sambuc 			for (ap = sp->argv; *ap != NULL; ++ap)
9084d9c625SLionel Sambuc 				free(*ap);
9184d9c625SLionel Sambuc 			free(sp->argv);
9284d9c625SLionel Sambuc 		}
9384d9c625SLionel Sambuc 		F_CLR(sp, SC_ARGNOFREE | SC_ARGRECOVER);
9484d9c625SLionel Sambuc 		sp->cargv = NULL;
9584d9c625SLionel Sambuc 
9684d9c625SLionel Sambuc 		/* Create a new list. */
9784d9c625SLionel Sambuc 		CALLOC_RET(sp,
9884d9c625SLionel Sambuc 		    sp->argv, char **, cmdp->argc + 1, sizeof(char *));
9984d9c625SLionel Sambuc 		for (ap = sp->argv,
10084d9c625SLionel Sambuc 		    argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv) {
10184d9c625SLionel Sambuc 			INT2CHAR(sp, argv[0]->bp, argv[0]->len, np, nlen);
10284d9c625SLionel Sambuc 			if ((*ap = v_strdup(sp, np, nlen)) == NULL)
10384d9c625SLionel Sambuc 				return (1);
10484d9c625SLionel Sambuc 		}
10584d9c625SLionel Sambuc 		*ap = NULL;
10684d9c625SLionel Sambuc 
10784d9c625SLionel Sambuc 		/* Switch to the first file. */
10884d9c625SLionel Sambuc 		sp->cargv = sp->argv;
10984d9c625SLionel Sambuc 		if ((frp = file_add(sp, *sp->cargv)) == NULL)
11084d9c625SLionel Sambuc 			return (1);
11184d9c625SLionel Sambuc 		noargs = 0;
11284d9c625SLionel Sambuc 
11384d9c625SLionel Sambuc 		/* Display a file count with the welcome message. */
11484d9c625SLionel Sambuc 		F_SET(sp, SC_STATUS_CNT);
11584d9c625SLionel Sambuc 	} else {
11684d9c625SLionel Sambuc 		if ((frp = file_add(sp, sp->cargv[1])) == NULL)
11784d9c625SLionel Sambuc 			return (1);
11884d9c625SLionel Sambuc 		if (F_ISSET(sp, SC_ARGRECOVER))
11984d9c625SLionel Sambuc 			F_SET(frp, FR_RECOVER);
12084d9c625SLionel Sambuc 		noargs = 1;
12184d9c625SLionel Sambuc 	}
12284d9c625SLionel Sambuc 
12384d9c625SLionel Sambuc 	if (file_init(sp, frp, NULL, FS_SETALT |
12484d9c625SLionel Sambuc 	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
12584d9c625SLionel Sambuc 		return (1);
12684d9c625SLionel Sambuc 	if (noargs)
12784d9c625SLionel Sambuc 		++sp->cargv;
12884d9c625SLionel Sambuc 
12984d9c625SLionel Sambuc 	F_SET(sp, SC_FSWITCH);
13084d9c625SLionel Sambuc 	return (0);
13184d9c625SLionel Sambuc }
13284d9c625SLionel Sambuc 
13384d9c625SLionel Sambuc /*
13484d9c625SLionel Sambuc  * ex_N_next --
13584d9c625SLionel Sambuc  *	New screen version of ex_next.
13684d9c625SLionel Sambuc  */
13784d9c625SLionel Sambuc static int
ex_N_next(SCR * sp,EXCMD * cmdp)13884d9c625SLionel Sambuc ex_N_next(SCR *sp, EXCMD *cmdp)
13984d9c625SLionel Sambuc {
14084d9c625SLionel Sambuc 	SCR *new;
14184d9c625SLionel Sambuc 	FREF *frp;
14284d9c625SLionel Sambuc 	const char *np;
14384d9c625SLionel Sambuc 	size_t nlen;
14484d9c625SLionel Sambuc 
14584d9c625SLionel Sambuc 	/* Get a new screen. */
14684d9c625SLionel Sambuc 	if (screen_init(sp->gp, sp, &new))
14784d9c625SLionel Sambuc 		return (1);
14884d9c625SLionel Sambuc 	if (vs_split(sp, new, 0)) {
149*0a6a1f1dSLionel Sambuc 		(void)screen_fini(new);
15084d9c625SLionel Sambuc 		return (1);
15184d9c625SLionel Sambuc 	}
15284d9c625SLionel Sambuc 
15384d9c625SLionel Sambuc 	/* Get a backing file. */
15484d9c625SLionel Sambuc 	INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, np, nlen);
15584d9c625SLionel Sambuc 	if ((frp = file_add(new, np)) == NULL ||
15684d9c625SLionel Sambuc 	    file_init(new, frp, NULL,
15784d9c625SLionel Sambuc 	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
15884d9c625SLionel Sambuc 		(void)vs_discard(new, NULL);
15984d9c625SLionel Sambuc 		(void)screen_end(new);
16084d9c625SLionel Sambuc 		return (1);
16184d9c625SLionel Sambuc 	}
16284d9c625SLionel Sambuc 
16384d9c625SLionel Sambuc 	/* The arguments are a replacement file list. */
16484d9c625SLionel Sambuc 	new->cargv = new->argv = ex_buildargv(sp, cmdp, NULL);
16584d9c625SLionel Sambuc 
16684d9c625SLionel Sambuc 	/* Display a file count with the welcome message. */
16784d9c625SLionel Sambuc 	F_SET(new, SC_STATUS_CNT);
16884d9c625SLionel Sambuc 
16984d9c625SLionel Sambuc 	/* Set up the switch. */
17084d9c625SLionel Sambuc 	sp->nextdisp = new;
17184d9c625SLionel Sambuc 	F_SET(sp, SC_SSWITCH);
17284d9c625SLionel Sambuc 
17384d9c625SLionel Sambuc 	return (0);
17484d9c625SLionel Sambuc }
17584d9c625SLionel Sambuc 
17684d9c625SLionel Sambuc /*
17784d9c625SLionel Sambuc  * ex_prev -- :prev
17884d9c625SLionel Sambuc  *	Edit the previous file.
17984d9c625SLionel Sambuc  *
18084d9c625SLionel Sambuc  * PUBLIC: int ex_prev __P((SCR *, EXCMD *));
18184d9c625SLionel Sambuc  */
18284d9c625SLionel Sambuc int
ex_prev(SCR * sp,EXCMD * cmdp)18384d9c625SLionel Sambuc ex_prev(SCR *sp, EXCMD *cmdp)
18484d9c625SLionel Sambuc {
18584d9c625SLionel Sambuc 	FREF *frp;
18684d9c625SLionel Sambuc 	size_t wlen;
18784d9c625SLionel Sambuc 	const CHAR_T *wp;
18884d9c625SLionel Sambuc 
18984d9c625SLionel Sambuc 	if (sp->cargv == sp->argv) {
19084d9c625SLionel Sambuc 		msgq(sp, M_ERR, "112|No previous files to edit");
19184d9c625SLionel Sambuc 		return (1);
19284d9c625SLionel Sambuc 	}
19384d9c625SLionel Sambuc 
19484d9c625SLionel Sambuc 	if (F_ISSET(cmdp, E_NEWSCREEN)) {
19584d9c625SLionel Sambuc 		CHAR2INT(sp, sp->cargv[-1], strlen(sp->cargv[-1]) + 1,
19684d9c625SLionel Sambuc 				   wp, wlen);
19784d9c625SLionel Sambuc 		if (argv_exp0(sp, cmdp, wp, wlen - 1))
19884d9c625SLionel Sambuc 			return (1);
19984d9c625SLionel Sambuc 		return (ex_edit(sp, cmdp));
20084d9c625SLionel Sambuc 	}
20184d9c625SLionel Sambuc 
20284d9c625SLionel Sambuc 	if (file_m1(sp,
20384d9c625SLionel Sambuc 	    FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
20484d9c625SLionel Sambuc 		return (1);
20584d9c625SLionel Sambuc 
20684d9c625SLionel Sambuc 	if ((frp = file_add(sp, sp->cargv[-1])) == NULL)
20784d9c625SLionel Sambuc 		return (1);
20884d9c625SLionel Sambuc 
20984d9c625SLionel Sambuc 	if (file_init(sp, frp, NULL, FS_SETALT |
21084d9c625SLionel Sambuc 	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
21184d9c625SLionel Sambuc 		return (1);
21284d9c625SLionel Sambuc 	--sp->cargv;
21384d9c625SLionel Sambuc 
21484d9c625SLionel Sambuc 	F_SET(sp, SC_FSWITCH);
21584d9c625SLionel Sambuc 	return (0);
21684d9c625SLionel Sambuc }
21784d9c625SLionel Sambuc 
21884d9c625SLionel Sambuc /*
21984d9c625SLionel Sambuc  * ex_rew -- :rew
22084d9c625SLionel Sambuc  *	Re-edit the list of files.
22184d9c625SLionel Sambuc  *
22284d9c625SLionel Sambuc  * !!!
22384d9c625SLionel Sambuc  * Historic practice was that all files would start editing at the beginning
22484d9c625SLionel Sambuc  * of the file.  We don't get this right because we may have multiple screens
22584d9c625SLionel Sambuc  * and we can't clear the FR_CURSORSET bit for a single screen.  I don't see
22684d9c625SLionel Sambuc  * anyone noticing, but if they do, we'll have to put information into the SCR
22784d9c625SLionel Sambuc  * structure so we can keep track of it.
22884d9c625SLionel Sambuc  *
22984d9c625SLionel Sambuc  * PUBLIC: int ex_rew __P((SCR *, EXCMD *));
23084d9c625SLionel Sambuc  */
23184d9c625SLionel Sambuc int
ex_rew(SCR * sp,EXCMD * cmdp)23284d9c625SLionel Sambuc ex_rew(SCR *sp, EXCMD *cmdp)
23384d9c625SLionel Sambuc {
23484d9c625SLionel Sambuc 	FREF *frp;
23584d9c625SLionel Sambuc 
23684d9c625SLionel Sambuc 	/*
23784d9c625SLionel Sambuc 	 * !!!
23884d9c625SLionel Sambuc 	 * Historic practice -- you can rewind to the current file.
23984d9c625SLionel Sambuc 	 */
24084d9c625SLionel Sambuc 	if (sp->argv == NULL) {
24184d9c625SLionel Sambuc 		msgq(sp, M_ERR, "113|No previous files to rewind");
24284d9c625SLionel Sambuc 		return (1);
24384d9c625SLionel Sambuc 	}
24484d9c625SLionel Sambuc 
24584d9c625SLionel Sambuc 	if (file_m1(sp,
24684d9c625SLionel Sambuc 	    FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
24784d9c625SLionel Sambuc 		return (1);
24884d9c625SLionel Sambuc 
24984d9c625SLionel Sambuc 	/* Switch to the first one. */
25084d9c625SLionel Sambuc 	sp->cargv = sp->argv;
25184d9c625SLionel Sambuc 	if ((frp = file_add(sp, *sp->cargv)) == NULL)
25284d9c625SLionel Sambuc 		return (1);
25384d9c625SLionel Sambuc 	if (file_init(sp, frp, NULL, FS_SETALT |
25484d9c625SLionel Sambuc 	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
25584d9c625SLionel Sambuc 		return (1);
25684d9c625SLionel Sambuc 
25784d9c625SLionel Sambuc 	/* Switch and display a file count with the welcome message. */
25884d9c625SLionel Sambuc 	F_SET(sp, SC_FSWITCH | SC_STATUS_CNT);
25984d9c625SLionel Sambuc 
26084d9c625SLionel Sambuc 	return (0);
26184d9c625SLionel Sambuc }
26284d9c625SLionel Sambuc 
26384d9c625SLionel Sambuc /*
26484d9c625SLionel Sambuc  * ex_args -- :args
26584d9c625SLionel Sambuc  *	Display the list of files.
26684d9c625SLionel Sambuc  *
26784d9c625SLionel Sambuc  * PUBLIC: int ex_args __P((SCR *, EXCMD *));
26884d9c625SLionel Sambuc  */
26984d9c625SLionel Sambuc int
ex_args(SCR * sp,EXCMD * cmdp)27084d9c625SLionel Sambuc ex_args(SCR *sp, EXCMD *cmdp)
27184d9c625SLionel Sambuc {
27284d9c625SLionel Sambuc 	int cnt, sep;
27384d9c625SLionel Sambuc 	size_t col, len;
27484d9c625SLionel Sambuc 	char **ap;
27584d9c625SLionel Sambuc 
27684d9c625SLionel Sambuc 	if (sp->argv == NULL) {
27784d9c625SLionel Sambuc 		(void)msgq(sp, M_ERR, "114|No file list to display");
27884d9c625SLionel Sambuc 		return (0);
27984d9c625SLionel Sambuc 	}
28084d9c625SLionel Sambuc 
28184d9c625SLionel Sambuc 	col = len = sep = 0;
28284d9c625SLionel Sambuc 	for (cnt = 1, ap = sp->argv; *ap != NULL; ++ap) {
28384d9c625SLionel Sambuc 		col += len = strlen(*ap) + sep + (ap == sp->cargv ? 2 : 0);
28484d9c625SLionel Sambuc 		if (col >= sp->cols - 1) {
28584d9c625SLionel Sambuc 			col = len;
28684d9c625SLionel Sambuc 			sep = 0;
28784d9c625SLionel Sambuc 			(void)ex_puts(sp, "\n");
28884d9c625SLionel Sambuc 		} else if (cnt != 1) {
28984d9c625SLionel Sambuc 			sep = 1;
29084d9c625SLionel Sambuc 			(void)ex_puts(sp, " ");
29184d9c625SLionel Sambuc 		}
29284d9c625SLionel Sambuc 		++cnt;
29384d9c625SLionel Sambuc 
29484d9c625SLionel Sambuc 		(void)ex_printf(sp, "%s%s%s", ap == sp->cargv ? "[" : "",
29584d9c625SLionel Sambuc 		    *ap, ap == sp->cargv ? "]" : "");
29684d9c625SLionel Sambuc 		if (INTERRUPTED(sp))
29784d9c625SLionel Sambuc 			break;
29884d9c625SLionel Sambuc 	}
29984d9c625SLionel Sambuc 	(void)ex_puts(sp, "\n");
30084d9c625SLionel Sambuc 	return (0);
30184d9c625SLionel Sambuc }
30284d9c625SLionel Sambuc 
30384d9c625SLionel Sambuc /*
30484d9c625SLionel Sambuc  * ex_buildargv --
30584d9c625SLionel Sambuc  *	Build a new file argument list.
30684d9c625SLionel Sambuc  *
30784d9c625SLionel Sambuc  * PUBLIC: char **ex_buildargv __P((SCR *, EXCMD *, char *));
30884d9c625SLionel Sambuc  */
30984d9c625SLionel Sambuc char **
ex_buildargv(SCR * sp,EXCMD * cmdp,char * name)31084d9c625SLionel Sambuc ex_buildargv(SCR *sp, EXCMD *cmdp, char *name)
31184d9c625SLionel Sambuc {
31284d9c625SLionel Sambuc 	ARGS **argv;
31384d9c625SLionel Sambuc 	int argc;
31484d9c625SLionel Sambuc 	char **ap, **s_argv;
31584d9c625SLionel Sambuc 	const char *np;
31684d9c625SLionel Sambuc 	size_t nlen;
31784d9c625SLionel Sambuc 
31884d9c625SLionel Sambuc 	argc = cmdp == NULL ? 1 : cmdp->argc;
31984d9c625SLionel Sambuc 	CALLOC(sp, s_argv, char **, argc + 1, sizeof(char *));
32084d9c625SLionel Sambuc 	if ((ap = s_argv) == NULL)
32184d9c625SLionel Sambuc 		return (NULL);
32284d9c625SLionel Sambuc 
32384d9c625SLionel Sambuc 	if (cmdp == NULL) {
32484d9c625SLionel Sambuc 		if ((*ap = v_strdup(sp, name, strlen(name))) == NULL)
32584d9c625SLionel Sambuc 			return (NULL);
32684d9c625SLionel Sambuc 		++ap;
32784d9c625SLionel Sambuc 	} else
32884d9c625SLionel Sambuc 		for (argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv) {
32984d9c625SLionel Sambuc 			INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len,
33084d9c625SLionel Sambuc 				 np, nlen);
33184d9c625SLionel Sambuc 			if ((*ap = v_strdup(sp, np, nlen)) == NULL)
33284d9c625SLionel Sambuc 				return (NULL);
33384d9c625SLionel Sambuc 		}
33484d9c625SLionel Sambuc 	*ap = NULL;
33584d9c625SLionel Sambuc 	return (s_argv);
33684d9c625SLionel Sambuc }
337