Doxygen
Loading...
Searching...
No Matches
htmlgen.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2023 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include <stdlib.h>
17#include <assert.h>
18
19#include <mutex>
20
21#include "message.h"
22#include "htmlgen.h"
23#include "config.h"
24#include "util.h"
25#include "doxygen.h"
26#include "diagram.h"
27#include "version.h"
28#include "dot.h"
29#include "dotcallgraph.h"
30#include "dotclassgraph.h"
31#include "dotdirdeps.h"
34#include "dotincldepgraph.h"
35#include "language.h"
36#include "htmlhelp.h"
37#include "docparser.h"
38#include "docnode.h"
39#include "htmldocvisitor.h"
40#include "searchindex.h"
41#include "pagedef.h"
42#include "debug.h"
43#include "dirdef.h"
44#include "vhdldocgen.h"
45#include "layout.h"
46#include "image.h"
47#include "ftvhelp.h"
48#include "resourcemgr.h"
49#include "tooltip.h"
50#include "growbuf.h"
51#include "fileinfo.h"
52#include "dir.h"
53#include "utf8.h"
54#include "textstream.h"
55#include "indexlist.h"
56#include "datetime.h"
57#include "portable.h"
58#include "outputlist.h"
59#include "stringutil.h"
60
61//#define DBG_HTML(x) x;
62#define DBG_HTML(x)
63
70static constexpr auto hex="0123456789ABCDEF";
71
72static const SelectionMarkerInfo htmlMarkerInfo = { '<', "<!--BEGIN ",10,"<!--END ",8,"-->",3 };
73
74// note: this is only active if DISABLE_INDEX=YES, if DISABLE_INDEX is disabled, this
75// part will be rendered inside menu.js
76static void writeClientSearchBox(TextStream &t,const QCString &relPath)
77{
78 t << " <div id=\"MSearchBox\" class=\"MSearchBoxInactive\">\n";
79 t << " <span class=\"left\">\n";
80 t << " <span id=\"MSearchSelect\" class=\"search-icon\" ";
81 t << "onmouseover=\"return searchBox.OnSearchSelectShow()\" ";
82 t << "onmouseout=\"return searchBox.OnSearchSelectHide()\">";
83 t << "<span class=\"search-icon-dropdown\"></span></span>\n";
84 t << " <input type=\"text\" id=\"MSearchField\" value=\"\" placeholder=\""
85 << theTranslator->trSearch() << "\" accesskey=\"S\"\n";
86 t << " onfocus=\"searchBox.OnSearchFieldFocus(true)\" \n";
87 t << " onblur=\"searchBox.OnSearchFieldFocus(false)\" \n";
88 t << " onkeyup=\"searchBox.OnSearchFieldChange(event)\"/>\n";
89 t << " </span><span class=\"right\">\n";
90 t << " <a id=\"MSearchClose\" href=\"javascript:searchBox.CloseResultsWindow()\">"
91 << "<div id=\"MSearchCloseImg\" class=\"close-icon\"></div></a>\n";
92 t << " </span>\n";
93 t << " </div>\n";
94}
95
96// note: this is only active if DISABLE_INDEX=YES. if DISABLE_INDEX is disabled, this
97// part will be rendered inside menu.js
98static void writeServerSearchBox(TextStream &t,const QCString &relPath,bool highlightSearch)
99{
100 bool externalSearch = Config_getBool(EXTERNAL_SEARCH);
101 t << " <div id=\"MSearchBox\" class=\"MSearchBoxInactive\">\n";
102 t << " <div class=\"left\">\n";
103 t << " <form id=\"FSearchBox\" action=\"" << relPath;
104 if (externalSearch)
105 {
106 t << "search" << Doxygen::htmlFileExtension;
107 }
108 else
109 {
110 t << "search.php";
111 }
112 t << "\" method=\"get\">\n";
113 t << " <span id=\"MSearchSelectExt\" class=\"search-icon\"></span>\n";
114 if (!highlightSearch || !Config_getBool(HTML_DYNAMIC_MENUS))
115 {
116 t << " <input type=\"text\" id=\"MSearchField\" name=\"query\" value=\"\" placeholder=\""
117 << theTranslator->trSearch() << "\" size=\"20\" accesskey=\"S\" \n";
118 t << " onfocus=\"searchBox.OnSearchFieldFocus(true)\" \n";
119 t << " onblur=\"searchBox.OnSearchFieldFocus(false)\"/>\n";
120 t << " </form>\n";
121 t << " </div><div class=\"right\"></div>\n";
122 t << " </div>\n";
123 }
124}
125
126//------------------------------------------------------------------------
127/// Convert a set of LaTeX commands `\‍(re)newcommand` to a form readable by MathJax
128/// LaTeX syntax:
129/// ```
130/// \newcommand{\cmd}{replacement}
131/// or
132/// \renewcommand{\cmd}{replacement}
133/// ```
134/// MathJax syntax:
135/// ```
136/// cmd: "{replacement}"
137/// ```
138///
139/// LaTeX syntax:
140/// ```
141/// \newcommand{\cmd}[nr]{replacement}
142/// or
143/// \renewcommand{\cmd}[nr]{replacement}
144/// ```
145/// MathJax syntax:
146/// ```
147/// cmd: ["{replacement}",nr]
148/// ```
150{
151 QCString macrofile = Config_getString(FORMULA_MACROFILE);
152 if (macrofile.isEmpty()) return "";
153 QCString s = fileToString(macrofile);
154 macrofile = FileInfo(macrofile.str()).absFilePath();
155 size_t size = s.length();
156 GrowBuf out(size);
157 const char *data = s.data();
158 int line = 1;
159 int cnt = 0;
160 size_t i = 0;
161 QCString nr;
162 while (i < size)
163 {
164 nr = "";
165 // skip initial white space, but count lines
166 while (i < size && (data[i] == ' ' || data[i] == '\t' || data[i] == '\n'))
167 {
168 if (data[i] == '\n') line++;
169 i++;
170 }
171 if (i >= size) break;
172 // check for \newcommand or \renewcommand
173 if (data[i] != '\\')
174 {
175 warn(macrofile,line, "file contains non valid code, expected '\\' got '{:c}'",data[i]);
176 return "";
177 }
178 i++;
179 if (literal_at(data+i,"newcommand"))
180 {
181 i += strlen("newcommand");
182 }
183 else if (literal_at(data+i,"renewcommand"))
184 {
185 i += strlen("renewcommand");
186 }
187 else
188 {
189 warn(macrofile,line, "file contains non valid code, expected 'newcommand' or 'renewcommand'");
190 return "";
191 }
192 // handle {cmd}
193 if (data[i] != '{')
194 {
195 warn(macrofile,line, "file contains non valid code, expected '{{' got '{:c}'",data[i]);
196 return "";
197 }
198 i++;
199 if (data[i] != '\\')
200 {
201 warn(macrofile,line, "file contains non valid code, expected '\\' got '{:c}'",data[i]);
202 return "";
203 }
204 i++;
205 // run till }, i.e. cmd
206 out.addStr(" ");
207 while (i < size && (data[i] != '}')) out.addChar(data[i++]);
208 if (i >= size)
209 {
210 warn(macrofile,line, "file contains non valid code, no closing '}}' for command");
211 return "";
212 }
213 out.addChar(':');
214 out.addChar(' ');
215 i++;
216
217 if (data[i] == '[')
218 {
219 // handle [nr]
220 // run till ]
221 out.addChar('[');
222 i++;
223 while (i < size && (data[i] != ']')) nr += data[i++];
224 if (i >= size)
225 {
226 warn(macrofile,line, "file contains non valid code, no closing ']'");
227 return "";
228 }
229 i++;
230 }
231 else if (data[i] != '{')
232 {
233 warn(macrofile,line, "file contains non valid code, expected '[' or '{{' got '{:c}'",data[i]);
234 return "";
235 }
236 // handle {replacement}
237 // retest as the '[' part might have advanced so we can have a new '{'
238 if (data[i] != '{')
239 {
240 warn(macrofile,line, "file contains non valid code, expected '{{' got '{:c}'",data[i]);
241 return "";
242 }
243 out.addChar('"');
244 out.addChar('{');
245 i++;
246 // run till }
247 cnt = 1;
248 while (i < size && cnt)
249 {
250 switch(data[i])
251 {
252 case '\\':
253 out.addChar('\\'); // need to escape it for MathJax js code
254 out.addChar('\\');
255 i++;
256 if (data[i] == '\\') // we have an escaped backslash
257 {
258 out.addChar('\\');
259 out.addChar('\\');
260 i++;
261 }
262 else if (data[i] != '"') out.addChar(data[i++]); // double quote handled separately
263 break;
264 case '{':
265 cnt++;
266 out.addChar(data[i++]);
267 break;
268 case '}':
269 cnt--;
270 if (cnt) out.addChar(data[i]);
271 i++;
272 break;
273 case '"':
274 out.addChar('\\'); // need to escape it for MathJax js code
275 out.addChar(data[i++]);
276 break;
277 case '\n':
278 line++;
279 out.addChar(data[i++]);
280 break;
281 default:
282 out.addChar(data[i++]);
283 break;
284 }
285 }
286 if (i > size)
287 {
288 warn(macrofile,line, "file contains non valid code, no closing '}}' for replacement");
289 return "";
290 }
291 out.addChar('}');
292 out.addChar('"');
293 if (!nr.isEmpty())
294 {
295 out.addChar(',');
296 out.addStr(nr);
297 }
298 if (!nr.isEmpty())
299 {
300 out.addChar(']');
301 }
302 out.addChar(',');
303 out.addChar('\n');
304 }
305 out.addChar(0);
306 return out.get();
307}
308
309static QCString getSearchBox(bool serverSide, QCString relPath, bool highlightSearch)
310{
311 TextStream t;
312 if (serverSide)
313 {
314 writeServerSearchBox(t, relPath, highlightSearch);
315 }
316 else
317 {
318 writeClientSearchBox(t, relPath);
319 }
320 return t.str();
321}
322
324 const QCString &str,
325 const QCString &title,
326 const QCString &relPath,
327 const QCString &navPath=QCString())
328{
329 // Build CSS/JavaScript tags depending on treeview, search engine settings
330 QCString cssFile;
331 QCString generatedBy;
332 QCString treeViewCssJs;
333 QCString searchCssJs;
334 QCString searchBox;
335 QCString mathJaxJs;
336 QCString extraCssText;
337
338 QCString projectName = Config_getString(PROJECT_NAME);
339 bool treeView = Config_getBool(GENERATE_TREEVIEW);
340 bool searchEngine = Config_getBool(SEARCHENGINE);
341 bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
342 bool mathJax = Config_getBool(USE_MATHJAX);
343 QCString mathJaxFormat = Config_getEnumAsString(MATHJAX_FORMAT);
344 bool disableIndex = Config_getBool(DISABLE_INDEX);
345 bool hasProjectName = !projectName.isEmpty();
346 bool hasProjectNumber = !Config_getString(PROJECT_NUMBER).isEmpty();
347 bool hasProjectBrief = !Config_getString(PROJECT_BRIEF).isEmpty();
348 bool hasProjectLogo = !Config_getString(PROJECT_LOGO).isEmpty();
349 bool hasProjectIcon = !Config_getString(PROJECT_ICON).isEmpty();
350 bool hasFullSideBar = Config_getBool(FULL_SIDEBAR) && /*disableIndex &&*/ treeView;
351 bool hasCopyClipboard = Config_getBool(HTML_COPY_CLIPBOARD);
352 bool hasCookie = treeView || searchEngine || Config_getEnum(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::TOGGLE;
353 static bool titleArea = (hasProjectName || hasProjectBrief || hasProjectLogo || (disableIndex && searchEngine));
354
355 cssFile = Config_getString(HTML_STYLESHEET);
356 if (cssFile.isEmpty())
357 {
358 cssFile = "doxygen.css";
359 }
360 else
361 {
362 if (!cssFile.startsWith("http:") && !cssFile.startsWith("https:"))
363 {
364 FileInfo cssfi(cssFile.str());
365 if (cssfi.exists())
366 {
367 cssFile = cssfi.fileName();
368 }
369 else
370 {
371 cssFile = "doxygen.css";
372 }
373 }
374 }
375
376 extraCssText = "";
377 const StringVector &extraCssFile = Config_getList(HTML_EXTRA_STYLESHEET);
378 for (const auto &fileName : extraCssFile)
379 {
380 if (!fileName.empty())
381 {
382 QCString htmlStyleSheet = fileName.c_str();
383 if (htmlStyleSheet.startsWith("http:") || htmlStyleSheet.startsWith("https:"))
384 {
385 extraCssText += "<link href=\""+htmlStyleSheet+"\" rel=\"stylesheet\" type=\"text/css\"/>\n";
386 }
387 else
388 {
389 FileInfo fi(fileName);
390 if (fi.exists())
391 {
392 extraCssText += "<link href=\"$relpath^"+stripPath(fileName.c_str())+"\" rel=\"stylesheet\" type=\"text/css\"/>\n";
393 }
394 }
395 }
396 }
397
398 switch (Config_getEnum(TIMESTAMP))
399 {
400 case TIMESTAMP_t::YES:
401 case TIMESTAMP_t::DATETIME:
402 generatedBy = theTranslator->trGeneratedAt(dateToString(DateTimeType::DateTime),
403 convertToHtml(Config_getString(PROJECT_NAME)));
404 break;
405 case TIMESTAMP_t::DATE:
406 generatedBy = theTranslator->trGeneratedAt(dateToString(DateTimeType::Date),
407 convertToHtml(Config_getString(PROJECT_NAME)));
408 break;
409 case TIMESTAMP_t::NO:
410 generatedBy = theTranslator->trGeneratedBy();
411 break;
412 }
413 if (treeView)
414 {
415 treeViewCssJs = "<link href=\"$relpath^navtree.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
416 "<script type=\"text/javascript\" src=\"$relpath^navtreedata.js\"></script>\n"
417 "<script type=\"text/javascript\" src=\"$relpath^navtree.js\"></script>\n";
418 }
419
420 if (searchEngine)
421 {
422 searchCssJs = "<link href=\"$relpath^search/search.css\" rel=\"stylesheet\" type=\"text/css\"/>\n";
423 if (!serverBasedSearch)
424 {
425 searchCssJs += "<script type=\"text/javascript\" src=\"$relpath^search/searchdata.js\"></script>\n";
426 }
427 searchCssJs += "<script type=\"text/javascript\" src=\"$relpath^search/search.js\"></script>\n";
428
429 if (!serverBasedSearch)
430 {
431 if (disableIndex || !Config_getBool(HTML_DYNAMIC_MENUS) || Config_getBool(FULL_SIDEBAR))
432 {
433 searchCssJs += "<script type=\"text/javascript\">\n"
434 " $(function() { init_search(); });\n"
435 "</script>";
436 }
437 }
438 else
439 {
440 if (disableIndex || !Config_getBool(HTML_DYNAMIC_MENUS))
441 {
442 searchCssJs += "<script type=\"text/javascript\">\n"
443 " $(function() {\n"
444 " if ($('.searchresults').length > 0) { searchBox.DOMSearchField().focus(); }\n"
445 " });\n"
446 "</script>\n";
447 }
448
449 // OPENSEARCH_PROVIDER {
450 searchCssJs += "<link rel=\"search\" href=\"" + relPath +
451 "search_opensearch.php?v=opensearch.xml\" "
452 "type=\"application/opensearchdescription+xml\" title=\"" +
453 (hasProjectName ? projectName : QCString("Doxygen")) +
454 "\"/>";
455 // OPENSEARCH_PROVIDER }
456 }
457 searchBox = getSearchBox(serverBasedSearch, relPath, FALSE);
458 }
459
460 if (mathJax)
461 {
462 auto mathJaxVersion = Config_getEnum(MATHJAX_VERSION);
463 QCString path = Config_getString(MATHJAX_RELPATH);
464 if (path.isEmpty() || path.startsWith("..")) // relative path
465 {
466 path.prepend(relPath);
467 }
468
469 switch (mathJaxVersion)
470 {
471 case MATHJAX_VERSION_t::MathJax_3:
472 {
473 mathJaxJs += // "<script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>\n" // needed for IE11 only, see #10354
474 "<script type=\"text/javascript\">\n"
475 "window.MathJax = {\n"
476 " options: {\n"
477 " ignoreHtmlClass: 'tex2jax_ignore',\n"
478 " processHtmlClass: 'tex2jax_process'\n"
479 " }";
480 const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS);
481 if (!mathJaxExtensions.empty() || !g_latex_macro.isEmpty())
482 {
483 mathJaxJs+= ",\n";
484 if (!mathJaxExtensions.empty())
485 {
486 bool first = true;
487 mathJaxJs+= " loader: {\n"
488 " load: [";
489 for (const auto &s : mathJaxExtensions)
490 {
491 if (!first) mathJaxJs+= ",";
492 mathJaxJs+= "'[tex]/"+QCString(s.c_str())+"'";
493 first = false;
494 }
495 mathJaxJs+= "]\n"
496 " },\n";
497 }
498 mathJaxJs+= " tex: {\n"
499 " macros: {";
500 if (!g_latex_macro.isEmpty())
501 {
502 mathJaxJs += g_latex_macro+" ";
503 }
504 mathJaxJs+="},\n"
505 " packages: ['base','configmacros'";
506 if (!g_latex_macro.isEmpty())
507 {
508 mathJaxJs+= ",'newcommand'";
509 }
510 for (const auto &s : mathJaxExtensions)
511 {
512 mathJaxJs+= ",'"+QCString(s.c_str())+"'";
513 }
514 mathJaxJs += "]\n"
515 " }\n";
516 }
517 else
518 {
519 mathJaxJs += "\n";
520 }
521 mathJaxJs += "};\n";
522 // MATHJAX_CODEFILE
523 if (!g_mathjax_code.isEmpty())
524 {
525 mathJaxJs += g_mathjax_code;
526 mathJaxJs += "\n";
527 }
528 mathJaxJs += "</script>\n";
529 mathJaxJs += "<script type=\"text/javascript\" id=\"MathJax-script\" async=\"async\" src=\"" +
530 path + "es5/tex-" + mathJaxFormat.lower() + ".js\">";
531 mathJaxJs+="</script>\n";
532 }
533 break;
534 case MATHJAX_VERSION_t::MathJax_2:
535 {
536 mathJaxJs = "<script type=\"text/x-mathjax-config\">\n"
537 "MathJax.Hub.Config({\n"
538 " extensions: [\"tex2jax.js\"";
539 const StringVector &mathJaxExtensions = Config_getList(MATHJAX_EXTENSIONS);
540 for (const auto &s : mathJaxExtensions)
541 {
542 mathJaxJs+= ", \""+QCString(s.c_str())+".js\"";
543 }
544 if (mathJaxFormat.isEmpty())
545 {
546 mathJaxFormat = "HTML-CSS";
547 }
548 mathJaxJs += "],\n"
549 " jax: [\"input/TeX\",\"output/"+mathJaxFormat+"\"],\n";
550 if (!g_latex_macro.isEmpty())
551 {
552 mathJaxJs += " TeX: { Macros: {\n";
553 mathJaxJs += g_latex_macro;
554 mathJaxJs += "\n"
555 " } }\n";
556 }
557 mathJaxJs += "});\n";
558 if (!g_mathjax_code.isEmpty())
559 {
560 mathJaxJs += g_mathjax_code;
561 mathJaxJs += "\n";
562 }
563 mathJaxJs += "</script>\n";
564 mathJaxJs += "<script type=\"text/javascript\" async=\"async\" src=\"" + path + "MathJax.js\"></script>\n";
565 }
566 break;
567 }
568 }
569
570 QCString darkModeJs;
571 if (Config_getEnum(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::TOGGLE)
572 {
573 darkModeJs="<script type=\"text/javascript\" src=\"$relpath^darkmode_toggle.js\"></script>\n";
574 }
575
576 if (hasCookie) // extend the $treeview tag to avoid breaking old files used with HTML_HEADER
577 {
578 treeViewCssJs+="<script type=\"text/javascript\" src=\"$relpath^cookie.js\"></script>\n";
579 }
580
581 // first substitute generic keywords
582 QCString result = substituteKeywords(file,str,title,
583 convertToHtml(Config_getString(PROJECT_NAME)),
584 convertToHtml(Config_getString(PROJECT_NUMBER)),
585 convertToHtml(Config_getString(PROJECT_BRIEF)));
586
587 // then do the HTML specific keywords
588 result = substituteKeywords(file,result,
589 {
590 // keyword value getter
591 { "$navpath", [&]() { return navPath; } },
592 { "$stylesheet", [&]() { return cssFile; } },
593 { "$treeview", [&]() { return treeViewCssJs; } },
594 { "$searchbox", [&]() { return searchBox; } },
595 { "$search", [&]() { return searchCssJs; } },
596 { "$mathjax", [&]() { return mathJaxJs; } },
597 { "$darkmode", [&]() { return darkModeJs; } },
598 { "$generatedby", [&]() { return generatedBy; } },
599 { "$extrastylesheet",[&]() { return extraCssText; } },
600 { "$relpath$", [&]() { return relPath; } } //<-- obsolete: for backwards compatibility only
601 });
602
603 result = substitute(result,"$relpath^",relPath); //<-- must be done after the previous substitutions
604
605 // remove conditional blocks
606 result = selectBlocks(result,
607 {
608 // keyword, is enabled
609 { "FULL_SIDEBAR", hasFullSideBar },
610 { "DISABLE_INDEX", disableIndex },
611 { "GENERATE_TREEVIEW", treeView },
612 { "SEARCHENGINE", searchEngine },
613 { "TITLEAREA", titleArea },
614 { "PROJECT_NAME", hasProjectName },
615 { "PROJECT_NUMBER", hasProjectNumber },
616 { "PROJECT_BRIEF", hasProjectBrief },
617 { "PROJECT_LOGO", hasProjectLogo },
618 { "PROJECT_ICON", hasProjectIcon },
619 { "COPY_CLIPBOARD", hasCopyClipboard },
621
622 result = removeEmptyLines(result);
623
624 return result;
625}
626
627//---------------------------------------------------------------------------------------------
628
631
632static void fillColorStyleMap(const QCString &definitions,StringUnorderedMap &map)
633{
634 int p=0,i=0;
635 while ((i=definitions.find('\n',p))!=-1)
636 {
637 QCString line = definitions.mid(p,i-p);
638 if (line.startsWith("--"))
639 {
640 int separator = line.find(':');
641 assert(separator!=-1);
642 std::string key = line.left(separator).str();
643 int semi = line.findRev(';');
644 assert(semi!=-1);
645 std::string value = line.mid(separator+1,semi-separator-1).stripWhiteSpace().str();
646 map.emplace(key,value);
647 //printf("var(%s)=%s\n",qPrint(key),qPrint(value));
648 }
649 p=i+1;
650 }
651}
652
654{
656 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
657 if (colorStyle==HTML_COLORSTYLE_t::LIGHT)
658 {
659 fillColorStyleMap(replaceColorMarkers(mgr.getAsString("lightmode_settings.css")),g_lightMap);
660 }
661 else if (colorStyle==HTML_COLORSTYLE_t::DARK)
662 {
663 fillColorStyleMap(replaceColorMarkers(mgr.getAsString("darkmode_settings.css")),g_darkMap);
664 }
665}
666
668{
669 auto doReplacements = [&input](const StringUnorderedMap &mapping) -> QCString
670 {
671 GrowBuf output;
672 int p=0,i=0;
673 while ((i=input.find("var(",p))!=-1)
674 {
675 output.addStr(input.data()+p,i-p);
676 int j=input.find(")",i+4);
677 assert(j!=-1);
678 auto it = mapping.find(input.mid(i+4,j-i-4).str()); // find variable
679 if (it==mapping.end())
680 { // should be found
681 err("failed to find value variable {}. It is not longer defined in doxygen.css\n",input.mid(i+4,j-i-4));
682 }
683 else
684 {
685 //printf("replace '%s' by '%s'\n",qPrint(input.mid(i+4,j-i-4)),qPrint(it->second));
686 output.addStr(it->second); // add it value
687 }
688 p=j+1;
689 }
690 output.addStr(input.data()+p,input.length()-p);
691 output.addChar(0);
692 return output.get();
693 };
694
695 auto colorStyle = Config_getEnum(HTML_COLORSTYLE);
696 if (colorStyle==HTML_COLORSTYLE_t::LIGHT)
697 {
698 return doReplacements(g_lightMap);
699 }
700 else if (colorStyle==HTML_COLORSTYLE_t::DARK)
701 {
702 return doReplacements(g_darkMap);
703 }
704 else
705 {
706 return input;
707 }
708}
709
710//----------------------------------------------------------------------------------------------
711
712
713//--------------------------------------------------------------------------
714
716{
717 //printf("%p:HtmlCodeGenerator()\n",(void*)this);
718}
719
721 : m_t(t), m_relPath(relPath)
722{
723 //printf("%p:HtmlCodeGenerator()\n",(void*)this);
724}
725
727{
728 m_relPath = path;
729}
730
732{
733 if (!str.isEmpty())
734 {
735 int tabSize = Config_getInt(TAB_SIZE);
736 const char *p=str.data();
737 if (m_hide) // only update column count
738 {
740 }
741 else // actually output content and keep track of m_col
742 {
743 while (*p)
744 {
745 char c=*p++;
746 switch(c)
747 {
748 case '\t': {
749 int spacesToNextTabStop = tabSize - (m_col%tabSize);
750 while (spacesToNextTabStop--)
751 {
752 if (m_col>=m_stripIndentAmount) *m_t << " ";
753 m_col++;
754 }
755 }
756 break;
757 case ' ': if (m_col>=m_stripIndentAmount) *m_t << " ";
758 m_col++;
759 break;
760 case '\n': *m_t << "\n"; m_col=0;
761 break;
762 case '\r': break;
763 case '<': *m_t << "&lt;"; m_col++;
764 break;
765 case '>': *m_t << "&gt;"; m_col++;
766 break;
767 case '&': *m_t << "&amp;"; m_col++;
768 break;
769 case '\'': *m_t << "&#39;"; m_col++; // &apos; is not valid XHTML
770 break;
771 case '"': *m_t << "&quot;"; m_col++;
772 break;
773 case '\\':
774 if (*p=='<')
775 { *m_t << "&lt;"; p++; }
776 else if (*p=='>')
777 { *m_t << "&gt;"; p++; }
778 else if (*p=='(')
779 { *m_t << "\\&zwj;("; m_col++;p++; }
780 else if (*p==')')
781 { *m_t << "\\&zwj;)"; m_col++;p++; }
782 else
783 *m_t << "\\";
784 m_col++;
785 break;
786 default:
787 {
788 uint8_t uc = static_cast<uint8_t>(c);
789 if (uc<32)
790 {
791 *m_t << "&#x24" << hex[uc>>4] << hex[uc&0xF] << ";";
792 m_col++;
793 }
794 else if (uc<0x80) // printable ASCII char
795 {
796 *m_t << c;
797 m_col++;
798 }
799 else // multibyte UTF-8 char
800 {
801 p=writeUTF8Char(*m_t,p-1);
802 m_col++;
803 }
804 }
805 break;
806 }
807 }
808 }
809 }
810}
811
816
818{
820 //*m_t << "[START]";
821}
822
824{
825 //*m_t << "[END]";
826 m_hide = false;
827}
828
830{
831 m_stripIndentAmount = amount;
832}
833
835 const QCString &anchor,int l,bool writeLineAnchor)
836{
837 m_lastLineInfo = LineInfo(ref,filename,anchor,l,writeLineAnchor);
838 if (m_hide) return;
839 const int maxLineNrStr = 10;
840 char lineNumber[maxLineNrStr];
841 char lineAnchor[maxLineNrStr];
842 qsnprintf(lineNumber,maxLineNrStr,"%5d",l);
843 qsnprintf(lineAnchor,maxLineNrStr,"l%05d",l);
844
845 if (!m_lineOpen)
846 {
847 *m_t << "<div class=\"line\">";
849 }
850
851 if (writeLineAnchor) *m_t << "<a id=\"" << lineAnchor << "\" name=\"" << lineAnchor << "\"></a>";
852 *m_t << "<span class=\"lineno\">";
853 if (!filename.isEmpty())
854 {
855 _writeCodeLink("line",ref,filename,anchor,lineNumber,QCString());
856 }
857 else
858 {
859 codify(lineNumber);
860 }
861 *m_t << "</span>";
862 m_col=0;
863}
864
866 const QCString &ref,const QCString &f,
867 const QCString &anchor, const QCString &name,
868 const QCString &tooltip)
869{
870 if (m_hide) return;
871 const char *hl = codeSymbolType2Str(type);
872 QCString hlClass = "code";
873 if (hl)
874 {
875 hlClass+=" hl_";
876 hlClass+=hl;
877 }
878 _writeCodeLink(hlClass,ref,f,anchor,name,tooltip);
879}
880
882 const QCString &ref,const QCString &f,
883 const QCString &anchor, const QCString &name,
884 const QCString &tooltip)
885{
886 m_col+=name.length();
887 if (m_hide) return;
888 if (!ref.isEmpty())
889 {
890 *m_t << "<a class=\"" << className << "Ref\" ";
892 }
893 else
894 {
895 *m_t << "<a class=\"" << className << "\" ";
896 }
897 *m_t << "href=\"";
898 QCString fn = f;
900 *m_t << createHtmlUrl(m_relPath,ref,true,
901 fileName()==fn,fn,anchor);
902 *m_t << "\"";
903 if (!tooltip.isEmpty()) *m_t << " title=\"" << convertToHtml(tooltip) << "\"";
904 *m_t << ">";
905 codify(name);
906 *m_t << "</a>";
907}
908
910 const QCString &decl, const QCString &desc,
911 const SourceLinkInfo &defInfo,
912 const SourceLinkInfo &declInfo)
913{
914 if (m_hide) return;
915 *m_t << "<div class=\"ttc\" id=\"" << id << "\">";
916 *m_t << "<div class=\"ttname\">";
917 if (!docInfo.url.isEmpty())
918 {
919 *m_t << "<a href=\"";
920 QCString fn = docInfo.url;
922 *m_t << createHtmlUrl(m_relPath,docInfo.ref,true,
923 fileName()==fn,fn,docInfo.anchor);
924 *m_t << "\">";
925 }
926 codify(docInfo.name);
927 if (!docInfo.url.isEmpty())
928 {
929 *m_t << "</a>";
930 }
931 *m_t << "</div>";
932
933 if (!decl.isEmpty())
934 {
935 *m_t << "<div class=\"ttdeci\">";
936 codify(decl);
937 *m_t << "</div>";
938 }
939
940 if (!desc.isEmpty())
941 {
942 *m_t << "<div class=\"ttdoc\">";
943 codify(desc);
944 *m_t << "</div>";
945 }
946
947 if (!defInfo.file.isEmpty())
948 {
949 *m_t << "<div class=\"ttdef\"><b>" << theTranslator->trDefinition() << "</b> ";
950 if (!defInfo.url.isEmpty())
951 {
952 *m_t << "<a href=\"";
953 QCString fn = defInfo.url;
955 *m_t << createHtmlUrl(m_relPath,defInfo.ref,true,
956 fileName()==fn,fn,defInfo.anchor);
957 *m_t << "\">";
958 }
959 *m_t << defInfo.file << ":" << defInfo.line;
960 if (!defInfo.url.isEmpty())
961 {
962 *m_t << "</a>";
963 }
964 *m_t << "</div>";
965 }
966 if (!declInfo.file.isEmpty())
967 {
968 *m_t << "<div class=\"ttdecl\"><b>" << theTranslator->trDeclaration() << "</b> ";
969 if (!declInfo.url.isEmpty())
970 {
971 *m_t << "<a href=\"";
972 QCString fn = declInfo.url;
974 *m_t << createHtmlUrl(m_relPath,declInfo.ref,true,
975 fileName()==fn,fn,declInfo.anchor);
976 *m_t << "\">";
977 }
978 *m_t << declInfo.file << ":" << declInfo.line;
979 if (!declInfo.url.isEmpty())
980 {
981 *m_t << "</a>";
982 }
983 *m_t << "</div>";
984 }
985 *m_t << "</div>\n";
986}
987
988
990{
991 m_col=0;
992 if (m_hide) return;
993 if (!m_lineOpen)
994 {
995 *m_t << "<div class=\"line\">";
997 }
998}
999
1001{
1002 if (m_hide) return;
1003 if (m_col == 0)
1004 {
1005 *m_t << " ";
1006 m_col++;
1007 }
1008 if (m_lineOpen)
1009 {
1010 *m_t << "</div>\n";
1011 m_lineOpen = FALSE;
1012 }
1013}
1014
1016{
1017 if (m_hide) return;
1018 *m_t << "<span class=\"" << s << "\">";
1019}
1020
1022{
1023 if (m_hide) return;
1024 *m_t << "</span>";
1025}
1026
1028{
1029 if (m_hide) return;
1030 *m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
1031}
1032
1034{
1035 *m_t << "<div class=\"fragment\">";
1036}
1037
1039{
1040 //endCodeLine checks is there is still an open code line, if so closes it.
1041 endCodeLine();
1042
1043 *m_t << "</div><!-- fragment -->";
1044}
1045
1046void HtmlCodeGenerator::startFold(int lineNr,const QCString &startMarker,const QCString &endMarker)
1047{
1048 if (m_lineOpen) // if we have a hidden comment in a code fold, we need to end the line
1049 {
1050 *m_t << "</div>\n";
1051 }
1052 const int maxLineNrStr = 10;
1053 char lineNumber[maxLineNrStr];
1054 qsnprintf(lineNumber,maxLineNrStr,"%05d",lineNr);
1055 *m_t << "<div class=\"foldopen\" id=\"foldopen" << lineNumber <<
1056 "\" data-start=\"" << startMarker <<
1057 "\" data-end=\"" << endMarker <<
1058 "\">\n";
1059 if (m_lineOpen) // if we have a hidden comment in a code fold, we need to restart the line
1060 {
1061 *m_t << "<div class=\"line\">";
1062 }
1063 m_hide=false;
1064}
1065
1067{
1068 *m_t << "<div class=\"line\">";
1069 bool wasHidden=m_hide;
1070 m_hide = false;
1071 m_lineOpen = true;
1073 m_lastLineInfo.fileName,
1074 m_lastLineInfo.anchor,
1075 m_lastLineInfo.line+1,
1076 m_lastLineInfo.writeAnchor);
1077 m_hide = wasHidden;
1078}
1079
1081{
1082 if (m_lineOpen) // if we have a hidden comment in a code fold, we need to end the line
1083 {
1084 *m_t << "</div>\n";
1085 }
1086 *m_t << "</div>\n";
1087 if (m_lineOpen)
1088 {
1090 }
1091}
1092
1093//--------------------------------------------------------------------------
1094
1096 : OutputGenerator(Config_getString(HTML_OUTPUT))
1097 , m_codeList(std::make_unique<OutputCodeList>())
1098{
1099 //printf("%p:HtmlGenerator()\n",(void*)this);
1101}
1102
1104{
1105 //printf("%p:HtmlGenerator(copy %p)\n",(void*)this,(void*)&og);
1106 m_codeList = std::make_unique<OutputCodeList>(*og.m_codeList);
1108 m_codeGen->setTextStream(&m_t);
1111 m_relPath = og.m_relPath;
1114}
1115
1117{
1118 //printf("%p:HtmlGenerator(copy assign %p)\n",(void*)this,(void*)&og);
1119 if (this!=&og)
1120 {
1121 m_dir = og.m_dir;
1122 m_codeList = std::make_unique<OutputCodeList>(*og.m_codeList);
1124 m_codeGen->setTextStream(&m_t);
1127 m_relPath = og.m_relPath;
1130 }
1131 return *this;
1132}
1133
1135
1140
1142{
1143 QCString dname = Config_getString(HTML_OUTPUT);
1144 Dir d(dname.str());
1145 if (!d.exists() && !d.mkdir(dname.str()))
1146 {
1147 term("Could not create output directory {}\n",dname);
1148 }
1149 //writeLogo(dname);
1150 if (!Config_getString(HTML_HEADER).isEmpty())
1151 {
1152 g_header_file=Config_getString(HTML_HEADER);
1154 //printf("g_header='%s'\n",qPrint(g_header));
1156 checkBlocks(result,Config_getString(HTML_HEADER),htmlMarkerInfo);
1157 }
1158 else
1159 {
1160 g_header_file="header.html";
1163 checkBlocks(result,"<default header.html>",htmlMarkerInfo);
1164 }
1165
1166 if (!Config_getString(HTML_FOOTER).isEmpty())
1167 {
1168 g_footer_file=Config_getString(HTML_FOOTER);
1170 //printf("g_footer='%s'\n",qPrint(g_footer));
1172 checkBlocks(result,Config_getString(HTML_FOOTER),htmlMarkerInfo);
1173 }
1174 else
1175 {
1176 g_footer_file = "footer.html";
1179 checkBlocks(result,"<default footer.html>",htmlMarkerInfo);
1180 }
1181
1182 if (Config_getBool(USE_MATHJAX))
1183 {
1184 if (!Config_getString(MATHJAX_CODEFILE).isEmpty())
1185 {
1186 g_mathjax_code=fileToString(Config_getString(MATHJAX_CODEFILE));
1187 //printf("g_mathjax_code='%s'\n",qPrint(g_mathjax_code));
1188 }
1190 //printf("converted g_latex_macro='%s'\n",qPrint(g_latex_macro));
1191 }
1192 createSubDirs(d);
1193
1195
1197
1198 {
1199 QCString tabsCss;
1200 if (Config_getBool(HTML_DYNAMIC_MENUS))
1201 {
1202 tabsCss = mgr.getAsString("tabs.css");
1203 }
1204 else // stylesheet for the 'old' static tabs
1205 {
1206 tabsCss = mgr.getAsString("fixed_tabs.css");
1207 }
1208
1209 std::ofstream f = Portable::openOutputStream(dname+"/tabs.css");
1210 if (f.is_open())
1211 {
1212 TextStream t(&f);
1213 t << replaceVariables(tabsCss);
1214 }
1215 }
1216
1217
1218 mgr.copyResource("jquery.js",dname);
1219 if (Config_getBool(INTERACTIVE_SVG))
1220 {
1221 mgr.copyResource("svg.min.js",dname);
1222 }
1223
1224 if (!Config_getBool(DISABLE_INDEX) && Config_getBool(HTML_DYNAMIC_MENUS))
1225 {
1226 mgr.copyResource("menu.js",dname);
1227 }
1228
1229 // copy navtree.css
1230 {
1231 std::ofstream f = Portable::openOutputStream(dname+"/navtree.css");
1232 if (f.is_open())
1233 {
1234 TextStream t(&f);
1235 t << getNavTreeCss();
1236 }
1237 }
1238
1239 if (Config_getBool(HTML_COPY_CLIPBOARD))
1240 {
1241 std::ofstream f = Portable::openOutputStream(dname+"/clipboard.js");
1242 if (f.is_open())
1243 {
1244 TextStream t(&f);
1245 t << substitute(mgr.getAsString("clipboard.js"),"$copy_to_clipboard_text",theTranslator->trCopyToClipboard());
1246 }
1247 }
1248
1249 bool hasCookie = Config_getBool(GENERATE_TREEVIEW) || Config_getBool(SEARCHENGINE) || Config_getEnum(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::TOGGLE;
1250 if (hasCookie)
1251 {
1252 mgr.copyResource("cookie.js",dname);
1253 }
1254
1255 if (Config_getBool(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::TOGGLE)
1256 {
1257 std::ofstream f = Portable::openOutputStream(dname+"/darkmode_toggle.js");
1258 if (f.is_open())
1259 {
1260 TextStream t(&f);
1261 t << substitute(replaceColorMarkers(mgr.getAsString("darkmode_toggle.js")),
1262 "$PROJECTID",getProjectId());
1263 }
1264 }
1265
1266 {
1267 std::ofstream f = Portable::openOutputStream(dname+"/dynsections.js");
1268 if (f.is_open())
1269 {
1270 TextStream t(&f);
1271 t << replaceVariables(mgr.getAsString("dynsections.js"));
1272 if (Config_getBool(SOURCE_BROWSER) && Config_getBool(SOURCE_TOOLTIPS))
1273 {
1274 t << replaceVariables(mgr.getAsString("dynsections_tooltips.js"));
1275 }
1276 }
1277 }
1278}
1279
1281{
1282 QCString dname = Config_getString(HTML_OUTPUT);
1283 Dir d(dname.str());
1284 clearSubDirs(d);
1285}
1286
1287/// Additional initialization after indices have been created
1289{
1290 Doxygen::indexList->addStyleSheetFile("tabs.css");
1291 QCString dname=Config_getString(HTML_OUTPUT);
1293 mgr.copyResource("doxygen.svg",dname);
1294 Doxygen::indexList->addImageFile("doxygen.svg");
1295}
1296
1298{
1299 //bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
1300 //writeImgData(dname,serverBasedSearch ? search_server_data : search_client_data);
1302
1303 QCString searchDirName = dname;
1304 std::ofstream f = Portable::openOutputStream(searchDirName+"/search.css");
1305 if (f.is_open())
1306 {
1307 TextStream t(&f);
1308 QCString searchCss;
1309 // the position of the search box depends on a number of settings.
1310 // Insert the right piece of CSS code depending on which options are selected
1311 if (Config_getBool(GENERATE_TREEVIEW) && Config_getBool(FULL_SIDEBAR))
1312 {
1313 searchCss = mgr.getAsString("search_sidebar.css"); // we have a full height side bar
1314 }
1315 else if (Config_getBool(DISABLE_INDEX))
1316 {
1317 if (Config_getBool(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::TOGGLE)
1318 {
1319 searchCss = mgr.getAsString("search_nomenu_toggle.css"); // we have no tabs but do have a darkmode button
1320 }
1321 else
1322 {
1323 searchCss = mgr.getAsString("search_nomenu.css"); // we have no tabs and no darkmode button
1324 }
1325 }
1326 else if (!Config_getBool(HTML_DYNAMIC_MENUS))
1327 {
1328 searchCss = mgr.getAsString("search_fixedtabs.css"); // we have tabs, but they are static
1329 }
1330 else
1331 {
1332 searchCss = mgr.getAsString("search.css"); // default case with a dynamic menu bar
1333 }
1334 // and then add the option independent part of the styling
1335 searchCss += mgr.getAsString("search_common.css");
1336 searchCss = substitute(searchCss,"$doxygenversion",getDoxygenVersion());
1337 t << replaceVariables(searchCss);
1338 Doxygen::indexList->addStyleSheetFile("search/search.css");
1339 }
1340}
1341
1343{
1344 t << "/* The standard CSS for doxygen " << getDoxygenVersion() << "*/\n\n";
1345 switch (Config_getEnum(HTML_COLORSTYLE))
1346 {
1347 case HTML_COLORSTYLE_t::LIGHT:
1348 case HTML_COLORSTYLE_t::DARK:
1349 /* variables will be resolved while writing to the CSS file */
1350 break;
1351 case HTML_COLORSTYLE_t::AUTO_LIGHT:
1352 case HTML_COLORSTYLE_t::TOGGLE:
1353 t << "html {\n";
1354 t << replaceColorMarkers(ResourceMgr::instance().getAsString("lightmode_settings.css"));
1355 t << "}\n\n";
1356 break;
1357 case HTML_COLORSTYLE_t::AUTO_DARK:
1358 t << "html {\n";
1359 t << replaceColorMarkers(ResourceMgr::instance().getAsString("darkmode_settings.css"));
1360 t << "}\n\n";
1361 break;
1362 }
1363 if (Config_getEnum(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::AUTO_LIGHT)
1364 {
1365 t << "@media (prefers-color-scheme: dark) {\n";
1366 t << " html:not(.dark-mode) {\n";
1367 t << " color-scheme: dark;\n\n";
1368 t << replaceColorMarkers(ResourceMgr::instance().getAsString("darkmode_settings.css"));
1369 t << "}}\n";
1370 }
1371 else if (Config_getEnum(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::AUTO_DARK)
1372 {
1373 t << "@media (prefers-color-scheme: light) {\n";
1374 t << " html:not(.light-mode) {\n";
1375 t << " color-scheme: light;\n\n";
1376 t << replaceColorMarkers(ResourceMgr::instance().getAsString("lightmode_settings.css"));
1377 t << "}}\n";
1378 }
1379 else if (Config_getEnum(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::TOGGLE)
1380 {
1381 t << "html.dark-mode {\n";
1382 t << replaceColorMarkers(ResourceMgr::instance().getAsString("darkmode_settings.css"));
1383 t << "}\n\n";
1384 }
1385
1386 QCString cssStr = ResourceMgr::instance().getAsString("doxygen.css");
1387 bool hasFullSidebar = Config_getBool(FULL_SIDEBAR) && Config_getBool(GENERATE_TREEVIEW);
1388 if (hasFullSidebar)
1389 {
1390 cssStr+="\n"
1391 "#titlearea {\n"
1392 " border-bottom: none;\n"
1393 " background-color: var(--nav-background-color);\n"
1394 " border-right: 1px solid var(--nav-border-color);\n"
1395 "}\n";
1396 }
1397 t << replaceVariables(cssStr);
1398
1399 // For Webkit based the scrollbar styling cannot be overruled (bug in chromium?).
1400 // To allow the user to style the scrollbars differently we should only add it in case
1401 // the user did not specify any extra stylesheets.
1402 bool addScrollbarStyling = Config_getList(HTML_EXTRA_STYLESHEET).empty();
1403 if (addScrollbarStyling)
1404 {
1405 t << replaceVariables(ResourceMgr::instance().getAsString("scrollbar.css"));
1406 }
1407
1408}
1409
1415
1417{
1418 t << "<!-- HTML header for doxygen " << getDoxygenVersion() << "-->\n";
1419 t << ResourceMgr::instance().getAsString("header.html");
1420}
1421
1423{
1424 t << "<!-- HTML footer for doxygen " << getDoxygenVersion() << "-->\n";
1425 t << ResourceMgr::instance().getAsString("footer.html");
1426}
1427
1428static std::mutex g_indexLock;
1429
1431 const QCString &title,int /*id*/, int /*hierarchyLevel*/)
1432{
1433 //printf("HtmlGenerator::startFile(%s)\n",qPrint(name));
1435 QCString fileName = name;
1437 m_lastTitle=title;
1438
1440 m_codeGen->setFileName(fileName);
1441 m_codeGen->setRelativePath(m_relPath);
1442 {
1443 std::lock_guard<std::mutex> lock(g_indexLock);
1444 Doxygen::indexList->addIndexFile(fileName);
1445 }
1446
1449
1450 m_t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen "
1451 << getDoxygenVersion() << " -->\n";
1452 bool searchEngine = Config_getBool(SEARCHENGINE);
1453 if (searchEngine /*&& !generateTreeView*/)
1454 {
1455 m_t << "<script type=\"text/javascript\">\n";
1456 m_t << "var searchBox = new SearchBox(\"searchBox\", \""
1457 << m_relPath<< "search/\",'" << Doxygen::htmlFileExtension << "');\n";
1458 m_t << "</script>\n";
1459 }
1460 if (Config_getBool(HTML_CODE_FOLDING))
1461 {
1462 m_t << "<script type=\"text/javascript\">\n";
1463 m_t << "$(function() { codefold.init(); });\n";
1464 m_t << "</script>\n";
1465 }
1467}
1468
1470{
1471 bool searchEngine = Config_getBool(SEARCHENGINE);
1472 bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
1473 if (searchEngine && !serverBasedSearch)
1474 {
1475 t << "<!-- window showing the filter options -->\n";
1476 t << "<div id=\"MSearchSelectWindow\"\n";
1477 t << " onmouseover=\"return searchBox.OnSearchSelectShow()\"\n";
1478 t << " onmouseout=\"return searchBox.OnSearchSelectHide()\"\n";
1479 t << " onkeydown=\"return searchBox.OnSearchSelectKey(event)\">\n";
1480 t << "</div>\n";
1481 t << "\n";
1482 t << "<!-- iframe showing the search results (closed by default) -->\n";
1483 t << "<div id=\"MSearchResultsWindow\">\n";
1484 t << "<div id=\"MSearchResults\">\n";
1485 t << "<div class=\"SRPage\">\n";
1486 t << "<div id=\"SRIndex\">\n";
1487 t << "<div id=\"SRResults\"></div>\n"; // here the results will be inserted
1488 t << "<div class=\"SRStatus\" id=\"Loading\">" << theTranslator->trLoading() << "</div>\n";
1489 t << "<div class=\"SRStatus\" id=\"Searching\">" << theTranslator->trSearching() << "</div>\n";
1490 t << "<div class=\"SRStatus\" id=\"NoMatches\">" << theTranslator->trNoMatches() << "</div>\n";
1491 t << "</div>\n"; // SRIndex
1492 t << "</div>\n"; // SRPage
1493 t << "</div>\n"; // MSearchResults
1494 t << "</div>\n"; // MSearchResultsWindow
1495 t << "\n";
1496 }
1497}
1498
1503
1504
1506{
1507 QCString result;
1508 switch (Config_getEnum(TIMESTAMP))
1509 {
1510 case TIMESTAMP_t::YES:
1511 case TIMESTAMP_t::DATETIME:
1512 result += theTranslator->trGeneratedAt(
1514 Config_getString(PROJECT_NAME)
1515 );
1516 break;
1517 case TIMESTAMP_t::DATE:
1518 result += theTranslator->trGeneratedAt(
1520 Config_getString(PROJECT_NAME)
1521 );
1522 break;
1523 case TIMESTAMP_t::NO:
1524 result += theTranslator->trGeneratedBy();
1525 break;
1526 }
1527 result += "&#160;\n<a href=\"https://www.doxygen.org/index.html\">\n"
1528 "<img class=\"footer\" src=\"";
1529 result += path;
1530 result += "doxygen.svg\" width=\"104\" height=\"31\" alt=\"doxygen\"/></a> ";
1531 result += getDoxygenVersion();
1532 result += " ";
1533 return result;
1534}
1535
1540
1542 const QCString &relPath,const QCString &navPath)
1543{
1544 t << substituteHtmlKeywords(g_footer_file,g_footer,convertToHtml(lastTitle),relPath,navPath);
1545}
1546
1548{
1550}
1551
1553{
1554 endPlainFile();
1555}
1556
1558{
1559 m_t << "<h3 class=\"version\">";
1560}
1561
1563{
1564 m_t << "</h3>";
1565}
1566
1568{
1569 //printf("writeStyleInfo(%d)\n",part);
1570 if (part==0)
1571 {
1572 if (Config_getString(HTML_STYLESHEET).isEmpty()) // write default style sheet
1573 {
1574 //printf("write doxygen.css\n");
1575 startPlainFile("doxygen.css");
1577 endPlainFile();
1578 Doxygen::indexList->addStyleSheetFile("doxygen.css");
1579 }
1580 else // write user defined style sheet
1581 {
1582 QCString cssName=Config_getString(HTML_STYLESHEET);
1583 if (!cssName.startsWith("http:") && !cssName.startsWith("https:"))
1584 {
1585 FileInfo cssfi(cssName.str());
1586 if (!cssfi.exists() || !cssfi.isFile() || !cssfi.isReadable())
1587 {
1588 err("style sheet {} does not exist or is not readable!\n", Config_getString(HTML_STYLESHEET));
1589 }
1590 else
1591 {
1592 // convert style sheet to string
1593 QCString fileStr = fileToString(cssName);
1594 // write the string into the output dir
1595 startPlainFile(cssfi.fileName().c_str());
1596 m_t << fileStr;
1597 endPlainFile();
1598 }
1599 Doxygen::indexList->addStyleSheetFile(cssfi.fileName().c_str());
1600 }
1601 }
1602 const StringVector &extraCssFiles = Config_getList(HTML_EXTRA_STYLESHEET);
1603 for (const auto &fileName : extraCssFiles)
1604 {
1605 if (!fileName.empty())
1606 {
1607 FileInfo fi(fileName);
1608 if (fi.exists())
1609 {
1610 Doxygen::indexList->addStyleSheetFile(fi.fileName().c_str());
1611 }
1612 }
1613 }
1614
1615 Doxygen::indexList->addStyleSheetFile("jquery.js");
1616 Doxygen::indexList->addStyleSheetFile("navtree.css");
1617
1618 Doxygen::indexList->addStyleSheetFile("dynsections.js");
1619
1620 if (Config_getEnum(HTML_COLORSTYLE)==HTML_COLORSTYLE_t::TOGGLE)
1621 {
1622 Doxygen::indexList->addStyleSheetFile("darkmode_toggle.js");
1623 }
1624
1625 if (Config_getBool(INTERACTIVE_SVG))
1626 {
1627 Doxygen::indexList->addStyleSheetFile("svg.min.js");
1628 }
1629
1630 if (!Config_getBool(DISABLE_INDEX) && Config_getBool(HTML_DYNAMIC_MENUS))
1631 {
1632 Doxygen::indexList->addStyleSheetFile("menu.js");
1633 Doxygen::indexList->addStyleSheetFile("menudata.js");
1634 }
1635 }
1636}
1637
1639 const QCString &anchor, const QCString &,
1640 const QCString &)
1641{
1642 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
1643}
1644
1646{
1647}
1648
1650{
1651}
1652
1654{
1655 if (!classDef.isEmpty())
1656 m_t << "\n<p class=\"" << classDef << "\">";
1657 else
1658 m_t << "\n<p>";
1659}
1660
1662{
1663 m_t << "</p>\n";
1664}
1665
1667{
1668 m_t << text;
1669}
1670
1672{
1673 m_t << "<li>";
1674}
1675
1677{
1678 m_t << "</li>\n";
1679}
1680
1682{
1683 //printf("HtmlGenerator::startIndexItem(%s,%s)\n",ref,f);
1684 if (!ref.isEmpty() || !f.isEmpty())
1685 {
1686 if (!ref.isEmpty())
1687 {
1688 m_t << "<a class=\"elRef\" ";
1690 }
1691 else
1692 {
1693 m_t << "<a class=\"el\" ";
1694 }
1695 m_t << "href=\"";
1696 m_t << externalRef(m_relPath,ref,TRUE);
1697 if (!f.isEmpty())
1698 {
1699 QCString fn=f;
1701 m_t << fn;
1702 }
1703 m_t << "\">";
1704 }
1705 else
1706 {
1707 m_t << "<b>";
1708 }
1709}
1710
1712{
1713 //printf("HtmlGenerator::endIndexItem(%s,%s,%s)\n",ref,f,name);
1714 if (!ref.isEmpty() || !f.isEmpty())
1715 {
1716 m_t << "</a>";
1717 }
1718 else
1719 {
1720 m_t << "</b>";
1721 }
1722}
1723
1725 const QCString &path,const QCString &name)
1726{
1727 m_t << "<li>";
1728 if (!path.isEmpty()) docify(path);
1729 QCString fn = f;
1731 m_t << "<a class=\"el\" href=\"" << fn << "\">";
1732 docify(name);
1733 m_t << "</a> ";
1734}
1735
1737 const QCString &anchor, const QCString &name)
1738{
1739 if (!ref.isEmpty())
1740 {
1741 m_t << "<a class=\"elRef\" ";
1743 }
1744 else
1745 {
1746 m_t << "<a class=\"el\" ";
1747 }
1748 m_t << "href=\"";
1749 QCString fn = f;
1751 m_t << createHtmlUrl(m_relPath,ref,true,
1752 fileName() == Config_getString(HTML_OUTPUT)+"/"+fn,
1753 fn,
1754 anchor);
1755 m_t << "\">";
1756 docify(name);
1757 m_t << "</a>";
1758}
1759
1761{
1762 m_t << "<a href=\"";
1763 QCString fn = f;
1765 m_t << createHtmlUrl(m_relPath,"",true,
1766 fileName() == Config_getString(HTML_OUTPUT)+"/"+fn,
1767 fn,
1768 anchor);
1769 m_t << "\">";
1770}
1771
1773{
1774 m_t << "</a>";
1775}
1776
1777void HtmlGenerator::startGroupHeader(const QCString &id,int extraIndentLevel)
1778{
1779 if (extraIndentLevel==2)
1780 {
1781 m_t << "<h4";
1782 }
1783 else if (extraIndentLevel==1)
1784 {
1785 m_t << "<h3";
1786 }
1787 else // extraIndentLevel==0
1788 {
1789 m_t << "<h2";
1790 }
1791 if (!id.isEmpty())
1792 {
1793 m_t <<" id=\"header-"+convertToId(id)+"\"";
1794 }
1795 m_t << " class=\"groupheader\">";
1796}
1797
1798void HtmlGenerator::endGroupHeader(int extraIndentLevel)
1799{
1800 if (extraIndentLevel==2)
1801 {
1802 m_t << "</h4>\n";
1803 }
1804 else if (extraIndentLevel==1)
1805 {
1806 m_t << "</h3>\n";
1807 }
1808 else
1809 {
1810 m_t << "</h2>\n";
1811 }
1812}
1813
1815{
1816 switch(type.level())
1817 {
1818 case SectionType::Page: m_t << "\n\n<h1 class=\"doxsection\">"; break;
1819 case SectionType::Section: m_t << "\n\n<h2 class=\"doxsection\">"; break;
1820 case SectionType::Subsection: m_t << "\n\n<h3 class=\"doxsection\">"; break;
1821 case SectionType::Subsubsection: m_t << "\n\n<h4 class=\"doxsection\">"; break;
1822 case SectionType::Paragraph: m_t << "\n\n<h5 class=\"doxsection\">"; break;
1823 case SectionType::Subparagraph: m_t << "\n\n<h6 class=\"doxsection\">"; break;
1824 case SectionType::Subsubparagraph: m_t << "\n\n<h6 class=\"doxsection\">"; break;
1825 default: ASSERT(0); break;
1826 }
1827 m_t << "<a id=\"" << lab << "\" name=\"" << lab << "\"></a>";
1828}
1829
1831{
1832 switch(type.level())
1833 {
1834 case SectionType::Page: m_t << "</h1>"; break;
1835 case SectionType::Section: m_t << "</h2>"; break;
1836 case SectionType::Subsection: m_t << "</h3>"; break;
1837 case SectionType::Subsubsection: m_t << "</h4>"; break;
1838 case SectionType::Paragraph: m_t << "</h5>"; break;
1839 case SectionType::Subparagraph: m_t << "</h6>"; break;
1840 case SectionType::Subsubparagraph: m_t << "</h6>"; break;
1841 default: ASSERT(0); break;
1842 }
1843}
1844
1846{
1847 docify_(str,FALSE);
1848}
1849
1850void HtmlGenerator::docify_(const QCString &str,bool inHtmlComment)
1851{
1852 if (!str.isEmpty())
1853 {
1854 const char *p=str.data();
1855 while (*p)
1856 {
1857 char c=*p++;
1858 switch(c)
1859 {
1860 case '<': m_t << "&lt;"; break;
1861 case '>': m_t << "&gt;"; break;
1862 case '&': m_t << "&amp;"; break;
1863 case '"': m_t << "&quot;"; break;
1864 case '-': if (inHtmlComment) m_t << "&#45;"; else m_t << "-"; break;
1865 case '\\':
1866 if (*p=='<')
1867 { m_t << "&lt;"; p++; }
1868 else if (*p=='>')
1869 { m_t << "&gt;"; p++; }
1870 else if (*p=='(')
1871 { m_t << "\\&zwj;("; p++; }
1872 else if (*p==')')
1873 { m_t << "\\&zwj;)"; p++; }
1874 else
1875 m_t << "\\";
1876 break;
1877 default: m_t << c;
1878 }
1879 }
1880 }
1881}
1882
1884{
1885 char cs[2];
1886 cs[0]=c;
1887 cs[1]=0;
1888 docify(cs);
1889}
1890
1891//--- helper function for dynamic sections -------------------------
1892
1894 const QCString &relPath,int sectionCount)
1895{
1896 //t << "<!-- startSectionHeader -->";
1897 bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS);
1898 if (dynamicSections)
1899 {
1900 t << "<div id=\"dynsection-" << sectionCount << "\" "
1901 "onclick=\"return dynsection.toggleVisibility(this)\" "
1902 "class=\"dynheader closed\" "
1903 "style=\"cursor:pointer;\">"
1904 "<span class=\"dynarrow\"><span class=\"arrowhead closed\"></span></span>";
1905 }
1906 else
1907 {
1908 t << "<div class=\"dynheader\">\n";
1909 }
1910}
1911
1913{
1914 //t << "<!-- endSectionHeader -->";
1915 t << "</div>\n";
1916}
1917
1918static void startSectionSummary(TextStream &t,int sectionCount)
1919{
1920 //t << "<!-- startSectionSummary -->";
1921 bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS);
1922 if (dynamicSections)
1923 {
1924 t << "<div id=\"dynsection-" << sectionCount << "-summary\" "
1925 "class=\"dynsummary\" "
1926 "style=\"display:block;\">\n";
1927 }
1928}
1929
1931{
1932 //t << "<!-- endSectionSummary -->";
1933 bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS);
1934 if (dynamicSections)
1935 {
1936 t << "</div>\n";
1937 }
1938}
1939
1940static void startSectionContent(TextStream &t,int sectionCount)
1941{
1942 //t << "<!-- startSectionContent -->";
1943 bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS);
1944 if (dynamicSections)
1945 {
1946 t << "<div id=\"dynsection-" << sectionCount << "-content\" "
1947 "class=\"dyncontent\" "
1948 "style=\"display:none;\">\n";
1949 }
1950 else
1951 {
1952 t << "<div class=\"dyncontent\">\n";
1953 }
1954}
1955
1957{
1958 //t << "<!-- endSectionContent -->";
1959 t << "</div>\n";
1960}
1961
1962//----------------------------
1963
1968
1970 const QCString &fileName,const QCString &name)
1971{
1976 TextStream tt;
1978 if (!tt.empty())
1979 {
1980 m_t << " <div class=\"center\">\n";
1981 m_t << " <img src=\"";
1982 m_t << m_relPath << fileName << ".png\" usemap=\"#" << convertToId(name);
1983 m_t << "_map\" alt=\"\"/>\n";
1984 m_t << " <map id=\"" << convertToId(name);
1985 m_t << "_map\" name=\"" << convertToId(name);
1986 m_t << "_map\">\n";
1987 m_t << tt.str();
1988 m_t << " </map>\n";
1989 m_t << "</div>";
1990 }
1991 else
1992 {
1993 m_t << " <div class=\"center\">\n";
1994 m_t << " <img src=\"";
1995 m_t << m_relPath << fileName << ".png\" alt=\"\"/>\n";
1996 m_t << " </div>";
1997 }
2000}
2001
2002
2004{
2005 DBG_HTML(m_t << "<!-- startMemberList -->\n")
2006}
2007
2009{
2010 DBG_HTML(m_t << "<!-- endMemberList -->\n")
2011}
2012
2013// anonymous type:
2014// 0 = single column right aligned
2015// 1 = double column left aligned
2016// 2 = single column left aligned
2018{
2019 DBG_HTML(m_t << "<!-- startMemberItem() -->\n")
2020 if (m_emptySection)
2021 {
2022 m_t << "<table class=\"memberdecls\">\n";
2024 }
2025 m_t << "<tr class=\"memitem:" << convertToId(anchor);
2026 if (!inheritId.isEmpty())
2027 {
2028 m_t << " inherit " << inheritId;
2029 }
2030 m_t << "\"";
2031 if (!anchor.isEmpty())
2032 {
2033 m_t << " id=\"r_" << convertToId(anchor) << "\"";
2034 }
2035 m_t << ">";
2037}
2038
2040{
2042 {
2043 insertMemberAlign(false);
2044 }
2045 m_t << "</td></tr>\n";
2046}
2047
2051
2053{
2054 m_t << "</td></tr>\n";
2055 m_t << "<tr class=\"memitem:" << convertToId(anchor);
2056 if (!inheritId.isEmpty())
2057 {
2058 m_t << " inherit " << inheritId;
2059 }
2060 m_t << " template\"><td class=\"memItemLeft\" align=\"right\" valign=\"top\">";
2061}
2062
2064{
2065 m_t << "<div class=\"compoundTemplParams\">";
2066}
2067
2069{
2070 m_t << "</div>";
2071}
2072
2074{
2075 DBG_HTML(m_t << "<!-- insertMemberAlign -->\n")
2076 m_t << "&#160;</td><td class=\"memItemRight\" valign=\"bottom\">";
2077}
2078
2080{
2081 if (!initTag) m_t << "&#160;</td>";
2082 switch (type)
2083 {
2084 case MemberItemType::Normal: m_t << "<td class=\"memItemLeft\" align=\"right\" valign=\"top\">"; break;
2085 case MemberItemType::AnonymousStart: m_t << "<td class=\"memItemLeft anon\">"; break;
2086 case MemberItemType::AnonymousEnd: m_t << "<td class=\"memItemLeft anonEnd\" valign=\"top\">"; break;
2087 case MemberItemType::Templated: m_t << "<td class=\"memTemplParams\" colspan=\"2\">"; break;
2088 }
2089}
2090
2091void HtmlGenerator::startMemberDescription(const QCString &anchor,const QCString &inheritId, bool typ)
2092{
2093 DBG_HTML(m_t << "<!-- startMemberDescription -->\n")
2094 if (m_emptySection)
2095 {
2096 m_t << "<table class=\"memberdecls\">\n";
2098 }
2099 m_t << "<tr class=\"memdesc:" << anchor;
2100 if (!inheritId.isEmpty())
2101 {
2102 m_t << " inherit " << inheritId;
2103 }
2104 m_t << "\">";
2105 m_t << "<td class=\"mdescLeft\">&#160;</td>";
2106 if (typ) m_t << "<td class=\"mdescLeft\">&#160;</td>";
2107 m_t << "<td class=\"mdescRight\">";
2108}
2109
2111{
2112 DBG_HTML(m_t << "<!-- endMemberDescription -->\n")
2113 m_t << "<br /></td></tr>\n";
2114}
2115
2117{
2118 DBG_HTML(m_t << "<!-- startMemberSections -->\n")
2119 m_emptySection=TRUE; // we postpone writing <table> until we actually
2120 // write a row to prevent empty tables, which
2121 // are not valid XHTML!
2122}
2123
2125{
2126 DBG_HTML(m_t << "<!-- endMemberSections -->\n")
2127 if (!m_emptySection)
2128 {
2129 m_t << "</table>\n";
2130 }
2131}
2132
2133void HtmlGenerator::startMemberHeader(const QCString &anchor, int typ)
2134{
2135 DBG_HTML(m_t << "<!-- startMemberHeader -->\n")
2136 if (!m_emptySection)
2137 {
2138 m_t << "</table>";
2140 }
2141 if (m_emptySection)
2142 {
2143 m_t << "<table class=\"memberdecls\">\n";
2145 }
2146 m_t << "<tr class=\"heading\"><td colspan=\"" << typ << "\"><h2";
2147 if (!anchor.isEmpty())
2148 {
2149 m_t << " id=\"header-" << anchor << "\"";
2150 }
2151 m_t << " class=\"groupheader\">";
2152 if (!anchor.isEmpty())
2153 {
2154 m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>\n";
2155 }
2156}
2157
2159{
2160 DBG_HTML(m_t << "<!-- endMemberHeader -->\n")
2161 m_t << "</h2></td></tr>\n";
2162}
2163
2165{
2166 DBG_HTML(m_t << "<!-- startMemberSubtitle -->\n")
2167 m_t << "<tr><td class=\"ititle\" colspan=\"2\">";
2168}
2169
2171{
2172 DBG_HTML(m_t << "<!-- endMemberSubtitle -->\n")
2173 m_t << "</td></tr>\n";
2174}
2175
2177{
2178 m_t << "<table>\n";
2179}
2180
2182{
2183 m_t << "</table>\n";
2184}
2185
2187{
2188 //m_t << " <tr><td class=\"indexkey\">";
2189}
2190
2192{
2193 //m_t << "</td>";
2194}
2195
2197{
2198 //m_t << "<td class=\"indexvalue\">";
2199}
2200
2202{
2203 //m_t << "</td></tr>\n";
2204}
2205
2207{
2208 DBG_HTML(m_t << "<!-- startMemberDocList -->\n";)
2209}
2210
2212{
2213 DBG_HTML(m_t << "<!-- endMemberDocList -->\n";)
2214}
2215
2216void HtmlGenerator::startMemberDoc( const QCString &/* clName */, const QCString &/* memName */,
2217 const QCString &anchor, const QCString &title,
2218 int memCount, int memTotal, bool /* showInline */)
2219{
2220 DBG_HTML(m_t << "<!-- startMemberDoc -->\n";)
2221 m_t << "\n<h2 class=\"memtitle\">"
2222 << "<span class=\"permalink\"><a href=\"#" << anchor << "\">&#9670;&#160;</a></span>";
2223 docify(title);
2224 if (memTotal>1)
2225 {
2226 m_t << " <span class=\"overload\">[" << memCount << "/" << memTotal <<"]</span>";
2227 }
2228 m_t << "</h2>\n";
2229 m_t << "\n<div class=\"memitem\">\n";
2230 m_t << "<div class=\"memproto\">\n";
2231}
2232
2234{
2235 DBG_HTML(m_t << "<!-- startMemberDocPrefixItem -->\n";)
2236 m_t << "<div class=\"memtemplate\">\n";
2237}
2238
2240{
2241 DBG_HTML(m_t << "<!-- endMemberDocPrefixItem -->\n";)
2242 m_t << "</div>\n";
2243}
2244
2246{
2247 DBG_HTML(m_t << "<!-- startMemberDocName -->\n";)
2248
2249 m_t << " <table class=\"memname\">\n";
2250
2251 m_t << " <tr>\n";
2252 m_t << " <td class=\"memname\">";
2253}
2254
2256{
2257 DBG_HTML(m_t << "<!-- endMemberDocName -->\n";)
2258 m_t << "</td>\n";
2259}
2260
2262{
2263 DBG_HTML(m_t << "<!-- startParameterList -->\n";)
2264 m_t << " <td>";
2265 if (openBracket) m_t << "(";
2266 m_t << "</td>\n";
2267}
2268
2270{
2271 if (first)
2272 {
2273 DBG_HTML(m_t << "<!-- startFirstParameterType -->\n";)
2274 m_t << " <td class=\"paramtype\">";
2275 }
2276 else
2277 {
2278 DBG_HTML(m_t << "<!-- startParameterType -->\n";)
2279 m_t << " <tr>\n";
2280 m_t << " <td class=\"paramkey\">" << key << "</td>\n";
2281 m_t << " <td></td>\n";
2282 m_t << " <td class=\"paramtype\">";
2283 }
2284}
2285
2287{
2288 DBG_HTML(m_t << "<!-- endParameterType -->\n";)
2289 m_t << "</td>";
2290}
2291
2292void HtmlGenerator::startParameterName(bool /*oneArgOnly*/)
2293{
2294 DBG_HTML(m_t << "<!-- startParameterName -->\n";)
2295 m_t << " <td class=\"paramname\"><span class=\"paramname\"><em>";
2296}
2297
2299{
2300 DBG_HTML(m_t << "<!-- endParameterName -->\n";)
2301 m_t << "</em></span>";
2302}
2303
2305{
2306 DBG_HTML(m_t << "<!-- startParameterExtra -->\n";)
2307}
2308
2309void HtmlGenerator::endParameterExtra(bool last,bool emptyList, bool closeBracket)
2310{
2311 DBG_HTML(m_t << "<!-- endParameterExtra -->\n";)
2312 if (last)
2313 {
2314 if (emptyList)
2315 {
2316 if (closeBracket) m_t << "</td><td>)";
2317 m_t << "</td>\n";
2318 m_t << " <td>";
2319 }
2320 else
2321 {
2322 m_t << "&#160;";
2323 if (closeBracket) m_t << ")";
2324 }
2325 }
2326 else
2327 {
2328 m_t << "</td>\n";
2329 m_t << " </tr>\n";
2330 }
2331}
2332
2334{
2335 m_t << "<span class=\"paramdefsep\">";
2336 docify(s);
2337 m_t << "</span><span class=\"paramdefval\">";
2338}
2339
2341{
2342 m_t << "</span>";
2343}
2344
2346{
2347 DBG_HTML(m_t << "<!-- endParameterList -->\n";)
2348 m_t << "</td>\n";
2349 m_t << " </tr>\n";
2350}
2351
2352void HtmlGenerator::exceptionEntry(const QCString &prefix,bool closeBracket)
2353{
2354 DBG_HTML(m_t << "<!-- exceptionEntry -->\n";)
2355 if (!closeBracket)
2356 {
2357 m_t << "</td>\n";
2358 m_t << " </tr>\n";
2359 m_t << " <tr>\n";
2360 m_t << " <td align=\"right\">";
2361 }
2362 // colspan 2 so it gets both parameter type and parameter name columns
2363 if (!prefix.isEmpty())
2364 m_t << prefix << "</td><td>(</td><td colspan=\"2\">";
2365 else if (closeBracket)
2366 m_t << "&#160;)</td><td></td><td></td><td>";
2367 else
2368 m_t << "</td><td></td><td colspan=\"2\">";
2369}
2370
2372{
2373 DBG_HTML(m_t << "<!-- endMemberDoc -->\n";)
2374 if (!hasArgs)
2375 {
2376 m_t << " </tr>\n";
2377 }
2378 m_t << " </table>\n";
2379 // m_t << "</div>\n";
2380}
2381
2386
2388{
2389 bool generateLegend = Config_getBool(GENERATE_LEGEND);
2390 bool umlLook = Config_getBool(UML_LOOK);
2395
2397 if (generateLegend && !umlLook)
2398 {
2399 QCString url = m_relPath+"graph_legend"+Doxygen::htmlFileExtension;
2400 m_t << "<center><span class=\"legend\">[";
2401 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2402 m_t << "<a ";
2403 if (generateTreeView) m_t << "target=\"top\" ";
2404 m_t << "href=\"";
2405 if (!url.isEmpty()) m_t << url;
2406 m_t << "\">";
2407 m_t << theTranslator->trLegend();
2408 m_t << "</a>";
2409 m_t << "]</span></center>";
2410 }
2411
2414}
2415
2420
2433
2438
2451
2456
2469
2474
2487
2492
2494{
2495 m_t << "<tr id=\"" << id << "\" class=\"groupHeader\"><td colspan=\"2\"><div class=\"groupHeader\">";
2496}
2497
2499{
2500 m_t << "</div></td></tr>\n";
2501}
2502
2504{
2505 m_t << "<tr><td colspan=\"2\"><div class=\"groupText\">";
2506}
2507
2509{
2510 m_t << "</div></td></tr>\n";
2511}
2512
2516
2518{
2519}
2520
2522{
2523 DBG_HTML(m_t << "<!-- startIndent -->\n";)
2524
2525 m_t << "<div class=\"memdoc\">\n";
2526}
2527
2529{
2530 DBG_HTML(m_t << "<!-- endIndent -->\n";)
2531 m_t << "\n</div>\n" << "</div>\n";
2532}
2533
2535{
2536}
2537
2539{
2540 for (int i=0; i<n; i++)
2541 {
2542 m_t << "&#160;";
2543 }
2544}
2545
2546void HtmlGenerator::startDescTable(const QCString &title,const bool hasInits)
2547{
2548 m_t << "<table class=\"fieldtable\">\n"
2549 << "<tr><th colspan=\"" << (hasInits?3:2) << "\">" << title << "</th></tr>";
2550}
2552{
2553 m_t << "</table>\n";
2554}
2555
2557{
2558 m_t << "<tr>";
2559}
2560
2562{
2563 m_t << "</tr>\n";
2564}
2565
2567{
2568 m_t << "<td class=\"fieldname\">";
2569}
2570
2572{
2573 m_t << "&#160;</td>";
2574}
2575
2577{
2578 m_t << "<td class=\"fieldinit\">";
2579}
2580
2582{
2583 m_t << "&#160;</td>";
2584}
2585
2587{
2588 m_t << "<td class=\"fielddoc\">";
2589}
2590
2592{
2593 m_t << "</td>";
2594}
2595
2597{
2598 m_t << "<dl class=\"section examples\"><dt>";
2599 docify(theTranslator->trExamples());
2600 m_t << "</dt>";
2601}
2602
2604{
2605 m_t << "</dl>\n";
2606}
2607
2608void HtmlGenerator::writeDoc(const IDocNodeAST *ast,const Definition *ctx,const MemberDef *,int id)
2609{
2610 const DocNodeAST *astImpl = dynamic_cast<const DocNodeAST*>(ast);
2611 if (astImpl)
2612 {
2613 m_codeList->setId(id);
2614 HtmlDocVisitor visitor(m_t,*m_codeList,ctx,fileName());
2615 std::visit(visitor,astImpl->root);
2616 }
2617}
2618
2619//---------------- helpers for index generation -----------------------------
2620
2621static void startQuickIndexList(TextStream &t,bool topLevel=TRUE)
2622{
2623 if (!Config_getBool(DISABLE_INDEX))
2624 {
2625 if (topLevel)
2626 {
2627 t << " <div id=\"navrow1\" class=\"tabs\">\n";
2628 }
2629 else
2630 {
2631 t << " <div id=\"navrow2\" class=\"tabs2\">\n";
2632 }
2633 t << " <ul class=\"tablist\">\n";
2634 }
2635 else
2636 {
2637 t << "<ul>";
2638 }
2639}
2640
2642{
2643 if (!Config_getBool(DISABLE_INDEX))
2644 {
2645 t << " </ul>\n";
2646 t << " </div>\n";
2647 }
2648 else
2649 {
2650 t << "</ul>\n";
2651 }
2652}
2653
2655 bool hl,bool /*compact*/,
2656 const QCString &relPath)
2657{
2658 t << " <li";
2659 if (hl)
2660 {
2661 t << " class=\"current\"";
2662 }
2663 t << ">";
2664 if (!l.isEmpty()) t << "<a href=\"" << correctURL(l,relPath) << "\">";
2665 t << "<span>";
2666}
2667
2668static void endQuickIndexItem(TextStream &t,const QCString &l)
2669{
2670 t << "</span>";
2671 if (!l.isEmpty()) t << "</a>";
2672 t << "</li>\n";
2673}
2674
2676{
2677 const auto &index = Index::instance();
2678 bool showNamespaces = Config_getBool(SHOW_NAMESPACES);
2679 bool showFiles = Config_getBool(SHOW_FILES);
2680 switch (kind)
2681 {
2682 case LayoutNavEntry::MainPage: return TRUE;
2683 case LayoutNavEntry::User: return TRUE;
2684 case LayoutNavEntry::UserGroup: return TRUE;
2685 case LayoutNavEntry::Pages: return index.numIndexedPages()>0;
2686 case LayoutNavEntry::Topics: return index.numDocumentedGroups()>0;
2687 case LayoutNavEntry::Modules: return index.numDocumentedModules()>0;
2688 case LayoutNavEntry::ModuleList: return index.numDocumentedModules()>0;
2689 case LayoutNavEntry::ModuleMembers: return index.numDocumentedModuleMembers(ModuleMemberHighlight::All)>0;
2690 case LayoutNavEntry::Namespaces: return showNamespaces && index.numDocumentedNamespaces()>0;
2691 case LayoutNavEntry::NamespaceList: return showNamespaces && index.numDocumentedNamespaces()>0;
2692 case LayoutNavEntry::NamespaceMembers: return showNamespaces && index.numDocumentedNamespaceMembers(NamespaceMemberHighlight::All)>0;
2693 case LayoutNavEntry::Concepts: return index.numDocumentedConcepts()>0;
2694 case LayoutNavEntry::Classes: return index.numAnnotatedClasses()>0;
2695 case LayoutNavEntry::ClassList: return index.numAnnotatedClasses()>0;
2696 case LayoutNavEntry::ClassIndex: return index.numAnnotatedClasses()>0;
2697 case LayoutNavEntry::ClassHierarchy: return index.numHierarchyClasses()>0;
2698 case LayoutNavEntry::ClassMembers: return index.numDocumentedClassMembers(ClassMemberHighlight::All)>0;
2699 case LayoutNavEntry::Files: return showFiles && index.numDocumentedFiles()>0;
2700 case LayoutNavEntry::FileList: return showFiles && index.numDocumentedFiles()>0;
2701 case LayoutNavEntry::FileGlobals: return showFiles && index.numDocumentedFileMembers(FileMemberHighlight::All)>0;
2702 case LayoutNavEntry::Examples: return !Doxygen::exampleLinkedMap->empty();
2703 case LayoutNavEntry::Interfaces: return index.numAnnotatedInterfaces()>0;
2704 case LayoutNavEntry::InterfaceList: return index.numAnnotatedInterfaces()>0;
2705 case LayoutNavEntry::InterfaceIndex: return index.numAnnotatedInterfaces()>0;
2706 case LayoutNavEntry::InterfaceHierarchy: return index.numHierarchyInterfaces()>0;
2707 case LayoutNavEntry::Structs: return index.numAnnotatedStructs()>0;
2708 case LayoutNavEntry::StructList: return index.numAnnotatedStructs()>0;
2709 case LayoutNavEntry::StructIndex: return index.numAnnotatedStructs()>0;
2710 case LayoutNavEntry::Exceptions: return index.numAnnotatedExceptions()>0;
2711 case LayoutNavEntry::ExceptionList: return index.numAnnotatedExceptions()>0;
2712 case LayoutNavEntry::ExceptionIndex: return index.numAnnotatedExceptions()>0;
2713 case LayoutNavEntry::ExceptionHierarchy: return index.numHierarchyExceptions()>0;
2714 case LayoutNavEntry::None: // should never happen, means not properly initialized
2715 assert(kind != LayoutNavEntry::None);
2716 return FALSE;
2717 }
2718 return FALSE;
2719}
2720
2721static void renderQuickLinksAsTree(TextStream &t,const QCString &relPath,LayoutNavEntry *root)
2722
2723{
2724 int count=0;
2725 for (const auto &entry : root->children())
2726 {
2727 if (entry->visible() && quickLinkVisible(entry->kind())) count++;
2728 }
2729 if (count>0) // at least one item is visible
2730 {
2732 for (const auto &entry : root->children())
2733 {
2734 if (entry->visible() && quickLinkVisible(entry->kind()))
2735 {
2736 QCString url = entry->url();
2737 t << "<li><a href=\"" << relPath << url << "\"><span>";
2738 t << fixSpaces(entry->title());
2739 t << "</span></a>\n";
2740 // recursive into child list
2741 renderQuickLinksAsTree(t,relPath,entry.get());
2742 t << "</li>";
2743 }
2744 }
2746 }
2747}
2748
2749
2750static void renderQuickLinksAsTabs(TextStream &t,const QCString &relPath,
2752 bool highlightParent,bool highlightSearch)
2753{
2754 if (hlEntry->parent()) // first draw the tabs for the parent of hlEntry
2755 {
2756 renderQuickLinksAsTabs(t,relPath,hlEntry->parent(),kind,highlightParent,highlightSearch);
2757 }
2758 if (hlEntry->parent() && !hlEntry->parent()->children().empty()) // draw tabs for row containing hlEntry
2759 {
2760 bool topLevel = hlEntry->parent()->parent()==nullptr;
2761 int count=0;
2762 for (const auto &entry : hlEntry->parent()->children())
2763 {
2764 if (entry->visible() && quickLinkVisible(entry->kind())) count++;
2765 }
2766 if (count>0) // at least one item is visible
2767 {
2768 startQuickIndexList(t,topLevel);
2769 for (const auto &entry : hlEntry->parent()->children())
2770 {
2771 if (entry->visible() && quickLinkVisible(entry->kind()))
2772 {
2773 QCString url = entry->url();
2774 startQuickIndexItem(t,url,
2775 entry.get()==hlEntry &&
2776 (!entry->children().empty() ||
2777 (entry->kind()==kind && !highlightParent)
2778 ),
2779 TRUE,relPath);
2780 t << fixSpaces(entry->title());
2781 endQuickIndexItem(t,url);
2782 }
2783 }
2784 if (hlEntry->parent()==LayoutDocManager::instance().rootNavEntry()) // first row is special as it contains the search box
2785 {
2786 bool searchEngine = Config_getBool(SEARCHENGINE);
2787 bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
2788 bool disableIndex = Config_getBool(DISABLE_INDEX);
2789 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2790 bool fullSidebar = Config_getBool(FULL_SIDEBAR);
2791 // case where DISABLE_INDEX=NO & GENERATE_TREEVIEW=YES & FULL_SIDEBAR=YES has search box in the side panel
2792 if (searchEngine)
2793 {
2794 t << " <li>\n";
2795 if (disableIndex || !generateTreeView || !fullSidebar)
2796 {
2797 if (!serverBasedSearch) // pure client side search
2798 {
2799 writeClientSearchBox(t,relPath);
2800 t << " </li>\n";
2801 }
2802 else // server based search
2803 {
2804 writeServerSearchBox(t,relPath,highlightSearch);
2805 if (!highlightSearch)
2806 {
2807 t << " </li>\n";
2808 }
2809 }
2810 }
2811 else
2812 {
2813 t << " </li>\n";
2814 }
2815 }
2816 if (!highlightSearch || Config_getBool(FULL_SIDEBAR))
2817 // on the search page the index will be ended by the page itself if the search box is part of the navigation bar
2818 {
2820 }
2821 }
2822 else // normal case for other rows than first one
2823 {
2825 }
2826 }
2827 }
2828}
2829
2831 HighlightedItem hli,
2832 const QCString &file,
2833 const QCString &relPath,
2834 bool extraTabs)
2835{
2836 bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
2837 bool searchEngine = Config_getBool(SEARCHENGINE);
2838 bool externalSearch = Config_getBool(EXTERNAL_SEARCH);
2839 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2840 bool fullSidebar = Config_getBool(FULL_SIDEBAR);
2841 bool disableIndex = Config_getBool(DISABLE_INDEX);
2842 bool dynamicMenus = Config_getBool(HTML_DYNAMIC_MENUS);
2844 LayoutNavEntry::Kind kind = LayoutNavEntry::None;
2845 LayoutNavEntry::Kind altKind = LayoutNavEntry::None; // fall back for the old layout file
2846 bool highlightParent=false;
2847 switch (hli) // map HLI enums to LayoutNavEntry::Kind enums
2848 {
2849 case HighlightedItem::Main: kind = LayoutNavEntry::MainPage; break;
2850 case HighlightedItem::Topics: kind = LayoutNavEntry::Topics; break;
2851 case HighlightedItem::Modules: kind = LayoutNavEntry::ModuleList; altKind = LayoutNavEntry::Modules; break;
2852 case HighlightedItem::Namespaces: kind = LayoutNavEntry::NamespaceList; altKind = LayoutNavEntry::Namespaces; break;
2853 case HighlightedItem::ClassHierarchy: kind = LayoutNavEntry::ClassHierarchy; break;
2854 case HighlightedItem::InterfaceHierarchy: kind = LayoutNavEntry::InterfaceHierarchy; break;
2855 case HighlightedItem::ExceptionHierarchy: kind = LayoutNavEntry::ExceptionHierarchy; break;
2856 case HighlightedItem::Classes: kind = LayoutNavEntry::ClassIndex; altKind = LayoutNavEntry::Classes; break;
2857 case HighlightedItem::Concepts: kind = LayoutNavEntry::Concepts; break;
2858 case HighlightedItem::Interfaces: kind = LayoutNavEntry::InterfaceIndex; altKind = LayoutNavEntry::Interfaces; break;
2859 case HighlightedItem::Structs: kind = LayoutNavEntry::StructIndex; altKind = LayoutNavEntry::Structs; break;
2860 case HighlightedItem::Exceptions: kind = LayoutNavEntry::ExceptionIndex; altKind = LayoutNavEntry::Exceptions; break;
2861 case HighlightedItem::AnnotatedClasses: kind = LayoutNavEntry::ClassList; altKind = LayoutNavEntry::Classes; break;
2862 case HighlightedItem::AnnotatedInterfaces: kind = LayoutNavEntry::InterfaceList; altKind = LayoutNavEntry::Interfaces; break;
2863 case HighlightedItem::AnnotatedStructs: kind = LayoutNavEntry::StructList; altKind = LayoutNavEntry::Structs; break;
2864 case HighlightedItem::AnnotatedExceptions: kind = LayoutNavEntry::ExceptionList; altKind = LayoutNavEntry::Exceptions; break;
2865 case HighlightedItem::Files: kind = LayoutNavEntry::FileList; altKind = LayoutNavEntry::Files; break;
2866 case HighlightedItem::NamespaceMembers: kind = LayoutNavEntry::NamespaceMembers; break;
2867 case HighlightedItem::ModuleMembers: kind = LayoutNavEntry::ModuleMembers; break;
2868 case HighlightedItem::Functions: kind = LayoutNavEntry::ClassMembers; break;
2869 case HighlightedItem::Globals: kind = LayoutNavEntry::FileGlobals; break;
2870 case HighlightedItem::Pages: kind = LayoutNavEntry::Pages; break;
2871 case HighlightedItem::Examples: kind = LayoutNavEntry::Examples; break;
2872 case HighlightedItem::UserGroup: kind = LayoutNavEntry::UserGroup; break;
2873 case HighlightedItem::ClassVisible: kind = LayoutNavEntry::ClassList; altKind = LayoutNavEntry::Classes;
2874 highlightParent = true; break;
2875 case HighlightedItem::ConceptVisible: kind = LayoutNavEntry::Concepts;
2876 highlightParent = true; break;
2877 case HighlightedItem::ModuleVisible: kind = LayoutNavEntry::ModuleList; altKind = LayoutNavEntry::Modules;
2878 highlightParent = true; break;
2879 case HighlightedItem::InterfaceVisible: kind = LayoutNavEntry::InterfaceList; altKind = LayoutNavEntry::Interfaces;
2880 highlightParent = true; break;
2881 case HighlightedItem::StructVisible: kind = LayoutNavEntry::StructList; altKind = LayoutNavEntry::Structs;
2882 highlightParent = true; break;
2883 case HighlightedItem::ExceptionVisible: kind = LayoutNavEntry::ExceptionList; altKind = LayoutNavEntry::Exceptions;
2884 highlightParent = true; break;
2885 case HighlightedItem::NamespaceVisible: kind = LayoutNavEntry::NamespaceList; altKind = LayoutNavEntry::Namespaces;
2886 highlightParent = true; break;
2887 case HighlightedItem::FileVisible: kind = LayoutNavEntry::FileList; altKind = LayoutNavEntry::Files;
2888 highlightParent = true; break;
2889 case HighlightedItem::None: break;
2890 case HighlightedItem::Search: break;
2891 }
2892
2893 if (!disableIndex && dynamicMenus)
2894 {
2895 QCString searchPage;
2896 if (externalSearch)
2897 {
2898 searchPage = "search" + Doxygen::htmlFileExtension;
2899 }
2900 else
2901 {
2902 searchPage = "search.php";
2903 }
2904 t << "<script type=\"text/javascript\" src=\"" << relPath << "menudata.js\"></script>\n";
2905 t << "<script type=\"text/javascript\" src=\"" << relPath << "menu.js\"></script>\n";
2906 t << "<script type=\"text/javascript\">\n";
2907 t << "$(function() {\n";
2908 t << " initMenu('" << relPath << "',"
2909 << (searchEngine && !(generateTreeView && fullSidebar)?"true":"false") << ","
2910 << (serverBasedSearch?"true":"false") << ",'"
2911 << searchPage << "','"
2912 << theTranslator->trSearch() << "',"
2913 << (generateTreeView?"true":"false")
2914 << ");\n";
2915 if (searchEngine)
2916 {
2917 if (!serverBasedSearch)
2918 {
2919 if (!disableIndex && dynamicMenus && !fullSidebar)
2920 {
2921 t << " $(function() { init_search(); });\n";
2922 }
2923 }
2924 else
2925 {
2926 t << " $(function() {\n"
2927 << " if ($('.searchresults').length > 0) { searchBox.DOMSearchField().focus(); }\n";
2928 t << " });\n";
2929 }
2930 }
2931 t << "});\n";
2932 t << "</script>\n";
2933 t << "<div id=\"main-nav\"></div>\n";
2934 }
2935 else if (!disableIndex) // && !Config_getBool(HTML_DYNAMIC_MENUS)
2936 {
2937 // find highlighted index item
2938 LayoutNavEntry *hlEntry = root->find(kind,kind==LayoutNavEntry::UserGroup ? file : QCString());
2939 if (!hlEntry && altKind!=LayoutNavEntry::None) { hlEntry=root->find(altKind); kind=altKind; }
2940 if (!hlEntry) // highlighted item not found in the index! -> just show the level 1 index...
2941 {
2942 highlightParent=TRUE;
2943 hlEntry = root->children().front().get();
2944 if (hlEntry==nullptr)
2945 {
2946 return; // argl, empty index!
2947 }
2948 }
2949 if (kind==LayoutNavEntry::UserGroup)
2950 {
2951 LayoutNavEntry *e = hlEntry->children().front().get();
2952 if (e)
2953 {
2954 hlEntry = e;
2955 }
2956 }
2957 t << "<div id=\"main-nav\">\n";
2958 renderQuickLinksAsTabs(t,relPath,hlEntry,kind,highlightParent,hli==HighlightedItem::Search);
2959 if (!extraTabs)
2960 {
2961 t << "</div><!-- main-nav -->\n";
2962 }
2963 }
2964 else if (!generateTreeView)
2965 {
2966 renderQuickLinksAsTree(t,relPath,root);
2967 }
2968 if (generateTreeView && !disableIndex && fullSidebar && !extraTabs)
2969 {
2970 t << "<div id=\"container\"><div id=\"doc-content\">\n";
2971 }
2972}
2973
2975{
2976 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2977 m_t << "</div><!-- top -->\n";
2978 if (!generateTreeView)
2979 {
2980 m_t << "<div id=\"doc-content\">\n";
2981 }
2982}
2983
2984QCString HtmlGenerator::writeSplitBarAsString(const QCString &name,const QCString &relpath,const QCString &allMembersFile)
2985{
2986 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
2987 QCString result;
2988 // write split bar
2989 if (generateTreeView)
2990 {
2991 QCString fn = name;
2993 if (!Config_getBool(FULL_SIDEBAR))
2994 {
2995 result += QCString(
2996 "<div id=\"side-nav\" class=\"ui-resizable side-nav-resizable\">\n");
2997 }
2998 result+=
2999 " <div id=\"nav-tree\">\n"
3000 " <div id=\"nav-tree-contents\">\n"
3001 " <div id=\"nav-sync\" class=\"sync\"></div>\n"
3002 " </div>\n"
3003 " </div>\n"
3004 " <div id=\"splitbar\" style=\"-moz-user-select:none;\" \n"
3005 " class=\"ui-resizable-handle\">\n"
3006 " </div>\n"
3007 "</div>\n"
3008 "<script type=\"text/javascript\">\n"
3009 "$(function(){initNavTree('" + fn + "','" + relpath + "','" + allMembersFile + "'); });\n"
3010 "</script>\n";
3011 if (Config_getBool(DISABLE_INDEX) || !Config_getBool(FULL_SIDEBAR))
3012 {
3013 result+="<div id=\"container\">\n<div id=\"doc-content\">\n";
3014 }
3015 }
3016 return result;
3017}
3018
3019void HtmlGenerator::writeSplitBar(const QCString &name,const QCString &allMembersFile)
3020{
3021 m_t << writeSplitBarAsString(name,m_relPath,allMembersFile);
3022}
3023
3025{
3026 m_t << substitute(s,"$relpath^",m_relPath);
3027}
3028
3030{
3031 m_t << "<div class=\"contents\">\n";
3032}
3033
3035{
3036 m_t << "</div><!-- contents -->\n";
3037}
3038
3039void HtmlGenerator::startPageDoc(const QCString &/* pageTitle */)
3040{
3041 m_t << "<div>";
3042}
3043
3045{
3046 m_t << "</div><!-- PageDoc -->\n";
3047}
3048
3049void HtmlGenerator::writeQuickLinks(HighlightedItem hli,const QCString &file,bool extraTabs)
3050{
3051 writeDefaultQuickLinks(m_t,hli,file,m_relPath,extraTabs);
3052}
3053
3054// PHP based search script
3056{
3057 bool disableIndex = Config_getBool(DISABLE_INDEX);
3058 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
3059 bool fullSidebar = Config_getBool(FULL_SIDEBAR);
3060 bool quickLinksAfterSplitbar = !disableIndex && generateTreeView && fullSidebar;
3061 QCString projectName = Config_getString(PROJECT_NAME);
3062 QCString htmlOutput = Config_getString(HTML_OUTPUT);
3063
3064 // OPENSEARCH_PROVIDER {
3065 QCString configFileName = htmlOutput+"/search_config.php";
3066 std::ofstream f = Portable::openOutputStream(configFileName);
3067 if (f.is_open())
3068 {
3069 TextStream t(&f);
3070 t << "<?php\n\n";
3071 t << "$config = array(\n";
3072 t << " 'PROJECT_NAME' => \"" << convertToHtml(projectName) << "\",\n";
3073 t << " 'GENERATE_TREEVIEW' => " << (generateTreeView?"true":"false") << ",\n";
3074 t << " 'DISABLE_INDEX' => " << (disableIndex?"true":"false") << ",\n";
3075 t << " 'FULL_SIDEBAR' => " << (fullSidebar?"true":"false") << ",\n";
3076 t << ");\n\n";
3077 t << "$translator = array(\n";
3078 t << " 'search_results_title' => \"" << theTranslator->trSearchResultsTitle() << "\",\n";
3079 t << " 'search_results' => array(\n";
3080 t << " 0 => \"" << theTranslator->trSearchResults(0) << "\",\n";
3081 t << " 1 => \"" << theTranslator->trSearchResults(1) << "\",\n";
3082 t << " 2 => \"" << substitute(theTranslator->trSearchResults(2), "$", "\\$") << "\",\n";
3083 t << " ),\n";
3084 t << " 'search_matches' => \"" << theTranslator->trSearchMatches() << "\",\n";
3085 t << " 'search' => \"" << theTranslator->trSearch() << "\",\n";
3086 t << " 'logo' => \"" << substitute(substitute(writeLogoAsString(""), "\"","\\\""), "\n","\\n") << "\",\n";
3087 t << ");\n\n";
3088 t << "?>\n";
3089 }
3090 f.close();
3091
3092 ResourceMgr::instance().copyResource("search_functions.php",htmlOutput);
3093 ResourceMgr::instance().copyResource("search_opensearch.php",htmlOutput);
3094 // OPENSEARCH_PROVIDER }
3095
3096 QCString fileName = htmlOutput+"/search.php";
3098 if (f.is_open())
3099 {
3100 TextStream t(&f);
3102
3103 t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen "
3104 << getDoxygenVersion() << " -->\n";
3105 t << "<script type=\"text/javascript\">\n";
3106 t << "var searchBox = new SearchBox(\"searchBox\", \""
3107 << "search/\",'" << Doxygen::htmlFileExtension << "');\n";
3108 t << "</script>\n";
3109
3110 if (!disableIndex && !quickLinksAfterSplitbar)
3111 {
3113 }
3114 if (generateTreeView)
3115 {
3116 t << "</div><!-- top -->\n";
3117 }
3118 t << writeSplitBarAsString("search.php",QCString(),QCString());
3119 if (quickLinksAfterSplitbar)
3120 {
3122 }
3123 t << "<!-- generated -->\n";
3124
3125 t << "<?php\n";
3126 t << "require_once \"search_functions.php\";\n";
3127 t << "main();\n";
3128 t << "?>\n";
3129
3130 // Write empty navigation path, to make footer connect properly
3131 if (generateTreeView)
3132 {
3133 t << "</div><!-- doc-content -->\n";
3134 t << "</div><!-- container -->\n";
3135 }
3136
3137 writePageFooter(t,"Search","","");
3138 }
3139 f.close();
3140
3141 QCString scriptName = htmlOutput+"/search/search.js";
3142 f = Portable::openOutputStream(scriptName);
3143 if (f.is_open())
3144 {
3145 TextStream t(&f);
3146 t << ResourceMgr::instance().getAsString("extsearch.js");
3147 }
3148 else
3149 {
3150 err("Failed to open file '{}' for writing...\n",scriptName);
3151 }
3152}
3153
3155{
3156 bool disableIndex = Config_getBool(DISABLE_INDEX);
3157 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
3158 bool fullSidebar = Config_getBool(FULL_SIDEBAR);
3159 bool quickLinksAfterSplitbar = !disableIndex && generateTreeView && fullSidebar;
3160 QCString dname = Config_getString(HTML_OUTPUT);
3162 std::ofstream f = Portable::openOutputStream(fileName);
3163 if (f.is_open())
3164 {
3165 TextStream t(&f);
3167
3168 t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen "
3169 << getDoxygenVersion() << " -->\n";
3170 t << "<script type=\"text/javascript\">\n";
3171 t << "var searchBox = new SearchBox(\"searchBox\", \""
3172 << "search/\",'" << Doxygen::htmlFileExtension << "');\n";
3173 t << "</script>\n";
3174
3175 if (!disableIndex && !quickLinksAfterSplitbar)
3176 {
3178 }
3179 if (generateTreeView)
3180 {
3181 t << "</div><!-- top -->\n";
3182 }
3183 t << writeSplitBarAsString("search.php",QCString(),QCString());
3184 if (quickLinksAfterSplitbar)
3185 {
3187 }
3188
3189 t << "<div class=\"header\">\n";
3190 t << " <div class=\"headertitle\">\n";
3191 t << " <div class=\"title\">" << theTranslator->trSearchResultsTitle() << "</div>\n";
3192 t << " </div>\n";
3193 t << "</div>\n";
3194 t << "<div class=\"contents\">\n";
3195
3196 t << "<div id=\"searchresults\"></div>\n";
3197 t << "</div>\n";
3198
3199 if (generateTreeView)
3200 {
3201 t << "</div><!-- doc-content -->\n";
3202 t << "</div><!-- container -->\n";
3203 }
3204
3205 writePageFooter(t,"Search","","");
3206
3207 }
3208 f.close();
3209
3210 QCString scriptName = dname+"/search/search.js";
3211 f = Portable::openOutputStream(scriptName);
3212 if (f.is_open())
3213 {
3214 TextStream t(&f);
3215 t << "var searchResultsText=["
3216 << "\"" << theTranslator->trSearchResults(0) << "\","
3217 << "\"" << theTranslator->trSearchResults(1) << "\","
3218 << "\"" << theTranslator->trSearchResults(2) << "\"];\n";
3219 t << "var serverUrl=\"" << Config_getString(SEARCHENGINE_URL) << "\";\n";
3220 t << "var tagMap = {\n";
3221 bool first=TRUE;
3222 // add search mappings
3223 const StringVector &extraSearchMappings = Config_getList(EXTRA_SEARCH_MAPPINGS);
3224 for (const auto &ml : extraSearchMappings)
3225 {
3226 QCString mapLine = ml.c_str();
3227 int eqPos = mapLine.find('=');
3228 if (eqPos!=-1) // tag command contains a destination
3229 {
3230 QCString tagName = mapLine.left(eqPos).stripWhiteSpace();
3231 QCString destName = mapLine.right(mapLine.length()-eqPos-1).stripWhiteSpace();
3232 if (!tagName.isEmpty())
3233 {
3234 if (!first) t << ",\n";
3235 t << " \"" << tagName << "\": \"" << destName << "\"";
3236 first=FALSE;
3237 }
3238 }
3239 }
3240 if (!first) t << "\n";
3241 t << "};\n\n";
3242 t << ResourceMgr::instance().getAsString("extsearch.js");
3243 t << "\n";
3244 t << "$(function() {\n";
3245 t << " var query = trim(getURLParameter('query'));\n";
3246 t << " if (query) {\n";
3247 t << " searchFor(query,0,20);\n";
3248 t << " } else {\n";
3249 t << " var results = $('#results');\n";
3250 t << " results.html('<p>" << theTranslator->trSearchResults(0) << "</p>');\n";
3251 t << " }\n";
3252 t << "});\n";
3253 }
3254 else
3255 {
3256 err("Failed to open file '{}' for writing...\n",scriptName);
3257 }
3258}
3259
3261{
3262 m_t << "<div class=\"typeconstraint\">\n";
3263 m_t << "<dl><dt><b>" << header << "</b></dt><dd>\n";
3264 m_t << "<table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">\n";
3265}
3266
3268{
3269 m_t << "<tr><td valign=\"top\"><em>";
3270}
3271
3273{
3274 m_t << "</em></td>";
3275}
3276
3278{
3279 m_t << "<td>&#160;:</td><td valign=\"top\"><em>";
3280}
3281
3283{
3284 m_t << "</em></td>";
3285}
3286
3288{
3289 m_t << "<td>&#160;";
3290}
3291
3293{
3294 m_t << "</td></tr>\n";
3295}
3296
3298{
3299 m_t << "</table>\n";
3300 m_t << "</dd>\n";
3301 m_t << "</dl>\n";
3302 m_t << "</div>\n";
3303}
3304
3306{
3307 if (!style.isEmpty())
3308 {
3309 m_t << "<br class=\"" << style << "\" />\n";
3310 }
3311 else
3312 {
3313 m_t << "<br />\n";
3314 }
3315}
3316
3318{
3319 m_t << "<div class=\"header\">\n";
3320}
3321
3323{
3324 m_t << " <div class=\"headertitle\">";
3325 startTitle();
3326}
3327
3329{
3330 endTitle();
3331 m_t << "</div>\n";
3332}
3333
3335{
3336 m_t << "</div><!--header-->\n";
3337}
3338
3340{
3341 if (m_emptySection)
3342 {
3343 m_t << "<table class=\"memberdecls\">\n";
3345 }
3346 m_t << "<tr><td colspan=\"2\"><h3>";
3347}
3348
3350{
3351 m_t << "</h3></td></tr>\n";
3352}
3353
3355{
3356 DBG_HTML(m_t << "<!-- startMemberDocSimple -->\n";)
3357 m_t << "<table class=\"fieldtable\">\n";
3358 m_t << "<tr><th colspan=\"" << (isEnum?"2":"3") << "\">";
3359 m_t << (isEnum? theTranslator->trEnumerationValues() :
3360 theTranslator->trCompoundMembers()) << "</th></tr>\n";
3361}
3362
3364{
3365 DBG_HTML(m_t << "<!-- endMemberDocSimple -->\n";)
3366 m_t << "</table>\n";
3367}
3368
3370{
3371 DBG_HTML(m_t << "<!-- startInlineMemberType -->\n";)
3372 m_t << "<tr><td class=\"fieldtype\">\n";
3373}
3374
3376{
3377 DBG_HTML(m_t << "<!-- endInlineMemberType -->\n";)
3378 m_t << "</td>\n";
3379}
3380
3382{
3383 DBG_HTML(m_t << "<!-- startInlineMemberName -->\n";)
3384 m_t << "<td class=\"fieldname\">\n";
3385}
3386
3388{
3389 DBG_HTML(m_t << "<!-- endInlineMemberName -->\n";)
3390 m_t << "</td>\n";
3391}
3392
3394{
3395 DBG_HTML(m_t << "<!-- startInlineMemberDoc -->\n";)
3396 m_t << "<td class=\"fielddoc\">\n";
3397}
3398
3400{
3401 DBG_HTML(m_t << "<!-- endInlineMemberDoc -->\n";)
3402 m_t << "</td></tr>\n";
3403}
3404
3406{
3407 DBG_HTML(m_t << "<!-- startLabels -->\n";)
3408 m_t << "<span class=\"mlabels\">";
3409}
3410
3411void HtmlGenerator::writeLabel(const QCString &label,bool /*isLast*/)
3412{
3413 DBG_HTML(m_t << "<!-- writeLabel(" << label << ") -->\n";)
3414
3415 auto convertLabelToClass = [](const std::string &lab) {
3416 QCString input = convertUTF8ToLower(lab);
3417 QCString result;
3418 size_t l=input.length();
3419 result.reserve(l);
3420
3421 // Create valid class selector, see 10.2 here https://www.w3.org/TR/selectors-3/#w3cselgrammar
3422 // ident [-]?{nmstart}{nmchar}*
3423 // nmstart [_a-z]|{nonascii}
3424 // nonascii [^\0-\177]
3425 // nmchar [_a-z0-9-]|{nonascii}
3426
3427 bool nmstart=false;
3428 for (size_t i=0; i<l; i++)
3429 {
3430 char c = input.at(i);
3431 if (c<0 || (c>='a' && c<='z') || c=='_') // nmstart pattern
3432 {
3433 nmstart=true;
3434 result+=c;
3435 }
3436 else if (nmstart && (c<0 || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='_')) // nmchar pattern
3437 {
3438 result+=c;
3439 }
3440 else if (nmstart && (c==' ' || c=='-')) // show whitespace as -
3441 {
3442 result+='-';
3443 }
3444 }
3445 return result;
3446 };
3447
3448 m_t << "<span class=\"mlabel " << convertLabelToClass(label.stripWhiteSpace().str()) << "\">" << label << "</span>";
3449}
3450
3452{
3453 DBG_HTML(m_t << "<!-- endLabels -->\n";)
3454 m_t << "</span>";
3455}
3456
3458 const QCString &id, const QCString &ref,
3459 const QCString &file, const QCString &anchor,
3460 const QCString &title, const QCString &name)
3461{
3462 DBG_HTML(m_t << "<!-- writeInheritedSectionTitle -->\n";)
3463 QCString a = anchor;
3464 if (!a.isEmpty()) a.prepend("#");
3465 QCString classLink = QCString("<a class=\"el\" ");
3466 if (!ref.isEmpty())
3467 {
3468 classLink+= externalLinkTarget();
3469 classLink += " href=\"";
3470 classLink+= externalRef(m_relPath,ref,TRUE);
3471 }
3472 else
3473 {
3474 classLink += "href=\"";
3475 classLink+=m_relPath;
3476 }
3477 QCString fn = file;
3479 classLink=classLink+fn+a;
3480 classLink+=QCString("\">")+convertToHtml(name,FALSE)+"</a>";
3481 m_t << "<tr class=\"inherit_header " << id << "\">"
3482 << "<td colspan=\"2\" onclick=\"javascript:dynsection.toggleInherit('" << id << "')\">"
3483 << "<span class=\"dynarrow\"><span class=\"arrowhead closed\"></span></span>"
3484 << theTranslator->trInheritedFrom(convertToHtml(title,FALSE),classLink)
3485 << "</td></tr>\n";
3486}
3487
3488void HtmlGenerator::writeSummaryLink(const QCString &file,const QCString &anchor,const QCString &title,bool first)
3489{
3490 if (first)
3491 {
3492 m_t << " <div class=\"summary\">\n";
3493 }
3494 else
3495 {
3496 m_t << " &#124;\n";
3497 }
3498 m_t << "<a href=\"";
3499 if (!file.isEmpty())
3500 {
3501 QCString fn = file;
3503 m_t << m_relPath << fn;
3504 }
3505 else if (!anchor.isEmpty())
3506 {
3507 m_t << "#";
3508 m_t << anchor;
3509 }
3510 m_t << "\">";
3511 m_t << title;
3512 m_t << "</a>";
3513}
3514
3516{
3517 m_t << "<div id=\"page-nav\" class=\"page-nav-panel\">\n";
3518 m_t << "<div id=\"page-nav-resize-handle\"></div>\n";
3519 m_t << "<div id=\"page-nav-tree\">\n";
3520 m_t << "<div id=\"page-nav-contents\">\n";
3521 m_t << "</div><!-- page-nav-contents -->\n";
3522 m_t << "</div><!-- page-nav-tree -->\n";
3523 m_t << "</div><!-- page-nav -->\n";
3524}
3525
3526void HtmlGenerator::endMemberDeclaration(const QCString &anchor,const QCString &inheritId)
3527{
3528}
3529
3534
3536{
3538 return replaceVariables(mgr.getAsString("navtree.css"));
3539}
3540
3542{
3543 m_tocState.level=0;
3544 m_tocState.indent=0;
3545 m_tocState.maxLevel=level;
3546 m_tocState.inLi = BoolVector(level+1,false);
3547 m_t << "<div class=\"toc\">";
3548 m_t << "<h3>" << theTranslator->trRTFTableOfContents() << "</h3>\n";
3549}
3550
3552{
3553 if (m_tocState.level > m_tocState.maxLevel) m_tocState.level = m_tocState.maxLevel;
3554 while (m_tocState.level>0)
3555 {
3556 m_tocState.decIndent(m_t,"</li>");
3557 m_tocState.decIndent(m_t,"</ul>");
3558 m_tocState.level--;
3559 }
3560 m_t << "</div>\n";
3561}
3562
3564{
3565 SectionType type = si->type();
3566 if (type.isSection())
3567 {
3568 //printf(" level=%d title=%s maxLevel=%d\n",level,qPrint(si->title()),maxLevel);
3569 int nextLevel = type.level();
3570 if (nextLevel>m_tocState.level)
3571 {
3572 for (int l=m_tocState.level;l<nextLevel;l++)
3573 {
3574 if (l < m_tocState.maxLevel)
3575 {
3576 m_tocState.incIndent(m_t,"<ul>");
3577 char cs[2] = { static_cast<char>('0'+l+1), 0 };
3578 const char *empty = (l!=nextLevel-1) ? " empty" : "";
3579 m_tocState.incIndent(m_t,"<li class=\"level" + QCString(cs) + empty + "\">");
3580 }
3581 }
3582 }
3583 else if (nextLevel<m_tocState.level)
3584 {
3585 for (int l=m_tocState.level;l>nextLevel;l--)
3586 {
3587 if (l <= m_tocState.maxLevel) m_tocState.decIndent(m_t,"</li>");
3588 m_tocState.inLi[l] = false;
3589 if (l <= m_tocState.maxLevel) m_tocState.decIndent(m_t,"</ul>");
3590 }
3591 }
3592 if (nextLevel <= m_tocState.maxLevel)
3593 {
3594 if (m_tocState.inLi[nextLevel] || m_tocState.level>nextLevel)
3595 {
3596 m_tocState.decIndent(m_t,"</li>");
3597 char cs[2] = { static_cast<char>('0'+nextLevel), 0 };
3598 m_tocState.incIndent(m_t,"<li class=\"level" + QCString(cs) + "\">");
3599 }
3600 QCString label = si->label();
3601 m_tocState.writeIndent(m_t);
3602 m_t << "<a href=\"#"+label+"\">";
3603 }
3604 }
3605}
3606
3608{
3609 SectionType type = si->type();
3610 int nextLevel = type.level();
3611 if (type.isSection() && nextLevel<=m_tocState.maxLevel)
3612 {
3613 m_t << "</a>\n";
3614 m_tocState.inLi[nextLevel]=true;
3615 m_tocState.level = nextLevel;
3616 }
3617}
3618
constexpr auto prefix
Definition anchor.cpp:44
Class representing a built-in class diagram.
Definition diagram.h:31
void writeImage(TextStream &t, const QCString &path, const QCString &relPath, const QCString &file, bool generateMap=true) const
Definition diagram.cpp:1369
The common base class of all entity definitions found in the sources.
Definition definition.h:76
Class representing a directory in the file system.
Definition dir.h:75
bool mkdir(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:295
bool exists() const
Definition dir.cpp:257
Class representing the abstract syntax tree of a documentation block.
Definition docnode.h:1461
DocNodeVariant root
Definition docnode.h:1482
Representation of an call graph.
QCString writeGraph(TextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, const QCString &path, const QCString &fileName, const QCString &relPath, bool writeImageMap=TRUE, int graphId=-1)
Representation of a class inheritance or dependency graph.
QCString writeGraph(TextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, const QCString &path, const QCString &fileName, const QCString &relPath, bool TBRank=TRUE, bool imageMap=TRUE, int graphId=-1)
Representation of an directory dependency graph.
Definition dotdirdeps.h:26
QCString writeGraph(TextStream &out, GraphOutputFormat gf, EmbeddedOutputFormat ef, const QCString &path, const QCString &fileName, const QCString &relPath, bool writeImageMap=TRUE, int graphId=-1, bool linkRelations=TRUE)
Represents a graphical class hierarchy.
void writeGraph(TextStream &t, const QCString &path, const QCString &fileName)
Representation of a group collaboration graph.
QCString writeGraph(TextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, const QCString &path, const QCString &fileName, const QCString &relPath, bool writeImageMap=TRUE, int graphId=-1)
Representation of an include dependency graph.
QCString writeGraph(TextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, const QCString &path, const QCString &fileName, const QCString &relPath, bool writeImageMap=TRUE, int graphId=-1)
static PageLinkedMap * exampleLinkedMap
Definition doxygen.h:99
static IndexList * indexList
Definition doxygen.h:134
static QCString htmlFileExtension
Definition doxygen.h:122
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
bool exists() const
Definition fileinfo.cpp:30
std::string fileName() const
Definition fileinfo.cpp:118
bool isReadable() const
Definition fileinfo.cpp:44
bool isFile() const
Definition fileinfo.cpp:63
std::string absFilePath() const
Definition fileinfo.cpp:101
Class representing a string buffer optimized for growing.
Definition growbuf.h:28
void addChar(char c)
Definition growbuf.h:69
void addStr(const QCString &s)
Definition growbuf.h:72
char * get()
Definition growbuf.h:114
Generator for HTML code fragments.
Definition htmlgen.h:26
void codify(const QCString &text) override
Definition htmlgen.cpp:731
bool m_stripCodeComments
Definition htmlgen.h:77
void startSpecialComment() override
Definition htmlgen.cpp:817
void endCodeLine() override
Definition htmlgen.cpp:1000
void startFontClass(const QCString &s) override
Definition htmlgen.cpp:1015
void writeCodeAnchor(const QCString &anchor) override
Definition htmlgen.cpp:1027
QCString fileName()
Definition htmlgen.h:33
size_t m_stripIndentAmount
Definition htmlgen.h:91
QCString m_relPath
Definition htmlgen.h:74
void writeCodeLink(CodeSymbolType type, const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name, const QCString &tooltip) override
Definition htmlgen.cpp:865
void startFold(int, const QCString &, const QCString &) override
Definition htmlgen.cpp:1046
void writeLineNumber(const QCString &, const QCString &, const QCString &, int, bool) override
Definition htmlgen.cpp:834
void startCodeLine(int) override
Definition htmlgen.cpp:989
void endFold() override
Definition htmlgen.cpp:1080
void _writeCodeLink(const QCString &className, const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name, const QCString &tooltip)
Definition htmlgen.cpp:881
void setRelativePath(const QCString &path)
Definition htmlgen.cpp:726
void setStripIndentAmount(size_t amount) override
Definition htmlgen.cpp:829
void endSpecialComment() override
Definition htmlgen.cpp:823
HtmlCodeGenerator(TextStream *t, const QCString &relPath)
Definition htmlgen.cpp:720
void writeTooltip(const QCString &id, const DocLinkInfo &docInfo, const QCString &decl, const QCString &desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo) override
Definition htmlgen.cpp:909
void endFontClass() override
Definition htmlgen.cpp:1021
void startCodeFragment(const QCString &style) override
Definition htmlgen.cpp:1033
TextStream * m_t
Definition htmlgen.h:72
LineInfo m_lastLineInfo
Definition htmlgen.h:90
void endCodeFragment(const QCString &) override
Definition htmlgen.cpp:1038
void stripCodeComments(bool b) override
Definition htmlgen.cpp:812
OutputType type() const override
Definition htmlgen.h:35
Concrete visitor implementation for HTML output.
void startClassDiagram() override
Definition htmlgen.cpp:1964
void writeLogo() override
Definition htmlgen.cpp:1536
void endFile() override
Definition htmlgen.cpp:1552
void endParameterExtra(bool last, bool emptyList, bool closeBracket) override
Definition htmlgen.cpp:2309
static void init()
Definition htmlgen.cpp:1141
void startTocEntry(const SectionInfo *si) override
Definition htmlgen.cpp:3563
void startInlineMemberName() override
Definition htmlgen.cpp:3381
void endDescTableInit() override
Definition htmlgen.cpp:2581
void startTitle()
Definition htmlgen.h:338
void startTextLink(const QCString &file, const QCString &anchor) override
Definition htmlgen.cpp:1760
void startInlineMemberType() override
Definition htmlgen.cpp:3369
void endDescTable() override
Definition htmlgen.cpp:2551
void startParameterDefVal(const char *sep) override
Definition htmlgen.cpp:2333
void endMemberGroupHeader() override
Definition htmlgen.cpp:2498
void startIndexKey() override
Definition htmlgen.cpp:2186
void lineBreak(const QCString &style) override
Definition htmlgen.cpp:3305
void startParameterName(bool) override
Definition htmlgen.cpp:2292
void startMemberItem(const QCString &anchor, MemberItemType, const QCString &inheritId) override
Definition htmlgen.cpp:2017
static void writeSearchPage()
Definition htmlgen.cpp:3055
void startInclDepGraph() override
Definition htmlgen.cpp:2416
void insertMemberAlignLeft(MemberItemType, bool) override
Definition htmlgen.cpp:2079
void writeQuickLinks(HighlightedItem hli, const QCString &file, bool extraTabs) override
Definition htmlgen.cpp:3049
void startMemberSubtitle() override
Definition htmlgen.cpp:2164
HtmlGenerator & operator=(const HtmlGenerator &)
Definition htmlgen.cpp:1116
void writeFooter(const QCString &navPath) override
Definition htmlgen.cpp:1547
int m_sectionCount
Definition htmlgen.h:346
void startMemberDocName(bool) override
Definition htmlgen.cpp:2245
void endParameterType() override
Definition htmlgen.cpp:2286
void startLabels() override
Definition htmlgen.cpp:3405
void startCallGraph() override
Definition htmlgen.cpp:2452
TocState m_tocState
Definition htmlgen.h:362
void endMemberList() override
Definition htmlgen.cpp:2008
static QCString getNavTreeCss()
Definition htmlgen.cpp:3535
void startParagraph(const QCString &classDef) override
Definition htmlgen.cpp:1653
void endIndexList() override
Definition htmlgen.cpp:2181
void writeSearchInfo() override
Definition htmlgen.cpp:1499
void startContents() override
Definition htmlgen.cpp:3029
void startMemberDoc(const QCString &clName, const QCString &memName, const QCString &anchor, const QCString &title, int memCount, int memTotal, bool showInline) override
Definition htmlgen.cpp:2216
void startDescTableRow() override
Definition htmlgen.cpp:2556
void startDoxyAnchor(const QCString &fName, const QCString &manName, const QCString &anchor, const QCString &name, const QCString &args) override
Definition htmlgen.cpp:1638
void startDirDepGraph() override
Definition htmlgen.cpp:2470
void startCompoundTemplateParams() override
Definition htmlgen.cpp:2063
void startConstraintParam() override
Definition htmlgen.cpp:3267
void endGroupHeader(int) override
Definition htmlgen.cpp:1798
QCString m_lastFile
Definition htmlgen.h:344
void writeNavigationPath(const QCString &s) override
Definition htmlgen.cpp:3024
void writeObjectLink(const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name) override
Definition htmlgen.cpp:1736
void startMemberDescription(const QCString &anchor, const QCString &inheritId, bool typ) override
Definition htmlgen.cpp:2091
void writeChar(char c) override
Definition htmlgen.cpp:1883
void endConstraintList() override
Definition htmlgen.cpp:3297
void endParameterList() override
Definition htmlgen.cpp:2345
void startMemberGroupHeader(const QCString &, bool) override
Definition htmlgen.cpp:2493
void writeDoc(const IDocNodeAST *node, const Definition *, const MemberDef *, int id) override
Definition htmlgen.cpp:2608
void startDotGraph() override
Definition htmlgen.cpp:2382
void endIndent() override
Definition htmlgen.cpp:2528
void endParameterName() override
Definition htmlgen.cpp:2298
void endPageDoc() override
Definition htmlgen.cpp:3044
void startMemberDocList() override
Definition htmlgen.cpp:2206
static QCString writeLogoAsString(const QCString &path)
Definition htmlgen.cpp:1505
void endDescTableRow() override
Definition htmlgen.cpp:2561
void startParameterType(bool first, const QCString &key) override
Definition htmlgen.cpp:2269
void startDescTableInit() override
Definition htmlgen.cpp:2576
void startLocalToc(int level) override
Definition htmlgen.cpp:3541
void startMemberList() override
Definition htmlgen.cpp:2003
void endQuickIndices() override
Definition htmlgen.cpp:2974
void startHeaderSection() override
Definition htmlgen.cpp:3317
void startDescTableTitle() override
Definition htmlgen.cpp:2566
void endDirDepGraph(DotDirDeps &g) override
Definition htmlgen.cpp:2475
void startIndexList() override
Definition htmlgen.cpp:2176
void endParameterDefVal() override
Definition htmlgen.cpp:2340
void endMemberGroup(bool) override
Definition htmlgen.cpp:2517
void endInlineHeader() override
Definition htmlgen.cpp:3349
static void writeFooterFile(TextStream &t)
Definition htmlgen.cpp:1422
void endMemberDescription() override
Definition htmlgen.cpp:2110
void startGroupCollaboration() override
Definition htmlgen.cpp:2434
void endClassDiagram(const ClassDiagram &, const QCString &, const QCString &) override
Definition htmlgen.cpp:1969
void startConstraintList(const QCString &) override
Definition htmlgen.cpp:3260
void startDescTable(const QCString &title, const bool hasInits) override
Definition htmlgen.cpp:2546
void endConstraintDocs() override
Definition htmlgen.cpp:3292
void writeNonBreakableSpace(int) override
Definition htmlgen.cpp:2538
void writePageOutline() override
Definition htmlgen.cpp:3515
void startInlineMemberDoc() override
Definition htmlgen.cpp:3393
void exceptionEntry(const QCString &, bool) override
Definition htmlgen.cpp:2352
static void writeTabData()
Additional initialization after indices have been created.
Definition htmlgen.cpp:1288
void endExamples() override
Definition htmlgen.cpp:2603
void endIndexKey() override
Definition htmlgen.cpp:2191
void writeString(const QCString &text) override
Definition htmlgen.cpp:1666
void endMemberDocName() override
Definition htmlgen.cpp:2255
void endContents() override
Definition htmlgen.cpp:3034
void endInlineMemberType() override
Definition htmlgen.cpp:3375
void startMemberGroupDocs() override
Definition htmlgen.cpp:2503
void startMemberDocSimple(bool) override
Definition htmlgen.cpp:3354
void startIndexItem(const QCString &ref, const QCString &file) override
Definition htmlgen.cpp:1681
OutputType type() const override
Definition htmlgen.h:122
void endHeaderSection() override
Definition htmlgen.cpp:3334
void startIndent() override
Definition htmlgen.cpp:2521
void writeStyleInfo(int part) override
Definition htmlgen.cpp:1567
void addIndexItem(const QCString &, const QCString &) override
Definition htmlgen.cpp:2534
void docify_(const QCString &text, bool inHtmlComment)
Definition htmlgen.cpp:1850
void endMemberGroupDocs() override
Definition htmlgen.cpp:2508
void cleanup() override
Definition htmlgen.cpp:1280
void endDotGraph(DotClassGraph &g) override
Definition htmlgen.cpp:2387
void endMemberHeader() override
Definition htmlgen.cpp:2158
void endTextLink() override
Definition htmlgen.cpp:1772
void writeLabel(const QCString &l, bool isLast) override
Definition htmlgen.cpp:3411
void startMemberSections() override
Definition htmlgen.cpp:2116
static void writeSearchData(const QCString &dir)
Definition htmlgen.cpp:1297
void endMemberSections() override
Definition htmlgen.cpp:2124
void endMemberDocList() override
Definition htmlgen.cpp:2211
void endCompoundTemplateParams() override
Definition htmlgen.cpp:2068
static void writeExternalSearchPage()
Definition htmlgen.cpp:3154
void endDescTableData() override
Definition htmlgen.cpp:2591
void startDescTableData() override
Definition htmlgen.cpp:2586
void writeStartAnnoItem(const QCString &type, const QCString &file, const QCString &path, const QCString &name) override
Definition htmlgen.cpp:1724
static void writePageFooter(TextStream &t, const QCString &, const QCString &, const QCString &)
Definition htmlgen.cpp:1541
void endParagraph() override
Definition htmlgen.cpp:1661
void insertMemberAlign(bool) override
Definition htmlgen.cpp:2073
static void writeStyleSheetFile(TextStream &t)
Definition htmlgen.cpp:1410
void endDoxyAnchor(const QCString &fName, const QCString &anchor) override
Definition htmlgen.cpp:1645
void startMemberTemplateParams() override
Definition htmlgen.cpp:2048
void endLabels() override
Definition htmlgen.cpp:3451
void startPageDoc(const QCString &pageTitle) override
Definition htmlgen.cpp:3039
void endMemberDeclaration(const QCString &anchor, const QCString &inheritId) override
Definition htmlgen.cpp:3526
HtmlCodeGenerator * m_codeGen
Definition htmlgen.h:349
void startIndexValue(bool) override
Definition htmlgen.cpp:2196
void endGroupCollaboration(DotGroupCollaboration &g) override
Definition htmlgen.cpp:2439
QCString m_relPath
Definition htmlgen.h:345
static void writeSearchInfoStatic(TextStream &t, const QCString &relPath)
Definition htmlgen.cpp:1469
void endLocalToc() override
Definition htmlgen.cpp:3551
std::unique_ptr< OutputCodeList > m_codeList
Definition htmlgen.h:348
static void writeHeaderFile(TextStream &t, const QCString &cssname)
Definition htmlgen.cpp:1416
void startConstraintType() override
Definition htmlgen.cpp:3277
void endConstraintParam() override
Definition htmlgen.cpp:3272
static QCString writeSplitBarAsString(const QCString &name, const QCString &relpath, const QCString &allMembersFile)
Definition htmlgen.cpp:2984
void startTitleHead(const QCString &) override
Definition htmlgen.cpp:3322
void startFile(const QCString &name, const QCString &manName, const QCString &title, int id, int hierarchyLevel) override
Definition htmlgen.cpp:1430
void endIndexValue(const QCString &, bool) override
Definition htmlgen.cpp:2201
void addCodeGen(OutputCodeList &list) override
Definition htmlgen.cpp:1136
void startConstraintDocs() override
Definition htmlgen.cpp:3287
void endMemberTemplateParams(const QCString &anchor, const QCString &inheritId) override
Definition htmlgen.cpp:2052
void endPlainFile() override
Definition htmlgen.h:335
void startIndexListItem() override
Definition htmlgen.cpp:1671
void endProjectNumber() override
Definition htmlgen.cpp:1562
void writeSummaryLink(const QCString &file, const QCString &anchor, const QCString &title, bool first) override
Definition htmlgen.cpp:3488
void endMemberDocPrefixItem() override
Definition htmlgen.cpp:2239
void endDescTableTitle() override
Definition htmlgen.cpp:2571
void addLabel(const QCString &, const QCString &) override
Definition htmlgen.cpp:1649
void startGroupHeader(const QCString &, int) override
Definition htmlgen.cpp:1777
void endInclDepGraph(DotInclDepGraph &g) override
Definition htmlgen.cpp:2421
void startParameterExtra() override
Definition htmlgen.cpp:2304
void startProjectNumber() override
Definition htmlgen.cpp:1557
void writeGraphicalHierarchy(DotGfxHierarchyTable &g) override
Definition htmlgen.cpp:2488
void startExamples() override
Definition htmlgen.cpp:2596
void docify(const QCString &text) override
Definition htmlgen.cpp:1845
bool m_emptySection
Definition htmlgen.h:347
void endInlineMemberDoc() override
Definition htmlgen.cpp:3399
void writeSplitBar(const QCString &name, const QCString &allMembersFile) override
Definition htmlgen.cpp:3019
void endCallGraph(DotCallGraph &g) override
Definition htmlgen.cpp:2457
void endConstraintType() override
Definition htmlgen.cpp:3282
void endMemberSubtitle() override
Definition htmlgen.cpp:2170
void endTitle()
Definition htmlgen.h:339
void startMemberDocPrefixItem() override
Definition htmlgen.cpp:2233
void startSection(const QCString &, const QCString &, SectionType) override
Definition htmlgen.cpp:1814
void endTocEntry(const SectionInfo *si) override
Definition htmlgen.cpp:3607
void endMemberItem(MemberItemType) override
Definition htmlgen.cpp:2039
void startMemberGroup() override
Definition htmlgen.cpp:2513
void endMemberDoc(bool) override
Definition htmlgen.cpp:2371
void endIndexItem(const QCString &ref, const QCString &file) override
Definition htmlgen.cpp:1711
void startMemberHeader(const QCString &, int) override
Definition htmlgen.cpp:2133
void endTitleHead(const QCString &, const QCString &) override
Definition htmlgen.cpp:3328
void endSection(const QCString &, SectionType) override
Definition htmlgen.cpp:1830
void startInlineHeader() override
Definition htmlgen.cpp:3339
void endInlineMemberName() override
Definition htmlgen.cpp:3387
void endMemberDocSimple(bool) override
Definition htmlgen.cpp:3363
void writeInheritedSectionTitle(const QCString &id, const QCString &ref, const QCString &file, const QCString &anchor, const QCString &title, const QCString &name) override
Definition htmlgen.cpp:3457
void endIndexListItem() override
Definition htmlgen.cpp:1676
static QCString getMathJaxMacros()
Definition htmlgen.cpp:3530
void startParameterList(bool) override
Definition htmlgen.cpp:2261
QCString m_lastTitle
Definition htmlgen.h:343
void startPlainFile(const QCString &name) override
Definition htmlgen.h:334
opaque representation of the abstract syntax tree (AST)
Definition docparser.h:49
static Index & instance()
Definition index.cpp:106
static LayoutDocManager & instance()
Returns a reference to this singleton.
Definition layout.cpp:1435
LayoutNavEntry * rootNavEntry() const
returns the (invisible) root of the navigation tree.
Definition layout.cpp:1446
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
Class representing a list of different code generators.
Definition outputlist.h:164
void add(OutputCodeIntfPtr &&p)
Definition outputlist.h:194
Abstract interface for output generators.
Definition outputgen.h:127
QCString dir() const
Definition outputgen.cpp:52
QCString m_dir
Definition outputgen.h:117
TextStream m_t
Definition outputgen.h:116
QCString fileName() const
Definition outputgen.cpp:57
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString & prepend(const char *s)
Definition qcstring.h:407
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
bool startsWith(const char *s) const
Definition qcstring.h:492
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
QCString lower() const
Definition qcstring.h:234
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:578
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:245
const std::string & str() const
Definition qcstring.h:537
QCString right(size_t len) const
Definition qcstring.h:219
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition qcstring.h:172
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159
QCString left(size_t len) const
Definition qcstring.h:214
Singleton for managing resources compiled into an executable.
Definition resourcemgr.h:37
static ResourceMgr & instance()
Returns the one and only instance of this class.
bool copyResource(const QCString &name, const QCString &targetDir) const
Copies a registered resource to a given target directory.
QCString getAsString(const QCString &name) const
Gets the resource data as a C string.
class that provide information about a section.
Definition section.h:57
QCString label() const
Definition section.h:68
SectionType type() const
Definition section.h:70
static constexpr int Section
Definition section.h:33
static constexpr int Subsection
Definition section.h:34
static constexpr int Subsubsection
Definition section.h:35
static constexpr int Page
Definition section.h:31
static constexpr int Paragraph
Definition section.h:36
static constexpr int Subsubparagraph
Definition section.h:38
static constexpr int Subparagraph
Definition section.h:37
Text streaming class that buffers data.
Definition textstream.h:36
bool empty() const
Returns true iff the buffer is empty.
Definition textstream.h:253
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:229
#define Config_getInt(name)
Definition config.h:34
#define Config_getList(name)
Definition config.h:38
#define Config_getEnumAsString(name)
Definition config.h:36
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
#define Config_getEnum(name)
Definition config.h:35
std::vector< std::string > StringVector
Definition containers.h:33
std::unordered_map< std::string, std::string > StringUnorderedMap
Definition containers.h:28
std::vector< bool > BoolVector
Definition containers.h:36
QCString dateToString(DateTimeType includeTime)
Returns the current date, when includeTime is set also the time is provided.
Definition datetime.cpp:63
static constexpr auto hex
#define DBG_HTML(x)
Definition htmlgen.cpp:62
static QCString replaceVariables(const QCString &input)
Definition htmlgen.cpp:667
static void fillColorStyleMap(const QCString &definitions, StringUnorderedMap &map)
Definition htmlgen.cpp:632
static QCString g_header
Definition htmlgen.cpp:64
static void startSectionContent(TextStream &t, int sectionCount)
Definition htmlgen.cpp:1940
static QCString g_header_file
Definition htmlgen.cpp:65
static void endQuickIndexList(TextStream &t)
Definition htmlgen.cpp:2641
static QCString g_mathjax_code
Definition htmlgen.cpp:68
static void writeServerSearchBox(TextStream &t, const QCString &relPath, bool highlightSearch)
Definition htmlgen.cpp:98
static void startQuickIndexList(TextStream &t, bool topLevel=TRUE)
Definition htmlgen.cpp:2621
static void startSectionSummary(TextStream &t, int sectionCount)
Definition htmlgen.cpp:1918
static void startQuickIndexItem(TextStream &t, const QCString &l, bool hl, bool, const QCString &relPath)
Definition htmlgen.cpp:2654
static void renderQuickLinksAsTabs(TextStream &t, const QCString &relPath, LayoutNavEntry *hlEntry, LayoutNavEntry::Kind kind, bool highlightParent, bool highlightSearch)
Definition htmlgen.cpp:2750
static QCString g_footer
Definition htmlgen.cpp:67
static const SelectionMarkerInfo htmlMarkerInfo
Definition htmlgen.cpp:72
static QCString getConvertLatexMacro()
Convert a set of LaTeX commands \‍(re)newcommand to a form readable by MathJax LaTeX syntax:
Definition htmlgen.cpp:149
static void writeDefaultQuickLinks(TextStream &t, HighlightedItem hli, const QCString &file, const QCString &relPath, bool extraTabs)
Definition htmlgen.cpp:2830
static QCString g_footer_file
Definition htmlgen.cpp:66
static void endSectionContent(TextStream &t)
Definition htmlgen.cpp:1956
static QCString getSearchBox(bool serverSide, QCString relPath, bool highlightSearch)
Definition htmlgen.cpp:309
static QCString g_latex_macro
Definition htmlgen.cpp:69
static void fillColorStyleMaps()
Definition htmlgen.cpp:653
static void endQuickIndexItem(TextStream &t, const QCString &l)
Definition htmlgen.cpp:2668
static StringUnorderedMap g_lightMap
Definition htmlgen.cpp:629
static void startSectionHeader(TextStream &t, const QCString &relPath, int sectionCount)
Definition htmlgen.cpp:1893
static QCString substituteHtmlKeywords(const QCString &file, const QCString &str, const QCString &title, const QCString &relPath, const QCString &navPath=QCString())
Definition htmlgen.cpp:323
static void writeDefaultStyleSheet(TextStream &t)
Definition htmlgen.cpp:1342
static void renderQuickLinksAsTree(TextStream &t, const QCString &relPath, LayoutNavEntry *root)
Definition htmlgen.cpp:2721
static bool quickLinkVisible(LayoutNavEntry::Kind kind)
Definition htmlgen.cpp:2675
static std::mutex g_indexLock
Definition htmlgen.cpp:1428
static StringUnorderedMap g_darkMap
Definition htmlgen.cpp:630
static void endSectionHeader(TextStream &t)
Definition htmlgen.cpp:1912
static void writeClientSearchBox(TextStream &t, const QCString &relPath)
Definition htmlgen.cpp:76
static void endSectionSummary(TextStream &t)
Definition htmlgen.cpp:1930
HighlightedItem
Definition index.h:59
@ AnnotatedExceptions
Definition index.h:76
@ InterfaceVisible
Definition index.h:89
@ InterfaceHierarchy
Definition index.h:66
@ AnnotatedInterfaces
Definition index.h:74
@ NamespaceMembers
Definition index.h:78
@ AnnotatedClasses
Definition index.h:73
@ AnnotatedStructs
Definition index.h:75
@ ExceptionVisible
Definition index.h:91
@ NamespaceVisible
Definition index.h:92
@ ExceptionHierarchy
Definition index.h:67
Translator * theTranslator
Definition language.cpp:71
#define warn(file, line, fmt,...)
Definition message.h:97
#define err(fmt,...)
Definition message.h:127
#define term(fmt,...)
Definition message.h:137
std::ofstream openOutputStream(const QCString &name, bool append=false)
Definition portable.cpp:665
OutputCodeDefer< HtmlCodeGenerator > HtmlCodeGeneratorDefer
Definition outputlist.h:101
Portable versions of functions that are platform dependent.
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:477
#define qsnprintf
Definition qcstring.h:49
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
#define ASSERT(x)
Definition qcstring.h:39
Web server based search engine.
Some helper functions for std::string.
bool literal_at(const char *data, const char(&str)[N])
returns TRUE iff data points to a substring that matches string literal str
Definition stringutil.h:98
Base class for the layout of a navigation item at the top of the HTML pages.
Definition layout.h:156
const LayoutNavEntryList & children() const
Definition layout.h:219
LayoutNavEntry * parent() const
Definition layout.h:212
LayoutNavEntry * find(LayoutNavEntry::Kind k, const QCString &file=QCString()) const
Definition layout.cpp:133
Kind
Definition layout.h:193
constexpr const char * codeSymbolType2Str(CodeSymbolType type)
Definition types.h:515
CodeSymbolType
Definition types.h:481
std::string convertUTF8ToLower(const std::string &input)
Converts the input string into a lower case version, also taking into account non-ASCII characters th...
Definition utf8.cpp:187
const char * writeUTF8Char(TextStream &t, const char *s)
Writes the UTF8 character pointed to by s to stream t and returns a pointer to the next character.
Definition utf8.cpp:197
Various UTF8 related helper functions.
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition util.cpp:6232
size_t updateColumnCount(const char *s, size_t col)
Definition util.cpp:7357
QCString convertToHtml(const QCString &s, bool keepEntities)
Definition util.cpp:4479
void checkBlocks(const QCString &s, const QCString fileName, const SelectionMarkerInfo &markerInfo)
Definition util.cpp:6999
QCString correctURL(const QCString &url, const QCString &relPath)
Corrects URL url according to the relative path relPath.
Definition util.cpp:6404
QCString stripPath(const QCString &s)
Definition util.cpp:5464
QCString removeEmptyLines(const QCString &s)
Definition util.cpp:7063
QCString selectBlocks(const QCString &s, const SelectionBlockList &blockList, const SelectionMarkerInfo &markerInfo)
remove disabled blocks and all block markers from s and return the result as a string
Definition util.cpp:6886
QCString substituteKeywords(const QCString &file, const QCString &s, const KeywordSubstitutionList &keywords)
Definition util.cpp:3571
QCString relativePathToRoot(const QCString &name)
Definition util.cpp:4095
void clearSubDirs(const Dir &d)
Definition util.cpp:4183
QCString fileToString(const QCString &name, bool filter, bool isSourceCode)
Definition util.cpp:1441
QCString filterTitle(const QCString &title)
Definition util.cpp:6093
void createSubDirs(const Dir &d)
Definition util.cpp:4156
QCString getProjectId()
Definition util.cpp:7288
QCString externalLinkTarget(const bool parent)
Definition util.cpp:6188
QCString replaceColorMarkers(const QCString &str)
Replaces any markers of the form ##AA in input string str by new markers of the form #AABBCC,...
Definition util.cpp:6285
QCString convertToId(const QCString &s)
Definition util.cpp:4388
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:5415
QCString createHtmlUrl(const QCString &relPath, const QCString &ref, bool href, bool isLocalFile, const QCString &targetFileName, const QCString &anchor)
Definition util.cpp:6199
A bunch of utility functions.
QCString fixSpaces(const QCString &s)
Definition util.h:471