summaryrefslogtreecommitdiffstatshomepage
path: root/term.c
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2009-02-20 23:35:36 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2009-02-20 23:35:36 +0000
commit24a95b9b6e0ec8aecdb7365d17ccde90fcceb59f (patch)
tree3a331e073782d4056d46de193acdb21461029f96 /term.c
parentf98cf823475cf1b354a213c9bf26d7927e50c14b (diff)
downloadmandoc-24a95b9b6e0ec8aecdb7365d17ccde90fcceb59f.tar.gz
mandoc-24a95b9b6e0ec8aecdb7365d17ccde90fcceb59f.tar.zst
mandoc-24a95b9b6e0ec8aecdb7365d17ccde90fcceb59f.zip
More flesh in terminal-encoder.
Diffstat (limited to 'term.c')
-rw-r--r--term.c837
1 files changed, 631 insertions, 206 deletions
diff --git a/term.c b/term.c
index 3116bab4..2a4aa003 100644
--- a/term.c
+++ b/term.c
@@ -1,4 +1,4 @@
-/* $Id: term.c,v 1.1 2009/02/20 11:04:23 kristaps Exp $ */
+/* $Id: term.c,v 1.2 2009/02/20 23:35:36 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -17,6 +17,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
+#include <ctype.h>
#include <curses.h>
#include <err.h>
#include <stdlib.h>
@@ -25,265 +26,639 @@
#include <term.h>
#include <unistd.h>
-#include "mdoc.h"
-
+#include "private.h"
+
+
+enum termesc {
+ ESC_CLEAR,
+ ESC_BOLD,
+ ESC_UNDERLINE
+};
+
+struct termp {
+ size_t maxvisible;
+ size_t maxcols;
+ size_t indent;
+ size_t col;
+ int flags;
+#define TERMP_BOLD (1 << 0)
+#define TERMP_UNDERLINE (1 << 1)
+#define TERMP_NOSPACE (1 << 2)
+ char *buf;
+};
+
+struct termact {
+ int (*pre)(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+ int (*post)(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+};
-static int termprint_r(size_t, size_t,
+static void termprint_r(struct termp *,
+ const struct mdoc_meta *,
const struct mdoc_node *);
-static void termprint_head(size_t,
+static void termprint_header(struct termp *,
const struct mdoc_meta *);
-static void termprint_tail(size_t,
+static void termprint_footer(struct termp *,
const struct mdoc_meta *);
-static char *arch2a(enum mdoc_arch);
-static char *vol2a(enum mdoc_vol);
-static char *msec2a(enum mdoc_msec);
+static void newln(struct termp *);
+static void vspace(struct termp *);
+static void pword(struct termp *, const char *, size_t);
+static void word(struct termp *, const char *);
+
+static int termp_it_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_ns_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_pp_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_fl_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_op_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_op_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_bl_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_sh_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_sh_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_nd_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_bold_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_under_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_bold_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_under_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+
+const struct termact termacts[MDOC_MAX] = {
+ { NULL, NULL }, /* \" */
+ { NULL, NULL }, /* Dd */
+ { NULL, NULL }, /* Dt */
+ { NULL, NULL }, /* Os */
+ { termp_sh_pre, termp_sh_post }, /* Sh */
+ { NULL, NULL }, /* Ss */
+ { termp_pp_pre, NULL }, /* Pp */
+ { NULL, NULL }, /* D1 */
+ { NULL, NULL }, /* Dl */
+ { NULL, NULL }, /* Bd */
+ { NULL, NULL }, /* Ed */
+ { NULL, termp_bl_post }, /* Bl */
+ { NULL, NULL }, /* El */
+ { termp_it_pre, NULL }, /* It */
+ { NULL, NULL }, /* Ad */
+ { NULL, NULL }, /* An */
+ { termp_under_pre, termp_under_post }, /* Ar */
+ { NULL, NULL }, /* Cd */
+ { NULL, NULL }, /* Cm */
+ { NULL, NULL }, /* Dv */
+ { NULL, NULL }, /* Er */
+ { NULL, NULL }, /* Ev */
+ { NULL, NULL }, /* Ex */
+ { NULL, NULL }, /* Fa */
+ { NULL, NULL }, /* Fd */
+ { termp_fl_pre, termp_bold_post }, /* Fl */
+ { NULL, NULL }, /* Fn */
+ { NULL, NULL }, /* Ft */
+ { NULL, NULL }, /* Ic */
+ { NULL, NULL }, /* In */
+ { NULL, NULL }, /* Li */
+ { termp_nd_pre, NULL }, /* Nd */
+ { termp_bold_pre, termp_bold_post }, /* Nm */
+ { termp_op_pre, termp_op_post }, /* Op */
+ { NULL, NULL }, /* Ot */
+ { NULL, NULL }, /* Pa */
+ { NULL, NULL }, /* Rv */
+ { NULL, NULL }, /* St */
+ { NULL, NULL }, /* Va */
+ { NULL, NULL }, /* Vt */
+ { NULL, NULL }, /* Xr */
+ { NULL, NULL }, /* %A */
+ { NULL, NULL }, /* %B */
+ { NULL, NULL }, /* %D */
+ { NULL, NULL }, /* %I */
+ { NULL, NULL }, /* %J */
+ { NULL, NULL }, /* %N */
+ { NULL, NULL }, /* %O */
+ { NULL, NULL }, /* %P */
+ { NULL, NULL }, /* %R */
+ { NULL, NULL }, /* %T */
+ { NULL, NULL }, /* %V */
+ { NULL, NULL }, /* Ac */
+ { NULL, NULL }, /* Ao */
+ { NULL, NULL }, /* Aq */
+ { NULL, NULL }, /* At */
+ { NULL, NULL }, /* Bc */
+ { NULL, NULL }, /* Bf */
+ { NULL, NULL }, /* Bo */
+ { NULL, NULL }, /* Bq */
+ { NULL, NULL }, /* Bsx */
+ { NULL, NULL }, /* Bx */
+ { NULL, NULL }, /* Db */
+ { NULL, NULL }, /* Dc */
+ { NULL, NULL }, /* Do */
+ { NULL, NULL }, /* Dq */
+ { NULL, NULL }, /* Ec */
+ { NULL, NULL }, /* Ef */
+ { NULL, NULL }, /* Em */
+ { NULL, NULL }, /* Eo */
+ { NULL, NULL }, /* Fx */
+ { NULL, NULL }, /* Ms */
+ { NULL, NULL }, /* No */
+ { termp_ns_pre, NULL }, /* Ns */
+ { NULL, NULL }, /* Nx */
+ { NULL, NULL }, /* Ox */
+ { NULL, NULL }, /* Pc */
+ { NULL, NULL }, /* Pf */
+ { NULL, NULL }, /* Po */
+ { NULL, NULL }, /* Pq */
+ { NULL, NULL }, /* Qc */
+ { NULL, NULL }, /* Ql */
+ { NULL, NULL }, /* Qo */
+ { NULL, NULL }, /* Qq */
+ { NULL, NULL }, /* Re */
+ { NULL, NULL }, /* Rs */
+ { NULL, NULL }, /* Sc */
+ { NULL, NULL }, /* So */
+ { NULL, NULL }, /* Sq */
+ { NULL, NULL }, /* Sm */
+ { NULL, NULL }, /* Sx */
+ { NULL, NULL }, /* Sy */
+ { NULL, NULL }, /* Tn */
+ { NULL, NULL }, /* Ux */
+ { NULL, NULL }, /* Xc */
+ { NULL, NULL }, /* Xo */
+ { NULL, NULL }, /* Fo */
+ { NULL, NULL }, /* Fc */
+ { NULL, NULL }, /* Oo */
+ { NULL, NULL }, /* Oc */
+ { NULL, NULL }, /* Bk */
+ { NULL, NULL }, /* Ek */
+ { NULL, NULL }, /* Bt */
+ { NULL, NULL }, /* Hf */
+ { NULL, NULL }, /* Fr */
+ { NULL, NULL }, /* Ud */
+};
+
+
+static void
+flush(struct termp *p)
+{
+ size_t i, j, vsz, vis, maxvis;
+
+ maxvis = p->maxvisible - (p->indent * 4);
+ vis = 0;
+
+ for (j = 0; j < (p->indent * 4); j++)
+ putchar(' ');
+
+ for (i = 0; i < p->col; i++) {
+ for (j = i, vsz = 0; j < p->col; j++) {
+ if (isspace(p->buf[j]))
+ break;
+ else if (27 == p->buf[j]) {
+ assert(j + 4 <= p->col);
+ j += 3;
+ } else
+ vsz++;
+ }
+ assert(vsz > 0);
+
+ if (vis && vis + vsz >= maxvis) {
+ putchar('\n');
+ for (j = 0; j < (p->indent * 4); j++)
+ putchar(' ');
+ vis = 0;
+ }
+
+ for ( ; i < p->col; i++) {
+ if (isspace(p->buf[i]))
+ break;
+ putchar(p->buf[i]);
+ }
+ vis += vsz;
+ if (i < p->col) {
+ putchar(' ');
+ vis++;
+ }
+ }
+
+ putchar('\n');
+ p->col = 0;
+}
+
+
+static void
+newln(struct termp *p)
+{
-static size_t ttitle2a(char *, enum mdoc_vol, enum mdoc_msec,
- enum mdoc_arch, size_t);
+ p->flags |= TERMP_NOSPACE;
+ if (0 == p->col)
+ return;
+ flush(p);
+}
-static char *
-arch2a(enum mdoc_arch arch)
+static void
+vspace(struct termp *p)
{
- switch (arch) {
- case (ARCH_alpha):
- return("Alpha");
- case (ARCH_amd64):
- return("AMD64");
- case (ARCH_amiga):
- return("Amiga");
- case (ARCH_arc):
- return("ARC");
- case (ARCH_arm):
- return("ARM");
- case (ARCH_armish):
- return("ARMISH");
- case (ARCH_aviion):
- return("AViion");
- case (ARCH_hp300):
- return("HP300");
- case (ARCH_hppa):
- return("HPPA");
- case (ARCH_hppa64):
- return("HPPA64");
- case (ARCH_i386):
- return("i386");
- case (ARCH_landisk):
- return("LANDISK");
- case (ARCH_luna88k):
- return("Luna88k");
- case (ARCH_mac68k):
- return("Mac68k");
- case (ARCH_macppc):
- return("MacPPC");
- case (ARCH_mvme68k):
- return("MVME68k");
- case (ARCH_mvme88k):
- return("MVME88k");
- case (ARCH_mvmeppc):
- return("MVMEPPC");
- case (ARCH_pmax):
- return("PMAX");
- case (ARCH_sgi):
- return("SGI");
- case (ARCH_socppc):
- return("SOCPPC");
- case (ARCH_sparc):
- return("SPARC");
- case (ARCH_sparc64):
- return("SPARC64");
- case (ARCH_sun3):
- return("Sun3");
- case (ARCH_vax):
- return("VAX");
- case (ARCH_zaurus):
- return("Zaurus");
- default:
+ newln(p);
+ putchar('\n');
+}
+
+
+static void
+chara(struct termp *p, char c)
+{
+
+ if (p->col + 1 >= p->maxcols)
+ errx(1, "line overrun");
+
+ p->buf[(p->col)++] = c;
+}
+
+
+static void
+escape(struct termp *p, enum termesc esc)
+{
+
+ if (p->col + 4 >= p->maxcols)
+ errx(1, "line overrun");
+
+ p->buf[(p->col)++] = 27;
+ p->buf[(p->col)++] = '[';
+ switch (esc) {
+ case (ESC_CLEAR):
+ p->buf[(p->col)++] = '0';
+ break;
+ case (ESC_BOLD):
+ p->buf[(p->col)++] = '1';
+ break;
+ case (ESC_UNDERLINE):
+ p->buf[(p->col)++] = '4';
break;
+ default:
+ abort();
+ /* NOTREACHED */
}
+ p->buf[(p->col)++] = 'm';
+}
+
+
+static void
+pword(struct termp *p, const char *word, size_t len)
+{
+ size_t i;
+
+ assert(len > 0);
- return(NULL);
+ if ( ! (p->flags & TERMP_NOSPACE))
+ chara(p, ' ');
+
+ p->flags &= ~TERMP_NOSPACE;
+
+ if (p->flags & TERMP_BOLD)
+ escape(p, ESC_BOLD);
+ if (p->flags & TERMP_UNDERLINE)
+ escape(p, ESC_UNDERLINE);
+
+ for (i = 0; i < len; i++)
+ chara(p, word[i]);
+
+ if (p->flags & TERMP_BOLD ||
+ p->flags & TERMP_UNDERLINE)
+ escape(p, ESC_CLEAR);
}
-static char *
-vol2a(enum mdoc_vol vol)
+static void
+word(struct termp *p, const char *word)
{
+ size_t i, j, len;
+
+ /* TODO: delimiters? */
- switch (vol) {
- case (VOL_AMD):
- return("OpenBSD Ancestral Manual Documents");
- case (VOL_IND):
- return("OpenBSD Manual Master Index");
- case (VOL_KM):
- return("OpenBSD Kernel Manual");
- case (VOL_LOCAL):
- return("OpenBSD Local Manual");
- case (VOL_PRM):
- return("OpenBSD Programmer's Manual");
- case (VOL_PS1):
- return("OpenBSD Programmer's Supplementary Documents");
- case (VOL_SMM):
- return("OpenBSD System Manager's Manual");
- case (VOL_URM):
- return("OpenBSD Reference Manual");
- case (VOL_USD):
- return("OpenBSD User's Supplementary Documents");
+ len = strlen(word);
+ assert(len > 0);
+
+ for (j = i = 0; i < len; i++) {
+ if ( ! isspace(word[i])) {
+ j++;
+ continue;
+ }
+ if (0 == j)
+ continue;
+ assert(i >= j);
+ pword(p, &word[i - j], j);
+ j = 0;
+ }
+ if (j > 0) {
+ assert(i >= j);
+ pword(p, &word[i - j], j);
+ }
+}
+
+
+static int
+termp_it_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ switch (node->type) {
+ case (MDOC_HEAD):
+ /* TODO: only print one, if compat. */
+ vspace(p);
+ break;
default:
break;
}
+ return(1);
+}
+
+
+static int
+termp_bold_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ p->flags &= ~TERMP_BOLD;
+ return(1);
+}
+
+
+static int
+termp_under_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
- return(NULL);
+ p->flags |= TERMP_UNDERLINE;
+ return(1);
}
-static char *
-msec2a(enum mdoc_msec msec)
+static int
+termp_bold_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
{
- switch (msec) {
- case(MSEC_1):
- return("1");
- case(MSEC_2):
- return("2");
- case(MSEC_3):
- return("3");
- case(MSEC_3f):
- return("3f");
- case(MSEC_3p):
- return("3p");
- case(MSEC_4):
- return("4");
- case(MSEC_5):
- return("5");
- case(MSEC_6):
- return("6");
- case(MSEC_7):
- return("7");
- case(MSEC_8):
- return("8");
- case(MSEC_9):
- return("9");
- case(MSEC_X11):
- return("X11");
- case(MSEC_X11R6):
- return("X11R6");
- case(MSEC_local):
- return("local");
- case(MSEC_n):
- return("n");
- case(MSEC_unass):
- /* FALLTHROUGH */
- case(MSEC_draft):
- return("draft");
- case(MSEC_paper):
- return("paper");
+ p->flags |= TERMP_BOLD;
+ return(1);
+}
+
+
+static int
+termp_ns_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ p->flags |= TERMP_NOSPACE;
+ return(1);
+}
+
+
+static int
+termp_pp_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ vspace(p);
+ return(1);
+}
+
+
+static int
+termp_under_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ p->flags &= ~TERMP_UNDERLINE;
+ return(1);
+}
+
+
+static int
+termp_nd_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ word(p, "-");
+ return(1);
+}
+
+
+static int
+termp_bl_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ switch (node->type) {
+ case (MDOC_BLOCK):
+ newln(p);
+ break;
default:
break;
}
- return(NULL);
+ return(1);
}
-static size_t
-ttitle2a(char *dst, enum mdoc_vol vol, enum mdoc_msec msec,
- enum mdoc_arch arch, size_t sz)
+static int
+termp_op_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
{
- char *p;
- size_t ssz;
- if (NULL == (p = vol2a(vol)))
- switch (msec) {
- case (MSEC_1):
- /* FALLTHROUGH */
- case (MSEC_6):
- /* FALLTHROUGH */
- case (MSEC_7):
- p = vol2a(VOL_URM);
- break;
- case (MSEC_8):
- p = vol2a(VOL_SMM);
- break;
- case (MSEC_2):
- /* FALLTHROUGH */
- case (MSEC_3):
- /* FALLTHROUGH */
- case (MSEC_4):
- /* FALLTHROUGH */
- case (MSEC_5):
- p = vol2a(VOL_PRM);
- break;
- case (MSEC_9):
- p = vol2a(VOL_KM);
- break;
- default:
- /* FIXME: capitalise. */
- if (NULL == (p = msec2a(msec)))
- p = msec2a(MSEC_local);
- break;
- }
- assert(p);
-
- if ((ssz = strlcpy(dst, p, sz)) >= sz)
- return(ssz);
-
- if ((p = arch2a(arch))) {
- if ((ssz = strlcat(dst, " (", sz)) >= sz)
- return(ssz);
- if ((ssz = strlcat(dst, p, sz)) >= sz)
- return(ssz);
- if ((ssz = strlcat(dst, ")", sz)) >= sz)
- return(ssz);
+ switch (node->type) {
+ case (MDOC_BODY):
+ p->flags |= TERMP_NOSPACE;
+ word(p, "\\(rB");
+ break;
+ default:
+ break;
}
+ return(1);
+}
- return(ssz);
+
+static int
+termp_sh_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ switch (node->type) {
+ case (MDOC_HEAD):
+ p->flags &= ~TERMP_BOLD;
+ newln(p);
+ break;
+ case (MDOC_BODY):
+ newln(p);
+ (p->indent)--;
+ break;
+ default:
+ break;
+ }
+ return(1);
}
static int
-termprint_r(size_t cols, size_t indent, const struct mdoc_node *node)
+termp_sh_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
{
+ switch (node->type) {
+ case (MDOC_HEAD):
+ vspace(p);
+ p->flags |= TERMP_BOLD;
+ break;
+ case (MDOC_BODY):
+ (p->indent)++;
+ break;
+ default:
+ break;
+ }
return(1);
}
+static int
+termp_op_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ switch (node->type) {
+ case (MDOC_BODY):
+ word(p, "\\(lB");
+ p->flags |= TERMP_NOSPACE;
+ break;
+ default:
+ break;
+ }
+ return(1);
+}
+
+
+static int
+termp_fl_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ p->flags |= TERMP_BOLD;
+ word(p, "-");
+ p->flags |= TERMP_NOSPACE;
+ return(1);
+}
+
+
+static void
+termprint_r(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ /* Pre-processing ----------------- */
+
+ if (MDOC_TEXT != node->type) {
+ if (termacts[node->tok].pre)
+ if ( ! (*termacts[node->tok].pre)(p, meta, node))
+ return;
+ } else /* MDOC_TEXT == node->type */
+ word(p, node->data.text.string);
+
+ /* Children ---------------------- */
+
+ if (NULL == node->child) {
+ /* No-child processing. */
+ switch (node->type) {
+ case (MDOC_ELEM):
+ switch (node->tok) {
+ case (MDOC_Nm):
+ word(p, "progname"); /* TODO */
+ break;
+ case (MDOC_Ar):
+ word(p, "...");
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else
+ termprint_r(p, meta, node->child);
+
+ /* Post-processing --------------- */
+
+ if (MDOC_TEXT != node->type) {
+ if (termacts[node->tok].post)
+ if ( ! (*termacts[node->tok].post)(p, meta, node))
+ return;
+ }
+
+ /* Siblings ---------------------- */
+
+ if (node->next)
+ termprint_r(p, meta, node->next);
+}
+
+
static void
-termprint_tail(size_t cols, const struct mdoc_meta *meta)
+termprint_footer(struct termp *p, const struct mdoc_meta *meta)
{
struct tm *tm;
char *buf, *os;
size_t sz, osz, ssz, i;
- if (NULL == (buf = malloc(cols)))
+ if (NULL == (buf = malloc(p->maxvisible)))
err(1, "malloc");
- if (NULL == (os = malloc(cols)))
+ if (NULL == (os = malloc(p->maxvisible)))
err(1, "malloc");
tm = localtime(&meta->date);
- if (NULL == strftime(buf, cols, "%B %d, %Y", tm))
+ if (NULL == strftime(buf, p->maxvisible, "%B %d, %Y", tm))
err(1, "strftime");
- osz = strlcpy(os, meta->os, cols);
+ osz = strlcpy(os, meta->os, p->maxvisible);
sz = strlen(buf);
ssz = sz + osz + 1;
- if (ssz > cols) {
- ssz -= cols;
+ if (ssz > p->maxvisible) {
+ ssz -= p->maxvisible;
assert(ssz <= osz);
os[osz - ssz] = 0;
ssz = 1;
} else
- ssz = cols - ssz + 1;
+ ssz = p->maxvisible - ssz + 1;
+ printf("\n");
printf("%s", os);
for (i = 0; i < ssz; i++)
printf(" ");
printf("%s\n", buf);
+ fflush(stdout);
free(buf);
free(os);
@@ -291,28 +666,69 @@ termprint_tail(size_t cols, const struct mdoc_meta *meta)
static void
-termprint_head(size_t cols, const struct mdoc_meta *meta)
+termprint_header(struct termp *p, const struct mdoc_meta *meta)
{
- char *msec, *buf, *title;
- size_t ssz, tsz, ttsz, i;
+ char *msec, *buf, *title, *pp;
+ size_t ssz, tsz, ttsz, i;;
- if (NULL == (buf = malloc(cols)))
+ if (NULL == (buf = malloc(p->maxvisible)))
err(1, "malloc");
- if (NULL == (title = malloc(cols)))
+ if (NULL == (title = malloc(p->maxvisible)))
err(1, "malloc");
- /* Format the manual page header. */
+ if (NULL == (pp = mdoc_vol2a(meta->vol)))
+ switch (meta->msec) {
+ case (MSEC_1):
+ /* FALLTHROUGH */
+ case (MSEC_6):
+ /* FALLTHROUGH */
+ case (MSEC_7):
+ pp = mdoc_vol2a(VOL_URM);
+ break;
+ case (MSEC_8):
+ pp = mdoc_vol2a(VOL_SMM);
+ break;
+ case (MSEC_2):
+ /* FALLTHROUGH */
+ case (MSEC_3):
+ /* FALLTHROUGH */
+ case (MSEC_4):
+ /* FALLTHROUGH */
+ case (MSEC_5):
+ pp = mdoc_vol2a(VOL_PRM);
+ break;
+ case (MSEC_9):
+ pp = mdoc_vol2a(VOL_KM);
+ break;
+ default:
+ /* FIXME: capitalise. */
+ if (NULL == (pp = mdoc_msec2a(meta->msec)))
+ pp = mdoc_msec2a(MSEC_local);
+ break;
+ }
+ assert(pp);
+
+ tsz = strlcpy(buf, pp, p->maxvisible);
+ assert(tsz < p->maxvisible);
+
+ if ((pp = mdoc_arch2a(meta->arch))) {
+ tsz = strlcat(buf, " (", p->maxvisible);
+ assert(tsz < p->maxvisible);
+ tsz = strlcat(buf, pp, p->maxvisible);
+ assert(tsz < p->maxvisible);
+ tsz = strlcat(buf, ")", p->maxvisible);
+ assert(tsz < p->maxvisible);
+ }
- tsz = ttitle2a(buf, meta->vol, meta->msec, meta->arch, cols);
- ttsz = strlcpy(title, meta->title, cols);
+ ttsz = strlcpy(title, meta->title, p->maxvisible);
- if (NULL == (msec = msec2a(meta->msec)))
+ if (NULL == (msec = mdoc_msec2a(meta->msec)))
msec = "";
ssz = (2 * (ttsz + 2 + strlen(msec))) + tsz + 2;
- if (ssz > cols) {
- if ((ssz -= cols) % 2)
+ if (ssz > p->maxvisible) {
+ if ((ssz -= p->maxvisible) % 2)
ssz++;
ssz /= 2;
@@ -320,7 +736,7 @@ termprint_head(size_t cols, const struct mdoc_meta *meta)
title[ttsz - ssz] = 0;
ssz = 1;
} else
- ssz = ((cols - ssz) / 2) + 1;
+ ssz = ((p->maxvisible - ssz) / 2) + 1;
printf("%s(%s)", title, msec);
@@ -332,7 +748,8 @@ termprint_head(size_t cols, const struct mdoc_meta *meta)
for (i = 0; i < ssz; i++)
printf(" ");
- printf("%s(%s)\n\n", title, msec);
+ printf("%s(%s)\n", title, msec);
+ fflush(stdout);
free(title);
free(buf);
@@ -343,17 +760,25 @@ int
termprint(const struct mdoc_node *node,
const struct mdoc_meta *meta)
{
- size_t cols;
+ struct termp p;
if (ERR == setupterm(NULL, STDOUT_FILENO, NULL))
return(0);
- cols = columns < 60 ? 60 : (size_t)columns;
+ p.maxvisible = columns < 60 ? 60 : (size_t)columns;
+ p.maxcols = 1024;
+ p.indent = p.col = 0;
+ p.flags = TERMP_NOSPACE;
+
+ if (NULL == (p.buf = malloc(p.maxcols)))
+ err(1, "malloc");
+
+ termprint_header(&p, meta);
+ termprint_r(&p, meta, node);
+ termprint_footer(&p, meta);
+
+ free(p.buf);
- termprint_head(cols, meta);
- if ( ! termprint_r(cols, 0, node))
- return(0);
- termprint_tail(cols, meta);
return(1);
}