Annotation of src/usr.bin/mandoc/eqn_html.c, Revision 1.6
1.6 ! schwarze 1: /* $OpenBSD: eqn_html.c,v 1.5 2014/10/10 15:25:06 schwarze Exp $ */
1.1 schwarze 2: /*
1.3 schwarze 3: * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
1.1 schwarze 4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
1.5 schwarze 17: #include <sys/types.h>
18:
1.1 schwarze 19: #include <assert.h>
20: #include <stdio.h>
21: #include <stdlib.h>
22: #include <string.h>
23:
24: #include "mandoc.h"
25: #include "out.h"
26: #include "html.h"
27:
1.5 schwarze 28: static void
29: eqn_box(struct html *p, const struct eqn_box *bp)
1.1 schwarze 30: {
1.5 schwarze 31: struct tag *post, *row, *cell, *t;
1.3 schwarze 32: struct htmlpair tag[2];
1.5 schwarze 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. */
60: post = print_otag(p, TAG_MTABLE, 0, NULL);
61: for (i = 0; i < rows; i++) {
62: parent = bp->first->first;
63: row = print_otag(p, TAG_MTR, 0, NULL);
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: }
71: cell = print_otag
72: (p, TAG_MTD, 0, NULL);
73: /*
74: * If we have no data for this
75: * particular cell, then print a
76: * placeholder and continue--don't puke.
77: */
78: if (NULL != child)
79: eqn_box(p, child->first);
80: print_tagq(p, cell);
81: parent = parent->next;
82: }
83: print_tagq(p, row);
84: }
85: goto out;
1.4 schwarze 86: }
1.3 schwarze 87:
88: switch (bp->pos) {
1.4 schwarze 89: case (EQNPOS_TO):
90: post = print_otag(p, TAG_MOVER, 0, NULL);
91: break;
1.3 schwarze 92: case (EQNPOS_SUP):
93: post = print_otag(p, TAG_MSUP, 0, NULL);
94: break;
95: case (EQNPOS_FROM):
1.4 schwarze 96: post = print_otag(p, TAG_MUNDER, 0, NULL);
97: break;
1.3 schwarze 98: case (EQNPOS_SUB):
99: post = print_otag(p, TAG_MSUB, 0, NULL);
100: break;
101: case (EQNPOS_OVER):
102: post = print_otag(p, TAG_MFRAC, 0, NULL);
103: break;
1.4 schwarze 104: case (EQNPOS_FROMTO):
105: post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
106: break;
1.3 schwarze 107: case (EQNPOS_SUBSUP):
108: post = print_otag(p, TAG_MSUBSUP, 0, NULL);
1.5 schwarze 109: break;
110: case (EQNPOS_SQRT):
111: post = print_otag(p, TAG_MSQRT, 0, NULL);
1.3 schwarze 112: break;
113: default:
114: break;
115: }
116:
1.5 schwarze 117: if (bp->top || bp->bottom) {
118: assert(NULL == post);
119: if (bp->top && NULL == bp->bottom)
120: post = print_otag(p, TAG_MOVER, 0, NULL);
121: else if (bp->top && bp->bottom)
122: post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
123: else if (bp->bottom)
124: post = print_otag(p, TAG_MUNDER, 0, NULL);
125: }
126:
127: if (EQN_PILE == bp->type) {
128: assert(NULL == post);
1.6 ! schwarze 129: if (bp->first != NULL && bp->first->type == EQN_LIST)
! 130: post = print_otag(p, TAG_MTABLE, 0, NULL);
! 131: } else if (bp->type == EQN_LIST &&
! 132: bp->parent && bp->parent->type == EQN_PILE) {
1.5 schwarze 133: assert(NULL == post);
134: post = print_otag(p, TAG_MTR, 0, NULL);
135: print_otag(p, TAG_MTD, 0, NULL);
136: }
1.3 schwarze 137:
138: if (NULL != bp->text) {
1.5 schwarze 139: assert(NULL == post);
140: post = print_otag(p, TAG_MI, 0, NULL);
141: print_text(p, bp->text);
142: } else if (NULL == post) {
1.3 schwarze 143: if (NULL != bp->left || NULL != bp->right) {
144: PAIR_INIT(&tag[0], ATTR_OPEN,
1.5 schwarze 145: NULL == bp->left ? "" : bp->left);
1.3 schwarze 146: PAIR_INIT(&tag[1], ATTR_CLOSE,
1.5 schwarze 147: NULL == bp->right ? "" : bp->right);
148: post = print_otag(p, TAG_MFENCED, 2, tag);
149: }
150: if (NULL == post)
151: post = print_otag(p, TAG_MROW, 0, NULL);
152: else
1.3 schwarze 153: print_otag(p, TAG_MROW, 0, NULL);
154: }
155:
1.5 schwarze 156: eqn_box(p, bp->first);
157:
158: out:
159: if (NULL != bp->bottom) {
160: t = print_otag(p, TAG_MO, 0, NULL);
161: print_text(p, bp->bottom);
162: print_tagq(p, t);
163: }
164: if (NULL != bp->top) {
165: t = print_otag(p, TAG_MO, 0, NULL);
166: print_text(p, bp->top);
167: print_tagq(p, t);
168: }
169:
170: if (NULL != post)
1.3 schwarze 171: print_tagq(p, post);
172:
1.5 schwarze 173: eqn_box(p, bp->next);
174: }
175:
176: void
177: print_eqn(struct html *p, const struct eqn *ep)
178: {
179: struct htmlpair tag;
180: struct tag *t;
181:
182: PAIR_CLASS_INIT(&tag, "eqn");
183: t = print_otag(p, TAG_MATH, 1, &tag);
184:
185: p->flags |= HTML_NONOSPACE;
186: eqn_box(p, ep->root);
187: p->flags &= ~HTML_NONOSPACE;
1.3 schwarze 188:
1.5 schwarze 189: print_tagq(p, t);
1.1 schwarze 190: }