Blame src/searchindex.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
 */
Packit 1c1d7e
Packit 1c1d7e
#include <ctype.h>
Packit 1c1d7e
#include <assert.h>
Packit 1c1d7e
Packit 1c1d7e
#include <qfile.h>
Packit 1c1d7e
#include <qregexp.h>
Packit 1c1d7e
Packit 1c1d7e
#include "searchindex.h"
Packit 1c1d7e
#include "config.h"
Packit 1c1d7e
#include "util.h"
Packit 1c1d7e
#include "doxygen.h"
Packit 1c1d7e
#include "language.h"
Packit 1c1d7e
#include "pagedef.h"
Packit 1c1d7e
#include "growbuf.h"
Packit 1c1d7e
#include "message.h"
Packit 1c1d7e
#include "version.h"
Packit 1c1d7e
#include "groupdef.h"
Packit 1c1d7e
#include "classlist.h"
Packit 1c1d7e
#include "filedef.h"
Packit 1c1d7e
#include "memberdef.h"
Packit 1c1d7e
#include "filename.h"
Packit 1c1d7e
#include "membername.h"
Packit 1c1d7e
#include "resourcemgr.h"
Packit 1c1d7e
Packit 1c1d7e
// file format: (all multi-byte values are stored in big endian format)
Packit 1c1d7e
//   4 byte header
Packit 1c1d7e
//   256*256*4 byte index (4 bytes)
Packit 1c1d7e
//   for each index entry: a zero terminated list of words
Packit 1c1d7e
//   for each word: a \0 terminated string + 4 byte offset to the stats info
Packit 1c1d7e
//   padding bytes to align at 4 byte boundary
Packit 1c1d7e
//   for each word: the number of urls (4 bytes)
Packit 1c1d7e
//               + for each url containing the word 8 bytes statistics
Packit 1c1d7e
//                 (4 bytes index to url string + 4 bytes frequency counter)
Packit 1c1d7e
//   for each url: a \0 terminated string
Packit 1c1d7e
Packit 1c1d7e
const int numIndexEntries = 256*256;
Packit 1c1d7e
Packit 1c1d7e
//--------------------------------------------------------------------
Packit 1c1d7e
Packit 1c1d7e
IndexWord::IndexWord(const char *word) : m_word(word), m_urls(17)
Packit 1c1d7e
{
Packit 1c1d7e
  m_urls.setAutoDelete(TRUE);
Packit 1c1d7e
  //printf("IndexWord::IndexWord(%s)\n",word);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void IndexWord::addUrlIndex(int idx,bool hiPriority)
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("IndexWord::addUrlIndex(%d,%d)\n",idx,hiPriority);
Packit 1c1d7e
  URLInfo *ui = m_urls.find(idx);
Packit 1c1d7e
  if (ui==0)
Packit 1c1d7e
  {
Packit 1c1d7e
    //printf("URLInfo::URLInfo(%d)\n",idx);
Packit 1c1d7e
    ui=new URLInfo(idx,0);
Packit 1c1d7e
    m_urls.insert(idx,ui);
Packit 1c1d7e
  }
Packit 1c1d7e
  ui->freq+=2;
Packit 1c1d7e
  if (hiPriority) ui->freq|=1; // mark as high priority document
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
//--------------------------------------------------------------------
Packit 1c1d7e
Packit 1c1d7e
SearchIndex::SearchIndex() : SearchIndexIntf(Internal),
Packit 1c1d7e
      m_words(328829), m_index(numIndexEntries), m_url2IdMap(10007), m_urls(10007), m_urlIndex(-1)
Packit 1c1d7e
{
Packit 1c1d7e
  int i;
Packit 1c1d7e
  m_words.setAutoDelete(TRUE);
Packit 1c1d7e
  m_url2IdMap.setAutoDelete(TRUE);
Packit 1c1d7e
  m_urls.setAutoDelete(TRUE);
Packit 1c1d7e
  m_index.setAutoDelete(TRUE);
Packit 1c1d7e
  for (i=0;i<numIndexEntries;i++) m_index.insert(i,new QList<IndexWord>);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile)
Packit 1c1d7e
{
Packit 1c1d7e
  if (ctx==0) return;
Packit 1c1d7e
  assert(!isSourceFile || ctx->definitionType()==Definition::TypeFile);
Packit 1c1d7e
  //printf("SearchIndex::setCurrentDoc(%s,%s,%s)\n",name,baseName,anchor);
Packit 1c1d7e
  QCString url=isSourceFile ? ((FileDef*)ctx)->getSourceFileBase() : ctx->getOutputFileBase();
Packit 1c1d7e
  url+=Config_getString(HTML_FILE_EXTENSION);
Packit 1c1d7e
  QCString baseUrl = url;
Packit 1c1d7e
  if (anchor) url+=QCString("#")+anchor;
Packit 1c1d7e
  if (!isSourceFile) baseUrl=url;
Packit 1c1d7e
  QCString name=ctx->qualifiedName();
Packit 1c1d7e
  if (ctx->definitionType()==Definition::TypeMember)
Packit 1c1d7e
  {
Packit 1c1d7e
    MemberDef *md = (MemberDef *)ctx;
Packit 1c1d7e
    name.prepend((md->getLanguage()==SrcLangExt_Fortran  ?
Packit 1c1d7e
                 theTranslator->trSubprogram(TRUE,TRUE) :
Packit 1c1d7e
                 theTranslator->trMember(TRUE,TRUE))+" ");
Packit 1c1d7e
  }
Packit 1c1d7e
  else // compound type
Packit 1c1d7e
  {
Packit 1c1d7e
    SrcLangExt lang = ctx->getLanguage();
Packit 1c1d7e
    QCString sep = getLanguageSpecificSeparator(lang);
Packit 1c1d7e
    if (sep!="::")
Packit 1c1d7e
    {
Packit 1c1d7e
      name = substitute(name,"::",sep);
Packit 1c1d7e
    }
Packit 1c1d7e
    switch (ctx->definitionType())
Packit 1c1d7e
    {
Packit 1c1d7e
      case Definition::TypePage:
Packit 1c1d7e
        {
Packit 1c1d7e
          PageDef *pd = (PageDef *)ctx;
Packit 1c1d7e
          if (!pd->title().isEmpty())
Packit 1c1d7e
          {
Packit 1c1d7e
            name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title();
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            name = theTranslator->trPage(TRUE,TRUE)+" "+pd->name();
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        break;
Packit 1c1d7e
      case Definition::TypeClass:
Packit 1c1d7e
        {
Packit 1c1d7e
          ClassDef *cd = (ClassDef *)ctx;
Packit 1c1d7e
          name.prepend(cd->compoundTypeString()+" ");
Packit 1c1d7e
        }
Packit 1c1d7e
        break;
Packit 1c1d7e
      case Definition::TypeNamespace:
Packit 1c1d7e
        {
Packit 1c1d7e
          if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp)
Packit 1c1d7e
          {
Packit 1c1d7e
            name = theTranslator->trPackage(name);
Packit 1c1d7e
          }
Packit 1c1d7e
          else if (lang==SrcLangExt_Fortran)
Packit 1c1d7e
          {
Packit 1c1d7e
            name.prepend(theTranslator->trModule(TRUE,TRUE)+" ");
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            name.prepend(theTranslator->trNamespace(TRUE,TRUE)+" ");
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        break;
Packit 1c1d7e
      case Definition::TypeGroup:
Packit 1c1d7e
        {
Packit 1c1d7e
          GroupDef *gd = (GroupDef *)ctx;
Packit 1c1d7e
          if (gd->groupTitle())
Packit 1c1d7e
          {
Packit 1c1d7e
            name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle();
Packit 1c1d7e
          }
Packit 1c1d7e
          else
Packit 1c1d7e
          {
Packit 1c1d7e
            name.prepend(theTranslator->trGroup(TRUE,TRUE)+" ");
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
        break;
Packit 1c1d7e
      default:
Packit 1c1d7e
        break;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  int *pIndex = m_url2IdMap.find(baseUrl);
Packit 1c1d7e
  if (pIndex==0)
Packit 1c1d7e
  {
Packit 1c1d7e
    ++m_urlIndex;
Packit 1c1d7e
    m_url2IdMap.insert(baseUrl,new int(m_urlIndex));
Packit 1c1d7e
    m_urls.insert(m_urlIndex,new URL(name,url));
Packit 1c1d7e
  }
Packit 1c1d7e
  else
Packit 1c1d7e
  {
Packit 1c1d7e
    m_urls.insert(*pIndex,new URL(name,url));
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static int charsToIndex(const char *word)
Packit 1c1d7e
{
Packit 1c1d7e
  if (word==0) return -1;
Packit 1c1d7e
Packit 1c1d7e
  // Fast string hashing algorithm
Packit 1c1d7e
  //register ushort h=0;
Packit 1c1d7e
  //const char *k = word;
Packit 1c1d7e
  //ushort mask=0xfc00;
Packit 1c1d7e
  //while ( *k )
Packit 1c1d7e
  //{
Packit 1c1d7e
  //  h = (h&mask)^(h<<6)^(*k++);
Packit 1c1d7e
  //}
Packit 1c1d7e
  //return h;
Packit 1c1d7e
Packit 1c1d7e
  // Simple hashing that allows for substring searching
Packit 1c1d7e
  uint c1=((uchar *)word)[0];
Packit 1c1d7e
  if (c1==0) return -1;
Packit 1c1d7e
  uint c2=((uchar *)word)[1];
Packit 1c1d7e
  if (c2==0) return -1;
Packit 1c1d7e
  return c1*256+c2;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void SearchIndex::addWord(const char *word,bool hiPriority,bool recurse)
Packit 1c1d7e
{
Packit 1c1d7e
  static QRegExp nextPart("[_a-z:][A-Z]");
Packit 1c1d7e
  if (word==0 || word[0]=='\0') return;
Packit 1c1d7e
  QCString wStr = QCString(word).lower();
Packit 1c1d7e
  //printf("SearchIndex::addWord(%s,%d) wStr=%s\n",word,hiPriority,wStr.data());
Packit 1c1d7e
  IndexWord *w = m_words[wStr];
Packit 1c1d7e
  if (w==0)
Packit 1c1d7e
  {
Packit 1c1d7e
    int idx=charsToIndex(wStr);
Packit 1c1d7e
    //fprintf(stderr,"addWord(%s) at index %d\n",word,idx);
Packit 1c1d7e
    if (idx<0) return;
Packit 1c1d7e
    w = new IndexWord(wStr);
Packit 1c1d7e
    m_index[idx]->append(w);
Packit 1c1d7e
    m_words.insert(wStr,w);
Packit 1c1d7e
  }
Packit 1c1d7e
  w->addUrlIndex(m_urlIndex,hiPriority);
Packit 1c1d7e
  int i;
Packit 1c1d7e
  bool found=FALSE;
Packit 1c1d7e
  if (!recurse) // the first time we check if we can strip the prefix
Packit 1c1d7e
  {
Packit 1c1d7e
    i=getPrefixIndex(word);
Packit 1c1d7e
    if (i>0)
Packit 1c1d7e
    {
Packit 1c1d7e
      addWord(word+i,hiPriority,TRUE);
Packit 1c1d7e
      found=TRUE;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  if (!found) // no prefix stripped
Packit 1c1d7e
  {
Packit 1c1d7e
    if ((i=nextPart.match(word))>=1)
Packit 1c1d7e
    {
Packit 1c1d7e
      addWord(word+i+1,hiPriority,TRUE);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void SearchIndex::addWord(const char *word,bool hiPriority)
Packit 1c1d7e
{
Packit 1c1d7e
  addWord(word,hiPriority,FALSE);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void writeInt(QFile &f,int index)
Packit 1c1d7e
{
Packit 1c1d7e
  f.putch(((uint)index)>>24);
Packit 1c1d7e
  f.putch((((uint)index)>>16)&0xff);
Packit 1c1d7e
  f.putch((((uint)index)>>8)&0xff);
Packit 1c1d7e
  f.putch(((uint)index)&0xff);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static void writeString(QFile &f,const char *s)
Packit 1c1d7e
{
Packit 1c1d7e
  const char *p = s;
Packit 1c1d7e
  while (*p) f.putch(*p++);
Packit 1c1d7e
  f.putch(0);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void SearchIndex::write(const char *fileName)
Packit 1c1d7e
{
Packit 1c1d7e
  int i;
Packit 1c1d7e
  int size=4; // for the header
Packit 1c1d7e
  size+=4*numIndexEntries; // for the index
Packit 1c1d7e
  int wordsOffset = size;
Packit 1c1d7e
  // first pass: compute the size of the wordlist
Packit 1c1d7e
  for (i=0;i
Packit 1c1d7e
  {
Packit 1c1d7e
    QList<IndexWord> *wlist = m_index[i];
Packit 1c1d7e
    if (!wlist->isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      QListIterator<IndexWord> iwi(*wlist);
Packit 1c1d7e
      IndexWord *iw;
Packit 1c1d7e
      for (iwi.toFirst();(iw=iwi.current());++iwi)
Packit 1c1d7e
      {
Packit 1c1d7e
        int ws = iw->word().length()+1;
Packit 1c1d7e
        size+=ws+4; // word + url info list offset
Packit 1c1d7e
      }
Packit 1c1d7e
      size+=1; // zero list terminator
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // second pass: compute the offsets in the index
Packit 1c1d7e
  int indexOffsets[numIndexEntries];
Packit 1c1d7e
  int offset=wordsOffset;
Packit 1c1d7e
  for (i=0;i
Packit 1c1d7e
  {
Packit 1c1d7e
    QList<IndexWord> *wlist = m_index[i];
Packit 1c1d7e
    if (!wlist->isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      indexOffsets[i]=offset;
Packit 1c1d7e
      QListIterator<IndexWord> iwi(*wlist);
Packit 1c1d7e
      IndexWord *iw;
Packit 1c1d7e
      for (iwi.toFirst();(iw=iwi.current());++iwi)
Packit 1c1d7e
      {
Packit 1c1d7e
        offset+= iw->word().length()+1;
Packit 1c1d7e
        offset+=4; // word + offset to url info array
Packit 1c1d7e
      }
Packit 1c1d7e
      offset+=1; // zero list terminator
Packit 1c1d7e
    }
Packit 1c1d7e
    else
Packit 1c1d7e
    {
Packit 1c1d7e
      indexOffsets[i]=0;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  int padding = size;
Packit 1c1d7e
  size = (size+3)&~;; // round up to 4 byte boundary
Packit 1c1d7e
  padding = size - padding;
Packit 1c1d7e
Packit 1c1d7e
  //int statsOffset = size;
Packit 1c1d7e
  //IndexWord *iw;
Packit 1c1d7e
  int *wordStatOffsets = new int[m_words.count()];
Packit 1c1d7e
Packit 1c1d7e
  int count=0;
Packit 1c1d7e
Packit 1c1d7e
  // third pass: compute offset to stats info for each word
Packit 1c1d7e
  for (i=0;i
Packit 1c1d7e
  {
Packit 1c1d7e
    QList<IndexWord> *wlist = m_index[i];
Packit 1c1d7e
    if (!wlist->isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      QListIterator<IndexWord> iwi(*wlist);
Packit 1c1d7e
      IndexWord *iw;
Packit 1c1d7e
      for (iwi.toFirst();(iw=iwi.current());++iwi)
Packit 1c1d7e
      {
Packit 1c1d7e
        //printf("wordStatOffsets[%d]=%d\n",count,size);
Packit 1c1d7e
        wordStatOffsets[count++] = size;
Packit 1c1d7e
        size+=4+iw->urls().count()*8; // count + (url_index,freq) per url
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  int *urlOffsets = new int[m_urls.count()];
Packit 1c1d7e
  //int urlsOffset = size;
Packit 1c1d7e
  QIntDictIterator<URL> udi(m_urls);
Packit 1c1d7e
  URL *url;
Packit 1c1d7e
  for (udi.toFirst();(url=udi.current());++udi)
Packit 1c1d7e
  {
Packit 1c1d7e
    urlOffsets[udi.currentKey()]=size;
Packit 1c1d7e
    size+=url->name.length()+1+
Packit 1c1d7e
          url->url.length()+1;
Packit 1c1d7e
  }
Packit 1c1d7e
  //printf("Total size %x bytes (word=%x stats=%x urls=%x)\n",size,wordsOffset,statsOffset,urlsOffset);
Packit 1c1d7e
  QFile f(fileName);
Packit 1c1d7e
  if (f.open(IO_WriteOnly))
Packit 1c1d7e
  {
Packit 1c1d7e
    // write header
Packit 1c1d7e
    f.putch('D'); f.putch('O'); f.putch('X'); f.putch('S');
Packit 1c1d7e
    // write index
Packit 1c1d7e
    for (i=0;i
Packit 1c1d7e
    {
Packit 1c1d7e
      writeInt(f,indexOffsets[i]);
Packit 1c1d7e
    }
Packit 1c1d7e
    // write word lists
Packit 1c1d7e
    count=0;
Packit 1c1d7e
    for (i=0;i
Packit 1c1d7e
    {
Packit 1c1d7e
      QList<IndexWord> *wlist = m_index[i];
Packit 1c1d7e
      if (!wlist->isEmpty())
Packit 1c1d7e
      {
Packit 1c1d7e
        QListIterator<IndexWord> iwi(*wlist);
Packit 1c1d7e
        IndexWord *iw;
Packit 1c1d7e
        for (iwi.toFirst();(iw=iwi.current());++iwi)
Packit 1c1d7e
        {
Packit 1c1d7e
          writeString(f,iw->word());
Packit 1c1d7e
          writeInt(f,wordStatOffsets[count++]);
Packit 1c1d7e
        }
Packit 1c1d7e
        f.putch(0);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    // write extra padding bytes
Packit 1c1d7e
    for (i=0;i
Packit 1c1d7e
    // write word statistics
Packit 1c1d7e
    for (i=0;i
Packit 1c1d7e
    {
Packit 1c1d7e
      QList<IndexWord> *wlist = m_index[i];
Packit 1c1d7e
      if (!wlist->isEmpty())
Packit 1c1d7e
      {
Packit 1c1d7e
        QListIterator<IndexWord> iwi(*wlist);
Packit 1c1d7e
        IndexWord *iw;
Packit 1c1d7e
        for (iwi.toFirst();(iw=iwi.current());++iwi)
Packit 1c1d7e
        {
Packit 1c1d7e
          int numUrls = iw->urls().count();
Packit 1c1d7e
          writeInt(f,numUrls);
Packit 1c1d7e
          QIntDictIterator<URLInfo> uli(iw->urls());
Packit 1c1d7e
          URLInfo *ui;
Packit 1c1d7e
          for (uli.toFirst();(ui=uli.current());++uli)
Packit 1c1d7e
          {
Packit 1c1d7e
            writeInt(f,urlOffsets[ui->urlIdx]);
Packit 1c1d7e
            writeInt(f,ui->freq);
Packit 1c1d7e
          }
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
    // write urls
Packit 1c1d7e
    QIntDictIterator<URL> udi(m_urls);
Packit 1c1d7e
    URL *url;
Packit 1c1d7e
    for (udi.toFirst();(url=udi.current());++udi)
Packit 1c1d7e
    {
Packit 1c1d7e
      writeString(f,url->name);
Packit 1c1d7e
      writeString(f,url->url);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  delete[] urlOffsets;
Packit 1c1d7e
  delete[] wordStatOffsets;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
Packit 1c1d7e
//---------------------------------------------------------------------------
Packit 1c1d7e
// the following part is for writing an external search index
Packit 1c1d7e
Packit 1c1d7e
struct SearchDocEntry
Packit 1c1d7e
{
Packit 1c1d7e
  QCString type;
Packit 1c1d7e
  QCString name;
Packit 1c1d7e
  QCString args;
Packit 1c1d7e
  QCString extId;
Packit 1c1d7e
  QCString url;
Packit 1c1d7e
  GrowBuf  importantText;
Packit 1c1d7e
  GrowBuf  normalText;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
struct SearchIndexExternal::Private
Packit 1c1d7e
{
Packit 1c1d7e
  Private() : docEntries(12251) {}
Packit 1c1d7e
  SDict<SearchDocEntry> docEntries;
Packit 1c1d7e
  SearchDocEntry *current;
Packit 1c1d7e
};
Packit 1c1d7e
Packit 1c1d7e
SearchIndexExternal::SearchIndexExternal() : SearchIndexIntf(External)
Packit 1c1d7e
{
Packit 1c1d7e
  p = new SearchIndexExternal::Private;
Packit 1c1d7e
  p->docEntries.setAutoDelete(TRUE);
Packit 1c1d7e
  p->current=0;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
SearchIndexExternal::~SearchIndexExternal()
Packit 1c1d7e
{
Packit 1c1d7e
  //printf("p->docEntries.count()=%d\n",p->docEntries.count());
Packit 1c1d7e
  delete p;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
static QCString definitionToName(Definition *ctx)
Packit 1c1d7e
{
Packit 1c1d7e
  if (ctx && ctx->definitionType()==Definition::TypeMember)
Packit 1c1d7e
  {
Packit 1c1d7e
    MemberDef *md = (MemberDef*)ctx;
Packit 1c1d7e
    if (md->isFunction())
Packit 1c1d7e
      return "function";
Packit 1c1d7e
    else if (md->isSlot())
Packit 1c1d7e
      return "slot";
Packit 1c1d7e
    else if (md->isSignal())
Packit 1c1d7e
      return "signal";
Packit 1c1d7e
    else if (md->isVariable())
Packit 1c1d7e
      return "variable";
Packit 1c1d7e
    else if (md->isTypedef())
Packit 1c1d7e
      return "typedef";
Packit 1c1d7e
    else if (md->isEnumerate())
Packit 1c1d7e
      return "enum";
Packit 1c1d7e
    else if (md->isEnumValue())
Packit 1c1d7e
      return "enumvalue";
Packit 1c1d7e
    else if (md->isProperty())
Packit 1c1d7e
      return "property";
Packit 1c1d7e
    else if (md->isEvent())
Packit 1c1d7e
      return "event";
Packit 1c1d7e
    else if (md->isRelated() || md->isForeign())
Packit 1c1d7e
      return "related";
Packit 1c1d7e
    else if (md->isFriend())
Packit 1c1d7e
      return "friend";
Packit 1c1d7e
    else if (md->isDefine())
Packit 1c1d7e
      return "define";
Packit 1c1d7e
  }
Packit 1c1d7e
  else if (ctx)
Packit 1c1d7e
  {
Packit 1c1d7e
    switch(ctx->definitionType())
Packit 1c1d7e
    {
Packit 1c1d7e
      case Definition::TypeClass:
Packit 1c1d7e
        return ((ClassDef*)ctx)->compoundTypeString();
Packit 1c1d7e
      case Definition::TypeFile:
Packit 1c1d7e
        return "file";
Packit 1c1d7e
      case Definition::TypeNamespace:
Packit 1c1d7e
        return "namespace";
Packit 1c1d7e
      case Definition::TypeGroup:
Packit 1c1d7e
        return "group";
Packit 1c1d7e
      case Definition::TypePackage:
Packit 1c1d7e
        return "package";
Packit 1c1d7e
      case Definition::TypePage:
Packit 1c1d7e
        return "page";
Packit 1c1d7e
      case Definition::TypeDir:
Packit 1c1d7e
        return "dir";
Packit 1c1d7e
      default:
Packit 1c1d7e
        break;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  return "unknown";
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void SearchIndexExternal::setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile)
Packit 1c1d7e
{
Packit 1c1d7e
  QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID));
Packit 1c1d7e
  QCString baseName = isSourceFile ? ((FileDef*)ctx)->getSourceFileBase() : ctx->getOutputFileBase();
Packit 1c1d7e
  QCString url = baseName + Doxygen::htmlFileExtension;
Packit 1c1d7e
  if (anchor) url+=QCString("#")+anchor;
Packit 1c1d7e
  QCString key = extId+";"+url;
Packit 1c1d7e
Packit 1c1d7e
  p->current = p->docEntries.find(key);
Packit 1c1d7e
  //printf("setCurrentDoc(url=%s,isSourceFile=%d) current=%p\n",url.data(),isSourceFile,p->current);
Packit 1c1d7e
  if (!p->current)
Packit 1c1d7e
  {
Packit 1c1d7e
    SearchDocEntry *e = new SearchDocEntry;
Packit 1c1d7e
    e->type = isSourceFile ? QCString("source") : definitionToName(ctx);
Packit 1c1d7e
    e->name = ctx->qualifiedName();
Packit 1c1d7e
    if (ctx->definitionType()==Definition::TypeMember)
Packit 1c1d7e
    {
Packit 1c1d7e
      e->args = ((MemberDef*)ctx)->argsString();
Packit 1c1d7e
    }
Packit 1c1d7e
    e->extId = extId;
Packit 1c1d7e
    e->url  = url;
Packit 1c1d7e
    p->current = e;
Packit 1c1d7e
    p->docEntries.append(key,e);
Packit 1c1d7e
    //printf("searchIndexExt %s : %s\n",e->name.data(),e->url.data());
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void SearchIndexExternal::addWord(const char *word,bool hiPriority)
Packit 1c1d7e
{
Packit 1c1d7e
  if (word==0 || !isId(*word) || p->current==0) return;
Packit 1c1d7e
  GrowBuf *pText = hiPriority ? &p->current->importantText : &p->current->normalText;
Packit 1c1d7e
  if (pText->getPos()>0) pText->addChar(' ');
Packit 1c1d7e
  pText->addStr(word);
Packit 1c1d7e
  //printf("addWord %s\n",word);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void SearchIndexExternal::write(const char *fileName)
Packit 1c1d7e
{
Packit 1c1d7e
  QFile f(fileName);
Packit 1c1d7e
  if (f.open(IO_WriteOnly))
Packit 1c1d7e
  {
Packit 1c1d7e
    FTextStream t(&f);
Packit 1c1d7e
    t << "" << endl;
Packit 1c1d7e
    t << "<add>" << endl;
Packit 1c1d7e
    SDict<SearchDocEntry>::Iterator it(p->docEntries);
Packit 1c1d7e
    SearchDocEntry *doc;
Packit 1c1d7e
    for (it.toFirst();(doc=it.current());++it)
Packit 1c1d7e
    {
Packit 1c1d7e
      doc->normalText.addChar(0);    // make sure buffer ends with a 0 terminator
Packit 1c1d7e
      doc->importantText.addChar(0); // make sure buffer ends with a 0 terminator
Packit 1c1d7e
      t << "  <doc>" << endl;
Packit 1c1d7e
      t << "    <field name=\"type\">"     << doc->type << "</field>" << endl;
Packit 1c1d7e
      t << "    <field name=\"name\">"     << convertToXML(doc->name) << "</field>" << endl;
Packit 1c1d7e
      if (!doc->args.isEmpty())
Packit 1c1d7e
      {
Packit 1c1d7e
        t << "    <field name=\"args\">"     << convertToXML(doc->args) << "</field>" << endl;
Packit 1c1d7e
      }
Packit 1c1d7e
      if (!doc->extId.isEmpty())
Packit 1c1d7e
      {
Packit 1c1d7e
        t << "    <field name=\"tag\">"      << convertToXML(doc->extId)  << "</field>" << endl;
Packit 1c1d7e
      }
Packit 1c1d7e
      t << "    <field name=\"url\">"      << convertToXML(doc->url)  << "</field>" << endl;
Packit 1c1d7e
      t << "    <field name=\"keywords\">" << convertToXML(doc->importantText.get())  << "</field>" << endl;
Packit 1c1d7e
      t << "    <field name=\"text\">"     << convertToXML(doc->normalText.get())     << "</field>" << endl;
Packit 1c1d7e
      t << "  </doc>" << endl;
Packit 1c1d7e
    }
Packit 1c1d7e
    t << "</add>" << endl;
Packit 1c1d7e
  }
Packit 1c1d7e
  else
Packit 1c1d7e
  {
Packit 1c1d7e
    err("Failed to open file %s for writing!\n",fileName);
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
//---------------------------------------------------------------------------
Packit 1c1d7e
// the following part is for the javascript based search engine
Packit 1c1d7e
Packit 1c1d7e
#include "memberdef.h"
Packit 1c1d7e
#include "namespacedef.h"
Packit 1c1d7e
#include "pagedef.h"
Packit 1c1d7e
#include "classdef.h"
Packit 1c1d7e
#include "filedef.h"
Packit 1c1d7e
#include "language.h"
Packit 1c1d7e
#include "doxygen.h"
Packit 1c1d7e
#include "message.h"
Packit 1c1d7e
Packit 1c1d7e
static SearchIndexInfo g_searchIndexInfo[NUM_SEARCH_INDICES];
Packit 1c1d7e
Packit 1c1d7e
static void addMemberToSearchIndex(MemberDef *md)
Packit 1c1d7e
{
Packit 1c1d7e
  static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
Packit 1c1d7e
  bool isLinkable = md->isLinkable();
Packit 1c1d7e
  ClassDef *cd=0;
Packit 1c1d7e
  NamespaceDef *nd=0;
Packit 1c1d7e
  FileDef *fd=0;
Packit 1c1d7e
  GroupDef *gd=0;
Packit 1c1d7e
  if (isLinkable &&
Packit 1c1d7e
      (
Packit 1c1d7e
       ((cd=md->getClassDef()) && cd->isLinkable() && cd->templateMaster()==0) ||
Packit 1c1d7e
       ((gd=md->getGroupDef()) && gd->isLinkable())
Packit 1c1d7e
      )
Packit 1c1d7e
     )
Packit 1c1d7e
  {
Packit 1c1d7e
    QCString n = md->name();
Packit 1c1d7e
    if (!n.isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      uint letter = getUtf8CodeToLower(n,0);
Packit 1c1d7e
      bool isFriendToHide = hideFriendCompounds &&
Packit 1c1d7e
        (QCString(md->typeString())=="friend class" ||
Packit 1c1d7e
         QCString(md->typeString())=="friend struct" ||
Packit 1c1d7e
         QCString(md->typeString())=="friend union");
Packit 1c1d7e
      if (!(md->isFriend() && isFriendToHide))
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      if (md->isFunction() || md->isSlot() || md->isSignal())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isVariable())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_VARIABLES].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isTypedef())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isEnumerate())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_ENUMS].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isEnumValue())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isProperty())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isEvent())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_EVENTS].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isRelated() || md->isForeign() ||
Packit 1c1d7e
               (md->isFriend() && !isFriendToHide))
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_RELATED].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  else if (isLinkable &&
Packit 1c1d7e
      (((nd=md->getNamespaceDef()) && nd->isLinkable()) ||
Packit 1c1d7e
       ((fd=md->getFileDef())      && fd->isLinkable())
Packit 1c1d7e
      )
Packit 1c1d7e
     )
Packit 1c1d7e
  {
Packit 1c1d7e
    QCString n = md->name();
Packit 1c1d7e
    if (!n.isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      uint letter = getUtf8CodeToLower(n,0);
Packit 1c1d7e
      g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,md);
Packit 1c1d7e
Packit 1c1d7e
      if (md->isFunction())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isVariable())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_VARIABLES].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isTypedef())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isEnumerate())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_ENUMS].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isEnumValue())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
      else if (md->isDefine())
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_DEFINES].symbolList.append(letter,md);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
// see also function convertToId() in search.js, which should match in
Packit 1c1d7e
// behaviour
Packit 1c1d7e
static QCString searchId(const QCString &s)
Packit 1c1d7e
{
Packit 1c1d7e
  int c;
Packit 1c1d7e
  uint i;
Packit 1c1d7e
  QCString result;
Packit 1c1d7e
  for (i=0;i
Packit 1c1d7e
  {
Packit 1c1d7e
    c=s.at(i);
Packit 1c1d7e
    if (c>0x7f || c<0) // part of multibyte character
Packit 1c1d7e
    {
Packit 1c1d7e
      result+=(char)c;
Packit 1c1d7e
    }
Packit 1c1d7e
    else if (isalnum(c)) // simply alpha numerical character
Packit 1c1d7e
    {
Packit 1c1d7e
      result+=(char)tolower(c);
Packit 1c1d7e
    }
Packit 1c1d7e
    else // other 'unprintable' characters
Packit 1c1d7e
    {
Packit 1c1d7e
      char val[4];
Packit 1c1d7e
      sprintf(val,"_%02x",(uchar)c);
Packit 1c1d7e
      result+=val;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  return result;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void createJavascriptSearchIndex()
Packit 1c1d7e
{
Packit 1c1d7e
  // set index names
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_ALL].name        = "all";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_CLASSES].name    = "classes";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].name = "namespaces";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_FILES].name      = "files";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].name  = "functions";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_VARIABLES].name  = "variables";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].name   = "typedefs";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_ENUMS].name      = "enums";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].name = "enumvalues";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].name = "properties";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_EVENTS].name     = "events";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_RELATED].name    = "related";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_DEFINES].name    = "defines";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_GROUPS].name     = "groups";
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_PAGES].name      = "pages";
Packit 1c1d7e
Packit 1c1d7e
  // set index texts
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_ALL].text        = theTranslator->trAll();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_CLASSES].text    = theTranslator->trClasses();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].text = theTranslator->trNamespace(TRUE,FALSE);
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_FILES].text      = theTranslator->trFile(TRUE,FALSE);
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].text  = theTranslator->trFunctions();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_VARIABLES].text  = theTranslator->trVariables();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].text   = theTranslator->trTypedefs();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_ENUMS].text      = theTranslator->trEnumerations();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].text = theTranslator->trEnumerationValues();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].text = theTranslator->trProperties();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_EVENTS].text     = theTranslator->trEvents();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_RELATED].text    = theTranslator->trFriends();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_DEFINES].text    = theTranslator->trDefines();
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_GROUPS].text     = theTranslator->trGroup(TRUE,FALSE);
Packit 1c1d7e
  g_searchIndexInfo[SEARCH_INDEX_PAGES].text      = theTranslator->trPage(TRUE,FALSE);
Packit 1c1d7e
Packit 1c1d7e
  // add symbols to letter -> symbol list map
Packit 1c1d7e
Packit 1c1d7e
  // index classes
Packit 1c1d7e
  ClassSDict::Iterator cli(*Doxygen::classSDict);
Packit 1c1d7e
  ClassDef *cd;
Packit 1c1d7e
  for (;(cd=cli.current());++cli)
Packit 1c1d7e
  {
Packit 1c1d7e
    uint letter = getUtf8CodeToLower(cd->localName(),0);
Packit 1c1d7e
    if (cd->isLinkable() && isId(letter))
Packit 1c1d7e
    {
Packit 1c1d7e
      g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,cd);
Packit 1c1d7e
      g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // index namespaces
Packit 1c1d7e
  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
Packit 1c1d7e
  NamespaceDef *nd;
Packit 1c1d7e
  for (;(nd=nli.current());++nli)
Packit 1c1d7e
  {
Packit 1c1d7e
    uint letter = getUtf8CodeToLower(nd->name(),0);
Packit 1c1d7e
    if (nd->isLinkable() && isId(letter))
Packit 1c1d7e
    {
Packit 1c1d7e
      g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,nd);
Packit 1c1d7e
      g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].symbolList.append(letter,nd);
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // index files
Packit 1c1d7e
  FileNameListIterator fnli(*Doxygen::inputNameList);
Packit 1c1d7e
  FileName *fn;
Packit 1c1d7e
  for (;(fn=fnli.current());++fnli)
Packit 1c1d7e
  {
Packit 1c1d7e
    FileNameIterator fni(*fn);
Packit 1c1d7e
    FileDef *fd;
Packit 1c1d7e
    for (;(fd=fni.current());++fni)
Packit 1c1d7e
    {
Packit 1c1d7e
      uint letter = getUtf8CodeToLower(fd->name(),0);
Packit 1c1d7e
      if (fd->isLinkable() && isId(letter))
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,fd);
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_FILES].symbolList.append(letter,fd);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // index class members
Packit 1c1d7e
  {
Packit 1c1d7e
    MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
Packit 1c1d7e
    MemberName *mn;
Packit 1c1d7e
    // for each member name
Packit 1c1d7e
    for (mnli.toFirst();(mn=mnli.current());++mnli)
Packit 1c1d7e
    {
Packit 1c1d7e
      MemberDef *md;
Packit 1c1d7e
      MemberNameIterator mni(*mn);
Packit 1c1d7e
      // for each member definition
Packit 1c1d7e
      for (mni.toFirst();(md=mni.current());++mni)
Packit 1c1d7e
      {
Packit 1c1d7e
        addMemberToSearchIndex(md);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // index file/namespace members
Packit 1c1d7e
  {
Packit 1c1d7e
    MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
Packit 1c1d7e
    MemberName *mn;
Packit 1c1d7e
    // for each member name
Packit 1c1d7e
    for (fnli.toFirst();(mn=fnli.current());++fnli)
Packit 1c1d7e
    {
Packit 1c1d7e
      MemberDef *md;
Packit 1c1d7e
      MemberNameIterator mni(*mn);
Packit 1c1d7e
      // for each member definition
Packit 1c1d7e
      for (mni.toFirst();(md=mni.current());++mni)
Packit 1c1d7e
      {
Packit 1c1d7e
        addMemberToSearchIndex(md);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // index groups
Packit 1c1d7e
  GroupSDict::Iterator gli(*Doxygen::groupSDict);
Packit 1c1d7e
  GroupDef *gd;
Packit 1c1d7e
  for (gli.toFirst();(gd=gli.current());++gli)
Packit 1c1d7e
  {
Packit 1c1d7e
    if (gd->isLinkable())
Packit 1c1d7e
    {
Packit 1c1d7e
      QCString title = gd->groupTitle();
Packit 1c1d7e
      if (!title.isEmpty()) // TODO: able searching for all word in the title
Packit 1c1d7e
      {
Packit 1c1d7e
        uchar charCode = title.at(0);
Packit 1c1d7e
        uint letter = charCode<128 ? tolower(charCode) : charCode;
Packit 1c1d7e
        if (isId(letter))
Packit 1c1d7e
        {
Packit 1c1d7e
          g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,gd);
Packit 1c1d7e
          g_searchIndexInfo[SEARCH_INDEX_GROUPS].symbolList.append(letter,gd);
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // index pages
Packit 1c1d7e
  PageSDict::Iterator pdi(*Doxygen::pageSDict);
Packit 1c1d7e
  PageDef *pd=0;
Packit 1c1d7e
  for (pdi.toFirst();(pd=pdi.current());++pdi)
Packit 1c1d7e
  {
Packit 1c1d7e
    if (pd->isLinkable())
Packit 1c1d7e
    {
Packit 1c1d7e
      QCString title = pd->title();
Packit 1c1d7e
      if (!title.isEmpty())
Packit 1c1d7e
      {
Packit 1c1d7e
        uchar charCode = title.at(0);
Packit 1c1d7e
        uint letter = charCode<128 ? tolower(charCode) : charCode;
Packit 1c1d7e
        if (isId(letter))
Packit 1c1d7e
        {
Packit 1c1d7e
          g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,pd);
Packit 1c1d7e
          g_searchIndexInfo[SEARCH_INDEX_PAGES].symbolList.append(letter,pd);
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  if (Doxygen::mainPage)
Packit 1c1d7e
  {
Packit 1c1d7e
    QCString title = Doxygen::mainPage->title();
Packit 1c1d7e
    if (!title.isEmpty())
Packit 1c1d7e
    {
Packit 1c1d7e
      uchar charCode = title.at(0);
Packit 1c1d7e
      uint letter = charCode<128 ? tolower(charCode) : charCode;
Packit 1c1d7e
      if (isId(letter))
Packit 1c1d7e
      {
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,Doxygen::mainPage);
Packit 1c1d7e
        g_searchIndexInfo[SEARCH_INDEX_PAGES].symbolList.append(letter,Doxygen::mainPage);
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  // sort all lists
Packit 1c1d7e
  int i;
Packit 1c1d7e
  for (i=0;i
Packit 1c1d7e
  {
Packit 1c1d7e
    SIntDict<SearchIndexList>::Iterator it(g_searchIndexInfo[i].symbolList);
Packit 1c1d7e
    SearchIndexList *sl;
Packit 1c1d7e
    for (it.toFirst();(sl=it.current());++it)
Packit 1c1d7e
    {
Packit 1c1d7e
      sl->sort();
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void writeJavascriptSearchIndex()
Packit 1c1d7e
{
Packit 1c1d7e
  int i;
Packit 1c1d7e
  // write index files
Packit 1c1d7e
  QCString searchDirName = Config_getString(HTML_OUTPUT)+"/search";
Packit 1c1d7e
Packit 1c1d7e
  for (i=0;i
Packit 1c1d7e
  {
Packit 1c1d7e
    SIntDict<SearchIndexList>::Iterator it(g_searchIndexInfo[i].symbolList);
Packit 1c1d7e
    SearchIndexList *sl;
Packit 1c1d7e
    int p=0;
Packit 1c1d7e
    for (it.toFirst();(sl=it.current());++it,++p) // for each letter
Packit 1c1d7e
    {
Packit 1c1d7e
      QCString baseName;
Packit 1c1d7e
      baseName.sprintf("%s_%x",g_searchIndexInfo[i].name.data(),p);
Packit 1c1d7e
Packit 1c1d7e
      QCString fileName = searchDirName + "/"+baseName+".html";
Packit 1c1d7e
      QCString dataFileName = searchDirName + "/"+baseName+".js";
Packit 1c1d7e
Packit 1c1d7e
      QFile outFile(fileName);
Packit 1c1d7e
      QFile dataOutFile(dataFileName);
Packit 1c1d7e
      if (outFile.open(IO_WriteOnly) && dataOutFile.open(IO_WriteOnly))
Packit 1c1d7e
      {
Packit 1c1d7e
        {
Packit 1c1d7e
          FTextStream t(&outFile);
Packit 1c1d7e
Packit 1c1d7e
          t << "
Packit 1c1d7e
            " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
Packit 1c1d7e
          t << "<html><head><title></title>" << endl;
Packit 1c1d7e
          t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl;
Packit 1c1d7e
          t << "<meta name=\"generator\" content=\"Doxygen " << versionString << "\"/>" << endl;
Packit 1c1d7e
          t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl;
Packit 1c1d7e
          t << "<script type=\"text/javascript\" src=\"" << baseName << ".js\"></script>" << endl;
Packit 1c1d7e
          t << "<script type=\"text/javascript\" src=\"search.js\"></script>" << endl;
Packit 1c1d7e
          t << "</head>" << endl;
Packit 1c1d7e
          t << "<body class=\"SRPage\">" << endl;
Packit 1c1d7e
          t << "
" << endl;
Packit 1c1d7e
          t << "
" << theTranslator->trLoading() << "
" << endl;
Packit 1c1d7e
          t << "
" << endl; // here the results will be inserted
Packit 1c1d7e
          t << "<script type=\"text/javascript\">
Packit 1c1d7e
					t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n";
Packit 1c1d7e
          t << "createResults();" << endl; // this function will insert the results
Packit 1c1d7e
					t << "/* @license-end */\n";
Packit 1c1d7e
          t << "--></script>" << endl;
Packit 1c1d7e
          t << "
"
Packit 1c1d7e
            << theTranslator->trSearching() << "" << endl;
Packit 1c1d7e
          t << "
"
Packit 1c1d7e
            << theTranslator->trNoMatches() << "" << endl;
Packit 1c1d7e
Packit 1c1d7e
          t << "<script type=\"text/javascript\">
Packit 1c1d7e
					t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n";
Packit 1c1d7e
          t << "document.getElementById(\"Loading\").style.display=\"none\";" << endl;
Packit 1c1d7e
          t << "document.getElementById(\"NoMatches\").style.display=\"none\";" << endl;
Packit 1c1d7e
          t << "var searchResults = new SearchResults(\"searchResults\");" << endl;
Packit 1c1d7e
          t << "searchResults.Search();" << endl;
Packit 1c1d7e
					t << "/* @license-end */\n";
Packit 1c1d7e
          t << "--></script>" << endl;
Packit 1c1d7e
          t << "" << endl; // SRIndex
Packit 1c1d7e
          t << "</body>" << endl;
Packit 1c1d7e
          t << "</html>" << endl;
Packit 1c1d7e
        }
Packit 1c1d7e
        FTextStream ti(&dataOutFile);
Packit 1c1d7e
Packit 1c1d7e
        ti << "var searchData=" << endl;
Packit 1c1d7e
        // format
Packit 1c1d7e
        // searchData[] = array of items
Packit 1c1d7e
        // searchData[x][0] = id
Packit 1c1d7e
        // searchData[x][1] = [ name + child1 + child2 + .. ]
Packit 1c1d7e
        // searchData[x][1][0] = name as shown
Packit 1c1d7e
        // searchData[x][1][y+1] = info for child y
Packit 1c1d7e
        // searchData[x][1][y+1][0] = url
Packit 1c1d7e
        // searchData[x][1][y+1][1] = 1 => target="_parent"
Packit 1c1d7e
        // searchData[x][1][y+1][2] = scope
Packit 1c1d7e
Packit 1c1d7e
        ti << "[" << endl;
Packit 1c1d7e
        bool firstEntry=TRUE;
Packit 1c1d7e
Packit 1c1d7e
        SDict<SearchDefinitionList>::Iterator li(*sl);
Packit 1c1d7e
        SearchDefinitionList *dl;
Packit 1c1d7e
        int itemCount=0;
Packit 1c1d7e
        for (li.toFirst();(dl=li.current());++li)
Packit 1c1d7e
        {
Packit 1c1d7e
          Definition *d = dl->getFirst();
Packit 1c1d7e
Packit 1c1d7e
          if (!firstEntry)
Packit 1c1d7e
          {
Packit 1c1d7e
            ti << "," << endl;
Packit 1c1d7e
          }
Packit 1c1d7e
          firstEntry=FALSE;
Packit 1c1d7e
Packit 1c1d7e
          ti << "  ['" << dl->id() << "',['" << convertToXML(dl->name()) << "',[";
Packit 1c1d7e
Packit 1c1d7e
          if (dl->count()==1) // item with a unique name
Packit 1c1d7e
          {
Packit 1c1d7e
            MemberDef  *md   = 0;
Packit 1c1d7e
            bool isMemberDef = d->definitionType()==Definition::TypeMember;
Packit 1c1d7e
            if (isMemberDef) md = (MemberDef*)d;
Packit 1c1d7e
            QCString anchor = d->anchor();
Packit 1c1d7e
Packit 1c1d7e
            ti << "'" << externalRef("../",d->getReference(),TRUE)
Packit 1c1d7e
              << d->getOutputFileBase() << Doxygen::htmlFileExtension;
Packit 1c1d7e
            if (!anchor.isEmpty())
Packit 1c1d7e
            {
Packit 1c1d7e
              ti << "#" << anchor;
Packit 1c1d7e
            }
Packit 1c1d7e
            ti << "',";
Packit 1c1d7e
Packit 1c1d7e
            static bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
Packit 1c1d7e
            if (!extLinksInWindow || d->getReference().isEmpty())
Packit 1c1d7e
            {
Packit 1c1d7e
              ti << "1,";
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              ti << "0,";
Packit 1c1d7e
            }
Packit 1c1d7e
Packit 1c1d7e
            if (d->getOuterScope()!=Doxygen::globalScope)
Packit 1c1d7e
            {
Packit 1c1d7e
              ti << "'" << convertToXML(d->getOuterScope()->name()) << "'";
Packit 1c1d7e
            }
Packit 1c1d7e
            else if (md)
Packit 1c1d7e
            {
Packit 1c1d7e
              FileDef *fd = md->getBodyDef();
Packit 1c1d7e
              if (fd==0) fd = md->getFileDef();
Packit 1c1d7e
              if (fd)
Packit 1c1d7e
              {
Packit 1c1d7e
                ti << "'" << convertToXML(fd->localName()) << "'";
Packit 1c1d7e
              }
Packit 1c1d7e
            }
Packit 1c1d7e
            else
Packit 1c1d7e
            {
Packit 1c1d7e
              ti << "''";
Packit 1c1d7e
            }
Packit 1c1d7e
            ti << "]]";
Packit 1c1d7e
          }
Packit 1c1d7e
          else // multiple items with the same name
Packit 1c1d7e
          {
Packit 1c1d7e
            QListIterator<Definition> di(*dl);
Packit 1c1d7e
            bool overloadedFunction = FALSE;
Packit 1c1d7e
            Definition *prevScope = 0;
Packit 1c1d7e
            int childCount=0;
Packit 1c1d7e
            for (di.toFirst();(d=di.current());)
Packit 1c1d7e
            {
Packit 1c1d7e
              ++di;
Packit 1c1d7e
              Definition *scope     = d->getOuterScope();
Packit 1c1d7e
              Definition *next      = di.current();
Packit 1c1d7e
              Definition *nextScope = 0;
Packit 1c1d7e
              MemberDef  *md        = 0;
Packit 1c1d7e
              bool isMemberDef = d->definitionType()==Definition::TypeMember;
Packit 1c1d7e
              if (isMemberDef) md = (MemberDef*)d;
Packit 1c1d7e
              if (next) nextScope = next->getOuterScope();
Packit 1c1d7e
              QCString anchor = d->anchor();
Packit 1c1d7e
Packit 1c1d7e
              if (childCount>0)
Packit 1c1d7e
              {
Packit 1c1d7e
                ti << "],[";
Packit 1c1d7e
              }
Packit 1c1d7e
              ti << "'" << externalRef("../",d->getReference(),TRUE)
Packit 1c1d7e
                << d->getOutputFileBase() << Doxygen::htmlFileExtension;
Packit 1c1d7e
              if (!anchor.isEmpty())
Packit 1c1d7e
              {
Packit 1c1d7e
                ti << "#" << anchor;
Packit 1c1d7e
              }
Packit 1c1d7e
              ti << "',";
Packit 1c1d7e
Packit 1c1d7e
              static bool extLinksInWindow = Config_getBool(EXT_LINKS_IN_WINDOW);
Packit 1c1d7e
              if (!extLinksInWindow || d->getReference().isEmpty())
Packit 1c1d7e
              {
Packit 1c1d7e
                ti << "1,";
Packit 1c1d7e
              }
Packit 1c1d7e
              else
Packit 1c1d7e
              {
Packit 1c1d7e
                ti << "0,";
Packit 1c1d7e
              }
Packit 1c1d7e
              bool found=FALSE;
Packit 1c1d7e
              overloadedFunction = ((prevScope!=0 && scope==prevScope) ||
Packit 1c1d7e
                  (scope && scope==nextScope)
Packit 1c1d7e
                  ) && md &&
Packit 1c1d7e
                (md->isFunction() || md->isSlot());
Packit 1c1d7e
              QCString prefix;
Packit 1c1d7e
              if (md) prefix=convertToXML(md->localName());
Packit 1c1d7e
              if (overloadedFunction) // overloaded member function
Packit 1c1d7e
              {
Packit 1c1d7e
                prefix+=convertToXML(md->argsString());
Packit 1c1d7e
                // show argument list to disambiguate overloaded functions
Packit 1c1d7e
              }
Packit 1c1d7e
              else if (md) // unique member function
Packit 1c1d7e
              {
Packit 1c1d7e
                prefix+="()"; // only to show it is a function
Packit 1c1d7e
              }
Packit 1c1d7e
              QCString name;
Packit 1c1d7e
              if (d->definitionType()==Definition::TypeClass)
Packit 1c1d7e
              {
Packit 1c1d7e
                name = convertToXML(((ClassDef*)d)->displayName());
Packit 1c1d7e
                found = TRUE;
Packit 1c1d7e
              }
Packit 1c1d7e
              else if (d->definitionType()==Definition::TypeNamespace)
Packit 1c1d7e
              {
Packit 1c1d7e
                name = convertToXML(((NamespaceDef*)d)->displayName());
Packit 1c1d7e
                found = TRUE;
Packit 1c1d7e
              }
Packit 1c1d7e
              else if (scope==0 || scope==Doxygen::globalScope) // in global scope
Packit 1c1d7e
              {
Packit 1c1d7e
                if (md)
Packit 1c1d7e
                {
Packit 1c1d7e
                  FileDef *fd = md->getBodyDef();
Packit 1c1d7e
                  if (fd==0) fd = md->getFileDef();
Packit 1c1d7e
                  if (fd)
Packit 1c1d7e
                  {
Packit 1c1d7e
                    if (!prefix.isEmpty()) prefix+=": ";
Packit 1c1d7e
                    name = prefix + convertToXML(fd->localName());
Packit 1c1d7e
                    found = TRUE;
Packit 1c1d7e
                  }
Packit 1c1d7e
                }
Packit 1c1d7e
              }
Packit 1c1d7e
              else if (md && (md->getClassDef() || md->getNamespaceDef()))
Packit 1c1d7e
                // member in class or namespace scope
Packit 1c1d7e
              {
Packit 1c1d7e
                SrcLangExt lang = md->getLanguage();
Packit 1c1d7e
                name = convertToXML(d->getOuterScope()->qualifiedName())
Packit 1c1d7e
                  + getLanguageSpecificSeparator(lang) + prefix;
Packit 1c1d7e
                found = TRUE;
Packit 1c1d7e
              }
Packit 1c1d7e
              else if (scope) // some thing else? -> show scope
Packit 1c1d7e
              {
Packit 1c1d7e
                name = prefix + convertToXML(scope->name());
Packit 1c1d7e
                found = TRUE;
Packit 1c1d7e
              }
Packit 1c1d7e
              if (!found) // fallback
Packit 1c1d7e
              {
Packit 1c1d7e
                name = prefix + "("+theTranslator->trGlobalNamespace()+")";
Packit 1c1d7e
              }
Packit 1c1d7e
Packit 1c1d7e
              ti << "'" << name << "'";
Packit 1c1d7e
Packit 1c1d7e
              prevScope = scope;
Packit 1c1d7e
              childCount++;
Packit 1c1d7e
            }
Packit 1c1d7e
Packit 1c1d7e
            ti << "]]";
Packit 1c1d7e
          }
Packit 1c1d7e
          ti << "]";
Packit 1c1d7e
          itemCount++;
Packit 1c1d7e
        }
Packit 1c1d7e
        if (!firstEntry)
Packit 1c1d7e
        {
Packit 1c1d7e
          ti << endl;
Packit 1c1d7e
        }
Packit 1c1d7e
Packit 1c1d7e
        ti << "];" << endl;
Packit 1c1d7e
Packit 1c1d7e
      }
Packit 1c1d7e
      else
Packit 1c1d7e
      {
Packit 1c1d7e
        err("Failed to open file '%s' for writing...\n",fileName.data());
Packit 1c1d7e
      }
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
Packit 1c1d7e
  {
Packit 1c1d7e
    QFile f(searchDirName+"/searchdata.js");
Packit 1c1d7e
    if (f.open(IO_WriteOnly))
Packit 1c1d7e
    {
Packit 1c1d7e
      FTextStream t(&f);
Packit 1c1d7e
      t << "var indexSectionsWithContent =" << endl;
Packit 1c1d7e
      t << "{" << endl;
Packit 1c1d7e
      bool first=TRUE;
Packit 1c1d7e
      int j=0;
Packit 1c1d7e
      for (i=0;i
Packit 1c1d7e
      {
Packit 1c1d7e
        if (g_searchIndexInfo[i].symbolList.count()>0)
Packit 1c1d7e
        {
Packit 1c1d7e
          if (!first) t << "," << endl;
Packit 1c1d7e
          t << "  " << j << ": \"";
Packit 1c1d7e
Packit 1c1d7e
          SIntDict<SearchIndexList>::Iterator it(g_searchIndexInfo[i].symbolList);
Packit 1c1d7e
          SearchIndexList *sl;
Packit 1c1d7e
          for (it.toFirst();(sl=it.current());++it) // for each letter
Packit 1c1d7e
          {
Packit 1c1d7e
            t << QString( QChar( sl->letter() ) ).utf8();
Packit 1c1d7e
          }
Packit 1c1d7e
          t << "\"";
Packit 1c1d7e
          first=FALSE;
Packit 1c1d7e
          j++;
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
      if (!first) t << "\n";
Packit 1c1d7e
      t << "};" << endl << endl;
Packit 1c1d7e
      t << "var indexSectionNames =" << endl;
Packit 1c1d7e
      t << "{" << endl;
Packit 1c1d7e
      first=TRUE;
Packit 1c1d7e
      j=0;
Packit 1c1d7e
      for (i=0;i
Packit 1c1d7e
      {
Packit 1c1d7e
        if (g_searchIndexInfo[i].symbolList.count()>0)
Packit 1c1d7e
        {
Packit 1c1d7e
          if (!first) t << "," << endl;
Packit 1c1d7e
          t << "  " << j << ": \"" << g_searchIndexInfo[i].name << "\"";
Packit 1c1d7e
          first=FALSE;
Packit 1c1d7e
          j++;
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
      if (!first) t << "\n";
Packit 1c1d7e
      t << "};" << endl << endl;
Packit 1c1d7e
      t << "var indexSectionLabels =" << endl;
Packit 1c1d7e
      t << "{" << endl;
Packit 1c1d7e
      first=TRUE;
Packit 1c1d7e
      j=0;
Packit 1c1d7e
      for (i=0;i
Packit 1c1d7e
      {
Packit 1c1d7e
        if (g_searchIndexInfo[i].symbolList.count()>0)
Packit 1c1d7e
        {
Packit 1c1d7e
          if (!first) t << "," << endl;
Packit 1c1d7e
          t << "  " << j << ": \"" << convertToXML(g_searchIndexInfo[i].text) << "\"";
Packit 1c1d7e
          first=FALSE;
Packit 1c1d7e
          j++;
Packit 1c1d7e
        }
Packit 1c1d7e
      }
Packit 1c1d7e
      if (!first) t << "\n";
Packit 1c1d7e
      t << "};" << endl << endl;
Packit 1c1d7e
    }
Packit 1c1d7e
    ResourceMgr::instance().copyResource("search.js",searchDirName);
Packit 1c1d7e
  }
Packit 1c1d7e
  {
Packit 1c1d7e
    QFile f(searchDirName+"/nomatches.html");
Packit 1c1d7e
    if (f.open(IO_WriteOnly))
Packit 1c1d7e
    {
Packit 1c1d7e
      FTextStream t(&f);
Packit 1c1d7e
      t << "
Packit 1c1d7e
           "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
Packit 1c1d7e
      t << "<html><head><title></title>" << endl;
Packit 1c1d7e
      t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl;
Packit 1c1d7e
      t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl;
Packit 1c1d7e
      t << "<script type=\"text/javascript\" src=\"search.js\"></script>" << endl;
Packit 1c1d7e
      t << "</head>" << endl;
Packit 1c1d7e
      t << "<body class=\"SRPage\">" << endl;
Packit 1c1d7e
      t << "
" << endl;
Packit 1c1d7e
      t << "
"
Packit 1c1d7e
        << theTranslator->trNoMatches() << "" << endl;
Packit 1c1d7e
      t << "" << endl;
Packit 1c1d7e
      t << "</body>" << endl;
Packit 1c1d7e
      t << "</html>" << endl;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  Doxygen::indexList->addStyleSheetFile("search/search.js");
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
const SearchIndexInfo *getSearchIndices()
Packit 1c1d7e
{
Packit 1c1d7e
  return g_searchIndexInfo;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
//---------------------------------------------------------------------------------------------
Packit 1c1d7e
Packit 1c1d7e
SearchIndexList::SearchIndexList(uint letter)
Packit 1c1d7e
  : SDict< SearchDefinitionList >(17,FALSE), m_letter(letter)
Packit 1c1d7e
{
Packit 1c1d7e
  setAutoDelete(TRUE);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
SearchIndexList::~SearchIndexList()
Packit 1c1d7e
{
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void SearchIndexList::append(Definition *d)
Packit 1c1d7e
{
Packit 1c1d7e
  QCString dispName = d->localName();
Packit 1c1d7e
  SearchDefinitionList *l = find(dispName);
Packit 1c1d7e
  if (l==0)
Packit 1c1d7e
  {
Packit 1c1d7e
    if (d->definitionType()==Definition::TypeGroup)
Packit 1c1d7e
    {
Packit 1c1d7e
      dispName = ((GroupDef*)d)->groupTitle();
Packit 1c1d7e
    }
Packit 1c1d7e
    else if (d->definitionType()==Definition::TypePage)
Packit 1c1d7e
    {
Packit 1c1d7e
      dispName = ((PageDef*)d)->title();
Packit 1c1d7e
    }
Packit 1c1d7e
    l=new SearchDefinitionList(searchId(dispName),dispName);
Packit 1c1d7e
    SDict< SearchDefinitionList >::append(dispName,l);
Packit 1c1d7e
  }
Packit 1c1d7e
  l->append(d);
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
uint SearchIndexList::letter() const
Packit 1c1d7e
{
Packit 1c1d7e
  return m_letter;
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
int SearchIndexList::compareValues(const SearchDefinitionList *md1, const SearchDefinitionList *md2) const
Packit 1c1d7e
{
Packit 1c1d7e
  QCString n1 = md1->getFirst()->localName();
Packit 1c1d7e
  QCString n2 = md2->getFirst()->localName();
Packit 1c1d7e
  return qstricmp(n1.data(),n2.data());
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
//---------------------------------------------------------------------------------------------
Packit 1c1d7e
Packit 1c1d7e
void initSearchIndexer()
Packit 1c1d7e
{
Packit 1c1d7e
  static bool searchEngine      = Config_getBool(SEARCHENGINE);
Packit 1c1d7e
  static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH);
Packit 1c1d7e
  static bool externalSearch    = Config_getBool(EXTERNAL_SEARCH);
Packit 1c1d7e
  if (searchEngine && serverBasedSearch)
Packit 1c1d7e
  {
Packit 1c1d7e
    if (externalSearch) // external tools produce search index and engine
Packit 1c1d7e
    {
Packit 1c1d7e
      Doxygen::searchIndex = new SearchIndexExternal;
Packit 1c1d7e
    }
Packit 1c1d7e
    else // doxygen produces search index and engine
Packit 1c1d7e
    {
Packit 1c1d7e
      Doxygen::searchIndex = new SearchIndex;
Packit 1c1d7e
    }
Packit 1c1d7e
  }
Packit 1c1d7e
  else // no search engine or pure javascript based search function
Packit 1c1d7e
  {
Packit 1c1d7e
    Doxygen::searchIndex = 0;
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
void finializeSearchIndexer()
Packit 1c1d7e
{
Packit 1c1d7e
  delete Doxygen::searchIndex;
Packit 1c1d7e
}