/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's html output routines. * * By Shawn Hargreaves. * * Grzegorz Adam Hankiewicz made the output valid HTML 4.0, made * sorted TOCs and added support for cross references and optional * CSS to color output. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include #include #include #include "makehtml.h" #include "makemisc.h" #include "makedoc.h" typedef struct t_post POST; struct t_post { char filename[1024]; char **token; int num; }; int html_flags; char charset[256]="iso-8859-1"; const char *html_extension = "html"; char *document_title; char *html_footer; char *html_see_also_text; static POST **_post; static FILE *_file; static char _filename[1024]; static char *_xref[256]; static int _xrefs; static int _empty_count; /* Internal functions */ static void _write_html_xref_list(char **xref, int *xrefs); static void _write_html_xref(char *xref); static void _output_html_footer(char *main_filename); static void _output_toc(char *filename, int root, int body, int part); static void _hfprintf(char *format, ...); static void _hfputs(char *string); static int _toc_scmp(const void *e1, const void *e2); static int _output_section_heading(LINE *line, char *filename, int section_number); static void _output_custom_markers(LINE *line); static void _output_buffered_text(void); static void _output_html_header(char *section); static void _add_post_process_xref(const char *token); static void _post_process_pending_xrefs(void); static POST *_search_post_section(const char *filename); static POST *_search_post_section_with_token(const char *token); static POST *_create_post_section(const char *filename); static void _destroy_post_page(POST *p); static const char *_get_clean_xref_token(const char *text); static void _post_process_filename(char *filename); static int _verify_correct_input(void); static void _close_html_file(FILE *file); static void _output_sorted_nested_toc(TOC **list, unsigned int num_items); /* write_html: * Entry point to the function which translates makedoc's format * to correct html output. */ int write_html(char *filename) { int block_empty_lines = 0, section_number = 0; LINE *line = head; if (_verify_correct_input()) return 1; /* English default text initialization */ if(!html_see_also_text) html_see_also_text = m_strdup("See also:"); printf("writing %s\n", filename); _file = fopen(filename, "w"); if (!_file) return 1; strcpy(_filename, filename); if(document_title) _output_html_header(0); while (line) { if (line->flags & HTML_FLAG) { if (line->flags & (HEADING_FLAG | NODE_FLAG | DEFINITION_FLAG)) _write_html_xref_list(_xref, &_xrefs); if (line->flags & HEADING_FLAG) { _output_buffered_text(); if (_output_section_heading(line, filename, section_number)) return 1; section_number++; } else if (line->flags & NODE_FLAG) { _output_buffered_text(); /* output a node marker, which will be followed by a chunk of text inside a chapter */ fprintf(_file, "

%s

\n", line->text, line->text); _add_post_process_xref(line->text); } else if (line->flags & DEFINITION_FLAG) { if (_empty_count && !block_empty_lines) _empty_count++; _output_buffered_text(); /* output a function definition */ _add_post_process_xref(line->text); _hfprintf("%s", line->text); if (!(line->flags & CONTINUE_FLAG)) fputs("
", _file); fputs("\n", _file); } else if ((!(line->flags & NO_EOL_FLAG)) && (is_empty(strip_html(line->text))) && (!strstr(line->text, "

  • "))) { _hfprintf("%s\n", line->text); if (!block_empty_lines) _empty_count++; } else if (strstr(line->text, "") || strstr(line->text, "")) { _output_buffered_text(); _output_custom_markers(line); } else { /* output a normal line */ _output_buffered_text(); if ((html_flags & HTML_SPACED_LI) && strstr(line->text, "
  • ")) fputs("

    ", _file); _hfputs(line->text); fputs("\n", _file); } /* mutex to control extra line output in preformated sections */ if (strstr(line->text, "

    ") || strstr(line->text, "
      ")) { block_empty_lines++; _empty_count = 0; } else if (strstr(line->text, "
    ") || strstr(line->text, "")) { block_empty_lines--; } } else if (line->flags & TOC_FLAG) { _write_html_xref_list(_xref, &_xrefs); if (flags & MULTIFILE_FLAG) { _output_buffered_text(); _output_toc(filename, 1, 0, -1); } else if (line->flags & SHORT_TOC_FLAG) { _output_buffered_text(); _output_toc(filename, 0, 1, -1); } else { _output_buffered_text(); _output_toc(filename, 1, 1, -1); } } else if (line->flags & XREF_FLAG) _xref[_xrefs++] = line->text; /* buffer cross reference */ line = line->next; } if ((flags & MULTIFILE_FLAG) && (section_number > 1)) _output_html_footer(filename); _close_html_file(_file); _post_process_pending_xrefs(); free(html_see_also_text); return 0; } /* _output_custom_markers: * Converts the and custom markers to proper html code. */ static void _output_custom_markers(LINE *line) { char *s2, *s3; /* special munging for links */ char *s = line->text; do { s2 = strstr(s, ""); s3 = strstr(s, ""); if ((s2) || (s3)) { int i; char buf[256]; if ((s3) && ((!s2) || (s3 < s2))) s2 = s3; i = 0; while (s < s2) buf[i++] = *(s++); buf[i] = 0; _hfputs(buf); while (*s != '>') s++; s++; i = 0; while ((*s) && (*s != '<')) buf[i++] = *(s++); buf[i] = 0; if (s2[1] == 'e') _hfprintf("%s", buf, buf); else _hfprintf("%s", buf, buf); } } while (s2); _hfputs(s); fputs("\n", _file); } /* _write_html_xref_list: * Recieves an array of pointers and a pointer to the variable holding * the number of buffered text lines. Returns if there are none waiting * to be printed, otherwise sorts the list and writes a block of cross * references. */ static void _write_html_xref_list(char **xref, int *xrefs) { int i; assert(html_see_also_text); if (!(*xrefs)) return ; qsort(xref, *xrefs, sizeof(char *), scmp); fputs("\n", _file); fputs(html_see_also_text, _file); fputs("\n", _file); for (i=0; i<(*xrefs); i++) { if (i) _hfprintf(",\n"); _write_html_xref(xref[i]); } *xrefs = 0; _hfprintf(".\n"); _empty_count = 0; } /* _write_html_xref: * Writes a single cross reference splitting xref if needed */ static void _write_html_xref(char *xref) { char *tok, first = 1; tok = strtok(xref, ",;"); while (tok) { while ((*tok) && (myisspace(*tok))) tok++; if (!first) _hfprintf(",\n"); first = 0; _hfprintf("%s", tok, tok); else _hfprintf("href=\"#%s\">%s", tok, tok); tok = strtok(NULL, ",;"); } } /* _output_html_footer: * Writes that "Back to contets" message at the end of a file with a link. */ static void _output_html_footer(char *main_filename) { assert(html_footer); if (html_flags & HTML_OLD_F_TAG_FLAG) fprintf(_file, html_footer, get_filename(main_filename)); else fprintf(_file, "
    %s\n", get_filename(main_filename), html_footer); } /* _output_toc: */ static void _output_toc(char *filename, int root, int body, int part) { char name[256]; char *s; TOC *toc; int nested = 0; #define ALT_TEXT(toc) ((toc->alt) ? toc->alt : toc->text) if (root) { int section_number = 0; toc = tochead; if (toc) toc = toc->next; fprintf(_file, "
      \n"); while (toc) { if ((toc->root) && (toc->htmlable)) { if (toc->otherfile) { sprintf(name, "%s.%s", toc->text, html_extension); mystrlwr(name); _hfprintf("
    • %s\n", name, ALT_TEXT(toc)); } else if (body) { _hfprintf("
    • %s\n", toc->text, ALT_TEXT(toc)); section_number++; } else { strcpy(name, filename); s = extension(name)-1; if ((int)s - (int)get_filename(name) > 5) s = get_filename(name)+5; sprintf(s, "%03d.%s", section_number, html_extension); _hfprintf("
    • %s\n", get_filename(name), ALT_TEXT(toc)); section_number++; } } toc = toc->next; } fprintf(_file, "
    \n"); } if (body) { toc = tochead; if (toc) toc = toc->next; if (part <= 0) { TOC *ptr[TOC_SIZE]; int i = 0; if (root) fprintf(_file, "