aboutsummaryrefslogtreecommitdiff
path: root/contrib/nvi/ex/ex_print.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/nvi/ex/ex_print.c')
-rw-r--r--contrib/nvi/ex/ex_print.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/contrib/nvi/ex/ex_print.c b/contrib/nvi/ex/ex_print.c
new file mode 100644
index 000000000000..4218e08e0978
--- /dev/null
+++ b/contrib/nvi/ex/ex_print.c
@@ -0,0 +1,352 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)ex_print.c 10.18 (Berkeley) 5/12/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <bitstring.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "../common/common.h"
+
+static int ex_prchars __P((SCR *, const char *, size_t *, size_t, u_int, int));
+
+/*
+ * ex_list -- :[line [,line]] l[ist] [count] [flags]
+ *
+ * Display the addressed lines such that the output is unambiguous.
+ *
+ * PUBLIC: int ex_list __P((SCR *, EXCMD *));
+ */
+int
+ex_list(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ if (ex_print(sp, cmdp,
+ &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_LIST))
+ return (1);
+ sp->lno = cmdp->addr2.lno;
+ sp->cno = cmdp->addr2.cno;
+ return (0);
+}
+
+/*
+ * ex_number -- :[line [,line]] nu[mber] [count] [flags]
+ *
+ * Display the addressed lines with a leading line number.
+ *
+ * PUBLIC: int ex_number __P((SCR *, EXCMD *));
+ */
+int
+ex_number(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ if (ex_print(sp, cmdp,
+ &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_HASH))
+ return (1);
+ sp->lno = cmdp->addr2.lno;
+ sp->cno = cmdp->addr2.cno;
+ return (0);
+}
+
+/*
+ * ex_pr -- :[line [,line]] p[rint] [count] [flags]
+ *
+ * Display the addressed lines.
+ *
+ * PUBLIC: int ex_pr __P((SCR *, EXCMD *));
+ */
+int
+ex_pr(sp, cmdp)
+ SCR *sp;
+ EXCMD *cmdp;
+{
+ if (ex_print(sp, cmdp, &cmdp->addr1, &cmdp->addr2, cmdp->iflags))
+ return (1);
+ sp->lno = cmdp->addr2.lno;
+ sp->cno = cmdp->addr2.cno;
+ return (0);
+}
+
+/*
+ * ex_print --
+ * Print the selected lines.
+ *
+ * PUBLIC: int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
+ */
+int
+ex_print(sp, cmdp, fp, tp, flags)
+ SCR *sp;
+ EXCMD *cmdp;
+ MARK *fp, *tp;
+ u_int32_t flags;
+{
+ GS *gp;
+ recno_t from, to;
+ size_t col, len;
+ char *p, buf[10];
+
+ NEEDFILE(sp, cmdp);
+
+ gp = sp->gp;
+ for (from = fp->lno, to = tp->lno; from <= to; ++from) {
+ col = 0;
+
+ /*
+ * Display the line number. The %6 format is specified
+ * by POSIX 1003.2, and is almost certainly large enough.
+ * Check, though, just in case.
+ */
+ if (LF_ISSET(E_C_HASH)) {
+ if (from <= 999999) {
+ snprintf(buf, sizeof(buf), "%6ld ", from);
+ p = buf;
+ } else
+ p = "TOOBIG ";
+ if (ex_prchars(sp, p, &col, 8, 0, 0))
+ return (1);
+ }
+
+ /*
+ * Display the line. The format for E_C_PRINT isn't very good,
+ * especially in handling end-of-line tabs, but they're almost
+ * backward compatible.
+ */
+ if (db_get(sp, from, DBG_FATAL, &p, &len))
+ return (1);
+
+ if (len == 0 && !LF_ISSET(E_C_LIST))
+ (void)ex_puts(sp, "\n");
+ else if (ex_ldisplay(sp, p, len, col, flags))
+ return (1);
+
+ if (INTERRUPTED(sp))
+ break;
+ }
+ return (0);
+}
+
+/*
+ * ex_ldisplay --
+ * Display a line without any preceding number.
+ *
+ * PUBLIC: int ex_ldisplay __P((SCR *, const char *, size_t, size_t, u_int));
+ */
+int
+ex_ldisplay(sp, p, len, col, flags)
+ SCR *sp;
+ const char *p;
+ size_t len, col;
+ u_int flags;
+{
+ if (len > 0 && ex_prchars(sp, p, &col, len, LF_ISSET(E_C_LIST), 0))
+ return (1);
+ if (!INTERRUPTED(sp) && LF_ISSET(E_C_LIST)) {
+ p = "$";
+ if (ex_prchars(sp, p, &col, 1, LF_ISSET(E_C_LIST), 0))
+ return (1);
+ }
+ if (!INTERRUPTED(sp))
+ (void)ex_puts(sp, "\n");
+ return (0);
+}
+
+/*
+ * ex_scprint --
+ * Display a line for the substitute with confirmation routine.
+ *
+ * PUBLIC: int ex_scprint __P((SCR *, MARK *, MARK *));
+ */
+int
+ex_scprint(sp, fp, tp)
+ SCR *sp;
+ MARK *fp, *tp;
+{
+ const char *p;
+ size_t col, len;
+
+ col = 0;
+ if (O_ISSET(sp, O_NUMBER)) {
+ p = " ";
+ if (ex_prchars(sp, p, &col, 8, 0, 0))
+ return (1);
+ }
+
+ if (db_get(sp, fp->lno, DBG_FATAL, (char **)&p, &len))
+ return (1);
+
+ if (ex_prchars(sp, p, &col, fp->cno, 0, ' '))
+ return (1);
+ p += fp->cno;
+ if (ex_prchars(sp,
+ p, &col, tp->cno == fp->cno ? 1 : tp->cno - fp->cno, 0, '^'))
+ return (1);
+ if (INTERRUPTED(sp))
+ return (1);
+ p = "[ynq]"; /* XXX: should be msg_cat. */
+ if (ex_prchars(sp, p, &col, 5, 0, 0))
+ return (1);
+ (void)ex_fflush(sp);
+ return (0);
+}
+
+/*
+ * ex_prchars --
+ * Local routine to dump characters to the screen.
+ */
+static int
+ex_prchars(sp, p, colp, len, flags, repeatc)
+ SCR *sp;
+ const char *p;
+ size_t *colp, len;
+ u_int flags;
+ int repeatc;
+{
+ CHAR_T ch, *kp;
+ GS *gp;
+ size_t col, tlen, ts;
+
+ if (O_ISSET(sp, O_LIST))
+ LF_SET(E_C_LIST);
+ gp = sp->gp;
+ ts = O_VAL(sp, O_TABSTOP);
+ for (col = *colp; len--;)
+ if ((ch = *p++) == '\t' && !LF_ISSET(E_C_LIST))
+ for (tlen = ts - col % ts;
+ col < sp->cols && tlen--; ++col) {
+ (void)ex_printf(sp,
+ "%c", repeatc ? repeatc : ' ');
+ if (INTERRUPTED(sp))
+ goto intr;
+ }
+ else {
+ kp = KEY_NAME(sp, ch);
+ tlen = KEY_LEN(sp, ch);
+ if (!repeatc && col + tlen < sp->cols) {
+ (void)ex_puts(sp, kp);
+ col += tlen;
+ } else
+ for (; tlen--; ++kp, ++col) {
+ if (col == sp->cols) {
+ col = 0;
+ (void)ex_puts(sp, "\n");
+ }
+ (void)ex_printf(sp,
+ "%c", repeatc ? repeatc : *kp);
+ if (INTERRUPTED(sp))
+ goto intr;
+ }
+ }
+intr: *colp = col;
+ return (0);
+}
+
+/*
+ * ex_printf --
+ * Ex's version of printf.
+ *
+ * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
+ */
+int
+#ifdef __STDC__
+ex_printf(SCR *sp, const char *fmt, ...)
+#else
+ex_printf(sp, fmt, va_alist)
+ SCR *sp;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ EX_PRIVATE *exp;
+ va_list ap;
+ size_t n;
+
+ exp = EXP(sp);
+
+#ifdef __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ exp->obp_len += n = vsnprintf(exp->obp + exp->obp_len,
+ sizeof(exp->obp) - exp->obp_len, fmt, ap);
+ va_end(ap);
+
+ /* Flush when reach a <newline> or half the buffer. */
+ if (exp->obp[exp->obp_len - 1] == '\n' ||
+ exp->obp_len > sizeof(exp->obp) / 2)
+ (void)ex_fflush(sp);
+ return (n);
+}
+
+/*
+ * ex_puts --
+ * Ex's version of puts.
+ *
+ * PUBLIC: int ex_puts __P((SCR *, const char *));
+ */
+int
+ex_puts(sp, str)
+ SCR *sp;
+ const char *str;
+{
+ EX_PRIVATE *exp;
+ int doflush, n;
+
+ exp = EXP(sp);
+
+ /* Flush when reach a <newline> or the end of the buffer. */
+ for (doflush = n = 0; *str != '\0'; ++n) {
+ if (exp->obp_len > sizeof(exp->obp))
+ (void)ex_fflush(sp);
+ if ((exp->obp[exp->obp_len++] = *str++) == '\n')
+ doflush = 1;
+ }
+ if (doflush)
+ (void)ex_fflush(sp);
+ return (n);
+}
+
+/*
+ * ex_fflush --
+ * Ex's version of fflush.
+ *
+ * PUBLIC: int ex_fflush __P((SCR *sp));
+ */
+int
+ex_fflush(sp)
+ SCR *sp;
+{
+ EX_PRIVATE *exp;
+
+ exp = EXP(sp);
+
+ if (exp->obp_len != 0) {
+ sp->gp->scr_msg(sp, M_NONE, exp->obp, exp->obp_len);
+ exp->obp_len = 0;
+ }
+ return (0);
+}