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.26 2013/11/02 02:11:07 zy Exp $";
16 #include <sys/types.h>
17 #include <sys/queue.h>
20 #include <bitstring.h>
27 #include "../common/common.h"
29 static int ex_prchars(SCR
*,
30 const CHAR_T
*, size_t *, size_t, u_int
, int);
33 * ex_list -- :[line [,line]] l[ist] [count] [flags]
35 * Display the addressed lines such that the output is unambiguous.
37 * PUBLIC: int ex_list(SCR *, EXCMD *);
40 ex_list(SCR
*sp
, EXCMD
*cmdp
)
42 if (ex_print(sp
, cmdp
,
43 &cmdp
->addr1
, &cmdp
->addr2
, cmdp
->iflags
| E_C_LIST
))
45 sp
->lno
= cmdp
->addr2
.lno
;
46 sp
->cno
= cmdp
->addr2
.cno
;
51 * ex_number -- :[line [,line]] nu[mber] [count] [flags]
53 * Display the addressed lines with a leading line number.
55 * PUBLIC: int ex_number(SCR *, EXCMD *);
58 ex_number(SCR
*sp
, EXCMD
*cmdp
)
60 if (ex_print(sp
, cmdp
,
61 &cmdp
->addr1
, &cmdp
->addr2
, cmdp
->iflags
| E_C_HASH
))
63 sp
->lno
= cmdp
->addr2
.lno
;
64 sp
->cno
= cmdp
->addr2
.cno
;
69 * ex_pr -- :[line [,line]] p[rint] [count] [flags]
71 * Display the addressed lines.
73 * PUBLIC: int ex_pr(SCR *, EXCMD *);
76 ex_pr(SCR
*sp
, EXCMD
*cmdp
)
78 if (ex_print(sp
, cmdp
, &cmdp
->addr1
, &cmdp
->addr2
, cmdp
->iflags
))
80 sp
->lno
= cmdp
->addr2
.lno
;
81 sp
->cno
= cmdp
->addr2
.cno
;
87 * Print the selected lines.
89 * PUBLIC: int ex_print(SCR *, EXCMD *, MARK *, MARK *, u_int32_t);
92 ex_print(SCR
*sp
, EXCMD
*cmdp
, MARK
*fp
, MARK
*tp
, u_int32_t flags
)
103 for (from
= fp
->lno
, to
= tp
->lno
; from
<= to
; ++from
) {
107 * Display the line number. The %6 format is specified
108 * by POSIX 1003.2, and is almost certainly large enough.
109 * Check, though, just in case.
111 if (LF_ISSET(E_C_HASH
)) {
112 if (from
<= 999999) {
113 SPRINTF(buf
, SIZE(buf
), L("%6u "), from
);
117 if (ex_prchars(sp
, p
, &col
, 8, 0, 0))
122 * Display the line. The format for E_C_PRINT isn't very good,
123 * especially in handling end-of-line tabs, but they're almost
124 * backward compatible.
126 if (db_get(sp
, from
, DBG_FATAL
, &p
, &len
))
129 if (len
== 0 && !LF_ISSET(E_C_LIST
))
130 (void)ex_puts(sp
, "\n");
131 else if (ex_ldisplay(sp
, p
, len
, col
, flags
))
142 * Display a line without any preceding number.
144 * PUBLIC: int ex_ldisplay(SCR *, const CHAR_T *, size_t, size_t, u_int);
147 ex_ldisplay(SCR
*sp
, const CHAR_T
*p
, size_t len
, size_t col
, u_int flags
)
149 if (len
> 0 && ex_prchars(sp
, p
, &col
, len
, LF_ISSET(E_C_LIST
), 0))
151 if (!INTERRUPTED(sp
) && LF_ISSET(E_C_LIST
)) {
153 if (ex_prchars(sp
, p
, &col
, 1, LF_ISSET(E_C_LIST
), 0))
156 if (!INTERRUPTED(sp
))
157 (void)ex_puts(sp
, "\n");
163 * Display a line for the substitute with confirmation routine.
165 * PUBLIC: int ex_scprint(SCR *, MARK *, MARK *);
168 ex_scprint(SCR
*sp
, MARK
*fp
, MARK
*tp
)
174 if (O_ISSET(sp
, O_NUMBER
)) {
176 if (ex_prchars(sp
, p
, &col
, 8, 0, 0))
180 if (db_get(sp
, fp
->lno
, DBG_FATAL
, &p
, &len
))
183 if (ex_prchars(sp
, p
, &col
, fp
->cno
, 0, ' '))
187 p
, &col
, tp
->cno
== fp
->cno
? 1 : tp
->cno
- fp
->cno
, 0, '^'))
191 p
= L("[ynq]"); /* XXX: should be msg_cat. */
192 if (ex_prchars(sp
, p
, &col
, 5, 0, 0))
200 * Local routine to dump characters to the screen.
203 ex_prchars(SCR
*sp
, const CHAR_T
*p
, size_t *colp
, size_t len
,
204 u_int flags
, int repeatc
)
209 size_t col
, tlen
, ts
;
211 if (O_ISSET(sp
, O_LIST
))
214 ts
= O_VAL(sp
, O_TABSTOP
);
215 for (col
= *colp
; len
--;)
216 if ((ch
= *p
++) == L('\t') && !LF_ISSET(E_C_LIST
))
217 for (tlen
= ts
- col
% ts
;
218 col
< sp
->cols
&& tlen
--; ++col
) {
220 "%c", repeatc
? repeatc
: ' ');
225 kp
= KEY_NAME(sp
, ch
);
226 tlen
= KEY_COL(sp
, ch
);
229 * Start a new line if the last character does not fit
230 * into the current line. The implicit new lines are
233 if (col
+ tlen
> sp
->cols
) {
235 (void)ex_puts(sp
, "\n");
240 (void)ex_puts(sp
, kp
);
243 } else while (tlen
--) {
244 (void)ex_printf(sp
, "%c", repeatc
);
248 if (col
== sp
->cols
) {
250 (void)ex_puts(sp
, "\n");
259 * Ex's version of printf.
261 * PUBLIC: int ex_printf(SCR *, const char *, ...);
276 exp
->obp_len
+= n
= vsnprintf(exp
->obp
+ exp
->obp_len
,
277 sizeof(exp
->obp
) - exp
->obp_len
, fmt
, ap
);
280 /* Flush when reach a <newline> or half the buffer. */
281 if (exp
->obp
[exp
->obp_len
- 1] == '\n' ||
282 exp
->obp_len
> sizeof(exp
->obp
) / 2)
289 * Ex's version of puts.
291 * PUBLIC: int ex_puts(SCR *, const char *);
294 ex_puts(SCR
*sp
, const char *str
)
301 /* Flush when reach a <newline> or the end of the buffer. */
302 for (doflush
= n
= 0; *str
!= '\0'; ++n
) {
303 if (exp
->obp_len
> sizeof(exp
->obp
))
305 if ((exp
->obp
[exp
->obp_len
++] = *str
++) == '\n')
315 * Ex's version of fflush.
317 * PUBLIC: int ex_fflush(SCR *sp);
326 if (exp
->obp_len
!= 0) {
327 sp
->gp
->scr_msg(sp
, M_NONE
, exp
->obp
, exp
->obp_len
);