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