Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/util/doxygen/src/htmlhelp.cpp

Source at commit 1322 created 9 years 5 months ago.
By meklort, Add doxygen to utils folder
1/******************************************************************************
2 *
3 *
4 *
5 * Copyright (C) 1997-2011 by Dimitri van Heesch.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
12 *
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
15 *
16 * The code is this file is largely based on a contribution from
17 * Harm van der Heijden <H.v.d.Heijden@phys.tue.nl>
18 * Please send thanks to him and bug reports to me :-)
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <qlist.h>
24#include <qdict.h>
25#include <qregexp.h>
26#include "qtextcodec.h"
27#include "sortdict.h"
28
29#include "htmlhelp.h"
30#include "config.h"
31#include "message.h"
32#include "doxygen.h"
33#include "language.h"
34#include "portable.h"
35
36//----------------------------------------------------------------------------
37
38struct IndexField
39{
40 QCString name;
41 QCString url;
42 QCString anchor;
43 bool link;
44 bool reversed;
45};
46
47class IndexFieldSDict : public SDict<IndexField>
48{
49 public:
50 IndexFieldSDict() : SDict<IndexField>(17) {}
51 ~IndexFieldSDict() {}
52 int compareItems(GCI item1, GCI item2)
53 {
54 return stricmp(((IndexField *)item1)->name,((IndexField *)item2)->name);
55 }
56};
57
58/*! A helper class for HtmlHelp that manages a two level index in
59 * alphabetical order
60 */
61class HtmlHelpIndex
62{
63 public:
64 HtmlHelpIndex();
65 ~HtmlHelpIndex();
66 void addItem(const char *first,const char *second,
67 const char *url, const char *anchor,
68 bool hasLink,bool reversed);
69 void writeFields(FTextStream &t);
70 private:
71 IndexFieldSDict *dict;
72};
73
74/*! Constructs a new HtmlHelp index */
75HtmlHelpIndex::HtmlHelpIndex()
76{
77 dict = new IndexFieldSDict;
78 dict->setAutoDelete(TRUE);
79}
80
81/*! Destroys the HtmlHelp index */
82HtmlHelpIndex::~HtmlHelpIndex()
83{
84 delete dict;
85}
86
87/*! Stores an item in the index if it is not already present.
88 * Items are stored in alphetical order, by sorting on the
89 * concatenation of \a level1 and \a level2 (if present).
90 *
91 * \param level1 the string at level 1 in the index.
92 * \param level2 the string at level 2 in the index (or 0 if not applicable).
93 * \param url the url of the documentation (without .html extension).
94 * \param anchor the anchor of the documentation within the page.
95 * \param hasLink if true, the url (without anchor) can be used in the
96 * level1 item, when writing the header of a list of level2 items.
97 * \param reversed TRUE if level1 is the member name and level2 the compound
98 * name.
99 */
100void HtmlHelpIndex::addItem(const char *level1,const char *level2,
101 const char *url,const char *anchor,bool hasLink,
102 bool reversed)
103{
104 QCString key = level1;
105 if (level2) key+= (QCString)"?" + level2;
106 if (key.find(QRegExp("@[0-9]+"))!=-1) // skip anonymous stuff
107 {
108 return;
109 }
110 if (dict->find(key)==0) // new key
111 {
112 //printf(">>>>>>>>> HtmlHelpIndex::addItem(%s,%s,%s,%s)\n",
113 // level1,level2,url,anchor);
114 IndexField *f = new IndexField;
115 f->name = key;
116 f->url = url;
117 f->anchor = anchor;
118 f->link = hasLink;
119 f->reversed = reversed;
120 dict->append(key,f);
121 }
122}
123
124/*! Writes the sorted list of index items into a html like list.
125 *
126 * An list of calls with <code>name = level1,level2</code> as follows:
127 * <pre>
128 * a1,b1
129 * a1,b2
130 * a2,b1
131 * a2,b2
132 * a3
133 * a4,b1
134 * </pre>
135 *
136 * Will result in the following list:
137 *
138 * <pre>
139 * a1 -> link to url if hasLink==TRUE
140 * b1 -> link to url#anchor
141 * b2 -> link to url#anchor
142 * a2 -> link to url if hasLink==TRUE
143 * b1 -> link to url#anchor
144 * b2 -> link to url#anchor
145 * a3 -> link to url if hasLink==TRUE
146 * a4 -> link to url if hasLink==TRUE
147 * b1 -> link to url#anchor
148 * </pre>
149 */
150void HtmlHelpIndex::writeFields(FTextStream &t)
151{
152 dict->sort();
153 IndexFieldSDict::Iterator ifli(*dict);
154 IndexField *f;
155 QCString lastLevel1;
156 bool level2Started=FALSE;
157 for (;(f=ifli.current());++ifli)
158 {
159 QCString level1,level2;
160 int i;
161 if ((i=f->name.find('?'))!=-1)
162 {
163 level1 = f->name.left(i);
164 level2 = f->name.right(f->name.length()-i-1);
165 }
166 else
167 {
168 level1 = f->name.copy();
169 }
170
171 if (level1!=lastLevel1)
172 { // finish old list at level 2
173 if (level2Started) t << " </UL>" << endl;
174 level2Started=FALSE;
175
176 // <Antony>
177 // Added this code so that an item with only one subitem is written
178 // without any subitem.
179 // For example:
180 // a1, b1 -> will create only a1, not separate subitem for b1
181 // a2, b2
182 // a2, b3
183 QCString nextLevel1;
184 IndexField* fnext = ++ifli;
185 if (fnext)
186 {
187 nextLevel1 = fnext->name.left(fnext->name.find('?'));
188 --ifli;
189 }
190 if (level1 != nextLevel1)
191 {
192 level2 = "";
193 }
194 // </Antony>
195
196 if (level2.isEmpty())
197 {
198 t << " <LI><OBJECT type=\"text/sitemap\">";
199 t << "<param name=\"Local\" value=\"" << f->url << Doxygen::htmlFileExtension;
200 if (!f->anchor.isEmpty() && f->reversed) t << "#" << f->anchor;
201 t << "\">";
202 t << "<param name=\"Name\" value=\"" << level1 << "\">"
203 "</OBJECT>\n";
204 }
205 else
206 {
207 if (f->link)
208 {
209 t << " <LI><OBJECT type=\"text/sitemap\">";
210 t << "<param name=\"Local\" value=\"" << f->url << Doxygen::htmlFileExtension;
211 if (!f->anchor.isEmpty() && f->reversed) t << "#" << f->anchor;
212 t << "\">";
213 t << "<param name=\"Name\" value=\"" << level1 << "\">"
214 "</OBJECT>\n";
215 }
216 else
217 {
218 t << " <LI><OBJECT type=\"text/sitemap\">";
219 t << "<param name=\"See Also\" value=\"" << level1 << "\">";
220 t << "<param name=\"Name\" value=\"" << level1 << "\">"
221 "</OBJECT>\n";
222 }
223 }
224 }
225 if (!level2Started && !level2.isEmpty())
226 { // start new list at level 2
227 t << " <UL>" << endl;
228 level2Started=TRUE;
229 }
230 else if (level2Started && level2.isEmpty())
231 { // end list at level 2
232 t << " </UL>" << endl;
233 level2Started=FALSE;
234 }
235 if (level2Started)
236 {
237 t << " <LI><OBJECT type=\"text/sitemap\">";
238 t << "<param name=\"Local\" value=\"" << f->url << Doxygen::htmlFileExtension;
239 if (!f->anchor.isEmpty()) t << "#" << f->anchor;
240 t << "\">";
241 t << "<param name=\"Name\" value=\"" << level2 << "\">"
242 "</OBJECT>\n";
243 }
244 lastLevel1 = level1.copy();
245 }
246 if (level2Started) t << " </UL>" << endl;
247}
248
249//----------------------------------------------------------------------------
250
251HtmlHelp *HtmlHelp::theInstance = 0;
252
253/*! Constructs an html object.
254 * The object has to be \link initialize() initialized\endlink before it can
255 * be used.
256 */
257HtmlHelp::HtmlHelp() : indexFileDict(1009)
258{
259 /* initial depth */
260 dc = 0;
261 cf = kf = 0;
262 index = new HtmlHelpIndex;
263 m_fromUtf8 = (void *)(-1);
264}
265
266HtmlHelp::~HtmlHelp()
267{
268 if (m_fromUtf8!=(void *)(-1)) portable_iconv_close(m_fromUtf8);
269}
270#if 0
271/*! return a reference to the one and only instance of this class.
272 */
273HtmlHelp *HtmlHelp::getInstance()
274{
275 if (theInstance==0) theInstance = new HtmlHelp;
276 return theInstance;
277}
278#endif
279
280static QDict<QCString> s_languageDict;
281
282/*! This will create a contents file (index.hhc) and a index file (index.hhk)
283 * and write the header of those files.
284 * It also creates a project file (index.hhp)
285 * \sa finalize()
286 */
287void HtmlHelp::initialize()
288{
289 const char *str = Config_getString("CHM_INDEX_ENCODING");
290 if (!str) str = "CP1250"; // use safe and likely default
291 m_fromUtf8 = portable_iconv_open(str,"UTF-8");
292 if (m_fromUtf8==(void *)(-1))
293 {
294 err("Error: unsupported character conversion for CHM_INDEX_ENCODING: '%s'->'UTF-8'\n", str);
295 exit(1);
296 }
297
298 /* open the contents file */
299 QCString fName = Config_getString("HTML_OUTPUT") + "/index.hhc";
300 cf = new QFile(fName);
301 if (!cf->open(IO_WriteOnly))
302 {
303 err("Could not open file %s for writing\n",fName.data());
304 exit(1);
305 }
306 /* Write the header of the contents file */
307 cts.setDevice(cf);
308 cts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n"
309 "<HTML><HEAD></HEAD><BODY>\n"
310 "<OBJECT type=\"text/site properties\">\n"
311 "<param name=\"FrameName\" value=\"right\">\n"
312 "</OBJECT>\n"
313 "<UL>\n";
314
315 /* open the contents file */
316 fName = Config_getString("HTML_OUTPUT") + "/index.hhk";
317 kf = new QFile(fName);
318 if (!kf->open(IO_WriteOnly))
319 {
320 err("Could not open file %s for writing\n",fName.data());
321 exit(1);
322 }
323 /* Write the header of the contents file */
324 kts.setDevice(kf);
325 kts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n"
326 "<HTML><HEAD></HEAD><BODY>\n"
327 "<OBJECT type=\"text/site properties\">\n"
328 "<param name=\"FrameName\" value=\"right\">\n"
329 "</OBJECT>\n"
330 "<UL>\n";
331
332 /* language codes for Html help
333 0x405 Czech
334 0x406 Danish
335 0x413 Dutch
336 0xC09 English (Australia)
337 0x809 English (Britain)
338 0x1009 English (Canada)
339 0x1809 English (Ireland)
340 0x1409 English (New Zealand)
341 0x1C09 English (South Africa)
342 0x409 English (United States)
343 0x40B Finnish
344 0x40C French
345 0x407 German
346 0x408 Greece
347 0x40E Hungarian
348 0x410 Italian
349 0x814 Norwegian
350 0x415 Polish
351 0x816 Portuguese(Portugal)
352 0x416 Portuguese(Brazil)
353 0x419 Russian
354 0x80A Spanish(Mexico)
355 0xC0A Spanish(Modern Sort)
356 0x40A Spanish(Traditional Sort)
357 0x41D Swedish
358 0x41F Turkey
359 0x411 Japanese
360 0x412 Korean
361 0x804 Chinese (PRC)
362 0x404 Chinese (Taiwan)
363
364 New LCIDs:
365 0x421 Indonesian
366 0x41A Croatian
367 0x418 Romanian
368 0x424 Slovenian
369 0x41B Slovak
370 0x422 Ukrainian
371 0x81A Serbian (Serbia, Latin)
372 0x403 Catalan
373 0x427 Lithuanian
374 0x436 Afrikaans
375 0x42A Vietnamese
376 0x429 Persian (Iran)
377 0xC01 Arabic (Egypt) - I don't know which version of arabic is used inside translator_ar.h ,
378 so I have chosen Egypt at random
379
380 */
381 s_languageDict.setAutoDelete(TRUE);
382 s_languageDict.clear();
383 s_languageDict.insert("czech", new QCString("0x405 Czech"));
384 s_languageDict.insert("danish", new QCString("0x406 Danish"));
385 s_languageDict.insert("dutch", new QCString("0x413 Dutch"));
386 s_languageDict.insert("finnish", new QCString("0x40B Finnish"));
387 s_languageDict.insert("french", new QCString("0x40C French"));
388 s_languageDict.insert("german", new QCString("0x407 German"));
389 s_languageDict.insert("greek", new QCString("0x408 Greece"));
390 s_languageDict.insert("hungarian", new QCString("0x40E Hungarian"));
391 s_languageDict.insert("italian", new QCString("0x410 Italian"));
392 s_languageDict.insert("norwegian", new QCString("0x814 Norwegian"));
393 s_languageDict.insert("polish", new QCString("0x415 Polish"));
394 s_languageDict.insert("portuguese", new QCString("0x816 Portuguese(Portugal)"));
395 s_languageDict.insert("brazil", new QCString("0x416 Portuguese(Brazil)"));
396 s_languageDict.insert("russian", new QCString("0x419 Russian"));
397 s_languageDict.insert("spanish", new QCString("0x40A Spanish(Traditional Sort)"));
398 s_languageDict.insert("swedish", new QCString("0x41D Swedish"));
399 s_languageDict.insert("turkish", new QCString("0x41F Turkey"));
400 s_languageDict.insert("japanese", new QCString("0x411 Japanese"));
401 s_languageDict.insert("japanese-en", new QCString("0x411 Japanese"));
402 s_languageDict.insert("korean", new QCString("0x412 Korean"));
403 s_languageDict.insert("korean-en", new QCString("0x412 Korean"));
404 s_languageDict.insert("chinese", new QCString("0x804 Chinese (PRC)"));
405 s_languageDict.insert("chinese-traditional", new QCString("0x404 Chinese (Taiwan)"));
406
407 // new LCIDs
408 s_languageDict.insert("indonesian", new QCString("0x412 Indonesian"));
409 s_languageDict.insert("croatian", new QCString("0x41A Croatian"));
410 s_languageDict.insert("romanian", new QCString("0x418 Romanian"));
411 s_languageDict.insert("slovene", new QCString("0x424 Slovenian"));
412 s_languageDict.insert("slovak", new QCString("0x41B Slovak"));
413 s_languageDict.insert("ukrainian", new QCString("0x422 Ukrainian"));
414 s_languageDict.insert("serbian", new QCString("0x81A Serbian (Serbia, Latin)"));
415 s_languageDict.insert("catalan", new QCString("0x403 Catalan"));
416 s_languageDict.insert("lithuanian", new QCString("0x427 Lithuanian"));
417 s_languageDict.insert("afrikaans", new QCString("0x436 Afrikaans"));
418 s_languageDict.insert("vietnamese", new QCString("0x42A Vietnamese"));
419 s_languageDict.insert("persian", new QCString("0x429 Persian (Iran)"));
420 s_languageDict.insert("arabic", new QCString("0xC01 Arabic (Egypt)"));
421}
422
423
424static QCString getLanguageString()
425{
426 if (!theTranslator->idLanguage().isEmpty())
427 {
428 QCString *s = s_languageDict[theTranslator->idLanguage()];
429 if (s)
430 {
431 return *s;
432 }
433 }
434 // default language
435 return "0x409 English (United States)";
436}
437
438
439
440void HtmlHelp::createProjectFile()
441{
442 /* Write the project file */
443 QCString fName = Config_getString("HTML_OUTPUT") + "/index.hhp";
444 QFile f(fName);
445 if (f.open(IO_WriteOnly))
446 {
447 FTextStream t(&f);
448
449 QCString indexName="index"+Doxygen::htmlFileExtension;
450 //if (Config_getBool("GENERATE_TREEVIEW")) indexName="main"+Doxygen::htmlFileExtension;
451 t << "[OPTIONS]\n";
452 if (!Config_getString("CHM_FILE").isEmpty())
453 {
454 t << "Compiled file=" << Config_getString("CHM_FILE") << "\n";
455 }
456 t << "Compatibility=1.1\n"
457 "Full-text search=Yes\n"
458 "Contents file=index.hhc\n"
459 "Default Window=main\n"
460 "Default topic=" << indexName << "\n"
461 "Index file=index.hhk\n"
462 "Language=" << getLanguageString() << endl;
463 if (Config_getBool("BINARY_TOC")) t << "Binary TOC=YES\n";
464 if (Config_getBool("GENERATE_CHI")) t << "Create CHI file=YES\n";
465 t << "Title=" << recode(Config_getString("PROJECT_NAME")) << endl << endl;
466
467 t << "[WINDOWS]" << endl;
468
469 // NOTE: the 0x10387e number is a set of bits specifying the buttons
470 // which should appear in the CHM viewer; that specific value
471 // means "show all buttons including the font-size one";
472 // the font-size one is not normally settable by the HTML Help Workshop
473 // utility but the way to set it is described here:
474 // http://support.microsoft.com/?scid=kb%3Ben-us%3B240062&x=17&y=18
475 t << "main=\"" << recode(Config_getString("PROJECT_NAME")) << "\",\"index.hhc\","
476 "\"index.hhk\",\"" << indexName << "\",\"" <<
477 indexName << "\",,,,,0x23520,,0x10387e,,,,,,,,0" << endl << endl;
478
479 t << "[FILES]" << endl;
480 char *s = indexFiles.first();
481 while (s)
482 {
483 t << s << endl;
484 s = indexFiles.next();
485 }
486#if 0
487 // items not found by the html help compiler scan.
488 t << "tabs.css" << endl;
489 t << "tab_a.png" << endl;
490 t << "tab_b.png" << endl;
491 t << "tab_h.png" << endl;
492 t << "tab_s.png" << endl;
493 t << "nav_h.png" << endl;
494 t << "nav_f.png" << endl;
495 t << "bc_s.png" << endl;
496 if (Config_getBool("HTML_DYNAMIC_SECTIONS"))
497 {
498 t << "open.png" << endl;
499 t << "closed.png" << endl;
500 }
501 if (Config_getBool("GENERATE_HTMLHELP"))
502 {
503 t << "ftv2blank.png" << endl;
504 t << "ftv2doc.png" << endl;
505 t << "ftv2folderclosed.png" << endl;
506 t << "ftv2folderopen.png" << endl;
507 t << "ftv2lastnode.png" << endl;
508 t << "ftv2link.png" << endl;
509 t << "ftv2mlastnode.png" << endl;
510 t << "ftv2mnode.png" << endl;
511 t << "ftv2node.png" << endl;
512 t << "ftv2plastnode.png" << endl;
513 t << "ftv2pnode.png" << endl;
514 t << "ftv2vertline.png" << endl;
515 }
516 if (Config_getBool("SEARCHENGINE"))
517 {
518 t << "search_l.png" << endl;
519 t << "search_m.png" << endl;
520 t << "search_r.png" << endl;
521 if (Config_getBool("SERVER_BASED_SEARCH"))
522 {
523 t << "mag.png" << endl;
524 }
525 else
526 {
527 t << "mag_sel.png" << endl;
528 t << "close.png" << endl;
529 }
530 }
531#endif
532 uint i;
533 for (i=0;i<imageFiles.count();i++)
534 {
535 t << imageFiles.at(i) << endl;
536 }
537 f.close();
538 }
539 else
540 {
541 err("Could not open file %s for writing\n",fName.data());
542 }
543}
544
545void HtmlHelp::addIndexFile(const char *s)
546{
547 if (indexFileDict.find(s)==0)
548 {
549 indexFiles.append(s);
550 indexFileDict.insert(s,(void *)0x8);
551 }
552}
553
554/*! Finalizes the HTML help. This will finish and close the
555 * contents file (index.hhc) and the index file (index.hhk).
556 * \sa initialize()
557 */
558void HtmlHelp::finalize()
559{
560 // end the contents file
561 cts << "</UL>\n";
562 cts << "</BODY>\n";
563 cts << "</HTML>\n";
564 cts.unsetDevice();
565 cf->close();
566 delete cf;
567
568 index->writeFields(kts);
569
570 // end the index file
571 kts << "</UL>\n";
572 kts << "</BODY>\n";
573 kts << "</HTML>\n";
574 kts.unsetDevice();
575 kf->close();
576 delete kf;
577
578 createProjectFile();
579 s_languageDict.clear();
580}
581
582/*! Increase the level of the contents hierarchy.
583 * This will start a new unnumbered HTML list in contents file.
584 * \sa decContentsDepth()
585 */
586void HtmlHelp::incContentsDepth()
587{
588 int i; for (i=0;i<dc+1;i++) cts << " ";
589 cts << "<UL>\n";
590 ++dc;
591}
592
593/*! Decrease the level of the contents hierarchy.
594 * This will end the unnumber HTML list.
595 * \sa incContentsDepth()
596 */
597void HtmlHelp::decContentsDepth()
598{
599 int i; for (i=0;i<dc;i++) cts << " ";
600 cts << "</UL>\n";
601 --dc;
602}
603
604QCString HtmlHelp::recode(const QCString &s)
605{
606 int iSize = s.length();
607 int oSize = iSize*4+1;
608 QCString output(oSize);
609 size_t iLeft = iSize;
610 size_t oLeft = oSize;
611 const char *iPtr = s.data();
612 char *oPtr = output.data();
613 if (!portable_iconv(m_fromUtf8,&iPtr,&iLeft,&oPtr,&oLeft))
614 {
615 oSize -= oLeft;
616 output.resize(oSize+1);
617 output.at(oSize)='\0';
618 return output;
619 }
620 else
621 {
622 return s;
623 }
624}
625
626/*! Add an list item to the contents file.
627 * \param isDir boolean indicating if this is a dir or file entry
628 * \param name the name of the item.
629 * \param ref the URL of to the item.
630 * \param file the file in which the item is defined.
631 * \param anchor the anchor of the item.
632 */
633void HtmlHelp::addContentsItem(bool isDir,
634 const char *name,
635 const char * /*ref*/,
636 const char *file,
637 const char *anchor)
638{
639 // If we're using a binary toc then folders cannot have links.
640 if(Config_getBool("BINARY_TOC") && isDir)
641 {
642 file = 0;
643 anchor = 0;
644 }
645 int i; for (i=0;i<dc;i++) cts << " ";
646 cts << "<LI><OBJECT type=\"text/sitemap\">";
647 cts << "<param name=\"Name\" value=\"" << recode(name) << "\">";
648 if (file) // made file optional param - KPW
649 {
650 cts << "<param name=\"Local\" value=\"" << file << Doxygen::htmlFileExtension;
651 if (anchor) cts << "#" << anchor;
652 cts << "\">";
653 }
654 cts << "<param name=\"ImageNumber\" value=\"";
655 if (isDir) // added - KPW
656 {
657 cts << (int)BOOK_CLOSED ;
658 }
659 else
660 {
661 cts << (int)TEXT;
662 }
663 cts << "\">";
664 cts << "</OBJECT>\n";
665}
666
667
668void HtmlHelp::addIndexItem(Definition *context,MemberDef *md,
669 const char *word)
670{
671 if (md)
672 {
673 static bool separateMemberPages = Config_getBool("SEPARATE_MEMBER_PAGES");
674 if (context==0) // global member
675 {
676 if (md->getGroupDef())
677 context = md->getGroupDef();
678 else if (md->getFileDef())
679 context = md->getFileDef();
680 }
681 if (context==0) return; // should not happen
682
683 QCString cfname = md->getOutputFileBase();
684 QCString cfiname = context->getOutputFileBase();
685 QCString level1 = context->name();
686 QCString level2 = md->name();
687 QCString contRef = separateMemberPages ? cfname : cfiname;
688 QCString memRef = cfname;
689 QCString anchor = md->anchor();
690 index->addItem(level1,level2,contRef,anchor,TRUE,FALSE);
691 index->addItem(level2,level1,memRef,anchor,TRUE,TRUE);
692 }
693 else if (context)
694 {
695 QCString level1 = word ? QCString(word) : context->name();
696 index->addItem(level1,0,context->getOutputFileBase(),0,TRUE,FALSE);
697 }
698}
699
700void HtmlHelp::addImageFile(const char *fileName)
701{
702 imageFiles.append(fileName);
703}
704
705

Archive Download this file

Revision: 1322