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