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