"Fossies" - the Fresh Open Source Software Archive

Member "highlight-3.57-x64/src/core/htmlgenerator.cpp" (12 May 2020, 16369 Bytes) of package /windows/www/highlight-3.57-x64.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "htmlgenerator.cpp": 3.52_vs_3.53.

    1 /***************************************************************************
    2                      htmlgenerator.cpp  -  description
    3                              -------------------
    4     begin                : Wed Nov 28 2001
    5     copyright            : (C) 2001-2012 by Andre Simon
    6     email                : a.simon@mailbox.org
    7  ***************************************************************************/
    8 
    9 
   10 /*
   11 This file is part of Highlight.
   12 
   13 Highlight is free software: you can redistribute it and/or modify
   14 it under the terms of the GNU General Public License as published by
   15 the Free Software Foundation, either version 3 of the License, or
   16 (at your option) any later version.
   17 
   18 Highlight is distributed in the hope that it will be useful,
   19 but WITHOUT ANY WARRANTY; without even the implied warranty of
   20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   21 GNU General Public License for more details.
   22 
   23 You should have received a copy of the GNU General Public License
   24 along with Highlight.  If not, see <http://www.gnu.org/licenses/>.
   25 */
   26 
   27 #include <fstream>
   28 #include <iostream>
   29 #include <sstream>
   30 #include <algorithm>
   31 
   32 #include "htmlgenerator.h"
   33 #include "version.h"
   34 
   35 namespace highlight
   36 {
   37 
   38 HtmlGenerator::HtmlGenerator () :
   39     CodeGenerator ( HTML ),
   40     brTag ( "<br>" ),
   41     hrTag ( "<hr>" ),
   42     fileSuffix ( ".html" ),
   43     cssClassName ( "hl" ),
   44     orderedList ( false ),
   45     useInlineCSS ( false ),
   46     enclosePreTag ( false ),
   47     attachAnchors ( false ),
   48     anchorPrefix ( "l" )
   49 {
   50     spacer = " ";
   51     styleCommentOpen="/*";
   52     styleCommentClose="*/";
   53 }
   54 
   55 
   56 string HtmlGenerator::getHeaderStart ( const string &title )
   57 {
   58     ostringstream header;
   59     header<<  "<!DOCTYPE html>\n<html>\n<head>\n";
   60     if ( encodingDefined() ) {
   61         header << "<meta charset=\""
   62                << encoding
   63                << "\">\n";
   64     }
   65     header << "<title>" << title << "</title>\n";
   66     return header.str();
   67 }
   68 
   69 string HtmlGenerator::getHeader()
   70 {
   71     ostringstream os;
   72     os << getHeaderStart ( docTitle );
   73     if ( !useInlineCSS ) {
   74         if ( includeStyleDef ) {
   75             os << "<style type=\"text/css\">\n";
   76             os << getStyleDefinition();
   77             os << CodeGenerator::readUserStyleDef();
   78             os << "</style>\n";
   79         } else {
   80             os << "<link rel=\"stylesheet\" type=\"text/css\" href=\""
   81                << getStyleOutputPath()
   82                << "\">\n";
   83         }
   84         os << "</head>\n<body";
   85         if (!cssClassName.empty())
   86             os << " class=\""<<cssClassName<<"\"";
   87         os << ">\n";
   88     } else {
   89         os << "</head>\n<body style=\""
   90            << "background-color:#"
   91            << ( docStyle.getBgColour().getRed ( HTML ) )
   92            << ( docStyle.getBgColour().getGreen ( HTML ) )
   93            << ( docStyle.getBgColour().getBlue ( HTML ) )
   94            << "\">\n";
   95     }
   96 
   97     return os.str();
   98 }
   99 
  100 string HtmlGenerator::getFooter()
  101 {
  102     return getGeneratorComment();
  103 }
  104 
  105 void HtmlGenerator::printBody()
  106 {
  107     if ( (!(showLineNumbers && orderedList) && !fragmentOutput) || enclosePreTag ) {
  108         if ( !useInlineCSS ) {
  109             *out << "<pre";
  110             if (!cssClassName.empty())
  111                 *out<<" class=\"" << cssClassName << "\"";
  112             *out<< ">";
  113         } else {
  114             bool quoteFont=getBaseFont().find_first_of(",'")==string::npos;
  115             *out << "<pre style=\""
  116                  << "color:#"
  117                  << ( docStyle.getDefaultStyle().getColour().getRed ( HTML ) )
  118                  << ( docStyle.getDefaultStyle().getColour().getGreen ( HTML ) )
  119                  << ( docStyle.getDefaultStyle().getColour().getBlue ( HTML ) )
  120                  << "; background-color:#"
  121                  << ( docStyle.getBgColour().getRed ( HTML ) )
  122                  << ( docStyle.getBgColour().getGreen ( HTML ) )
  123                  << ( docStyle.getBgColour().getBlue ( HTML ) )
  124                  << "; font-size:" << this->getBaseFontSize()
  125                  << "pt; font-family:"
  126                  <<((quoteFont)?"'":"")
  127                  << this->getBaseFont()
  128                  <<((quoteFont)?"'":"")
  129                  <<";\">";
  130         }
  131     }
  132     if ( showLineNumbers && orderedList ) {
  133         *out << "<ol";
  134         if (!cssClassName.empty())
  135             *out<<" class=\"" << cssClassName << "\"";
  136         *out<< ">\n";
  137     }
  138 
  139     processRootState();
  140 
  141     if ( showLineNumbers && orderedList ) *out << "</ol>";
  142 
  143     if ( (!(showLineNumbers && orderedList) && !fragmentOutput)  || enclosePreTag )  *out << "</pre>";
  144 }
  145 
  146 
  147 void HtmlGenerator::initOutputTags ()
  148 {
  149     openTags.push_back ( "" );
  150     if ( useInlineCSS ) {
  151         openTags.push_back ( getOpenTag ( docStyle.getStringStyle() ) );
  152         openTags.push_back ( getOpenTag ( docStyle.getNumberStyle() ) );
  153         openTags.push_back ( getOpenTag ( docStyle.getSingleLineCommentStyle() ) );
  154         openTags.push_back ( getOpenTag ( docStyle.getCommentStyle() ) );
  155         openTags.push_back ( getOpenTag ( docStyle.getEscapeCharStyle() ) );
  156         openTags.push_back ( getOpenTag ( docStyle.getPreProcessorStyle() ) );
  157         openTags.push_back ( getOpenTag ( docStyle.getPreProcStringStyle() ) );
  158         openTags.push_back ( getOpenTag ( docStyle.getLineStyle() ) );
  159         openTags.push_back ( getOpenTag ( docStyle.getOperatorStyle() ) );
  160         openTags.push_back ( getOpenTag ( docStyle.getInterpolationStyle() ) );
  161     } else {
  162         openTags.push_back ( getOpenTag ( STY_NAME_STR ) );
  163         openTags.push_back ( getOpenTag ( STY_NAME_NUM ) );
  164         openTags.push_back ( getOpenTag ( STY_NAME_SLC ) );
  165         openTags.push_back ( getOpenTag ( STY_NAME_COM ) );
  166         openTags.push_back ( getOpenTag ( STY_NAME_ESC ) );
  167         openTags.push_back ( getOpenTag ( STY_NAME_DIR ) );
  168         openTags.push_back ( getOpenTag ( STY_NAME_DST ) );
  169         openTags.push_back ( getOpenTag ( STY_NAME_LIN ) );
  170         openTags.push_back ( getOpenTag ( STY_NAME_SYM ) );
  171         openTags.push_back ( getOpenTag ( STY_NAME_IPL ) );
  172     }
  173 
  174     closeTags.push_back ( "" );
  175     for (unsigned int i=1; i<NUMBER_BUILTIN_STATES; i++ ) {
  176         closeTags.push_back ( "</span>" );
  177     }
  178 
  179 }
  180 
  181 string  HtmlGenerator::getAttributes ( const string & elemName, const ElementStyle & elem )
  182 {
  183     ostringstream s;
  184     if ( !elemName.empty() ) {
  185         if (!cssClassName.empty())
  186             s << "."<<cssClassName;
  187         s <<"."<<elemName<<" { ";
  188     }
  189     s << "color:#"
  190       << ( elem.getColour().getRed ( HTML ) )
  191       << ( elem.getColour().getGreen ( HTML ) )
  192       << ( elem.getColour().getBlue ( HTML ) )
  193       << ( elem.isBold() ?     "; font-weight:bold" :"" )
  194       << ( elem.isItalic() ?   "; font-style:italic" :"" )
  195       << ( elem.isUnderline() ? "; text-decoration:underline" :"" );
  196     if ( !elemName.empty() ) {
  197         s << "; }\n" ;
  198     }
  199     return s.str();
  200 }
  201 
  202 string  HtmlGenerator::getOpenTag ( const string& styleName )
  203 {
  204     return "<span class=\"" + (cssClassName.empty() ? "":cssClassName+ " ")  + styleName + "\">";
  205 }
  206 
  207 string  HtmlGenerator::getOpenTag ( const ElementStyle & elem )
  208 {
  209     return "<span style=\""+getAttributes ( "",elem ) + "\">";
  210 }
  211 
  212 string HtmlGenerator::getGeneratorComment()
  213 {
  214     ostringstream s;
  215     s << "\n</body>\n</html>\n";
  216     
  217     if (!omitVersionComment) {
  218         s << "<!--HTML generated by highlight "
  219           << HIGHLIGHT_VERSION << ", " <<  HIGHLIGHT_URL <<"-->\n";     
  220     }
  221    
  222     return s.str();
  223 }
  224 
  225 string HtmlGenerator::getStyleDefinition()
  226 {
  227     if (disableStyleCache || styleDefinitionCache.empty() ) {
  228         bool quoteFont=getBaseFont().find_first_of(",'")==string::npos;
  229         ostringstream os;
  230         
  231         os << "/* highlight theme: "<<docStyle.getDescription()<<" */\n";
  232 
  233         string classNameSuffix;
  234         if (!cssClassName.empty())
  235             classNameSuffix="."+cssClassName;
  236 
  237         os  << "body"<<classNameSuffix;
  238 
  239         os  <<"\t{ background-color:#"
  240             << ( docStyle.getBgColour().getRed ( HTML ) )
  241             << ( docStyle.getBgColour().getGreen ( HTML ) )
  242             << ( docStyle.getBgColour().getBlue ( HTML ) )
  243             << "; }\n";
  244 
  245         os << ( (orderedList) ? "ol" : "pre" ) << classNameSuffix;
  246 
  247         os << "\t{ color:#"
  248            << ( docStyle.getDefaultStyle().getColour().getRed ( HTML ) )
  249            << ( docStyle.getDefaultStyle().getColour().getGreen ( HTML ) )
  250            << ( docStyle.getDefaultStyle().getColour().getBlue ( HTML ) )
  251            << "; background-color:#"
  252            << ( docStyle.getBgColour().getRed ( HTML ) )
  253            << ( docStyle.getBgColour().getGreen ( HTML ) )
  254            << ( docStyle.getBgColour().getBlue ( HTML ) )
  255            << "; font-size:" << this->getBaseFontSize();
  256 
  257         os << "pt; font-family:"<<((quoteFont)?"'":"") << getBaseFont() << ((quoteFont)?"'":"")
  258            << ";}\n";
  259 
  260         os  << getAttributes ( STY_NAME_NUM, docStyle.getNumberStyle() )
  261             << getAttributes ( STY_NAME_ESC, docStyle.getEscapeCharStyle() )
  262             << getAttributes ( STY_NAME_STR, docStyle.getStringStyle() )
  263             << getAttributes ( STY_NAME_DST, docStyle.getPreProcStringStyle() )
  264             << getAttributes ( STY_NAME_SLC, docStyle.getSingleLineCommentStyle() )
  265             << getAttributes ( STY_NAME_COM, docStyle.getCommentStyle() )
  266             << getAttributes ( STY_NAME_DIR, docStyle.getPreProcessorStyle() )
  267             << getAttributes ( STY_NAME_SYM, docStyle.getOperatorStyle() )
  268             << getAttributes ( STY_NAME_IPL, docStyle.getInterpolationStyle() )
  269             << getAttributes ( STY_NAME_LIN, docStyle.getLineStyle() );
  270 
  271         KeywordStyles styles = docStyle.getKeywordStyles();
  272         for ( KSIterator it=styles.begin(); it!=styles.end(); it++ ) {
  273             os << getAttributes ( it->first, it->second );
  274         }
  275         styleDefinitionCache=os.str();
  276     }
  277     return styleDefinitionCache;
  278 }
  279 
  280 string HtmlGenerator::maskCharacter ( unsigned char c )
  281 {
  282     switch ( c ) {
  283     case '<' :
  284         return "&lt;";
  285         break;
  286     case '>' :
  287         return "&gt;";
  288         break;
  289     case '&' :
  290         return "&amp;";
  291         break;
  292     case '\"' :
  293         return "&quot;";
  294         break;
  295     case '\'' :
  296         return "&#39;"; // &apos; not supported by w3m
  297         break;
  298 
  299     case '@' :
  300         return "&#64;";
  301         break;
  302 
  303     default :
  304         return string ( 1, c );
  305     }
  306 }
  307 
  308 string HtmlGenerator::getNewLine()
  309 {
  310     string nlStr;
  311     if ( showLineNumbers && orderedList ) nlStr +="</li>";
  312     if (printNewLines) nlStr+="\n";
  313     return nlStr;
  314 }
  315 
  316 void HtmlGenerator::insertLineNumber ( bool insertNewLine )
  317 {
  318     if ( insertNewLine ) {
  319 
  320         if (currentSyntax->getDecorateLineEndFct()) {
  321             Diluculum::LuaValueList res=callDecorateLineFct(false);
  322             if (res.size()==1) {
  323                 wsBuffer +=res[0].asString();
  324             }
  325         }
  326 
  327         wsBuffer += getNewLine();
  328     }
  329 
  330     if (currentSyntax->getDecorateLineBeginFct()) {
  331         Diluculum::LuaValueList res=callDecorateLineFct(true);
  332         if (res.size()==1) {
  333             wsBuffer +=res[0].asString();
  334         }
  335     }
  336 
  337     if ( showLineNumbers ) {
  338         ostringstream numberPrefix;
  339         int lineNo = lineNumber+lineNumberOffset;
  340 
  341         string lineID;
  342         //attach Anchor only if we're in a new line.
  343         if ( attachAnchors && numberCurrentLine ) {
  344             ostringstream idStream;
  345             idStream << " id=\"" << anchorPrefix << "_" << lineNo << "\"";
  346             lineID = idStream.str();
  347         }
  348 
  349         if ( orderedList ) {
  350             if ( useInlineCSS ) {
  351                 bool quoteFont=getBaseFont().find_first_of(",'")==string::npos;
  352                 numberPrefix<< "<li"
  353                             << lineID
  354                             << " style=\""
  355                             << getAttributes ( "", docStyle.getLineStyle() )
  356                             << "; font-size:" << this->getBaseFontSize()
  357                             << "pt; font-family:"<<((quoteFont)?"'":"")
  358                             << getBaseFont() << ((quoteFont)?"'":"")
  359                             << ";\">";
  360             } else {
  361                 if (!cssClassName.empty())
  362                     numberPrefix<<"<li"
  363                                 << lineID
  364                                 << " class=\""<<cssClassName<<"\">";
  365                 else
  366                     numberPrefix<<"<li"
  367                                 << lineID
  368                                 << ">";
  369             }
  370             // Opera 8 ignores empty list items -> add &nbsp;
  371             //if ( line.empty() ) numberPrefix<<"&nbsp;";
  372         }
  373 
  374         if ( !orderedList ) {
  375             //if we're in a wrapped line, don't fill with zeroes.
  376             ostringstream os;
  377             if ( lineNumberFillZeroes && numberCurrentLine ) {
  378                 os.fill ( '0' );
  379             }
  380 
  381             os << setw ( getLineNumberWidth() ) << right;
  382             //if we're in a wrapped line, don't attach lineNo.
  383             if ( numberCurrentLine ) {
  384                 os << lineNo;
  385             } else {
  386                 os << "";
  387             }
  388 
  389             string tagOpen=openTags[LINENUMBER];
  390             numberPrefix << tagOpen.insert(tagOpen.size()-1, lineID)
  391                          << os.str()
  392                          << spacer
  393                          << closeTags[LINENUMBER];
  394         }
  395         wsBuffer += numberPrefix.str();
  396     }
  397 
  398 }
  399 
  400 bool HtmlGenerator::printIndexFile ( const vector<string> &fileList,
  401                                      const string &outPath )
  402 {
  403     string suffix = fileSuffix;
  404     string outFilePath(outPath);
  405     string fileName = "index" + suffix;
  406     if (outFilePath.size()==0 || outFilePath[outFilePath.size()-1] == Platform::pathSeparator)
  407         outFilePath.append(fileName);
  408 
  409     ofstream indexfile ( outFilePath.c_str() );
  410 
  411     if ( !indexfile.fail() ) {
  412         string inFileName;
  413         string inFilePath, newInFilePath;
  414         std::set<string> usedFileNames;
  415         indexfile << getHeaderStart ( "Source Index" );
  416         indexfile << "</head>\n<body>\n<h1>Source Index</h1>\n"
  417                   << hrTag
  418                   <<  "\n<ul>\n";
  419                   
  420         string::size_type pos;
  421         for ( unsigned int i=0; i < fileList.size();  i++ ) {
  422             pos= ( fileList[i] ).find_last_of ( Platform::pathSeparator );
  423             if ( pos!=string::npos ) {
  424                 newInFilePath = ( fileList[i] ).substr ( 0, pos+1 );
  425             } else {
  426                 newInFilePath=Platform::pathSeparator;
  427             }
  428             if ( newInFilePath!=inFilePath ) {
  429                 indexfile << "</ul>\n<h2>";
  430                 indexfile << newInFilePath;
  431                 indexfile << "</h2>\n<ul>\n";
  432                 inFilePath=newInFilePath;
  433             }
  434             inFileName = ( fileList[i] ).substr ( pos+1 );
  435 
  436             if (usedFileNames.count(inFileName)) {
  437                 string prefix=fileList[i].substr (0, pos+1 );
  438                 replace (prefix.begin(), prefix.end(), Platform::pathSeparator, '_');
  439                 inFileName.insert(0, prefix);
  440             } else {
  441                 usedFileNames.insert(inFileName);
  442             }
  443 
  444             indexfile << "<li><a href=\"" << inFileName << suffix << "\">";
  445             indexfile << inFileName << suffix <<"</a></li>\n";
  446         }
  447 
  448         indexfile << "</ul>\n";
  449         if (!omitVersionComment) {
  450             indexfile << hrTag << brTag
  451                     << "<small>Generated by highlight "
  452                     << HIGHLIGHT_VERSION
  453                     << ", <a href=\"" << HIGHLIGHT_URL << "\" target=\"new\">"
  454                     << HIGHLIGHT_URL << "</a></small>";
  455         }
  456         indexfile << "</body></html>\n";
  457     } else {
  458         return false;
  459     }
  460     return true;
  461 }
  462 
  463 string HtmlGenerator::getKeywordOpenTag ( unsigned int styleID )
  464 {
  465     if ( useInlineCSS ) {
  466         return getOpenTag ( docStyle.getKeywordStyle ( currentSyntax->getKeywordClasses() [styleID] ) );
  467     }
  468     return getOpenTag ( currentSyntax->getKeywordClasses() [styleID] );
  469 }
  470 
  471 string HtmlGenerator::getKeywordCloseTag ( unsigned int styleID )
  472 {
  473     return "</span>";
  474 }
  475 
  476 void HtmlGenerator::setHTMLOrderedList ( bool b )
  477 {
  478     orderedList = b;
  479     if( b ) spacer = "&nbsp;";
  480     maskWs = b;
  481 
  482     if (b && !preFormatter.getReplaceTabs()) {
  483         preFormatter.setReplaceTabs ( true );
  484         preFormatter.setNumberSpaces ( 4 );
  485     }
  486 }
  487 
  488 }