packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmDocumentationFormatterHTML.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmDocumentationFormatterHTML.h"
13 #include "cmDocumentationSection.h"
14 #include "cmVersion.h"
15 //----------------------------------------------------------------------------
16 static bool cmDocumentationIsHyperlinkChar(char c)
17 {
18   // This is not a complete list but works for CMake documentation.
19   return ((c >= 'A' && c <= 'Z') ||
20           (c >= 'a' && c <= 'z') ||
21           (c >= '0' && c <= '9') ||
22           c == '-' || c == '.' || c == '/' || c == '~' || c == '@' ||
23           c == ':' || c == '_' || c == '&' || c == '?' || c == '=');
24 }
25
26 //----------------------------------------------------------------------------
27 static void cmDocumentationPrintHTMLChar(std::ostream& os, char c)
28 {
29   // Use an escape sequence if necessary.
30   switch (c)
31     {
32     case '<':
33       os << "&lt;";
34       break;
35     case '>':
36       os << "&gt;";
37       break;
38     case '&':
39       os << "&amp;";
40       break;
41     case '\n':
42       os << "<br />";
43       break;
44     default:
45       os << c;
46   }
47 }
48
49 //----------------------------------------------------------------------------
50 bool cmDocumentationHTMLIsIdChar(char c)
51 {
52   // From the HTML specification:
53   //   ID and NAME tokens must begin with a letter ([A-Za-z]) and may
54   //   be followed by any number of letters, digits ([0-9]), hyphens
55   //   ("-"), underscores ("_"), colons (":"), and periods (".").
56   return ((c >= 'A' && c <= 'Z') ||
57           (c >= 'a' && c <= 'z') ||
58           (c >= '0' && c <= '9') ||
59           c == '-' || c == '_' || c == ':' || c == '.');
60 }
61
62 //----------------------------------------------------------------------------
63 void cmDocumentationPrintHTMLId(std::ostream& os, const char* begin)
64 {
65   for(const char* c = begin; *c; ++c)
66     {
67     if(cmDocumentationHTMLIsIdChar(*c))
68       {
69       os << *c;
70       }
71     }
72 }
73
74 //----------------------------------------------------------------------------
75 const char* cmDocumentationPrintHTMLLink(std::ostream& os, const char* begin)
76 {
77   // Look for the end of the link.
78   const char* end = begin;
79   while(cmDocumentationIsHyperlinkChar(*end))
80     {
81     ++end;
82     }
83
84   // Print the hyperlink itself.
85   os << "<a href=\"";
86   for(const char* c = begin; c != end; ++c)
87     {
88     cmDocumentationPrintHTMLChar(os, *c);
89     }
90   os << "\">";
91
92   // The name of the hyperlink is the text itself.
93   for(const char* c = begin; c != end; ++c)
94     {
95     cmDocumentationPrintHTMLChar(os, *c);
96     }
97   os << "</a>";
98
99   // Return the position at which to continue scanning the input
100   // string.
101   return end;
102 }
103
104
105 cmDocumentationFormatterHTML::cmDocumentationFormatterHTML()
106 :cmDocumentationFormatter()
107 {
108 }
109
110 void cmDocumentationFormatterHTML
111 ::PrintSection(std::ostream& os,
112                const cmDocumentationSection &section,
113                const char* name)
114 {
115   std::string prefix = this->ComputeSectionLinkPrefix(name);
116
117   const std::vector<cmDocumentationEntry> &entries =
118     section.GetEntries();
119
120   // skip the index if the help for only a single item (--help-command,
121   // --help-policy, --help-property, --help-module) is printed
122   bool isSingleItemHelp = ((name!=0) && (strcmp(name, "SingleItem")==0));
123
124   if (!isSingleItemHelp)
125     {
126     if (name)
127       {
128       os << "<h2><a name=\"section_";
129       cmDocumentationPrintHTMLId(os, name);
130       os << "\"></a>" << name << "</h2>\n";
131       }
132
133     // Is a list needed?
134     for(std::vector<cmDocumentationEntry>::const_iterator op
135          = entries.begin(); op != entries.end(); ++ op )
136       {
137       if (op->Name.size())
138         {
139         os << "<ul>\n";
140         for(;op != entries.end() && op->Name.size(); ++op)
141           {
142           if(op->Name.size())
143             {
144             os << "    <li><a href=\"#" << prefix << ":";
145             cmDocumentationPrintHTMLId(os, op->Name.c_str());
146             os << "\"><b><code>";
147             this->PrintHTMLEscapes(os, op->Name.c_str());
148             os << "</code></b></a></li>\n";
149             }
150           }
151         os << "</ul>\n" ;
152         break; // Skip outer loop termination test
153         }
154       }
155     }
156
157   for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
158       op != entries.end();)
159     {
160     if(op->Name.size())
161       {
162       os << "<ul>\n";
163       for(;op != entries.end() && op->Name.size(); ++op)
164         {
165         os << "  <li>\n";
166         if(op->Name.size())
167           {
168           os << "    <a name=\"" << prefix << ":";
169           cmDocumentationPrintHTMLId(os, op->Name.c_str());
170           os << "\"></a><b><code>";
171           this->PrintHTMLEscapes(os, op->Name.c_str());
172           os << "</code></b>: ";
173           }
174         this->PrintHTMLEscapes(os, op->Brief.c_str());
175         if(op->Full.size())
176           {
177           os << "<br />\n    ";
178           this->PrintFormatted(os, op->Full.c_str());
179           }
180         os << "\n";
181         os << "  </li>\n";
182         }
183       os << "</ul>\n";
184       }
185     else
186       {
187       this->PrintFormatted(os, op->Brief.c_str());
188       os << "\n";
189       ++op;
190       }
191     }
192 }
193
194 void cmDocumentationFormatterHTML::PrintPreformatted(std::ostream& os,
195                                                      const char* text)
196 {
197   os << "<pre>";
198   this->PrintHTMLEscapes(os, text);
199   os << "</pre>\n    ";
200 }
201
202 void cmDocumentationFormatterHTML::PrintParagraph(std::ostream& os,
203                                                   const char* text)
204 {
205   os << "<p>";
206   this->PrintHTMLEscapes(os, text);
207   os << "</p>\n";
208 }
209
210 //----------------------------------------------------------------------------
211 void cmDocumentationFormatterHTML::PrintHeader(const char* docname,
212                                                const char* appname,
213                                                std::ostream& os)
214 {
215   os << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
216      << " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
217   os << "<html xmlns=\"http://www.w3.org/1999/xhtml\""
218      << " xml:lang=\"en\" lang=\"en\">\n";
219   os << "<head><meta http-equiv=\"Content-Type\" "
220      << "content=\"text/html;charset=utf-8\" /><title>";
221   os << docname << " - " << appname;
222   os << "</title></head><body>\n";
223 }
224
225 //----------------------------------------------------------------------------
226 void cmDocumentationFormatterHTML::PrintFooter(std::ostream& os)
227 {
228   os << "</body></html>\n";
229 }
230
231 //----------------------------------------------------------------------------
232 void cmDocumentationFormatterHTML::PrintHTMLEscapes(std::ostream& os,
233                                                     const char* text)
234 {
235   // Hyperlink prefixes.
236   static const char* hyperlinks[] = {"http://", "ftp://", "mailto:", 0};
237
238   // Print each character.
239   for(const char* p = text; *p;)
240     {
241     // Handle hyperlinks specially to make them active.
242     bool found_hyperlink = false;
243     for(const char** h = hyperlinks; !found_hyperlink && *h; ++h)
244       {
245       if(strncmp(p, *h, strlen(*h)) == 0)
246         {
247         p = cmDocumentationPrintHTMLLink(os, p);
248         found_hyperlink = true;
249         }
250       }
251
252     // Print other characters normally.
253     if(!found_hyperlink)
254       {
255       cmDocumentationPrintHTMLChar(os, *p++);
256       }
257     }
258 }
259
260 void cmDocumentationFormatterHTML
261 ::PrintIndex(std::ostream& os,
262              std::vector<const cmDocumentationSection *>& sections)
263 {
264   // skip the index if only the help for a single item is printed
265   if ((sections.size() == 1)
266        && (sections[0]->GetName(this->GetForm()) != 0 )
267        && (std::string(sections[0]->GetName(this->GetForm())) == "SingleItem"))
268     {
269     return;
270     }
271
272   os << "<h2><a name=\"section_Index\"></a>Master Index "
273      << "CMake " << cmVersion::GetCMakeVersion()
274      << "</h2>\n";
275
276   if (!sections.empty())
277     {
278     os << "<ul>\n";
279     for(unsigned int i=0; i < sections.size(); ++i)
280       {
281       std::string name = sections[i]->GetName((this->GetForm()));
282       os << "  <li><a href=\"#section_";
283       cmDocumentationPrintHTMLId(os, name.c_str());
284       os << "\"><b>" << name << "</b></a></li>\n";
285       }
286     os << "</ul>\n";
287     }
288 }