GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mandoc/eqn_html.c Lines: 0 94 0.0 %
Date: 2016-12-06 Branches: 0 87 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: eqn_html.c,v 1.6 2014/10/12 19:10:56 schwarze Exp $ */
2
/*
3
 * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
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
 */
17
#include <sys/types.h>
18
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
28
static void
29
eqn_box(struct html *p, const struct eqn_box *bp)
30
{
31
	struct tag	*post, *row, *cell, *t;
32
	struct htmlpair	 tag[2];
33
	const struct eqn_box *child, *parent;
34
	size_t		 i, j, rows;
35
36
	if (NULL == bp)
37
		return;
38
39
	post = NULL;
40
41
	/*
42
	 * Special handling for a matrix, which is presented to us in
43
	 * column order, but must be printed in row-order.
44
	 */
45
	if (EQN_MATRIX == bp->type) {
46
		if (NULL == bp->first)
47
			goto out;
48
		if (EQN_LIST != bp->first->type) {
49
			eqn_box(p, bp->first);
50
			goto out;
51
		}
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;
86
	}
87
88
	switch (bp->pos) {
89
	case (EQNPOS_TO):
90
		post = print_otag(p, TAG_MOVER, 0, NULL);
91
		break;
92
	case (EQNPOS_SUP):
93
		post = print_otag(p, TAG_MSUP, 0, NULL);
94
		break;
95
	case (EQNPOS_FROM):
96
		post = print_otag(p, TAG_MUNDER, 0, NULL);
97
		break;
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;
104
	case (EQNPOS_FROMTO):
105
		post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
106
		break;
107
	case (EQNPOS_SUBSUP):
108
		post = print_otag(p, TAG_MSUBSUP, 0, NULL);
109
		break;
110
	case (EQNPOS_SQRT):
111
		post = print_otag(p, TAG_MSQRT, 0, NULL);
112
		break;
113
	default:
114
		break;
115
	}
116
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);
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) {
133
		assert(NULL == post);
134
		post = print_otag(p, TAG_MTR, 0, NULL);
135
		print_otag(p, TAG_MTD, 0, NULL);
136
	}
137
138
	if (NULL != bp->text) {
139
		assert(NULL == post);
140
		post = print_otag(p, TAG_MI, 0, NULL);
141
		print_text(p, bp->text);
142
	} else if (NULL == post) {
143
		if (NULL != bp->left || NULL != bp->right) {
144
			PAIR_INIT(&tag[0], ATTR_OPEN,
145
			    NULL == bp->left ? "" : bp->left);
146
			PAIR_INIT(&tag[1], ATTR_CLOSE,
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
153
			print_otag(p, TAG_MROW, 0, NULL);
154
	}
155
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)
171
		print_tagq(p, post);
172
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;
188
189
	print_tagq(p, t);
190
}