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