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 void eqn_box(struct html *p, const struct eqn_box *bp) { struct tag *t; t = EQNFONT_NONE == bp->font ? NULL : print_otag(p, fontmap[(int)bp->font], 0, NULL); if (bp->left) print_text(p, bp->left); if (bp->text) print_text(p, bp->text); if (bp->first) eqn_box(p, bp->first); if (NULL != t) print_tagq(p, t); if (bp->right) print_text(p, bp->right); if (bp->next) eqn_box(p, bp->next); }
void term_eqn(struct termp *p, const struct eqn_box *bp) { eqn_box(p, bp); p->flags &= ~TERMP_NOSPACE; }
void term_eqn(struct termp *p, const struct eqn *ep) { eqn_box(p, ep->root); p->flags &= ~TERMP_NOSPACE; }
void term_eqn(struct termp *p, const struct eqn *ep) { p->flags |= TERMP_NONOSPACE; eqn_box(p, ep->root); term_word(p, " "); p->flags &= ~TERMP_NONOSPACE; }
static enum eqn_rest eqn_eqn(struct eqn_node *ep, struct eqn_box *last) { struct eqn_box *bp; enum eqn_rest c; bp = eqn_box_alloc(ep, last); bp->type = EQN_SUBEXPR; while (EQN_OK == (c = eqn_box(ep, bp))) /* Spin! */ ; return(c); }
void print_eqn(struct html *p, const struct eqn *ep) { struct htmlpair tag; struct tag *t; PAIR_CLASS_INIT(&tag, "eqn"); t = print_otag(p, TAG_MATH, 1, &tag); p->flags |= HTML_NONOSPACE; eqn_box(p, ep->root); p->flags &= ~HTML_NONOSPACE; print_tagq(p, t); }
static enum eqn_rest eqn_matrix(struct eqn_node *ep, struct eqn_box *last) { struct eqn_box *bp; const char *start; size_t sz; enum eqn_rest c; bp = eqn_box_alloc(ep, last); bp->type = EQN_MATRIX; if (NULL == (start = eqn_nexttok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } if ( ! STRNEQ(start, sz, "{", 1)) { EQN_MSG(MANDOCERR_EQNSYNT, ep); return(EQN_ERR); } while (EQN_OK == (c = eqn_box(ep, bp))) switch (bp->last->pile) { case (EQNPILE_LCOL): /* FALLTHROUGH */ case (EQNPILE_CCOL): /* FALLTHROUGH */ case (EQNPILE_RCOL): continue; default: EQN_MSG(MANDOCERR_EQNSYNT, ep); return(EQN_ERR); }; if (EQN_DESCOPE != c) { if (EQN_EOF == c) EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } eqn_rewind(ep); start = eqn_nexttok(ep, &sz); assert(start); if (STRNEQ(start, sz, "}", 1)) return(EQN_OK); EQN_MSG(MANDOCERR_EQNBADSCOPE, ep); return(EQN_ERR); }
static void eqn_box(struct html *p, const struct eqn_box *bp) { struct tag *post, *row, *cell, *t; struct htmlpair tag[2]; const struct eqn_box *child, *parent; size_t i, j, rows; if (NULL == bp) return; post = NULL; /* * Special handling for a matrix, which is presented to us in * column order, but must be printed in row-order. */ if (EQN_MATRIX == bp->type) { if (NULL == bp->first) goto out; if (EQN_LIST != bp->first->type) { eqn_box(p, bp->first); goto out; } if (NULL == (parent = bp->first->first)) goto out; /* Estimate the number of rows, first. */ if (NULL == (child = parent->first)) goto out; for (rows = 0; NULL != child; rows++) child = child->next; /* Print row-by-row. */ post = print_otag(p, TAG_MTABLE, 0, NULL); for (i = 0; i < rows; i++) { parent = bp->first->first; row = print_otag(p, TAG_MTR, 0, NULL); while (NULL != parent) { child = parent->first; for (j = 0; j < i; j++) { if (NULL == child) break; child = child->next; } cell = print_otag (p, TAG_MTD, 0, NULL); /* * If we have no data for this * particular cell, then print a * placeholder and continue--don't puke. */ if (NULL != child) eqn_box(p, child->first); print_tagq(p, cell); parent = parent->next; } print_tagq(p, row); } goto out; } switch (bp->pos) { case (EQNPOS_TO): post = print_otag(p, TAG_MOVER, 0, NULL); break; case (EQNPOS_SUP): post = print_otag(p, TAG_MSUP, 0, NULL); break; case (EQNPOS_FROM): post = print_otag(p, TAG_MUNDER, 0, NULL); break; case (EQNPOS_SUB): post = print_otag(p, TAG_MSUB, 0, NULL); break; case (EQNPOS_OVER): post = print_otag(p, TAG_MFRAC, 0, NULL); break; case (EQNPOS_FROMTO): post = print_otag(p, TAG_MUNDEROVER, 0, NULL); break; case (EQNPOS_SUBSUP): post = print_otag(p, TAG_MSUBSUP, 0, NULL); break; case (EQNPOS_SQRT): post = print_otag(p, TAG_MSQRT, 0, NULL); break; default: break; } if (bp->top || bp->bottom) { assert(NULL == post); if (bp->top && NULL == bp->bottom) post = print_otag(p, TAG_MOVER, 0, NULL); else if (bp->top && bp->bottom) post = print_otag(p, TAG_MUNDEROVER, 0, NULL); else if (bp->bottom) post = print_otag(p, TAG_MUNDER, 0, NULL); } if (EQN_PILE == bp->type) { assert(NULL == post); if (bp->first != NULL && bp->first->type == EQN_LIST) post = print_otag(p, TAG_MTABLE, 0, NULL); } else if (bp->type == EQN_LIST && bp->parent && bp->parent->type == EQN_PILE) { assert(NULL == post); post = print_otag(p, TAG_MTR, 0, NULL); print_otag(p, TAG_MTD, 0, NULL); } if (NULL != bp->text) { assert(NULL == post); post = print_otag(p, TAG_MI, 0, NULL); print_text(p, bp->text); } else if (NULL == post) { if (NULL != bp->left || NULL != bp->right) { PAIR_INIT(&tag[0], ATTR_OPEN, NULL == bp->left ? "" : bp->left); PAIR_INIT(&tag[1], ATTR_CLOSE, NULL == bp->right ? "" : bp->right); post = print_otag(p, TAG_MFENCED, 2, tag); } if (NULL == post) post = print_otag(p, TAG_MROW, 0, NULL); else print_otag(p, TAG_MROW, 0, NULL); } eqn_box(p, bp->first); out: if (NULL != bp->bottom) { t = print_otag(p, TAG_MO, 0, NULL); print_text(p, bp->bottom); print_tagq(p, t); } if (NULL != bp->top) { t = print_otag(p, TAG_MO, 0, NULL); print_text(p, bp->top); print_tagq(p, t); } if (NULL != post) print_tagq(p, post); eqn_box(p, bp->next); }
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, "_"); } }
static enum eqn_rest eqn_box(struct eqn_node *ep, struct eqn_box *last) { size_t sz; const char *start; char *left; char sym[64]; enum eqn_rest c; int i, size; struct eqn_box *bp; if (NULL == (start = eqn_nexttok(ep, &sz))) return(EQN_EOF); if (STRNEQ(start, sz, "}", 1)) return(EQN_DESCOPE); else if (STRNEQ(start, sz, "right", 5)) return(EQN_DESCOPE); else if (STRNEQ(start, sz, "above", 5)) return(EQN_DESCOPE); else if (STRNEQ(start, sz, "mark", 4)) return(EQN_OK); else if (STRNEQ(start, sz, "lineup", 6)) return(EQN_OK); for (i = 0; i < (int)EQN__MAX; i++) { if ( ! EQNSTREQ(&eqnparts[i].str, start, sz)) continue; return((*eqnparts[i].fp)(ep) ? EQN_OK : EQN_ERR); } if (STRNEQ(start, sz, "{", 1)) { if (EQN_DESCOPE != (c = eqn_eqn(ep, last))) { if (EQN_ERR != c) EQN_MSG(MANDOCERR_EQNSCOPE, ep); return(EQN_ERR); } eqn_rewind(ep); start = eqn_nexttok(ep, &sz); assert(start); if (STRNEQ(start, sz, "}", 1)) return(EQN_OK); EQN_MSG(MANDOCERR_EQNBADSCOPE, ep); return(EQN_ERR); } for (i = 0; i < (int)EQNPILE__MAX; i++) { if ( ! EQNSTREQ(&eqnpiles[i], start, sz)) continue; if (EQN_OK == (c = eqn_list(ep, last))) last->last->pile = (enum eqn_pilet)i; return(c); } if (STRNEQ(start, sz, "matrix", 6)) return(eqn_matrix(ep, last)); if (STRNEQ(start, sz, "left", 4)) { if (NULL == (start = eqn_nexttok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } left = mandoc_strndup(start, sz); c = eqn_eqn(ep, last); if (last->last) last->last->left = left; else free(left); if (EQN_DESCOPE != c) return(c); assert(last->last); eqn_rewind(ep); start = eqn_nexttok(ep, &sz); assert(start); if ( ! STRNEQ(start, sz, "right", 5)) return(EQN_DESCOPE); if (NULL == (start = eqn_nexttok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } last->last->right = mandoc_strndup(start, sz); return(EQN_OK); } for (i = 0; i < (int)EQNPOS__MAX; i++) { if ( ! EQNSTREQ(&eqnposs[i], start, sz)) continue; if (NULL == last->last) { EQN_MSG(MANDOCERR_EQNSYNT, ep); return(EQN_ERR); } last->last->pos = (enum eqn_post)i; if (EQN_EOF == (c = eqn_box(ep, last))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } return(c); } for (i = 0; i < (int)EQNMARK__MAX; i++) { if ( ! EQNSTREQ(&eqnmarks[i], start, sz)) continue; if (NULL == last->last) { EQN_MSG(MANDOCERR_EQNSYNT, ep); return(EQN_ERR); } last->last->mark = (enum eqn_markt)i; if (EQN_EOF == (c = eqn_box(ep, last))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } return(c); } for (i = 0; i < (int)EQNFONT__MAX; i++) { if ( ! EQNSTREQ(&eqnfonts[i], start, sz)) continue; if (EQN_EOF == (c = eqn_box(ep, last))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } else if (EQN_OK == c) last->last->font = (enum eqn_fontt)i; return(c); } if (STRNEQ(start, sz, "size", 4)) { if (NULL == (start = eqn_nexttok(ep, &sz))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } size = mandoc_strntoi(start, sz, 10); if (EQN_EOF == (c = eqn_box(ep, last))) { EQN_MSG(MANDOCERR_EQNEOF, ep); return(EQN_ERR); } else if (EQN_OK != c) return(c); last->last->size = size; } bp = eqn_box_alloc(ep, last); bp->type = EQN_TEXT; for (i = 0; i < (int)EQNSYM__MAX; i++) if (EQNSTREQ(&eqnsyms[i].str, start, sz)) { sym[63] = '\0'; snprintf(sym, 62, "\\[%s]", eqnsyms[i].sym); bp->text = mandoc_strdup(sym); return(EQN_OK); } bp->text = mandoc_strndup(start, sz); return(EQN_OK); }