version 1.10, 2014/10/12 19:31:41 |
version 1.19, 2019/03/17 18:21:45 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> |
|
* Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
|
|
#include <assert.h> |
#include <assert.h> |
|
#include <ctype.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
#include "mandoc.h" |
#include "mandoc.h" |
|
#include "roff.h" |
|
#include "eqn.h" |
#include "out.h" |
#include "out.h" |
#include "html.h" |
#include "html.h" |
|
|
|
|
eqn_box(struct html *p, const struct eqn_box *bp) |
eqn_box(struct html *p, const struct eqn_box *bp) |
{ |
{ |
struct tag *post, *row, *cell, *t; |
struct tag *post, *row, *cell, *t; |
struct htmlpair tag[2]; |
|
const struct eqn_box *child, *parent; |
const struct eqn_box *child, *parent; |
|
const char *cp; |
size_t i, j, rows; |
size_t i, j, rows; |
|
enum htmltag tag; |
|
enum eqn_fontt font; |
|
|
if (NULL == bp) |
if (NULL == bp) |
return; |
return; |
Line 47 eqn_box(struct html *p, const struct eqn_box *bp) |
|
Line 53 eqn_box(struct html *p, const struct eqn_box *bp) |
|
if (EQN_MATRIX == bp->type) { |
if (EQN_MATRIX == bp->type) { |
if (NULL == bp->first) |
if (NULL == bp->first) |
goto out; |
goto out; |
if (EQN_LIST != bp->first->type) { |
if (bp->first->type != EQN_LIST || |
|
bp->first->expectargs == 1) { |
eqn_box(p, bp->first); |
eqn_box(p, bp->first); |
goto out; |
goto out; |
} |
} |
Line 59 eqn_box(struct html *p, const struct eqn_box *bp) |
|
Line 66 eqn_box(struct html *p, const struct eqn_box *bp) |
|
for (rows = 0; NULL != child; rows++) |
for (rows = 0; NULL != child; rows++) |
child = child->next; |
child = child->next; |
/* Print row-by-row. */ |
/* Print row-by-row. */ |
post = print_otag(p, TAG_MTABLE, 0, NULL); |
post = print_otag(p, TAG_MTABLE, ""); |
for (i = 0; i < rows; i++) { |
for (i = 0; i < rows; i++) { |
parent = bp->first->first; |
parent = bp->first->first; |
row = print_otag(p, TAG_MTR, 0, NULL); |
row = print_otag(p, TAG_MTR, ""); |
while (NULL != parent) { |
while (NULL != parent) { |
child = parent->first; |
child = parent->first; |
for (j = 0; j < i; j++) { |
for (j = 0; j < i; j++) { |
Line 70 eqn_box(struct html *p, const struct eqn_box *bp) |
|
Line 77 eqn_box(struct html *p, const struct eqn_box *bp) |
|
break; |
break; |
child = child->next; |
child = child->next; |
} |
} |
cell = print_otag |
cell = print_otag(p, TAG_MTD, ""); |
(p, TAG_MTD, 0, NULL); |
|
/* |
/* |
* If we have no data for this |
* If we have no data for this |
* particular cell, then print a |
* particular cell, then print a |
Line 88 eqn_box(struct html *p, const struct eqn_box *bp) |
|
Line 94 eqn_box(struct html *p, const struct eqn_box *bp) |
|
} |
} |
|
|
switch (bp->pos) { |
switch (bp->pos) { |
case (EQNPOS_TO): |
case EQNPOS_TO: |
post = print_otag(p, TAG_MOVER, 0, NULL); |
post = print_otag(p, TAG_MOVER, ""); |
break; |
break; |
case (EQNPOS_SUP): |
case EQNPOS_SUP: |
post = print_otag(p, TAG_MSUP, 0, NULL); |
post = print_otag(p, TAG_MSUP, ""); |
break; |
break; |
case (EQNPOS_FROM): |
case EQNPOS_FROM: |
post = print_otag(p, TAG_MUNDER, 0, NULL); |
post = print_otag(p, TAG_MUNDER, ""); |
break; |
break; |
case (EQNPOS_SUB): |
case EQNPOS_SUB: |
post = print_otag(p, TAG_MSUB, 0, NULL); |
post = print_otag(p, TAG_MSUB, ""); |
break; |
break; |
case (EQNPOS_OVER): |
case EQNPOS_OVER: |
post = print_otag(p, TAG_MFRAC, 0, NULL); |
post = print_otag(p, TAG_MFRAC, ""); |
break; |
break; |
case (EQNPOS_FROMTO): |
case EQNPOS_FROMTO: |
post = print_otag(p, TAG_MUNDEROVER, 0, NULL); |
post = print_otag(p, TAG_MUNDEROVER, ""); |
break; |
break; |
case (EQNPOS_SUBSUP): |
case EQNPOS_SUBSUP: |
post = print_otag(p, TAG_MSUBSUP, 0, NULL); |
post = print_otag(p, TAG_MSUBSUP, ""); |
break; |
break; |
case (EQNPOS_SQRT): |
case EQNPOS_SQRT: |
post = print_otag(p, TAG_MSQRT, 0, NULL); |
post = print_otag(p, TAG_MSQRT, ""); |
break; |
break; |
default: |
default: |
break; |
break; |
Line 119 eqn_box(struct html *p, const struct eqn_box *bp) |
|
Line 125 eqn_box(struct html *p, const struct eqn_box *bp) |
|
if (bp->top || bp->bottom) { |
if (bp->top || bp->bottom) { |
assert(NULL == post); |
assert(NULL == post); |
if (bp->top && NULL == bp->bottom) |
if (bp->top && NULL == bp->bottom) |
post = print_otag(p, TAG_MOVER, 0, NULL); |
post = print_otag(p, TAG_MOVER, ""); |
else if (bp->top && bp->bottom) |
else if (bp->top && bp->bottom) |
post = print_otag(p, TAG_MUNDEROVER, 0, NULL); |
post = print_otag(p, TAG_MUNDEROVER, ""); |
else if (bp->bottom) |
else if (bp->bottom) |
post = print_otag(p, TAG_MUNDER, 0, NULL); |
post = print_otag(p, TAG_MUNDER, ""); |
} |
} |
|
|
if (EQN_PILE == bp->type) { |
if (EQN_PILE == bp->type) { |
assert(NULL == post); |
assert(NULL == post); |
if (bp->first != NULL && bp->first->type == EQN_LIST) |
if (bp->first != NULL && |
post = print_otag(p, TAG_MTABLE, 0, NULL); |
bp->first->type == EQN_LIST && |
} else if (bp->type == EQN_LIST && |
bp->first->expectargs > 1) |
|
post = print_otag(p, TAG_MTABLE, ""); |
|
} else if (bp->type == EQN_LIST && bp->expectargs > 1 && |
bp->parent && bp->parent->type == EQN_PILE) { |
bp->parent && bp->parent->type == EQN_PILE) { |
assert(NULL == post); |
assert(NULL == post); |
post = print_otag(p, TAG_MTR, 0, NULL); |
post = print_otag(p, TAG_MTR, ""); |
print_otag(p, TAG_MTD, 0, NULL); |
print_otag(p, TAG_MTD, ""); |
} |
} |
|
|
if (NULL != bp->text) { |
if (bp->text != NULL) { |
assert(NULL == post); |
assert(post == NULL); |
post = print_otag(p, TAG_MI, 0, NULL); |
tag = TAG_MI; |
|
cp = bp->text; |
|
if (isdigit((unsigned char)cp[0]) || |
|
(cp[0] == '.' && isdigit((unsigned char)cp[1]))) { |
|
tag = TAG_MN; |
|
while (*++cp != '\0') { |
|
if (*cp != '.' && |
|
isdigit((unsigned char)*cp) == 0) { |
|
tag = TAG_MI; |
|
break; |
|
} |
|
} |
|
} else if (*cp != '\0' && isalpha((unsigned char)*cp) == 0) { |
|
tag = TAG_MO; |
|
while (*cp != '\0') { |
|
if (cp[0] == '\\' && cp[1] != '\0') { |
|
cp++; |
|
mandoc_escape(&cp, NULL, NULL); |
|
} else if (isalnum((unsigned char)*cp)) { |
|
tag = TAG_MI; |
|
break; |
|
} else |
|
cp++; |
|
} |
|
} |
|
font = bp->font; |
|
if (bp->text[0] != '\0' && |
|
(((tag == TAG_MN || tag == TAG_MO) && |
|
font == EQNFONT_ROMAN) || |
|
(tag == TAG_MI && font == (bp->text[1] == '\0' ? |
|
EQNFONT_ITALIC : EQNFONT_ROMAN)))) |
|
font = EQNFONT_NONE; |
|
switch (font) { |
|
case EQNFONT_NONE: |
|
post = print_otag(p, tag, ""); |
|
break; |
|
case EQNFONT_ROMAN: |
|
post = print_otag(p, tag, "?", "fontstyle", "normal"); |
|
break; |
|
case EQNFONT_BOLD: |
|
case EQNFONT_FAT: |
|
post = print_otag(p, tag, "?", "fontweight", "bold"); |
|
break; |
|
case EQNFONT_ITALIC: |
|
post = print_otag(p, tag, "?", "fontstyle", "italic"); |
|
break; |
|
default: |
|
abort(); |
|
} |
print_text(p, bp->text); |
print_text(p, bp->text); |
} else if (NULL == post) { |
} else if (NULL == post) { |
if (NULL != bp->left || NULL != bp->right) { |
if (NULL != bp->left || NULL != bp->right) |
PAIR_INIT(&tag[0], ATTR_OPEN, |
post = print_otag(p, TAG_MFENCED, "??", |
NULL == bp->left ? "" : bp->left); |
"open", bp->left == NULL ? "" : bp->left, |
PAIR_INIT(&tag[1], ATTR_CLOSE, |
"close", bp->right == NULL ? "" : bp->right); |
NULL == bp->right ? "" : bp->right); |
|
post = print_otag(p, TAG_MFENCED, 2, tag); |
|
} |
|
if (NULL == post) |
if (NULL == post) |
post = print_otag(p, TAG_MROW, 0, NULL); |
post = print_otag(p, TAG_MROW, ""); |
else |
else |
print_otag(p, TAG_MROW, 0, NULL); |
print_otag(p, TAG_MROW, ""); |
} |
} |
|
|
eqn_box(p, bp->first); |
eqn_box(p, bp->first); |
|
|
out: |
out: |
if (NULL != bp->bottom) { |
if (NULL != bp->bottom) { |
t = print_otag(p, TAG_MO, 0, NULL); |
t = print_otag(p, TAG_MO, ""); |
print_text(p, bp->bottom); |
print_text(p, bp->bottom); |
print_tagq(p, t); |
print_tagq(p, t); |
} |
} |
if (NULL != bp->top) { |
if (NULL != bp->top) { |
t = print_otag(p, TAG_MO, 0, NULL); |
t = print_otag(p, TAG_MO, ""); |
print_text(p, bp->top); |
print_text(p, bp->top); |
print_tagq(p, t); |
print_tagq(p, t); |
} |
} |
|
|
} |
} |
|
|
void |
void |
print_eqn(struct html *p, const struct eqn *ep) |
print_eqn(struct html *p, const struct eqn_box *bp) |
{ |
{ |
struct htmlpair tag; |
|
struct tag *t; |
struct tag *t; |
|
|
PAIR_CLASS_INIT(&tag, "eqn"); |
if (bp->first == NULL) |
t = print_otag(p, TAG_MATH, 1, &tag); |
return; |
|
|
|
t = print_otag(p, TAG_MATH, "c", "eqn"); |
|
|
p->flags |= HTML_NONOSPACE; |
p->flags |= HTML_NONOSPACE; |
eqn_box(p, ep->root); |
eqn_box(p, bp); |
p->flags &= ~HTML_NONOSPACE; |
p->flags &= ~HTML_NONOSPACE; |
|
|
print_tagq(p, t); |
print_tagq(p, t); |