1 /* $NetBSD: ex_append.c,v 1.1.1.2 2008/05/18 14:31:11 aymeric Exp $ */
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1992, 1993, 1994, 1995, 1996
7 * Keith Bostic. All rights reserved.
9 * See the LICENSE file for redistribution information.
15 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";
18 #include <sys/types.h>
19 #include <sys/queue.h>
21 #include <bitstring.h>
27 #include "../common/common.h"
29 enum which
{APPEND
, CHANGE
, INSERT
};
31 static int ex_aci
__P((SCR
*, EXCMD
*, enum which
));
34 * ex_append -- :[line] a[ppend][!]
35 * Append one or more lines of new text after the specified line,
36 * or the current line if no address is specified.
38 * PUBLIC: int ex_append __P((SCR *, EXCMD *));
41 ex_append(SCR
*sp
, EXCMD
*cmdp
)
43 return (ex_aci(sp
, cmdp
, APPEND
));
47 * ex_change -- :[line[,line]] c[hange][!] [count]
48 * Change one or more lines to the input text.
50 * PUBLIC: int ex_change __P((SCR *, EXCMD *));
53 ex_change(SCR
*sp
, EXCMD
*cmdp
)
55 return (ex_aci(sp
, cmdp
, CHANGE
));
59 * ex_insert -- :[line] i[nsert][!]
60 * Insert one or more lines of new text before the specified line,
61 * or the current line if no address is specified.
63 * PUBLIC: int ex_insert __P((SCR *, EXCMD *));
66 ex_insert(SCR
*sp
, EXCMD
*cmdp
)
68 return (ex_aci(sp
, cmdp
, INSERT
));
73 * Append, change, insert in ex.
76 ex_aci(SCR
*sp
, EXCMD
*cmdp
, enum which cmd
)
91 * If doing a change, replace lines for as long as possible. Then,
92 * append more lines or delete remaining lines. Changes to an empty
93 * file are appends, inserts are the same as appends to the previous
97 * Set the address to which we'll append. We set sp->lno to this
98 * address as well so that autoindent works correctly when get text
101 lno
= cmdp
->addr1
.lno
;
103 if ((cmd
== CHANGE
|| cmd
== INSERT
) && lno
!= 0)
108 * If the file isn't empty, cut changes into the unnamed buffer.
110 if (cmd
== CHANGE
&& cmdp
->addr1
.lno
!= 0 &&
111 (cut(sp
, NULL
, &cmdp
->addr1
, &cmdp
->addr2
, CUT_LINEMODE
) ||
112 del(sp
, &cmdp
->addr1
, &cmdp
->addr2
, 1)))
117 * Anything that was left after the command separator becomes part
118 * of the inserted text. Apparently, it was common usage to enter:
120 * :g/pattern/append|stuff1
122 * and append the line of text "stuff1" to the lines containing the
123 * pattern. It was also historically legal to enter:
129 * and the text on the ex command line would be appended as well as
130 * the text inserted after it. There was an historic bug however,
131 * that the user had to enter *two* terminating lines (the '.' lines)
132 * to terminate text input mode, in this case. This whole thing
133 * could be taken too far, however. Entering:
140 * i.e. mixing and matching the forms confused the historic vi, and,
141 * not only did it take two terminating lines to terminate text input
142 * mode, but the trailing backslashes were retained on the input. We
143 * match historic practice except that we discard the backslashes.
145 * Input lines specified on the ex command line lines are separated by
146 * <newline>s. If there is a trailing delimiter an empty line was
147 * inserted. There may also be a leading delimiter, which is ignored
148 * unless it's also a trailing delimiter. It is possible to encounter
149 * a termination line, i.e. a single '.', in a global command, but not
150 * necessary if the text insert command was the last of the global
153 if (cmdp
->save_cmdlen
!= 0) {
154 for (p
= cmdp
->save_cmd
,
155 len
= cmdp
->save_cmdlen
; len
> 0; p
= t
) {
156 for (t
= p
; len
> 0 && t
[0] != '\n'; ++t
, --len
);
157 if (t
!= p
|| len
== 0) {
158 if (F_ISSET(sp
, SC_EX_GLOBAL
) &&
159 t
- p
== 1 && p
[0] == '.') {
165 if (db_append(sp
, 1, lno
++, p
, t
- p
))
171 db_append(sp
, 1, lno
++, NULL
, 0))
176 * If there's any remaining text, we're in a global, and
177 * there's more command to parse.
180 * We depend on the fact that non-global commands will eat the
181 * rest of the command line as text input, and before getting
182 * any text input from the user. Otherwise, we'd have to save
183 * off the command text before or during the call to the text
184 * input function below.
188 cmdp
->save_cmdlen
= len
;
191 if (F_ISSET(sp
, SC_EX_GLOBAL
)) {
192 if ((sp
->lno
= lno
) == 0 && db_exist(sp
, 1))
198 * If not in a global command, read from the terminal.
200 * If this code is called by vi, we want to reset the terminal and use
201 * ex's line get routine. It actually works fine if we use vi's get
202 * routine, but it doesn't look as nice. Maybe if we had a separate
203 * window or something, but getting a line at a time looks awkward.
204 * However, depending on the screen that we're using, that may not
207 if (F_ISSET(sp
, SC_VI
)) {
208 if (gp
->scr_screen(sp
, SC_EX
)) {
209 ex_wemsg(sp
, cmdp
->cmd
->name
, EXM_NOCANON
);
213 /* If we're still in the vi screen, move out explicitly. */
214 need_newline
= !F_ISSET(sp
, SC_SCR_EXWROTE
);
215 F_SET(sp
, SC_SCR_EX
| SC_SCR_EXWROTE
);
217 (void)ex_puts(sp
, "\n");
221 * Users of historical versions of vi sometimes get confused
222 * when they enter append mode, and can't seem to get out of
223 * it. Give them an informational message.
226 msg_cat(sp
, "273|Entering ex input mode.", NULL
));
227 (void)ex_puts(sp
, "\n");
232 * Set input flags; the ! flag turns off autoindent for append,
235 LF_INIT(TXT_DOTTERM
| TXT_NUMBER
);
236 if (!FL_ISSET(cmdp
->iflags
, E_C_FORCE
) && O_ISSET(sp
, O_AUTOINDENT
))
237 LF_SET(TXT_AUTOINDENT
);
238 if (O_ISSET(sp
, O_BEAUTIFY
))
239 LF_SET(TXT_BEAUTIFY
);
242 * This code can't use the common screen TEXTH structure (sp->tiq),
243 * as it may already be in use, e.g. ":append|s/abc/ABC/" would fail
244 * as we are only halfway through the text when the append code fires.
245 * Use a local structure instead. (The ex code would have to use a
246 * local structure except that we're guaranteed to finish remaining
247 * characters in the common TEXTH structure when they were inserted
248 * into the file, above.)
250 memset(&tiq
, 0, sizeof(TEXTH
));
253 if (ex_txt(sp
, &tiq
, 0, flags
))
256 for (cnt
= 0, tp
= tiq
.cqh_first
;
257 tp
!= (TEXT
*)(void *)&tiq
; ++cnt
, tp
= tp
->q
.cqe_next
)
258 if (db_append(sp
, 1, lno
++, tp
->lb
, tp
->len
))
262 * Set sp->lno to the final line number value (correcting for a
263 * possible 0 value) as that's historically correct for the final
264 * line value, whether or not the user entered any text.
266 if ((sp
->lno
= lno
) == 0 && db_exist(sp
, 1))