/* Copyright (C) 1994-2007 Frans Slothouber, Jacco van Weert, Petteri Kettunen, Bernd Koesling, Thomas Aglassinger, Anthon Pang, Stefan Kost, David Druffner, Sasha Vasko, Kai Hofmann, Thierry Pierron, Friedrich Haase, and Gergely Budai. This file is part of ROBODoc ROBODoc is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /****h* ROBODoc/HTML_Generator * 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 ******* * $Id: html_generator.c,v 1.91 2007/07/10 19:13:51 gumpu Exp $ */ #include #include #include #include #include #include "html_generator.h" #include "util.h" #include "globals.h" #include "robodoc.h" #include "links.h" #include "headers.h" #include "headertypes.h" #include "generator.h" #include "items.h" #include "string.h" #include "document.h" #include "directory.h" #include "path.h" #include "part.h" #include "roboconfig.h" #ifdef DMALLOC #include #endif static char *css_name = NULL; static int in_linecomment = 0; // are we in a line comment? static void RB_HTML_Generate_String( FILE *dest_doc, const char *a_string ); /* TODO Documentation */ static void HTML_Generate_Div( FILE *dest_doc, char *id ) { fprintf( dest_doc, "
\n", id ); } /* TODO Documentation */ static void HTML_Generate_Div_End( FILE *dest_doc, char *id ) { fprintf( dest_doc, "
\n", id ); } /* TODO Documentation */ char *HTML_TOC_Index_Filename( struct RB_Document *document ) { char *toc_index_path = NULL; char *toc_index_name = "toc_index.html"; assert( document->docroot->name ); toc_index_path = calloc( strlen( toc_index_name ) + 2 + strlen( document->docroot->name ), 1 ); strcpy( toc_index_path, document->docroot->name ); strcat( toc_index_path, toc_index_name ); return toc_index_path; } /* TODO Documentation */ static void RB_HTML_Generate_Source_Tree_Entry( FILE *dest_doc, char *dest_name, struct RB_Path *parent_path, struct RB_Directory *srctree, struct RB_Document *document ) { struct RB_Path *cur_path; struct RB_Filename *cur_filename; fprintf( dest_doc, "
    \n" ); for ( cur_filename = srctree->first; cur_filename; cur_filename = cur_filename->next ) { if ( cur_filename->path == parent_path ) { char *r = 0; if ( cur_filename->link ) { if ( document->actions.do_one_file_per_header ) { fprintf( dest_doc, "
  • \n" ); RB_HTML_Generate_String( dest_doc, cur_filename->name ); fprintf( dest_doc, "
  • \n" ); } else { r = RB_HTML_RelativeAddress( dest_name, cur_filename->link-> file_name ); fprintf( dest_doc, "
  • \n" ); fprintf( dest_doc, "\n", r, cur_filename->link->label_name ); RB_HTML_Generate_String( dest_doc, cur_filename->name ); fprintf( dest_doc, "
  • \n" ); } } } } for ( cur_path = srctree->first_path; cur_path; cur_path = cur_path->next ) { if ( cur_path->parent == parent_path ) { fprintf( dest_doc, "
  • \n" ); RB_HTML_Generate_String( dest_doc, cur_path->name ); RB_HTML_Generate_Source_Tree_Entry( dest_doc, dest_name, cur_path, srctree, document ); fprintf( dest_doc, "
  • \n" ); } } fprintf( dest_doc, "
\n" ); } /* TODO Documentation */ void RB_HTML_Generate_Source_Tree( FILE *dest_doc, char *dest_name, struct RB_Document *document ) { struct RB_Directory *srctree; srctree = document->srctree; RB_HTML_Generate_Source_Tree_Entry( dest_doc, dest_name, NULL, srctree, document ); } /****if* HTML_Generator/RB_HTML_Generate_String * FUNCTION * Write a string to the destination document, escaping * characters where necessary. * SYNOPSIS */ static void RB_HTML_Generate_String( FILE *dest_doc, const char *a_string ) /* * INPUTS * o dest_doc -- the file the characters are written too * o a_string -- a nul terminated string. * SEE ALSO * RB_HTML_Generate_Char() * SOURCE */ { int i; int l = strlen( a_string ); unsigned char c; for ( i = 0; i < l; ++i ) { c = a_string[i]; RB_HTML_Generate_Char( dest_doc, c ); } } /*******/ /****if* HTML_Generator/RB_HTML_Generate_False_Link * FUNCTION * Create a representation for a link that links an word in * a header to the header itself. * SYNOPSIS */ void RB_HTML_Generate_False_Link( FILE *dest_doc, char *name ) /* * INPUTS * * dest_doc -- the file the representation is written to. * * name -- the word. * SOURCE */ { fprintf( dest_doc, "" ); RB_HTML_Generate_String( dest_doc, name ); fprintf( dest_doc, "" ); } /*******/ /****f* HTML_Generator/RB_HTML_Color_String * 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, "" ); break; // opening, string case 1: fprintf( dest_doc, "", class ); RB_HTML_Generate_String( dest_doc, string ); break; // opening, string, closing case 2: fprintf( dest_doc, "", class ); RB_HTML_Generate_String( dest_doc, string ); fprintf( dest_doc, "" ); break; // opening, char, closing case 3: fprintf( dest_doc, "", class ); RB_HTML_Generate_Char( dest_doc, *string ); fprintf( dest_doc, "" ); break; // Bug default: assert( 0 ); } } /*******/ /****f* HTML_Generator/RB_HTML_Generate_Line_Comment_End * 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, "" ); } } /*******/ /****f* HTML_Generator/RB_HTML_Generate_Extra * 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 * o dest_doc -- the file to write to. * o item_type -- the kind of item the body belongs to. * o cur_char -- pointer to a substring of the item's body * o 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, "%s.", link, link ); } else { fprintf( dest_doc, "%s", link, link ); } } else if ( strncmp( "href:", cur_char, 5 ) == 0 ) { /* * handy in relative hyperlink paths, e.g. * href:../../modulex/ */ sscanf( ( cur_char + 5 ), "%s", link ); RB_Say( "found link %s\n", SAY_DEBUG, link ); res = ( strlen( link ) + 4 ); fprintf( dest_doc, "%s", 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, "%s", 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, "%s", 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, "", link ); } } return res; } /******/ void RB_HTML_Generate_Item_Name( FILE *dest_doc, char *name ) { fprintf( dest_doc, "

" ); RB_HTML_Generate_String( dest_doc, name ); fprintf( dest_doc, "

\n" ); } void RB_HTML_Generate_Item_Begin( FILE *dest_doc, char *name ) { USE( dest_doc ); USE( name ); /* empty */ } void RB_HTML_Generate_Item_End( FILE *dest_doc, char *name ) { USE( dest_doc ); USE( name ); /* empty */ } int sectiontoc_counters[MAX_SECTION_DEPTH]; /****f* HTML_Generator/RB_HTML_Generate_TOC_Section * 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 * o dest_doc -- the file to write to. * o dest_name -- the name of this file. * o parent -- the parent of the headers for which the the * current level(depth) of TOC is created. * o headers -- an array of headers for which the TOC is created * o count -- the number of headers in this array * o 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, "
  • " ); // 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, "
  • \n" ); for ( i = 0; i < count; ++i ) { header = headers[i]; if ( header->parent == parent ) { // Generate better TOC level hiearchy (Thuffir) // We only generate
      once for a level if ( !once ) { once = 1; fprintf( dest_doc, "
        \n" ); } RB_HTML_Generate_TOC_Section( dest_doc, dest_name, header, headers, count, depth + 1 ); } else { /* Empty */ } } // If we have generated an
          before, generate the closing one too. if ( once ) fprintf( dest_doc, "
        \n" ); } /*******/ void RB_HTML_Generate_TOC_Entries( FILE *dest_doc, struct RB_header **headers, int count, struct RB_Part *owner, char *dest_name ) { struct RB_header *header; char *object_name, *label_name, *file_name; int i, j; // fprintf( dest_doc, "

        Table of Contents

        \n" ); fprintf( dest_doc, "

        TABLE OF CONTENTS

        \n" ); fprintf( dest_doc, "
          \n" ); for ( i = count - 1; i >= 0; i-- ) { header = headers[i]; if ( header->htype->typeCharacter != 'h' && !strcmp( owner->filename->name, header->owner->filename->name ) && Find_Link( header->function_name, &object_name, &label_name, &file_name ) ) { for ( j = 0; j < header->no_names; j++ ) { fprintf( dest_doc, "
        • " ); RB_HTML_Generate_Link( dest_doc, dest_name, file_name, "", object_name, 0); fprintf( dest_doc, "
        • \n" ); } } } fprintf( dest_doc, "
        \n" ); } void RB_HTML_Generate_TOC_2( FILE *dest_doc, struct RB_header **headers, int count, struct RB_Part *owner, char *dest_name ) { struct RB_header *header; int i, j; int depth = 1; for ( i = 0; i < MAX_SECTION_DEPTH; ++i ) { sectiontoc_counters[i] = 0; } fprintf( dest_doc, "

        TABLE OF CONTENTS

        \n" ); if ( course_of_action.do_sections ) { /* --sections was specified, create a TOC based on the * hierarchy of the headers. */ fprintf( dest_doc, "
          \n" ); for ( i = 0; i < count; ++i ) { header = headers[i]; if ( owner == NULL ) { if ( header->parent ) { /* Will be done in the subfunction */ } else { RB_HTML_Generate_TOC_Section( dest_doc, dest_name, header, headers, count, depth ); } } else { /* This is the TOC for a specific RB_Part (MultiDoc * documentation). We only include the headers that * are part of the subtree. That is, headers that are * parth the RB_Part, or that are childern of the * headers in the RB_Part. */ if ( header->owner == owner ) { /* BUG 721690 */ /* Any of the parents of this header should not * have the same owner as this header, otherwise * this header will be part of the TOC multiple times. */ int no_bad_parent = TRUE; struct RB_header *parent = header->parent; for ( ; parent; parent = parent->parent ) { if ( parent->owner == owner ) { no_bad_parent = FALSE; break; } } if ( no_bad_parent ) { RB_HTML_Generate_TOC_Section( dest_doc, dest_name, header, headers, count, depth ); } } } } fprintf( dest_doc, "
        \n" ); } else { /* No --section option, generate a plain, one-level * TOC */ fprintf( dest_doc, "
          \n" ); for ( i = 0; i < count; ++i ) { header = headers[i]; if ( header->name && header->function_name && ( ( owner == NULL ) || ( header->owner == owner ) ) ) { for ( j = 0; j < header->no_names; j++ ) { fprintf( dest_doc, "
        • " ); RB_HTML_Generate_Link( dest_doc, dest_name, header->file_name, header->unique_name, header->names[j], 0 ); fprintf( dest_doc, "
        • \n" ); } } } fprintf( dest_doc, "
        \n" ); } } /****f* HTML_Generator/RB_HTML_Generate_Label * 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 * o dest_doc -- the file to write it to. * o name -- the name of the label. * SOURCE */ { int i; int l = strlen( name ); unsigned char c; fprintf( dest_doc, "\n" ); } /********/ static int section_counters[MAX_SECTION_DEPTH]; /* TODO Documentation */ void RB_HTML_Generate_BeginSection( FILE *dest_doc, int depth, char *name, struct RB_header *header ) { int i; ++section_counters[depth]; for ( i = depth + 1; i < MAX_SECTION_DEPTH; ++i ) { section_counters[i] = 0; } switch ( depth ) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: fprintf( dest_doc, "", depth ); // Only generate section numbers if no sectionnameonly if ( !( course_of_action.do_sectionnameonly ) ) { for ( i = 1; i <= depth; ++i ) { fprintf( dest_doc, "%d.", section_counters[i] ); } fprintf( dest_doc, " " ); } // Print Header "first" name RB_HTML_Generate_String( dest_doc, name ); // Print further names for ( i = 1; i < header->no_names; i++ ) { fprintf( dest_doc, ( i % header_breaks ) ? ", " : ",
        " ); RB_HTML_Generate_String( dest_doc, header->names[i] ); } // Include module name if not sectionnameonly if ( !( course_of_action.do_sectionnameonly ) ) { fprintf( dest_doc, " [ " ); RB_HTML_Generate_String( dest_doc, header->htype->indexName ); fprintf( dest_doc, " ]" ); } fprintf( dest_doc, "
        \n", depth ); break; default: /* too deep, don't do anything. */ assert( 0 ); } } void RB_HTML_Generate_EndSection( FILE *dest_doc, int depth, char *name ) { USE( dest_doc ); USE( name ); USE( depth ); /* Empty */ } char *RB_HTML_Get_Default_Extension( void ) { return ( ".html" ); } /****f* HTML_Generator/RB_HTML_Generate_Doc_Start * 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 * o dest_doc -- the output file. * o src_name -- The file or directoryname from which * this document is generated. * o name -- The title for this document * o dest_name -- the name of the output file. * o 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 */ } else { /* Append document type and title */ fprintf( dest_doc, "\n", charset ? charset : DEFAULT_CHARSET ); fprintf( dest_doc, "\n" ); fprintf( dest_doc, "\n" ); fprintf( dest_doc, "\n" ); fprintf( dest_doc, "\n" ); /* TODO is charset still needed?? */ fprintf( dest_doc, "\n", charset ? charset : DEFAULT_CHARSET ); RB_InsertCSS( dest_doc, dest_name ); fprintf( dest_doc, "%s\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, "\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, "" ); } 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, "\n" ); fprintf( dest_doc, "\n" ); } // HTML_Generate_Div( dest_doc, "container" ); /* Use user specified header if present */ if ( document_header ) { fprintf ( dest_doc, document_header ); } else { /* Generate document title if available (Thuffir) */ HTML_Generate_Div( dest_doc, "logo" ); fprintf( dest_doc, "
        " ); if ( document_title ) RB_HTML_Generate_String( dest_doc, document_title ); fprintf( dest_doc, "\n" ); HTML_Generate_Div_End( dest_doc, "logo" ); } } /******/ /* TODO */ /*x**if* HTML_Generator/RB_HTML_Generate_Doc_End * NAME * RB_HTML_Generate_Doc_End -- * FUNCTION * Close of the document with the proper end tags. ****** */ void RB_HTML_Generate_Doc_End( FILE *dest_doc, char *name, char *src_name ) { USE( name ); /* Use user specified footer if present */ if ( document_footer ) { fprintf ( dest_doc, document_footer ); } else { HTML_Generate_Div( dest_doc, "footer" ); /* TODO This should be done with * RB_Generate_Label() */ if ( course_of_action.do_nogenwith ) { fprintf( dest_doc, "

        Generated from %s on ", src_name ); RB_TimeStamp( dest_doc ); fprintf( dest_doc, "

        \n" ); } else { fprintf( dest_doc, "

        Generated from %s with ROBODoc V%s on ", src_name, VERSION ); RB_TimeStamp( dest_doc ); fprintf( dest_doc, "

        \n" ); } HTML_Generate_Div_End( dest_doc, "footer" ); } // HTML_Generate_Div_End( dest_doc, "container" ); if ( course_of_action.do_footless ) { /* The user does not want the foot of the * document. */ } else { fprintf( dest_doc, "\n\n" ); } } void RB_HTML_Generate_Nav_Bar( struct RB_Document *document, FILE *current_doc, struct RB_header *current_header ) { char *current_filename = NULL; char *target_filename = NULL; char *label = NULL; char *label_name = NULL; current_filename = RB_Get_FullDocname( current_header->owner->filename ); target_filename = RB_Get_FullDocname( current_header->owner->filename ); label = Get_Fullname( current_header->owner->filename ); /* The navigation bar */ fprintf( current_doc, "

        " ); // [ Top ] fprintf( current_doc, "[ " ); RB_HTML_Generate_Link( current_doc, current_filename, NULL, "robo_top_of_doc", "Top", 0 ); fprintf( current_doc, " ] " ); // [ "Parentname" ] if ( current_header->parent ) { fprintf( current_doc, "[ " ); target_filename = RB_Get_FullDocname( current_header->parent->owner->filename ); label = current_header->parent->unique_name; label_name = current_header->parent->function_name; RB_HTML_Generate_Link( current_doc, current_filename, target_filename, label, label_name, 0 ); fprintf( current_doc, " ] " ); } // [ "Modulename" ] fprintf( current_doc, "[ " ); label_name = current_header->htype->indexName; if ( ( course_of_action.do_index ) && ( course_of_action.do_multidoc ) ) { target_filename = RB_Get_SubIndex_FileName( document->docroot->name, document->extension, current_header->htype ); RB_HTML_Generate_Link( current_doc, current_filename, target_filename, "robo_top_of_doc", label_name, 0 ); free( target_filename ); } else { RB_HTML_Generate_String( current_doc, label_name ); } fprintf( current_doc, " ]

        \n" ); } /* TODO Documentation */ void RB_HTML_Generate_Nav_Bar_One_File_Per_Header( struct RB_Document *document, FILE *current_doc, struct RB_header *current_header ) { char *current_filename = NULL; char *target_filename = NULL; char *label = NULL; char *label_name = NULL; current_filename = RB_Get_FullDocname( current_header->owner->filename ); target_filename = RB_Get_FullDocname( current_header->owner->filename ); label = Get_Fullname( current_header->owner->filename ); /* The navigation bar */ if ( current_header->parent ) { target_filename = RB_Get_FullDocname( current_header->parent->owner->filename ); label = current_header->parent->unique_name; label_name = current_header->parent->function_name; RB_HTML_Generate_Link( current_doc, current_filename, target_filename, label, label_name, "menuitem" ); } /* FS TODO one_file_per_header without index is not logical */ if ( ( course_of_action.do_index ) && ( course_of_action.do_multidoc ) ) { target_filename = RB_Get_SubIndex_FileName( document->docroot->name, document->extension, current_header->htype ); label_name = current_header->htype->indexName; RB_HTML_Generate_Link( current_doc, current_filename, target_filename, "robo_top_of_doc", label_name, "menuitem" ); free( target_filename ); } } /* TODO Documentation */ /*x**if* HTML_Generator/RB_HTML_Generate_Header_Start * NAME * RB_HTML_Generate_Header_Start -- ****** */ void RB_HTML_Generate_Header_Start( FILE *dest_doc, struct RB_header *cur_header ) { struct RB_HeaderType *header_type; int i; if ( cur_header->name && cur_header->function_name ) { /* fprintf( dest_doc, "
        \n" ); */ RB_HTML_Generate_Label( dest_doc, cur_header->name ); fprintf( dest_doc, "

        ", cur_header->unique_name ); header_type = RB_FindHeaderType( cur_header->htype->typeCharacter ); for ( i = 1; i <= cur_header->no_names; i++ ) { // If Section names only, do not print module name if ( i == 1 && ( course_of_action.do_sectionnameonly ) ) RB_HTML_Generate_String( dest_doc, cur_header->function_name ); else RB_HTML_Generate_String( dest_doc, cur_header->names[i - 1] ); // Break lines after a predefined number of header names if ( i < cur_header->no_names ) fprintf( dest_doc, ( i % header_breaks ) ? ", " : ",
        " ); } // Print header type (if available and not Section names only) if ( header_type && !( course_of_action.do_sectionnameonly ) ) { fprintf( dest_doc, " [ " ); RB_HTML_Generate_String( dest_doc, header_type->indexName ); fprintf( dest_doc, " ]" ); } fprintf( dest_doc, "

        \n\n" ); } } /* TODO */ /*x**f* HTML_Generator/RB_HTML_Generate_Header_End * NAME * RB_HTML_Generate_Header_End -- ****** */ void RB_HTML_Generate_Header_End( FILE *dest_doc, struct RB_header *cur_header ) { USE( cur_header ); fprintf( dest_doc, "\n" ); } /****f* HTML_Generator/RB_HTML_Generate_IndexMenu * 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. ****** */ { unsigned char type_char; char *toc_index_path = NULL; USE( cur_type ); /* TODO FS make use of this */ assert( dest_doc ); assert( filename ); assert( document ); toc_index_path = HTML_TOC_Index_Filename( document ); RB_HTML_Generate_Link( dest_doc, filename, toc_index_path, "top", "Table of Contents", "menuitem" ); free( toc_index_path ); fprintf( dest_doc, "\n" ); for ( type_char = MIN_HEADER_TYPE; type_char < MAX_HEADER_TYPE; ++type_char ) { struct RB_HeaderType *header_type; int n; header_type = RB_FindHeaderType( type_char ); if ( header_type ) { n = RB_Number_Of_Links( header_type, NULL, FALSE ) + RB_Number_Of_Links( header_type, NULL, TRUE ); if ( n ) { char *targetfilename = 0; targetfilename = RB_Get_SubIndex_FileName( document->docroot->name, document->extension, header_type ); assert( targetfilename ); RB_HTML_Generate_Link( dest_doc, filename, targetfilename, "top", header_type->indexName, "menuitem" ); free( targetfilename ); fprintf( dest_doc, "\n" ); } } } } /****f* HTML_Generator/RB_HTML_Generate_Header_IndexMenu * FUNCTION * Generates a menu to jump to the header's entries. The menu is * generated for each entry file. * SYNOPSIS */ void RB_HTML_Generate_Header_IndexMenu( FILE *dest_doc, char *filename, struct RB_Document *document, struct RB_Part *owner, 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. ****** */ { struct RB_header *header; char *object_name, *label_name, *file_name; int i, j; for ( i = document->no_headers - 1; i >= 0; i-- ) { header = document->headers[i]; if ( !strcmp( owner->filename->name, header->owner->filename->name ) && ( header->htype->typeCharacter == 'h' || Find_Link( header->function_name, &object_name, &label_name, &file_name ) ) ) { for ( j = 0; j < header->no_names; j++ ) { if ( header->htype->typeCharacter == 'h' ) { RB_HTML_Generate_Link( dest_doc, filename, header->owner->filename->docname, NULL, header->function_name, "menuitem" ); fprintf( dest_doc, "\n" ); } else { RB_HTML_Generate_Link( dest_doc, filename, file_name, "", object_name, "menuitem" ); fprintf( dest_doc, "\n" ); } } } } } /****f* HTML_Generator/RB_HTML_Generate_Module_IndexMenu * FUNCTION * Generates a menu to jump to the different modules. The menu is * generated for each header file. * SYNOPSIS */ void RB_HTML_Generate_Module_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. ****** */ { struct RB_Part *i_part; for ( i_part = document->parts; i_part != NULL; i_part = i_part->next ) { if ( !i_part->headers || i_part->headers[0].htype->typeCharacter != 'h' || !strcmp(i_part->headers[0].function_name, "ROBODoc Cascading Style Sheet") ) continue; RB_HTML_Generate_Link( dest_doc, filename, i_part->filename->docname, NULL, i_part->headers[0].function_name, "menuitem" ); fprintf( dest_doc, "\n" ); } } /****f* HTML_Generator/RB_HTML_Generate_Index_Page * 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 * o document -- the document * o header_type -- the type for which the table is to * be generated. ****** */ { char *filename = 0; FILE *file; assert( document ); assert( header_type ); filename = RB_Get_SubIndex_FileName( document->docroot->name, document->extension, header_type ); assert( filename ); file = fopen( filename, "w" ); if ( !file ) { RB_Panic( "can't open (%s)!\n", filename ); } else { /* File opened, now we generate an index * for the specified header type */ RB_HTML_Generate_Doc_Start( file, document->srcroot->name, header_type->indexName, filename, document->charset ); /* breadcrumbtrail */ HTML_Generate_Begin_Extra( file ); /* No content for extra section yet... */ HTML_Generate_End_Extra( file ); /* Menu for navigation */ HTML_Generate_Begin_Navigation( file ); RB_HTML_Generate_IndexMenu( file, filename, document, header_type ); HTML_Generate_End_Navigation( file ); /* Content */ HTML_Generate_Begin_Content( file ); if ( RB_CompareHeaderTypes ( header_type, RB_FindHeaderType( HT_SOURCEHEADERTYPE ) ) && ( header_type->typeCharacter != HT_MASTERINDEXTYPE ) ) { RB_HTML_Generate_Source_Tree( file, filename, document ); } else { RB_HTML_Generate_Index_Table( file, filename, header_type, header_type->indexName ); } HTML_Generate_End_Content( file ); RB_HTML_Generate_Doc_End( file, filename, document->srcroot->name ); fclose( file ); } free( filename ); } /* Create an index page that contains only the table of content */ void HTML_Generate_TOC_Index_Page( struct RB_Document *document ) { FILE *file = NULL; char *toc_index_path = HTML_TOC_Index_Filename( document ); file = fopen( toc_index_path, "w" ); if ( !file ) { RB_Panic( "can't open (%s)!\n", toc_index_path ); } else { RB_HTML_Generate_Doc_Start( file, document->srcroot->name, "Table of Contents", toc_index_path, document->charset ); /* breadcrumbtrail */ HTML_Generate_Begin_Extra( file ); /* No content for extra section yet... */ HTML_Generate_End_Extra( file ); /* Menu for navigation */ HTML_Generate_Begin_Navigation( file ); RB_HTML_Generate_IndexMenu( file, toc_index_path, document, NULL ); HTML_Generate_End_Navigation( file ); /* Content */ HTML_Generate_Begin_Content( file ); RB_Generate_TOC_2( file, document->headers, document->no_headers, NULL, toc_index_path ); HTML_Generate_End_Content( file ); /* End part */ RB_HTML_Generate_Doc_End( file, toc_index_path, document->srcroot->name ); fclose( file ); } free( toc_index_path ); } /* TODO */ /*x**if* HTML_Generator/RB_HTML_Generate_Index * NAME * RB_HTML_Generate_Index -- ****** */ /* Should be called indexes */ void RB_HTML_Generate_Index( struct RB_Document *document ) { unsigned char type_char = 0; assert( document ); for ( type_char = MIN_HEADER_TYPE; type_char < MAX_HEADER_TYPE; ++type_char ) { struct RB_HeaderType *header_type; int n; header_type = RB_FindHeaderType( type_char ); if ( header_type ) { n = RB_Number_Of_Links( header_type, NULL, FALSE ) + RB_Number_Of_Links( header_type, NULL, TRUE ); if ( n ) { /* There are headers of this type, so create an index page * for them */ RB_HTML_Generate_Index_Page( document, header_type ); } } } RB_HTML_Generate_Index_Page( document, RB_FindHeaderType( HT_MASTERINDEXTYPE ) ); HTML_Generate_TOC_Index_Page( document ); } void RB_HTML_Generate_Table_Body( FILE *dest, char *dest_name, struct RB_HeaderType *type, int internal ) { struct RB_link *cur_link; unsigned int i; char first_char = ' '; int found = FALSE; /* Compute the number of columns we need for * this type of header. */ for ( i = 0; i < link_index_size; ++i ) { cur_link = link_index[i]; if ( cur_link->htype && RB_CompareHeaderTypes( cur_link->htype, type ) && ( ( cur_link->is_internal && internal ) || ( !cur_link->is_internal && !internal ) ) ) { char *r = 0; r = RB_HTML_RelativeAddress( dest_name, cur_link->file_name ); if ( toupper( cur_link->object_name[0] ) != first_char ) { first_char = toupper( cur_link->object_name[0] ); if ( found ) { // fprintf( dest, "\n" ); } fprintf( dest, "

        ", first_char ); RB_HTML_Generate_Char( dest, first_char ); fprintf( dest, "

        " ); // fprintf( dest, "
        \n" ); found = TRUE; } fprintf( dest, "", r, cur_link->label_name ); RB_HTML_Generate_String( dest, cur_link->object_name ); fprintf( dest, "\n" ); } } if ( found ) { // fprintf( dest, "
        \n" ); } } /****if* HTML_Generator/RB_HTML_Generate_Index_Shortcuts * NAME * RB_HTML_Generate_Index_Shortcuts * FUNCTION * Generates alphabetic shortcuts to index entries. * SYNOPSIS */ static void RB_HTML_Generate_Index_Shortcuts( FILE *dest ) /* * INPUTS * o dest -- the file to write to * TODO * - Only list used letters. * - List all letters (accented, signs, etc), not just the common ones. * - Should be better to implement it as a
        ? * SOURCE */ { unsigned char c; fprintf( dest, "

        " ); // Generate A - Z for ( c = 'A'; c <= 'Z'; c++ ) { fprintf( dest, "", c ); RB_HTML_Generate_Char( dest, c ); fprintf( dest, " - " ); } // Generate 0 - 9 for ( c = '0'; c <= '9'; c++ ) { fprintf( dest, "", c ); RB_HTML_Generate_Char( dest, c ); fprintf( dest, "" ); // Do not generate separator for the last char if ( c != '9' ) { fprintf( dest, " - " ); } } fprintf( dest, "

        \n" ); } /********/ /****if* HTML_Generator/RB_HTML_Generate_Index_Table * NAME * RB_HTML_Generate_Index_Table -- * FUNCTION * Create a HTML TABLE containing links to headers of a particular * type. This creates two tables, a table for normal headers as * well as one for internal headers. * SYNOPSIS */ void RB_HTML_Generate_Index_Table( FILE *dest, char *dest_name, struct RB_HeaderType *type, char *title ) /* * INPUTS * o dest -- the file in which to write the table * o dest_name -- the name of this file * o type -- the type of header for which to generate * the table * o title -- the title of the table. * SOURCE */ { /* Compute the number of columns we need for * this type of header. */ // Generate Index Title fprintf( dest, "

        " ); RB_HTML_Generate_String( dest, title ); fprintf( dest, "

        \n" ); // Generate Shortcuts at the begining RB_HTML_Generate_Index_Shortcuts( dest ); if ( RB_Number_Of_Links( type, NULL, FALSE ) ) { if ( RB_Number_Of_Links( type, NULL, TRUE ) ) { /* only print a title if there are two tables. */ fprintf( dest, "

        Normal

        " ); } RB_HTML_Generate_Table_Body( dest, dest_name, type, FALSE ); } if ( RB_Number_Of_Links( type, NULL, TRUE ) ) { /* Always print the Internal title, since * these headers are special and the user should know * he is looking at something special. */ fprintf( dest, "

        Internal

        " ); RB_HTML_Generate_Table_Body( dest, dest_name, type, TRUE ); } // Generate Shortcuts at the end RB_HTML_Generate_Index_Shortcuts( dest ); } /********/ /* TODO */ /*x**if* HTML_Generator/RB_HTML_Generate_Empty_Item * NAME * RB_HTML_Generate_Empty_Item -- ****** */ void RB_HTML_Generate_Empty_Item( FILE *dest_doc ) { fprintf( dest_doc, "
        \n" ); } /****f* HTML_Generator/RB_HTML_Generate_Link * 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, "", r, labelname ); RB_HTML_Generate_String( cur_doc, linkname ); fprintf( cur_doc, "" ); } else if (labelname) { fprintf( cur_doc, "href=\"#%s\">", labelname ); RB_HTML_Generate_String( cur_doc, linkname ); fprintf( cur_doc, "" ); } else { fprintf( cur_doc, "href=\"%s\">", filename); RB_HTML_Generate_String( cur_doc, linkname ); fprintf( cur_doc, "" ); } } /******/ /****f* HTML_Generator/RB_HTML_RelativeAddress * 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; } /******/ /****f* HTML_Generator/RB_HTML_Generate_Char * 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 ); } } /*******/ void HTML_Generate_Begin_Content( FILE *dest_doc ) { HTML_Generate_Div( dest_doc, "content" ); } void HTML_Generate_End_Content( FILE *dest_doc ) { HTML_Generate_Div_End( dest_doc, "content" ); } void HTML_Generate_Begin_Navigation( FILE *dest_doc ) { HTML_Generate_Div( dest_doc, "navigation" ); } void HTML_Generate_End_Navigation( FILE *dest_doc ) { HTML_Generate_Div_End( dest_doc, "navigation" ); } void HTML_Generate_Begin_Extra( FILE *dest_doc ) { HTML_Generate_Div( dest_doc, "extra" ); } void HTML_Generate_End_Extra( FILE *dest_doc ) { HTML_Generate_Div_End( dest_doc, "extra" ); } /****f* HTML_Generator/RB_Create_CSS * 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 * o 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 \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.91 2007/07/10 19:13:51 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" "\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 ); } } } /*******/ void RB_InsertCSS( FILE *dest_doc, char *filename ) { if ( css_name ) { char *r = RB_HTML_RelativeAddress( filename, css_name ); assert( r ); assert( strlen( r ) ); fprintf( dest_doc, "\n", r ); } } void HTML_Generate_Begin_Paragraph( FILE *dest_doc ) { fprintf( dest_doc, "

        " ); } void HTML_Generate_End_Paragraph( FILE *dest_doc ) { fprintf( dest_doc, "

        \n" ); } void HTML_Generate_Begin_Preformatted( FILE *dest_doc, int source ) { // Check if we are preformatting a SOURCE item if ( source ) { // SOURCE items have their own class in the CSS fprintf( dest_doc, "
        ", SOURCE_CLASS );
            }
            else
            {
                fprintf( dest_doc, "
        " );
            }
        }
        
        void HTML_Generate_End_Preformatted(
            FILE *dest_doc )
        {
            fprintf( dest_doc, "
        \n" ); } void HTML_Generate_Begin_List( FILE *dest_doc ) { fprintf( dest_doc, "
          " ); } void HTML_Generate_End_List( FILE *dest_doc ) { fprintf( dest_doc, "
        \n" ); } void HTML_Generate_Begin_List_Item( FILE *dest_doc ) { fprintf( dest_doc, "
      • " ); } void HTML_Generate_End_List_Item( FILE *dest_doc ) { fprintf( dest_doc, "
      • \n" ); }