My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
htmlgen.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  *
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby
9  * granted. No representations are made about the suitability of this software
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17 
18 #include <stdlib.h>
19 
20 #include <qdir.h>
21 #include <qregexp.h>
22 #include "message.h"
23 #include "htmlgen.h"
24 #include "config.h"
25 #include "util.h"
26 #include "doxygen.h"
27 #include "logos.h"
28 #include "diagram.h"
29 #include "version.h"
30 #include "dot.h"
31 #include "language.h"
32 #include "htmlhelp.h"
33 #include "docparser.h"
34 #include "htmldocvisitor.h"
35 #include "searchindex.h"
36 #include "pagedef.h"
37 #include "debug.h"
38 #include "dirdef.h"
39 #include "vhdldocgen.h"
40 #include "layout.h"
41 #include "image.h"
42 #include "ftvhelp.h"
43 #include "bufstr.h"
44 #include "resourcemgr.h"
45 
46 
47 //#define DBG_HTML(x) x;
48 #define DBG_HTML(x)
49 
50 static QCString g_header;
51 static QCString g_footer;
52 static QCString g_mathjax_code;
53 
54 
55 // note: this is only active if DISABLE_INDEX=YES, if DISABLE_INDEX is disabled, this
56 // part will be rendered inside menu.js
57 static void writeClientSearchBox(FTextStream &t,const char *relPath)
58 {
59  t << " <div id=\"MSearchBox\" class=\"MSearchBoxInactive\">\n";
60  t << " <span class=\"left\">\n";
61  t << " <img id=\"MSearchSelect\" src=\"" << relPath << "search/mag_sel.png\"\n";
62  t << " onmouseover=\"return searchBox.OnSearchSelectShow()\"\n";
63  t << " onmouseout=\"return searchBox.OnSearchSelectHide()\"\n";
64  t << " alt=\"\"/>\n";
65  t << " <input type=\"text\" id=\"MSearchField\" value=\""
66  << theTranslator->trSearch() << "\" accesskey=\"S\"\n";
67  t << " onfocus=\"searchBox.OnSearchFieldFocus(true)\" \n";
68  t << " onblur=\"searchBox.OnSearchFieldFocus(false)\" \n";
69  t << " onkeyup=\"searchBox.OnSearchFieldChange(event)\"/>\n";
70  t << " </span><span class=\"right\">\n";
71  t << " <a id=\"MSearchClose\" href=\"javascript:searchBox.CloseResultsWindow()\">"
72  << "<img id=\"MSearchCloseImg\" border=\"0\" src=\"" << relPath << "search/close.png\" alt=\"\"/></a>\n";
73  t << " </span>\n";
74  t << " </div>\n";
75 }
76 
77 // note: this is only active if DISABLE_INDEX=YES. if DISABLE_INDEX is disabled, this
78 // part will be rendered inside menu.js
79 static void writeServerSearchBox(FTextStream &t,const char *relPath,bool highlightSearch)
80 {
81  static bool externalSearch = Config_getBool(EXTERNAL_SEARCH);
82  t << " <div id=\"MSearchBox\" class=\"MSearchBoxInactive\">\n";
83  t << " <div class=\"left\">\n";
84  t << " <form id=\"FSearchBox\" action=\"" << relPath;
85  if (externalSearch)
86  {
87  t << "search" << Doxygen::htmlFileExtension;
88  }
89  else
90  {
91  t << "search.php";
92  }
93  t << "\" method=\"get\">\n";
94  t << " <img id=\"MSearchSelect\" src=\"" << relPath << "search/mag.png\" alt=\"\"/>\n";
95  if (!highlightSearch)
96  {
97  t << " <input type=\"text\" id=\"MSearchField\" name=\"query\" value=\""
98  << theTranslator->trSearch() << "\" size=\"20\" accesskey=\"S\" \n";
99  t << " onfocus=\"searchBox.OnSearchFieldFocus(true)\" \n";
100  t << " onblur=\"searchBox.OnSearchFieldFocus(false)\"/>\n";
101  t << " </form>\n";
102  t << " </div><div class=\"right\"></div>\n";
103  t << " </div>\n";
104  }
105 }
106 
107 //------------------------------------------------------------------------
108 
110 QCString clearBlock(const char *s,const char *begin,const char *end)
111 {
112  if (s==0 || begin==0 || end==0) return s;
113  const char *p, *q;
114  int beginLen = qstrlen(begin);
115  int endLen = qstrlen(end);
116  int resLen = 0;
117  for (p=s; (q=strstr(p,begin))!=0; p=q+endLen)
118  {
119  resLen+=(int)(q-p);
120  p=q+beginLen;
121  if ((q=strstr(p,end))==0)
122  {
123  resLen+=beginLen;
124  break;
125  }
126  }
127  resLen+=qstrlen(p);
128  // resLen is the length of the string without the marked block
129 
130  QCString result(resLen+1);
131  char *r;
132  for (r=result.rawData(), p=s; (q=strstr(p,begin))!=0; p=q+endLen)
133  {
134  int l = (int)(q-p);
135  memcpy(r,p,l);
136  r+=l;
137  p=q+beginLen;
138  if ((q=strstr(p,end))==0)
139  {
140  memcpy(r,begin,beginLen);
141  r+=beginLen;
142  break;
143  }
144  }
145  qstrcpy(r,p);
146  return result;
147 }
148 //----------------------------------------------------------------------
149 
150 QCString selectBlock(const QCString& s,const QCString &name,bool enable)
151 {
152  // TODO: this is an expensive function that is called a lot -> optimize it
153  const QCString begin = "<!--BEGIN " + name + "-->";
154  const QCString end = "<!--END " + name + "-->";
155  const QCString nobegin = "<!--BEGIN !" + name + "-->";
156  const QCString noend = "<!--END !" + name + "-->";
157 
158  QCString result = s;
159  if (enable)
160  {
161  result = substitute(result, begin, "");
162  result = substitute(result, end, "");
163  result = clearBlock(result, nobegin, noend);
164  }
165  else
166  {
167  result = substitute(result, nobegin, "");
168  result = substitute(result, noend, "");
169  result = clearBlock(result, begin, end);
170  }
171 
172  return result;
173 }
174 
175 static QCString getSearchBox(bool serverSide, QCString relPath, bool highlightSearch)
176 {
177  QGString result;
178  FTextStream t(&result);
179  if (serverSide)
180  {
181  writeServerSearchBox(t, relPath, highlightSearch);
182  }
183  else
184  {
185  writeClientSearchBox(t, relPath);
186  }
187  return QCString(result);
188 }
189 
190 static QCString removeEmptyLines(const QCString &s)
191 {
192  BufStr out(s.length()+1);
193  const char *p=s.data();
194  if (p)
195  {
196  char c;
197  while ((c=*p++))
198  {
199  if (c=='\n')
200  {
201  const char *e = p;
202  while (*e==' ' || *e=='\t') e++;
203  if (*e=='\n')
204  {
205  p=e;
206  }
207  else out.addChar(c);
208  }
209  else
210  {
211  out.addChar(c);
212  }
213  }
214  }
215  out.addChar('\0');
216  //printf("removeEmptyLines(%s)=%s\n",s.data(),out.data());
217  return out.data();
218 }
219 
220 static QCString substituteHtmlKeywords(const QCString &s,
221  const QCString &title,
222  const QCString &relPath,
223  const QCString &navPath=QCString())
224 {
225  // Build CSS/Javascript tags depending on treeview, search engine settings
226  QCString cssFile;
227  QStrList extraCssFile;
228  QCString generatedBy;
229  QCString treeViewCssJs;
230  QCString searchCssJs;
231  QCString searchBox;
232  QCString mathJaxJs;
233  QCString extraCssText;
234 
235  static QCString projectName = Config_getString(PROJECT_NAME);
236  static bool timeStamp = Config_getBool(HTML_TIMESTAMP);
237  static bool treeView = Config_getBool(GENERATE_TREEVIEW);
238  static bool searchEngine = Config_getBool(SEARCHENGINE);
239  static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
240  static bool mathJax = Config_getBool(USE_MATHJAX);
241  static QCString mathJaxFormat = Config_getEnum(MATHJAX_FORMAT);
242  static bool disableIndex = Config_getBool(DISABLE_INDEX);
243  static bool hasProjectName = !projectName.isEmpty();
244  static bool hasProjectNumber = !Config_getString(PROJECT_NUMBER).isEmpty();
245  static bool hasProjectBrief = !Config_getString(PROJECT_BRIEF).isEmpty();
246  static bool hasProjectLogo = !Config_getString(PROJECT_LOGO).isEmpty();
247  static bool titleArea = (hasProjectName || hasProjectBrief || hasProjectLogo || (disableIndex && searchEngine));
248 
249  cssFile = Config_getString(HTML_STYLESHEET);
250  if (cssFile.isEmpty())
251  {
252  cssFile = "doxygen.css";
253  }
254  else
255  {
256  QFileInfo cssfi(cssFile);
257  if (cssfi.exists())
258  {
259  cssFile = cssfi.fileName().utf8();
260  }
261  else
262  {
263  cssFile = "doxygen.css";
264  }
265  }
266 
267  extraCssText = "";
268  extraCssFile = Config_getList(HTML_EXTRA_STYLESHEET);
269  for (uint i=0; i<extraCssFile.count(); ++i)
270  {
271  QCString fileName(extraCssFile.at(i));
272  if (!fileName.isEmpty())
273  {
274  QFileInfo fi(fileName);
275  if (fi.exists())
276  {
277  extraCssText += "<link href=\"$relpath^"+stripPath(fileName)+"\" rel=\"stylesheet\" type=\"text/css\"/>\n";
278  }
279  }
280  }
281 
282  if (timeStamp)
283  {
284  generatedBy = theTranslator->trGeneratedAt(dateToString(TRUE), convertToHtml(Config_getString(PROJECT_NAME)));
285  }
286  else
287  {
288  generatedBy = theTranslator->trGeneratedBy();
289  }
290 
291  if (treeView)
292  {
293  treeViewCssJs = "<link href=\"$relpath^navtree.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
294  "<script type=\"text/javascript\" src=\"$relpath^resize.js\"></script>\n"
295  "<script type=\"text/javascript\" src=\"$relpath^navtreedata.js\"></script>\n"
296  "<script type=\"text/javascript\" src=\"$relpath^navtree.js\"></script>\n"
297  "<script type=\"text/javascript\">\n"
298  " $(document).ready(initResizable);\n"
299  "</script>";
300  }
301 
302  if (searchEngine)
303  {
304  searchCssJs = "<link href=\"$relpath^search/search.css\" rel=\"stylesheet\" type=\"text/css\"/>\n";
305  if (!serverBasedSearch)
306  {
307  searchCssJs += "<script type=\"text/javascript\" src=\"$relpath^search/searchdata.js\"></script>\n";
308  }
309  searchCssJs += "<script type=\"text/javascript\" src=\"$relpath^search/search.js\"></script>\n";
310 
311  if (!serverBasedSearch)
312  {
313  if (disableIndex)
314  {
315  searchCssJs += "<script type=\"text/javascript\">\n"
316  " $(document).ready(function() { init_search(); });\n"
317  "</script>";
318  }
319  }
320  else
321  {
322  if (disableIndex)
323  {
324  searchCssJs += "<script type=\"text/javascript\">\n"
325  " $(document).ready(function() {\n"
326  " if ($('.searchresults').length > 0) { searchBox.DOMSearchField().focus(); }\n"
327  " });\n"
328  "</script>\n";
329  }
330 
331  // OPENSEARCH_PROVIDER {
332  searchCssJs += "<link rel=\"search\" href=\"" + relPath +
333  "search_opensearch.php?v=opensearch.xml\" "
334  "type=\"application/opensearchdescription+xml\" title=\"" +
335  (hasProjectName ? projectName : QCString("Doxygen")) +
336  "\"/>";
337  // OPENSEARCH_PROVIDER }
338  }
339  searchBox = getSearchBox(serverBasedSearch, relPath, FALSE);
340  }
341 
342  if (mathJax)
343  {
344  QCString path = Config_getString(MATHJAX_RELPATH);
345  if (path.isEmpty() || path.left(2)=="..") // relative path
346  {
347  path.prepend(relPath);
348  }
349  mathJaxJs = "<script type=\"text/x-mathjax-config\">\n"
350  " MathJax.Hub.Config({\n"
351  " extensions: [\"tex2jax.js\"";
352  QStrList &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS);
353  const char *s = mathJaxExtensions.first();
354  while (s)
355  {
356  mathJaxJs+= ", \""+QCString(s)+".js\"";
357  s = mathJaxExtensions.next();
358  }
359  if (mathJaxFormat.isEmpty())
360  {
361  mathJaxFormat = "HTML-CSS";
362  }
363  mathJaxJs += "],\n"
364  " jax: [\"input/TeX\",\"output/"+mathJaxFormat+"\"],\n"
365  "});\n";
366  if (!g_mathjax_code.isEmpty())
367  {
368  mathJaxJs += g_mathjax_code;
369  mathJaxJs += "\n";
370  }
371  mathJaxJs += "</script>";
372  mathJaxJs += "<script type=\"text/javascript\" src=\"" + path + "MathJax.js\"></script>\n";
373  }
374 
375  // first substitute generic keywords
376  QCString result = substituteKeywords(s,title,
377  convertToHtml(Config_getString(PROJECT_NAME)),
378  convertToHtml(Config_getString(PROJECT_NUMBER)),
379  convertToHtml(Config_getString(PROJECT_BRIEF)));
380 
381  // additional HTML only keywords
382  result = substitute(result,"$navpath",navPath);
383  result = substitute(result,"$stylesheet",cssFile);
384  result = substitute(result,"$treeview",treeViewCssJs);
385  result = substitute(result,"$searchbox",searchBox);
386  result = substitute(result,"$search",searchCssJs);
387  result = substitute(result,"$mathjax",mathJaxJs);
388  result = substitute(result,"$generatedby",generatedBy);
389  result = substitute(result,"$extrastylesheet",extraCssText);
390  result = substitute(result,"$relpath$",relPath); //<-- obsolete: for backwards compatibility only
391  result = substitute(result,"$relpath^",relPath); //<-- must be last
392 
393  // additional HTML only conditional blocks
394  result = selectBlock(result,"DISABLE_INDEX",disableIndex);
395  result = selectBlock(result,"GENERATE_TREEVIEW",treeView);
396  result = selectBlock(result,"SEARCHENGINE",searchEngine);
397  result = selectBlock(result,"TITLEAREA",titleArea);
398  result = selectBlock(result,"PROJECT_NAME",hasProjectName);
399  result = selectBlock(result,"PROJECT_NUMBER",hasProjectNumber);
400  result = selectBlock(result,"PROJECT_BRIEF",hasProjectBrief);
401  result = selectBlock(result,"PROJECT_LOGO",hasProjectLogo);
402 
403  result = removeEmptyLines(result);
404 
405  return result;
406 }
407 
408 //--------------------------------------------------------------------------
409 
411  : m_streamSet(FALSE), m_col(0)
412 {
413 }
414 
416  : m_col(0), m_relPath(relPath)
417 {
418  setTextStream(t);
419 }
420 
422 {
423  m_streamSet = t.device()!=0;
424  m_t.setDevice(t.device());
425 }
426 
427 void HtmlCodeGenerator::setRelativePath(const QCString &path)
428 {
429  m_relPath = path;
430 }
431 
432 void HtmlCodeGenerator::codify(const char *str)
433 {
434  static int tabSize = Config_getInt(TAB_SIZE);
435  if (str && m_streamSet)
436  {
437  const char *p=str;
438  char c;
439  int spacesToNextTabStop;
440  while (*p)
441  {
442  c=*p++;
443  switch(c)
444  {
445  case '\t': spacesToNextTabStop =
446  tabSize - (m_col%tabSize);
447  m_t << Doxygen::spaces.left(spacesToNextTabStop);
448  m_col+=spacesToNextTabStop;
449  break;
450  case '\n': m_t << "\n"; m_col=0;
451  break;
452  case '\r': break;
453  case '<': m_t << "&lt;"; m_col++;
454  break;
455  case '>': m_t << "&gt;"; m_col++;
456  break;
457  case '&': m_t << "&amp;"; m_col++;
458  break;
459  case '\'': m_t << "&#39;"; m_col++; // &apos; is not valid XHTML
460  break;
461  case '"': m_t << "&quot;"; m_col++;
462  break;
463  case '\\':
464  if (*p=='<')
465  { m_t << "&lt;"; p++; }
466  else if (*p=='>')
467  { m_t << "&gt;"; p++; }
468  else
469  m_t << "\\";
470  m_col++;
471  break;
472  default: p=writeUtf8Char(m_t,p-1);
473  m_col++;
474  break;
475  }
476  }
477  }
478 }
479 
480 void HtmlCodeGenerator::docify(const char *str)
481 {
482  if (str && m_streamSet)
483  {
484  const char *p=str;
485  char c;
486  while (*p)
487  {
488  c=*p++;
489  switch(c)
490  {
491  case '<': m_t << "&lt;"; break;
492  case '>': m_t << "&gt;"; break;
493  case '&': m_t << "&amp;"; break;
494  case '"': m_t << "&quot;"; break;
495  case '\\':
496  if (*p=='<')
497  { m_t << "&lt;"; p++; }
498  else if (*p=='>')
499  { m_t << "&gt;"; p++; }
500  else
501  m_t << "\\";
502  break;
503  default: m_t << c;
504  }
505  }
506  }
507 }
508 
509 void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename,
510  const char *anchor,int l)
511 {
512  if (!m_streamSet) return;
513  const int maxLineNrStr = 10;
514  char lineNumber[maxLineNrStr];
515  char lineAnchor[maxLineNrStr];
516  qsnprintf(lineNumber,maxLineNrStr,"%5d",l);
517  qsnprintf(lineAnchor,maxLineNrStr,"l%05d",l);
518 
519  m_t << "<div class=\"line\">";
520  m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">";
521  if (filename)
522  {
523  _writeCodeLink("line",ref,filename,anchor,lineNumber,0);
524  }
525  else
526  {
527  codify(lineNumber);
528  }
529  m_t << "</span>";
530  m_t << "&#160;";
531 }
532 
533 void HtmlCodeGenerator::writeCodeLink(const char *ref,const char *f,
534  const char *anchor, const char *name,
535  const char *tooltip)
536 {
537  if (!m_streamSet) return;
538  //printf("writeCodeLink(ref=%s,f=%s,anchor=%s,name=%s,tooltip=%s)\n",ref,f,anchor,name,tooltip);
539  _writeCodeLink("code",ref,f,anchor,name,tooltip);
540 }
541 
542 void HtmlCodeGenerator::_writeCodeLink(const char *className,
543  const char *ref,const char *f,
544  const char *anchor, const char *name,
545  const char *tooltip)
546 {
547  if (ref)
548  {
549  m_t << "<a class=\"" << className << "Ref\" ";
550  m_t << externalLinkTarget() << externalRef(m_relPath,ref,FALSE);
551  }
552  else
553  {
554  m_t << "<a class=\"" << className << "\" ";
555  }
556  m_t << "href=\"";
557  m_t << externalRef(m_relPath,ref,TRUE);
558  if (f) m_t << f << Doxygen::htmlFileExtension;
559  if (anchor) m_t << "#" << anchor;
560  m_t << "\"";
561  if (tooltip) m_t << " title=\"" << convertToHtml(tooltip) << "\"";
562  m_t << ">";
563  docify(name);
564  m_t << "</a>";
565  m_col+=qstrlen(name);
566 }
567 
568 void HtmlCodeGenerator::writeTooltip(const char *id, const DocLinkInfo &docInfo,
569  const char *decl, const char *desc,
570  const SourceLinkInfo &defInfo,
571  const SourceLinkInfo &declInfo)
572 {
573  m_t << "<div class=\"ttc\" id=\"" << id << "\">";
574  m_t << "<div class=\"ttname\">";
575  if (!docInfo.url.isEmpty())
576  {
577  m_t << "<a href=\"";
578  m_t << externalRef(m_relPath,docInfo.ref,TRUE);
579  m_t << docInfo.url << Doxygen::htmlFileExtension;
580  if (!docInfo.anchor.isEmpty())
581  {
582  m_t << "#" << docInfo.anchor;
583  }
584  m_t << "\">";
585  }
586  docify(docInfo.name);
587  if (!docInfo.url.isEmpty())
588  {
589  m_t << "</a>";
590  }
591  m_t << "</div>";
592  if (decl)
593  {
594  m_t << "<div class=\"ttdeci\">";
595  docify(decl);
596  m_t << "</div>";
597  }
598  if (desc)
599  {
600  m_t << "<div class=\"ttdoc\">";
601  docify(desc); // desc is already HTML escaped; but there are still < and > signs
602  m_t << "</div>";
603  }
604  if (!defInfo.file.isEmpty())
605  {
606  m_t << "<div class=\"ttdef\"><b>Definition:</b> ";
607  if (!defInfo.url.isEmpty())
608  {
609  m_t << "<a href=\"";
610  m_t << externalRef(m_relPath,defInfo.ref,TRUE);
611  m_t << defInfo.url << Doxygen::htmlFileExtension;
612  if (!defInfo.anchor.isEmpty())
613  {
614  m_t << "#" << defInfo.anchor;
615  }
616  m_t << "\">";
617  }
618  m_t << defInfo.file << ":" << defInfo.line;
619  if (!defInfo.url.isEmpty())
620  {
621  m_t << "</a>";
622  }
623  m_t << "</div>";
624  }
625  if (!declInfo.file.isEmpty())
626  {
627  m_t << "<div class=\"ttdecl\"><b>Declaration:</b> ";
628  if (!declInfo.url.isEmpty())
629  {
630  m_t << "<a href=\"";
631  m_t << externalRef(m_relPath,declInfo.ref,TRUE);
632  m_t << declInfo.url << Doxygen::htmlFileExtension;
633  if (!declInfo.anchor.isEmpty())
634  {
635  m_t << "#" << declInfo.anchor;
636  }
637  m_t << "\">";
638  }
639  m_t << declInfo.file << ":" << declInfo.line;
640  if (!declInfo.url.isEmpty())
641  {
642  m_t << "</a>";
643  }
644  m_t << "</div>";
645  }
646  m_t << "</div>" << endl;
647 }
648 
649 
650 void HtmlCodeGenerator::startCodeLine(bool hasLineNumbers)
651 {
652  if (m_streamSet)
653  {
654  if (!hasLineNumbers) m_t << "<div class=\"line\">";
655  m_col=0;
656  }
657 }
658 
660 {
661  if (m_streamSet) m_t << "</div>";
662 }
663 
665 {
666  if (m_streamSet) m_t << "<span class=\"" << s << "\">";
667 }
668 
670 {
671  if (m_streamSet) m_t << "</span>";
672 }
673 
674 void HtmlCodeGenerator::writeCodeAnchor(const char *anchor)
675 {
676  if (m_streamSet) m_t << "<a name=\"" << anchor << "\"></a>";
677 }
678 
679 //--------------------------------------------------------------------------
680 
682 {
683  dir=Config_getString(HTML_OUTPUT);
684  m_emptySection=FALSE;
685 }
686 
688 {
689  //printf("HtmlGenerator::~HtmlGenerator()\n");
690 }
691 
693 {
694  QCString dname=Config_getString(HTML_OUTPUT);
695  QDir d(dname);
696  if (!d.exists() && !d.mkdir(dname))
697  {
698  err("Could not create output directory %s\n",dname.data());
699  exit(1);
700  }
701  //writeLogo(dname);
702  if (!Config_getString(HTML_HEADER).isEmpty())
703  {
704  g_header=fileToString(Config_getString(HTML_HEADER));
705  //printf("g_header='%s'\n",g_header.data());
706  }
707  else
708  {
709  g_header = ResourceMgr::instance().getAsString("header.html");
710  }
711 
712  if (!Config_getString(HTML_FOOTER).isEmpty())
713  {
714  g_footer=fileToString(Config_getString(HTML_FOOTER));
715  //printf("g_footer='%s'\n",g_footer.data());
716  }
717  else
718  {
719  g_footer = ResourceMgr::instance().getAsString("footer.html");
720  }
721 
722  if (Config_getBool(USE_MATHJAX))
723  {
724  if (!Config_getString(MATHJAX_CODEFILE).isEmpty())
725  {
726  g_mathjax_code=fileToString(Config_getString(MATHJAX_CODEFILE));
727  //printf("g_mathjax_code='%s'\n",g_mathjax_code.data());
728  }
729  }
730  createSubDirs(d);
731 
733  mgr.copyResource("tabs.css",dname);
734  mgr.copyResource("jquery.js",dname);
735  if (Config_getBool(INTERACTIVE_SVG))
736  {
737  mgr.copyResource("svgpan.js",dname);
738  }
739  if (!Config_getBool(DISABLE_INDEX))
740  {
741  mgr.copyResource("menu.js",dname);
742  }
743 
744  {
745  QFile f(dname+"/dynsections.js");
746  if (f.open(IO_WriteOnly))
747  {
748  FTextStream t(&f);
749  t << mgr.getAsString("dynsections.js");
750  if (Config_getBool(SOURCE_BROWSER) && Config_getBool(SOURCE_TOOLTIPS))
751  {
752  t << endl <<
753  "$(document).ready(function() {\n"
754  " $('.code,.codeRef').each(function() {\n"
755  " $(this).data('powertip',$('#'+$(this).attr('href').replace(/.*\\//,'').replace(/[^a-z_A-Z0-9]/g,'_')).html());\n"
756  " $(this).powerTip({ placement: 's', smartPlacement: true, mouseOnToPopup: true });\n"
757  " });\n"
758  "});\n";
759  }
760  }
761  }
762 }
763 
766 {
768  QCString dname=Config_getString(HTML_OUTPUT);
770  //writeColoredImgData(dname,colored_tab_data);
771  mgr.copyResource("tab_a.lum",dname);
772  mgr.copyResource("tab_b.lum",dname);
773  mgr.copyResource("tab_h.lum",dname);
774  mgr.copyResource("tab_s.lum",dname);
775  mgr.copyResource("nav_h.lum",dname);
776  mgr.copyResource("nav_f.lum",dname);
777  mgr.copyResource("bc_s.luma",dname);
778  mgr.copyResource("doxygen.luma",dname);
779  mgr.copyResource("closed.luma",dname);
780  mgr.copyResource("open.luma",dname);
781  mgr.copyResource("bdwn.luma",dname);
782  mgr.copyResource("sync_on.luma",dname);
783  mgr.copyResource("sync_off.luma",dname);
784 
785  //{
786  // unsigned char shadow[6] = { 5, 5, 5, 5, 5, 5 };
787  // unsigned char shadow_alpha[6] = { 80, 60, 40, 20, 10, 0 };
788  // ColoredImage img(1,6,shadow,shadow_alpha,0,0,100);
789  // img.save(dname+"/nav_g.png");
790  //}
791  mgr.copyResource("nav_g.png",dname);
792 }
793 
794 void HtmlGenerator::writeSearchData(const char *dir)
795 {
796  static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
797  //writeImgData(dir,serverBasedSearch ? search_server_data : search_client_data);
799 
800  mgr.copyResource("search_l.png",dir);
801  Doxygen::indexList->addImageFile("search/search_l.png");
802  mgr.copyResource("search_m.png",dir);
803  Doxygen::indexList->addImageFile("search/search_m.png");
804  mgr.copyResource("search_r.png",dir);
805  Doxygen::indexList->addImageFile("search/search_r.png");
806  if (serverBasedSearch)
807  {
808  mgr.copyResource("mag.png",dir);
809  Doxygen::indexList->addImageFile("search/mag.png");
810  }
811  else
812  {
813  mgr.copyResource("close.png",dir);
814  Doxygen::indexList->addImageFile("search/close.png");
815  mgr.copyResource("mag_sel.png",dir);
816  Doxygen::indexList->addImageFile("search/mag_sel.png");
817  }
818 
819  QCString searchDirName = Config_getString(HTML_OUTPUT)+"/search";
820  QFile f(searchDirName+"/search.css");
821  if (f.open(IO_WriteOnly))
822  {
823  FTextStream t(&f);
824  QCString searchCss;
825  if (Config_getBool(DISABLE_INDEX))
826  {
827  searchCss = mgr.getAsString("search_nomenu.css");
828  }
829  else
830  {
831  searchCss = mgr.getAsString("search.css");
832  }
833  searchCss = substitute(replaceColorMarkers(searchCss),"$doxygenversion",versionString);
834  t << searchCss;
835  Doxygen::indexList->addStyleSheetFile("search/search.css");
836  }
837 }
838 
840 {
841  FTextStream t(&file);
842  t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",versionString));
843 }
844 
845 void HtmlGenerator::writeHeaderFile(QFile &file, const char * /*cssname*/)
846 {
847  FTextStream t(&file);
848  t << "<!-- HTML header for doxygen " << versionString << "-->" << endl;
849  t << ResourceMgr::instance().getAsString("header.html");
850 }
851 
853 {
854  FTextStream t(&file);
855  t << "<!-- HTML footer for doxygen " << versionString << "-->" << endl;
856  t << ResourceMgr::instance().getAsString("footer.html");
857 }
858 
859 void HtmlGenerator::startFile(const char *name,const char *,
860  const char *title)
861 {
862  //printf("HtmlGenerator::startFile(%s)\n",name);
863  QCString fileName=name;
864  lastTitle=title;
865  relPath = relativePathToRoot(fileName);
866 
867  if (fileName.right(Doxygen::htmlFileExtension.length())!=Doxygen::htmlFileExtension)
868  {
869  fileName+=Doxygen::htmlFileExtension;
870  }
871  startPlainFile(fileName);
873  m_codeGen.setRelativePath(relPath);
874  Doxygen::indexList->addIndexFile(fileName);
875 
876  lastFile = fileName;
878 
879  t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen "
880  << versionString << " -->" << endl;
881  //static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
882  static bool searchEngine = Config_getBool(SEARCHENGINE);
883  if (searchEngine /*&& !generateTreeView*/)
884  {
885  t << "<script type=\"text/javascript\">\n";
886  t << "var searchBox = new SearchBox(\"searchBox\", \""
887  << relPath<< "search\",false,'" << theTranslator->trSearch() << "');\n";
888  t << "</script>\n";
889  }
890  //generateDynamicSections(t,relPath);
891  m_sectionCount=0;
892 }
893 
894 void HtmlGenerator::writeSearchInfo(FTextStream &t,const QCString &relPath)
895 {
896  static bool searchEngine = Config_getBool(SEARCHENGINE);
897  static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
898  if (searchEngine && !serverBasedSearch)
899  {
900  (void)relPath;
901  t << "<!-- window showing the filter options -->\n";
902  t << "<div id=\"MSearchSelectWindow\"\n";
903  t << " onmouseover=\"return searchBox.OnSearchSelectShow()\"\n";
904  t << " onmouseout=\"return searchBox.OnSearchSelectHide()\"\n";
905  t << " onkeydown=\"return searchBox.OnSearchSelectKey(event)\">\n";
906  t << "</div>\n";
907  t << "\n";
908  t << "<!-- iframe showing the search results (closed by default) -->\n";
909  t << "<div id=\"MSearchResultsWindow\">\n";
910  t << "<iframe src=\"javascript:void(0)\" frameborder=\"0\" \n";
911  t << " name=\"MSearchResults\" id=\"MSearchResults\">\n";
912  t << "</iframe>\n";
913  t << "</div>\n";
914  t << "\n";
915  }
916 }
917 
919 {
920  writeSearchInfo(t,relPath);
921 }
922 
923 
924 QCString HtmlGenerator::writeLogoAsString(const char *path)
925 {
926  static bool timeStamp = Config_getBool(HTML_TIMESTAMP);
927  QCString result;
928  if (timeStamp)
929  {
930  result += theTranslator->trGeneratedAt(
931  dateToString(TRUE),
932  Config_getString(PROJECT_NAME)
933  );
934  }
935  else
936  {
937  result += theTranslator->trGeneratedBy();
938  }
939  result += "&#160;\n<a href=\"http://www.doxygen.org/index.html\">\n"
940  "<img class=\"footer\" src=\"";
941  result += path;
942  result += "doxygen.png\" alt=\"doxygen\"/></a> ";
943  result += versionString;
944  result += " ";
945  return result;
946 }
947 
949 {
950  t << writeLogoAsString(relPath);
951 }
952 
953 void HtmlGenerator::writePageFooter(FTextStream &t,const QCString &lastTitle,
954  const QCString &relPath,const QCString &navPath)
955 {
956  t << substituteHtmlKeywords(g_footer,convertToHtml(lastTitle),relPath,navPath);
957 }
958 
959 void HtmlGenerator::writeFooter(const char *navPath)
960 {
961  writePageFooter(t,lastTitle,relPath,navPath);
962 }
963 
965 {
966  endPlainFile();
967 }
968 
970 {
971  t << "<h3 class=\"version\">";
972 }
973 
975 {
976  t << "</h3>";
977 }
978 
980 {
981  //printf("writeStyleInfo(%d)\n",part);
982  if (part==0)
983  {
984  if (Config_getString(HTML_STYLESHEET).isEmpty()) // write default style sheet
985  {
986  //printf("write doxygen.css\n");
987  startPlainFile("doxygen.css");
988 
989  // alternative, cooler looking titles
990  //t << "H1 { text-align: center; border-width: thin none thin none;" << endl;
991  //t << " border-style : double; border-color : blue; padding-left : 1em; padding-right : 1em }" << endl;
992 
993  t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",versionString));
994  endPlainFile();
995  Doxygen::indexList->addStyleSheetFile("doxygen.css");
996  }
997  else // write user defined style sheet
998  {
999  QCString cssname=Config_getString(HTML_STYLESHEET);
1000  QFileInfo cssfi(cssname);
1001  if (!cssfi.exists() || !cssfi.isFile() || !cssfi.isReadable())
1002  {
1003  err("style sheet %s does not exist or is not readable!", Config_getString(HTML_STYLESHEET).data());
1004  }
1005  else
1006  {
1007  // convert style sheet to string
1008  QCString fileStr = fileToString(cssname);
1009  // write the string into the output dir
1010  startPlainFile(cssfi.fileName().utf8());
1011  t << fileStr;
1012  endPlainFile();
1013  }
1014  Doxygen::indexList->addStyleSheetFile(cssfi.fileName().utf8());
1015  }
1016  static QStrList extraCssFile = Config_getList(HTML_EXTRA_STYLESHEET);
1017  for (uint i=0; i<extraCssFile.count(); ++i)
1018  {
1019  QCString fileName(extraCssFile.at(i));
1020  if (!fileName.isEmpty())
1021  {
1022  QFileInfo fi(fileName);
1023  if (fi.exists())
1024  {
1025  Doxygen::indexList->addStyleSheetFile(fi.fileName().utf8());
1026  }
1027  }
1028  }
1029  }
1030 }
1031 
1032 void HtmlGenerator::startDoxyAnchor(const char *,const char *,
1033  const char *anchor, const char *,
1034  const char *)
1035 {
1036  t << "<a id=\"" << anchor << "\"></a>";
1037 }
1038 
1039 void HtmlGenerator::endDoxyAnchor(const char *,const char *)
1040 {
1041 }
1042 
1043 //void HtmlGenerator::newParagraph()
1044 //{
1045 // t << endl << "<p>" << endl;
1046 //}
1047 
1049 {
1050  t << endl << "<p>";
1051 }
1052 
1054 {
1055  t << "</p>" << endl;
1056 }
1057 
1058 void HtmlGenerator::writeString(const char *text)
1059 {
1060  t << text;
1061 }
1062 
1064 {
1065  t << "<li>";
1066 }
1067 
1069 {
1070  t << "</li>" << endl;
1071 }
1072 
1073 void HtmlGenerator::startIndexItem(const char *ref,const char *f)
1074 {
1075  //printf("HtmlGenerator::startIndexItem(%s,%s)\n",ref,f);
1076  if (ref || f)
1077  {
1078  if (ref)
1079  {
1080  t << "<a class=\"elRef\" ";
1081  t << externalLinkTarget() << externalRef(relPath,ref,FALSE);
1082  }
1083  else
1084  {
1085  t << "<a class=\"el\" ";
1086  }
1087  t << "href=\"";
1088  t << externalRef(relPath,ref,TRUE);
1089  if (f) t << f << Doxygen::htmlFileExtension << "\">";
1090  }
1091  else
1092  {
1093  t << "<b>";
1094  }
1095 }
1096 
1097 void HtmlGenerator::endIndexItem(const char *ref,const char *f)
1098 {
1099  //printf("HtmlGenerator::endIndexItem(%s,%s,%s)\n",ref,f,name);
1100  if (ref || f)
1101  {
1102  t << "</a>";
1103  }
1104  else
1105  {
1106  t << "</b>";
1107  }
1108 }
1109 
1110 void HtmlGenerator::writeStartAnnoItem(const char *,const char *f,
1111  const char *path,const char *name)
1112 {
1113  t << "<li>";
1114  if (path) docify(path);
1115  t << "<a class=\"el\" href=\"" << f << Doxygen::htmlFileExtension << "\">";
1116  docify(name);
1117  t << "</a> ";
1118 }
1119 
1120 void HtmlGenerator::writeObjectLink(const char *ref,const char *f,
1121  const char *anchor, const char *name)
1122 {
1123  if (ref)
1124  {
1125  t << "<a class=\"elRef\" ";
1126  t << externalLinkTarget() << externalRef(relPath,ref,FALSE);
1127  }
1128  else
1129  {
1130  t << "<a class=\"el\" ";
1131  }
1132  t << "href=\"";
1133  t << externalRef(relPath,ref,TRUE);
1134  if (f) t << f << Doxygen::htmlFileExtension;
1135  if (anchor) t << "#" << anchor;
1136  t << "\">";
1137  docify(name);
1138  t << "</a>";
1139 }
1140 
1141 void HtmlGenerator::startTextLink(const char *f,const char *anchor)
1142 {
1143  t << "<a href=\"";
1144  if (f) t << relPath << f << Doxygen::htmlFileExtension;
1145  if (anchor) t << "#" << anchor;
1146  t << "\">";
1147 }
1148 
1150 {
1151  t << "</a>";
1152 }
1153 
1154 void HtmlGenerator::startHtmlLink(const char *url)
1155 {
1156  static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
1157  t << "<a ";
1158  if (generateTreeView) t << "target=\"top\" ";
1159  t << "href=\"";
1160  if (url) t << url;
1161  t << "\">";
1162 }
1163 
1165 {
1166  t << "</a>";
1167 }
1168 
1169 void HtmlGenerator::startGroupHeader(int extraIndentLevel)
1170 {
1171  if (extraIndentLevel==2)
1172  {
1173  t << "<h4 class=\"groupheader\">";
1174  }
1175  else if (extraIndentLevel==1)
1176  {
1177  t << "<h3 class=\"groupheader\">";
1178  }
1179  else // extraIndentLevel==0
1180  {
1181  t << "<h2 class=\"groupheader\">";
1182  }
1183 }
1184 
1185 void HtmlGenerator::endGroupHeader(int extraIndentLevel)
1186 {
1187  if (extraIndentLevel==2)
1188  {
1189  t << "</h4>" << endl;
1190  }
1191  else if (extraIndentLevel==1)
1192  {
1193  t << "</h3>" << endl;
1194  }
1195  else
1196  {
1197  t << "</h2>" << endl;
1198  }
1199 }
1200 
1201 void HtmlGenerator::startSection(const char *lab,const char *,SectionInfo::SectionType type)
1202 {
1203  switch(type)
1204  {
1205  case SectionInfo::Page: t << "\n\n<h1>"; break;
1206  case SectionInfo::Section: t << "\n\n<h2>"; break;
1207  case SectionInfo::Subsection: t << "\n\n<h3>"; break;
1208  case SectionInfo::Subsubsection: t << "\n\n<h4>"; break;
1209  case SectionInfo::Paragraph: t << "\n\n<h5>"; break;
1210  default: ASSERT(0); break;
1211  }
1212  t << "<a id=\"" << lab << "\"></a>";
1213 }
1214 
1216 {
1217  switch(type)
1218  {
1219  case SectionInfo::Page: t << "</h1>"; break;
1220  case SectionInfo::Section: t << "</h2>"; break;
1221  case SectionInfo::Subsection: t << "</h3>"; break;
1222  case SectionInfo::Subsubsection: t << "</h4>"; break;
1223  case SectionInfo::Paragraph: t << "</h5>"; break;
1224  default: ASSERT(0); break;
1225  }
1226 }
1227 
1228 void HtmlGenerator::docify(const char *str)
1229 {
1230  docify(str,FALSE);
1231 }
1232 
1233 void HtmlGenerator::docify(const char *str,bool inHtmlComment)
1234 {
1235  if (str)
1236  {
1237  const char *p=str;
1238  char c;
1239  while (*p)
1240  {
1241  c=*p++;
1242  switch(c)
1243  {
1244  case '<': t << "&lt;"; break;
1245  case '>': t << "&gt;"; break;
1246  case '&': t << "&amp;"; break;
1247  case '"': t << "&quot;"; break;
1248  case '-': if (inHtmlComment) t << "&#45;"; else t << "-"; break;
1249  case '\\':
1250  if (*p=='<')
1251  { t << "&lt;"; p++; }
1252  else if (*p=='>')
1253  { t << "&gt;"; p++; }
1254  else
1255  t << "\\";
1256  break;
1257  default: t << c;
1258  }
1259  }
1260  }
1261 }
1262 
1264 {
1265  char cs[2];
1266  cs[0]=c;
1267  cs[1]=0;
1268  docify(cs);
1269 }
1270 
1271 //--- helper function for dynamic sections -------------------------
1272 
1274  const QCString &relPath,int sectionCount)
1275 {
1276  //t << "<!-- startSectionHeader -->";
1277  static bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS);
1278  if (dynamicSections)
1279  {
1280  t << "<div id=\"dynsection-" << sectionCount << "\" "
1281  "onclick=\"return toggleVisibility(this)\" "
1282  "class=\"dynheader closed\" "
1283  "style=\"cursor:pointer;\">" << endl;
1284  t << " <img id=\"dynsection-" << sectionCount << "-trigger\" src=\""
1285  << relPath << "closed.png\" alt=\"+\"/> ";
1286  }
1287  else
1288  {
1289  t << "<div class=\"dynheader\">" << endl;
1290  }
1291 }
1292 
1294 {
1295  //t << "<!-- endSectionHeader -->";
1296  t << "</div>" << endl;
1297 }
1298 
1299 static void startSectionSummary(FTextStream &t,int sectionCount)
1300 {
1301  //t << "<!-- startSectionSummary -->";
1302  static bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS);
1303  if (dynamicSections)
1304  {
1305  t << "<div id=\"dynsection-" << sectionCount << "-summary\" "
1306  "class=\"dynsummary\" "
1307  "style=\"display:block;\">" << endl;
1308  }
1309 }
1310 
1312 {
1313  //t << "<!-- endSectionSummary -->";
1314  static bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS);
1315  if (dynamicSections)
1316  {
1317  t << "</div>" << endl;
1318  }
1319 }
1320 
1321 static void startSectionContent(FTextStream &t,int sectionCount)
1322 {
1323  //t << "<!-- startSectionContent -->";
1324  static bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS);
1325  if (dynamicSections)
1326  {
1327  t << "<div id=\"dynsection-" << sectionCount << "-content\" "
1328  "class=\"dyncontent\" "
1329  "style=\"display:none;\">" << endl;
1330  }
1331  else
1332  {
1333  t << "<div class=\"dyncontent\">" << endl;
1334  }
1335 }
1336 
1338 {
1339  //t << "<!-- endSectionContent -->";
1340  t << "</div>" << endl;
1341 }
1342 
1343 //----------------------------
1344 
1346 {
1348 }
1349 
1351  const char *fileName,const char *name)
1352 {
1357  t << " <div class=\"center\">" << endl;
1358  t << " <img src=\"";
1359  t << relPath << fileName << ".png\" usemap=\"#" << convertToId(name);
1360  t << "_map\" alt=\"\"/>" << endl;
1361  t << " <map id=\"" << convertToId(name);
1362  t << "_map\" name=\"";
1363  docify(name);
1364  t << "_map\">" << endl;
1365 
1366  d.writeImage(t,dir,relPath,fileName);
1367  t << " </div>";
1369  m_sectionCount++;
1370 }
1371 
1372 
1374 {
1375  DBG_HTML(t << "<!-- startMemberList -->" << endl)
1376 }
1377 
1379 {
1380  DBG_HTML(t << "<!-- endMemberList -->" << endl)
1381 }
1382 
1383 // anonymous type:
1384 // 0 = single column right aligned
1385 // 1 = double column left aligned
1386 // 2 = single column left aligned
1387 void HtmlGenerator::startMemberItem(const char *anchor,int annoType,const char *inheritId)
1388 {
1389  DBG_HTML(t << "<!-- startMemberItem() -->" << endl)
1390  if (m_emptySection)
1391  {
1392  t << "<table class=\"memberdecls\">" << endl;
1393  m_emptySection=FALSE;
1394  }
1395  t << "<tr class=\"memitem:" << anchor;
1396  if (inheritId)
1397  {
1398  t << " inherit " << inheritId;
1399  }
1400  t << "\">";
1401  switch(annoType)
1402  {
1403  case 0: t << "<td class=\"memItemLeft\" align=\"right\" valign=\"top\">"; break;
1404  case 1: t << "<td class=\"memItemLeft\" >"; break;
1405  case 2: t << "<td class=\"memItemLeft\" valign=\"top\">"; break;
1406  default: t << "<td class=\"memTemplParams\" colspan=\"2\">"; break;
1407  }
1408 }
1409 
1411 {
1412  t << "</td></tr>";
1413  t << endl;
1414 }
1415 
1417 {
1418 }
1419 
1420 void HtmlGenerator::endMemberTemplateParams(const char *anchor,const char *inheritId)
1421 {
1422  t << "</td></tr>" << endl;
1423  t << "<tr class=\"memitem:" << anchor;
1424  if (inheritId)
1425  {
1426  t << " inherit " << inheritId;
1427  }
1428  t << "\"><td class=\"memTemplItemLeft\" align=\"right\" valign=\"top\">";
1429 }
1430 
1431 
1433 {
1434  DBG_HTML(t << "<!-- insertMemberAlign -->" << endl)
1435  QCString className = templ ? "memTemplItemRight" : "memItemRight";
1436  t << "&#160;</td><td class=\"" << className << "\" valign=\"bottom\">";
1437 }
1438 
1439 void HtmlGenerator::startMemberDescription(const char *anchor,const char *inheritId)
1440 {
1441  DBG_HTML(t << "<!-- startMemberDescription -->" << endl)
1442  if (m_emptySection)
1443  {
1444  t << "<table class=\"memberdecls\">" << endl;
1445  m_emptySection=FALSE;
1446  }
1447  t << "<tr class=\"memdesc:" << anchor;
1448  if (inheritId)
1449  {
1450  t << " inherit " << inheritId;
1451  }
1452  t << "\"><td class=\"mdescLeft\">&#160;</td><td class=\"mdescRight\">";
1453 }
1454 
1456 {
1457  DBG_HTML(t << "<!-- endMemberDescription -->" << endl)
1458  t << "<br /></td></tr>" << endl;
1459 }
1460 
1462 {
1463  DBG_HTML(t << "<!-- startMemberSections -->" << endl)
1464  m_emptySection=TRUE; // we postpone writing <table> until we actually
1465  // write a row to prevent empty tables, which
1466  // are not valid XHTML!
1467 }
1468 
1470 {
1471  DBG_HTML(t << "<!-- endMemberSections -->" << endl)
1472  if (!m_emptySection)
1473  {
1474  t << "</table>" << endl;
1475  }
1476 }
1477 
1478 void HtmlGenerator::startMemberHeader(const char *anchor)
1479 {
1480  DBG_HTML(t << "<!-- startMemberHeader -->" << endl)
1481  if (!m_emptySection)
1482  {
1483  t << "</table>";
1484  m_emptySection=TRUE;
1485  }
1486  if (m_emptySection)
1487  {
1488  t << "<table class=\"memberdecls\">" << endl;
1489  m_emptySection=FALSE;
1490  }
1491  t << "<tr class=\"heading\"><td colspan=\"2\"><h2 class=\"groupheader\">";
1492  if (anchor)
1493  {
1494  t << "<a name=\"" << anchor << "\"></a>" << endl;
1495  }
1496 }
1497 
1499 {
1500  DBG_HTML(t << "<!-- endMemberHeader -->" << endl)
1501  t << "</h2></td></tr>" << endl;
1502 }
1503 
1505 {
1506  DBG_HTML(t << "<!-- startMemberSubtitle -->" << endl)
1507  t << "<tr><td class=\"ititle\" colspan=\"2\">";
1508 }
1509 
1511 {
1512  DBG_HTML(t << "<!-- endMemberSubtitle -->" << endl)
1513  t << "</td></tr>" << endl;
1514 }
1515 
1517 {
1518  t << "<table>" << endl;
1519 }
1520 
1522 {
1523  t << "</table>" << endl;
1524 }
1525 
1527 {
1528  // inserted 'class = ...', 02 jan 2002, jh
1529  t << " <tr><td class=\"indexkey\">";
1530 }
1531 
1533 {
1534  t << "</td>";
1535 }
1536 
1538 {
1539  // inserted 'class = ...', 02 jan 2002, jh
1540  t << "<td class=\"indexvalue\">";
1541 }
1542 
1543 void HtmlGenerator::endIndexValue(const char *,bool)
1544 {
1545  t << "</td></tr>" << endl;
1546 }
1547 
1549 {
1550  DBG_HTML(t << "<!-- startMemberDocList -->" << endl;)
1551 }
1552 
1554 {
1555  DBG_HTML(t << "<!-- endMemberDocList -->" << endl;)
1556 }
1557 
1558 void HtmlGenerator::startMemberDoc( const char *clName, const char *memName,
1559  const char *anchor, const char *title,
1560  int memCount, int memTotal, bool showInline)
1561 {
1562  DBG_HTML(t << "<!-- startMemberDoc -->" << endl;)
1563  t << "\n<h2 class=\"memtitle\">"
1564  << "<span class=\"permalink\"><a href=\"#" << anchor << "\">&sect;&nbsp;</a></span>"
1565  << title;
1566  if (memTotal>1)
1567  {
1568  t << " <span class=\"overload\">[" << memCount << "/" << memTotal <<"]</span>";
1569  }
1570  t << "</h2>"
1571  << endl;
1572  t << "\n<div class=\"memitem\">" << endl;
1573  t << "<div class=\"memproto\">" << endl;
1574 }
1575 
1577 {
1578  DBG_HTML(t << "<!-- startMemberDocPrefixItem -->" << endl;)
1579  t << "<div class=\"memtemplate\">" << endl;
1580 }
1581 
1583 {
1584  DBG_HTML(t << "<!-- endMemberDocPrefixItem -->" << endl;)
1585  t << "</div>" << endl;
1586 }
1587 
1589 {
1590  DBG_HTML(t << "<!-- startMemberDocName -->" << endl;)
1591 
1592  t << " <table class=\"memname\">" << endl;
1593 
1594  t << " <tr>" << endl;
1595  t << " <td class=\"memname\">";
1596 }
1597 
1599 {
1600  DBG_HTML(t << "<!-- endMemberDocName -->" << endl;)
1601  t << "</td>" << endl;
1602 }
1603 
1605 {
1606  DBG_HTML(t << "<!-- startParameterList -->" << endl;)
1607  t << " <td>";
1608  if (openBracket) t << "(";
1609  t << "</td>" << endl;
1610 }
1611 
1612 void HtmlGenerator::startParameterType(bool first,const char *key)
1613 {
1614  if (first)
1615  {
1616  DBG_HTML(t << "<!-- startFirstParameterType -->" << endl;)
1617  t << " <td class=\"paramtype\">";
1618  }
1619  else
1620  {
1621  DBG_HTML(t << "<!-- startParameterType -->" << endl;)
1622  t << " <tr>" << endl;
1623  t << " <td class=\"paramkey\">";
1624  if (key) t << key;
1625  t << "</td>" << endl;
1626  t << " <td></td>" << endl;
1627  t << " <td class=\"paramtype\">";
1628  }
1629 }
1630 
1632 {
1633  DBG_HTML(t << "<!-- endParameterType -->" << endl;)
1634  t << "&#160;</td>" << endl;
1635 }
1636 
1637 void HtmlGenerator::startParameterName(bool /*oneArgOnly*/)
1638 {
1639  DBG_HTML(t << "<!-- startParameterName -->" << endl;)
1640  t << " <td class=\"paramname\">";
1641 }
1642 
1643 void HtmlGenerator::endParameterName(bool last,bool emptyList,bool closeBracket)
1644 {
1645  DBG_HTML(t << "<!-- endParameterName -->" << endl;)
1646  if (last)
1647  {
1648  if (emptyList)
1649  {
1650  if (closeBracket) t << "</td><td>)";
1651  t << "</td>" << endl;
1652  t << " <td>";
1653  }
1654  else
1655  {
1656  t << "&#160;</td>" << endl;
1657  t << " </tr>" << endl;
1658  t << " <tr>" << endl;
1659  t << " <td></td>" << endl;
1660  t << " <td>";
1661  if (closeBracket) t << ")";
1662  t << "</td>" << endl;
1663  t << " <td></td><td>";
1664  }
1665  }
1666  else
1667  {
1668  t << "</td>" << endl;
1669  t << " </tr>" << endl;
1670  }
1671 }
1672 
1674 {
1675  DBG_HTML(t << "<!-- endParameterList -->" << endl;)
1676  t << "</td>" << endl;
1677  t << " </tr>" << endl;
1678 }
1679 
1680 void HtmlGenerator::exceptionEntry(const char* prefix,bool closeBracket)
1681 {
1682  DBG_HTML(t << "<!-- exceptionEntry -->" << endl;)
1683  t << "</td>" << endl;
1684  t << " </tr>" << endl;
1685  t << " <tr>" << endl;
1686  t << " <td align=\"right\">";
1687  // colspan 2 so it gets both parameter type and parameter name columns
1688  if (prefix)
1689  t << prefix << "</td><td>(</td><td colspan=\"2\">";
1690  else if (closeBracket)
1691  t << "</td><td>)</td><td></td><td>";
1692  else
1693  t << "</td><td></td><td colspan=\"2\">";
1694 }
1695 
1696 void HtmlGenerator::endMemberDoc(bool hasArgs)
1697 {
1698  DBG_HTML(t << "<!-- endMemberDoc -->" << endl;)
1699  if (!hasArgs)
1700  {
1701  t << " </tr>" << endl;
1702  }
1703  t << " </table>" << endl;
1704  // t << "</div>" << endl;
1705 }
1706 
1708 {
1710 }
1711 
1713 {
1714  bool generateLegend = Config_getBool(GENERATE_LEGEND);
1715  bool umlLook = Config_getBool(UML_LOOK);
1720 
1721  g.writeGraph(t,GOF_BITMAP,EOF_Html,dir,fileName,relPath,TRUE,TRUE,m_sectionCount);
1722  if (generateLegend && !umlLook)
1723  {
1724  t << "<center><span class=\"legend\">[";
1725  startHtmlLink(relPath+"graph_legend"+Doxygen::htmlFileExtension);
1726  t << theTranslator->trLegend();
1727  endHtmlLink();
1728  t << "]</span></center>";
1729  }
1730 
1732  m_sectionCount++;
1733 }
1734 
1736 {
1738 }
1739 
1741 {
1746 
1748 
1750  m_sectionCount++;
1751 }
1752 
1754 {
1756 }
1757 
1759 {
1764 
1766 
1768  m_sectionCount++;
1769 }
1770 
1772 {
1774 }
1775 
1777 {
1782 
1784 
1786  m_sectionCount++;
1787 }
1788 
1790 {
1792 }
1793 
1795 {
1800 
1802 
1804  m_sectionCount++;
1805 }
1806 
1808 {
1809  g.writeGraph(t,dir,fileName);
1810 }
1811 
1813 {
1814  t << "<tr><td colspan=\"2\"><div class=\"groupHeader\">";
1815 }
1816 
1818 {
1819  t << "</div></td></tr>" << endl;
1820 }
1821 
1823 {
1824  t << "<tr><td colspan=\"2\"><div class=\"groupText\">";
1825 }
1826 
1828 {
1829  t << "</div></td></tr>" << endl;
1830 }
1831 
1833 {
1834 }
1835 
1837 {
1838 }
1839 
1841 {
1842  DBG_HTML(t << "<!-- startIndent -->" << endl;)
1843 
1844  t << "<div class=\"memdoc\">\n";
1845 }
1846 
1848 {
1849  DBG_HTML(t << "<!-- endIndent -->" << endl;)
1850  t << endl << "</div>" << endl << "</div>" << endl;
1851 }
1852 
1853 void HtmlGenerator::addIndexItem(const char *,const char *)
1854 {
1855 }
1856 
1858 {
1859  int i;
1860  for (i=0;i<n;i++)
1861  {
1862  t << "&#160;";
1863  }
1864 }
1865 
1866 void HtmlGenerator::startDescTable(const char *title)
1867 {
1868  t << "<table class=\"fieldtable\">" << endl
1869  << "<tr><th colspan=\"2\">" << title << "</th></tr>";
1870 }
1872 {
1873  t << "</table>" << endl;
1874 }
1875 
1877 {
1878  t << "<tr>";
1879 }
1880 
1882 {
1883  t << "</tr>" << endl;
1884 }
1885 
1887 {
1888  t << "<td class=\"fieldname\">";
1889 }
1890 
1892 {
1893  t << "&#160;</td>";
1894 }
1895 
1897 {
1898  t << "<td class=\"fielddoc\">";
1899 }
1900 
1902 {
1903  t << "</td>";
1904 }
1905 
1907  const char *filename,const char *anchor,
1908  const char *title)
1909 {
1910  t << "<dl><dt><b>";
1911  if (filename)
1912  {
1913  writeObjectLink(0,filename,anchor,title);
1914  }
1915  else
1916  {
1917  docify(title);
1918  }
1919  t << "</b></dt>";
1920 }
1921 
1923 {
1924  t << "</dl>";
1925 }
1926 
1928  const char *title)
1929 {
1930  t << "<dl><dt><b>";
1931  docify(title);
1932  t << "</b></dt>";
1933 }
1934 
1936 {
1937  t << "</dl>";
1938 }
1939 
1941 {
1942  HtmlDocVisitor *visitor = new HtmlDocVisitor(t,m_codeGen,ctx);
1943  n->accept(visitor);
1944  delete visitor;
1945 }
1946 
1947 //---------------- helpers for index generation -----------------------------
1948 
1949 static void startQuickIndexList(FTextStream &t,bool compact,bool topLevel=TRUE)
1950 {
1951  if (compact)
1952  {
1953  if (topLevel)
1954  {
1955  t << " <div id=\"navrow1\" class=\"tabs\">\n";
1956  }
1957  else
1958  {
1959  t << " <div id=\"navrow2\" class=\"tabs2\">\n";
1960  }
1961  t << " <ul class=\"tablist\">\n";
1962  }
1963  else
1964  {
1965  t << "<ul>";
1966  }
1967 }
1968 
1969 static void endQuickIndexList(FTextStream &t,bool compact)
1970 {
1971  if (compact)
1972  {
1973  t << " </ul>\n";
1974  t << " </div>\n";
1975  }
1976  else
1977  {
1978  t << "</ul>\n";
1979  }
1980 }
1981 
1982 static void startQuickIndexItem(FTextStream &t,const char *l,
1983  bool hl,bool /*compact*/,
1984  const QCString &relPath)
1985 {
1986  t << " <li";
1987  if (hl)
1988  {
1989  t << " class=\"current\"";
1990  }
1991  t << ">";
1992  if (l) t << "<a href=\"" << correctURL(l,relPath) << "\">";
1993  t << "<span>";
1994 }
1995 
1996 static void endQuickIndexItem(FTextStream &t,const char *l)
1997 {
1998  t << "</span>";
1999  if (l) t << "</a>";
2000  t << "</li>\n";
2001 }
2002 
2004 {
2005  static bool showFiles = Config_getBool(SHOW_FILES);
2006  static bool showNamespaces = Config_getBool(SHOW_NAMESPACES);
2007  switch (kind)
2008  {
2009  case LayoutNavEntry::MainPage: return TRUE;
2010  case LayoutNavEntry::User: return TRUE;
2011  case LayoutNavEntry::UserGroup: return TRUE;
2012  case LayoutNavEntry::Pages: return indexedPages>0;
2014  case LayoutNavEntry::Namespaces: return documentedNamespaces>0 && showNamespaces;
2015  case LayoutNavEntry::NamespaceList: return documentedNamespaces>0 && showNamespaces;
2022  case LayoutNavEntry::Files: return documentedHtmlFiles>0 && showFiles;
2023  case LayoutNavEntry::FileList: return documentedHtmlFiles>0 && showFiles;
2025  //case LayoutNavEntry::Dirs: return documentedDirs>0;
2027  }
2028  return FALSE;
2029 }
2030 
2031 static void renderQuickLinksAsTree(FTextStream &t,const QCString &relPath,LayoutNavEntry *root)
2032 
2033 {
2034  QListIterator<LayoutNavEntry> li(root->children());
2035  LayoutNavEntry *entry;
2036  int count=0;
2037  for (li.toFirst();(entry=li.current());++li)
2038  {
2039  if (entry->visible() && quickLinkVisible(entry->kind())) count++;
2040  }
2041  if (count>0) // at least one item is visible
2042  {
2043  startQuickIndexList(t,FALSE);
2044  for (li.toFirst();(entry=li.current());++li)
2045  {
2046  if (entry->visible() && quickLinkVisible(entry->kind()))
2047  {
2048  QCString url = entry->url();
2049  t << "<li><a href=\"" << relPath << url << "\"><span>";
2050  t << fixSpaces(entry->title());
2051  t << "</span></a>\n";
2052  // recursive into child list
2053  renderQuickLinksAsTree(t,relPath,entry);
2054  t << "</li>";
2055  }
2056  }
2057  endQuickIndexList(t,FALSE);
2058  }
2059 }
2060 
2061 
2062 static void renderQuickLinksAsTabs(FTextStream &t,const QCString &relPath,
2063  LayoutNavEntry *hlEntry,LayoutNavEntry::Kind kind,
2064  bool highlightParent,bool highlightSearch)
2065 {
2066  if (hlEntry->parent()) // first draw the tabs for the parent of hlEntry
2067  {
2068  renderQuickLinksAsTabs(t,relPath,hlEntry->parent(),kind,highlightParent,highlightSearch);
2069  }
2070  if (hlEntry->parent() && hlEntry->parent()->children().count()>0) // draw tabs for row containing hlEntry
2071  {
2072  bool topLevel = hlEntry->parent()->parent()==0;
2073  QListIterator<LayoutNavEntry> li(hlEntry->parent()->children());
2074  LayoutNavEntry *entry;
2075 
2076  int count=0;
2077  for (li.toFirst();(entry=li.current());++li)
2078  {
2079  if (entry->visible() && quickLinkVisible(entry->kind())) count++;
2080  }
2081  if (count>0) // at least one item is visible
2082  {
2083  startQuickIndexList(t,TRUE,topLevel);
2084  for (li.toFirst();(entry=li.current());++li)
2085  {
2086  if (entry->visible() && quickLinkVisible(entry->kind()))
2087  {
2088  QCString url = entry->url();
2089  startQuickIndexItem(t,url,
2090  entry==hlEntry &&
2091  (entry->children().count()>0 ||
2092  (entry->kind()==kind && !highlightParent)
2093  ),
2094  TRUE,relPath);
2095  t << fixSpaces(entry->title());
2096  endQuickIndexItem(t,url);
2097  }
2098  }
2099  if (hlEntry->parent()==LayoutDocManager::instance().rootNavEntry()) // first row is special as it contains the search box
2100  {
2101  static bool searchEngine = Config_getBool(SEARCHENGINE);
2102  static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
2103  if (searchEngine)
2104  {
2105  t << " <li>\n";
2106  if (!serverBasedSearch) // pure client side search
2107  {
2108  writeClientSearchBox(t,relPath);
2109  t << " </li>\n";
2110  }
2111  else // server based search
2112  {
2113  writeServerSearchBox(t,relPath,highlightSearch);
2114  if (!highlightSearch)
2115  {
2116  t << " </li>\n";
2117  }
2118  }
2119  }
2120  if (!highlightSearch) // on the search page the index will be ended by the
2121  // page itself
2122  {
2123  endQuickIndexList(t,TRUE);
2124  }
2125  }
2126  else // normal case for other rows than first one
2127  {
2128  endQuickIndexList(t,TRUE);
2129  }
2130  }
2131  }
2132 }
2133 
2134 static void writeDefaultQuickLinks(FTextStream &t,bool compact,
2135  HighlightedItem hli,
2136  const char *file,
2137  const QCString &relPath)
2138 {
2139  static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
2140  static bool searchEngine = Config_getBool(SEARCHENGINE);
2141  static bool externalSearch = Config_getBool(EXTERNAL_SEARCH);
2143 
2144  if (compact)
2145  {
2146  QCString searchPage;
2147  if (externalSearch)
2148  {
2149  searchPage = "search" + Doxygen::htmlFileExtension;
2150  }
2151  else
2152  {
2153  searchPage = "search.php";
2154  }
2155  t << "<script type=\"text/javascript\" src=\"" << relPath << "menudata.js\"></script>" << endl;
2156  t << "<script type=\"text/javascript\" src=\"" << relPath << "menu.js\"></script>" << endl;
2157  t << "<script type=\"text/javascript\">" << endl;
2158  t << "$(function() {" << endl;
2159  t << " initMenu('" << relPath << "',"
2160  << (searchEngine?"true":"false") << ","
2161  << (serverBasedSearch?"true":"false") << ",'"
2162  << searchPage << "','"
2163  << theTranslator->trSearch() << "');" << endl;
2164  if (Config_getBool(SEARCHENGINE))
2165  {
2166  if (!serverBasedSearch)
2167  {
2168  t << " $(document).ready(function() { init_search(); });\n";
2169  }
2170  else
2171  {
2172  t << " $(document).ready(function() {\n"
2173  << " if ($('.searchresults').length > 0) { searchBox.DOMSearchField().focus(); }\n"
2174  << " });\n";
2175  }
2176  }
2177  t << "});" << endl;
2178  t << "</script>" << endl;
2179  t << "<div id=\"main-nav\"></div>" << endl;
2180  }
2181  else
2182  {
2183  renderQuickLinksAsTree(t,relPath,root);
2184  }
2185 }
2186 
2188 {
2189  t << "</div><!-- top -->" << endl;
2190 }
2191 
2192 QCString HtmlGenerator::writeSplitBarAsString(const char *name,const char *relpath)
2193 {
2194  static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2195  QCString result;
2196  // write split bar
2197  if (generateTreeView)
2198  {
2199  result = QCString(
2200  "<div id=\"side-nav\" class=\"ui-resizable side-nav-resizable\">\n"
2201  " <div id=\"nav-tree\">\n"
2202  " <div id=\"nav-tree-contents\">\n"
2203  " <div id=\"nav-sync\" class=\"sync\"></div>\n"
2204  " </div>\n"
2205  " </div>\n"
2206  " <div id=\"splitbar\" style=\"-moz-user-select:none;\" \n"
2207  " class=\"ui-resizable-handle\">\n"
2208  " </div>\n"
2209  "</div>\n"
2210  "<script type=\"text/javascript\">\n"
2211  "$(document).ready(function(){initNavTree('") +
2212  QCString(name) + Doxygen::htmlFileExtension +
2213  QCString("','") + relpath +
2214  QCString("');});\n"
2215  "</script>\n"
2216  "<div id=\"doc-content\">\n");
2217  }
2218  return result;
2219 }
2220 
2221 void HtmlGenerator::writeSplitBar(const char *name)
2222 {
2223  t << writeSplitBarAsString(name,relPath);
2224 }
2225 
2227 {
2228  t << substitute(s,"$relpath^",relPath);
2229 }
2230 
2232 {
2233  t << "<div class=\"contents\">" << endl;
2234 }
2235 
2237 {
2238  t << "</div><!-- contents -->" << endl;
2239 }
2240 
2241 void HtmlGenerator::writeQuickLinks(bool compact,HighlightedItem hli,const char *file)
2242 {
2243  writeDefaultQuickLinks(t,compact,hli,file,relPath);
2244 }
2245 
2246 // PHP based search script
2248 {
2249  static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2250  static bool disableIndex = Config_getBool(DISABLE_INDEX);
2251  static QCString projectName = Config_getString(PROJECT_NAME);
2252  static QCString htmlOutput = Config_getString(HTML_OUTPUT);
2253 
2254  // OPENSEARCH_PROVIDER {
2255  QCString configFileName = htmlOutput+"/search_config.php";
2256  QFile cf(configFileName);
2257  if (cf.open(IO_WriteOnly))
2258  {
2259  FTextStream t(&cf);
2260  t << "<script language=\"php\">\n\n";
2261  t << "$config = array(\n";
2262  t << " 'PROJECT_NAME' => \"" << convertToHtml(projectName) << "\",\n";
2263  t << " 'GENERATE_TREEVIEW' => " << (generateTreeView?"true":"false") << ",\n";
2264  t << " 'DISABLE_INDEX' => " << (disableIndex?"true":"false") << ",\n";
2265  t << ");\n\n";
2266  t << "$translator = array(\n";
2267  t << " 'search_results_title' => \"" << theTranslator->trSearchResultsTitle() << "\",\n";
2268  t << " 'search_results' => array(\n";
2269  t << " 0 => \"" << theTranslator->trSearchResults(0) << "\",\n";
2270  t << " 1 => \"" << theTranslator->trSearchResults(1) << "\",\n";
2271  t << " 2 => \"" << substitute(theTranslator->trSearchResults(2), "$", "\\$") << "\",\n";
2272  t << " ),\n";
2273  t << " 'search_matches' => \"" << theTranslator->trSearchMatches() << "\",\n";
2274  t << " 'search' => \"" << theTranslator->trSearch() << "\",\n";
2275  t << " 'split_bar' => \"" << substitute(substitute(writeSplitBarAsString("search",""), "\"","\\\""), "\n","\\n") << "\",\n";
2276  t << " 'logo' => \"" << substitute(substitute(writeLogoAsString(""), "\"","\\\""), "\n","\\n") << "\",\n";
2277  t << ");\n\n";
2278  t << "</script>\n";
2279  }
2280 
2281  ResourceMgr::instance().copyResource("search_functions.php",htmlOutput);
2282  ResourceMgr::instance().copyResource("search_opensearch.php",htmlOutput);
2283  // OPENSEARCH_PROVIDER }
2284 
2285  QCString fileName = htmlOutput+"/search.php";
2286  QFile f(fileName);
2287  if (f.open(IO_WriteOnly))
2288  {
2289  FTextStream t(&f);
2290  t << substituteHtmlKeywords(g_header,"Search","");
2291 
2292  t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen "
2293  << versionString << " -->" << endl;
2294  t << "<script type=\"text/javascript\">\n";
2295  t << "var searchBox = new SearchBox(\"searchBox\", \""
2296  << "search\",false,'" << theTranslator->trSearch() << "');\n";
2297  t << "</script>\n";
2298  if (!Config_getBool(DISABLE_INDEX))
2299  {
2300  writeDefaultQuickLinks(t,TRUE,HLI_Search,0,"");
2301  }
2302  else
2303  {
2304  t << "</div>" << endl;
2305  }
2306 
2307  t << "<script language=\"php\">\n";
2308  t << "require_once \"search_functions.php\";\n";
2309  t << "main();\n";
2310  t << "</script>\n";
2311 
2312  // Write empty navigation path, to make footer connect properly
2313  if (generateTreeView)
2314  {
2315  t << "</div><!-- doc-content -->\n";
2316  }
2317 
2318  writePageFooter(t,"Search","","");
2319  }
2320  QCString scriptName = htmlOutput+"/search/search.js";
2321  QFile sf(scriptName);
2322  if (sf.open(IO_WriteOnly))
2323  {
2324  FTextStream t(&sf);
2325  t << ResourceMgr::instance().getAsString("extsearch.js");
2326  }
2327  else
2328  {
2329  err("Failed to open file '%s' for writing...\n",scriptName.data());
2330  }
2331 }
2332 
2334 {
2335  static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2336  static bool disableIndex = Config_getBool(DISABLE_INDEX);
2337  QCString fileName = Config_getString(HTML_OUTPUT)+"/search"+Doxygen::htmlFileExtension;
2338  QFile f(fileName);
2339  if (f.open(IO_WriteOnly))
2340  {
2341  FTextStream t(&f);
2342  t << substituteHtmlKeywords(g_header,"Search","");
2343 
2344  t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen "
2345  << versionString << " -->" << endl;
2346  t << "<script type=\"text/javascript\">\n";
2347  t << "var searchBox = new SearchBox(\"searchBox\", \""
2348  << "search\",false,'" << theTranslator->trSearch() << "');\n";
2349  t << "</script>\n";
2350  if (!Config_getBool(DISABLE_INDEX))
2351  {
2352  writeDefaultQuickLinks(t,TRUE,HLI_Search,0,"");
2353  t << " <input type=\"text\" id=\"MSearchField\" name=\"query\" value=\"\" size=\"20\" accesskey=\"S\" onfocus=\"searchBox.OnSearchFieldFocus(true)\" onblur=\"searchBox.OnSearchFieldFocus(false)\"/>\n";
2354  t << " </form>\n";
2355  t << " </div><div class=\"right\"></div>\n";
2356  t << " </div>\n";
2357  t << " </li>\n";
2358  t << " </ul>\n";
2359  t << " </div>\n";
2360  t << "</div>\n";
2361  }
2362  else
2363  {
2364  t << "</div>" << endl;
2365  }
2366  t << writeSplitBarAsString("search","");
2367  t << "<div class=\"header\">" << endl;
2368  t << " <div class=\"headertitle\">" << endl;
2369  t << " <div class=\"title\">" << theTranslator->trSearchResultsTitle() << "</div>" << endl;
2370  t << " </div>" << endl;
2371  t << "</div>" << endl;
2372  t << "<div class=\"contents\">" << endl;
2373 
2374  t << "<div id=\"searchresults\"></div>" << endl;
2375  t << "</div>" << endl;
2376 
2377  if (generateTreeView)
2378  {
2379  t << "</div><!-- doc-content -->" << endl;
2380  }
2381 
2382  writePageFooter(t,"Search","","");
2383 
2384  }
2385  QCString scriptName = Config_getString(HTML_OUTPUT)+"/search/search.js";
2386  QFile sf(scriptName);
2387  if (sf.open(IO_WriteOnly))
2388  {
2389  FTextStream t(&sf);
2390  t << "var searchResultsText=["
2391  << "\"" << theTranslator->trSearchResults(0) << "\","
2392  << "\"" << theTranslator->trSearchResults(1) << "\","
2393  << "\"" << theTranslator->trSearchResults(2) << "\"];" << endl;
2394  t << "var serverUrl=\"" << Config_getString(SEARCHENGINE_URL) << "\";" << endl;
2395  t << "var tagMap = {" << endl;
2396  bool first=TRUE;
2397  // add search mappings
2398  QStrList &extraSearchMappings = Config_getList(EXTRA_SEARCH_MAPPINGS);
2399  char *ml=extraSearchMappings.first();
2400  while (ml)
2401  {
2402  QCString mapLine = ml;
2403  int eqPos = mapLine.find('=');
2404  if (eqPos!=-1) // tag command contains a destination
2405  {
2406  QCString tagName = mapLine.left(eqPos).stripWhiteSpace();
2407  QCString destName = mapLine.right(mapLine.length()-eqPos-1).stripWhiteSpace();
2408  if (!tagName.isEmpty())
2409  {
2410  if (!first) t << "," << endl;
2411  t << " \"" << tagName << "\": \"" << destName << "\"";
2412  first=FALSE;
2413  }
2414  }
2415  ml=extraSearchMappings.next();
2416  }
2417  if (!first) t << endl;
2418  t << "};" << endl << endl;
2419  t << ResourceMgr::instance().getAsString("extsearch.js");
2420  t << endl;
2421  t << "$(document).ready(function() {" << endl;
2422  t << " var query = trim(getURLParameter('query'));" << endl;
2423  t << " if (query) {" << endl;
2424  t << " searchFor(query,0,20);" << endl;
2425  t << " } else {" << endl;
2426  t << " var results = $('#results');" << endl;
2427  t << " results.html('<p>" << theTranslator->trSearchResults(0) << "</p>');" << endl;
2428  t << " }" << endl;
2429  t << "});" << endl;
2430  }
2431  else
2432  {
2433  err("Failed to open file '%s' for writing...\n",scriptName.data());
2434  }
2435 }
2436 
2437 void HtmlGenerator::startConstraintList(const char *header)
2438 {
2439  t << "<div class=\"typeconstraint\">" << endl;
2440  t << "<dl><dt><b>" << header << "</b></dt><dd>" << endl;
2441  t << "<table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">" << endl;
2442 }
2443 
2445 {
2446  t << "<tr><td valign=\"top\"><em>";
2447 }
2448 
2450 {
2451  t << "</em></td>";
2452 }
2453 
2455 {
2456  t << "<td>&#160;:</td><td valign=\"top\"><em>";
2457 }
2458 
2460 {
2461  t << "</em></td>";
2462 }
2463 
2465 {
2466  t << "<td>&#160;";
2467 }
2468 
2470 {
2471  t << "</td></tr>" << endl;
2472 }
2473 
2475 {
2476  t << "</table>" << endl;
2477  t << "</dd>" << endl;
2478  t << "</dl>" << endl;
2479  t << "</div>" << endl;
2480 }
2481 
2482 void HtmlGenerator::lineBreak(const char *style)
2483 {
2484  if (style)
2485  {
2486  t << "<br class=\"" << style << "\" />" << endl;
2487  }
2488  else
2489  {
2490  t << "<br />" << endl;
2491  }
2492 }
2493 
2495 {
2496  t << "<div class=\"header\">" << endl;
2497 }
2498 
2500 {
2501  t << " <div class=\"headertitle\">" << endl;
2502  startTitle();
2503 }
2504 
2505 void HtmlGenerator::endTitleHead(const char *,const char *)
2506 {
2507  endTitle();
2508  t << " </div>" << endl;
2509 }
2510 
2512 {
2513  t << "</div><!--header-->" << endl;
2514 }
2515 
2517 {
2518  if (m_emptySection)
2519  {
2520  t << "<table class=\"memberdecls\">" << endl;
2521  m_emptySection=FALSE;
2522  }
2523  t << "<tr><td colspan=\"2\"><h3>";
2524 }
2525 
2527 {
2528  t << "</h3></td></tr>" << endl;
2529 }
2530 
2532 {
2533  DBG_HTML(t << "<!-- startMemberDocSimple -->" << endl;)
2534  t << "<table class=\"fieldtable\">" << endl;
2535  t << "<tr><th colspan=\"" << (isEnum?"2":"3") << "\">";
2536  t << (isEnum? theTranslator->trEnumerationValues() :
2537  theTranslator->trCompoundMembers()) << "</th></tr>" << endl;
2538 }
2539 
2541 {
2542  DBG_HTML(t << "<!-- endMemberDocSimple -->" << endl;)
2543  t << "</table>" << endl;
2544 }
2545 
2547 {
2548  DBG_HTML(t << "<!-- startInlineMemberType -->" << endl;)
2549  t << "<tr><td class=\"fieldtype\">" << endl;
2550 }
2551 
2553 {
2554  DBG_HTML(t << "<!-- endInlineMemberType -->" << endl;)
2555  t << "</td>" << endl;
2556 }
2557 
2559 {
2560  DBG_HTML(t << "<!-- startInlineMemberName -->" << endl;)
2561  t << "<td class=\"fieldname\">" << endl;
2562 }
2563 
2565 {
2566  DBG_HTML(t << "<!-- endInlineMemberName -->" << endl;)
2567  t << "</td>" << endl;
2568 }
2569 
2571 {
2572  DBG_HTML(t << "<!-- startInlineMemberDoc -->" << endl;)
2573  t << "<td class=\"fielddoc\">" << endl;
2574 }
2575 
2577 {
2578  DBG_HTML(t << "<!-- endInlineMemberDoc -->" << endl;)
2579  t << "</td></tr>" << endl;
2580 }
2581 
2583 {
2584  DBG_HTML(t << "<!-- startLabels -->" << endl;)
2585  t << "<span class=\"mlabels\">";
2586 }
2587 
2588 void HtmlGenerator::writeLabel(const char *l,bool /*isLast*/)
2589 {
2590  DBG_HTML(t << "<!-- writeLabel(" << l << ") -->" << endl;)
2591  //t << "<tt>[" << l << "]</tt>";
2592  //if (!isLast) t << ", ";
2593  t << "<span class=\"mlabel\">" << l << "</span>";
2594 }
2595 
2597 {
2598  DBG_HTML(t << "<!-- endLabels -->" << endl;)
2599  t << "</span>";
2600 }
2601 
2603  const char *id, const char *ref,
2604  const char *file, const char *anchor,
2605  const char *title, const char *name)
2606 {
2607  DBG_HTML(t << "<!-- writeInheritedSectionTitle -->" << endl;)
2608  QCString a = anchor;
2609  if (!a.isEmpty()) a.prepend("#");
2610  QCString classLink = QCString("<a class=\"el\" href=\"");
2611  if (ref)
2612  {
2613  classLink+= externalLinkTarget() + externalRef(relPath,ref,TRUE);
2614  }
2615  else
2616  {
2617  classLink+=relPath;
2618  }
2619  classLink+=file+Doxygen::htmlFileExtension+a;
2620  classLink+=QCString("\">")+convertToHtml(name,FALSE)+"</a>";
2621  t << "<tr class=\"inherit_header " << id << "\">"
2622  << "<td colspan=\"2\" onclick=\"javascript:toggleInherit('" << id << "')\">"
2623  << "<img src=\"" << relPath << "closed.png\" alt=\"-\"/>&#160;"
2624  << theTranslator->trInheritedFrom(convertToHtml(title,FALSE),classLink)
2625  << "</td></tr>" << endl;
2626 }
2627 
2628 void HtmlGenerator::writeSummaryLink(const char *file,const char *anchor,const char *title,bool first)
2629 {
2630  if (first)
2631  {
2632  t << " <div class=\"summary\">\n";
2633  }
2634  else
2635  {
2636  t << " &#124;\n";
2637  }
2638  t << "<a href=\"";
2639  if (file)
2640  {
2641  t << relPath << file;
2643  }
2644  else
2645  {
2646  t << "#";
2647  t << anchor;
2648  }
2649  t << "\">";
2650  t << title;
2651  t << "</a>";
2652 }
2653 
2654 void HtmlGenerator::endMemberDeclaration(const char *anchor,const char *inheritId)
2655 {
2656  t << "<tr class=\"separator:" << anchor;
2657  if (inheritId)
2658  {
2659  t << " inherit " << inheritId;
2660  }
2661  t << "\"><td class=\"memSeparator\" colspan=\"2\">&#160;</td></tr>\n";
2662 }
2663 
2664 void HtmlGenerator::setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile)
2665 {
2667  {
2668  Doxygen::searchIndex->setCurrentDoc(context,anchor,isSourceFile);
2669  }
2670 }
2671 
2672 void HtmlGenerator::addWord(const char *word,bool hiPriority)
2673 {
2675  {
2676  Doxygen::searchIndex->addWord(word,hiPriority);
2677  }
2678 }
2679