Annotation of src/usr.bin/mandoc/eqn_html.c, Revision 1.8
1.8 ! schwarze 1: /* $OpenBSD: eqn_html.c,v 1.7 2017/01/17 01:47:46 schwarze Exp $ */
1.1 schwarze 2: /*
1.3 schwarze 3: * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
1.7 schwarze 4: * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
1.1 schwarze 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: */
1.5 schwarze 18: #include <sys/types.h>
19:
1.1 schwarze 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 "html.h"
28:
1.5 schwarze 29: static void
30: eqn_box(struct html *p, const struct eqn_box *bp)
1.1 schwarze 31: {
1.5 schwarze 32: struct tag *post, *row, *cell, *t;
33: const struct eqn_box *child, *parent;
34: size_t i, j, rows;
1.3 schwarze 35:
36: if (NULL == bp)
1.5 schwarze 37: return;
1.3 schwarze 38:
1.5 schwarze 39: post = NULL;
1.3 schwarze 40:
41: /*
1.5 schwarze 42: * Special handling for a matrix, which is presented to us in
43: * column order, but must be printed in row-order.
1.3 schwarze 44: */
1.5 schwarze 45: if (EQN_MATRIX == bp->type) {
46: if (NULL == bp->first)
47: goto out;
1.6 schwarze 48: if (EQN_LIST != bp->first->type) {
49: eqn_box(p, bp->first);
50: goto out;
51: }
1.5 schwarze 52: if (NULL == (parent = bp->first->first))
53: goto out;
54: /* Estimate the number of rows, first. */
55: if (NULL == (child = parent->first))
56: goto out;
57: for (rows = 0; NULL != child; rows++)
58: child = child->next;
59: /* Print row-by-row. */
1.7 schwarze 60: post = print_otag(p, TAG_MTABLE, "");
1.5 schwarze 61: for (i = 0; i < rows; i++) {
62: parent = bp->first->first;
1.7 schwarze 63: row = print_otag(p, TAG_MTR, "");
1.5 schwarze 64: while (NULL != parent) {
65: child = parent->first;
66: for (j = 0; j < i; j++) {
67: if (NULL == child)
68: break;
69: child = child->next;
70: }
1.7 schwarze 71: cell = print_otag(p, TAG_MTD, "");
1.5 schwarze 72: /*
73: * If we have no data for this
74: * particular cell, then print a
75: * placeholder and continue--don't puke.
76: */
77: if (NULL != child)
78: eqn_box(p, child->first);
79: print_tagq(p, cell);
80: parent = parent->next;
81: }
82: print_tagq(p, row);
83: }
84: goto out;
1.4 schwarze 85: }
1.3 schwarze 86:
87: switch (bp->pos) {
1.8 ! schwarze 88: case EQNPOS_TO:
1.7 schwarze 89: post = print_otag(p, TAG_MOVER, "");
1.4 schwarze 90: break;
1.8 ! schwarze 91: case EQNPOS_SUP:
1.7 schwarze 92: post = print_otag(p, TAG_MSUP, "");
1.3 schwarze 93: break;
1.8 ! schwarze 94: case EQNPOS_FROM:
1.7 schwarze 95: post = print_otag(p, TAG_MUNDER, "");
1.4 schwarze 96: break;
1.8 ! schwarze 97: case EQNPOS_SUB:
1.7 schwarze 98: post = print_otag(p, TAG_MSUB, "");
1.3 schwarze 99: break;
1.8 ! schwarze 100: case EQNPOS_OVER:
1.7 schwarze 101: post = print_otag(p, TAG_MFRAC, "");
1.3 schwarze 102: break;
1.8 ! schwarze 103: case EQNPOS_FROMTO:
1.7 schwarze 104: post = print_otag(p, TAG_MUNDEROVER, "");
1.4 schwarze 105: break;
1.8 ! schwarze 106: case EQNPOS_SUBSUP:
1.7 schwarze 107: post = print_otag(p, TAG_MSUBSUP, "");
1.5 schwarze 108: break;
1.8 ! schwarze 109: case EQNPOS_SQRT:
1.7 schwarze 110: post = print_otag(p, TAG_MSQRT, "");
1.3 schwarze 111: break;
112: default:
113: break;
114: }
115:
1.5 schwarze 116: if (bp->top || bp->bottom) {
117: assert(NULL == post);
118: if (bp->top && NULL == bp->bottom)
1.7 schwarze 119: post = print_otag(p, TAG_MOVER, "");
1.5 schwarze 120: else if (bp->top && bp->bottom)
1.7 schwarze 121: post = print_otag(p, TAG_MUNDEROVER, "");
1.5 schwarze 122: else if (bp->bottom)
1.7 schwarze 123: post = print_otag(p, TAG_MUNDER, "");
1.5 schwarze 124: }
125:
126: if (EQN_PILE == bp->type) {
127: assert(NULL == post);
1.6 schwarze 128: if (bp->first != NULL && bp->first->type == EQN_LIST)
1.7 schwarze 129: post = print_otag(p, TAG_MTABLE, "");
1.6 schwarze 130: } else if (bp->type == EQN_LIST &&
131: bp->parent && bp->parent->type == EQN_PILE) {
1.5 schwarze 132: assert(NULL == post);
1.7 schwarze 133: post = print_otag(p, TAG_MTR, "");
134: print_otag(p, TAG_MTD, "");
1.5 schwarze 135: }
1.3 schwarze 136:
137: if (NULL != bp->text) {
1.5 schwarze 138: assert(NULL == post);
1.7 schwarze 139: post = print_otag(p, TAG_MI, "");
1.5 schwarze 140: print_text(p, bp->text);
141: } else if (NULL == post) {
1.7 schwarze 142: if (NULL != bp->left || NULL != bp->right)
143: post = print_otag(p, TAG_MFENCED, "??",
144: "open", bp->left == NULL ? "" : bp->left,
145: "close", bp->right == NULL ? "" : bp->right);
1.5 schwarze 146: if (NULL == post)
1.7 schwarze 147: post = print_otag(p, TAG_MROW, "");
1.5 schwarze 148: else
1.7 schwarze 149: print_otag(p, TAG_MROW, "");
1.3 schwarze 150: }
151:
1.5 schwarze 152: eqn_box(p, bp->first);
153:
154: out:
155: if (NULL != bp->bottom) {
1.7 schwarze 156: t = print_otag(p, TAG_MO, "");
1.5 schwarze 157: print_text(p, bp->bottom);
158: print_tagq(p, t);
159: }
160: if (NULL != bp->top) {
1.7 schwarze 161: t = print_otag(p, TAG_MO, "");
1.5 schwarze 162: print_text(p, bp->top);
163: print_tagq(p, t);
164: }
165:
166: if (NULL != post)
1.3 schwarze 167: print_tagq(p, post);
168:
1.5 schwarze 169: eqn_box(p, bp->next);
170: }
171:
172: void
173: print_eqn(struct html *p, const struct eqn *ep)
174: {
175: struct tag *t;
176:
1.7 schwarze 177: t = print_otag(p, TAG_MATH, "c", "eqn");
1.5 schwarze 178:
179: p->flags |= HTML_NONOSPACE;
180: eqn_box(p, ep->root);
181: p->flags &= ~HTML_NONOSPACE;
1.3 schwarze 182:
1.5 schwarze 183: print_tagq(p, t);
1.1 schwarze 184: }