2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
9 static char sccsid
[] = "$Id: v_replace.c,v 8.12 1993/12/09 19:43:17 bostic Exp $ (Berkeley) $Date: 1993/12/09 19:43:17 $";
12 #include <sys/types.h>
23 * v_replace -- [count]rc
24 * The r command in historic vi was almost beautiful in its badness.
25 * For example, "r<erase>" and "r<word erase>" beeped the terminal
26 * and deleted a single character. "Nr<carriage return>", where N
27 * was greater than 1, inserted a single carriage return. This may
28 * not be right, but at least it's not insane.
31 v_replace(sp
, ep
, vp
, fm
, tm
, rp
)
46 * If the line doesn't exist, or it's empty, replacement isn't
47 * allowed. It's not hard to implement, but:
49 * 1: It's historic practice.
50 * 2: For consistency, this change would require that the more
51 * general case, "Nr", when the user is < N characters from
52 * the end of the line, also work.
53 * 3: Replacing a newline has somewhat odd semantics.
55 if ((p
= file_gline(sp
, ep
, fm
->lno
, &len
)) == NULL
) {
56 if (file_lline(sp
, ep
, &lno
))
59 GETLINE_ERR(sp
, fm
->lno
);
65 nochar
: msgq(sp
, M_BERR
, "No characters to replace");
70 * Figure out how many characters to be replace; for no particular
71 * reason other than that the semantics of replacing the newline
72 * are confusing, only permit the replacement of the characters in
73 * the current line. I suppose we could simply append the replacement
74 * characters to the line, but I see no compelling reason to do so.
76 cnt
= F_ISSET(vp
, VC_C1SET
) ? vp
->count
: 1;
77 rp
->cno
= fm
->cno
+ cnt
- 1;
78 if (rp
->cno
> len
- 1) {
83 /* Get the character, literal escapes, escape terminates. */
84 if (F_ISSET(vp
, VC_ISDOT
)) {
85 ikey
.ch
= VIP(sp
)->rlast
;
86 ikey
.value
= term_key_val(sp
, ikey
.ch
);
88 if (term_key(sp
, &ikey
, 0) != INP_OK
)
95 if (term_key(sp
, &ikey
, 0) != INP_OK
)
99 VIP(sp
)->rlast
= ikey
.ch
;
103 GET_SPACE_RET(sp
, bp
, blen
, len
);
107 if (ikey
.value
== K_CR
|| ikey
.value
== K_NL
) {
108 /* Set return line. */
109 rp
->lno
= fm
->lno
+ cnt
;
111 /* The first part of the current line. */
112 if (file_sline(sp
, ep
, fm
->lno
, p
, fm
->cno
))
116 * The rest of the current line. And, of course, now it gets
117 * tricky. Any white space after the replaced character is
118 * stripped, and autoindent is applied. Put the cursor on the
119 * last indent character as did historic vi.
121 for (p
+= fm
->cno
+ cnt
, len
-= fm
->cno
+ cnt
;
122 len
&& isblank(*p
); --len
, ++p
);
124 if ((tp
= text_init(sp
, p
, len
, len
)) == NULL
)
126 if (txt_auto(sp
, ep
, fm
->lno
, NULL
, 0, tp
))
128 rp
->cno
= tp
->ai
? tp
->ai
- 1 : 0;
129 if (file_aline(sp
, ep
, 1, fm
->lno
, tp
->lb
, tp
->len
))
135 /* All of the middle lines. */
137 if (file_aline(sp
, ep
, 1, fm
->lno
, "", 0)) {
142 memset(bp
+ fm
->cno
, ikey
.ch
, cnt
);
143 rval
= file_sline(sp
, ep
, fm
->lno
, bp
, len
);
146 rp
->cno
= fm
->cno
+ cnt
- 1;
148 FREE_SPACE(sp
, bp
, blen
);