Blame src/htmlhelp.cpp

Packit 1c1d7e
/******************************************************************************
Packit 1c1d7e
 *
Packit 1c1d7e
 * 
Packit 1c1d7e
 *
Packit 1c1d7e
 * Copyright (C) 1997-2015 by Dimitri van Heesch.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Permission to use, copy, modify, and distribute this software and its
Packit 1c1d7e
 * documentation under the terms of the GNU General Public License is hereby 
Packit 1c1d7e
 * granted. No representations are made about the suitability of this software 
Packit 1c1d7e
 * for any purpose. It is provided "as is" without express or implied warranty.
Packit 1c1d7e
 * See the GNU General Public License for more details.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Documents produced by Doxygen are derivative works derived from the
Packit 1c1d7e
 * input used in their production; they are not affected by this license.
Packit 1c1d7e
 *
Packit 1c1d7e
 * The original version of this file is largely based on a contribution from
Packit 1c1d7e
 * Harm van der Heijden.
Packit 1c1d7e
 */
Packit 1c1d7e
Packit 1c1d7e
#include <stdio.h>
Packit 1c1d7e
#include <stdlib.h>
Packit 1c1d7e
#include <qlist.h>
Packit 1c1d7e
#include <qdict.h>
Packit 1c1d7e
#include <qregexp.h>
Packit 1c1d7e
#include <qfile.h>
Packit 1c1d7e
Packit 1c1d7e
#include "qtextcodec.h"
Packit 1c1d7e
#include "sortdict.h"
Packit 1c1d7e
#include "htmlhelp.h"
Packit 1c1d7e
#include "config.h"
Packit 1c1d7e
#include "message.h"
Packit 1c1d7e
#include "doxygen.h"
Packit 1c1d7e
#include "language.h"
Packit 1c1d7e
#include "portable.h"
Packit 1c1d7e
#include "groupdef.h"
Packit 1c1d7e
#include "memberdef.h"
Packit 1c1d7e
#include "filedef.h"
Packit 1c1d7e
#include "util.h"
Packit 1c1d7e
Packit 1c1d7e
//----------------------------------------------------------------------------
Packit 1c1d7e
Packit 1c1d7e
/** Class representing a field in the HTML help index. */
Packit 1c1d7e
struct IndexField
Packit 1c1d7e
{
Packit 1c1d7e
  QCString name;
Packit 1c1d7e
  QCString url;
Packit 1c1d7e
  QCString anchor;
Packit 1c1d7e
  bool     link;
Packit 1c1d7e
  bool     reversed;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
/** Sorted dictionary of IndexField objects. */
Packit 1c1d7e
class IndexFieldSDict : public SDict<IndexField>
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    IndexFieldSDict() : SDict<IndexField>(17) {}
Packit 1c1d7e
   ~IndexFieldSDict() {}
Packit 1c1d7e
 private:
Packit 1c1d7e
    int compareValues(const IndexField *item1, const IndexField *item2) const
Packit 1c1d7e
    {
Packit 1c1d7e
      return qstricmp(item1->name,item2->name);
Packit 1c1d7e
    }
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
/** A helper class for HtmlHelp that manages a two level index in 
Packit 1c1d7e
 *  alphabetical order.
Packit 1c1d7e
 */
Packit 1c1d7e
class HtmlHelpIndex
Packit 1c1d7e
{
Packit 1c1d7e
  public:
Packit 1c1d7e
    HtmlHelpIndex(HtmlHelp *help);
Packit 1c1d7e
   ~HtmlHelpIndex();
Packit 1c1d7e
    void addItem(const char *first,const char *second, 
Packit 1c1d7e
                 const char *url, const char *anchor,
Packit 1c1d7e
                 bool hasLink,bool reversed);
Packit 1c1d7e
    void writeFields(FTextStream &t);
Packit 1c1d7e
  private:
Packit 1c1d7e
    IndexFieldSDict *dict;   
Packit 1c1d7e
    HtmlHelp *m_help;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
/*! Constructs a new HtmlHelp index */
Packit 1c1d7e
HtmlHelpIndex::HtmlHelpIndex(HtmlHelp *help) : m_help(help)
Packit 1c1d7e
{
Packit 1c1d7e
  dict = new IndexFieldSDict;
Packit 1c1d7e
  dict->setAutoDelete(TRUE);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*! Destroys the HtmlHelp index */
Packit 1c1d7e
HtmlHelpIndex::~HtmlHelpIndex()
Packit 1c1d7e
{
Packit 1c1d7e
  delete dict;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*! Stores an item in the index if it is not already present. 
Packit 1c1d7e
 *  Items are stored in alphetical order, by sorting on the
Packit 1c1d7e
 *  concatenation of \a level1 and \a level2 (if present).
Packit 1c1d7e
 *
Packit 1c1d7e
 *  \param level1 the string at level 1 in the index.
Packit 1c1d7e
 *  \param level2 the string at level 2 in the index (or 0 if not applicable).
Packit 1c1d7e
 *  \param url the url of the documentation (without .html extension).
Packit 1c1d7e
 *  \param anchor the anchor of the documentation within the page.
Packit 1c1d7e
 *  \param hasLink if true, the url (without anchor) can be used in the 
Packit 1c1d7e
 *         level1 item, when writing the header of a list of level2 items.
Packit 1c1d7e
 *  \param reversed TRUE if level1 is the member name and level2 the compound
Packit 1c1d7e
 *         name.
Packit 1c1d7e
 */
Packit 1c1d7e
void HtmlHelpIndex::addItem(const char *level1,const char *level2,
Packit 1c1d7e
                       const char *url,const char *anchor,bool hasLink,
Packit 1c1d7e
                       bool reversed)
Packit 1c1d7e
{
Packit 1c1d7e
  QCString key = level1; 
Packit 1c1d7e
  if (level2) key+= (QCString)"?" + level2;
Packit 1c1d7e
  if (key.find(QRegExp("@[0-9]+"))!=-1) // skip anonymous stuff
Packit 1c1d7e
  {
Packit 1c1d7e
    return;
Packit 1c1d7e
  }
Packit 1c1d7e
  if (dict->find(key)==0) // new key
Packit 1c1d7e
  {
Packit 1c1d7e
    //printf(">>>>>>>>> HtmlHelpIndex::addItem(%s,%s,%s,%s)\n",
Packit 1c1d7e
    //      level1,level2,url,anchor);
Packit 1c1d7e
    IndexField *f = new IndexField;
Packit 1c1d7e
    f->name     = key;
Packit 1c1d7e
    f->url      = url;
Packit 1c1d7e
    f->anchor   = anchor;
Packit 1c1d7e
    f->link     = hasLink;
Packit 1c1d7e
    f->reversed = reversed;
Packit 1c1d7e
    dict->append(key,f);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static QCString field2URL(const IndexField *f,bool checkReversed)
Packit 1c1d7e
{
Packit 1c1d7e
  QCString result = f->url + Doxygen::htmlFileExtension;
Packit 1c1d7e
  if (!f->anchor.isEmpty() && (!checkReversed || f->reversed)) 
Packit 1c1d7e
  {
Packit 1c1d7e
    // HTML Help needs colons in link anchors to be escaped in the .hhk file.
Packit 1c1d7e
    result+="#"+substitute(f->anchor,":","%3A");
Packit 1c1d7e
  }
Packit 1c1d7e
  return result;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*! Writes the sorted list of index items into a html like list.
Packit 1c1d7e
 *
Packit 1c1d7e
 *  An list of calls with name = level1,level2 as follows:
Packit 1c1d7e
 *  
Packit 1c1d7e
 *    a1,b1
Packit 1c1d7e
 *    a1,b2
Packit 1c1d7e
 *    a2,b1
Packit 1c1d7e
 *    a2,b2
Packit 1c1d7e
 *    a3
Packit 1c1d7e
 *    a4,b1
Packit 1c1d7e
 *  
Packit 1c1d7e
 *
Packit 1c1d7e
 *  Will result in the following list:
Packit 1c1d7e
 *
Packit 1c1d7e
 *  
Packit 1c1d7e
 *    a1       -> link to url if hasLink==TRUE
Packit 1c1d7e
 *      b1     -> link to url#anchor
Packit 1c1d7e
 *      b2     -> link to url#anchor
Packit 1c1d7e
 *    a2       -> link to url if hasLink==TRUE
Packit 1c1d7e
 *      b1     -> link to url#anchor
Packit 1c1d7e
 *      b2     -> link to url#anchor
Packit 1c1d7e
 *    a3       -> link to url if hasLink==TRUE
Packit 1c1d7e
 *    a4       -> link to url if hasLink==TRUE
Packit 1c1d7e
 *      b1     -> link to url#anchor 
Packit 1c1d7e
 *  
Packit 1c1d7e
 */
Packit 1c1d7e
void HtmlHelpIndex::writeFields(FTextStream &t)
Packit 1c1d7e
{
Packit 1c1d7e
  dict->sort();
Packit 1c1d7e
  IndexFieldSDict::Iterator ifli(*dict);
Packit 1c1d7e
  IndexField *f;
Packit 1c1d7e
  QCString lastLevel1;
Packit 1c1d7e
  bool level2Started=FALSE;
Packit 1c1d7e
  for (;(f=ifli.current());++ifli)
Packit 1c1d7e
  {
Packit 1c1d7e
    QCString level1,level2;
Packit 1c1d7e
    int i;
Packit 1c1d7e
    if ((i=f->name.find('?'))!=-1)
Packit 1c1d7e
    {
Packit 1c1d7e
      level1 = f->name.left(i);
Packit 1c1d7e
      level2 = f->name.right(f->name.length()-i-1); 
Packit 1c1d7e
    }
Packit 1c1d7e
    else
Packit 1c1d7e
    {
Packit 1c1d7e
      level1  = f->name.copy();
Packit 1c1d7e
    }
Packit 1c1d7e
Packit 1c1d7e
    if (level1!=lastLevel1)
Packit 1c1d7e
    { // finish old list at level 2
Packit 1c1d7e
      if (level2Started) t << "  " << endl;
Packit 1c1d7e
      level2Started=FALSE;
Packit 1c1d7e
Packit 1c1d7e
      // <Antony>
Packit 1c1d7e
      // Added this code so that an item with only one subitem is written
Packit 1c1d7e
      // without any subitem.
Packit 1c1d7e
      // For example:
Packit 1c1d7e
      //   a1, b1 -> will create only a1, not separate subitem for b1
Packit 1c1d7e
      //   a2, b2
Packit 1c1d7e
      //   a2, b3
Packit 1c1d7e
      QCString nextLevel1;
Packit 1c1d7e
      IndexField* fnext = ++ifli;
Packit 1c1d7e
      if (fnext)
Packit 1c1d7e
      {
Packit 1c1d7e
        nextLevel1 = fnext->name.left(fnext->name.find('?'));
Packit 1c1d7e
        --ifli;
Packit 1c1d7e
      }
Packit 1c1d7e
      if (level1 != nextLevel1)
Packit 1c1d7e
      {
Packit 1c1d7e
        level2 = "";
Packit 1c1d7e
      }
Packit 1c1d7e
      // </Antony>
Packit 1c1d7e
Packit 1c1d7e
      if (level2.isEmpty())
Packit 1c1d7e
      {
Packit 1c1d7e
        t << "  
  • <OBJECT type=\"text/sitemap\">";
  • Packit 1c1d7e
            t << "
    Packit 1c1d7e
            t << "\">";
    Packit 1c1d7e
            t << "<param name=\"Name\" value=\"" << m_help->recode(level1) << "\">"
    Packit 1c1d7e
               "</OBJECT>\n";
    Packit 1c1d7e
          }
    Packit 1c1d7e
          else
    Packit 1c1d7e
          {
    Packit 1c1d7e
            if (f->link)
    Packit 1c1d7e
            {
    Packit 1c1d7e
              t << "  
  • <OBJECT type=\"text/sitemap\">";
  • Packit 1c1d7e
              t << "
    Packit 1c1d7e
              t << "\">";
    Packit 1c1d7e
              t << "<param name=\"Name\" value=\"" << m_help->recode(level1) << "\">"
    Packit 1c1d7e
                   "</OBJECT>\n";
    Packit 1c1d7e
            }
    Packit 1c1d7e
            else
    Packit 1c1d7e
            {
    Packit 1c1d7e
              t << "  
  • <OBJECT type=\"text/sitemap\">";
  • Packit 1c1d7e
              t << "<param name=\"See Also\" value=\"" << m_help->recode(level1) << "\">";
    Packit 1c1d7e
              t << "<param name=\"Name\" value=\"" << m_help->recode(level1) << "\">"
    Packit 1c1d7e
                   "</OBJECT>\n";
    Packit 1c1d7e
            }
    Packit 1c1d7e
          }
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if (!level2Started && !level2.isEmpty())
    Packit 1c1d7e
        { // start new list at level 2
    Packit 1c1d7e
          t << "  
      " << endl;
    Packit 1c1d7e
          level2Started=TRUE;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        else if (level2Started && level2.isEmpty())
    Packit 1c1d7e
        { // end list at level 2
    Packit 1c1d7e
          t << "  " << endl;
    Packit 1c1d7e
          level2Started=FALSE;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if (level2Started)
    Packit 1c1d7e
        {
    Packit 1c1d7e
          t << "    
  • <OBJECT type=\"text/sitemap\">";
  • Packit 1c1d7e
          t << "
    Packit 1c1d7e
          t << "\">";
    Packit 1c1d7e
          t << "<param name=\"Name\" value=\"" << m_help->recode(level2) << "\">"
    Packit 1c1d7e
             "</OBJECT>\n";
    Packit 1c1d7e
        }
    Packit 1c1d7e
        lastLevel1 = level1.copy();
    Packit 1c1d7e
      } 
    Packit 1c1d7e
      if (level2Started) t << "  " << endl;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    //----------------------------------------------------------------------------
    Packit 1c1d7e
    Packit 1c1d7e
    HtmlHelp *HtmlHelp::theInstance = 0;
    Packit 1c1d7e
    Packit 1c1d7e
    /*! Constructs an html object. 
    Packit 1c1d7e
     *  The object has to be \link initialize() initialized\endlink before it can 
    Packit 1c1d7e
     *  be used.
    Packit 1c1d7e
     */
    Packit 1c1d7e
    HtmlHelp::HtmlHelp() : indexFileDict(1009)
    Packit 1c1d7e
    {
    Packit 1c1d7e
      /* initial depth */
    Packit 1c1d7e
      dc = 0;
    Packit 1c1d7e
      cf = kf = 0;
    Packit 1c1d7e
      index = new HtmlHelpIndex(this);
    Packit 1c1d7e
      m_fromUtf8 = (void *)(-1);
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    HtmlHelp::~HtmlHelp()
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (m_fromUtf8!=(void *)(-1))   portable_iconv_close(m_fromUtf8);
    Packit 1c1d7e
      delete index;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    #if 0
    Packit 1c1d7e
    /*! return a reference to the one and only instance of this class. 
    Packit 1c1d7e
     */
    Packit 1c1d7e
    HtmlHelp *HtmlHelp::getInstance()
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (theInstance==0) theInstance = new HtmlHelp;
    Packit 1c1d7e
      return theInstance;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    Packit 1c1d7e
    static QDict<QCString> s_languageDict;
    Packit 1c1d7e
    Packit 1c1d7e
    /*! This will create a contents file (index.hhc) and a index file (index.hhk)
    Packit 1c1d7e
     *  and write the header of those files. 
    Packit 1c1d7e
     *  It also creates a project file (index.hhp)
    Packit 1c1d7e
     *  \sa finalize()
    Packit 1c1d7e
     */
    Packit 1c1d7e
    void HtmlHelp::initialize()
    Packit 1c1d7e
    {
    Packit 1c1d7e
      const char *str = Config_getString(CHM_INDEX_ENCODING);
    Packit 1c1d7e
      if (!str) str = "CP1250"; // use safe and likely default
    Packit 1c1d7e
      m_fromUtf8 = portable_iconv_open(str,"UTF-8"); 
    Packit 1c1d7e
      if (m_fromUtf8==(void *)(-1))
    Packit 1c1d7e
      {
    Packit 1c1d7e
        err("unsupported character conversion for CHM_INDEX_ENCODING: '%s'->'UTF-8'\n", str);
    Packit 1c1d7e
        exit(1);
    Packit 1c1d7e
      }
    Packit 1c1d7e
    Packit 1c1d7e
      /* open the contents file */
    Packit 1c1d7e
      QCString fName = Config_getString(HTML_OUTPUT) + "/index.hhc";
    Packit 1c1d7e
      cf = new QFile(fName);
    Packit 1c1d7e
      if (!cf->open(IO_WriteOnly))
    Packit 1c1d7e
      {
    Packit 1c1d7e
        err("Could not open file %s for writing\n",fName.data());
    Packit 1c1d7e
        exit(1);
    Packit 1c1d7e
      }
    Packit 1c1d7e
      /* Write the header of the contents file */
    Packit 1c1d7e
      cts.setDevice(cf);
    Packit 1c1d7e
      cts << "\n"
    Packit 1c1d7e
             "<HTML><HEAD></HEAD><BODY>\n"
    Packit 1c1d7e
             "<OBJECT type=\"text/site properties\">\n"
    Packit 1c1d7e
             "<param name=\"FrameName\" value=\"right\">\n"
    Packit 1c1d7e
             "</OBJECT>\n"
    Packit 1c1d7e
             "
      \n";
    Packit 1c1d7e
      
    Packit 1c1d7e
      /* open the contents file */
    Packit 1c1d7e
      fName = Config_getString(HTML_OUTPUT) + "/index.hhk";
    Packit 1c1d7e
      kf = new QFile(fName);
    Packit 1c1d7e
      if (!kf->open(IO_WriteOnly))
    Packit 1c1d7e
      {
    Packit 1c1d7e
        err("Could not open file %s for writing\n",fName.data());
    Packit 1c1d7e
        exit(1);
    Packit 1c1d7e
      }
    Packit 1c1d7e
      /* Write the header of the contents file */
    Packit 1c1d7e
      kts.setDevice(kf);
    Packit 1c1d7e
      kts << "\n"
    Packit 1c1d7e
             "<HTML><HEAD></HEAD><BODY>\n"
    Packit 1c1d7e
             "<OBJECT type=\"text/site properties\">\n"
    Packit 1c1d7e
             "<param name=\"FrameName\" value=\"right\">\n"
    Packit 1c1d7e
             "</OBJECT>\n"
    Packit 1c1d7e
             "
      \n";
    Packit 1c1d7e
    Packit 1c1d7e
      /* language codes for Html help
    Packit 1c1d7e
         0x405 Czech
    Packit 1c1d7e
         0x406 Danish
    Packit 1c1d7e
         0x413 Dutch
    Packit 1c1d7e
         0xC09 English (Australia)
    Packit 1c1d7e
         0x809 English (Britain)
    Packit 1c1d7e
         0x1009 English (Canada)
    Packit 1c1d7e
         0x1809 English (Ireland)
    Packit 1c1d7e
         0x1409 English (New Zealand)
    Packit 1c1d7e
         0x1C09 English (South Africa)
    Packit 1c1d7e
         0x409 English (United States)
    Packit 1c1d7e
         0x40B Finnish
    Packit 1c1d7e
         0x40C French
    Packit 1c1d7e
         0x407 German
    Packit 1c1d7e
         0x408 Greece
    Packit 1c1d7e
         0x40E Hungarian
    Packit 1c1d7e
         0x410 Italian
    Packit 1c1d7e
         0x814 Norwegian
    Packit 1c1d7e
         0x415 Polish
    Packit 1c1d7e
         0x816 Portuguese(Portugal)
    Packit 1c1d7e
         0x416 Portuguese(Brazil)
    Packit 1c1d7e
         0x419 Russian
    Packit 1c1d7e
         0x80A Spanish(Mexico)
    Packit 1c1d7e
         0xC0A Spanish(Modern Sort)
    Packit 1c1d7e
         0x40A Spanish(Traditional Sort)
    Packit 1c1d7e
         0x41D Swedish
    Packit 1c1d7e
         0x41F Turkey
    Packit 1c1d7e
         0x411 Japanese
    Packit 1c1d7e
         0x412 Korean
    Packit 1c1d7e
         0x804 Chinese (PRC)
    Packit 1c1d7e
         0x404 Chinese (Taiwan)
    Packit 1c1d7e
    Packit 1c1d7e
         New LCIDs:
    Packit 1c1d7e
    	 0x421 Indonesian
    Packit 1c1d7e
    	 0x41A Croatian
    Packit 1c1d7e
    	 0x418 Romanian
    Packit 1c1d7e
    	 0x424 Slovenian
    Packit 1c1d7e
    	 0x41B Slovak
    Packit 1c1d7e
    	 0x422 Ukrainian
    Packit 1c1d7e
    	 0x81A Serbian (Serbia, Latin)
    Packit 1c1d7e
    	 0x403 Catalan
    Packit 1c1d7e
    	 0x426 Latvian
    Packit 1c1d7e
    	 0x427 Lithuanian
    Packit 1c1d7e
    	 0x436 Afrikaans
    Packit 1c1d7e
    	 0x42A Vietnamese
    Packit 1c1d7e
    	 0x429 Persian (Iran)
    Packit 1c1d7e
    	 0xC01 Arabic (Egypt) - I don't know which version of arabic is used inside translator_ar.h ,
    Packit 1c1d7e
         so I have chosen Egypt at random
    Packit 1c1d7e
    Packit 1c1d7e
      */
    Packit 1c1d7e
      s_languageDict.setAutoDelete(TRUE);
    Packit 1c1d7e
      s_languageDict.clear();
    Packit 1c1d7e
      s_languageDict.insert("czech",       new QCString("0x405 Czech"));
    Packit 1c1d7e
      s_languageDict.insert("danish",      new QCString("0x406 Danish"));
    Packit 1c1d7e
      s_languageDict.insert("dutch",       new QCString("0x413 Dutch"));
    Packit 1c1d7e
      s_languageDict.insert("finnish",     new QCString("0x40B Finnish"));
    Packit 1c1d7e
      s_languageDict.insert("french",      new QCString("0x40C French"));
    Packit 1c1d7e
      s_languageDict.insert("german",      new QCString("0x407 German"));
    Packit 1c1d7e
      s_languageDict.insert("greek",       new QCString("0x408 Greece"));
    Packit 1c1d7e
      s_languageDict.insert("hungarian",   new QCString("0x40E Hungarian"));
    Packit 1c1d7e
      s_languageDict.insert("italian",     new QCString("0x410 Italian"));
    Packit 1c1d7e
      s_languageDict.insert("norwegian",   new QCString("0x814 Norwegian"));
    Packit 1c1d7e
      s_languageDict.insert("polish",      new QCString("0x415 Polish"));
    Packit 1c1d7e
      s_languageDict.insert("portuguese",  new QCString("0x816 Portuguese(Portugal)"));
    Packit 1c1d7e
      s_languageDict.insert("brazilian",   new QCString("0x416 Portuguese(Brazil)"));
    Packit 1c1d7e
      s_languageDict.insert("russian",     new QCString("0x419 Russian"));
    Packit 1c1d7e
      s_languageDict.insert("spanish",     new QCString("0x40A Spanish(Traditional Sort)"));
    Packit 1c1d7e
      s_languageDict.insert("swedish",     new QCString("0x41D Swedish"));
    Packit 1c1d7e
      s_languageDict.insert("turkish",     new QCString("0x41F Turkey"));
    Packit 1c1d7e
      s_languageDict.insert("japanese",    new QCString("0x411 Japanese"));
    Packit 1c1d7e
      s_languageDict.insert("japanese-en", new QCString("0x411 Japanese"));
    Packit 1c1d7e
      s_languageDict.insert("korean",      new QCString("0x412 Korean"));
    Packit 1c1d7e
      s_languageDict.insert("korean-en",   new QCString("0x412 Korean"));
    Packit 1c1d7e
      s_languageDict.insert("chinese",     new QCString("0x804 Chinese (PRC)"));
    Packit 1c1d7e
      s_languageDict.insert("chinese-traditional", new QCString("0x404 Chinese (Taiwan)"));
    Packit 1c1d7e
    Packit 1c1d7e
      // new LCIDs
    Packit 1c1d7e
      s_languageDict.insert("indonesian",  new QCString("0x412 Indonesian"));
    Packit 1c1d7e
      s_languageDict.insert("croatian",    new QCString("0x41A Croatian"));
    Packit 1c1d7e
      s_languageDict.insert("romanian",    new QCString("0x418 Romanian"));
    Packit 1c1d7e
      s_languageDict.insert("slovene",     new QCString("0x424 Slovenian"));
    Packit 1c1d7e
      s_languageDict.insert("slovak",      new QCString("0x41B Slovak"));
    Packit 1c1d7e
      s_languageDict.insert("ukrainian",   new QCString("0x422 Ukrainian"));
    Packit 1c1d7e
      s_languageDict.insert("serbian",     new QCString("0x81A Serbian (Serbia, Latin)"));
    Packit 1c1d7e
      s_languageDict.insert("catalan",     new QCString("0x403 Catalan"));
    Packit 1c1d7e
      s_languageDict.insert("lithuanian",  new QCString("0x427 Lithuanian"));
    Packit 1c1d7e
      s_languageDict.insert("afrikaans",   new QCString("0x436 Afrikaans"));
    Packit 1c1d7e
      s_languageDict.insert("vietnamese",  new QCString("0x42A Vietnamese"));
    Packit 1c1d7e
      s_languageDict.insert("persian",     new QCString("0x429 Persian (Iran)"));
    Packit 1c1d7e
      s_languageDict.insert("arabic",      new QCString("0xC01 Arabic (Egypt)"));
    Packit 1c1d7e
      s_languageDict.insert("latvian",     new QCString("0x426 Latvian"));
    Packit 1c1d7e
      s_languageDict.insert("macedonian",  new QCString("0x042f Macedonian (Former Yugoslav Republic of Macedonia)"));
    Packit 1c1d7e
      s_languageDict.insert("armenian",    new QCString("0x42b Armenian"));
    Packit 1c1d7e
      //Code for Esperanto should be as shown below but the htmlhelp compiler 1.3 does not support this
    Packit 1c1d7e
      // (and no newer version is available).
    Packit 1c1d7e
      //So do a fallback to the default language (see getLanguageString())
    Packit 1c1d7e
      //s_languageDict.insert("esperanto",   new QCString("0x48f Esperanto"));
    Packit 1c1d7e
      s_languageDict.insert("serbian-cyrillic", new QCString("0xC1A Serbian (Serbia, Cyrillic)"));
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    Packit 1c1d7e
    QCString HtmlHelp::getLanguageString()
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (!theTranslator->idLanguage().isEmpty())
    Packit 1c1d7e
      {
    Packit 1c1d7e
        QCString *s = s_languageDict[theTranslator->idLanguage()];
    Packit 1c1d7e
        if (s)
    Packit 1c1d7e
        {
    Packit 1c1d7e
          return *s;
    Packit 1c1d7e
        }
    Packit 1c1d7e
      }
    Packit 1c1d7e
      // default language
    Packit 1c1d7e
      return "0x409 English (United States)";
    Packit 1c1d7e
    }
    Packit 1c1d7e
      
    Packit 1c1d7e
    Packit 1c1d7e
    Packit 1c1d7e
    void HtmlHelp::createProjectFile()
    Packit 1c1d7e
    {
    Packit 1c1d7e
      /* Write the project file */
    Packit 1c1d7e
      QCString fName = Config_getString(HTML_OUTPUT) + "/index.hhp";
    Packit 1c1d7e
      QFile f(fName);
    Packit 1c1d7e
      if (f.open(IO_WriteOnly))
    Packit 1c1d7e
      {
    Packit 1c1d7e
        FTextStream t(&f);
    Packit 1c1d7e
        
    Packit 1c1d7e
        QCString indexName="index"+Doxygen::htmlFileExtension;
    Packit 1c1d7e
        t << "[OPTIONS]\n";
    Packit 1c1d7e
        if (!Config_getString(CHM_FILE).isEmpty())
    Packit 1c1d7e
        {
    Packit 1c1d7e
          t << "Compiled file=" << Config_getString(CHM_FILE) << "\n";
    Packit 1c1d7e
        }
    Packit 1c1d7e
        t << "Compatibility=1.1\n"
    Packit 1c1d7e
             "Full-text search=Yes\n"
    Packit 1c1d7e
             "Contents file=index.hhc\n"
    Packit 1c1d7e
             "Default Window=main\n"
    Packit 1c1d7e
             "Default topic=" << indexName << "\n"
    Packit 1c1d7e
             "Index file=index.hhk\n"
    Packit 1c1d7e
             "Language=" << getLanguageString() << endl;
    Packit 1c1d7e
        if (Config_getBool(BINARY_TOC)) t << "Binary TOC=YES\n";
    Packit 1c1d7e
        if (Config_getBool(GENERATE_CHI)) t << "Create CHI file=YES\n";
    Packit 1c1d7e
        t << "Title=" << recode(Config_getString(PROJECT_NAME)) << endl << endl;
    Packit 1c1d7e
        
    Packit 1c1d7e
        t << "[WINDOWS]" << endl;
    Packit 1c1d7e
    Packit 1c1d7e
        // NOTE: the 0x10387e number is a set of bits specifying the buttons
    Packit 1c1d7e
        //       which should appear in the CHM viewer; that specific value
    Packit 1c1d7e
        //       means "show all buttons including the font-size one";
    Packit 1c1d7e
        //       the font-size one is not normally settable by the HTML Help Workshop
    Packit 1c1d7e
        //       utility but the way to set it is described here:
    Packit 1c1d7e
        //          http://support.microsoft.com/?scid=kb%3Ben-us%3B240062&x=17&y=18
    Packit 1c1d7e
        // NOTE: the 0x70387e number in addition to the above the Next and Prev button
    Packit 1c1d7e
        //       are shown. They can only be shown in case of a binary toc.
    Packit 1c1d7e
        //          dee http://www.mif2go.com/xhtml/htmlhelp_0016_943addingtabsandtoolbarbuttonstohtmlhelp.htm#Rz108x95873
    Packit 1c1d7e
        //       Value has been taken from htmlhelp.h file of the HTML Help Workshop
    Packit 1c1d7e
        if (Config_getBool(BINARY_TOC))
    Packit 1c1d7e
        {
    Packit 1c1d7e
          t << "main=\"" << recode(Config_getString(PROJECT_NAME)) << "\",\"index.hhc\","
    Packit 1c1d7e
             "\"index.hhk\",\"" << indexName << "\",\"" << 
    Packit 1c1d7e
             indexName << "\",,,,,0x23520,,0x70387e,,,,,,,,0" << endl << endl;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        else
    Packit 1c1d7e
        {
    Packit 1c1d7e
          t << "main=\"" << recode(Config_getString(PROJECT_NAME)) << "\",\"index.hhc\","
    Packit 1c1d7e
             "\"index.hhk\",\"" << indexName << "\",\"" << 
    Packit 1c1d7e
             indexName << "\",,,,,0x23520,,0x10387e,,,,,,,,0" << endl << endl;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        
    Packit 1c1d7e
        t << "[FILES]" << endl;
    Packit 1c1d7e
        char *s = indexFiles.first();
    Packit 1c1d7e
        while (s)
    Packit 1c1d7e
        {
    Packit 1c1d7e
          t << s << endl;
    Packit 1c1d7e
          s = indexFiles.next();
    Packit 1c1d7e
        }
    Packit 1c1d7e
        uint i;
    Packit 1c1d7e
        for (i=0;i
    Packit 1c1d7e
        {
    Packit 1c1d7e
          t << imageFiles.at(i) << endl;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        f.close();
    Packit 1c1d7e
      }
    Packit 1c1d7e
      else
    Packit 1c1d7e
      {
    Packit 1c1d7e
        err("Could not open file %s for writing\n",fName.data());
    Packit 1c1d7e
      }
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    void HtmlHelp::addIndexFile(const char *s)
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (indexFileDict.find(s)==0)
    Packit 1c1d7e
      {
    Packit 1c1d7e
        indexFiles.append(s);
    Packit 1c1d7e
        indexFileDict.insert(s,(void *)0x8);
    Packit 1c1d7e
      }
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*! Finalizes the HTML help. This will finish and close the
    Packit 1c1d7e
     *  contents file (index.hhc) and the index file (index.hhk).
    Packit 1c1d7e
     *  \sa initialize()
    Packit 1c1d7e
     */
    Packit 1c1d7e
    void HtmlHelp::finalize()
    Packit 1c1d7e
    {
    Packit 1c1d7e
      // end the contents file
    Packit 1c1d7e
      cts << "\n";
    Packit 1c1d7e
      cts << "</BODY>\n";
    Packit 1c1d7e
      cts << "</HTML>\n";
    Packit 1c1d7e
      cts.unsetDevice();
    Packit 1c1d7e
      cf->close();
    Packit 1c1d7e
      delete cf;
    Packit 1c1d7e
      
    Packit 1c1d7e
      index->writeFields(kts);
    Packit 1c1d7e
      
    Packit 1c1d7e
      // end the index file
    Packit 1c1d7e
      kts << "\n";
    Packit 1c1d7e
      kts << "</BODY>\n";
    Packit 1c1d7e
      kts << "</HTML>\n";
    Packit 1c1d7e
      kts.unsetDevice();
    Packit 1c1d7e
      kf->close();
    Packit 1c1d7e
      delete kf;
    Packit 1c1d7e
    Packit 1c1d7e
      createProjectFile();
    Packit 1c1d7e
      s_languageDict.clear();
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*! Increase the level of the contents hierarchy. 
    Packit 1c1d7e
     *  This will start a new unnumbered HTML list in contents file.
    Packit 1c1d7e
     *  \sa decContentsDepth()
    Packit 1c1d7e
     */
    Packit 1c1d7e
    void HtmlHelp::incContentsDepth()
    Packit 1c1d7e
    {
    Packit 1c1d7e
      int i; for (i=0;i
    Packit 1c1d7e
      cts << "
      \n";
    Packit 1c1d7e
      ++dc;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*! Decrease the level of the contents hierarchy.
    Packit 1c1d7e
     *  This will end the unnumber HTML list.
    Packit 1c1d7e
     *  \sa incContentsDepth()
    Packit 1c1d7e
     */
    Packit 1c1d7e
    void HtmlHelp::decContentsDepth()
    Packit 1c1d7e
    {
    Packit 1c1d7e
      int i; for (i=0;i
    Packit 1c1d7e
      cts << "\n";
    Packit 1c1d7e
      --dc;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    QCString HtmlHelp::recode(const QCString &s) 
    Packit 1c1d7e
    {
    Packit 1c1d7e
      int iSize        = s.length();
    Packit 1c1d7e
      int oSize        = iSize*4+1;
    Packit 1c1d7e
      QCString output(oSize);
    Packit 1c1d7e
      size_t iLeft     = iSize;
    Packit 1c1d7e
      size_t oLeft     = oSize;
    Packit 1c1d7e
      char *iPtr       = s.rawData();
    Packit 1c1d7e
      char *oPtr       = output.rawData();
    Packit 1c1d7e
      if (!portable_iconv(m_fromUtf8,&iPtr,&iLeft,&oPtr,&oLeft))
    Packit 1c1d7e
      {
    Packit 1c1d7e
        oSize -= (int)oLeft;
    Packit 1c1d7e
        output.resize(oSize+1);
    Packit 1c1d7e
        output.at(oSize)='\0';
    Packit 1c1d7e
        return output;
    Packit 1c1d7e
      }
    Packit 1c1d7e
      else
    Packit 1c1d7e
      {
    Packit 1c1d7e
        return s;
    Packit 1c1d7e
      }
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*! Add an list item to the contents file.
    Packit 1c1d7e
     *  \param isDir boolean indicating if this is a dir or file entry
    Packit 1c1d7e
     *  \param name the name of the item.
    Packit 1c1d7e
     *  \param ref  the URL of to the item.
    Packit 1c1d7e
     *  \param file the file in which the item is defined.
    Packit 1c1d7e
     *  \param anchor the anchor of the item.
    Packit 1c1d7e
     *  \param separateIndex not used.
    Packit 1c1d7e
     *  \param addToNavIndex not used.
    Packit 1c1d7e
     *  \param def not used.
    Packit 1c1d7e
     */
    Packit 1c1d7e
    void HtmlHelp::addContentsItem(bool isDir,
    Packit 1c1d7e
                                   const char *name,
    Packit 1c1d7e
                                   const char * /*ref*/, 
    Packit 1c1d7e
                                   const char *file,
    Packit 1c1d7e
                                   const char *anchor,
    Packit 1c1d7e
                                   bool /* separateIndex */,
    Packit 1c1d7e
                                   bool /* addToNavIndex */,
    Packit 1c1d7e
                                   Definition * /* def */)
    Packit 1c1d7e
    {
    Packit 1c1d7e
      // If we're using a binary toc then folders cannot have links. 
    Packit 1c1d7e
      // Tried this and I didn't see any problems, when not using
    Packit 1c1d7e
      // the resetting of file and anchor the TOC works better
    Packit 1c1d7e
      // (prev / next button)
    Packit 1c1d7e
      //if(Config_getBool(BINARY_TOC) && isDir) 
    Packit 1c1d7e
      //{
    Packit 1c1d7e
        //file = 0;
    Packit 1c1d7e
        //anchor = 0;
    Packit 1c1d7e
      //}
    Packit 1c1d7e
      int i; for (i=0;i
    Packit 1c1d7e
      cts << "
  • <OBJECT type=\"text/sitemap\">";
  • Packit 1c1d7e
      cts << "<param name=\"Name\" value=\"" << convertToHtml(recode(name),TRUE) << "\">";
    Packit 1c1d7e
      if (file)      // made file optional param - KPW
    Packit 1c1d7e
      {
    Packit 1c1d7e
        if (file && (file[0]=='!' || file[0]=='^')) // special markers for user defined URLs
    Packit 1c1d7e
        {
    Packit 1c1d7e
          cts << "
    Packit 1c1d7e
          if (file[0]=='^') cts << "URL"; else cts << "Local";
    Packit 1c1d7e
          cts << "\" value=\"";
    Packit 1c1d7e
          cts << &file[1];
    Packit 1c1d7e
        }
    Packit 1c1d7e
        else
    Packit 1c1d7e
        {
    Packit 1c1d7e
          cts << "
    Packit 1c1d7e
          cts << file << Doxygen::htmlFileExtension;
    Packit 1c1d7e
          if (anchor) cts << "#" << anchor;  
    Packit 1c1d7e
        }
    Packit 1c1d7e
        cts << "\">";
    Packit 1c1d7e
      }
    Packit 1c1d7e
      cts << "
    Packit 1c1d7e
      if (isDir)  // added - KPW
    Packit 1c1d7e
      {
    Packit 1c1d7e
        cts << (int)BOOK_CLOSED ;
    Packit 1c1d7e
      }
    Packit 1c1d7e
      else
    Packit 1c1d7e
      {
    Packit 1c1d7e
        cts << (int)TEXT;
    Packit 1c1d7e
      }
    Packit 1c1d7e
      cts << "\">";
    Packit 1c1d7e
      cts << "</OBJECT>\n";
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    Packit 1c1d7e
    void HtmlHelp::addIndexItem(Definition *context,MemberDef *md,
    Packit 1c1d7e
                                const char *sectionAnchor,const char *word)
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (md)
    Packit 1c1d7e
      {
    Packit 1c1d7e
        static bool separateMemberPages = Config_getBool(SEPARATE_MEMBER_PAGES);
    Packit 1c1d7e
        if (context==0) // global member
    Packit 1c1d7e
        {
    Packit 1c1d7e
          if (md->getGroupDef())
    Packit 1c1d7e
            context = md->getGroupDef();
    Packit 1c1d7e
          else if (md->getFileDef())
    Packit 1c1d7e
            context = md->getFileDef();
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if (context==0) return; // should not happen
    Packit 1c1d7e
    Packit 1c1d7e
        QCString cfname  = md->getOutputFileBase();
    Packit 1c1d7e
        QCString cfiname = context->getOutputFileBase();
    Packit 1c1d7e
        QCString level1  = context->name();
    Packit 1c1d7e
        QCString level2  = md->name();
    Packit 1c1d7e
        QCString contRef = separateMemberPages ? cfname : cfiname;
    Packit 1c1d7e
        QCString memRef  = cfname;
    Packit 1c1d7e
        QCString anchor  = sectionAnchor ? QCString(sectionAnchor) : md->anchor();
    Packit 1c1d7e
        index->addItem(level1,level2,contRef,anchor,TRUE,FALSE);
    Packit 1c1d7e
        index->addItem(level2,level1,memRef,anchor,TRUE,TRUE);
    Packit 1c1d7e
      }
    Packit 1c1d7e
      else if (context)
    Packit 1c1d7e
      {
    Packit 1c1d7e
        QCString level1  = word ? QCString(word) : context->name();
    Packit 1c1d7e
        index->addItem(level1,0,context->getOutputFileBase(),sectionAnchor,TRUE,FALSE);
    Packit 1c1d7e
      }
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    void HtmlHelp::addImageFile(const char *fileName)
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (!imageFiles.contains(fileName)) imageFiles.append(fileName);
    Packit 1c1d7e
    }
    Packit 1c1d7e