1/*-
2 * Copyright (c) 1992, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 *	Keith Bostic.  All rights reserved.
6 *
7 * See the LICENSE file for redistribution information.
8 */
9
10#include "config.h"
11
12#ifndef lint
13static const char sccsid[] = "@(#)ex_edit.c	10.10 (Berkeley) 4/27/96";
14#endif /* not lint */
15
16#include <sys/types.h>
17#include <sys/queue.h>
18#include <sys/time.h>
19
20#include <bitstring.h>
21#include <errno.h>
22#include <limits.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "../common/common.h"
28#include "../vi/vi.h"
29
30static int ex_N_edit __P((SCR *, EXCMD *, FREF *, int));
31
32/*
33 * ex_edit --	:e[dit][!] [+cmd] [file]
34 *		:ex[!] [+cmd] [file]
35 *		:vi[sual][!] [+cmd] [file]
36 *
37 * Edit a file; if none specified, re-edit the current file.  The third
38 * form of the command can only be executed while in vi mode.  See the
39 * hack in ex.c:ex_cmd().
40 *
41 * !!!
42 * Historic vi didn't permit the '+' command form without specifying
43 * a file name as well.  This seems unreasonable, so we support it
44 * regardless.
45 *
46 * PUBLIC: int ex_edit __P((SCR *, EXCMD *));
47 */
48int
49ex_edit(sp, cmdp)
50	SCR *sp;
51	EXCMD *cmdp;
52{
53	FREF *frp;
54	int attach, setalt;
55
56	switch (cmdp->argc) {
57	case 0:
58		/*
59		 * If the name has been changed, we edit that file, not the
60		 * original name.  If the user was editing a temporary file
61		 * (or wasn't editing any file), create another one.  The
62		 * reason for not reusing temporary files is that there is
63		 * special exit processing of them, and reuse is tricky.
64		 */
65		frp = sp->frp;
66		if (sp->ep == NULL || F_ISSET(frp, FR_TMPFILE)) {
67			if ((frp = file_add(sp, NULL)) == NULL)
68				return (1);
69			attach = 0;
70		} else
71			attach = 1;
72		setalt = 0;
73		break;
74	case 1:
75		if ((frp = file_add(sp, cmdp->argv[0]->bp)) == NULL)
76			return (1);
77		attach = 0;
78		setalt = 1;
79		set_alt_name(sp, cmdp->argv[0]->bp);
80		break;
81	default:
82		abort();
83	}
84
85	if (F_ISSET(cmdp, E_NEWSCREEN))
86		return (ex_N_edit(sp, cmdp, frp, attach));
87
88	/*
89	 * Check for modifications.
90	 *
91	 * !!!
92	 * Contrary to POSIX 1003.2-1992, autowrite did not affect :edit.
93	 */
94	if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
95		return (1);
96
97	/* Switch files. */
98	if (file_init(sp, frp, NULL, (setalt ? FS_SETALT : 0) |
99	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
100		return (1);
101
102	F_SET(sp, SC_FSWITCH);
103	return (0);
104}
105
106/*
107 * ex_N_edit --
108 *	New screen version of ex_edit.
109 */
110static int
111ex_N_edit(sp, cmdp, frp, attach)
112	SCR *sp;
113	EXCMD *cmdp;
114	FREF *frp;
115	int attach;
116{
117	SCR *new;
118
119	/* Get a new screen. */
120	if (screen_init(sp->gp, sp, &new))
121		return (1);
122	if (vs_split(sp, new, 0)) {
123		(void)screen_end(new);
124		return (1);
125	}
126
127	/* Get a backing file. */
128	if (attach) {
129		/* Copy file state, keep the screen and cursor the same. */
130		new->ep = sp->ep;
131		++new->ep->refcnt;
132
133		new->frp = frp;
134		new->frp->flags = sp->frp->flags;
135
136		new->lno = sp->lno;
137		new->cno = sp->cno;
138	} else if (file_init(new, frp, NULL,
139	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
140		(void)vs_discard(new, NULL);
141		(void)screen_end(new);
142		return (1);
143	}
144
145	/* Create the argument list. */
146	new->cargv = new->argv = ex_buildargv(sp, NULL, frp->name);
147
148	/* Set up the switch. */
149	sp->nextdisp = new;
150	F_SET(sp, SC_SSWITCH);
151
152	return (0);
153}
154