Annotation of mandoc/eqn_html.c, Revision 1.18
1.18 ! schwarze 1: /* $Id: eqn_html.c,v 1.17 2017/07/14 13:32:35 schwarze Exp $ */
1.1 kristaps 2: /*
1.9 schwarze 3: * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
1.11 schwarze 4: * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 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 "config.h"
1.4 schwarze 19:
20: #include <sys/types.h>
1.1 kristaps 21:
22: #include <assert.h>
1.13 schwarze 23: #include <ctype.h>
1.1 kristaps 24: #include <stdio.h>
25: #include <stdlib.h>
26: #include <string.h>
27:
28: #include "mandoc.h"
1.18 ! schwarze 29: #include "eqn.h"
1.1 kristaps 30: #include "out.h"
31: #include "html.h"
32:
1.8 kristaps 33: static void
34: eqn_box(struct html *p, const struct eqn_box *bp)
1.1 kristaps 35: {
1.8 kristaps 36: struct tag *post, *row, *cell, *t;
37: const struct eqn_box *child, *parent;
1.14 schwarze 38: const char *cp;
1.8 kristaps 39: size_t i, j, rows;
1.13 schwarze 40: enum htmltag tag;
41: enum eqn_fontt font;
1.5 kristaps 42:
43: if (NULL == bp)
1.8 kristaps 44: return;
1.5 kristaps 45:
1.8 kristaps 46: post = NULL;
1.5 kristaps 47:
48: /*
1.8 kristaps 49: * Special handling for a matrix, which is presented to us in
50: * column order, but must be printed in row-order.
1.5 kristaps 51: */
1.8 kristaps 52: if (EQN_MATRIX == bp->type) {
53: if (NULL == bp->first)
54: goto out;
1.15 schwarze 55: if (bp->first->type != EQN_LIST ||
56: bp->first->expectargs == 1) {
1.10 schwarze 57: eqn_box(p, bp->first);
58: goto out;
59: }
1.8 kristaps 60: if (NULL == (parent = bp->first->first))
61: goto out;
62: /* Estimate the number of rows, first. */
63: if (NULL == (child = parent->first))
64: goto out;
1.9 schwarze 65: for (rows = 0; NULL != child; rows++)
1.8 kristaps 66: child = child->next;
67: /* Print row-by-row. */
1.11 schwarze 68: post = print_otag(p, TAG_MTABLE, "");
1.8 kristaps 69: for (i = 0; i < rows; i++) {
70: parent = bp->first->first;
1.11 schwarze 71: row = print_otag(p, TAG_MTR, "");
1.8 kristaps 72: while (NULL != parent) {
73: child = parent->first;
74: for (j = 0; j < i; j++) {
75: if (NULL == child)
76: break;
77: child = child->next;
78: }
1.11 schwarze 79: cell = print_otag(p, TAG_MTD, "");
1.9 schwarze 80: /*
1.8 kristaps 81: * If we have no data for this
82: * particular cell, then print a
83: * placeholder and continue--don't puke.
84: */
1.9 schwarze 85: if (NULL != child)
1.8 kristaps 86: eqn_box(p, child->first);
87: print_tagq(p, cell);
88: parent = parent->next;
89: }
90: print_tagq(p, row);
91: }
92: goto out;
1.6 kristaps 93: }
1.5 kristaps 94:
95: switch (bp->pos) {
1.12 schwarze 96: case EQNPOS_TO:
1.11 schwarze 97: post = print_otag(p, TAG_MOVER, "");
1.7 kristaps 98: break;
1.12 schwarze 99: case EQNPOS_SUP:
1.11 schwarze 100: post = print_otag(p, TAG_MSUP, "");
1.5 kristaps 101: break;
1.12 schwarze 102: case EQNPOS_FROM:
1.11 schwarze 103: post = print_otag(p, TAG_MUNDER, "");
1.7 kristaps 104: break;
1.12 schwarze 105: case EQNPOS_SUB:
1.11 schwarze 106: post = print_otag(p, TAG_MSUB, "");
1.5 kristaps 107: break;
1.12 schwarze 108: case EQNPOS_OVER:
1.11 schwarze 109: post = print_otag(p, TAG_MFRAC, "");
1.5 kristaps 110: break;
1.12 schwarze 111: case EQNPOS_FROMTO:
1.11 schwarze 112: post = print_otag(p, TAG_MUNDEROVER, "");
1.7 kristaps 113: break;
1.12 schwarze 114: case EQNPOS_SUBSUP:
1.11 schwarze 115: post = print_otag(p, TAG_MSUBSUP, "");
1.8 kristaps 116: break;
1.12 schwarze 117: case EQNPOS_SQRT:
1.11 schwarze 118: post = print_otag(p, TAG_MSQRT, "");
1.5 kristaps 119: break;
120: default:
121: break;
122: }
123:
1.8 kristaps 124: if (bp->top || bp->bottom) {
125: assert(NULL == post);
126: if (bp->top && NULL == bp->bottom)
1.11 schwarze 127: post = print_otag(p, TAG_MOVER, "");
1.8 kristaps 128: else if (bp->top && bp->bottom)
1.11 schwarze 129: post = print_otag(p, TAG_MUNDEROVER, "");
1.8 kristaps 130: else if (bp->bottom)
1.11 schwarze 131: post = print_otag(p, TAG_MUNDER, "");
1.8 kristaps 132: }
133:
134: if (EQN_PILE == bp->type) {
135: assert(NULL == post);
1.15 schwarze 136: if (bp->first != NULL &&
137: bp->first->type == EQN_LIST &&
138: bp->first->expectargs > 1)
1.11 schwarze 139: post = print_otag(p, TAG_MTABLE, "");
1.15 schwarze 140: } else if (bp->type == EQN_LIST && bp->expectargs > 1 &&
1.10 schwarze 141: bp->parent && bp->parent->type == EQN_PILE) {
1.8 kristaps 142: assert(NULL == post);
1.11 schwarze 143: post = print_otag(p, TAG_MTR, "");
144: print_otag(p, TAG_MTD, "");
1.8 kristaps 145: }
1.5 kristaps 146:
1.13 schwarze 147: if (bp->text != NULL) {
148: assert(post == NULL);
149: tag = TAG_MI;
1.14 schwarze 150: cp = bp->text;
151: if (isdigit((unsigned char)cp[0]) ||
152: (cp[0] == '.' && isdigit((unsigned char)cp[1]))) {
1.13 schwarze 153: tag = TAG_MN;
154: while (*++cp != '\0') {
1.14 schwarze 155: if (*cp != '.' &&
156: isdigit((unsigned char)*cp) == 0) {
1.13 schwarze 157: tag = TAG_MI;
158: break;
159: }
160: }
1.14 schwarze 161: } else if (*cp != '\0' && isalpha((unsigned char)*cp) == 0) {
1.13 schwarze 162: tag = TAG_MO;
1.14 schwarze 163: while (*cp != '\0') {
164: if (cp[0] == '\\' && cp[1] != '\0') {
165: cp++;
166: mandoc_escape(&cp, NULL, NULL);
167: } else if (isalnum((unsigned char)*cp)) {
1.13 schwarze 168: tag = TAG_MI;
169: break;
1.14 schwarze 170: } else
171: cp++;
1.13 schwarze 172: }
173: }
174: font = bp->font;
175: if (bp->text[0] != '\0' &&
176: (((tag == TAG_MN || tag == TAG_MO) &&
177: font == EQNFONT_ROMAN) ||
178: (tag == TAG_MI && font == (bp->text[1] == '\0' ?
179: EQNFONT_ITALIC : EQNFONT_ROMAN))))
180: font = EQNFONT_NONE;
181: switch (font) {
182: case EQNFONT_NONE:
183: post = print_otag(p, tag, "");
184: break;
185: case EQNFONT_ROMAN:
186: post = print_otag(p, tag, "?", "fontstyle", "normal");
187: break;
188: case EQNFONT_BOLD:
189: case EQNFONT_FAT:
190: post = print_otag(p, tag, "?", "fontweight", "bold");
191: break;
192: case EQNFONT_ITALIC:
193: post = print_otag(p, tag, "?", "fontstyle", "italic");
194: break;
195: default:
196: abort();
197: }
1.8 kristaps 198: print_text(p, bp->text);
1.9 schwarze 199: } else if (NULL == post) {
1.11 schwarze 200: if (NULL != bp->left || NULL != bp->right)
201: post = print_otag(p, TAG_MFENCED, "??",
202: "open", bp->left == NULL ? "" : bp->left,
203: "close", bp->right == NULL ? "" : bp->right);
1.8 kristaps 204: if (NULL == post)
1.11 schwarze 205: post = print_otag(p, TAG_MROW, "");
1.8 kristaps 206: else
1.11 schwarze 207: print_otag(p, TAG_MROW, "");
1.5 kristaps 208: }
209:
1.8 kristaps 210: eqn_box(p, bp->first);
211:
212: out:
213: if (NULL != bp->bottom) {
1.11 schwarze 214: t = print_otag(p, TAG_MO, "");
1.8 kristaps 215: print_text(p, bp->bottom);
216: print_tagq(p, t);
1.9 schwarze 217: }
1.8 kristaps 218: if (NULL != bp->top) {
1.11 schwarze 219: t = print_otag(p, TAG_MO, "");
1.8 kristaps 220: print_text(p, bp->top);
221: print_tagq(p, t);
222: }
223:
224: if (NULL != post)
1.5 kristaps 225: print_tagq(p, post);
226:
1.8 kristaps 227: eqn_box(p, bp->next);
228: }
229:
230: void
1.16 schwarze 231: print_eqn(struct html *p, const struct eqn_box *bp)
1.8 kristaps 232: {
233: struct tag *t;
1.17 schwarze 234:
235: if (bp->first == NULL)
236: return;
1.8 kristaps 237:
1.11 schwarze 238: t = print_otag(p, TAG_MATH, "c", "eqn");
1.8 kristaps 239:
240: p->flags |= HTML_NONOSPACE;
1.16 schwarze 241: eqn_box(p, bp);
1.8 kristaps 242: p->flags &= ~HTML_NONOSPACE;
1.5 kristaps 243:
1.8 kristaps 244: print_tagq(p, t);
1.1 kristaps 245: }
CVSweb