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