version 1.194, 2017/01/17 01:47:51 |
version 1.195, 2017/01/17 15:32:43 |
Line 106 static const char *const roffscales[SCALE_MAX] = { |
|
Line 106 static const char *const roffscales[SCALE_MAX] = { |
|
}; |
}; |
|
|
static void a2width(const char *, struct roffsu *); |
static void a2width(const char *, struct roffsu *); |
static void bufncat(struct html *, const char *, size_t); |
|
static void print_ctag(struct html *, struct tag *); |
static void print_ctag(struct html *, struct tag *); |
static int print_escape(char); |
static int print_escape(char); |
static int print_encode(struct html *, const char *, int); |
static int print_encode(struct html *, const char *, const char *, int); |
|
static void print_href(struct html *, const char *, const char *, int); |
static void print_metaf(struct html *, enum mandoc_esc); |
static void print_metaf(struct html *, enum mandoc_esc); |
static void print_attr(struct html *, const char *, const char *); |
|
|
|
|
|
void * |
void * |
Line 304 print_escape(char c) |
|
Line 303 print_escape(char c) |
|
} |
} |
|
|
static int |
static int |
print_encode(struct html *h, const char *p, int norecurse) |
print_encode(struct html *h, const char *p, const char *pend, int norecurse) |
{ |
{ |
size_t sz; |
size_t sz; |
int c, len, nospace; |
int c, len, nospace; |
Line 313 print_encode(struct html *h, const char *p, int norecu |
|
Line 312 print_encode(struct html *h, const char *p, int norecu |
|
static const char rejs[9] = { '\\', '<', '>', '&', '"', |
static const char rejs[9] = { '\\', '<', '>', '&', '"', |
ASCII_NBRSP, ASCII_HYPH, ASCII_BREAK, '\0' }; |
ASCII_NBRSP, ASCII_HYPH, ASCII_BREAK, '\0' }; |
|
|
|
if (pend == NULL) |
|
pend = strchr(p, '\0'); |
|
|
nospace = 0; |
nospace = 0; |
|
|
while ('\0' != *p) { |
while (p < pend) { |
if (HTML_SKIPCHAR & h->flags && '\\' != *p) { |
if (HTML_SKIPCHAR & h->flags && '\\' != *p) { |
h->flags &= ~HTML_SKIPCHAR; |
h->flags &= ~HTML_SKIPCHAR; |
p++; |
p++; |
Line 323 print_encode(struct html *h, const char *p, int norecu |
|
Line 325 print_encode(struct html *h, const char *p, int norecu |
|
} |
} |
|
|
sz = strcspn(p, rejs); |
sz = strcspn(p, rejs); |
|
if (p + sz > pend) |
|
sz = pend - p; |
|
|
fwrite(p, 1, sz, stdout); |
fwrite(p, 1, sz, stdout); |
p += (int)sz; |
p += (int)sz; |
|
|
if ('\0' == *p) |
if (p >= pend) |
break; |
break; |
|
|
if (print_escape(*p++)) |
if (print_escape(*p++)) |
Line 399 print_encode(struct html *h, const char *p, int norecu |
|
Line 403 print_encode(struct html *h, const char *p, int norecu |
|
} |
} |
|
|
static void |
static void |
print_attr(struct html *h, const char *key, const char *val) |
print_href(struct html *h, const char *name, const char *sec, int man) |
{ |
{ |
printf(" %s=\"", key); |
const char *p, *pp; |
(void)print_encode(h, val, 1); |
|
putchar('\"'); |
pp = man ? h->base_man : h->base_includes; |
|
while ((p = strchr(pp, '%')) != NULL) { |
|
print_encode(h, pp, p, 1); |
|
if (man && p[1] == 'S') { |
|
if (sec == NULL) |
|
putchar('1'); |
|
else |
|
print_encode(h, sec, NULL, 1); |
|
} else if ((man && p[1] == 'N') || |
|
(man == 0 && p[1] == 'I')) |
|
print_encode(h, name, NULL, 1); |
|
else |
|
print_encode(h, p, p + 2, 1); |
|
pp = p + 2; |
|
} |
|
if (*pp != '\0') |
|
print_encode(h, pp, NULL, 1); |
} |
} |
|
|
struct tag * |
struct tag * |
Line 412 print_otag(struct html *h, enum htmltag tag, const cha |
|
Line 432 print_otag(struct html *h, enum htmltag tag, const cha |
|
va_list ap; |
va_list ap; |
struct roffsu mysu, *su; |
struct roffsu mysu, *su; |
struct tag *t; |
struct tag *t; |
|
const char *attr; |
char *s; |
char *s; |
|
double v; |
int i, have_style; |
int i, have_style; |
|
|
/* Push this tags onto the stack of open scopes. */ |
/* Push this tags onto the stack of open scopes. */ |
Line 458 print_otag(struct html *h, enum htmltag tag, const cha |
|
Line 480 print_otag(struct html *h, enum htmltag tag, const cha |
|
s = va_arg(ap, char *); |
s = va_arg(ap, char *); |
switch (*fmt++) { |
switch (*fmt++) { |
case 'c': |
case 'c': |
print_attr(h, "class", s); |
attr = "class"; |
break; |
break; |
case 'h': |
case 'h': |
print_attr(h, "href", s); |
attr = "href"; |
break; |
break; |
case 'i': |
case 'i': |
print_attr(h, "id", s); |
attr = "id"; |
break; |
break; |
case '?': |
case '?': |
print_attr(h, s, va_arg(ap, char *)); |
attr = s; |
|
s = va_arg(ap, char *); |
break; |
break; |
default: |
default: |
abort(); |
abort(); |
} |
} |
|
printf(" %s=\"", attr); |
|
switch (*fmt) { |
|
case 'M': |
|
print_href(h, s, va_arg(ap, char *), 1); |
|
fmt++; |
|
break; |
|
case 'I': |
|
print_href(h, s, NULL, 0); |
|
fmt++; |
|
break; |
|
case 'R': |
|
putchar('#'); |
|
fmt++; |
|
/* FALLTHROUGH */ |
|
default: |
|
print_encode(h, s, NULL, 1); |
|
break; |
|
} |
|
putchar('"'); |
} |
} |
|
|
/* Print out styles. */ |
/* Print out styles. */ |
Line 507 print_otag(struct html *h, enum htmltag tag, const cha |
|
Line 549 print_otag(struct html *h, enum htmltag tag, const cha |
|
|
|
/* Second letter: style name. */ |
/* Second letter: style name. */ |
|
|
bufinit(h); |
|
switch (*fmt++) { |
switch (*fmt++) { |
case 'b': |
case 'b': |
bufcat_su(h, "margin-bottom", su); |
attr = "margin-bottom"; |
break; |
break; |
case 'h': |
case 'h': |
bufcat_su(h, "height", su); |
attr = "height"; |
break; |
break; |
case 'i': |
case 'i': |
bufcat_su(h, "text-indent", su); |
attr = "text-indent"; |
break; |
break; |
case 'l': |
case 'l': |
bufcat_su(h, "margin-left", su); |
attr = "margin-left"; |
break; |
break; |
case 't': |
case 't': |
bufcat_su(h, "margin-top", su); |
attr = "margin-top"; |
break; |
break; |
case 'w': |
case 'w': |
bufcat_su(h, "width", su); |
attr = "width"; |
break; |
break; |
case 'W': |
case 'W': |
bufcat_su(h, "min-width", su); |
attr = "min-width"; |
break; |
break; |
case '?': |
case '?': |
bufcat_style(h, s, va_arg(ap, char *)); |
printf("%s: %s;", s, va_arg(ap, char *)); |
break; |
continue; |
default: |
default: |
abort(); |
abort(); |
} |
} |
printf("%s", h->buf); |
v = su->scale; |
|
if (su->unit == SCALE_MM && (v /= 100.0) == 0.0) |
|
v = 1.0; |
|
else if (su->unit == SCALE_BU) |
|
v /= 24.0; |
|
printf("%s: %.2f%s;", attr, v, roffscales[su->unit]); |
} |
} |
if (have_style) |
if (have_style) |
putchar('"'); |
putchar('"'); |
Line 619 print_text(struct html *h, const char *word) |
|
Line 665 print_text(struct html *h, const char *word) |
|
} |
} |
|
|
assert(word); |
assert(word); |
if ( ! print_encode(h, word, 0)) { |
if ( ! print_encode(h, word, NULL, 0)) { |
if ( ! (h->flags & HTML_NONOSPACE)) |
if ( ! (h->flags & HTML_NONOSPACE)) |
h->flags &= ~HTML_NOSPACE; |
h->flags &= ~HTML_NOSPACE; |
h->flags &= ~HTML_NONEWLINE; |
h->flags &= ~HTML_NONEWLINE; |
Line 681 a2width(const char *p, struct roffsu *su) |
|
Line 727 a2width(const char *p, struct roffsu *su) |
|
su->scale = html_strlen(p); |
su->scale = html_strlen(p); |
} else if (su->scale < 0.0) |
} else if (su->scale < 0.0) |
su->scale = 0.0; |
su->scale = 0.0; |
} |
|
|
|
void |
|
bufinit(struct html *h) |
|
{ |
|
|
|
h->buf[0] = '\0'; |
|
h->buflen = 0; |
|
} |
|
|
|
void |
|
bufcat_style(struct html *h, const char *key, const char *val) |
|
{ |
|
|
|
bufcat(h, key); |
|
bufcat(h, ":"); |
|
bufcat(h, val); |
|
bufcat(h, ";"); |
|
} |
|
|
|
void |
|
bufcat(struct html *h, const char *p) |
|
{ |
|
|
|
/* |
|
* XXX This is broken and not easy to fix. |
|
* When using the -Oincludes option, buffmt_includes() |
|
* may pass in strings overrunning BUFSIZ, causing a crash. |
|
*/ |
|
|
|
h->buflen = strlcat(h->buf, p, BUFSIZ); |
|
assert(h->buflen < BUFSIZ); |
|
} |
|
|
|
void |
|
bufcat_fmt(struct html *h, const char *fmt, ...) |
|
{ |
|
va_list ap; |
|
|
|
va_start(ap, fmt); |
|
(void)vsnprintf(h->buf + (int)h->buflen, |
|
BUFSIZ - h->buflen - 1, fmt, ap); |
|
va_end(ap); |
|
h->buflen = strlen(h->buf); |
|
} |
|
|
|
static void |
|
bufncat(struct html *h, const char *p, size_t sz) |
|
{ |
|
|
|
assert(h->buflen + sz + 1 < BUFSIZ); |
|
strncat(h->buf, p, sz); |
|
h->buflen += sz; |
|
} |
|
|
|
void |
|
buffmt_includes(struct html *h, const char *name) |
|
{ |
|
const char *p, *pp; |
|
|
|
pp = h->base_includes; |
|
|
|
bufinit(h); |
|
while (NULL != (p = strchr(pp, '%'))) { |
|
bufncat(h, pp, (size_t)(p - pp)); |
|
switch (*(p + 1)) { |
|
case 'I': |
|
bufcat(h, name); |
|
break; |
|
default: |
|
bufncat(h, p, 2); |
|
break; |
|
} |
|
pp = p + 2; |
|
} |
|
if (pp) |
|
bufcat(h, pp); |
|
} |
|
|
|
void |
|
buffmt_man(struct html *h, const char *name, const char *sec) |
|
{ |
|
const char *p, *pp; |
|
|
|
pp = h->base_man; |
|
|
|
bufinit(h); |
|
while (NULL != (p = strchr(pp, '%'))) { |
|
bufncat(h, pp, (size_t)(p - pp)); |
|
switch (*(p + 1)) { |
|
case 'S': |
|
bufcat(h, sec ? sec : "1"); |
|
break; |
|
case 'N': |
|
bufcat_fmt(h, "%s", name); |
|
break; |
|
default: |
|
bufncat(h, p, 2); |
|
break; |
|
} |
|
pp = p + 2; |
|
} |
|
if (pp) |
|
bufcat(h, pp); |
|
} |
|
|
|
void |
|
bufcat_su(struct html *h, const char *p, const struct roffsu *su) |
|
{ |
|
double v; |
|
|
|
v = su->scale; |
|
if (SCALE_MM == su->unit && 0.0 == (v /= 100.0)) |
|
v = 1.0; |
|
else if (SCALE_BU == su->unit) |
|
v /= 24.0; |
|
|
|
bufcat_fmt(h, "%s: %.2f%s;", p, v, roffscales[su->unit]); |
|
} |
|
|
|
void |
|
bufcat_id(struct html *h, const char *src) |
|
{ |
|
|
|
/* Cf. <http://www.w3.org/TR/html5/dom.html#the-id-attribute>. */ |
|
|
|
for (; '\0' != *src; src++) |
|
bufncat(h, *src == ' ' ? "_" : src, 1); |
|
} |
} |