rework initial error handling -- since we check for any screens on
[nvi.git] / ex / ex_args.c
blob4abd5fd84e5c9f7aea1de65c44f69335cbf3b66f
1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: ex_args.c,v 8.13 1993/12/20 09:35:28 bostic Exp $ (Berkeley) $Date: 1993/12/20 09:35:28 $";
10 #endif /* not lint */
12 #include <sys/types.h>
14 #include <errno.h>
15 #include <stdlib.h>
16 #include <string.h>
18 #include "vi.h"
19 #include "excmd.h"
22 * ex_next -- :next [files]
23 * Edit the next file, optionally setting the list of files.
25 * !!!
26 * The :next command behaved differently from the :rewind command in
27 * historic vi. See nvi/docs/autowrite for details, but the basic
28 * idea was that it ignored the force flag if the autowrite flag was
29 * set. This implementation handles them all identically.
31 int
32 ex_next(sp, ep, cmdp)
33 SCR *sp;
34 EXF *ep;
35 EXCMDARG *cmdp;
37 ARGS **argv;
38 FREF *frp;
39 char *name;
41 MODIFY_CHECK(sp, ep, F_ISSET(cmdp, E_FORCE));
43 if (cmdp->argc) {
44 /* Mark all the current files as ignored. */
45 for (frp = sp->frefq.cqh_first;
46 frp != (FREF *)&sp->frefq; frp = frp->q.cqe_next)
47 F_SET(frp, FR_IGNORE);
49 /* Add the new files into the file list. */
50 for (argv = cmdp->argv; argv[0]->len != 0; ++argv)
51 if (file_add(sp, NULL, argv[0]->bp, 0) == NULL)
52 return (1);
54 if ((frp = file_first(sp)) == NULL)
55 return (1);
56 } else if ((frp = file_next(sp, sp->a_frp)) == NULL) {
57 msgq(sp, M_ERR, "No more files to edit.");
58 return (1);
62 * There's a tricky sequence, where the user edits two files, e.g.
63 * "x" and "y". While in "x", they do ":e y|:f foo", which changes
64 * the name of that FRP entry. Then, the :n command finds the file
65 * "y" with a name change. If the file name has been changed, get
66 * a new FREF for the original file name, and make it be the one that
67 * is displayed in the argument list, not the one with the name change.
69 if (frp->cname != NULL) {
70 F_SET(frp, FR_IGNORE);
71 name = frp->name == NULL ? frp->tname : frp->name;
72 if ((frp = file_add(sp, sp->a_frp, name, 0)) == NULL)
73 return (1);
75 if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE)))
76 return (1);
77 sp->a_frp = frp;
78 F_SET(sp, S_FSWITCH);
79 return (0);
83 * ex_prev -- :prev
84 * Edit the previous file.
86 int
87 ex_prev(sp, ep, cmdp)
88 SCR *sp;
89 EXF *ep;
90 EXCMDARG *cmdp;
92 FREF *frp;
93 char *name;
95 MODIFY_CHECK(sp, ep, F_ISSET(cmdp, E_FORCE));
97 if ((frp = file_prev(sp, sp->a_frp)) == NULL) {
98 msgq(sp, M_ERR, "No previous files to edit.");
99 return (1);
102 /* See comment in ex_next(). */
103 if (frp->cname != NULL) {
104 F_SET(frp, FR_IGNORE);
105 name = frp->name == NULL ? frp->tname : frp->name;
106 if ((frp = file_add(sp, frp, name, 0)) == NULL)
107 return (1);
109 if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE)))
110 return (1);
111 sp->a_frp = frp;
112 F_SET(sp, S_FSWITCH);
113 return (0);
117 * ex_rew -- :rew
118 * Re-edit the list of files.
121 ex_rew(sp, ep, cmdp)
122 SCR *sp;
123 EXF *ep;
124 EXCMDARG *cmdp;
126 FREF *frp, *tfrp;
129 * !!!
130 * Historic practice -- you can rewind to the current file.
132 if ((frp = file_first(sp)) == NULL) {
133 msgq(sp, M_ERR, "No previous files to rewind.");
134 return (1);
137 MODIFY_CHECK(sp, ep, F_ISSET(cmdp, E_FORCE));
140 * !!!
141 * Historic practice, turn off the edited bit. The :next and :prev
142 * code will discard any name changes, so ignore them here. Start
143 * at the beginning of the file, too.
145 for (tfrp = sp->frefq.cqh_first;
146 tfrp != (FREF *)&sp->frefq; tfrp = tfrp->q.cqe_next)
147 F_CLR(tfrp, FR_CHANGEWRITE | FR_CURSORSET | FR_EDITED);
149 if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE)))
150 return (1);
151 sp->a_frp = frp;
152 F_SET(sp, S_FSWITCH);
153 return (0);
157 * ex_args -- :args
158 * Display the list of files.
161 ex_args(sp, ep, cmdp)
162 SCR *sp;
163 EXF *ep;
164 EXCMDARG *cmdp;
166 FREF *frp;
167 int cnt, col, iscur, len, nlen, sep;
168 char *name;
171 * !!!
172 * Ignore files that aren't in the "argument" list unless they are the
173 * one we're currently editing. I'm not sure this is right, but the
174 * historic vi behavior of not showing the current file if it was the
175 * result of a ":e" command, or if the file name was changed was wrong.
176 * This is actually pretty tricky, don't modify it without thinking it
177 * through. There have been a lot of problems in here.
179 * Also, historic practice was to display the original name of the file
180 * even if the user had used a file command to change the file name.
181 * Confusing, at best. We show both names: the original as that's what
182 * the user will get in a next, prev or rewind, and the new one since
183 * that's what the user is actually editing now.
185 * When we find the "argument" FREF, i.e. the current location in the
186 * user's argument list, if it's not the same as the current FREF, we
187 * display the current FREF as following the argument in the list.
188 * This means that if the user edits three files, "x", "y" and "z", and
189 * then does a :e command in the file "x" to edit "z", "z" will appear
190 * in the list twice.
192 col = len = sep = 0;
193 for (cnt = 1, frp = sp->frefq.cqh_first;
194 frp != (FREF *)&sp->frefq; frp = frp->q.cqe_next) {
195 iscur = 0;
197 * If the last argument FREF structure, and we're editing
198 * it, set the current bit. Otherwise, we'll display it,
199 * then the file we're editing, and the latter will have
200 * the current bit set.
202 if (frp == sp->a_frp) {
203 if (frp == sp->frp && frp->cname == NULL)
204 iscur = 1;
205 } else if (F_ISSET(frp, FR_IGNORE))
206 continue;
207 name = frp->name == NULL ? frp->tname : frp->name;
209 * Mistake. The user edited a temporary file (vi /tmp), then
210 * switched to another file (:e file). The argument FREF is
211 * pointing to the temporary file, but it doesn't have a name.
212 * Gracefully recover through the creative use of goto's.
214 if (name == NULL)
215 goto testcur;
216 extra: nlen = strlen(name);
217 col += len = nlen + sep + (iscur ? 2 : 0);
218 if (col >= sp->cols - 1) {
219 col = len;
220 sep = 0;
221 (void)ex_printf(EXCOOKIE, "\n");
222 } else if (cnt != 1) {
223 sep = 1;
224 (void)ex_printf(EXCOOKIE, " ");
226 ++cnt;
228 if (iscur)
229 (void)ex_printf(EXCOOKIE, "[%s]", name);
230 else {
231 (void)ex_printf(EXCOOKIE, "%s", name);
232 testcur: if (frp == sp->a_frp) {
233 if (frp != sp->frp)
234 name = FILENAME(sp->frp);
235 else
236 name = frp->cname;
237 iscur = 1;
238 goto extra;
242 /* This should never happen; left in because it's been known to. */
243 if (cnt == 1)
244 (void)ex_printf(EXCOOKIE, "No files.\n");
245 else
246 (void)ex_printf(EXCOOKIE, "\n");
247 return (0);