static int termp_rv_pre(DECL_ARGS) { int nchild; term_newln(p); nchild = n->nchild; if (nchild > 0) { term_word(p, "The"); for (n = n->child; n; n = n->next) { term_fontpush(p, TERMFONT_BOLD); term_word(p, n->string); term_fontpop(p); p->flags |= TERMP_NOSPACE; term_word(p, "()"); if (n->next == NULL) continue; if (nchild > 2) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } if (n->next->next == NULL) term_word(p, "and"); } if (nchild > 1) term_word(p, "functions return"); else term_word(p, "function returns"); term_word(p, "the value\\~0 if successful;"); } else term_word(p, "Upon successful completion," " the value\\~0 is returned;"); term_word(p, "otherwise the value\\~\\-1 is returned" " and the global variable"); term_fontpush(p, TERMFONT_UNDER); term_word(p, "errno"); term_fontpop(p); term_word(p, "is set to indicate the error."); p->flags |= TERMP_SENTENCE; return(0); }
static void eqn_box(struct termp *p, const struct eqn_box *bp) { if (EQNFONT_NONE != bp->font) term_fontpush(p, fontmap[(int)bp->font]); if (bp->left) term_word(p, bp->left); if (EQN_SUBEXPR == bp->type) term_word(p, "("); if (bp->text) term_word(p, bp->text); if (bp->first) eqn_box(p, bp->first); if (EQN_SUBEXPR == bp->type) term_word(p, ")"); if (bp->right) term_word(p, bp->right); if (EQNFONT_NONE != bp->font) term_fontpop(p); if (bp->next) eqn_box(p, bp->next); }
static int termp_ex_pre(DECL_ARGS) { struct roff_node *nch; term_newln(p); term_word(p, "The"); for (nch = n->child; nch != NULL; nch = nch->next) { term_fontpush(p, TERMFONT_BOLD); term_word(p, nch->string); term_fontpop(p); if (nch->next == NULL) continue; if (nch->prev != NULL || nch->next->next != NULL) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } if (nch->next->next == NULL) term_word(p, "and"); } if (n->child != NULL && n->child->next != NULL) term_word(p, "utilities exit\\~0"); else term_word(p, "utility exits\\~0"); term_word(p, "on success, and\\~>0 if an error occurs."); p->flags |= TERMP_SENTENCE; return 0; }
static int termp_ex_pre(DECL_ARGS) { int nchild; term_newln(p); term_word(p, "The"); nchild = n->nchild; for (n = n->child; n; n = n->next) { term_fontpush(p, TERMFONT_BOLD); term_word(p, n->string); term_fontpop(p); if (nchild > 2 && n->next) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } if (n->next && NULL == n->next->next) term_word(p, "and"); } if (nchild > 1) term_word(p, "utilities exit\\~0"); else term_word(p, "utility exits\\~0"); term_word(p, "on success, and\\~>0 if an error occurs."); p->flags |= TERMP_SENTENCE; return 0; }
/* ARGSUSED */ static int termp_fa_pre(DECL_ARGS) { const struct mdoc_node *nn; if (n->parent->tok != MDOC_Fo) { term_fontpush(p, TERMFONT_UNDER); return(1); } for (nn = n->child; nn; nn = nn->next) { term_fontpush(p, TERMFONT_UNDER); term_word(p, nn->string); term_fontpop(p); if (nn->next) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } } if (n->child && n->next && n->next->tok == MDOC_Fa) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } return(0); }
/* ARGSUSED */ static int termp_ex_pre(DECL_ARGS) { const struct mdoc_node *nn; term_word(p, "The"); for (nn = n->child; nn; nn = nn->next) { term_fontpush(p, TERMFONT_BOLD); term_word(p, nn->string); term_fontpop(p); p->flags |= TERMP_NOSPACE; if (nn->next && NULL == nn->next->next) term_word(p, ", and"); else if (nn->next) term_word(p, ","); else p->flags &= ~TERMP_NOSPACE; } if (n->child && n->child->next) term_word(p, "utilities exit"); else term_word(p, "utility exits"); term_word(p, "0 on success, and >0 if an error occurs."); p->flags |= TERMP_SENTENCE; return(0); }
/* ARGSUSED */ static int termp_rv_pre(DECL_ARGS) { int nchild; term_newln(p); term_word(p, "The"); nchild = n->nchild; for (n = n->child; n; n = n->next) { term_fontpush(p, TERMFONT_BOLD); term_word(p, n->string); term_fontpop(p); p->flags |= TERMP_NOSPACE; term_word(p, "()"); if (nchild > 2 && n->next) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } if (n->next && NULL == n->next->next) term_word(p, "and"); } if (nchild > 1) term_word(p, "functions return"); else term_word(p, "function returns"); term_word(p, "the value 0 if successful; otherwise the value " "-1 is returned and the global variable"); term_fontpush(p, TERMFONT_UNDER); term_word(p, "errno"); term_fontpop(p); term_word(p, "is set to indicate the error."); p->flags |= TERMP_SENTENCE; return(0); }
/* ARGSUSED */ static int termp_fn_pre(DECL_ARGS) { int pretty; pretty = MDOC_SYNPRETTY & n->flags; synopsis_pre(p, n); if (NULL == (n = n->child)) return(0); assert(MDOC_TEXT == n->type); term_fontpush(p, TERMFONT_BOLD); term_word(p, n->string); term_fontpop(p); p->flags |= TERMP_NOSPACE; term_word(p, "("); p->flags |= TERMP_NOSPACE; for (n = n->next; n; n = n->next) { assert(MDOC_TEXT == n->type); term_fontpush(p, TERMFONT_UNDER); term_word(p, n->string); term_fontpop(p); if (n->next) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } } p->flags |= TERMP_NOSPACE; term_word(p, ")"); if (pretty) { p->flags |= TERMP_NOSPACE; term_word(p, ";"); } return(0); }
static void termp_in_post(DECL_ARGS) { if (MDOC_SYNPRETTY & n->flags) term_fontpush(p, TERMFONT_BOLD); p->flags |= TERMP_NOSPACE; term_word(p, ">"); if (MDOC_SYNPRETTY & n->flags) term_fontpop(p); }
static int termp_it_pre(DECL_ARGS) { char buf[24]; const struct roff_node *bl, *nn; size_t ncols, dcol; int i, offset, width; enum mdoc_list type; if (n->type == ROFFT_BLOCK) { print_bvspace(p, n->parent->parent, n); return 1; } bl = n->parent->parent->parent; type = bl->norm->Bl.type; /* * Defaults for specific list types. */ switch (type) { case LIST_bullet: case LIST_dash: case LIST_hyphen: case LIST_enum: width = term_len(p, 2); break; case LIST_hang: width = term_len(p, 8); break; case LIST_column: case LIST_tag: width = term_len(p, 10); break; default: width = 0; break; } offset = 0; /* * First calculate width and offset. This is pretty easy unless * we're a -column list, in which case all prior columns must * be accounted for. */ if (bl->norm->Bl.offs != NULL) { offset = a2width(p, bl->norm->Bl.offs); if (offset < 0 && (size_t)(-offset) > p->offset) offset = -p->offset; else if (offset > SHRT_MAX) offset = 0; } switch (type) { case LIST_column: if (n->type == ROFFT_HEAD) break; /* * Imitate groff's column handling: * - For each earlier column, add its width. * - For less than 5 columns, add four more blanks per * column. * - For exactly 5 columns, add three more blank per * column. * - For more than 5 columns, add only one column. */ ncols = bl->norm->Bl.ncols; dcol = ncols < 5 ? term_len(p, 4) : ncols == 5 ? term_len(p, 3) : term_len(p, 1); /* * Calculate the offset by applying all prior ROFFT_BODY, * so we stop at the ROFFT_HEAD (nn->prev == NULL). */ for (i = 0, nn = n->prev; nn->prev && i < (int)ncols; nn = nn->prev, i++) offset += dcol + a2width(p, bl->norm->Bl.cols[i]); /* * When exceeding the declared number of columns, leave * the remaining widths at 0. This will later be * adjusted to the default width of 10, or, for the last * column, stretched to the right margin. */ if (i >= (int)ncols) break; /* * Use the declared column widths, extended as explained * in the preceding paragraph. */ width = a2width(p, bl->norm->Bl.cols[i]) + dcol; break; default: if (NULL == bl->norm->Bl.width) break; /* * Note: buffer the width by 2, which is groff's magic * number for buffering single arguments. See the above * handling for column for how this changes. */ width = a2width(p, bl->norm->Bl.width) + term_len(p, 2); if (width < 0 && (size_t)(-width) > p->offset) width = -p->offset; else if (width > SHRT_MAX) width = 0; break; } /* * Whitespace control. Inset bodies need an initial space, * while diagonal bodies need two. */ p->flags |= TERMP_NOSPACE; switch (type) { case LIST_diag: if (n->type == ROFFT_BODY) term_word(p, "\\ \\ "); break; case LIST_inset: if (n->type == ROFFT_BODY && n->parent->head->child != NULL) term_word(p, "\\ "); break; default: break; } p->flags |= TERMP_NOSPACE; switch (type) { case LIST_diag: if (n->type == ROFFT_HEAD) term_fontpush(p, TERMFONT_BOLD); break; default: break; } /* * Pad and break control. This is the tricky part. These flags * are documented in term_flushln() in term.c. Note that we're * going to unset all of these flags in termp_it_post() when we * exit. */ switch (type) { case LIST_enum: case LIST_bullet: case LIST_dash: case LIST_hyphen: /* * Weird special case. * Some very narrow lists actually hang. */ if (width <= (int)term_len(p, 2)) p->flags |= TERMP_HANG; if (n->type != ROFFT_HEAD) break; p->flags |= TERMP_NOBREAK; p->trailspace = 1; break; case LIST_hang: if (n->type != ROFFT_HEAD) break; /* * This is ugly. If `-hang' is specified and the body * is a `Bl' or `Bd', then we want basically to nullify * the "overstep" effect in term_flushln() and treat * this as a `-ohang' list instead. */ if (NULL != n->next && NULL != n->next->child && (MDOC_Bl == n->next->child->tok || MDOC_Bd == n->next->child->tok)) break; p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG; p->trailspace = 1; break; case LIST_tag: if (n->type != ROFFT_HEAD) break; p->flags |= TERMP_NOBREAK | TERMP_BRTRSP | TERMP_BRIND; p->trailspace = 2; if (NULL == n->next || NULL == n->next->child) p->flags |= TERMP_DANGLE; break; case LIST_column: if (n->type == ROFFT_HEAD) break; if (NULL == n->next) { p->flags &= ~TERMP_NOBREAK; p->trailspace = 0; } else { p->flags |= TERMP_NOBREAK; p->trailspace = 1; } break; case LIST_diag: if (n->type != ROFFT_HEAD) break; p->flags |= TERMP_NOBREAK | TERMP_BRIND; p->trailspace = 1; break; default: break; } /* * Margin control. Set-head-width lists have their right * margins shortened. The body for these lists has the offset * necessarily lengthened. Everybody gets the offset. */ p->offset += offset; switch (type) { case LIST_hang: /* * Same stipulation as above, regarding `-hang'. We * don't want to recalculate rmargin and offsets when * using `Bd' or `Bl' within `-hang' overstep lists. */ if (n->type == ROFFT_HEAD && NULL != n->next && NULL != n->next->child && (MDOC_Bl == n->next->child->tok || MDOC_Bd == n->next->child->tok)) break; /* FALLTHROUGH */ case LIST_bullet: case LIST_dash: case LIST_enum: case LIST_hyphen: case LIST_tag: if (n->type == ROFFT_HEAD) p->rmargin = p->offset + width; else p->offset += width; break; case LIST_column: assert(width); p->rmargin = p->offset + width; /* * XXX - this behaviour is not documented: the * right-most column is filled to the right margin. */ if (n->type == ROFFT_HEAD) break; if (NULL == n->next && p->rmargin < p->maxrmargin) p->rmargin = p->maxrmargin; break; default: break; } /* * The dash, hyphen, bullet and enum lists all have a special * HEAD character (temporarily bold, in some cases). */ if (n->type == ROFFT_HEAD) switch (type) { case LIST_bullet: term_fontpush(p, TERMFONT_BOLD); term_word(p, "\\[bu]"); term_fontpop(p); break; case LIST_dash: case LIST_hyphen: term_fontpush(p, TERMFONT_BOLD); term_word(p, "-"); term_fontpop(p); break; case LIST_enum: (pair->ppair->ppair->count)++; (void)snprintf(buf, sizeof(buf), "%d.", pair->ppair->ppair->count); term_word(p, buf); break; default: break; } /* * If we're not going to process our children, indicate so here. */ switch (type) { case LIST_bullet: case LIST_item: case LIST_dash: case LIST_hyphen: case LIST_enum: if (n->type == ROFFT_HEAD) return 0; break; case LIST_column: if (n->type == ROFFT_HEAD) return 0; break; default: break; } return 1; }
static int termp_fn_pre(DECL_ARGS) { size_t rmargin = 0; int pretty; pretty = MDOC_SYNPRETTY & n->flags; synopsis_pre(p, n); if (NULL == (n = n->child)) return 0; if (pretty) { rmargin = p->rmargin; p->rmargin = p->offset + term_len(p, 4); p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG; } assert(n->type == ROFFT_TEXT); term_fontpush(p, TERMFONT_BOLD); term_word(p, n->string); term_fontpop(p); if (n->sec == SEC_DESCRIPTION) tag_put(n->string, ++fn_prio, p->line); if (pretty) { term_flushln(p); p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG); p->offset = p->rmargin; p->rmargin = rmargin; } p->flags |= TERMP_NOSPACE; term_word(p, "("); p->flags |= TERMP_NOSPACE; for (n = n->next; n; n = n->next) { assert(n->type == ROFFT_TEXT); term_fontpush(p, TERMFONT_UNDER); if (pretty) p->flags |= TERMP_NBRWORD; term_word(p, n->string); term_fontpop(p); if (n->next) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } } p->flags |= TERMP_NOSPACE; term_word(p, ")"); if (pretty) { p->flags |= TERMP_NOSPACE; term_word(p, ";"); term_flushln(p); } return 0; }
static void eqn_box(struct termp *p, const struct eqn_box *bp) { const struct eqn_box *child; const char *cp; int delim; /* Delimiters around this box? */ if ((bp->type == EQN_LIST && bp->expectargs > 1) || (bp->type == EQN_PILE && (bp->prev || bp->next)) || (bp->parent != NULL && (bp->parent->pos == EQNPOS_SQRT || /* Diacritic followed by ^ or _. */ ((bp->top != NULL || bp->bottom != NULL) && bp->parent->type == EQN_SUBEXPR && bp->parent->pos != EQNPOS_OVER && bp->next != NULL) || /* Nested over, sub, sup, from, to. */ (bp->type == EQN_SUBEXPR && bp->pos != EQNPOS_SQRT && ((bp->parent->type == EQN_LIST && bp->expectargs == 1) || (bp->parent->type == EQN_SUBEXPR && bp->pos != EQNPOS_SQRT)))))) { if ((bp->parent->type == EQN_SUBEXPR && bp->prev != NULL) || (bp->type == EQN_LIST && bp->first != NULL && bp->first->type != EQN_PILE && bp->first->type != EQN_MATRIX && bp->prev != NULL && (bp->prev->type == EQN_LIST || (bp->prev->type == EQN_TEXT && (*bp->prev->text == '\\' || isalpha((unsigned char)*bp->prev->text)))))) p->flags |= TERMP_NOSPACE; term_word(p, bp->left != NULL ? bp->left : "("); p->flags |= TERMP_NOSPACE; delim = 1; } else delim = 0; /* Handle Fonts and text. */ if (bp->font != EQNFONT_NONE) term_fontpush(p, fontmap[(int)bp->font]); if (bp->text != NULL) { if (strchr("!\"'),.:;?]}", *bp->text) != NULL) p->flags |= TERMP_NOSPACE; term_word(p, bp->text); if ((cp = strchr(bp->text, '\0')) > bp->text && (strchr("\"'([{", cp[-1]) != NULL || (bp->prev == NULL && (cp[-1] == '-' || (cp >= bp->text + 5 && strcmp(cp - 5, "\\[mi]") == 0))))) p->flags |= TERMP_NOSPACE; } /* Special box types. */ if (bp->pos == EQNPOS_SQRT) { term_word(p, "\\(sr"); if (bp->first != NULL) { p->flags |= TERMP_NOSPACE; eqn_box(p, bp->first); } } else if (bp->type == EQN_SUBEXPR) { child = bp->first; eqn_box(p, child); p->flags |= TERMP_NOSPACE; term_word(p, bp->pos == EQNPOS_OVER ? "/" : (bp->pos == EQNPOS_SUP || bp->pos == EQNPOS_TO) ? "^" : "_"); child = child->next; if (child != NULL) { p->flags |= TERMP_NOSPACE; eqn_box(p, child); if (bp->pos == EQNPOS_FROMTO || bp->pos == EQNPOS_SUBSUP) { p->flags |= TERMP_NOSPACE; term_word(p, "^"); p->flags |= TERMP_NOSPACE; child = child->next; if (child != NULL) eqn_box(p, child); } } } else { child = bp->first; if (bp->type == EQN_MATRIX && child != NULL && child->type == EQN_LIST && child->expectargs > 1) child = child->first; while (child != NULL) { eqn_box(p, bp->type == EQN_PILE && child->type == EQN_LIST && child->expectargs > 1 && child->args == 1 ? child->first : child); child = child->next; } } /* Handle Fonts and diacritics. */ if (bp->font != EQNFONT_NONE) term_fontpop(p); if (bp->top != NULL) { p->flags |= TERMP_NOSPACE; term_word(p, bp->top); } if (bp->bottom != NULL) { p->flags |= TERMP_NOSPACE; term_word(p, "_"); } /* Right delimiter after this box? */ if (delim) { p->flags |= TERMP_NOSPACE; term_word(p, bp->right != NULL ? bp->right : ")"); if (bp->parent->type == EQN_SUBEXPR && bp->next != NULL) p->flags |= TERMP_NOSPACE; } }
static void eqn_box(struct termp *p, const struct eqn_box *bp) { const struct eqn_box *child; if (bp->type == EQN_LIST || (bp->type == EQN_PILE && (bp->prev || bp->next)) || (bp->parent != NULL && bp->parent->pos == EQNPOS_SQRT)) { if (bp->parent->type == EQN_SUBEXPR && bp->prev != NULL) p->flags |= TERMP_NOSPACE; term_word(p, bp->left != NULL ? bp->left : "("); p->flags |= TERMP_NOSPACE; } if (bp->font != EQNFONT_NONE) term_fontpush(p, fontmap[(int)bp->font]); if (bp->text != NULL) term_word(p, bp->text); if (bp->pos == EQNPOS_SQRT) { term_word(p, "sqrt"); p->flags |= TERMP_NOSPACE; eqn_box(p, bp->first); } else if (bp->type == EQN_SUBEXPR) { child = bp->first; eqn_box(p, child); p->flags |= TERMP_NOSPACE; term_word(p, bp->pos == EQNPOS_OVER ? "/" : (bp->pos == EQNPOS_SUP || bp->pos == EQNPOS_TO) ? "^" : "_"); p->flags |= TERMP_NOSPACE; child = child->next; eqn_box(p, child); if (bp->pos == EQNPOS_FROMTO || bp->pos == EQNPOS_SUBSUP) { p->flags |= TERMP_NOSPACE; term_word(p, "^"); p->flags |= TERMP_NOSPACE; child = child->next; eqn_box(p, child); } } else { child = bp->first; if (bp->type == EQN_MATRIX && child->type == EQN_LIST) child = child->first; while (child != NULL) { eqn_box(p, bp->type == EQN_PILE && child->type == EQN_LIST && child->args == 1 ? child->first : child); child = child->next; } } if (bp->font != EQNFONT_NONE) term_fontpop(p); if (bp->type == EQN_LIST || (bp->type == EQN_PILE && (bp->prev || bp->next)) || (bp->parent != NULL && bp->parent->pos == EQNPOS_SQRT)) { p->flags |= TERMP_NOSPACE; term_word(p, bp->right != NULL ? bp->right : ")"); if (bp->parent->type == EQN_SUBEXPR && bp->next != NULL) p->flags |= TERMP_NOSPACE; } if (bp->top != NULL) { p->flags |= TERMP_NOSPACE; term_word(p, bp->top); } if (bp->bottom != NULL) { p->flags |= TERMP_NOSPACE; term_word(p, "_"); } }
/* ARGSUSED */ static int termp_it_pre(DECL_ARGS) { const struct mdoc_node *bl, *nn; char buf[7]; int i; size_t width, offset, ncols, dcol; enum mdoc_list type; if (MDOC_BLOCK == n->type) { print_bvspace(p, n->parent->parent, n); return(1); } bl = n->parent->parent->parent; type = bl->norm->Bl.type; /* * First calculate width and offset. This is pretty easy unless * we're a -column list, in which case all prior columns must * be accounted for. */ width = offset = 0; if (bl->norm->Bl.offs) offset = a2offs(p, bl->norm->Bl.offs); switch (type) { case (LIST_column): if (MDOC_HEAD == n->type) break; /* * Imitate groff's column handling: * - For each earlier column, add its width. * - For less than 5 columns, add four more blanks per * column. * - For exactly 5 columns, add three more blank per * column. * - For more than 5 columns, add only one column. */ ncols = bl->norm->Bl.ncols; /* LINTED */ dcol = ncols < 5 ? term_len(p, 4) : ncols == 5 ? term_len(p, 3) : term_len(p, 1); /* * Calculate the offset by applying all prior MDOC_BODY, * so we stop at the MDOC_HEAD (NULL == nn->prev). */ for (i = 0, nn = n->prev; nn->prev && i < (int)ncols; nn = nn->prev, i++) offset += dcol + a2width (p, bl->norm->Bl.cols[i]); /* * When exceeding the declared number of columns, leave * the remaining widths at 0. This will later be * adjusted to the default width of 10, or, for the last * column, stretched to the right margin. */ if (i >= (int)ncols) break; /* * Use the declared column widths, extended as explained * in the preceding paragraph. */ width = a2width(p, bl->norm->Bl.cols[i]) + dcol; break; default: if (NULL == bl->norm->Bl.width) break; /* * Note: buffer the width by 2, which is groff's magic * number for buffering single arguments. See the above * handling for column for how this changes. */ assert(bl->norm->Bl.width); width = a2width(p, bl->norm->Bl.width) + term_len(p, 2); break; } /* * List-type can override the width in the case of fixed-head * values (bullet, dash/hyphen, enum). Tags need a non-zero * offset. */ switch (type) { case (LIST_bullet): /* FALLTHROUGH */ case (LIST_dash): /* FALLTHROUGH */ case (LIST_hyphen): if (width < term_len(p, 4)) width = term_len(p, 4); break; case (LIST_enum): if (width < term_len(p, 5)) width = term_len(p, 5); break; case (LIST_hang): if (0 == width) width = term_len(p, 8); break; case (LIST_column): /* FALLTHROUGH */ case (LIST_tag): if (0 == width) width = term_len(p, 10); break; default: break; } /* * Whitespace control. Inset bodies need an initial space, * while diagonal bodies need two. */ p->flags |= TERMP_NOSPACE; switch (type) { case (LIST_diag): if (MDOC_BODY == n->type) term_word(p, "\\ \\ "); break; case (LIST_inset): if (MDOC_BODY == n->type) term_word(p, "\\ "); break; default: break; } p->flags |= TERMP_NOSPACE; switch (type) { case (LIST_diag): if (MDOC_HEAD == n->type) term_fontpush(p, TERMFONT_BOLD); break; default: break; } /* * Pad and break control. This is the tricky part. These flags * are documented in term_flushln() in term.c. Note that we're * going to unset all of these flags in termp_it_post() when we * exit. */ switch (type) { case (LIST_bullet): /* FALLTHROUGH */ case (LIST_dash): /* FALLTHROUGH */ case (LIST_enum): /* FALLTHROUGH */ case (LIST_hyphen): if (MDOC_HEAD == n->type) p->flags |= TERMP_NOBREAK; break; case (LIST_hang): if (MDOC_HEAD == n->type) p->flags |= TERMP_NOBREAK; else break; /* * This is ugly. If `-hang' is specified and the body * is a `Bl' or `Bd', then we want basically to nullify * the "overstep" effect in term_flushln() and treat * this as a `-ohang' list instead. */ if (n->next->child && (MDOC_Bl == n->next->child->tok || MDOC_Bd == n->next->child->tok)) p->flags &= ~TERMP_NOBREAK; else p->flags |= TERMP_HANG; break; case (LIST_tag): if (MDOC_HEAD == n->type) p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE; if (MDOC_HEAD != n->type) break; if (NULL == n->next || NULL == n->next->child) p->flags |= TERMP_DANGLE; break; case (LIST_column): if (MDOC_HEAD == n->type) break; if (NULL == n->next) p->flags &= ~TERMP_NOBREAK; else p->flags |= TERMP_NOBREAK; break; case (LIST_diag): if (MDOC_HEAD == n->type) p->flags |= TERMP_NOBREAK; break; default: break; } /* * Margin control. Set-head-width lists have their right * margins shortened. The body for these lists has the offset * necessarily lengthened. Everybody gets the offset. */ p->offset += offset; switch (type) { case (LIST_hang): /* * Same stipulation as above, regarding `-hang'. We * don't want to recalculate rmargin and offsets when * using `Bd' or `Bl' within `-hang' overstep lists. */ if (MDOC_HEAD == n->type && n->next->child && (MDOC_Bl == n->next->child->tok || MDOC_Bd == n->next->child->tok)) break; /* FALLTHROUGH */ case (LIST_bullet): /* FALLTHROUGH */ case (LIST_dash): /* FALLTHROUGH */ case (LIST_enum): /* FALLTHROUGH */ case (LIST_hyphen): /* FALLTHROUGH */ case (LIST_tag): assert(width); if (MDOC_HEAD == n->type) p->rmargin = p->offset + width; else p->offset += width; break; case (LIST_column): assert(width); p->rmargin = p->offset + width; /* * XXX - this behaviour is not documented: the * right-most column is filled to the right margin. */ if (MDOC_HEAD == n->type) break; if (NULL == n->next && p->rmargin < p->maxrmargin) p->rmargin = p->maxrmargin; break; default: break; } /* * The dash, hyphen, bullet and enum lists all have a special * HEAD character (temporarily bold, in some cases). */ if (MDOC_HEAD == n->type) switch (type) { case (LIST_bullet): term_fontpush(p, TERMFONT_BOLD); term_word(p, "\\[bu]"); term_fontpop(p); break; case (LIST_dash): /* FALLTHROUGH */ case (LIST_hyphen): term_fontpush(p, TERMFONT_BOLD); term_word(p, "\\(hy"); term_fontpop(p); break; case (LIST_enum): (pair->ppair->ppair->count)++; snprintf(buf, sizeof(buf), "%d.", pair->ppair->ppair->count); term_word(p, buf); break; default: break; } /* * If we're not going to process our children, indicate so here. */ switch (type) { case (LIST_bullet): /* FALLTHROUGH */ case (LIST_item): /* FALLTHROUGH */ case (LIST_dash): /* FALLTHROUGH */ case (LIST_hyphen): /* FALLTHROUGH */ case (LIST_enum): if (MDOC_HEAD == n->type) return(0); break; case (LIST_column): if (MDOC_HEAD == n->type) return(0); break; default: break; } return(1); }