xref: /freebsd/contrib/nvi/ex/ex_edit.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
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
13 static 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 
30 static 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  */
48 int
49 ex_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  */
110 static int
111 ex_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