|
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 |
}
|