Merge from vendor branch DIFFUTILS:
[dragonfly.git] / contrib / nvi / ex / ex_edit.c
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 }