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