align CHAR_T string in log
[nvi.git] / ex / ex_print.c
blob1de09d793fa81d43be0f1cf11a60734762093861
1 /*-
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.
8 */
10 #include "config.h"
12 #ifndef lint
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 $";
14 #endif /* not lint */
16 #include <sys/types.h>
17 #include <sys/queue.h>
19 #include <bitstring.h>
20 #include <ctype.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <string.h>
25 #ifdef __STDC__
26 #include <stdarg.h>
27 #else
28 #include <varargs.h>
29 #endif
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 *));
42 int
43 ex_list(sp, cmdp)
44 SCR *sp;
45 EXCMD *cmdp;
47 if (ex_print(sp, cmdp,
48 &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_LIST))
49 return (1);
50 sp->lno = cmdp->addr2.lno;
51 sp->cno = cmdp->addr2.cno;
52 return (0);
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 *));
62 int
63 ex_number(sp, cmdp)
64 SCR *sp;
65 EXCMD *cmdp;
67 if (ex_print(sp, cmdp,
68 &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_HASH))
69 return (1);
70 sp->lno = cmdp->addr2.lno;
71 sp->cno = cmdp->addr2.cno;
72 return (0);
76 * ex_pr -- :[line [,line]] p[rint] [count] [flags]
78 * Display the addressed lines.
80 * PUBLIC: int ex_pr __P((SCR *, EXCMD *));
82 int
83 ex_pr(sp, cmdp)
84 SCR *sp;
85 EXCMD *cmdp;
87 if (ex_print(sp, cmdp, &cmdp->addr1, &cmdp->addr2, cmdp->iflags))
88 return (1);
89 sp->lno = cmdp->addr2.lno;
90 sp->cno = cmdp->addr2.cno;
91 return (0);
95 * ex_print --
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)
102 SCR *sp;
103 EXCMD *cmdp;
104 MARK *fp, *tp;
105 u_int32_t flags;
107 GS *gp;
108 db_recno_t from, to;
109 size_t col, len;
110 char *p;
111 char buf[10];
112 CHAR_T *wp;
113 size_t wlen;
115 NEEDFILE(sp, cmdp);
117 gp = sp->gp;
118 for (from = fp->lno, to = tp->lno; from <= to; ++from) {
119 col = 0;
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);
129 p = buf;
130 } else
131 p = "TOOBIG ";
132 if (ex_prchars(sp, p, &col, 8, 0, 0))
133 return (1);
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))
142 return (1);
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))
148 return (1);
150 if (INTERRUPTED(sp))
151 break;
153 return (0);
157 * ex_ldisplay --
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)
164 SCR *sp;
165 const char *p;
166 size_t len, col;
167 u_int flags;
169 if (len > 0 && ex_prchars(sp, p, &col, len, LF_ISSET(E_C_LIST), 0))
170 return (1);
171 if (!INTERRUPTED(sp) && LF_ISSET(E_C_LIST)) {
172 p = "$";
173 if (ex_prchars(sp, p, &col, 1, LF_ISSET(E_C_LIST), 0))
174 return (1);
176 if (!INTERRUPTED(sp))
177 (void)ex_puts(sp, "\n");
178 return (0);
182 * ex_scprint --
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)
189 SCR *sp;
190 MARK *fp, *tp;
192 char *p;
193 size_t col, len;
194 CHAR_T *wp;
195 size_t wlen;
197 col = 0;
198 if (O_ISSET(sp, O_NUMBER)) {
199 p = " ";
200 if (ex_prchars(sp, p, &col, 8, 0, 0))
201 return (1);
204 if (db_get(sp, fp->lno, DBG_FATAL, &wp, &wlen))
205 return (1);
206 INT2CHAR(sp, wp, wlen, p, len);
208 if (ex_prchars(sp, p, &col, fp->cno, 0, ' '))
209 return (1);
210 p += fp->cno;
211 if (ex_prchars(sp,
212 p, &col, tp->cno == fp->cno ? 1 : tp->cno - fp->cno, 0, '^'))
213 return (1);
214 if (INTERRUPTED(sp))
215 return (1);
216 p = "[ynq]"; /* XXX: should be msg_cat. */
217 if (ex_prchars(sp, p, &col, 5, 0, 0))
218 return (1);
219 (void)ex_fflush(sp);
220 return (0);
224 * ex_prchars --
225 * Local routine to dump characters to the screen.
227 static int
228 ex_prchars(sp, p, colp, len, flags, repeatc)
229 SCR *sp;
230 const char *p;
231 size_t *colp, len;
232 u_int flags;
233 int repeatc;
235 CHAR_T ch;
236 char *kp;
237 GS *gp;
238 size_t col, tlen, ts;
240 if (O_ISSET(sp, O_LIST))
241 LF_SET(E_C_LIST);
242 gp = sp->gp;
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) {
248 (void)ex_printf(sp,
249 "%c", repeatc ? repeatc : ' ');
250 if (INTERRUPTED(sp))
251 goto intr;
253 else {
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);
258 col += tlen;
259 } else
260 for (; tlen--; ++kp, ++col) {
261 if (col == sp->cols) {
262 col = 0;
263 (void)ex_puts(sp, "\n");
265 (void)ex_printf(sp,
266 "%c", repeatc ? repeatc : *kp);
267 if (INTERRUPTED(sp))
268 goto intr;
271 intr: *colp = col;
272 return (0);
276 * ex_printf --
277 * Ex's version of printf.
279 * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
282 #ifdef __STDC__
283 ex_printf(SCR *sp, const char *fmt, ...)
284 #else
285 ex_printf(sp, fmt, va_alist)
286 SCR *sp;
287 const char *fmt;
288 va_dcl
289 #endif
291 EX_PRIVATE *exp;
292 va_list ap;
293 size_t n;
294 CHAR_T *kp;
296 exp = EXP(sp);
298 #ifdef __STDC__
299 va_start(ap, fmt);
300 #else
301 va_start(ap);
302 #endif
303 exp->obp_len += n = vsnprintf(exp->obp + exp->obp_len,
304 sizeof(exp->obp) - exp->obp_len, fmt, ap);
305 va_end(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)
310 (void)ex_fflush(sp);
311 return (n);
315 * ex_puts --
316 * Ex's version of puts.
318 * PUBLIC: int ex_puts __P((SCR *, const char *));
321 ex_puts(sp, str)
322 SCR *sp;
323 const char *str;
325 EX_PRIVATE *exp;
326 int doflush, n;
328 exp = EXP(sp);
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))
333 (void)ex_fflush(sp);
334 if ((exp->obp[exp->obp_len++] = *str++) == '\n')
335 doflush = 1;
337 if (doflush)
338 (void)ex_fflush(sp);
339 return (n);
343 * ex_fflush --
344 * Ex's version of fflush.
346 * PUBLIC: int ex_fflush __P((SCR *sp));
349 ex_fflush(sp)
350 SCR *sp;
352 EX_PRIVATE *exp;
354 exp = EXP(sp);
356 if (exp->obp_len != 0) {
357 sp->gp->scr_msg(sp, M_NONE, exp->obp, exp->obp_len);
358 exp->obp_len = 0;
360 return (0);