1 /* $OpenBSD: eqn_term.c,v 1.4 2015/01/01 15:34:43 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4 * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 #include <sys/types.h> 19 20 #include <assert.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #include "mandoc.h" 26 #include "out.h" 27 #include "term.h" 28 29 static const enum termfont fontmap[EQNFONT__MAX] = { 30 TERMFONT_NONE, /* EQNFONT_NONE */ 31 TERMFONT_NONE, /* EQNFONT_ROMAN */ 32 TERMFONT_BOLD, /* EQNFONT_BOLD */ 33 TERMFONT_BOLD, /* EQNFONT_FAT */ 34 TERMFONT_UNDER /* EQNFONT_ITALIC */ 35 }; 36 37 static void eqn_box(struct termp *, const struct eqn_box *); 38 39 40 void 41 term_eqn(struct termp *p, const struct eqn *ep) 42 { 43 44 eqn_box(p, ep->root); 45 p->flags &= ~TERMP_NOSPACE; 46 } 47 48 static void 49 eqn_box(struct termp *p, const struct eqn_box *bp) 50 { 51 const struct eqn_box *child; 52 53 if (bp->type == EQN_LIST || 54 (bp->type == EQN_PILE && (bp->prev || bp->next)) || 55 (bp->parent != NULL && bp->parent->pos == EQNPOS_SQRT)) { 56 if (bp->parent->type == EQN_SUBEXPR && bp->prev != NULL) 57 p->flags |= TERMP_NOSPACE; 58 term_word(p, bp->left != NULL ? bp->left : "("); 59 p->flags |= TERMP_NOSPACE; 60 } 61 if (bp->font != EQNFONT_NONE) 62 term_fontpush(p, fontmap[(int)bp->font]); 63 64 if (bp->text != NULL) 65 term_word(p, bp->text); 66 67 if (bp->pos == EQNPOS_SQRT) { 68 term_word(p, "sqrt"); 69 p->flags |= TERMP_NOSPACE; 70 eqn_box(p, bp->first); 71 } else if (bp->type == EQN_SUBEXPR) { 72 child = bp->first; 73 eqn_box(p, child); 74 p->flags |= TERMP_NOSPACE; 75 term_word(p, bp->pos == EQNPOS_OVER ? "/" : 76 (bp->pos == EQNPOS_SUP || 77 bp->pos == EQNPOS_TO) ? "^" : "_"); 78 p->flags |= TERMP_NOSPACE; 79 child = child->next; 80 if (child != NULL) { 81 eqn_box(p, child); 82 if (bp->pos == EQNPOS_FROMTO || 83 bp->pos == EQNPOS_SUBSUP) { 84 p->flags |= TERMP_NOSPACE; 85 term_word(p, "^"); 86 p->flags |= TERMP_NOSPACE; 87 child = child->next; 88 if (child != NULL) 89 eqn_box(p, child); 90 } 91 } 92 } else { 93 child = bp->first; 94 if (bp->type == EQN_MATRIX && child->type == EQN_LIST) 95 child = child->first; 96 while (child != NULL) { 97 eqn_box(p, 98 bp->type == EQN_PILE && 99 child->type == EQN_LIST && 100 child->args == 1 ? 101 child->first : child); 102 child = child->next; 103 } 104 } 105 106 if (bp->font != EQNFONT_NONE) 107 term_fontpop(p); 108 if (bp->type == EQN_LIST || 109 (bp->type == EQN_PILE && (bp->prev || bp->next)) || 110 (bp->parent != NULL && bp->parent->pos == EQNPOS_SQRT)) { 111 p->flags |= TERMP_NOSPACE; 112 term_word(p, bp->right != NULL ? bp->right : ")"); 113 if (bp->parent->type == EQN_SUBEXPR && bp->next != NULL) 114 p->flags |= TERMP_NOSPACE; 115 } 116 117 if (bp->top != NULL) { 118 p->flags |= TERMP_NOSPACE; 119 term_word(p, bp->top); 120 } 121 if (bp->bottom != NULL) { 122 p->flags |= TERMP_NOSPACE; 123 term_word(p, "_"); 124 } 125 } 126