HTML_Generator
[ Top ] [ ROBODoc ] [ Modules ]
FUNCTION
The generator for HTML output.
The generator supports sections upto 7 levels deep. It supports a Table of Contents based on all headers. A masterindex for all headertypes and seperate masterindexes for each headertype.
MODIFICATION HISTORY
2003-02-03 Frans Slothouber Refactoring ????-??-?? Frans Slothouber V1.0
RB_Create_CSS
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Create the .css file. Unless the user specified it's own css file robodoc creates a default one.
For multidoc mode the name of the .css file is
robodoc.css
For singledoc mode the name of the .css file is equal to the name of the documentation file.
SYNOPSIS
void RB_Create_CSS( struct RB_Document *document )
INPUTS
- document -- the document for which to create the file.
SOURCE
{ size_t l = 0; FILE *css_file; /* compute the complete path to the css file */ if ( ( document->actions.do_singledoc ) || ( document->actions.do_singlefile ) ) { char *extension = ".css"; l += strlen( document->singledoc_name ); l += strlen( extension ); ++l; css_name = malloc( l ); strcpy( css_name, document->singledoc_name ); strcat( css_name, extension ); } else { struct RB_Path *docroot = document->docroot; char *docrootname = docroot->name; char *filename = "robodoc.css"; l = strlen( filename ); l += strlen( docrootname ); ++l; css_name = malloc( l ); strcpy( css_name, docrootname ); strcat( css_name, filename ); } RB_Say( "Creating CSS file %s\n", SAY_DEBUG, css_name ); if ( document->css ) { /* The user specified its own css file, * so we use the content of that. */ RB_CopyFile( document->css, css_name ); } else { css_file = fopen( css_name, "w" ); if ( css_file ) { /** BEGIN BEGIN BEGIN Don't remove */ fprintf( css_file, "/****h* ROBODoc/ROBODoc Cascading Style Sheet\n" " * FUNCTION\n" " * This is the default cascading style sheet for documentation\n" " * generated with ROBODoc.\n" " * You can edit this file to your own liking and then use\n" " * it with the option\n" " * --css <filename>\n" " *\n" " * This style-sheet defines the following layout\n" " * +----------------------------------------+\n" " * | logo |\n" " * +----------------------------------------+\n" " * | extra |\n" " * +----------------------------------------+\n" " * | | navi- |\n" " * | | gation |\n" " * | content | |\n" " * | | |\n" " * +----------------------------------------+\n" " * | footer |\n" " * +----------------------------------------+\n" " *\n" " * This style-sheet is based on a style-sheet that was automatically\n" " * generated with the Strange Banana stylesheet generator.\n" " * See http://www.strangebanana.com/generator.aspx\n" " *\n" " ******\n" " * $Id: html_generator.c,v 1.94 2008/06/17 11:49:27 gumpu Exp $\n" " */\n" "\n" "body\n" "{\n" " background-color: rgb(255,255,255);\n" " color: rgb(98,84,55);\n" " font-family: Arial, serif;\n" " border-color: rgb(226,199,143);\n" "}\n" "\n" "pre\n" "{\n" " font-family: monospace;\n" " margin: 15px;\n" " padding: 5px;\n" " white-space: pre;\n" " color: #000;\n" "}\n" "\n" "pre.source\n" "{\n" " background-color: #ffe;\n" " border: dashed #aa9 1px;\n" "}\n" "\n" "p\n" "{\n" " margin:15px;\n" "}\n" "\n" "p.item_name \n" "{\n" " font-weight: bolder;\n" " margin:5px;\n" " font-size: 120%%;\n" "}\n" "\n" "#content\n" "{\n" " font-size: 100%%;\n" ); fprintf( css_file, " color: rgb(0,0,0);\n" " background-color: rgb(255,255,255);\n" " border-left-width: 0px; \n" " border-right-width: 0px; \n" " border-top-width: 0px; \n" " border-bottom-width: 0px;\n" " border-left-style: none; \n" " border-right-style: none; \n" " border-top-style: none; \n" " border-bottom-style: none;\n" " padding: 40px 31px 14px 17px;\n" " border-color: rgb(0,0,0);\n" " text-align: justify;\n" "}\n" "\n" "#navigation\n" "{\n" " background-color: rgb(98,84,55);\n" " color: rgb(230,221,202);\n" " font-family: \"Times New Roman\", serif;\n" " font-style: normal;\n" " border-color: rgb(0,0,0);\n" "}\n" "\n" "a.menuitem\n" "{\n" " font-size: 120%%;\n" " background-color: rgb(0,0,0);\n" " color: rgb(195,165,100);\n" " font-variant: normal;\n" " text-transform: none;\n" " font-weight: normal;\n" " padding: 1px 8px 3px 1px;\n" " margin-left: 5px; \n" " margin-right: 5px; \n" " margin-top: 5px; \n" " margin-bottom: 5px;\n" " border-color: rgb(159,126,57);\n" " text-align: right;\n" "}\n" "\n" "#logo, #logo a\n" "{\n" " font-size: 130%%;\n" " background-color: rgb(198,178,135);\n" " color: rgb(98,84,55);\n" " font-family: Georgia, serif;\n" " font-style: normal;\n" " font-variant: normal;\n" " text-transform: none;\n" " font-weight: bold;\n" " padding: 20px 18px 20px 18px;\n" " border-color: rgb(255,255,255);\n" " text-align: right;\n" "}\n" "\n" "#extra, #extra a\n" "{\n" " font-size: 128%%;\n" " background-color: rgb(0,0,0);\n" " color: rgb(230,221,202);\n" " font-style: normal;\n" " font-variant: normal;\n" " text-transform: none;\n" " font-weight: normal;\n" ); fprintf( css_file, " border-left-width: 0px; \n" " border-right-width: 0px; \n" " border-top-width: 0px; \n" " border-bottom-width: 0px;\n" " border-left-style: none; \n" " border-right-style: none; \n" " border-top-style: none; \n" " border-bottom-style: none;\n" " padding: 12px 12px 12px 12px;\n" " border-color: rgb(195,165,100);\n" " text-align: center;\n" "}\n" "\n" "#content a\n" "{\n" " color: rgb(159,126,57);\n" " text-decoration: none;\n" "}\n" "\n" "#content a:hover, #content a:active\n" "{\n" " color: rgb(255,255,255);\n" " background-color: rgb(159,126,57);\n" "}\n" "\n" "a.indexitem\n" "{\n" " display: block;\n" "}\n" "\n" "h1, h2, h3, h4, h5, h6\n" "{\n" " background-color: rgb(221,221,221);\n" " font-family: Arial, serif;\n" " font-style: normal;\n" " font-variant: normal;\n" " text-transform: none;\n" " font-weight: normal;\n" "}\n" "\n" "h1\n" "{\n" " font-size: 151%%;\n" "}\n" "\n" "h2\n" "{\n" " font-size: 142%%;\n" "}\n" "\n" "h3\n" "{\n" " font-size: 133%%;\n" "}\n" "\n" "h4\n" "{\n" " font-size: 124%%;\n" "}\n" "\n" "h5\n" "{\n" " font-size: 115%%;\n" "}\n" "\n" "h6\n" "{\n" " font-size: 106%%;\n" "}\n" "\n" "#navigation a\n" "{\n" " text-decoration: none;\n" "}\n" "\n" ".menuitem:hover\n" "{\n" " background-color: rgb(195,165,100);\n" " color: rgb(0,0,0);\n" "}\n" "\n" "#extra a\n" "{\n" " text-decoration: none;\n" "}\n" "\n" "#logo a\n" "{\n" " text-decoration: none;\n" "}\n" "\n" "#extra a:hover\n" "{\n" "}\n" "\n" "/* layout */\n" "#navigation\n" "{\n" " width: 22%%; \n" " position: relative; \n" " top: 0; \n" " right: 0; \n" " float: right; \n" " text-align: center;\n" " margin-left: 10px;\n" "}\n" "\n" ".menuitem {width: auto;}\n" "#content {width: auto;}\n" ".menuitem {display: block;}\n" "\n" "\n" ); fprintf( css_file, "div#footer\n" "{\n" " background-color: rgb(198,178,135);\n" " color: rgb(98,84,55);\n" " clear: left;\n" " width: 100%%;\n" " font-size: 71%%;\n" "}\n" "\n" "div#footer a\n" "{\n" " background-color: rgb(198,178,135);\n" " color: rgb(98,84,55);\n" "}\n" "\n" "div#footer p\n" "{\n" " margin:0;\n" " padding:5px 10px\n" "}\n" "\n" "span.keyword\n" "{\n" " color: #00F;\n" "}\n" "\n" "span.comment\n" "{\n" " color: #080;\n" "}\n" "\n" "span.quote\n" "{\n" " color: #F00;\n" "}\n" "\n" "span.squote\n" "{\n" " color: #F0F;\n" "}\n" "\n" "span.sign\n" "{\n" " color: #008B8B;\n" "}\n" "\n" "span.line_number\n" "{\n" " color: #808080;\n" "}\n" "\n" "@media print\n" "{\n" " #navigation {display: none;}\n" " #content {padding: 0px;}\n" " #content a {text-decoration: underline;}\n" "}\n" ); /** END END END Don't remove */ fclose( css_file ); } else { RB_Panic( "Can't open %s for writing\n", css_name ); } } }
RB_HTML_Color_String
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Generates various colored strings
SOURCE
static void RB_HTML_Color_String( FILE *dest_doc, int open, const char *class, const char *string ) { switch ( open ) { /* string, closing */ case 0: RB_HTML_Generate_String( dest_doc, string ); fprintf( dest_doc, "</span>" ); break; /* opening, string */ case 1: fprintf( dest_doc, "<span class=\"%s\">", class ); RB_HTML_Generate_String( dest_doc, string ); break; /* opening, string, closing */ case 2: fprintf( dest_doc, "<span class=\"%s\">", class ); RB_HTML_Generate_String( dest_doc, string ); fprintf( dest_doc, "</span>" ); break; /* opening, char, closing */ case 3: fprintf( dest_doc, "<span class=\"%s\">", class ); RB_HTML_Generate_Char( dest_doc, *string ); fprintf( dest_doc, "</span>" ); break; /* Bug */ default: assert( 0 ); } }
RB_HTML_Generate_Char
[ Top ] [ HTML_Generator ] [ Functions ]
NAME
RB_HTML_Generate_Char -- generate a single character for an item.
SYNOPSIS
void RB_HTML_Generate_Char( FILE *dest_doc, int c )
FUNCTION
This function is called for every character that goes into an item's body. This escapes all the reserved HTML characters such as '&', '<', '>', '"'.
SOURCE
{ switch ( c ) { case '\n': assert( 0 ); break; case '\t': assert( 0 ); break; case '<': fprintf( dest_doc, "<" ); break; case '>': fprintf( dest_doc, ">" ); break; case '&': fprintf( dest_doc, "&" ); break; default: /* All others are printed literally */ fputc( c, dest_doc ); } }
RB_HTML_Generate_Doc_Start
[ Top ] [ HTML_Generator ] [ Functions ]
NAME
RB_HTML_Generate_Doc_Start --
FUNCTION
Generate the first part of a HTML document. As far as ROBODoc is concerned a HTML document consists of three parts:
- The start of a document
- The body of a document
- The end of a document
SYNOPSIS
void RB_HTML_Generate_Doc_Start( FILE *dest_doc, char *src_name, char *name, char *dest_name, char *charset )
INPUTS
- dest_doc -- the output file.
- src_name -- The file or directoryname from which this document is generated.
- name -- The title for this document
- dest_name -- the name of the output file.
- charset -- the charset to be used for the file.
SOURCE
{ if ( course_of_action.do_headless ) { /* The user wants a headless document, so we skip everything * upto and until <BODY> */ } else { /* Append document type and title */ fprintf( dest_doc, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", charset ? charset : DEFAULT_CHARSET ); fprintf( dest_doc, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n" ); fprintf( dest_doc, " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" ); fprintf( dest_doc, "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" ); fprintf( dest_doc, "<head>\n" ); fprintf( dest_doc, "<meta http-equiv=\"Content-Style-Type\" content=\"text/css\" />\n" ); /* TODO is charset still needed?? */ fprintf( dest_doc, "<meta http-equiv=\"Content-type\" content=\"text/html; charset=%s\" />\n", charset ? charset : DEFAULT_CHARSET ); RB_InsertCSS( dest_doc, dest_name ); fprintf( dest_doc, "<title>%s</title>\n", name ); /* append SGML-comment with document- and copyright-info. This code * ensures that every line has an own comment to avoid problems with * buggy browsers */ fprintf( dest_doc, "<!-- Source: %s -->\n", src_name ); if ( course_of_action.do_nogenwith ) { } else { static const char copyright_text[] = COMMENT_ROBODOC /* COMMENT_COPYRIGHT */ ; size_t i = 0; char previous_char = '\n'; char current_char = copyright_text[i]; while ( current_char ) { if ( previous_char == '\n' ) { fprintf( dest_doc, "<!-- " ); } if ( current_char == '\n' ) { fprintf( dest_doc, " -->" ); } else if ( ( current_char == '-' ) && ( previous_char == '-' ) ) { /* avoid "--" inside SGML-comment, and use "-_" instead; this * looks a bit strange, but one should still be able to figure * out what is meant when reading the output */ current_char = '_'; } fputc( current_char, dest_doc ); i += 1; previous_char = current_char; current_char = copyright_text[i]; } } /* append heading and start list of links to functions */ fprintf( dest_doc, "</head>\n" ); fprintf( dest_doc, "<body>\n" ); } /* HTML_Generate_Div( dest_doc, "container" ); */ /* Generate document title if available (Thuffir) */ HTML_Generate_Div( dest_doc, "logo" ); fprintf( dest_doc, "<a name=\"robo_top_of_doc\">" ); if ( document_title ) RB_HTML_Generate_String( dest_doc, document_title ); fprintf( dest_doc, "</a>\n" ); HTML_Generate_Div_End( dest_doc, "logo" ); }
RB_HTML_Generate_Extra
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Do some additional processing to detect HTML extra's like file references and other kind of links for the documentation body of an item.
SYNOPSIS
int RB_HTML_Generate_Extra( FILE *dest_doc, enum ItemType item_type, char *cur_char, char prev_char )
INPUTS
- dest_doc -- the file to write to.
- item_type -- the kind of item the body belongs to.
- cur_char -- pointer to a substring of the item's body
- prev_char -- the character just before cur char (zero if none)
RESULTS
Number of characters produced.
SOURCE
{ char link[1024], *str; int res = -1; unsigned int i; static int incomment = 0; /* are we in comment? */ static int quote = 0; /* double quote */ static int squote = 0; /* single quote */ /* Reset comment and quote state machine if not source item */ if ( !Works_Like_SourceItem( item_type ) ) { quote = 0; squote = 0; incomment = 0; in_linecomment = 0; } /* else check for quotations and string literals */ else if ( !( incomment || in_linecomment ) ) { switch ( *cur_char ) { /* Check for quoted string literals ("string") */ case '\"': if ( !squote && course_of_action.do_quotes ) { if ( prev_char != '\\' ) { quote = !quote; RB_HTML_Color_String( dest_doc, quote, QUOTE_CLASS, "\"" ); return 0; } else if ( quote && *( ( char * ) ( cur_char - 2 ) ) == '\\' ) { quote = !quote; /* case "... \\" */ RB_HTML_Color_String( dest_doc, quote, QUOTE_CLASS, "\"" ); return 0; } } break; /* Check for single quoted string literals ('string') */ case '\'': if ( !quote && course_of_action.do_squotes ) { if ( prev_char != '\\' ) { squote = !squote; RB_HTML_Color_String( dest_doc, squote, SQUOTE_CLASS, "\'" ); return 0; } else if ( squote && *( ( char * ) ( cur_char - 2 ) ) == '\\' ) { squote = !squote; /* case '\\' */ RB_HTML_Color_String( dest_doc, squote, SQUOTE_CLASS, "\'" ); return 0; } } break; default: break; } } /* Recognise line comments */ if ( Works_Like_SourceItem( item_type ) && !incomment && !quote && !squote && course_of_action.do_line_comments ) { /* check for line comment start */ if ( !in_linecomment ) { str = Find_Parameter_Partial( & ( configuration. source_line_comments ), cur_char ); if ( str ) { in_linecomment = 1; RB_HTML_Color_String( dest_doc, in_linecomment, COMMENT_CLASS, str ); /* We found it, so exit */ return strlen( str ) - 1; } } /* The end of line comments are generated in */ /* RB_HTML_Generate_Line_Comment_End() */ } /* Recognise block comments */ if ( Works_Like_SourceItem( item_type ) && !in_linecomment && !quote && !squote && course_of_action.do_block_comments ) { /* Check for block comment start */ if ( !incomment ) { str = Find_Parameter_Partial( & ( configuration. remark_begin_markers ), cur_char ); if ( str ) { incomment = 1; RB_HTML_Color_String( dest_doc, incomment, COMMENT_CLASS, str ); /* We found it, so exit */ return strlen( str ) - 1; } } /* Check for block comment end */ else { str = Find_Parameter_Partial( &( configuration.remark_end_markers ), cur_char ); if ( str ) { incomment = 0; RB_HTML_Color_String( dest_doc, incomment, COMMENT_CLASS, str ); /* We found it, so exit */ return strlen( str ) - 1; } } } /* Do further source formating */ if ( Works_Like_SourceItem( item_type ) && !in_linecomment && !incomment && !quote && !squote ) { /* Check for keywords */ if ( configuration.keywords.number && course_of_action.do_keywords ) { char *keyword; /* Check if we are at the beginning of a word */ if ( !utf8_isalnum( prev_char ) && ( prev_char != '_' ) ) { /* Count word length */ for ( i = 1; /* A word should have at least one character... */ utf8_isalnum( cur_char[i] ) || ( cur_char[i] == '_' ); i++ ); /* Check if it is a keyword */ if ( ( keyword = Find_Keyword( cur_char, i ) ) ) { RB_HTML_Color_String( dest_doc, 2, KEYWORD_CLASS, keyword ); /* Exit function */ return i - 1; } } } /* Do some fancy coloration for non-alphanumeric chars */ if ( !utf8_isalnum( *cur_char ) && *cur_char != '_' && *cur_char != ' ' && course_of_action.do_non_alpha ) { RB_HTML_Color_String( dest_doc, 3, SIGN_CLASS, cur_char ); return 0; } } /* Check for links, etc... */ if ( incomment || in_linecomment || !Works_Like_SourceItem( item_type ) ) { if ( strncmp( "http://", cur_char, 7 ) == 0 ) { sscanf( cur_char, "%s", link ); RB_Say( "found link %s\n", SAY_DEBUG, link ); res = ( strlen( link ) - 1 ); /* [ 697247 ] http://body. does not skip the '.' */ if ( link[( strlen( link ) - 1 )] == '.' ) { link[( strlen( link ) - 1 )] = '\0'; fprintf( dest_doc, "<a href=\"%s\">%s</a>.", link, link ); } else { fprintf( dest_doc, "<a href=\"%s\">%s</a>", link, link ); } } else if ( strncmp( "href:", cur_char, 5 ) == 0 ) { /* * handy in relative hyperlink paths, e.g. * ../../modulex/ */ sscanf( ( cur_char + 5 ), "%s", link ); RB_Say( "found link %s\n", SAY_DEBUG, link ); res = ( strlen( link ) + 4 ); fprintf( dest_doc, "<a href=\"%s\">%s</a>", link, link ); } else if ( strncmp( "file:/", cur_char, strlen( "file:/" ) ) == 0 ) { sscanf( cur_char, "%s", link ); RB_Say( "found link %s\n", SAY_DEBUG, link ); res = ( strlen( link ) - 1 ); fprintf( dest_doc, "<a href=\"%s\">%s</a>", link, link ); } else if ( strncmp( "mailto:", cur_char, 7 ) == 0 ) { sscanf( ( cur_char + 7 ), "%s", link ); RB_Say( "found mail to %s\n", SAY_DEBUG, link ); res = ( strlen( link ) + 6 ); fprintf( dest_doc, "<a href=\"mailto:%s\">%s</a>", link, link ); } else if ( strncmp( "image:", cur_char, 6 ) == 0 ) { sscanf( ( cur_char + 6 ), "%s", link ); RB_Say( "found image %s\n", SAY_DEBUG, link ); res = ( strlen( link ) + 5 ); fprintf( dest_doc, "<img src=\"%s\">", link ); } } return res; }
RB_HTML_Generate_Index_Page
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Generate a single file with a index table for headers of one specific type of headers
SYNOPSIS
void RB_HTML_Generate_Index_Page( struct RB_Document *document, struct RB_HeaderType *header_type )
INPUTS
- document -- the document
- header_type -- the type for which the table is to be generated.
RB_HTML_Generate_IndexMenu
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Generates a menu to jump to the various master index files for the various header types. The menu is generated for each of the master index files. The current header type is highlighted.
SYNOPSIS
void RB_HTML_Generate_IndexMenu( FILE *dest_doc, char *filename, struct RB_Document *document, struct RB_HeaderType *cur_type ) /* TODO Use cur_type */
INPUTS
- dest_doc -- the output file.
- filename -- the name of the output file
- document -- the gathered documention.
- cur_headertype -- the header type that is to be highlighted.
RB_HTML_Generate_Item_Line_Number
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Generate line numbers for SOURCE like items
SYNOPSIS
void RB_HTML_Generate_Item_Line_Number( FILE *dest_doc, char *line_number_string )
INPUTS
- dest_doc -- the file to write to.
- line_number_string -- the line number as string.
SOURCE
{ RB_HTML_Color_String( dest_doc, 2, LINE_NUMBER_CLASS, line_number_string ); }
RB_HTML_Generate_Label
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Generate a label (name) that can be refered too. A label should consist of only alphanumeric characters so all 'odd' characters are replaced with their ASCII code in hex format.
SYNOPSIS
void RB_HTML_Generate_Label( FILE *dest_doc, char *name )
INPUTS
- dest_doc -- the file to write it to.
- name -- the name of the label.
SOURCE
{ int i; int l = strlen( name ); unsigned char c; fprintf( dest_doc, "<a name=\"" ); for ( i = 0; i < l; ++i ) { c = name[i]; if ( utf8_isalnum( c ) ) { RB_HTML_Generate_Char( dest_doc, c ); } else { char buf[4]; sprintf( buf, "%02x", c ); RB_HTML_Generate_Char( dest_doc, buf[0] ); RB_HTML_Generate_Char( dest_doc, buf[1] ); } } fprintf( dest_doc, "\"></a>\n" ); }
RB_HTML_Generate_Line_Comment_End
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Check if a line comment is active and generate ending sequence for it. Should be called at the end of each SOURCE line.
SYNOPSIS
void RB_HTML_Generate_Line_Comment_End( FILE *dest_doc ) { /* Check if we are in a line comment */ if ( in_linecomment ) { /* and end the line comment */ in_linecomment = 0; RB_HTML_Color_String( dest_doc, in_linecomment, COMMENT_CLASS, "" ); } }
RB_HTML_Generate_Link
[ Top ] [ HTML_Generator ] [ Functions ]
NAME
RB_HTML_Generate_Link --
SYNOPSIS
void RB_HTML_Generate_Link( FILE *cur_doc, char *cur_name, char *filename, char *labelname, char *linkname, char *classname )
INPUTS
cur_doc -- the file to which the text is written cur_name -- the name of the destination file
(the file from which we link)
filename -- the name of the file that contains the link
(the file we link to)
labelname-- the name of the unique label of the link. linkname -- the name of the link as shown to the user.
SOURCE
{ if ( classname ) { fprintf( cur_doc, "<a class=\"%s\" ", classname ); } else { fprintf( cur_doc, "<a " ); } if ( filename && strcmp( filename, cur_name ) ) { char *r = RB_HTML_RelativeAddress( cur_name, filename ); fprintf( cur_doc, "href=\"%s#%s\">", r, labelname ); RB_HTML_Generate_String( cur_doc, linkname ); fprintf( cur_doc, "</a>" ); } else { fprintf( cur_doc, "href=\"#%s\">", labelname ); RB_HTML_Generate_String( cur_doc, linkname ); fprintf( cur_doc, "</a>" ); } }
RB_HTML_Generate_TOC_Section
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Create a table of contents based on the hierarchy of the headers starting for a particular point in this hierarchy (the parent).
SYNOPSIS
void RB_HTML_Generate_TOC_Section( FILE *dest_doc, char *dest_name, struct RB_header *parent, struct RB_header **headers, int count, int depth )
INPUTS
- dest_doc -- the file to write to.
- dest_name -- the name of this file.
- parent -- the parent of the headers for which the the current level(depth) of TOC is created.
- headers -- an array of headers for which the TOC is created
- count -- the number of headers in this array
- depth -- the current depth of the TOC
NOTES
This is a recursive function and tricky stuff.
SOURCE
{ struct RB_header *header; int i, n, once = 0; ++sectiontoc_counters[depth]; for ( i = depth + 1; i < MAX_SECTION_DEPTH; ++i ) { sectiontoc_counters[i] = 0; } /* List item start */ fprintf( dest_doc, "<li>" ); /* Do not generate section numbers if sectionnameonly */ if ( !( course_of_action.do_sectionnameonly ) ) { for ( i = 1; i <= depth; ++i ) { fprintf( dest_doc, "%d.", sectiontoc_counters[i] ); } fprintf( dest_doc, " " ); } /* Generate Link to first reference name */ RB_HTML_Generate_Link( dest_doc, dest_name, parent->file_name, parent->unique_name, /* only generate function name if sectionnameonly */ ( course_of_action.do_sectionnameonly ) ? parent->function_name : parent->name, 0 ); /* Generate links to further reference names */ for ( n = 1; n < parent->no_names; n++ ) { RB_HTML_Generate_String( dest_doc, ", " ); RB_HTML_Generate_Link( dest_doc, dest_name, parent->file_name, parent->unique_name, parent->names[n], 0 ); } /* List item end */ fprintf( dest_doc, "</li>\n" ); for ( i = 0; i < count; ++i ) { header = headers[i]; if ( header->parent == parent ) { /* Generate better TOC level hiearchy (Thuffir) */ /* We only generate <ul> once for a level */ if ( !once ) { once = 1; fprintf( dest_doc, "<ul>\n" ); } RB_HTML_Generate_TOC_Section( dest_doc, dest_name, header, headers, count, depth + 1 ); } else { /* Empty */ } } /* If we have generated an <ul> before, generate the closing one too. */ if ( once ) fprintf( dest_doc, "</ul>\n" ); }
RB_HTML_RelativeAddress
[ Top ] [ HTML_Generator ] [ Functions ]
FUNCTION
Link to 'that' from 'this' computing the relative path. Here 'this' and 'that' are both paths. This function is used to create links from one document to another document that might be in a completely different directory.
SYNOPSIS
char *RB_HTML_RelativeAddress( char *thisname, char *thatname )
EXAMPLE
The following two
this /sub1/sub2/sub3/f.html that /sub1/sub2/g.html
result in
../g.html
this /sub1/f.html that /sub1/sub2/g.html == ./sub2/g.html
this /sub1/f.html that /sub1/g.html == ./g.html
this /sub1/doc3/doc1/tt.html that /sub1/doc5/doc2/qq.html == ../../doc5/doc2/qq.html
NOTES
Notice the execelent docmentation.
SOURCE
#define MAX_RELATIVE_SIZE 1024 { static char relative[MAX_RELATIVE_SIZE + 1]; char *i_this; char *i_that; char *i_this_slash = NULL; char *i_that_slash = NULL; relative[0] = '\0'; assert( thisname ); assert( thatname ); for ( i_this = thisname, i_that = thatname; ( *i_this && *i_that ) && ( *i_this == *i_that ); ++i_this, ++i_that ) { if ( *i_this == '/' ) { i_this_slash = i_this; } if ( *i_that == '/' ) { i_that_slash = i_that; } } if ( i_this_slash && i_that_slash ) { int this_slashes_left = 0; int that_slashes_left = 0; char *i_c; for ( i_c = i_this_slash + 1; *i_c; ++i_c ) { if ( *i_c == '/' ) { ++this_slashes_left; } } for ( i_c = i_that_slash + 1; *i_c; ++i_c ) { if ( *i_c == '/' ) { ++that_slashes_left; } } if ( this_slashes_left ) { int i; for ( i = 0; i < this_slashes_left; ++i ) { strcat( relative, "../" ); } strcat( relative, i_that_slash + 1 ); } else if ( that_slashes_left ) { /* !this_slashes_left && that_slashes_left */ strcat( relative, "./" ); strcat( relative, i_that_slash + 1 ); } else { /* !this_slashes_left && !that_slashes_left */ strcat( relative, "./" ); strcat( relative, i_that_slash + 1 ); } } return relative; }