Remove building with NOCRYPTO option
[minix3.git] / external / bsd / nvi / dist / ex / ex_append.c
blob3369ad29a71992f9dedec4c29d3bed51c6e86de8
1 /* $NetBSD: ex_append.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
2 /*-
3 * Copyright (c) 1992, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved.
8 * See the LICENSE file for redistribution information.
9 */
11 #include "config.h"
13 #include <sys/cdefs.h>
14 #if 0
15 #ifndef lint
16 static const char sccsid[] = "Id: ex_append.c,v 10.34 2001/06/25 15:19:14 skimo Exp (Berkeley) Date: 2001/06/25 15:19:14 ";
17 #endif /* not lint */
18 #else
19 __RCSID("$NetBSD: ex_append.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
20 #endif
22 #include <sys/types.h>
23 #include <sys/queue.h>
25 #include <bitstring.h>
26 #include <limits.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
31 #include "../common/common.h"
33 enum which {APPEND, CHANGE, INSERT};
35 static int ex_aci __P((SCR *, EXCMD *, enum which));
38 * ex_append -- :[line] a[ppend][!]
39 * Append one or more lines of new text after the specified line,
40 * or the current line if no address is specified.
42 * PUBLIC: int ex_append __P((SCR *, EXCMD *));
44 int
45 ex_append(SCR *sp, EXCMD *cmdp)
47 return (ex_aci(sp, cmdp, APPEND));
51 * ex_change -- :[line[,line]] c[hange][!] [count]
52 * Change one or more lines to the input text.
54 * PUBLIC: int ex_change __P((SCR *, EXCMD *));
56 int
57 ex_change(SCR *sp, EXCMD *cmdp)
59 return (ex_aci(sp, cmdp, CHANGE));
63 * ex_insert -- :[line] i[nsert][!]
64 * Insert one or more lines of new text before the specified line,
65 * or the current line if no address is specified.
67 * PUBLIC: int ex_insert __P((SCR *, EXCMD *));
69 int
70 ex_insert(SCR *sp, EXCMD *cmdp)
72 return (ex_aci(sp, cmdp, INSERT));
76 * ex_aci --
77 * Append, change, insert in ex.
79 static int
80 ex_aci(SCR *sp, EXCMD *cmdp, enum which cmd)
82 CHAR_T *p, *t;
83 GS *gp;
84 TEXT *tp;
85 TEXTH tiq;
86 db_recno_t cnt, lno;
87 size_t len;
88 u_int32_t flags;
89 int need_newline;
91 gp = sp->gp;
92 NEEDFILE(sp, cmdp);
95 * If doing a change, replace lines for as long as possible. Then,
96 * append more lines or delete remaining lines. Changes to an empty
97 * file are appends, inserts are the same as appends to the previous
98 * line.
100 * !!!
101 * Set the address to which we'll append. We set sp->lno to this
102 * address as well so that autoindent works correctly when get text
103 * from the user.
105 lno = cmdp->addr1.lno;
106 sp->lno = lno;
107 if ((cmd == CHANGE || cmd == INSERT) && lno != 0)
108 --lno;
111 * !!!
112 * If the file isn't empty, cut changes into the unnamed buffer.
114 if (cmd == CHANGE && cmdp->addr1.lno != 0 &&
115 (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
116 del(sp, &cmdp->addr1, &cmdp->addr2, 1)))
117 return (1);
120 * !!!
121 * Anything that was left after the command separator becomes part
122 * of the inserted text. Apparently, it was common usage to enter:
124 * :g/pattern/append|stuff1
126 * and append the line of text "stuff1" to the lines containing the
127 * pattern. It was also historically legal to enter:
129 * :append|stuff1
130 * stuff2
133 * and the text on the ex command line would be appended as well as
134 * the text inserted after it. There was an historic bug however,
135 * that the user had to enter *two* terminating lines (the '.' lines)
136 * to terminate text input mode, in this case. This whole thing
137 * could be taken too far, however. Entering:
139 * :append|stuff1\
140 * stuff2
141 * stuff3
144 * i.e. mixing and matching the forms confused the historic vi, and,
145 * not only did it take two terminating lines to terminate text input
146 * mode, but the trailing backslashes were retained on the input. We
147 * match historic practice except that we discard the backslashes.
149 * Input lines specified on the ex command line lines are separated by
150 * <newline>s. If there is a trailing delimiter an empty line was
151 * inserted. There may also be a leading delimiter, which is ignored
152 * unless it's also a trailing delimiter. It is possible to encounter
153 * a termination line, i.e. a single '.', in a global command, but not
154 * necessary if the text insert command was the last of the global
155 * commands.
157 if (cmdp->save_cmdlen != 0) {
158 for (p = cmdp->save_cmd,
159 len = cmdp->save_cmdlen; len > 0; p = t) {
160 for (t = p; len > 0 && t[0] != '\n'; ++t, --len);
161 if (t != p || len == 0) {
162 if (F_ISSET(sp, SC_EX_GLOBAL) &&
163 t - p == 1 && p[0] == '.') {
164 ++t;
165 if (len > 0)
166 --len;
167 break;
169 if (db_append(sp, 1, lno++, p, t - p))
170 return (1);
172 if (len != 0) {
173 ++t;
174 if (--len == 0 &&
175 db_append(sp, 1, lno++, NULL, 0))
176 return (1);
180 * If there's any remaining text, we're in a global, and
181 * there's more command to parse.
183 * !!!
184 * We depend on the fact that non-global commands will eat the
185 * rest of the command line as text input, and before getting
186 * any text input from the user. Otherwise, we'd have to save
187 * off the command text before or during the call to the text
188 * input function below.
190 if (len != 0)
191 cmdp->save_cmd = t;
192 cmdp->save_cmdlen = len;
195 if (F_ISSET(sp, SC_EX_GLOBAL)) {
196 if ((sp->lno = lno) == 0 && db_exist(sp, 1))
197 sp->lno = 1;
198 return (0);
202 * If not in a global command, read from the terminal.
204 * If this code is called by vi, we want to reset the terminal and use
205 * ex's line get routine. It actually works fine if we use vi's get
206 * routine, but it doesn't look as nice. Maybe if we had a separate
207 * window or something, but getting a line at a time looks awkward.
208 * However, depending on the screen that we're using, that may not
209 * be possible.
211 if (F_ISSET(sp, SC_VI)) {
212 if (gp->scr_screen(sp, SC_EX)) {
213 ex_wemsg(sp, cmdp->cmd->name, EXM_NOCANON);
214 return (1);
217 /* If we're still in the vi screen, move out explicitly. */
218 need_newline = !F_ISSET(sp, SC_SCR_EXWROTE);
219 F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
220 if (need_newline)
221 (void)ex_puts(sp, "\n");
224 * !!!
225 * Users of historical versions of vi sometimes get confused
226 * when they enter append mode, and can't seem to get out of
227 * it. Give them an informational message.
229 (void)ex_puts(sp,
230 msg_cat(sp, "273|Entering ex input mode.", NULL));
231 (void)ex_puts(sp, "\n");
232 (void)ex_fflush(sp);
236 * Set input flags; the ! flag turns off autoindent for append,
237 * change and insert.
239 LF_INIT(TXT_DOTTERM | TXT_NUMBER);
240 if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && O_ISSET(sp, O_AUTOINDENT))
241 LF_SET(TXT_AUTOINDENT);
242 if (O_ISSET(sp, O_BEAUTIFY))
243 LF_SET(TXT_BEAUTIFY);
246 * This code can't use the common screen TEXTH structure (sp->tiq),
247 * as it may already be in use, e.g. ":append|s/abc/ABC/" would fail
248 * as we are only halfway through the text when the append code fires.
249 * Use a local structure instead. (The ex code would have to use a
250 * local structure except that we're guaranteed to finish remaining
251 * characters in the common TEXTH structure when they were inserted
252 * into the file, above.)
254 memset(&tiq, 0, sizeof(TEXTH));
255 TAILQ_INIT(&tiq);
257 if (ex_txt(sp, &tiq, 0, flags))
258 return (1);
260 for (cnt = 0, tp = TAILQ_FIRST(&tiq); tp != NULL;
261 ++cnt, tp = TAILQ_NEXT(tp, q))
262 if (db_append(sp, 1, lno++, tp->lb, tp->len))
263 return (1);
266 * Set sp->lno to the final line number value (correcting for a
267 * possible 0 value) as that's historically correct for the final
268 * line value, whether or not the user entered any text.
270 if ((sp->lno = lno) == 0 && db_exist(sp, 1))
271 sp->lno = 1;
273 return (0);