/*========================================================================= Program: CMake - Cross-Platform Makefile Generator Module: $RCSfile$ Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "cmDocumentationFormatterDocbook.h" #include "cmDocumentationSection.h" //---------------------------------------------------------------------------- // this function is a copy of the one in the HTML formatter // the three functions below are slightly modified copies static bool cmDocumentationIsHyperlinkCharDocbook(char c) { // This is not a complete list but works for CMake documentation. return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '.' || c == '/' || c == '~' || c == '@' || c == ':' || c == '_' || c == '&' || c == '?' || c == '='); } //---------------------------------------------------------------------------- static void cmDocumentationPrintDocbookChar(std::ostream& os, char c) { // Use an escape sequence if necessary. switch(c) { case '<': os << "<"; break; case '>': os << ">"; break; case '&': os << "&"; break; default: os << c; } } //---------------------------------------------------------------------------- const char* cmDocumentationPrintDocbookLink(std::ostream& os,const char* begin) { // Look for the end of the link. const char* end = begin; while(cmDocumentationIsHyperlinkCharDocbook(*end)) { ++end; } // Print the hyperlink itself. os << "<ulink url=\""; for(const char* c = begin; c != end; ++c) { cmDocumentationPrintDocbookChar(os, *c); } os << "\" />"; return end; } //---------------------------------------------------------------------------- void cmDocumentationPrintDocbookEscapes(std::ostream& os, const char* text) { // Hyperlink prefixes. static const char* hyperlinks[] = {"http://", "ftp://", "mailto:", 0}; // Print each character. for(const char* p = text; *p;) { // Handle hyperlinks specially to make them active. bool found_hyperlink = false; for(const char** h = hyperlinks; !found_hyperlink && *h; ++h) { if(strncmp(p, *h, strlen(*h)) == 0) { p = cmDocumentationPrintDocbookLink(os, p); found_hyperlink = true; } } // Print other characters normally. if(!found_hyperlink) { cmDocumentationPrintDocbookChar(os, *p++); } } } cmDocumentationFormatterDocbook::cmDocumentationFormatterDocbook() :cmDocumentationFormatter() { } void cmDocumentationFormatterDocbook ::PrintSection(std::ostream& os, const cmDocumentationSection §ion, const char* name) { if(name) { std::string id = "section_"; id += name; if (this->EmittedLinkIds.find(id) == this->EmittedLinkIds.end()) { this->EmittedLinkIds.insert(id); os << "<sect1 id=\"section_" << name << "\">\n" "<title>\n" << name << "</title>\n"; } else { static unsigned int i=0; i++; os << "<sect1 id=\"section_" << name << i << "\">\n" "<title>\n" << name << "</title>\n"; } } std::string prefix = this->ComputeSectionLinkPrefix(name); const std::vector<cmDocumentationEntry> &entries = section.GetEntries(); os << "<itemizedlist>\n"; for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin(); op != entries.end(); ++ op ) { if(op->Name.size()) { os << " <listitem><link linkend=\"" << prefix << "_"; cmDocumentationPrintDocbookEscapes(os, op->Name.c_str()); os << "\"><emphasis><literal>"; cmDocumentationPrintDocbookEscapes(os, op->Name.c_str()); os << "</literal></emphasis></link></listitem>\n"; } } os << "</itemizedlist>\n" ; for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin(); op != entries.end();) { if(op->Name.size()) { for(;op != entries.end() && op->Name.size(); ++op) { if(op->Name.size()) { os << " <para id=\"" << prefix << "_"; cmDocumentationPrintDocbookEscapes(os, op->Name.c_str()); // make sure that each id exists only once. Since it seems // not easily possible to determine which link refers to which id, // we have at least to make sure that the duplicated id's get a // different name (by appending an increasing number), Alex std::string id = prefix; id += "_"; id += op->Name; if (this->EmittedLinkIds.find(id) == this->EmittedLinkIds.end()) { this->EmittedLinkIds.insert(id); } else { static unsigned int i=0; i++; os << i; } // continue as normal... os << "\"><sect2><title>"; cmDocumentationPrintDocbookEscapes(os, op->Name.c_str()); os << "</title></sect2> "; } cmDocumentationPrintDocbookEscapes(os, op->Brief.c_str()); if(op->Name.size()) { os << "</para>\n"; } if(op->Full.size()) { // a line break seems to be simply a line break with docbook os << "\n "; this->PrintFormatted(os, op->Full.c_str()); } os << "\n"; } } else { this->PrintFormatted(os, op->Brief.c_str()); os << "\n"; ++op; } } if(name) { os << "</sect1>\n"; } } void cmDocumentationFormatterDocbook::PrintPreformatted(std::ostream& os, const char* text) { os << "<literallayout>"; cmDocumentationPrintDocbookEscapes(os, text); os << "</literallayout>\n "; } void cmDocumentationFormatterDocbook::PrintParagraph(std::ostream& os, const char* text) { os << "<para>"; cmDocumentationPrintDocbookEscapes(os, text); os << "</para>"; } //---------------------------------------------------------------------------- void cmDocumentationFormatterDocbook::PrintHeader(const char* name, std::ostream& os) { // this one is used to ensure that we don't create multiple link targets // with the same name. We can clear it here since we are at the // start of a document here. this->EmittedLinkIds.clear(); os << "<?xml version=\"1.0\" ?>\n" "<!DOCTYPE article PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\" " "\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\" [\n" "<!ENTITY % addindex \"IGNORE\">\n" "<!ENTITY % English \"INCLUDE\"> ]>\n" "<article>\n" "<articleinfo>\n" "<title>" << name << "</title>\n" "</articleinfo>\n"; } //---------------------------------------------------------------------------- void cmDocumentationFormatterDocbook::PrintFooter(std::ostream& os) { os << "</article>\n"; }