diff options
Diffstat (limited to 'man/mantohtml.c')
-rw-r--r-- | man/mantohtml.c | 1042 |
1 files changed, 707 insertions, 335 deletions
diff --git a/man/mantohtml.c b/man/mantohtml.c index 512dda134..6811f0b90 100644 --- a/man/mantohtml.c +++ b/man/mantohtml.c @@ -1,22 +1,16 @@ /* - * "$Id: mantohtml.c 10996 2013-05-29 11:51:34Z msweet $" + * "$Id: mantohtml.c 11818 2014-04-15 20:56:19Z msweet $" * - * Man page to HTML conversion program. + * Man page to HTML conversion program. * - * Copyright 2007-2010 by Apple Inc. - * Copyright 2004-2006 by Easy Software Products. + * Copyright 2007-2010, 2014 by Apple Inc. + * Copyright 2004-2006 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Convert a man page to HTML. - * putc_entity() - Put a single character, using entities as needed. - * strmove() - Move characters within a string. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -24,14 +18,26 @@ */ #include <cups/string-private.h> +#include <cups/array-private.h> #include <unistd.h> /* + * Local globals... + */ + +static const char /* Start/end tags for fonts */ + * const start_fonts[] = { "", "<b>", "<i>" }, + * const end_fonts[] = { "", "</b>", "</i>" }; + + +/* * Local functions... */ -static void putc_entity(int ch, FILE *fp); +static void html_alternate(const char *s, const char *first, const char *second, FILE *fp); +static void html_fputs(const char *s, int *font, FILE *fp); +static void html_putc(int ch, FILE *fp); static void strmove(char *d, const char *s); @@ -47,20 +53,18 @@ main(int argc, /* I - Number of command-line args */ *outfile; /* Output file */ char line[1024], /* Line from file */ *lineptr, /* Pointer into line */ - *endptr, /* Pointer to end of current */ - endchar, /* End character */ - *paren, /* Pointer to parenthesis */ - name[1024]; /* Man page name */ - int section, /* Man page section */ - pre, /* Preformatted */ - font, /* Current font */ - blist, /* In a bullet list? */ - list, /* In a list? */ - linenum; /* Current line number */ - const char *post; /* Text to add after the current line */ - static const char /* Start/end tags for fonts */ - * const start_fonts[] = { "", "<b>", "<i>" }, - * const end_fonts[] = { "", "</b>", "</i>" }; + name[1024], /* Man page name */ + ddpost[256]; /* Tagged list post markup */ + int section = -1, /* Man page section */ + pre = 0, /* Preformatted */ + font = 0, /* Current font */ + linenum = 0; /* Current line number */ + float list_indent = 0.0f, /* Current list indentation */ + nested_indent = 0.0f; /* Nested list indentation, if any */ + const char *list = NULL, /* Current list, if any */ + *nested = NULL; /* Nested list, if any */ + const char *post = NULL; /* Text to add after the current line */ + /* * Check arguments... @@ -103,24 +107,20 @@ main(int argc, /* I - Number of command-line args */ * Read from input and write the output... */ - fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" " - "\"http://www.w3.org/TR/html4/loose.dtd\">\n" + fputs("<!DOCTYPE HTML>\n" "<html>\n" "<!-- SECTION: Man Pages -->\n" "<head>\n" "\t<link rel=\"stylesheet\" type=\"text/css\" " "href=\"../cups-printable.css\">\n", outfile); - blist = 0; - font = 0; - list = 0; - linenum = 0; - pre = 0; - post = NULL; - section = -1; - while (fgets(line, sizeof(line), infile)) { + size_t linelen = strlen(line); /* Length of line */ + + if (linelen > 0 && line[linelen - 1] == '\n') + line[linelen - 1] = '\0'; + linenum ++; if (line[0] == '.') @@ -163,247 +163,492 @@ main(int argc, /* I - Number of command-line args */ int first = 1; fputs(end_fonts[font], outfile); - - if (blist) - { - fputs("</li>\n</ul>\n", outfile); - blist = 0; - } + font = 0; if (list) { - if (list == 1) - fputs("</dt>\n", outfile); - else if (list) - fputs("</dd>\n", outfile); - - fputs("</dl>\n", outfile); - list = 0; + fprintf(outfile, "</%s>\n", list); + list = NULL; } - line[strlen(line) - 1] = '\0'; /* Strip LF */ - if (line[2] == 'H') fputs("<h2 class=\"title\"><a name=\"", outfile); else fputs("<h3><a name=\"", outfile); for (lineptr = line + 4; *lineptr; lineptr ++) - if (*lineptr == '\"') + if (*lineptr == '\"') continue; - else if (*lineptr == ' ') - putc_entity('_', outfile); + else if (isalnum(*lineptr & 255)) + html_putc(*lineptr, outfile); else - putc_entity(*lineptr, outfile); + html_putc('_', outfile); fputs("\">", outfile); for (lineptr = line + 4; *lineptr; lineptr ++) + { if (*lineptr == '\"') continue; else if (*lineptr == ' ') { - putc_entity(' ', outfile); + html_putc(' ', outfile); first = 1; } else { if (first) - putc_entity(*lineptr, outfile); + html_putc(*lineptr, outfile); else - putc_entity(tolower(*lineptr), outfile); + html_putc(tolower(*lineptr & 255), outfile); first = 0; } + } if (line[2] == 'H') - fprintf(outfile, "</a></h2>\n%s", start_fonts[font]); + fputs("</a></h2>\n", outfile); else - fprintf(outfile, "</a></h3>\n%s", start_fonts[font]); + fputs("</a></h3>\n", outfile); } - else if (!strncmp(line, ".LP", 3) || !strncmp(line, ".PP", 3)) + else if (!strncmp(line, ".B ", 3)) { /* - * New paragraph... + * Grab bold text... */ fputs(end_fonts[font], outfile); + font = 0; + + html_alternate(line + 3, "b", "b", outfile); - if (blist) + if (post) { - fputs("</li>\n</ul>\n", outfile); - blist = 0; + fputs(post, outfile); + post = NULL; } + } + else if (!strncmp(line, ".I ", 3)) + { + /* + * Grab italic text... + */ - if (list) + fputs(end_fonts[font], outfile); + font = 0; + + html_alternate(line + 3, "i", "i", outfile); + + if (post) { - if (list == 1) - fputs("</dt>\n", outfile); - else if (list) - fputs("</dd>\n", outfile); + fputs(post, outfile); + post = NULL; + } + } + else if (!strncmp(line, ".BI ", 4)) + { + /* + * Alternating bold and italic text... + */ + + fputs(end_fonts[font], outfile); + font = 0; + + html_alternate(line + 4, "b", "i", outfile); - fputs("</dl>\n", outfile); - list = 0; + if (post) + { + fputs(post, outfile); + post = NULL; } + } + else if (!strncmp(line, ".BR ", 4)) + { + /* + * Alternating bold and roman (plain) text... + */ - fputs("<p>", outfile); + fputs(end_fonts[font], outfile); font = 0; + + html_alternate(line + 4, "b", NULL, outfile); + + if (post) + { + fputs(post, outfile); + post = NULL; + } } - else if (!strncmp(line, ".TP ", 4)) + else if (!strncmp(line, ".IB ", 4)) { /* - * Grab list... - */ + * Alternating italic and bold text... + */ fputs(end_fonts[font], outfile); + font = 0; + + html_alternate(line + 4, "i", "b", outfile); - if (blist) + if (post) { - fputs("</li>\n</ul>\n", outfile); - blist = 0; + fputs(post, outfile); + post = NULL; } + } + else if (!strncmp(line, ".IR ", 4)) + { + /* + * Alternating italic and roman (plain) text... + */ - if (!list) - fputs("<dl>\n", outfile); - else if (list == 1) - fputs("</dt>\n", outfile); - else if (list) - fputs("</dd>\n", outfile); - - fputs("<dt>", outfile); - list = 1; + fputs(end_fonts[font], outfile); font = 0; + + html_alternate(line + 4, "i", NULL, outfile); + + if (post) + { + fputs(post, outfile); + post = NULL; + } } - else if (!strncmp(line, ".br", 3)) + else if (!strncmp(line, ".RB ", 4)) { /* - * Grab line break... - */ + * Alternating roman (plain) and bold text... + */ - if (list == 1) + fputs(end_fonts[font], outfile); + font = 0; + + html_alternate(line + 4, NULL, "b", outfile); + + if (post) { - fputs("</dt>\n<dd>", outfile); - list = 2; + fputs(post, outfile); + post = NULL; } - else if (list) - fputs("</dd>\n<dd>", outfile); - else - fputs("<br>\n", outfile); } - else if (!strncmp(line, ".de ", 4)) + else if (!strncmp(line, ".RI ", 4)) { /* - * Define macro - ignore... - */ + * Alternating roman (plain) and italic text... + */ - while (fgets(line, sizeof(line), infile)) + fputs(end_fonts[font], outfile); + font = 0; + + html_alternate(line + 4, NULL, "i", outfile); + + if (post) { - linenum ++; + fputs(post, outfile); + post = NULL; + } + } + else if (!strncmp(line, ".SB ", 4)) + { + /* + * Alternating small and bold text... + */ - if (!strncmp(line, "..", 2)) - break; + fputs(end_fonts[font], outfile); + font = 0; + + html_alternate(line + 4, "small", "b", outfile); + + if (post) + { + fputs(post, outfile); + post = NULL; } } - else if (!strncmp(line, ".RS", 3)) + else if (!strncmp(line, ".SM ", 4)) { /* - * Indent... - */ + * Small text... + */ - fputs("<div style='margin-left: 3em;'>\n", outfile); + fputs(end_fonts[font], outfile); + font = 0; + + html_alternate(line + 4, "small", "small", outfile); + + if (post) + { + fputs(post, outfile); + post = NULL; + } } - else if (!strncmp(line, ".RE", 3)) + else if (!strcmp(line, ".LP") || !strcmp(line, ".PP") || !strcmp(line, ".P")) { /* - * Unindent... + * New paragraph... */ - fputs("</div>\n", outfile); + fputs(end_fonts[font], outfile); + font = 0; + + if (list) + { + fprintf(outfile, "</%s>\n", list); + list = NULL; + } + + fputs("<p>", outfile); } - else if (!strncmp(line, ".ds ", 4) || !strncmp(line, ".rm ", 4) || - !strncmp(line, ".tr ", 4) || !strncmp(line, ".hy ", 4) || - !strncmp(line, ".IX ", 4) || !strncmp(line, ".PD", 3) || - !strncmp(line, ".Sp", 3)) + else if (!strcmp(line, ".RS") || !strncmp(line, ".RS ", 4)) { /* - * Ignore unused commands... + * Indent... */ + + float amount = 3.0; /* Indentation */ + + if (line[3]) + amount = atof(line + 4); + + fputs(end_fonts[font], outfile); + font = 0; + + if (list) + { + nested = list; + list = NULL; + nested_indent = list_indent; + list_indent = 0.0f; + } + + fprintf(outfile, "<div style=\"margin-left: %.1fem;\">\n", amount - nested_indent); } - else if (!strncmp(line, ".Vb", 3) || !strncmp(line, ".nf", 3)) + else if (!strcmp(line, ".RE")) { /* - * Start preformatted... + * Unindent... */ - pre = 1; - fputs("<pre>\n", outfile); + fputs(end_fonts[font], outfile); + font = 0; + + fputs("</div>\n", outfile); + + if (nested) + { + list = nested; + nested = NULL; + + list_indent = nested_indent; + nested_indent = 0.0f; + } } - else if (!strncmp(line, ".Ve", 3) || !strncmp(line, ".fi", 3)) + else if (!strcmp(line, ".HP") || !strncmp(line, ".HP ", 4)) { /* - * End preformatted... + * Hanging paragraph... + * + * .HP i */ - if (pre) - { - pre = 0; - fputs("</pre>\n", outfile); - } + float amount = 3.0; /* Indentation */ + + if (line[3]) + amount = atof(line + 4); + + fputs(end_fonts[font], outfile); + font = 0; + + if (list) + { + fprintf(outfile, "</%s>\n", list); + list = NULL; + } + + fprintf(outfile, "<p style=\"margin-left: %.1fem; text-indent: %.1fem\">", amount, -amount); + + if (line[1] == 'T') + post = "<br>\n"; } - else if (!strncmp(line, ".IP \\(bu", 8)) + else if (!strcmp(line, ".TP") || !strncmp(line, ".TP ", 4)) { /* - * Bullet list... + * Tagged list... + * + * .TP i */ - if (blist) - fputs("</li>\n", outfile); - else - { - fputs("<ul>\n", outfile); - blist = 1; - } + float amount = 3.0; /* Indentation */ + + if (line[3]) + amount = atof(line + 4); + + fputs(end_fonts[font], outfile); + font = 0; + + if (list && strcmp(list, "dl")) + { + fprintf(outfile, "</%s>\n", list); + list = NULL; + } - fputs("<li>", outfile); + if (!list) + { + fputs("<dl class=\"man\">\n", outfile); + list = "dl"; + list_indent = amount; + } + + fputs("<dt>", outfile); + snprintf(ddpost, sizeof(ddpost), "<dd style=\"margin-left: %.1fem\">", amount); + post = ddpost; } else if (!strncmp(line, ".IP ", 4)) { /* * Indented paragraph... + * + * .IP x i */ - if (blist) + float amount = 3.0; /* Indentation */ + const char *newlist = NULL; /* New list style */ + const char *newtype = NULL; /* New list numbering type */ + + fputs(end_fonts[font], outfile); + font = 0; + + lineptr = line + 4; + while (isspace(*lineptr & 255)) + lineptr ++; + + if (!strncmp(lineptr, "\\(bu", 4) || !strncmp(lineptr, "\\(em", 4)) { - fputs("</li>\n</ul>\n", outfile); - blist = 0; - } + /* + * Bullet list... + */ - fputs("<p style='margin-left: 3em;'>", outfile); + newlist = "ul"; + } + else if (isdigit(*lineptr & 255)) + { + /* + * Numbered list... + */ - for (lineptr = line + 4; isspace(*lineptr); lineptr ++); + newlist = "ol"; + } + else if (islower(*lineptr & 255)) + { + /* + * Lowercase alpha list... + */ - if (*lineptr == '\"') + newlist = "ol"; + newtype = "a"; + } + else if (isupper(*lineptr & 255)) { - strmove(line, lineptr + 1); + /* + * Lowercase alpha list... + */ + + newlist = "ol"; + newtype = "A"; + } + + while (!isspace(*lineptr & 255)) + lineptr ++; + while (isspace(*lineptr & 255)) + lineptr ++; - if ((lineptr = strchr(line, '\"')) != NULL) - *lineptr = '\0'; + if (isdigit(*lineptr & 255)) + amount = atof(lineptr); + + if (newlist && list && strcmp(newlist, list)) + { + fprintf(outfile, "</%s>\n", list); + list = NULL; } - else - { - strmove(line, lineptr); - if ((lineptr = strchr(line, ' ')) != NULL) - *lineptr = '\0'; + if (newlist && !list) + { + if (newtype) + fprintf(outfile, "<%s type=\"%s\">\n", newlist, newtype); + else + fprintf(outfile, "<%s>\n", newlist); + + list = newlist; } + if (list) + fprintf(outfile, "<li style=\"margin-left: %.1fem;\">", amount); + else + fprintf(outfile, "<p style=\"margin-left: %.1fem;\">", amount); + } + else if (!strncmp(line, ".br", 3)) + { /* - * Process the text as if it was in-line... + * Grab line break... */ - post = "\n<br>\n<br>"; - goto process_text; + fputs("<br>\n", outfile); + } + else if (!strncmp(line, ".de ", 4)) + { + /* + * Define macro - ignore... + */ + + while (fgets(line, sizeof(line), infile)) + { + linenum ++; + + if (!strncmp(line, "..", 2)) + break; + } + } + else if (!strncmp(line, ".ds ", 4) || !strncmp(line, ".rm ", 4) || + !strncmp(line, ".tr ", 4) || !strncmp(line, ".hy ", 4) || + !strncmp(line, ".IX ", 4) || !strncmp(line, ".PD", 3) || + !strncmp(line, ".Sp", 3)) + { + /* + * Ignore unused commands... + */ + } + else if (!strncmp(line, ".Vb", 3) || !strncmp(line, ".nf", 3) || !strncmp(line, ".EX", 3)) + { + /* + * Start preformatted... + */ + + fputs(end_fonts[font], outfile); + font = 0; + +// if (list) +// { +// fprintf(outfile, "</%s>\n", list); +// list = NULL; +// } + + pre = 1; + fputs("<pre class=\"man\">\n", outfile); + } + else if (!strncmp(line, ".Ve", 3) || !strncmp(line, ".fi", 3) || !strncmp(line, ".EE", 3)) + { + /* + * End preformatted... + */ + + fputs(end_fonts[font], outfile); + font = 0; + + if (pre) + { + pre = 0; + fputs("</pre>\n", outfile); + } } else if (!strncmp(line, ".\\}", 3)) { @@ -441,24 +686,6 @@ main(int argc, /* I - Number of command-line args */ */ } #endif /* 0 */ - else if (!strncmp(line, ".B ", 3)) - { - /* - * Grab bold text... - */ - - fprintf(outfile, "%s<b>%s</b>%s", end_fonts[font], line + 3, - start_fonts[font]); - } - else if (!strncmp(line, ".I ", 3)) - { - /* - * Grab italic text... - */ - - fprintf(outfile, "%s<i>%s</i>%s", end_fonts[font], line + 3, - start_fonts[font]); - } else if (strncmp(line, ".\\\"", 3)) { /* @@ -470,15 +697,14 @@ main(int argc, /* I - Number of command-line args */ else if ((lineptr = strchr(line, '\n')) != NULL) *lineptr = '\0'; - fprintf(stderr, "mantohtml: Unknown man page command \'%s\' on line %d!\n", - line, linenum); + fprintf(stderr, "mantohtml: Unknown man page command \'%s\' on line %d.\n", line, linenum); } /* * Skip continuation lines... */ - lineptr = line + strlen(line) - 2; + lineptr = line + strlen(line) - 1; if (lineptr >= line && *lineptr == '\\') { while (fgets(line, sizeof(line), infile)) @@ -497,169 +723,24 @@ main(int argc, /* I - Number of command-line args */ * Process man page text... */ -process_text: - - for (lineptr = line; *lineptr; lineptr ++) - { - if (!strncmp(lineptr, "http://", 7)) - { - /* - * Embed URL... - */ - - for (endptr = lineptr + 7; - *endptr && !isspace(*endptr & 255); - endptr ++); - - endchar = *endptr; - *endptr = '\0'; - - fprintf(outfile, "<a href='%s'>%s</a>", lineptr, lineptr); - *endptr = endchar; - lineptr = endptr - 1; - } - else if (!strncmp(lineptr, "\\fI", 3) && - (endptr = strstr(lineptr, "\\fR")) != NULL && - (paren = strchr(lineptr, '(')) != NULL && - paren < endptr) - { - /* - * Link to man page? - */ - - char manfile[1024], /* Man page filename */ - manurl[1024]; /* Man page URL */ - - - /* - * See if the man file is available locally... - */ - - lineptr += 3; - endchar = *paren; - *paren = '\0'; - - snprintf(manfile, sizeof(manfile), "%s.man", lineptr); - snprintf(manurl, sizeof(manurl), "man-%s.html?TOPIC=Man+Pages", - lineptr); - - *paren = endchar; - endchar = *endptr; - *endptr = '\0'; - - if (access(manfile, 0)) - { - /* - * Not a local man page, just do it italic... - */ - - fputs("<i>", outfile); - while (*lineptr) - putc_entity(*lineptr++, outfile); - fputs("</i>", outfile); - } - else - { - /* - * Local man page, do a link... - */ - - fprintf(outfile, "<a href='%s'>", manurl); - while (*lineptr) - putc_entity(*lineptr++, outfile); - fputs("</a>", outfile); - } - - *endptr = endchar; - lineptr = endptr + 2; - } - else if (*lineptr == '\\') - { - lineptr ++; - if (!*lineptr) - break; - else if (isdigit(lineptr[0]) && isdigit(lineptr[1]) && - isdigit(lineptr[2])) - { - fprintf(outfile, "&#%d;", ((lineptr[0] - '0') * 8 + - lineptr[1] - '0') * 8 + - lineptr[2] - '0'); - lineptr += 2; - } - else if (*lineptr == '&') - continue; - else if (*lineptr == 's') - { - while (lineptr[1] == '-' || isdigit(lineptr[1])) - lineptr ++; - } - else if (*lineptr == '*') - { - lineptr += 2; - } - else if (*lineptr != 'f') - putc_entity(*lineptr, outfile); - else - { - lineptr ++; - if (!*lineptr) - break; - else - { - fputs(end_fonts[font], outfile); - - switch (*lineptr) - { - default : /* Regular */ - font = 0; - break; - case 'B' : /* Bold */ - case 'b' : - font = 1; - break; - case 'I' : /* Italic */ - case 'i' : - font = 2; - break; - } - - fputs(start_fonts[font], outfile); - } - } - } - else - putc_entity(*lineptr, outfile); - } + html_fputs(line, &font, outfile); + putc('\n', outfile); if (post) { fputs(post, outfile); post = NULL; } - - if (list == 1) - { - fputs("</dt>\n<dd>", outfile); - list = 2; - } } } fprintf(outfile, "%s\n", end_fonts[font]); - - if (blist) - { - fputs("</li>\n</ul>\n", outfile); - } + font = 0; if (list) { - if (list == 1) - fputs("</dt>\n", outfile); - else if (list) - fputs("</dd>\n", outfile); - - fputs("</dl>\n", outfile); + fprintf(outfile, "</%s>\n", list); + list = NULL; } fputs("</body>\n" @@ -684,12 +765,303 @@ process_text: /* - * 'putc_entity()' - Put a single character, using entities as needed. + * 'html_alternate()' - Alternate words between two styles of text. + */ + +static void +html_alternate(const char *s, /* I - String */ + const char *first, /* I - First style or NULL */ + const char *second, /* I - Second style of NULL */ + FILE *fp) /* I - File */ +{ + int i = 0; /* Which style */ + int quote = 0; /* Saw quote? */ + int dolinks, /* Do hyperlinks to other man pages? */ + link = 0; /* Doing a link now? */ + + + /* + * Skip leading whitespace... + */ + + while (isspace(*s & 255)) + s ++; + + dolinks = first && !strcmp(first, "b") && !second; + + while (*s) + { + if (!i && dolinks) + { + /* + * See if we need to make a link to a man page... + */ + + const char *end; /* End of current word */ + const char *next; /* Start of next word */ + + for (end = s; *end && !isspace(*end & 255); end ++); + for (next = end; isspace(*next & 255); next ++); + + if (isalnum(*s & 255) && *next == '(') + { + /* + * See if the man file is available locally... + */ + + char name[1024], /* Name */ + manfile[1024], /* Man page filename */ + manurl[1024]; /* Man page URL */ + + strlcpy(name, s, sizeof(name)); + if ((size_t)(end - s) < sizeof(name)) + name[end - s] = '\0'; + + snprintf(manfile, sizeof(manfile), "%s.man", name); + snprintf(manurl, sizeof(manurl), "man-%s.html?TOPIC=Man+Pages", name); + + if (!access(manfile, 0)) + { + /* + * Local man page, do a link... + */ + + fprintf(fp, "<a href=\"%s\">", manurl); + link = 1; + } + } + } + + if (!i && first) + fprintf(fp, "<%s>", first); + else if (i && second) + fprintf(fp, "<%s>", second); + + while ((!isspace(*s & 255) || quote) && *s) + { + if (*s == '\"') + quote = !quote; + else if (*s == '\\' && s[1]) + { + s ++; + html_putc(*s++, fp); + } + else + html_putc(*s++, fp); + } + + if (!i && first) + fprintf(fp, "</%s>", first); + else if (i && second) + fprintf(fp, "</%s>", second); + + if (i && link) + { + fputs("</a>", fp); + link = 0; + } + + i = 1 - i; + + /* + * Skip trailing whitespace... + */ + + while (isspace(*s & 255)) + s ++; + } + + putc('\n', fp); +} + +/* + * 'html_fputs()' - Output a string, quoting as needed HTML entities. + */ + +static void +html_fputs(const char *s, /* I - String */ + int *font, /* IO - Font */ + FILE *fp) /* I - File */ +{ + while (*s) + { + if (*s == '\\') + { + s ++; + if (!*s) + break; + + if (*s == 'f') + { + int newfont; /* New font */ + + s ++; + if (!*s) + break; + + if (!font) + { + s ++; + continue; + } + + switch (*s++) + { + case 'R' : + case 'P' : + newfont = 0; + break; + + case 'b' : + case 'B' : + newfont = 1; + break; + + case 'i' : + case 'I' : + newfont = 2; + break; + + default : + fprintf(stderr, "mantohtml: Unknown font \"\\f%c\" ignored.\n", s[-1]); + newfont = *font; + break; + } + + if (newfont != *font) + { + fputs(end_fonts[*font], fp); + *font = newfont; + fputs(start_fonts[*font], fp); + } + } + else if (*s == '*') + { + /* + * Substitute macro... + */ + + s ++; + if (!*s) + break; + + switch (*s++) + { + case 'R' : + fputs("®", fp); + break; + + case '(' : + if (!strncmp(s, "lq", 2)) + fputs("“", fp); + else if (!strncmp(s, "rq", 2)) + fputs("”", fp); + else if (!strncmp(s, "Tm", 2)) + fputs("<sup>TM</sup>", fp); + else + fprintf(stderr, "mantohtml: Unknown macro \"\\*(%2s\" ignored.\n", s); + + if (*s) + s ++; + if (*s) + s ++; + break; + + default : + fprintf(stderr, "mantohtml: Unknown macro \"\\*%c\" ignored.\n", s[-1]); + break; + } + } + else if (*s == '(') + { + if (!strncmp(s, "(em", 3)) + { + fputs("—", fp); + s += 3; + } + else if (!strncmp(s, "(en", 3)) + { + fputs("–", fp); + s += 3; + } + else + { + putc(*s, fp); + s ++; + } + } + else if (*s == '[') + { + /* + * Substitute escaped character... + */ + + s ++; + if (!strncmp(s, "co]", 3)) + fputs("©", fp); + else if (!strncmp(s, "de]", 3)) + fputs("°", fp); + else if (!strncmp(s, "rg]", 3)) + fputs("®", fp); + else if (!strncmp(s, "tm]", 3)) + fputs("<sup>TM</sup>", fp); + + if (*s) + s ++; + if (*s) + s ++; + if (*s) + s ++; + } + else if (isdigit(s[0]) && isdigit(s[1]) && + isdigit(s[2])) + { + fprintf(fp, "&#%d;", ((s[0] - '0') * 8 + s[1] - '0') * 8 + s[2] - '0'); + s += 3; + } + else + { + if (*s != '\\' && *s == '\"' && *s == '\'' && *s == '-') + fprintf(stderr, "mantohtml: Unrecognized escape \"\\%c\" ignored.\n", *s); + + html_putc(*s++, fp); + } + } + else if (!strncmp(s, "http://", 7) || !strncmp(s, "https://", 8) || !strncmp(s, "ftp://", 6)) + { + /* + * Embed URL... + */ + + char temp[1024]; /* Temporary string */ + const char *end = s + 6; /* End of URL */ + + while (*end && !isspace(*end & 255)) + end ++; + + if (end[-1] == ',' || end[-1] == '.' || end[-1] == ')') + end --; + + strlcpy(temp, s, sizeof(temp)); + if ((size_t)(end -s) < sizeof(temp)) + temp[end - s] = '\0'; + + fprintf(fp, "<a href=\"%s\">%s</a>", temp, temp); + s = end; + } + else + html_putc(*s++ & 255, fp); + } +} + + +/* + * 'html_putc()' - Put a single character, using entities as needed. */ static void -putc_entity(int ch, /* I - Character */ - FILE *fp) /* I - File */ +html_putc(int ch, /* I - Character */ + FILE *fp) /* I - File */ { if (ch == '&') fputs("&", fp); @@ -716,5 +1088,5 @@ strmove(char *d, /* I - Destination */ /* - * End of "$Id: mantohtml.c 10996 2013-05-29 11:51:34Z msweet $". + * End of "$Id: mantohtml.c 11818 2014-04-15 20:56:19Z msweet $". */ |