summaryrefslogtreecommitdiffstats
path: root/src/htmlhelp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/htmlhelp.cpp')
-rw-r--r--src/htmlhelp.cpp381
1 files changed, 381 insertions, 0 deletions
diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp
new file mode 100644
index 0000000..b1aed98
--- /dev/null
+++ b/src/htmlhelp.cpp
@@ -0,0 +1,381 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ * The code is this file is largely based on a contribution from
+ * Harm van der Heijden <H.v.d.Heijden@phys.tue.nl>
+ * Please send thanks to him and bug reports to me :-)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <qlist.h>
+#include <qdict.h>
+
+#include "htmlhelp.h"
+#include "config.h"
+#include "message.h"
+
+//----------------------------------------------------------------------------
+
+struct IndexField
+{
+ QCString name;
+ QCString url;
+ QCString anchor;
+ bool link;
+};
+
+class IndexFieldList : public QList<IndexField>
+{
+ public:
+ int compareItems(GCI item1, GCI item2)
+ {
+ return stricmp(((IndexField *)item1)->name,((IndexField *)item2)->name);
+ }
+};
+
+class IndexFieldListIterator : public QListIterator<IndexField>
+{
+ public:
+ IndexFieldListIterator( const IndexFieldList &list) :
+ QListIterator<IndexField>(list) {}
+};
+
+class IndexFieldDict : public QDict<IndexField>
+{
+ public:
+ IndexFieldDict(int size) : QDict<IndexField>(size) {}
+};
+
+/*! A helper class for HtmlHelp that manages a two level index in
+ * alphabetical order
+ */
+class HtmlHelpIndex
+{
+ public:
+ HtmlHelpIndex();
+ ~HtmlHelpIndex();
+ void addItem(const char *first,const char *second,
+ const char *url, const char *anchor,bool hasLink);
+ void writeFields(QTextStream &t);
+ private:
+ IndexFieldList *list;
+ IndexFieldDict *dict;
+};
+
+/*! Constructs a new HtmlHelp index */
+HtmlHelpIndex::HtmlHelpIndex()
+{
+ list = new IndexFieldList;
+ dict = new IndexFieldDict(10007);
+ list->setAutoDelete(TRUE);
+}
+
+/*! Destroys the HtmlHelp index */
+HtmlHelpIndex::~HtmlHelpIndex()
+{
+ delete list;
+ delete dict;
+}
+
+/*! Stores an item in the index if it is not already present.
+ * Items are stored in alphetical order, by sorting on the
+ * concatenation of \a level1 and \a level2 (if present).
+ *
+ * \param level1 the string at level 1 in the index.
+ * \param level2 the string at level 2 in the index (or 0 if not applicable).
+ * \param url the url of the documentation (without .html extension).
+ * \param anchor the anchor of the documentation within the page.
+ * \param hasLink if true, the url (without anchor) can be used in the
+ * level1 item, when writing the header of a list of level2 items.
+ */
+void HtmlHelpIndex::addItem(const char *level1,const char *level2,
+ const char *url,const char *anchor,bool hasLink)
+{
+ QCString key = level1;
+ if (level2) key+= (QCString)"?" + level2;
+ if (dict->find(key)==0) // new key
+ {
+ //printf(">>>>>>>>> HtmlHelpIndex::addItem(%s,%s,%s,%s)\n",
+ // level1,level2,url,anchor);
+ IndexField *f = new IndexField;
+ f->name = key;
+ f->url = url;
+ f->anchor = anchor;
+ f->link = hasLink;
+ list->inSort(f);
+ dict->insert(key,f);
+ }
+}
+
+/*! Writes the sorted list of index items into a html like list.
+ *
+ * An list of calls with <code>name = level1,level2</code> as follows:
+ * <pre>
+ * a1,b1
+ * a1,b2
+ * a2,b1
+ * a2,b2
+ * a3
+ * a4,b1
+ * </pre>
+ *
+ * Will result in the following list:
+ *
+ * <pre>
+ * a1 -> link to url if hasLink==TRUE
+ * b1 -> link to url#anchor
+ * b2 -> link to url#anchor
+ * a2 -> link to url if hasLink==TRUE
+ * b1 -> link to url#anchor
+ * b2 -> link to url#anchor
+ * a3 -> link to url if hasLink==TRUE
+ * a4 -> link to url if hasLink==TRUE
+ * b1 -> link to url#anchor
+ * </pre>
+ */
+void HtmlHelpIndex::writeFields(QTextStream &t)
+{
+ IndexFieldListIterator ifli(*list);
+ IndexField *f;
+ QCString lastLevel1;
+ bool level2Started=FALSE;
+ for (;(f=ifli.current());++ifli)
+ {
+ QCString level1,level2;
+ int i;
+ if ((i=f->name.find('?'))!=-1)
+ {
+ level1 = f->name.left(i);
+ level2 = f->name.right(f->name.length()-i-1);
+ }
+ else
+ {
+ level1 = f->name.copy();
+ }
+
+ if (level1!=lastLevel1)
+ { // finish old list at level 2
+ if (level2Started) t << " </UL>" << endl;
+ level2Started=FALSE;
+
+ if (level2.isEmpty())
+ {
+ t << " <LI><OBJECT type=\"text/sitemap\">";
+ t << "<param name=\"Local\" value=\"" << f->url << ".html";
+ if (!f->anchor.isEmpty()) t << "#" << f->anchor;
+ t << "\">";
+ t << "<param name=\"Name\" value=\"" << level1 << "\">"
+ "</OBJECT>\n";
+ }
+ else
+ {
+ if (f->link)
+ {
+ t << " <LI><OBJECT type=\"text/sitemap\">";
+ t << "<param name=\"Local\" value=\"" << f->url << ".html\">";
+ t << "<param name=\"Name\" value=\"" << level1 << "\">"
+ "</OBJECT>\n";
+ }
+ else
+ {
+ t << " <LI><OBJECT type=\"text/sitemap\">";
+ t << "<param name=\"See Also\" value=\"" << level1 << "\">";
+ t << "<param name=\"Name\" value=\"" << level1 << "\">"
+ "</OBJECT>\n";
+ }
+ }
+ }
+ if (!level2Started && !level2.isEmpty())
+ { // start new list at level 2
+ t << " <UL>" << endl;
+ level2Started=TRUE;
+ }
+ else if (level2Started && level2.isEmpty())
+ { // end list at level 2
+ t << " </UL>" << endl;
+ level2Started=FALSE;
+ }
+ if (level2Started)
+ {
+ t << " <LI><OBJECT type=\"text/sitemap\">";
+ t << "<param name=\"Local\" value=\"" << f->url << ".html";
+ if (!f->anchor.isEmpty()) t << "#" << f->anchor;
+ t << "\">";
+ t << "<param name=\"Name\" value=\"" << level2 << "\">"
+ "</OBJECT>\n";
+ }
+ lastLevel1 = level1.copy();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+HtmlHelp *HtmlHelp::theInstance = 0;
+
+/*! Constructs an html object.
+ * The object has to be \link initialize() initialized\endlink before it can
+ * be used.
+ */
+HtmlHelp::HtmlHelp()
+{
+ /* initial depth */
+ dc = 0;
+ cf = kf = 0;
+ index = new HtmlHelpIndex;
+}
+
+/*! return a reference to the one and only instance of this class.
+ */
+HtmlHelp *HtmlHelp::getInstance()
+{
+ if (theInstance==0) theInstance = new HtmlHelp;
+ return theInstance;
+}
+
+/*! This will create a contents file (index.hhc) and a index file (index.hhk)
+ * and write the header of those files.
+ * It also creates a project file (index.hhp)
+ * \sa finalize()
+ */
+void HtmlHelp::initialize()
+{
+ /* open the contents file */
+ QCString fName = Config::htmlOutputDir + "/index.hhc";
+ cf = new QFile(fName);
+ if (!cf->open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",fName.data());
+ exit(1);
+ }
+ /* Write the header of the contents file */
+ cts.setDevice(cf);
+ cts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n"
+ "<HTML><HEAD></HEAD><BODY>\n"
+ "<OBJECT type=\"text/site properties\">\n"
+ "<param name=\"ImageType\" value=\"Folder\">\n"
+ "</OBJECT>\n"
+ "<UL>\n";
+
+ /* open the contents file */
+ fName = Config::htmlOutputDir + "/index.hhk";
+ kf = new QFile(fName);
+ if (!kf->open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",fName.data());
+ exit(1);
+ }
+ /* Write the header of the contents file */
+ kts.setDevice(kf);
+ kts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n"
+ "<HTML><HEAD></HEAD><BODY>\n"
+ "<OBJECT type=\"text/site properties\">\n"
+ "<param name=\"ImageType\" value=\"Folder\">\n"
+ "</OBJECT>\n"
+ "<UL>\n";
+
+ /* Write the project file */
+ fName = Config::htmlOutputDir + "/index.hhp";
+ QFile f(fName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "[OPTIONS]\n"
+ "Compatibility=1.1\n"
+ "Full-text search=Yes\n"
+ "Contents file=index.hhc\n"
+ "Default Window=indexHelp\n"
+ "Default topic=index.html\n"
+ "Index file=index.hhk\n"
+ "Title=" << Config::projectName << endl << endl
+ << "[FILES]\n"
+ "index.html";
+ f.close();
+ }
+ else
+ {
+ err("Could not open file %s for writing\n",fName.data());
+ }
+}
+
+/*! Finalizes the HTML help. This will finish and close the
+ * contents file (index.hhc) and the index file (index.hhk).
+ * \sa initialize()
+ */
+void HtmlHelp::finalize()
+{
+ // end the contents file
+ cts << "</UL>\n";
+ cts.unsetDevice();
+ cf->close();
+ delete cf;
+
+ index->writeFields(kts);
+
+ // end the index file
+ kts << "</UL>\n";
+ kts.unsetDevice();
+ kf->close();
+ delete kf;
+}
+
+/*! Increase the level of the contents hierarchy.
+ * This will start a new unnumbered HTML list in contents file.
+ * \sa decContentsDepth()
+ */
+int HtmlHelp::incContentsDepth()
+{
+ int i; for (i=0;i<dc+1;i++) cts << " ";
+ cts << "<UL>\n";
+ return ++dc;
+}
+
+/*! Decrease the level of the contents hierarchy.
+ * This will end the unnumber HTML list.
+ * \sa incContentsDepth()
+ */
+int HtmlHelp::decContentsDepth()
+{
+ int i; for (i=0;i<dc;i++) cts << " ";
+ cts << "</UL>\n";
+ return --dc;
+}
+
+/*! Add an list item to the contents file.
+ * \param name the name of the item.
+ * \param ref the URL of to the item.
+ */
+void HtmlHelp::addContentsItem(const char *name,const char *ref,
+ const char *anchor)
+{
+ int i; for (i=0;i<dc;i++) cts << " ";
+ cts << "<LI><OBJECT type=\"text/sitemap\">";
+ cts << "<param name=\"Local\" value=\"" << ref << ".html";
+ if (anchor) cts << "#" << anchor;
+ cts << "\">";
+ cts << "<param name=\"Name\" value=\"" << name << "\">"
+ "</OBJECT>\n";
+}
+
+/*! Add an list item to the index file.
+ * \param name the name of the item.
+ * \param ref the URL of to the item.
+ * \sa HtmlHelpIndex
+ */
+void HtmlHelp::addIndexItem(const char *level1, const char *level2,
+ const char *ref, const char *anchor)
+{
+ index->addItem(level1,level2,ref,anchor,TRUE);
+ index->addItem(level2,level1,ref,anchor,FALSE);
+}