xref: /openbsd/usr.bin/mandoc/eqn_html.c (revision 229cc7fd)
1*229cc7fdSschwarze /*	$OpenBSD: eqn_html.c,v 1.7 2017/01/17 01:47:46 schwarze Exp $ */
2f8618d99Sschwarze /*
3933d2e00Sschwarze  * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
4*229cc7fdSschwarze  * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
5f8618d99Sschwarze  *
6f8618d99Sschwarze  * Permission to use, copy, modify, and distribute this software for any
7f8618d99Sschwarze  * purpose with or without fee is hereby granted, provided that the above
8f8618d99Sschwarze  * copyright notice and this permission notice appear in all copies.
9f8618d99Sschwarze  *
10f8618d99Sschwarze  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11f8618d99Sschwarze  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12f8618d99Sschwarze  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13f8618d99Sschwarze  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14f8618d99Sschwarze  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15f8618d99Sschwarze  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16f8618d99Sschwarze  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17f8618d99Sschwarze  */
18f8617809Sschwarze #include <sys/types.h>
19f8617809Sschwarze 
20f8618d99Sschwarze #include <assert.h>
21f8618d99Sschwarze #include <stdio.h>
22f8618d99Sschwarze #include <stdlib.h>
23f8618d99Sschwarze #include <string.h>
24f8618d99Sschwarze 
25f8618d99Sschwarze #include "mandoc.h"
26f8618d99Sschwarze #include "out.h"
27f8618d99Sschwarze #include "html.h"
28f8618d99Sschwarze 
29f8617809Sschwarze static void
30f8617809Sschwarze eqn_box(struct html *p, const struct eqn_box *bp)
31f8618d99Sschwarze {
32f8617809Sschwarze 	struct tag	*post, *row, *cell, *t;
33f8617809Sschwarze 	const struct eqn_box *child, *parent;
34f8617809Sschwarze 	size_t		 i, j, rows;
35f8618d99Sschwarze 
36933d2e00Sschwarze 	if (NULL == bp)
37f8617809Sschwarze 		return;
38f8618d99Sschwarze 
39f8617809Sschwarze 	post = NULL;
40f8618d99Sschwarze 
41933d2e00Sschwarze 	/*
42f8617809Sschwarze 	 * Special handling for a matrix, which is presented to us in
43f8617809Sschwarze 	 * column order, but must be printed in row-order.
44933d2e00Sschwarze 	 */
45f8617809Sschwarze 	if (EQN_MATRIX == bp->type) {
46f8617809Sschwarze 		if (NULL == bp->first)
47f8617809Sschwarze 			goto out;
48a4dfe1bcSschwarze 		if (EQN_LIST != bp->first->type) {
49a4dfe1bcSschwarze 			eqn_box(p, bp->first);
50a4dfe1bcSschwarze 			goto out;
51a4dfe1bcSschwarze 		}
52f8617809Sschwarze 		if (NULL == (parent = bp->first->first))
53f8617809Sschwarze 			goto out;
54f8617809Sschwarze 		/* Estimate the number of rows, first. */
55f8617809Sschwarze 		if (NULL == (child = parent->first))
56f8617809Sschwarze 			goto out;
57f8617809Sschwarze 		for (rows = 0; NULL != child; rows++)
58f8617809Sschwarze 			child = child->next;
59f8617809Sschwarze 		/* Print row-by-row. */
60*229cc7fdSschwarze 		post = print_otag(p, TAG_MTABLE, "");
61f8617809Sschwarze 		for (i = 0; i < rows; i++) {
62f8617809Sschwarze 			parent = bp->first->first;
63*229cc7fdSschwarze 			row = print_otag(p, TAG_MTR, "");
64f8617809Sschwarze 			while (NULL != parent) {
65f8617809Sschwarze 				child = parent->first;
66f8617809Sschwarze 				for (j = 0; j < i; j++) {
67f8617809Sschwarze 					if (NULL == child)
68f8617809Sschwarze 						break;
69f8617809Sschwarze 					child = child->next;
70933d2e00Sschwarze 				}
71*229cc7fdSschwarze 				cell = print_otag(p, TAG_MTD, "");
72f8617809Sschwarze 				/*
73f8617809Sschwarze 				 * If we have no data for this
74f8617809Sschwarze 				 * particular cell, then print a
75f8617809Sschwarze 				 * placeholder and continue--don't puke.
76f8617809Sschwarze 				 */
77f8617809Sschwarze 				if (NULL != child)
78f8617809Sschwarze 					eqn_box(p, child->first);
79f8617809Sschwarze 				print_tagq(p, cell);
80f8617809Sschwarze 				parent = parent->next;
81f8617809Sschwarze 			}
82f8617809Sschwarze 			print_tagq(p, row);
83f8617809Sschwarze 		}
84f8617809Sschwarze 		goto out;
85a3108a0aSschwarze 	}
86933d2e00Sschwarze 
87933d2e00Sschwarze 	switch (bp->pos) {
88a3108a0aSschwarze 	case (EQNPOS_TO):
89*229cc7fdSschwarze 		post = print_otag(p, TAG_MOVER, "");
90a3108a0aSschwarze 		break;
91933d2e00Sschwarze 	case (EQNPOS_SUP):
92*229cc7fdSschwarze 		post = print_otag(p, TAG_MSUP, "");
93933d2e00Sschwarze 		break;
94933d2e00Sschwarze 	case (EQNPOS_FROM):
95*229cc7fdSschwarze 		post = print_otag(p, TAG_MUNDER, "");
96a3108a0aSschwarze 		break;
97933d2e00Sschwarze 	case (EQNPOS_SUB):
98*229cc7fdSschwarze 		post = print_otag(p, TAG_MSUB, "");
99933d2e00Sschwarze 		break;
100933d2e00Sschwarze 	case (EQNPOS_OVER):
101*229cc7fdSschwarze 		post = print_otag(p, TAG_MFRAC, "");
102933d2e00Sschwarze 		break;
103a3108a0aSschwarze 	case (EQNPOS_FROMTO):
104*229cc7fdSschwarze 		post = print_otag(p, TAG_MUNDEROVER, "");
105a3108a0aSschwarze 		break;
106933d2e00Sschwarze 	case (EQNPOS_SUBSUP):
107*229cc7fdSschwarze 		post = print_otag(p, TAG_MSUBSUP, "");
108f8617809Sschwarze 		break;
109f8617809Sschwarze 	case (EQNPOS_SQRT):
110*229cc7fdSschwarze 		post = print_otag(p, TAG_MSQRT, "");
111933d2e00Sschwarze 		break;
112933d2e00Sschwarze 	default:
113933d2e00Sschwarze 		break;
114933d2e00Sschwarze 	}
115933d2e00Sschwarze 
116f8617809Sschwarze 	if (bp->top || bp->bottom) {
117f8617809Sschwarze 		assert(NULL == post);
118f8617809Sschwarze 		if (bp->top && NULL == bp->bottom)
119*229cc7fdSschwarze 			post = print_otag(p, TAG_MOVER, "");
120f8617809Sschwarze 		else if (bp->top && bp->bottom)
121*229cc7fdSschwarze 			post = print_otag(p, TAG_MUNDEROVER, "");
122f8617809Sschwarze 		else if (bp->bottom)
123*229cc7fdSschwarze 			post = print_otag(p, TAG_MUNDER, "");
124f8617809Sschwarze 	}
125f8617809Sschwarze 
126f8617809Sschwarze 	if (EQN_PILE == bp->type) {
127f8617809Sschwarze 		assert(NULL == post);
128a4dfe1bcSschwarze 		if (bp->first != NULL && bp->first->type == EQN_LIST)
129*229cc7fdSschwarze 			post = print_otag(p, TAG_MTABLE, "");
130a4dfe1bcSschwarze 	} else if (bp->type == EQN_LIST &&
131a4dfe1bcSschwarze 	    bp->parent && bp->parent->type == EQN_PILE) {
132f8617809Sschwarze 		assert(NULL == post);
133*229cc7fdSschwarze 		post = print_otag(p, TAG_MTR, "");
134*229cc7fdSschwarze 		print_otag(p, TAG_MTD, "");
135f8617809Sschwarze 	}
136933d2e00Sschwarze 
137933d2e00Sschwarze 	if (NULL != bp->text) {
138f8617809Sschwarze 		assert(NULL == post);
139*229cc7fdSschwarze 		post = print_otag(p, TAG_MI, "");
140f8618d99Sschwarze 		print_text(p, bp->text);
141f8617809Sschwarze 	} else if (NULL == post) {
142*229cc7fdSschwarze 		if (NULL != bp->left || NULL != bp->right)
143*229cc7fdSschwarze 			post = print_otag(p, TAG_MFENCED, "??",
144*229cc7fdSschwarze 			    "open", bp->left == NULL ? "" : bp->left,
145*229cc7fdSschwarze 			    "close", bp->right == NULL ? "" : bp->right);
146f8617809Sschwarze 		if (NULL == post)
147*229cc7fdSschwarze 			post = print_otag(p, TAG_MROW, "");
148f8617809Sschwarze 		else
149*229cc7fdSschwarze 			print_otag(p, TAG_MROW, "");
150933d2e00Sschwarze 	}
151f8618d99Sschwarze 
152f8617809Sschwarze 	eqn_box(p, bp->first);
153f8617809Sschwarze 
154f8617809Sschwarze out:
155f8617809Sschwarze 	if (NULL != bp->bottom) {
156*229cc7fdSschwarze 		t = print_otag(p, TAG_MO, "");
157f8617809Sschwarze 		print_text(p, bp->bottom);
158f8617809Sschwarze 		print_tagq(p, t);
159f8617809Sschwarze 	}
160f8617809Sschwarze 	if (NULL != bp->top) {
161*229cc7fdSschwarze 		t = print_otag(p, TAG_MO, "");
162f8617809Sschwarze 		print_text(p, bp->top);
163f8617809Sschwarze 		print_tagq(p, t);
164f8617809Sschwarze 	}
165f8617809Sschwarze 
166f8617809Sschwarze 	if (NULL != post)
167933d2e00Sschwarze 		print_tagq(p, post);
168f8617809Sschwarze 
169f8617809Sschwarze 	eqn_box(p, bp->next);
170933d2e00Sschwarze }
171f8618d99Sschwarze 
172f8617809Sschwarze void
173f8617809Sschwarze print_eqn(struct html *p, const struct eqn *ep)
174f8617809Sschwarze {
175f8617809Sschwarze 	struct tag	*t;
176f8618d99Sschwarze 
177*229cc7fdSschwarze 	t = print_otag(p, TAG_MATH, "c", "eqn");
178f8617809Sschwarze 
179f8617809Sschwarze 	p->flags |= HTML_NONOSPACE;
180f8617809Sschwarze 	eqn_box(p, ep->root);
181f8617809Sschwarze 	p->flags &= ~HTML_NONOSPACE;
182f8617809Sschwarze 
183f8617809Sschwarze 	print_tagq(p, t);
184f8618d99Sschwarze }
185