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.
7 * See the LICENSE file for redistribution information.
13 static const char sccsid
[] = "$Id: ex_print.c,v 10.21 2000/07/14 14:29:20 skimo Exp $ (Berkeley) $Date: 2000/07/14 14:29:20 $";
16 #include <sys/types.h>
17 #include <sys/queue.h>
19 #include <bitstring.h>
31 #include "../common/common.h"
33 static int ex_prchars
__P((SCR
*, const char *, size_t *, size_t, u_int
, int));
36 * ex_list -- :[line [,line]] l[ist] [count] [flags]
38 * Display the addressed lines such that the output is unambiguous.
40 * PUBLIC: int ex_list __P((SCR *, EXCMD *));
47 if (ex_print(sp
, cmdp
,
48 &cmdp
->addr1
, &cmdp
->addr2
, cmdp
->iflags
| E_C_LIST
))
50 sp
->lno
= cmdp
->addr2
.lno
;
51 sp
->cno
= cmdp
->addr2
.cno
;
56 * ex_number -- :[line [,line]] nu[mber] [count] [flags]
58 * Display the addressed lines with a leading line number.
60 * PUBLIC: int ex_number __P((SCR *, EXCMD *));
67 if (ex_print(sp
, cmdp
,
68 &cmdp
->addr1
, &cmdp
->addr2
, cmdp
->iflags
| E_C_HASH
))
70 sp
->lno
= cmdp
->addr2
.lno
;
71 sp
->cno
= cmdp
->addr2
.cno
;
76 * ex_pr -- :[line [,line]] p[rint] [count] [flags]
78 * Display the addressed lines.
80 * PUBLIC: int ex_pr __P((SCR *, EXCMD *));
87 if (ex_print(sp
, cmdp
, &cmdp
->addr1
, &cmdp
->addr2
, cmdp
->iflags
))
89 sp
->lno
= cmdp
->addr2
.lno
;
90 sp
->cno
= cmdp
->addr2
.cno
;
96 * Print the selected lines.
98 * PUBLIC: int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
101 ex_print(sp
, cmdp
, fp
, tp
, flags
)
118 for (from
= fp
->lno
, to
= tp
->lno
; from
<= to
; ++from
) {
122 * Display the line number. The %6 format is specified
123 * by POSIX 1003.2, and is almost certainly large enough.
124 * Check, though, just in case.
126 if (LF_ISSET(E_C_HASH
)) {
127 if (from
<= 999999) {
128 snprintf(buf
, sizeof(buf
), "%6ld ", from
);
132 if (ex_prchars(sp
, p
, &col
, 8, 0, 0))
137 * Display the line. The format for E_C_PRINT isn't very good,
138 * especially in handling end-of-line tabs, but they're almost
139 * backward compatible.
141 if (db_get(sp
, from
, DBG_FATAL
, &wp
, &wlen
))
143 INT2CHAR(sp
, wp
, wlen
, p
, len
);
145 if (len
== 0 && !LF_ISSET(E_C_LIST
))
146 (void)ex_puts(sp
, "\n");
147 else if (ex_ldisplay(sp
, p
, len
, col
, flags
))
158 * Display a line without any preceding number.
160 * PUBLIC: int ex_ldisplay __P((SCR *, const char *, size_t, size_t, u_int));
163 ex_ldisplay(sp
, p
, len
, col
, flags
)
169 if (len
> 0 && ex_prchars(sp
, p
, &col
, len
, LF_ISSET(E_C_LIST
), 0))
171 if (!INTERRUPTED(sp
) && LF_ISSET(E_C_LIST
)) {
173 if (ex_prchars(sp
, p
, &col
, 1, LF_ISSET(E_C_LIST
), 0))
176 if (!INTERRUPTED(sp
))
177 (void)ex_puts(sp
, "\n");
183 * Display a line for the substitute with confirmation routine.
185 * PUBLIC: int ex_scprint __P((SCR *, MARK *, MARK *));
188 ex_scprint(sp
, fp
, tp
)
198 if (O_ISSET(sp
, O_NUMBER
)) {
200 if (ex_prchars(sp
, p
, &col
, 8, 0, 0))
204 if (db_get(sp
, fp
->lno
, DBG_FATAL
, &wp
, &wlen
))
206 INT2CHAR(sp
, wp
, wlen
, p
, len
);
208 if (ex_prchars(sp
, p
, &col
, fp
->cno
, 0, ' '))
212 p
, &col
, tp
->cno
== fp
->cno
? 1 : tp
->cno
- fp
->cno
, 0, '^'))
216 p
= "[ynq]"; /* XXX: should be msg_cat. */
217 if (ex_prchars(sp
, p
, &col
, 5, 0, 0))
225 * Local routine to dump characters to the screen.
228 ex_prchars(sp
, p
, colp
, len
, flags
, repeatc
)
238 size_t col
, tlen
, ts
;
240 if (O_ISSET(sp
, O_LIST
))
243 ts
= O_VAL(sp
, O_TABSTOP
);
244 for (col
= *colp
; len
--;)
245 if ((ch
= *p
++) == '\t' && !LF_ISSET(E_C_LIST
))
246 for (tlen
= ts
- col
% ts
;
247 col
< sp
->cols
&& tlen
--; ++col
) {
249 "%c", repeatc
? repeatc
: ' ');
254 kp
= KEY_NAME(sp
, ch
);
255 tlen
= KEY_LEN(sp
, ch
);
256 if (!repeatc
&& col
+ tlen
< sp
->cols
) {
257 (void)ex_puts(sp
, kp
);
260 for (; tlen
--; ++kp
, ++col
) {
261 if (col
== sp
->cols
) {
263 (void)ex_puts(sp
, "\n");
266 "%c", repeatc
? repeatc
: *kp
);
277 * Ex's version of printf.
279 * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
283 ex_printf(SCR
*sp
, const char *fmt
, ...)
285 ex_printf(sp
, fmt
, va_alist
)
303 exp
->obp_len
+= n
= vsnprintf(exp
->obp
+ exp
->obp_len
,
304 sizeof(exp
->obp
) - exp
->obp_len
, fmt
, ap
);
307 /* Flush when reach a <newline> or half the buffer. */
308 if (exp
->obp
[exp
->obp_len
- 1] == '\n' ||
309 exp
->obp_len
> sizeof(exp
->obp
) / 2)
316 * Ex's version of puts.
318 * PUBLIC: int ex_puts __P((SCR *, const char *));
330 /* Flush when reach a <newline> or the end of the buffer. */
331 for (doflush
= n
= 0; *str
!= '\0'; ++n
) {
332 if (exp
->obp_len
> sizeof(exp
->obp
))
334 if ((exp
->obp
[exp
->obp_len
++] = *str
++) == '\n')
344 * Ex's version of fflush.
346 * PUBLIC: int ex_fflush __P((SCR *sp));
356 if (exp
->obp_len
!= 0) {
357 sp
->gp
->scr_msg(sp
, M_NONE
, exp
->obp
, exp
->obp_len
);