version 1.258, 2019/09/01 15:12:19 |
version 1.264, 2020/03/13 15:32:28 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
|
* Copyright (c) 2011-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org> |
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2011-2015, 2017-2019 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 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
* |
|
* Common functions for mandoc(1) HTML formatters. |
|
* For use by individual formatters and by the main program. |
*/ |
*/ |
#include "config.h" |
#include "config.h" |
|
|
Line 88 static const struct htmldata htmltags[TAG_MAX] = { |
|
Line 91 static const struct htmldata htmltags[TAG_MAX] = { |
|
{"span", HTML_INPHRASE | HTML_TOPHRASE}, |
{"span", HTML_INPHRASE | HTML_TOPHRASE}, |
{"var", HTML_INPHRASE | HTML_TOPHRASE}, |
{"var", HTML_INPHRASE | HTML_TOPHRASE}, |
{"br", HTML_INPHRASE | HTML_NOSTACK | HTML_NLALL}, |
{"br", HTML_INPHRASE | HTML_NOSTACK | HTML_NLALL}, |
|
{"mark", HTML_INPHRASE }, |
{"math", HTML_INPHRASE | HTML_NLALL | HTML_INDENT}, |
{"math", HTML_INPHRASE | HTML_NLALL | HTML_INDENT}, |
{"mrow", 0}, |
{"mrow", 0}, |
{"mi", 0}, |
{"mi", 0}, |
Line 271 print_metaf(struct html *h) |
|
Line 275 print_metaf(struct html *h) |
|
void |
void |
html_close_paragraph(struct html *h) |
html_close_paragraph(struct html *h) |
{ |
{ |
struct tag *t; |
struct tag *this, *next; |
|
int flags; |
|
|
for (t = h->tag; t != NULL && t->closed == 0; t = t->next) { |
this = h->tag; |
switch(t->tag) { |
for (;;) { |
case TAG_P: |
next = this->next; |
case TAG_PRE: |
flags = htmltags[this->tag].flags; |
print_tagq(h, t); |
if (flags & (HTML_INPHRASE | HTML_TOPHRASE)) |
|
print_ctag(h, this); |
|
if ((flags & HTML_INPHRASE) == 0) |
break; |
break; |
case TAG_A: |
this = next; |
print_tagq(h, t); |
|
continue; |
|
default: |
|
continue; |
|
} |
|
break; |
|
} |
} |
} |
} |
|
|
Line 323 html_fillmode(struct html *h, enum roff_tok want) |
|
Line 324 html_fillmode(struct html *h, enum roff_tok want) |
|
return had; |
return had; |
} |
} |
|
|
|
/* |
|
* Allocate a string to be used for the "id=" attribute of an HTML |
|
* element and/or as a segment identifier for a URI in an <a> element. |
|
* The function may fail and return NULL if the node lacks text data |
|
* to create the attribute from. |
|
* If the "unique" argument is 0, the caller is responsible for |
|
* free(3)ing the returned string after using it. |
|
* If the "unique" argument is non-zero, the "id_unique" ohash table |
|
* is used for de-duplication and owns the returned string, so the |
|
* caller must not free(3) it. In this case, it will be freed |
|
* automatically by html_reset() or html_free(). |
|
*/ |
char * |
char * |
html_make_id(const struct roff_node *n, int unique) |
html_make_id(const struct roff_node *n, int unique) |
{ |
{ |
Line 331 html_make_id(const struct roff_node *n, int unique) |
|
Line 344 html_make_id(const struct roff_node *n, int unique) |
|
unsigned int slot; |
unsigned int slot; |
int suffix; |
int suffix; |
|
|
for (nch = n->child; nch != NULL; nch = nch->next) |
if (n->string != NULL) |
if (nch->type != ROFFT_TEXT) |
buf = mandoc_strdup(n->string); |
return NULL; |
else { |
|
switch (n->tok) { |
|
case MDOC_Sh: |
|
case MDOC_Ss: |
|
case MDOC_Sx: |
|
case MAN_SH: |
|
case MAN_SS: |
|
for (nch = n->child; nch != NULL; nch = nch->next) |
|
if (nch->type != ROFFT_TEXT) |
|
return NULL; |
|
buf = NULL; |
|
deroff(&buf, n); |
|
if (buf == NULL) |
|
return NULL; |
|
break; |
|
default: |
|
if (n->child->type != ROFFT_TEXT) |
|
return NULL; |
|
buf = mandoc_strdup(n->child->string); |
|
break; |
|
} |
|
} |
|
|
buf = NULL; |
|
deroff(&buf, n); |
|
if (buf == NULL) |
|
return NULL; |
|
|
|
/* |
/* |
* In ID attributes, only use ASCII characters that are |
* In ID attributes, only use ASCII characters that are |
* permitted in URL-fragment strings according to the |
* permitted in URL-fragment strings according to the |
Line 593 print_otag(struct html *h, enum htmltag tag, const cha |
|
Line 622 print_otag(struct html *h, enum htmltag tag, const cha |
|
assert((htmltags[t->tag].flags & HTML_TOPHRASE) == 0); |
assert((htmltags[t->tag].flags & HTML_TOPHRASE) == 0); |
break; |
break; |
} |
} |
} |
|
|
|
|
/* |
|
* Always wrap phrasing elements in a paragraph |
|
* unless already contained in some flow container; |
|
* never put them directly into a section. |
|
*/ |
|
|
|
} else if (tflags & HTML_TOPHRASE && h->tag->tag == TAG_SECTION) |
|
print_otag(h, TAG_P, "c", "Pp"); |
|
|
/* Push this tag onto the stack of open scopes. */ |
/* Push this tag onto the stack of open scopes. */ |
|
|
if ((tflags & HTML_NOSTACK) == 0) { |
if ((tflags & HTML_NOSTACK) == 0) { |
Line 730 print_otag(struct html *h, enum htmltag tag, const cha |
|
Line 767 print_otag(struct html *h, enum htmltag tag, const cha |
|
return t; |
return t; |
} |
} |
|
|
|
/* |
|
* Print an element with an optional "id=" attribute. |
|
* If there is an "id=" attribute, also add a permalink: |
|
* outside if it's a phrasing element, or inside otherwise. |
|
*/ |
|
struct tag * |
|
print_otag_id(struct html *h, enum htmltag elemtype, const char *cattr, |
|
struct roff_node *n) |
|
{ |
|
struct tag *ret, *t; |
|
const char *id; |
|
|
|
ret = NULL; |
|
id = NULL; |
|
if (n->flags & NODE_ID) |
|
id = html_make_id(n, 1); |
|
if (id != NULL && htmltags[elemtype].flags & HTML_INPHRASE) |
|
ret = print_otag(h, TAG_A, "chR", "permalink", id); |
|
t = print_otag(h, elemtype, "ci", cattr, id); |
|
if (ret == NULL) { |
|
ret = t; |
|
if (id != NULL) |
|
print_otag(h, TAG_A, "chR", "permalink", id); |
|
} |
|
return ret; |
|
} |
|
|
static void |
static void |
print_ctag(struct html *h, struct tag *tag) |
print_ctag(struct html *h, struct tag *tag) |
{ |
{ |
Line 799 print_gen_comment(struct html *h, struct roff_node *n) |
|
Line 863 print_gen_comment(struct html *h, struct roff_node *n) |
|
void |
void |
print_text(struct html *h, const char *word) |
print_text(struct html *h, const char *word) |
{ |
{ |
|
/* |
|
* Always wrap text in a paragraph unless already contained in |
|
* some flow container; never put it directly into a section. |
|
*/ |
|
|
|
if (h->tag->tag == TAG_SECTION) |
|
print_otag(h, TAG_P, "c", "Pp"); |
|
|
|
/* Output whitespace before this text? */ |
|
|
if (h->col && (h->flags & HTML_NOSPACE) == 0) { |
if (h->col && (h->flags & HTML_NOSPACE) == 0) { |
if ( ! (HTML_KEEP & h->flags)) { |
if ( ! (HTML_KEEP & h->flags)) { |
if (HTML_PREKEEP & h->flags) |
if (HTML_PREKEEP & h->flags) |
Line 808 print_text(struct html *h, const char *word) |
|
Line 882 print_text(struct html *h, const char *word) |
|
print_word(h, " "); |
print_word(h, " "); |
} |
} |
|
|
|
/* |
|
* Print the text, optionally surrounded by HTML whitespace, |
|
* optionally manually switching fonts before and after. |
|
*/ |
|
|
assert(h->metaf == NULL); |
assert(h->metaf == NULL); |
print_metaf(h); |
print_metaf(h); |
print_indent(h); |
print_indent(h); |
Line 948 print_indent(struct html *h) |
|
Line 1027 print_indent(struct html *h) |
|
{ |
{ |
size_t i; |
size_t i; |
|
|
if (h->col) |
if (h->col || h->noindent) |
return; |
return; |
|
|
if (h->noindent == 0) { |
h->col = h->indent * 2; |
h->col = h->indent * 2; |
for (i = 0; i < h->col; i++) |
for (i = 0; i < h->col; i++) |
putchar(' '); |
putchar(' '); |
|
} |
|
h->flags &= ~HTML_NOSPACE; |
|
} |
} |
|
|
/* |
/* |