xref: /minix3/external/bsd/nvi/dist/ex/ex_print.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: ex_print.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc /*-
384d9c625SLionel Sambuc  * Copyright (c) 1992, 1993, 1994
484d9c625SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
584d9c625SLionel Sambuc  * Copyright (c) 1992, 1993, 1994, 1995, 1996
684d9c625SLionel Sambuc  *	Keith Bostic.  All rights reserved.
784d9c625SLionel Sambuc  *
884d9c625SLionel Sambuc  * See the LICENSE file for redistribution information.
984d9c625SLionel Sambuc  */
1084d9c625SLionel Sambuc 
1184d9c625SLionel Sambuc #include "config.h"
1284d9c625SLionel Sambuc 
13*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
14*0a6a1f1dSLionel Sambuc #if 0
1584d9c625SLionel Sambuc #ifndef lint
1684d9c625SLionel Sambuc static const char sccsid[] = "Id: ex_print.c,v 10.24 2001/07/29 19:07:29 skimo Exp  (Berkeley) Date: 2001/07/29 19:07:29 ";
1784d9c625SLionel Sambuc #endif /* not lint */
18*0a6a1f1dSLionel Sambuc #else
19*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: ex_print.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
20*0a6a1f1dSLionel Sambuc #endif
2184d9c625SLionel Sambuc 
2284d9c625SLionel Sambuc #include <sys/types.h>
2384d9c625SLionel Sambuc #include <sys/queue.h>
2484d9c625SLionel Sambuc 
2584d9c625SLionel Sambuc #include <bitstring.h>
2684d9c625SLionel Sambuc #include <ctype.h>
2784d9c625SLionel Sambuc #include <limits.h>
2884d9c625SLionel Sambuc #include <stdio.h>
2984d9c625SLionel Sambuc #include <string.h>
3084d9c625SLionel Sambuc 
3184d9c625SLionel Sambuc #ifdef __STDC__
3284d9c625SLionel Sambuc #include <stdarg.h>
3384d9c625SLionel Sambuc #else
3484d9c625SLionel Sambuc #include <varargs.h>
3584d9c625SLionel Sambuc #endif
3684d9c625SLionel Sambuc 
3784d9c625SLionel Sambuc #include "../common/common.h"
3884d9c625SLionel Sambuc 
3984d9c625SLionel Sambuc static int ex_prchars __P((SCR *, const CHAR_T *, size_t *, size_t,
4084d9c625SLionel Sambuc                            u_int, int));
4184d9c625SLionel Sambuc 
4284d9c625SLionel Sambuc /*
4384d9c625SLionel Sambuc  * ex_list -- :[line [,line]] l[ist] [count] [flags]
4484d9c625SLionel Sambuc  *
4584d9c625SLionel Sambuc  *	Display the addressed lines such that the output is unambiguous.
4684d9c625SLionel Sambuc  *
4784d9c625SLionel Sambuc  * PUBLIC: int ex_list __P((SCR *, EXCMD *));
4884d9c625SLionel Sambuc  */
4984d9c625SLionel Sambuc int
ex_list(SCR * sp,EXCMD * cmdp)5084d9c625SLionel Sambuc ex_list(SCR *sp, EXCMD *cmdp)
5184d9c625SLionel Sambuc {
5284d9c625SLionel Sambuc 	if (ex_print(sp, cmdp,
5384d9c625SLionel Sambuc 	    &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_LIST))
5484d9c625SLionel Sambuc 		return (1);
5584d9c625SLionel Sambuc 	sp->lno = cmdp->addr2.lno;
5684d9c625SLionel Sambuc 	sp->cno = cmdp->addr2.cno;
5784d9c625SLionel Sambuc 	return (0);
5884d9c625SLionel Sambuc }
5984d9c625SLionel Sambuc 
6084d9c625SLionel Sambuc /*
6184d9c625SLionel Sambuc  * ex_number -- :[line [,line]] nu[mber] [count] [flags]
6284d9c625SLionel Sambuc  *
6384d9c625SLionel Sambuc  *	Display the addressed lines with a leading line number.
6484d9c625SLionel Sambuc  *
6584d9c625SLionel Sambuc  * PUBLIC: int ex_number __P((SCR *, EXCMD *));
6684d9c625SLionel Sambuc  */
6784d9c625SLionel Sambuc int
ex_number(SCR * sp,EXCMD * cmdp)6884d9c625SLionel Sambuc ex_number(SCR *sp, EXCMD *cmdp)
6984d9c625SLionel Sambuc {
7084d9c625SLionel Sambuc 	if (ex_print(sp, cmdp,
7184d9c625SLionel Sambuc 	    &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_HASH))
7284d9c625SLionel Sambuc 		return (1);
7384d9c625SLionel Sambuc 	sp->lno = cmdp->addr2.lno;
7484d9c625SLionel Sambuc 	sp->cno = cmdp->addr2.cno;
7584d9c625SLionel Sambuc 	return (0);
7684d9c625SLionel Sambuc }
7784d9c625SLionel Sambuc 
7884d9c625SLionel Sambuc /*
7984d9c625SLionel Sambuc  * ex_pr -- :[line [,line]] p[rint] [count] [flags]
8084d9c625SLionel Sambuc  *
8184d9c625SLionel Sambuc  *	Display the addressed lines.
8284d9c625SLionel Sambuc  *
8384d9c625SLionel Sambuc  * PUBLIC: int ex_pr __P((SCR *, EXCMD *));
8484d9c625SLionel Sambuc  */
8584d9c625SLionel Sambuc int
ex_pr(SCR * sp,EXCMD * cmdp)8684d9c625SLionel Sambuc ex_pr(SCR *sp, EXCMD *cmdp)
8784d9c625SLionel Sambuc {
8884d9c625SLionel Sambuc 	if (ex_print(sp, cmdp, &cmdp->addr1, &cmdp->addr2, cmdp->iflags))
8984d9c625SLionel Sambuc 		return (1);
9084d9c625SLionel Sambuc 	sp->lno = cmdp->addr2.lno;
9184d9c625SLionel Sambuc 	sp->cno = cmdp->addr2.cno;
9284d9c625SLionel Sambuc 	return (0);
9384d9c625SLionel Sambuc }
9484d9c625SLionel Sambuc 
9584d9c625SLionel Sambuc /*
9684d9c625SLionel Sambuc  * ex_print --
9784d9c625SLionel Sambuc  *	Print the selected lines.
9884d9c625SLionel Sambuc  *
9984d9c625SLionel Sambuc  * PUBLIC: int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
10084d9c625SLionel Sambuc  */
10184d9c625SLionel Sambuc int
ex_print(SCR * sp,EXCMD * cmdp,MARK * fp,MARK * tp,u_int32_t flags)10284d9c625SLionel Sambuc ex_print(SCR *sp, EXCMD *cmdp, MARK *fp, MARK *tp, u_int32_t flags)
10384d9c625SLionel Sambuc {
10484d9c625SLionel Sambuc 	db_recno_t from, to;
10584d9c625SLionel Sambuc 	size_t col, len;
10684d9c625SLionel Sambuc 	const CHAR_T *p;
10784d9c625SLionel Sambuc 	CHAR_T buf[10];
10884d9c625SLionel Sambuc 	CHAR_T *q;
10984d9c625SLionel Sambuc 
11084d9c625SLionel Sambuc 	NEEDFILE(sp, cmdp);
11184d9c625SLionel Sambuc 
11284d9c625SLionel Sambuc 	for (from = fp->lno, to = tp->lno; from <= to; ++from) {
11384d9c625SLionel Sambuc 		col = 0;
11484d9c625SLionel Sambuc 
11584d9c625SLionel Sambuc 		/*
11684d9c625SLionel Sambuc 		 * Display the line number.  The %6 format is specified
11784d9c625SLionel Sambuc 		 * by POSIX 1003.2, and is almost certainly large enough.
11884d9c625SLionel Sambuc 		 * Check, though, just in case.
11984d9c625SLionel Sambuc 		 */
12084d9c625SLionel Sambuc 		if (LF_ISSET(E_C_HASH)) {
12184d9c625SLionel Sambuc 			if (from <= 999999) {
12284d9c625SLionel Sambuc 				SPRINTF(buf, SIZE(buf), L("%6ld  "), from);
12384d9c625SLionel Sambuc 				p = buf;
12484d9c625SLionel Sambuc 			} else
12584d9c625SLionel Sambuc 				p = L("TOOBIG  ");
12684d9c625SLionel Sambuc 			if (ex_prchars(sp, p, &col, 8, 0, 0))
12784d9c625SLionel Sambuc 				return (1);
12884d9c625SLionel Sambuc 		}
12984d9c625SLionel Sambuc 
13084d9c625SLionel Sambuc 		/*
13184d9c625SLionel Sambuc 		 * Display the line.  The format for E_C_PRINT isn't very good,
13284d9c625SLionel Sambuc 		 * especially in handling end-of-line tabs, but they're almost
13384d9c625SLionel Sambuc 		 * backward compatible.
13484d9c625SLionel Sambuc 		 */
13584d9c625SLionel Sambuc 		if (db_get(sp, from, DBG_FATAL, &q, &len))
13684d9c625SLionel Sambuc 			return (1);
13784d9c625SLionel Sambuc 		p = q;
13884d9c625SLionel Sambuc 
13984d9c625SLionel Sambuc 		if (len == 0 && !LF_ISSET(E_C_LIST))
14084d9c625SLionel Sambuc 			(void)ex_puts(sp, "\n");
14184d9c625SLionel Sambuc 		else if (ex_ldisplay(sp, p, len, col, flags))
14284d9c625SLionel Sambuc 			return (1);
14384d9c625SLionel Sambuc 
14484d9c625SLionel Sambuc 		if (INTERRUPTED(sp))
14584d9c625SLionel Sambuc 			break;
14684d9c625SLionel Sambuc 	}
14784d9c625SLionel Sambuc 	return (0);
14884d9c625SLionel Sambuc }
14984d9c625SLionel Sambuc 
15084d9c625SLionel Sambuc /*
15184d9c625SLionel Sambuc  * ex_ldisplay --
15284d9c625SLionel Sambuc  *	Display a line without any preceding number.
15384d9c625SLionel Sambuc  *
15484d9c625SLionel Sambuc  * PUBLIC: int ex_ldisplay __P((SCR *, const CHAR_T *, size_t, size_t, u_int));
15584d9c625SLionel Sambuc  */
15684d9c625SLionel Sambuc int
ex_ldisplay(SCR * sp,const CHAR_T * p,size_t len,size_t col,u_int flags)15784d9c625SLionel Sambuc ex_ldisplay(SCR *sp, const CHAR_T *p, size_t len, size_t col, u_int flags)
15884d9c625SLionel Sambuc {
15984d9c625SLionel Sambuc 	if (len > 0 && ex_prchars(sp, p, &col, len, LF_ISSET(E_C_LIST), 0))
16084d9c625SLionel Sambuc 		return (1);
16184d9c625SLionel Sambuc 	if (!INTERRUPTED(sp) && LF_ISSET(E_C_LIST)) {
16284d9c625SLionel Sambuc 		p = L("$");
16384d9c625SLionel Sambuc 		if (ex_prchars(sp, p, &col, 1, LF_ISSET(E_C_LIST), 0))
16484d9c625SLionel Sambuc 			return (1);
16584d9c625SLionel Sambuc 	}
16684d9c625SLionel Sambuc 	if (!INTERRUPTED(sp))
16784d9c625SLionel Sambuc 		(void)ex_puts(sp, "\n");
16884d9c625SLionel Sambuc 	return (0);
16984d9c625SLionel Sambuc }
17084d9c625SLionel Sambuc 
17184d9c625SLionel Sambuc /*
17284d9c625SLionel Sambuc  * ex_scprint --
17384d9c625SLionel Sambuc  *	Display a line for the substitute with confirmation routine.
17484d9c625SLionel Sambuc  *
17584d9c625SLionel Sambuc  * PUBLIC: int ex_scprint __P((SCR *, MARK *, MARK *));
17684d9c625SLionel Sambuc  */
17784d9c625SLionel Sambuc int
ex_scprint(SCR * sp,MARK * fp,MARK * tp)17884d9c625SLionel Sambuc ex_scprint(SCR *sp, MARK *fp, MARK *tp)
17984d9c625SLionel Sambuc {
18084d9c625SLionel Sambuc 	const CHAR_T *p;
18184d9c625SLionel Sambuc 	CHAR_T *q;
18284d9c625SLionel Sambuc 	size_t col, len;
18384d9c625SLionel Sambuc 
18484d9c625SLionel Sambuc 	col = 0;
18584d9c625SLionel Sambuc 	if (O_ISSET(sp, O_NUMBER)) {
18684d9c625SLionel Sambuc 		p = L("        ");
18784d9c625SLionel Sambuc 		if (ex_prchars(sp, p, &col, 8, 0, 0))
18884d9c625SLionel Sambuc 			return (1);
18984d9c625SLionel Sambuc 	}
19084d9c625SLionel Sambuc 
19184d9c625SLionel Sambuc 	if (db_get(sp, fp->lno, DBG_FATAL, &q, &len))
19284d9c625SLionel Sambuc 		return (1);
19384d9c625SLionel Sambuc 	p = q;
19484d9c625SLionel Sambuc 
19584d9c625SLionel Sambuc 	if (ex_prchars(sp, p, &col, fp->cno, 0, ' '))
19684d9c625SLionel Sambuc 		return (1);
19784d9c625SLionel Sambuc 	p += fp->cno;
19884d9c625SLionel Sambuc 	if (ex_prchars(sp,
19984d9c625SLionel Sambuc 	    p, &col, tp->cno == fp->cno ? 1 : tp->cno - fp->cno, 0, '^'))
20084d9c625SLionel Sambuc 		return (1);
20184d9c625SLionel Sambuc 	if (INTERRUPTED(sp))
20284d9c625SLionel Sambuc 		return (1);
20384d9c625SLionel Sambuc 	p = L("[ynq]");		/* XXX: should be msg_cat. */
20484d9c625SLionel Sambuc 	if (ex_prchars(sp, p, &col, 5, 0, 0))
20584d9c625SLionel Sambuc 		return (1);
20684d9c625SLionel Sambuc 	(void)ex_fflush(sp);
20784d9c625SLionel Sambuc 	return (0);
20884d9c625SLionel Sambuc }
20984d9c625SLionel Sambuc 
21084d9c625SLionel Sambuc /*
21184d9c625SLionel Sambuc  * ex_prchars --
21284d9c625SLionel Sambuc  *	Local routine to dump characters to the screen.
21384d9c625SLionel Sambuc  */
21484d9c625SLionel Sambuc static int
ex_prchars(SCR * sp,const CHAR_T * p,size_t * colp,size_t len,u_int flags,int repeatc)21584d9c625SLionel Sambuc ex_prchars(SCR *sp, const CHAR_T *p, size_t *colp, size_t len,
21684d9c625SLionel Sambuc 	    u_int flags, int repeatc)
21784d9c625SLionel Sambuc {
21884d9c625SLionel Sambuc 	CHAR_T ch;
21984d9c625SLionel Sambuc 	const char *kp;
22084d9c625SLionel Sambuc 	size_t col, tlen, ts;
22184d9c625SLionel Sambuc 
22284d9c625SLionel Sambuc 	if (O_ISSET(sp, O_LIST))
22384d9c625SLionel Sambuc 		LF_SET(E_C_LIST);
22484d9c625SLionel Sambuc 	ts = O_VAL(sp, O_TABSTOP);
22584d9c625SLionel Sambuc 	for (col = *colp; len--;)
22684d9c625SLionel Sambuc 		if ((ch = *p++) == L('\t') && !LF_ISSET(E_C_LIST))
22784d9c625SLionel Sambuc 			for (tlen = ts - col % ts;
22884d9c625SLionel Sambuc 			    col < sp->cols && tlen--; ++col) {
22984d9c625SLionel Sambuc 				(void)ex_printf(sp,
23084d9c625SLionel Sambuc 				    "%c", repeatc ? repeatc : ' ');
23184d9c625SLionel Sambuc 				if (INTERRUPTED(sp))
23284d9c625SLionel Sambuc 					goto intr;
23384d9c625SLionel Sambuc 			}
23484d9c625SLionel Sambuc 		else {
23584d9c625SLionel Sambuc 			/* XXXX */
23684d9c625SLionel Sambuc 			if (INTISWIDE(ch)) {
23784d9c625SLionel Sambuc 			    CHAR_T str[2] = {0, 0};
23884d9c625SLionel Sambuc 			    str[0] = ch;
23984d9c625SLionel Sambuc 			    INT2CHAR(sp, str, 2, kp, tlen);
24084d9c625SLionel Sambuc 			} else {
24184d9c625SLionel Sambuc 			    kp = (char *)KEY_NAME(sp, ch);
24284d9c625SLionel Sambuc 			    tlen = KEY_LEN(sp, ch);
24384d9c625SLionel Sambuc 			}
24484d9c625SLionel Sambuc 			if (!repeatc  && col + tlen < sp->cols) {
24584d9c625SLionel Sambuc 				(void)ex_puts(sp, kp);
24684d9c625SLionel Sambuc 				col += tlen;
24784d9c625SLionel Sambuc 			} else
24884d9c625SLionel Sambuc 				for (; tlen--; ++kp, ++col) {
24984d9c625SLionel Sambuc 					if (col == sp->cols) {
25084d9c625SLionel Sambuc 						col = 0;
25184d9c625SLionel Sambuc 						(void)ex_puts(sp, "\n");
25284d9c625SLionel Sambuc 					}
25384d9c625SLionel Sambuc 					(void)ex_printf(sp,
25484d9c625SLionel Sambuc 					    "%c", repeatc ? repeatc : *kp);
25584d9c625SLionel Sambuc 					if (INTERRUPTED(sp))
25684d9c625SLionel Sambuc 						goto intr;
25784d9c625SLionel Sambuc 				}
25884d9c625SLionel Sambuc 		}
25984d9c625SLionel Sambuc intr:	*colp = col;
26084d9c625SLionel Sambuc 	return (0);
26184d9c625SLionel Sambuc }
26284d9c625SLionel Sambuc 
26384d9c625SLionel Sambuc /*
26484d9c625SLionel Sambuc  * ex_printf --
26584d9c625SLionel Sambuc  *	Ex's version of printf.
26684d9c625SLionel Sambuc  *
26784d9c625SLionel Sambuc  * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
26884d9c625SLionel Sambuc  */
26984d9c625SLionel Sambuc int
27084d9c625SLionel Sambuc #ifdef __STDC__
ex_printf(SCR * sp,const char * fmt,...)27184d9c625SLionel Sambuc ex_printf(SCR *sp, const char *fmt, ...)
27284d9c625SLionel Sambuc #else
27384d9c625SLionel Sambuc ex_printf(sp, fmt, va_alist)
27484d9c625SLionel Sambuc 	SCR *sp;
27584d9c625SLionel Sambuc 	const char *fmt;
27684d9c625SLionel Sambuc 	va_dcl
27784d9c625SLionel Sambuc #endif
27884d9c625SLionel Sambuc {
27984d9c625SLionel Sambuc 	EX_PRIVATE *exp;
28084d9c625SLionel Sambuc 	va_list ap;
28184d9c625SLionel Sambuc 	size_t n;
28284d9c625SLionel Sambuc 
28384d9c625SLionel Sambuc 	exp = EXP(sp);
28484d9c625SLionel Sambuc 
28584d9c625SLionel Sambuc #ifdef __STDC__
28684d9c625SLionel Sambuc 	va_start(ap, fmt);
28784d9c625SLionel Sambuc #else
28884d9c625SLionel Sambuc 	va_start(ap);
28984d9c625SLionel Sambuc #endif
29084d9c625SLionel Sambuc 	exp->obp_len += n = vsnprintf(exp->obp + exp->obp_len,
29184d9c625SLionel Sambuc 	    sizeof(exp->obp) - exp->obp_len, fmt, ap);
29284d9c625SLionel Sambuc 	va_end(ap);
29384d9c625SLionel Sambuc 
29484d9c625SLionel Sambuc 	/* Flush when reach a <newline> or half the buffer. */
29584d9c625SLionel Sambuc 	if (exp->obp[exp->obp_len - 1] == '\n' ||
29684d9c625SLionel Sambuc 	    exp->obp_len > sizeof(exp->obp) / 2)
29784d9c625SLionel Sambuc 		(void)ex_fflush(sp);
29884d9c625SLionel Sambuc 	return (n);
29984d9c625SLionel Sambuc }
30084d9c625SLionel Sambuc 
30184d9c625SLionel Sambuc /*
30284d9c625SLionel Sambuc  * ex_puts --
30384d9c625SLionel Sambuc  *	Ex's version of puts.
30484d9c625SLionel Sambuc  *
30584d9c625SLionel Sambuc  * PUBLIC: int ex_puts __P((SCR *, const char *));
30684d9c625SLionel Sambuc  */
30784d9c625SLionel Sambuc int
ex_puts(SCR * sp,const char * str)30884d9c625SLionel Sambuc ex_puts(SCR *sp, const char *str)
30984d9c625SLionel Sambuc {
31084d9c625SLionel Sambuc 	EX_PRIVATE *exp;
31184d9c625SLionel Sambuc 	int doflush, n;
31284d9c625SLionel Sambuc 
31384d9c625SLionel Sambuc 	exp = EXP(sp);
31484d9c625SLionel Sambuc 
31584d9c625SLionel Sambuc 	/* Flush when reach a <newline> or the end of the buffer. */
31684d9c625SLionel Sambuc 	for (doflush = n = 0; *str != '\0'; ++n) {
31784d9c625SLionel Sambuc 		if (exp->obp_len > sizeof(exp->obp))
31884d9c625SLionel Sambuc 			(void)ex_fflush(sp);
31984d9c625SLionel Sambuc 		if ((exp->obp[exp->obp_len++] = *str++) == '\n')
32084d9c625SLionel Sambuc 			doflush = 1;
32184d9c625SLionel Sambuc 	}
32284d9c625SLionel Sambuc 	if (doflush)
32384d9c625SLionel Sambuc 		(void)ex_fflush(sp);
32484d9c625SLionel Sambuc 	return (n);
32584d9c625SLionel Sambuc }
32684d9c625SLionel Sambuc 
32784d9c625SLionel Sambuc /*
32884d9c625SLionel Sambuc  * ex_fflush --
32984d9c625SLionel Sambuc  *	Ex's version of fflush.
33084d9c625SLionel Sambuc  *
33184d9c625SLionel Sambuc  * PUBLIC: int ex_fflush __P((SCR *sp));
33284d9c625SLionel Sambuc  */
33384d9c625SLionel Sambuc int
ex_fflush(SCR * sp)33484d9c625SLionel Sambuc ex_fflush(SCR *sp)
33584d9c625SLionel Sambuc {
33684d9c625SLionel Sambuc 	EX_PRIVATE *exp;
33784d9c625SLionel Sambuc 
33884d9c625SLionel Sambuc 	exp = EXP(sp);
33984d9c625SLionel Sambuc 
34084d9c625SLionel Sambuc 	if (exp && exp->obp_len != 0) {
34184d9c625SLionel Sambuc 		sp->wp->scr_msg(sp, M_NONE, exp->obp, exp->obp_len);
34284d9c625SLionel Sambuc 		exp->obp_len = 0;
34384d9c625SLionel Sambuc 	}
34484d9c625SLionel Sambuc 	return (0);
34584d9c625SLionel Sambuc }
346