Merge branch 'vendor/GCC44'
[dragonfly.git] / contrib / nvi / ex / ex_print.c
blob1cc2500c775390f819d668ed56088a53f971445b
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[] = "@(#)ex_print.c 10.18 (Berkeley) 5/12/96";
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 recno_t from, to;
109 size_t col, len;
110 char *p, buf[10];
112 NEEDFILE(sp, cmdp);
114 gp = sp->gp;
115 for (from = fp->lno, to = tp->lno; from <= to; ++from) {
116 col = 0;
119 * Display the line number. The %6 format is specified
120 * by POSIX 1003.2, and is almost certainly large enough.
121 * Check, though, just in case.
123 if (LF_ISSET(E_C_HASH)) {
124 if (from <= 999999) {
125 snprintf(buf, sizeof(buf), "%6lu ",
126 (u_long)from);
127 p = buf;
128 } else
129 p = "TOOBIG ";
130 if (ex_prchars(sp, p, &col, 8, 0, 0))
131 return (1);
135 * Display the line. The format for E_C_PRINT isn't very good,
136 * especially in handling end-of-line tabs, but they're almost
137 * backward compatible.
139 if (db_get(sp, from, DBG_FATAL, &p, &len))
140 return (1);
142 if (len == 0 && !LF_ISSET(E_C_LIST))
143 (void)ex_puts(sp, "\n");
144 else if (ex_ldisplay(sp, p, len, col, flags))
145 return (1);
147 if (INTERRUPTED(sp))
148 break;
150 return (0);
154 * ex_ldisplay --
155 * Display a line without any preceding number.
157 * PUBLIC: int ex_ldisplay __P((SCR *, const char *, size_t, size_t, u_int));
160 ex_ldisplay(sp, p, len, col, flags)
161 SCR *sp;
162 const char *p;
163 size_t len, col;
164 u_int flags;
166 if (len > 0 && ex_prchars(sp, p, &col, len, LF_ISSET(E_C_LIST), 0))
167 return (1);
168 if (!INTERRUPTED(sp) && LF_ISSET(E_C_LIST)) {
169 p = "$";
170 if (ex_prchars(sp, p, &col, 1, LF_ISSET(E_C_LIST), 0))
171 return (1);
173 if (!INTERRUPTED(sp))
174 (void)ex_puts(sp, "\n");
175 return (0);
179 * ex_scprint --
180 * Display a line for the substitute with confirmation routine.
182 * PUBLIC: int ex_scprint __P((SCR *, MARK *, MARK *));
185 ex_scprint(sp, fp, tp)
186 SCR *sp;
187 MARK *fp, *tp;
189 const char *p;
190 size_t col, len;
192 col = 0;
193 if (O_ISSET(sp, O_NUMBER)) {
194 p = " ";
195 if (ex_prchars(sp, p, &col, 8, 0, 0))
196 return (1);
199 if (db_get(sp, fp->lno, DBG_FATAL, (char **)&p, &len))
200 return (1);
202 if (ex_prchars(sp, p, &col, fp->cno, 0, ' '))
203 return (1);
204 p += fp->cno;
205 if (ex_prchars(sp,
206 p, &col, tp->cno == fp->cno ? 1 : tp->cno - fp->cno, 0, '^'))
207 return (1);
208 if (INTERRUPTED(sp))
209 return (1);
210 p = "[ynq]"; /* XXX: should be msg_cat. */
211 if (ex_prchars(sp, p, &col, 5, 0, 0))
212 return (1);
213 (void)ex_fflush(sp);
214 return (0);
218 * ex_prchars --
219 * Local routine to dump characters to the screen.
221 static int
222 ex_prchars(sp, p, colp, len, flags, repeatc)
223 SCR *sp;
224 const char *p;
225 size_t *colp, len;
226 u_int flags;
227 int repeatc;
229 CHAR_T ch, *kp;
230 GS *gp;
231 size_t col, tlen, ts;
233 if (O_ISSET(sp, O_LIST))
234 LF_SET(E_C_LIST);
235 gp = sp->gp;
236 ts = O_VAL(sp, O_TABSTOP);
237 for (col = *colp; len--;)
238 if ((ch = *p++) == '\t' && !LF_ISSET(E_C_LIST))
239 for (tlen = ts - col % ts;
240 col < sp->cols && tlen--; ++col) {
241 (void)ex_printf(sp,
242 "%c", repeatc ? repeatc : ' ');
243 if (INTERRUPTED(sp))
244 goto intr;
246 else {
247 kp = KEY_NAME(sp, ch);
248 tlen = KEY_LEN(sp, ch);
249 if (!repeatc && col + tlen < sp->cols) {
250 (void)ex_puts(sp, kp);
251 col += tlen;
252 } else
253 for (; tlen--; ++kp, ++col) {
254 if (col == sp->cols) {
255 col = 0;
256 (void)ex_puts(sp, "\n");
258 (void)ex_printf(sp,
259 "%c", repeatc ? repeatc : *kp);
260 if (INTERRUPTED(sp))
261 goto intr;
264 intr: *colp = col;
265 return (0);
269 * ex_printf --
270 * Ex's version of printf.
272 * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
275 #ifdef __STDC__
276 ex_printf(SCR *sp, const char *fmt, ...)
277 #else
278 ex_printf(sp, fmt, va_alist)
279 SCR *sp;
280 const char *fmt;
281 va_dcl
282 #endif
284 EX_PRIVATE *exp;
285 va_list ap;
286 size_t n;
288 exp = EXP(sp);
290 #ifdef __STDC__
291 va_start(ap, fmt);
292 #else
293 va_start(ap);
294 #endif
295 exp->obp_len += n = vsnprintf(exp->obp + exp->obp_len,
296 sizeof(exp->obp) - exp->obp_len, fmt, ap);
297 va_end(ap);
299 /* Flush when reach a <newline> or half the buffer. */
300 if (exp->obp[exp->obp_len - 1] == '\n' ||
301 exp->obp_len > sizeof(exp->obp) / 2)
302 (void)ex_fflush(sp);
303 return (n);
307 * ex_puts --
308 * Ex's version of puts.
310 * PUBLIC: int ex_puts __P((SCR *, const char *));
313 ex_puts(sp, str)
314 SCR *sp;
315 const char *str;
317 EX_PRIVATE *exp;
318 int doflush, n;
320 exp = EXP(sp);
322 /* Flush when reach a <newline> or the end of the buffer. */
323 for (doflush = n = 0; *str != '\0'; ++n) {
324 if (exp->obp_len > sizeof(exp->obp))
325 (void)ex_fflush(sp);
326 if ((exp->obp[exp->obp_len++] = *str++) == '\n')
327 doflush = 1;
329 if (doflush)
330 (void)ex_fflush(sp);
331 return (n);
335 * ex_fflush --
336 * Ex's version of fflush.
338 * PUBLIC: int ex_fflush __P((SCR *sp));
341 ex_fflush(sp)
342 SCR *sp;
344 EX_PRIVATE *exp;
346 exp = EXP(sp);
348 if (exp->obp_len != 0) {
349 sp->gp->scr_msg(sp, M_NONE, exp->obp, exp->obp_len);
350 exp->obp_len = 0;
352 return (0);