-/* $Id: man_term.c,v 1.155 2014/10/28 17:36:19 schwarze Exp $ */
+/* $Id: man_term.c,v 1.163 2014/12/23 13:48:57 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
struct mtermp {
int fl;
#define MANT_LITERAL (1 << 0)
- size_t lmargin[MAXMARGINS]; /* margins (incl. visible page) */
+ int lmargin[MAXMARGINS]; /* margins (incl. vis. page) */
int lmargincur; /* index of current margin */
int lmarginsz; /* actual number of nested margins */
size_t offset; /* default offset to visible page */
#define MAN_NOTEXT (1 << 0) /* Never has text children. */
};
-static int a2width(const struct termp *, const char *);
-static size_t a2height(const struct termp *, const char *);
-
static void print_man_nodelist(DECL_ARGS);
static void print_man_node(DECL_ARGS);
static void print_man_head(struct termp *, const void *);
{ NULL, NULL, 0 }, /* RE */
{ pre_RS, post_RS, 0 }, /* RS */
{ pre_ign, NULL, 0 }, /* DT */
- { pre_ign, NULL, 0 }, /* UC */
+ { pre_ign, NULL, MAN_NOTEXT }, /* UC */
{ pre_PD, NULL, MAN_NOTEXT }, /* PD */
{ pre_ign, NULL, 0 }, /* AT */
{ pre_in, NULL, MAN_NOTEXT }, /* in */
}
}
-
-static size_t
-a2height(const struct termp *p, const char *cp)
-{
- struct roffsu su;
-
- if ( ! a2roffsu(cp, &su, SCALE_VS))
- SCALE_VS_INIT(&su, atoi(cp));
-
- return(term_vspan(p, &su));
-}
-
-static int
-a2width(const struct termp *p, const char *cp)
-{
- struct roffsu su;
-
- if ( ! a2roffsu(cp, &su, SCALE_BU))
- return(-1);
-
- return((int)term_hspan(p, &su));
-}
-
/*
* Printing leading vertical space before a block.
* This is used for the paragraph macros.
static int
pre_PD(DECL_ARGS)
{
+ struct roffsu su;
n = n->child;
- if (0 == n) {
+ if (n == NULL) {
mt->pardist = 1;
return(0);
}
assert(MAN_TEXT == n->type);
- mt->pardist = atoi(n->string);
+ if (a2roffsu(n->string, &su, SCALE_VS))
+ mt->pardist = term_vspan(p, &su);
return(0);
}
static int
pre_in(DECL_ARGS)
{
- int len, less;
- size_t v;
+ struct roffsu su;
const char *cp;
+ size_t v;
+ int less;
term_newln(p);
else
cp--;
- if ((len = a2width(p, ++cp)) < 0)
+ if ( ! a2roffsu(++cp, &su, SCALE_EN))
return(0);
- v = (size_t)len;
+ v = term_hspan(p, &su);
if (less < 0)
p->offset -= p->offset > v ? v : p->offset;
else
p->offset = v;
- /* Don't let this creep beyond the right margin. */
-
- if (p->offset > p->rmargin)
- p->offset = p->rmargin;
-
return(0);
}
static int
pre_sp(DECL_ARGS)
{
- char *s;
- size_t i, len;
- int neg;
+ struct roffsu su;
+ int i, len;
if ((NULL == n->prev && n->parent)) {
switch (n->parent->tok) {
}
}
- neg = 0;
- switch (n->tok) {
- case MAN_br:
+ if (n->tok == MAN_br)
len = 0;
- break;
- default:
- if (NULL == n->child) {
- len = 1;
- break;
- }
- s = n->child->string;
- if ('-' == *s) {
- neg = 1;
- s++;
- }
- len = a2height(p, s);
- break;
+ else if (n->child == NULL)
+ len = 1;
+ else {
+ if ( ! a2roffsu(n->child->string, &su, SCALE_VS))
+ su.scale = 1.0;
+ len = term_vspan(p, &su);
}
- if (0 == len)
+ if (len == 0)
term_newln(p);
- else if (neg)
- p->skipvsp += len;
+ else if (len < 0)
+ p->skipvsp -= len;
else
for (i = 0; i < len; i++)
term_vspace(p);
static int
pre_HP(DECL_ARGS)
{
- size_t len, one;
- int ival;
+ struct roffsu su;
const struct man_node *nn;
+ int len;
switch (n->type) {
case MAN_BLOCK:
p->trailspace = 2;
}
- len = mt->lmargin[mt->lmargincur];
- ival = -1;
-
/* Calculate offset. */
- if (NULL != (nn = n->parent->head->child))
- if ((ival = a2width(p, nn->string)) >= 0)
- len = (size_t)ival;
-
- one = term_len(p, 1);
- if (len < one)
- len = one;
+ if ((nn = n->parent->head->child) != NULL &&
+ a2roffsu(nn->string, &su, SCALE_EN)) {
+ len = term_hspan(p, &su);
+ mt->lmargin[mt->lmargincur] = len;
+ } else
+ len = mt->lmargin[mt->lmargincur];
p->offset = mt->offset;
- p->rmargin = mt->offset + len;
-
- if (ival >= 0)
- mt->lmargin[mt->lmargincur] = (size_t)ival;
+ if (len > 0 || (size_t)(-len) < mt->offset)
+ p->rmargin = mt->offset + len;
+ else
+ p->rmargin = 0;
return(1);
}
static int
pre_IP(DECL_ARGS)
{
+ struct roffsu su;
const struct man_node *nn;
- size_t len;
- int savelit, ival;
+ int len, savelit;
switch (n->type) {
case MAN_BODY:
return(1);
}
- len = mt->lmargin[mt->lmargincur];
- ival = -1;
-
/* Calculate the offset from the optional second argument. */
- if (NULL != (nn = n->parent->head->child))
- if (NULL != (nn = nn->next))
- if ((ival = a2width(p, nn->string)) >= 0)
- len = (size_t)ival;
+ if ((nn = n->parent->head->child) != NULL &&
+ (nn = nn->next) != NULL &&
+ a2roffsu(nn->string, &su, SCALE_EN)) {
+ len = term_hspan(p, &su);
+ mt->lmargin[mt->lmargincur] = len;
+ if (len < 0 && (size_t)(-len) > mt->offset)
+ len = -mt->offset;
+ } else
+ len = mt->lmargin[mt->lmargincur];
switch (n->type) {
case MAN_HEAD:
- /* Handle zero-width lengths. */
- if (0 == len)
- len = term_len(p, 1);
-
p->offset = mt->offset;
p->rmargin = mt->offset + len;
- if (ival < 0)
- break;
-
- /* Set the saved left-margin. */
- mt->lmargin[mt->lmargincur] = (size_t)ival;
savelit = MANT_LITERAL & mt->fl;
mt->fl &= ~MANT_LITERAL;
return(0);
case MAN_BODY:
p->offset = mt->offset + len;
- p->rmargin = p->maxrmargin > p->offset ?
- p->maxrmargin : p->offset;
+ p->rmargin = p->maxrmargin;
break;
default:
break;
static int
pre_TP(DECL_ARGS)
{
+ struct roffsu su;
const struct man_node *nn;
- size_t len;
- int savelit, ival;
+ int len, savelit;
switch (n->type) {
case MAN_HEAD:
return(1);
}
- len = (size_t)mt->lmargin[mt->lmargincur];
- ival = -1;
-
/* Calculate offset. */
- if (NULL != (nn = n->parent->head->child))
- if (nn->string && 0 == (MAN_LINE & nn->flags))
- if ((ival = a2width(p, nn->string)) >= 0)
- len = (size_t)ival;
+ if ((nn = n->parent->head->child) != NULL &&
+ nn->string != NULL && ! (MAN_LINE & nn->flags) &&
+ a2roffsu(nn->string, &su, SCALE_EN)) {
+ len = term_hspan(p, &su);
+ mt->lmargin[mt->lmargincur] = len;
+ if (len < 0 && (size_t)(-len) > mt->offset)
+ len = -mt->offset;
+ } else
+ len = mt->lmargin[mt->lmargincur];
switch (n->type) {
case MAN_HEAD:
- /* Handle zero-length properly. */
- if (0 == len)
- len = term_len(p, 1);
-
p->offset = mt->offset;
p->rmargin = mt->offset + len;
if (savelit)
mt->fl |= MANT_LITERAL;
- if (ival >= 0)
- mt->lmargin[mt->lmargincur] = (size_t)ival;
-
return(0);
case MAN_BODY:
p->offset = mt->offset + len;
- p->rmargin = p->maxrmargin > p->offset ?
- p->maxrmargin : p->offset;
+ p->rmargin = p->maxrmargin;
p->trailspace = 0;
p->flags &= ~TERMP_NOBREAK;
break;
mt->fl &= ~MANT_LITERAL;
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
mt->offset = term_len(p, p->defindent);
- /* If following a prior empty `SS', no vspace. */
- if (n->prev && MAN_SS == n->prev->tok)
- if (NULL == n->prev->body->child)
- break;
- if (NULL == n->prev)
+
+ /*
+ * No vertical space before the first subsection
+ * and after an empty subsection.
+ */
+
+ do {
+ n = n->prev;
+ } while (n != NULL && termacts[n->tok].flags & MAN_NOTEXT);
+ if (n == NULL || (n->tok == MAN_SS && n->body->child == NULL))
break;
+
for (i = 0; i < mt->pardist; i++)
term_vspace(p);
break;
mt->fl &= ~MANT_LITERAL;
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
mt->offset = term_len(p, p->defindent);
- /* If following a prior empty `SH', no vspace. */
- if (n->prev && MAN_SH == n->prev->tok)
- if (NULL == n->prev->body->child)
- break;
- /* If the first macro, no vspae. */
- if (NULL == n->prev)
+
+ /*
+ * No vertical space before the first section
+ * and after an empty section.
+ */
+
+ do {
+ n = n->prev;
+ } while (n != NULL && termacts[n->tok].flags & MAN_NOTEXT);
+ if (n == NULL || (n->tok == MAN_SH && n->body->child == NULL))
break;
+
for (i = 0; i < mt->pardist; i++)
term_vspace(p);
break;
static int
pre_RS(DECL_ARGS)
{
- int ival;
- size_t sz;
+ struct roffsu su;
+ int len;
switch (n->type) {
case MAN_BLOCK:
break;
}
- sz = term_len(p, p->defindent);
-
- if (NULL != (n = n->parent->head->child))
- if ((ival = a2width(p, n->string)) >= 0)
- sz = (size_t)ival;
+ if ((n = n->parent->head->child) != NULL &&
+ a2roffsu(n->string, &su, SCALE_EN))
+ len = term_hspan(p, &su);
+ else
+ len = term_len(p, p->defindent);
- mt->offset += sz;
+ if (len > 0 || (size_t)(-len) < mt->offset)
+ mt->offset += len;
+ else
+ mt->offset = 0;
p->offset = mt->offset;
- p->rmargin = p->maxrmargin > p->offset ?
- p->maxrmargin : p->offset;
+ p->rmargin = p->maxrmargin;
if (++mt->lmarginsz < MAXMARGINS)
mt->lmargincur = mt->lmarginsz;
static void
post_RS(DECL_ARGS)
{
- int ival;
- size_t sz;
+ struct roffsu su;
+ int len;
switch (n->type) {
case MAN_BLOCK:
break;
}
- sz = term_len(p, p->defindent);
-
- if (NULL != (n = n->parent->head->child))
- if ((ival = a2width(p, n->string)) >= 0)
- sz = (size_t)ival;
+ if ((n = n->parent->head->child) != NULL &&
+ a2roffsu(n->string, &su, SCALE_EN))
+ len = term_hspan(p, &su);
+ else
+ len = term_len(p, p->defindent);
- mt->offset = mt->offset < sz ? 0 : mt->offset - sz;
+ if (len < 0 || (size_t)len < mt->offset)
+ mt->offset -= len;
+ else
+ mt->offset = 0;
p->offset = mt->offset;
if (--mt->lmarginsz < MAXMARGINS)
* -man doesn't have nested macros, we don't need to be
* more specific than this.
*/
- if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) &&
- (NULL == n->next || MAN_LINE & n->next->flags)) {
+ if (mt->fl & MANT_LITERAL &&
+ ! (p->flags & (TERMP_NOBREAK | TERMP_NONEWLINE)) &&
+ (n->next == NULL || n->next->flags & MAN_LINE)) {
rm = p->rmargin;
rmax = p->maxrmargin;
p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
p->flags |= TERMP_NOSPACE;
- if (NULL != n->string && '\0' != *n->string)
+ if (n->string != NULL && *n->string != '\0')
term_flushln(p);
else
term_newln(p);
{
const struct man_meta *meta;
char *title;
- size_t datelen;
+ size_t datelen, titlen;
meta = (const struct man_meta *)arg;
assert(meta->title);
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
p->trailspace = 1;
p->offset = 0;
- p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2;
+ p->rmargin = p->maxrmargin > datelen ?
+ (p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0;
if (meta->source)
term_word(p, meta->source);
/* At the bottom in the middle: manual date. */
- p->flags |= TERMP_NOSPACE;
p->offset = p->rmargin;
- p->rmargin = p->maxrmargin - term_strlen(p, title);
- if (p->offset + datelen >= p->rmargin)
- p->rmargin = p->offset + datelen;
+ titlen = term_strlen(p, title);
+ p->rmargin = p->maxrmargin > titlen ? p->maxrmargin - titlen : 0;
+ p->flags |= TERMP_NOSPACE;
term_word(p, meta->date);
term_flushln(p);
p->offset = 0;
p->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ?
(p->maxrmargin - vollen + term_len(p, 1)) / 2 :
- p->maxrmargin - vollen;
+ vollen < p->maxrmargin ? p->maxrmargin - vollen : 0;
term_word(p, title);
term_flushln(p);