From 6bb0d2908b4ca7908a8e655a5abcf7615a5f4c77 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Tue, 30 Dec 2014 13:57:27 +0100 Subject: [PATCH] Added javascript search engine data to the template context --- src/context.cpp | 502 +++++++++++++++++++++++++++ src/context.h | 172 ++++++++- src/doxygen.cpp | 9 +- src/searchindex.cpp | 331 ++++++++---------- src/searchindex.h | 53 +++ src/template.cpp | 42 ++- templates/html/htmlallmembers.tpl | 6 +- templates/html/htmlbase.tpl | 3 + templates/html/htmlclasses.tpl | 2 +- templates/html/htmljssearchdata.tpl | 31 ++ templates/html/htmljssearchindex.tpl | 15 + templates/html/htmllayout.tpl | 17 +- templates/html/htmlsearchresult.tpl | 27 ++ templates/html/htmltabs.tpl | 2 + 14 files changed, 1000 insertions(+), 212 deletions(-) create mode 100644 templates/html/htmljssearchdata.tpl create mode 100644 templates/html/htmljssearchindex.tpl create mode 100644 templates/html/htmlsearchresult.tpl diff --git a/src/context.cpp b/src/context.cpp index e7c14d56862..72065350242 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -43,6 +43,7 @@ #include "portable.h" #include "arguments.h" #include "groupdef.h" +#include "searchindex.h" // TODO: pass the current file to Dot*::writeGraph, so the user can put dot graphs in other // files as well @@ -882,6 +883,18 @@ class TranslateContext::Private : public PropertyMapper { return theTranslator->trDefines(); } + TemplateVariant loading() const + { + return theTranslator->trLoading(); + } + TemplateVariant searching() const + { + return theTranslator->trSearching(); + } + TemplateVariant noMatches() const + { + return theTranslator->trNoMatches(); + } Private() { //%% string generatedBy @@ -1030,6 +1043,12 @@ class TranslateContext::Private : public PropertyMapper addProperty("gotoGraphicalHierarchy",this,&Private::gotoGraphicalHierarchy); //%% string gotoTextualHierarchy addProperty("gotoTextualHierarchy",this,&Private::gotoTextualHierarchy); + //%% string loading + addProperty("loading", this,&Private::loading); + //%% string searching + addProperty("searching", this,&Private::searching); + //%% string noMatches + addProperty("noMatches", this,&Private::noMatches); m_javaOpt = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); m_fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); @@ -8064,6 +8083,486 @@ TemplateListIntf::ConstIterator *ArgumentListContext::createIterator() const return p->createIterator(); } +//------------------------------------------------------------------------ + +// SymbolIndex +// - name: string +// - letter: string +// - symbolGroups: SymbolGroupList +// SymbolGroupList: list of SymbolGroups +// SymbolGroup +// - id +// - name +// - symbols: SymbolList +// SymbolList: list of Symbols +// Symbol +// - obj +// - scope +// - relPath + +//------------------------------------------------------------------------ + +//%% struct SymbolGroup: search group of similar symbols +//%% { +class SymbolContext::Private : public PropertyMapper +{ + public: + Private(const Definition *d,const Definition *prev, + const Definition *next) : m_def(d), m_prevDef(prev), m_nextDef(next) + { + addProperty("fileName",this,&Private::fileName); + addProperty("anchor", this,&Private::anchor); + addProperty("scope", this,&Private::scope); + addProperty("relPath", this,&Private::relPath); + } + TemplateVariant fileName() const + { + return m_def->getOutputFileBase(); + } + TemplateVariant anchor() const + { + return m_def->anchor(); + } + TemplateVariant scope() const + { + const Definition *scope = m_def->getOuterScope(); + const Definition *next = m_nextDef; + const Definition *prev = m_prevDef; + const Definition *nextScope = next ? next->getOuterScope() : 0; + const Definition *prevScope = prev ? prev->getOuterScope() : 0; + bool isMemberDef = m_def->definitionType()==Definition::TypeMember; + const MemberDef *md = isMemberDef ? (const MemberDef*)m_def : 0; + bool isFunctionLike = md && (md->isFunction() || md->isSlot() || md->isSignal()); + bool overloadedFunction = isFunctionLike && + ((prevScope!=0 && scope==prevScope) || (scope && scope==nextScope)); + QCString prefix; + if (md) prefix=md->localName(); + if (overloadedFunction) // overloaded member function + { + prefix+=md->argsString(); + // show argument list to disambiguate overloaded functions + } + else if (md && isFunctionLike) // unique member function + { + prefix+="()"; // only to show it is a function + } + bool found=FALSE; + QCString name; + if (m_def->definitionType()==Definition::TypeClass) + { + name = m_def->displayName(); + found = TRUE; + } + else if (m_def->definitionType()==Definition::TypeNamespace) + { + name = m_def->displayName(); + found = TRUE; + } + else if (scope==0 || scope==Doxygen::globalScope) // in global scope + { + if (md) + { + FileDef *fd = md->getBodyDef(); + if (fd==0) fd = md->getFileDef(); + if (fd) + { + if (!prefix.isEmpty()) prefix+=": "; + name = prefix + convertToXML(fd->localName()); + found = TRUE; + } + } + } + else if (md && (md->getClassDef() || md->getNamespaceDef())) + // member in class or namespace scope + { + SrcLangExt lang = md->getLanguage(); + name = m_def->getOuterScope()->qualifiedName() + + getLanguageSpecificSeparator(lang) + prefix; + found = TRUE; + } + else if (scope) // some thing else? -> show scope + { + name = prefix + convertToXML(scope->name()); + found = TRUE; + } + if (!found) // fallback + { + name = prefix + "("+theTranslator->trGlobalNamespace()+")"; + } + return name; + } + TemplateVariant relPath() const + { + return externalRef("../",m_def->getReference(),TRUE); + } + private: + const Definition *m_def; + const Definition *m_prevDef; + const Definition *m_nextDef; +}; +//%% } + +SymbolContext::SymbolContext(const Definition *def,const Definition *prevDef,const Definition *nextDef) + : RefCountedContext("SymbolContext") +{ + p = new Private(def,prevDef,nextDef); +} + +SymbolContext::~SymbolContext() +{ + delete p; +} + +TemplateVariant SymbolContext::get(const char *name) const +{ + return p->get(name); +} + +//------------------------------------------------------------------------ + +//%% list SymbolList[Symbol] : list of search symbols with the same name +class SymbolListContext::Private : public GenericNodeListContext +{ + public: + Private(const SearchDefinitionList *sdl) + { + QListIterator li(*sdl); + Definition *def; + Definition *prev = 0; + for (li.toFirst();(def=li.current());) + { + ++li; + const Definition *next = li.current(); + append(SymbolContext::alloc(def,prev,next)); + prev = def; + } + } +}; + +SymbolListContext::SymbolListContext(const SearchDefinitionList *sdl) + : RefCountedContext("SymbolListContext") +{ + p = new Private(sdl); +} + +SymbolListContext::~SymbolListContext() +{ + delete p; +} + +// TemplateListIntf +int SymbolListContext::count() const +{ + return p->count(); +} + +TemplateVariant SymbolListContext::at(int index) const +{ + return p->at(index); +} + +TemplateListIntf::ConstIterator *SymbolListContext::createIterator() const +{ + return p->createIterator(); +} + +//------------------------------------------------------------------------ + +//%% struct SymbolGroup: search group of similar symbols +//%% { +class SymbolGroupContext::Private : public PropertyMapper +{ + public: + Private(const SearchDefinitionList *sdl) : m_sdl(sdl) + { + addProperty("id", this,&Private::id); + addProperty("name", this,&Private::name); + addProperty("symbols",this,&Private::symbolList); + } + TemplateVariant id() const + { + return m_sdl->id(); + } + TemplateVariant name() const + { + return m_sdl->name(); + } + TemplateVariant symbolList() const + { + if (!m_cache.symbolList) + { + m_cache.symbolList.reset(SymbolListContext::alloc(m_sdl)); + } + return m_cache.symbolList.get(); + } + private: + const SearchDefinitionList *m_sdl; + struct Cachable + { + SharedPtr symbolList; + }; + mutable Cachable m_cache; +}; +//%% } + +SymbolGroupContext::SymbolGroupContext(const SearchDefinitionList *sdl) + : RefCountedContext("SymbolGroupContext") +{ + p = new Private(sdl); +} + +SymbolGroupContext::~SymbolGroupContext() +{ + delete p; +} + +TemplateVariant SymbolGroupContext::get(const char *name) const +{ + return p->get(name); +} + +//------------------------------------------------------------------------ + +//%% list SymbolGroupList[SymbolGroup] : list of search groups one per by name +class SymbolGroupListContext::Private : public GenericNodeListContext +{ + public: + Private(const SearchIndexList *sil) + { + SDict::Iterator li(*sil); + SearchDefinitionList *dl; + for (li.toFirst();(dl=li.current());++li) + { + append(SymbolGroupContext::alloc(dl)); + } + } +}; + +SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList *sil) + : RefCountedContext("SymbolGroupListContext") +{ + p = new Private(sil); +} + +SymbolGroupListContext::~SymbolGroupListContext() +{ + delete p; +} + +// TemplateListIntf +int SymbolGroupListContext::count() const +{ + return p->count(); +} + +TemplateVariant SymbolGroupListContext::at(int index) const +{ + return p->at(index); +} + +TemplateListIntf::ConstIterator *SymbolGroupListContext::createIterator() const +{ + return p->createIterator(); +} + +//------------------------------------------------------------------------ + +//%% struct SymbolIndex: search index +//%% { +class SymbolIndexContext::Private : public PropertyMapper +{ + public: + Private(const SearchIndexList *sl,const QCString &name) : m_searchList(sl), m_name(name) + { + addProperty("name", this,&Private::name); + addProperty("letter", this,&Private::letter); + addProperty("symbolGroups",this,&Private::symbolGroups); + } + TemplateVariant name() const + { + return m_name; + } + TemplateVariant letter() const + { + return QString(QChar(m_searchList->letter())).utf8(); + } + TemplateVariant symbolGroups() const + { + if (!m_cache.symbolGroups) + { + m_cache.symbolGroups.reset(SymbolGroupListContext::alloc(m_searchList)); + } + return m_cache.symbolGroups.get(); + } + private: + const SearchIndexList *m_searchList; + QCString m_name; + struct Cachable + { + SharedPtr symbolGroups; + }; + mutable Cachable m_cache; +}; +//%% } + +SymbolIndexContext::SymbolIndexContext(const SearchIndexList *sl,const QCString &name) + : RefCountedContext("SymbolIndexContext") +{ + p = new Private(sl,name); +} + +SymbolIndexContext::~SymbolIndexContext() +{ + delete p; +} + +TemplateVariant SymbolIndexContext::get(const char *name) const +{ + return p->get(name); +} + +//------------------------------------------------------------------------ + +//%% list SymbolIndices[SymbolIndex] : list of search indices one per by type +class SymbolIndicesContext::Private : public GenericNodeListContext +{ + public: + Private(const SearchIndexInfo *info) + { + // use info->symbolList to populate the list + SIntDict::Iterator it(info->symbolList); + const SearchIndexList *sl; + for (it.toFirst();(sl=it.current());++it) // for each letter + { + append(SymbolIndexContext::alloc(sl,info->name)); + } + } +}; + +SymbolIndicesContext::SymbolIndicesContext(const SearchIndexInfo *info) : RefCountedContext("SymbolIndicesContext") +{ + p = new Private(info); +} + +SymbolIndicesContext::~SymbolIndicesContext() +{ + delete p; +} + +// TemplateListIntf +int SymbolIndicesContext::count() const +{ + return p->count(); +} + +TemplateVariant SymbolIndicesContext::at(int index) const +{ + return p->at(index); +} + +TemplateListIntf::ConstIterator *SymbolIndicesContext::createIterator() const +{ + return p->createIterator(); +} + +//------------------------------------------------------------------------ + +//%% struct SearchIndex: search index +//%% { +class SearchIndexContext::Private : public PropertyMapper +{ + public: + Private(const SearchIndexInfo *info) : m_info(info) + { + addProperty("name", this,&Private::name); + addProperty("text", this,&Private::text); + addProperty("symbolIndices",this,&Private::symbolIndices); + } + TemplateVariant name() const + { + return m_info->name; + } + TemplateVariant text() const + { + return m_info->text; + } + TemplateVariant symbolIndices() const + { + if (!m_cache.symbolIndices) + { + m_cache.symbolIndices.reset(SymbolIndicesContext::alloc(m_info)); + } + return m_cache.symbolIndices.get(); + } + private: + const SearchIndexInfo *m_info; + struct Cachable + { + SharedPtr symbolIndices; + }; + mutable Cachable m_cache; +}; +//%% } + +SearchIndexContext::SearchIndexContext(const SearchIndexInfo *info) + : RefCountedContext("SearchIndexContext") +{ + p = new Private(info); +} + +SearchIndexContext::~SearchIndexContext() +{ + delete p; +} + +TemplateVariant SearchIndexContext::get(const char *name) const +{ + return p->get(name); +} + +//------------------------------------------------------------------------ + +//%% list SearchIndices[SearchIndex] : list of search indices one per by type +class SearchIndicesContext::Private : public GenericNodeListContext +{ + public: + Private() + { + const SearchIndexInfo *indices = getSearchIndices(); + for (int i=0;icount(); +} + +TemplateVariant SearchIndicesContext::at(int index) const +{ + return p->at(index); +} + +TemplateListIntf::ConstIterator *SearchIndicesContext::createIterator() const +{ + return p->createIterator(); +} + + //------------------------------------------------------------------------ class HtmlEscaper : public TemplateEscapeIntf @@ -8183,6 +8682,7 @@ void generateOutputViaTemplate() SharedPtr globalsIndex (GlobalsIndexContext::alloc()); SharedPtr classMembersIndex (ClassMembersIndexContext::alloc()); SharedPtr namespaceMembersIndex(NamespaceMembersIndexContext::alloc()); + SharedPtr searchIndices (SearchIndicesContext::alloc()); //%% Doxygen doxygen: ctx->set("doxygen",doxygen.get()); @@ -8238,6 +8738,8 @@ void generateOutputViaTemplate() ctx->set("classMembersIndex",classMembersIndex.get()); //%% NamespaceMembersIndex namespaceMembersIndex: ctx->set("namespaceMembersIndex",namespaceMembersIndex.get()); + //%% SearchIndicaes searchindicaes + ctx->set("searchIndices",searchIndices.get()); // render HTML output Template *tpl = e.loadByName("htmllayout.tpl",1); diff --git a/src/context.h b/src/context.h index cb203139761..77a3a95cde8 100644 --- a/src/context.h +++ b/src/context.h @@ -52,7 +52,10 @@ class MemberGroup; class MemberGroupSDict; class MemberGroupList; class DotNode; -class DotGfxHierarchyTable; +class DotGfxHierarchyTable; +struct SearchIndexInfo; +class SearchIndexList; +class SearchDefinitionList; //---------------------------------------------------- @@ -1154,6 +1157,173 @@ class ArgumentListContext : public RefCountedContext, public TemplateListIntf //---------------------------------------------------- +class SymbolContext : public RefCountedContext, public TemplateStructIntf +{ + public: + static SymbolContext *alloc(const Definition *def,const Definition *prev,const Definition *next) + { return new SymbolContext(def,prev,next); } + + // TemplateStructIntf methods + virtual TemplateVariant get(const char *name) const; + virtual int addRef() { return RefCountedContext::addRef(); } + virtual int release() { return RefCountedContext::release(); } + + private: + SymbolContext(const Definition *def,const Definition *prev,const Definition *next); + ~SymbolContext(); + class Private; + Private *p; +}; + +//---------------------------------------------------- + +class SymbolListContext : public RefCountedContext, public TemplateListIntf +{ + public: + static SymbolListContext *alloc(const SearchDefinitionList *sdl) + { return new SymbolListContext(sdl); } + + // TemplateListIntf + virtual int count() const; + virtual TemplateVariant at(int index) const; + virtual TemplateListIntf::ConstIterator *createIterator() const; + virtual int addRef() { return RefCountedContext::addRef(); } + virtual int release() { return RefCountedContext::release(); } + + private: + SymbolListContext(const SearchDefinitionList *sdl); + ~SymbolListContext(); + class Private; + Private *p; +}; + +//---------------------------------------------------- + +class SymbolGroupContext : public RefCountedContext, public TemplateStructIntf +{ + public: + static SymbolGroupContext *alloc(const SearchDefinitionList *sdl) + { return new SymbolGroupContext(sdl); } + + // TemplateStructIntf methods + virtual TemplateVariant get(const char *name) const; + virtual int addRef() { return RefCountedContext::addRef(); } + virtual int release() { return RefCountedContext::release(); } + + private: + SymbolGroupContext(const SearchDefinitionList *sdl); + ~SymbolGroupContext(); + class Private; + Private *p; +}; + +//---------------------------------------------------- + +class SymbolGroupListContext : public RefCountedContext, public TemplateListIntf +{ + public: + static SymbolGroupListContext *alloc(const SearchIndexList *sil) + { return new SymbolGroupListContext(sil); } + + // TemplateListIntf + virtual int count() const; + virtual TemplateVariant at(int index) const; + virtual TemplateListIntf::ConstIterator *createIterator() const; + virtual int addRef() { return RefCountedContext::addRef(); } + virtual int release() { return RefCountedContext::release(); } + + private: + SymbolGroupListContext(const SearchIndexList *sil); + ~SymbolGroupListContext(); + class Private; + Private *p; +}; + +//---------------------------------------------------- + +class SymbolIndexContext : public RefCountedContext, public TemplateStructIntf +{ + public: + static SymbolIndexContext *alloc(const SearchIndexList *sl,const QCString &name) + { return new SymbolIndexContext(sl,name); } + + // TemplateStructIntf methods + virtual TemplateVariant get(const char *name) const; + virtual int addRef() { return RefCountedContext::addRef(); } + virtual int release() { return RefCountedContext::release(); } + + private: + SymbolIndexContext(const SearchIndexList *sl,const QCString &name); + ~SymbolIndexContext(); + class Private; + Private *p; +}; + +//---------------------------------------------------- + +class SymbolIndicesContext : public RefCountedContext, public TemplateListIntf +{ + public: + static SymbolIndicesContext *alloc(const SearchIndexInfo *info) + { return new SymbolIndicesContext(info); } + + // TemplateListIntf + virtual int count() const; + virtual TemplateVariant at(int index) const; + virtual TemplateListIntf::ConstIterator *createIterator() const; + virtual int addRef() { return RefCountedContext::addRef(); } + virtual int release() { return RefCountedContext::release(); } + + private: + SymbolIndicesContext(const SearchIndexInfo *info); + ~SymbolIndicesContext(); + class Private; + Private *p; +}; + +//---------------------------------------------------- + +class SearchIndexContext : public RefCountedContext, public TemplateStructIntf +{ + public: + static SearchIndexContext *alloc(const SearchIndexInfo *info) + { return new SearchIndexContext(info); } + + // TemplateStructIntf methods + virtual TemplateVariant get(const char *name) const; + virtual int addRef() { return RefCountedContext::addRef(); } + virtual int release() { return RefCountedContext::release(); } + + private: + SearchIndexContext(const SearchIndexInfo *info); + ~SearchIndexContext(); + class Private; + Private *p; +}; + +//---------------------------------------------------- + +class SearchIndicesContext : public RefCountedContext, public TemplateListIntf +{ + public: + static SearchIndicesContext *alloc() { return new SearchIndicesContext; } + + // TemplateListIntf + virtual int count() const; + virtual TemplateVariant at(int index) const; + virtual TemplateListIntf::ConstIterator *createIterator() const; + virtual int addRef() { return RefCountedContext::addRef(); } + virtual int release() { return RefCountedContext::release(); } + + private: + SearchIndicesContext(); + ~SearchIndicesContext(); + class Private; + Private *p; +}; + +//---------------------------------------------------- + void generateOutputViaTemplate(); #endif diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 4ff533d972a..51b9341d760 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -11484,12 +11484,17 @@ void generateOutput() static bool searchEngine = Config_getBool("SEARCHENGINE"); static bool serverBasedSearch = Config_getBool("SERVER_BASED_SEARCH"); + g_s.begin("Generating search indices...\n"); + if (searchEngine && !serverBasedSearch && (generateHtml || g_useOutputTemplate)) + { + createJavascriptSearchIndex(); + } + // generate search indices (need to do this before writing other HTML // pages as these contain a drop down menu with options depending on // what categories we find in this function. if (generateHtml && searchEngine) { - g_s.begin("Generating search indices...\n"); QCString searchDirName = Config_getString("HTML_OUTPUT")+"/search"; QDir searchDir(searchDirName); if (!searchDir.exists() && !searchDir.mkdir(searchDirName)) @@ -11503,8 +11508,8 @@ void generateOutput() { writeJavascriptSearchIndex(); } - g_s.end(); } + g_s.end(); g_s.begin("Generating example documentation...\n"); generateExampleDocs(); diff --git a/src/searchindex.cpp b/src/searchindex.cpp index ee545bf702c..9bfe7b09c86 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -583,70 +583,9 @@ void SearchIndexExternal::write(const char *fileName) #include "doxygen.h" #include "message.h" -//static const char search_script[]= -//#include "search.js.h" -//; - -#define SEARCH_INDEX_ALL 0 -#define SEARCH_INDEX_CLASSES 1 -#define SEARCH_INDEX_NAMESPACES 2 -#define SEARCH_INDEX_FILES 3 -#define SEARCH_INDEX_FUNCTIONS 4 -#define SEARCH_INDEX_VARIABLES 5 -#define SEARCH_INDEX_TYPEDEFS 6 -#define SEARCH_INDEX_ENUMS 7 -#define SEARCH_INDEX_ENUMVALUES 8 -#define SEARCH_INDEX_PROPERTIES 9 -#define SEARCH_INDEX_EVENTS 10 -#define SEARCH_INDEX_RELATED 11 -#define SEARCH_INDEX_DEFINES 12 -#define SEARCH_INDEX_GROUPS 13 -#define SEARCH_INDEX_PAGES 14 -#define NUM_SEARCH_INDICES 15 - -class SearchDefinitionList : public QList -{ - public: - SearchDefinitionList(uint letter) : m_letter(letter) {} - uint letter() const { return m_letter; } - private: - uint m_letter; -}; +static SearchIndexInfo g_searchIndexInfo[NUM_SEARCH_INDICES]; -class SearchIndexList : public SDict< SearchDefinitionList > -{ - public: - typedef Definition ElementType; - SearchIndexList(uint letter) : SDict(17,FALSE), m_letter(letter) - { - setAutoDelete(TRUE); - } - ~SearchIndexList() {} - void append(Definition *d) - { - SearchDefinitionList *l = find(d->name()); - if (l==0) - { - l=new SearchDefinitionList(m_letter); - SDict::append(d->name(),l); - } - l->append(d); - } - uint letter() const { return m_letter; } - private: - int compareValues(const SearchDefinitionList *md1, const SearchDefinitionList *md2) const - { - QCString n1 = md1->getFirst()->localName(); - QCString n2 = md2->getFirst()->localName(); - return qstricmp(n1.data(),n2.data()); - } - uint m_letter; -}; - -static void addMemberToSearchIndex( - LetterToIndexMap symbols[NUM_SEARCH_INDICES], - int symbolCount[NUM_SEARCH_INDICES], - MemberDef *md) +static void addMemberToSearchIndex(MemberDef *md) { static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS"); bool isLinkable = md->isLinkable(); @@ -654,7 +593,7 @@ static void addMemberToSearchIndex( NamespaceDef *nd=0; FileDef *fd=0; GroupDef *gd=0; - if (isLinkable && + if (isLinkable && ( ((cd=md->getClassDef()) && cd->isLinkable() && cd->templateMaster()==0) || ((gd=md->getGroupDef()) && gd->isLinkable()) @@ -662,58 +601,49 @@ static void addMemberToSearchIndex( ) { QCString n = md->name(); - if (!n.isEmpty()) + if (!n.isEmpty()) { uint letter = getUtf8CodeToLower(n,0); bool isFriendToHide = hideFriendCompounds && - (QCString(md->typeString())=="friend class" || + (QCString(md->typeString())=="friend class" || QCString(md->typeString())=="friend struct" || QCString(md->typeString())=="friend union"); if (!(md->isFriend() && isFriendToHide)) { - symbols[SEARCH_INDEX_ALL].append(letter,md); - symbolCount[SEARCH_INDEX_ALL]++; + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,md); } if (md->isFunction() || md->isSlot() || md->isSignal()) { - symbols[SEARCH_INDEX_FUNCTIONS].append(letter,md); - symbolCount[SEARCH_INDEX_FUNCTIONS]++; - } + g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].symbolList.append(letter,md); + } else if (md->isVariable()) { - symbols[SEARCH_INDEX_VARIABLES].append(letter,md); - symbolCount[SEARCH_INDEX_VARIABLES]++; + g_searchIndexInfo[SEARCH_INDEX_VARIABLES].symbolList.append(letter,md); } else if (md->isTypedef()) { - symbols[SEARCH_INDEX_TYPEDEFS].append(letter,md); - symbolCount[SEARCH_INDEX_TYPEDEFS]++; + g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].symbolList.append(letter,md); } else if (md->isEnumerate()) { - symbols[SEARCH_INDEX_ENUMS].append(letter,md); - symbolCount[SEARCH_INDEX_ENUMS]++; + g_searchIndexInfo[SEARCH_INDEX_ENUMS].symbolList.append(letter,md); } else if (md->isEnumValue()) { - symbols[SEARCH_INDEX_ENUMVALUES].append(letter,md); - symbolCount[SEARCH_INDEX_ENUMVALUES]++; + g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].symbolList.append(letter,md); } else if (md->isProperty()) { - symbols[SEARCH_INDEX_PROPERTIES].append(letter,md); - symbolCount[SEARCH_INDEX_PROPERTIES]++; + g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].symbolList.append(letter,md); } else if (md->isEvent()) { - symbols[SEARCH_INDEX_EVENTS].append(letter,md); - symbolCount[SEARCH_INDEX_EVENTS]++; + g_searchIndexInfo[SEARCH_INDEX_EVENTS].symbolList.append(letter,md); } else if (md->isRelated() || md->isForeign() || (md->isFriend() && !isFriendToHide)) { - symbols[SEARCH_INDEX_RELATED].append(letter,md); - symbolCount[SEARCH_INDEX_RELATED]++; + g_searchIndexInfo[SEARCH_INDEX_RELATED].symbolList.append(letter,md); } } } @@ -727,38 +657,31 @@ static void addMemberToSearchIndex( if (!n.isEmpty()) { uint letter = getUtf8CodeToLower(n,0); - symbols[SEARCH_INDEX_ALL].append(letter,md); - symbolCount[SEARCH_INDEX_ALL]++; + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,md); if (md->isFunction()) { - symbols[SEARCH_INDEX_FUNCTIONS].append(letter,md); - symbolCount[SEARCH_INDEX_FUNCTIONS]++; + g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].symbolList.append(letter,md); } else if (md->isVariable()) { - symbols[SEARCH_INDEX_VARIABLES].append(letter,md); - symbolCount[SEARCH_INDEX_VARIABLES]++; + g_searchIndexInfo[SEARCH_INDEX_VARIABLES].symbolList.append(letter,md); } else if (md->isTypedef()) { - symbols[SEARCH_INDEX_TYPEDEFS].append(letter,md); - symbolCount[SEARCH_INDEX_TYPEDEFS]++; + g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].symbolList.append(letter,md); } else if (md->isEnumerate()) { - symbols[SEARCH_INDEX_ENUMS].append(letter,md); - symbolCount[SEARCH_INDEX_ENUMS]++; + g_searchIndexInfo[SEARCH_INDEX_ENUMS].symbolList.append(letter,md); } else if (md->isEnumValue()) { - symbols[SEARCH_INDEX_ENUMVALUES].append(letter,md); - symbolCount[SEARCH_INDEX_ENUMVALUES]++; + g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].symbolList.append(letter,md); } else if (md->isDefine()) { - symbols[SEARCH_INDEX_DEFINES].append(letter,md); - symbolCount[SEARCH_INDEX_DEFINES]++; + g_searchIndexInfo[SEARCH_INDEX_DEFINES].symbolList.append(letter,md); } } } @@ -792,55 +715,43 @@ static QCString searchId(const QCString &s) return result; } -static int g_searchIndexCount[NUM_SEARCH_INDICES]; -static LetterToIndexMap g_searchIndexSymbols[NUM_SEARCH_INDICES]; -static const char *g_searchIndexName[NUM_SEARCH_INDICES] = -{ - "all", - "classes", - "namespaces", - "files", - "functions", - "variables", - "typedefs", - "enums", - "enumvalues", - "properties", - "events", - "related", - "defines", - "groups", - "pages" -}; - - -class SearchIndexCategoryMapping +void createJavascriptSearchIndex() { - public: - SearchIndexCategoryMapping() - { - categoryLabel[SEARCH_INDEX_ALL] = theTranslator->trAll(); - categoryLabel[SEARCH_INDEX_CLASSES] = theTranslator->trClasses(); - categoryLabel[SEARCH_INDEX_NAMESPACES] = theTranslator->trNamespace(TRUE,FALSE); - categoryLabel[SEARCH_INDEX_FILES] = theTranslator->trFile(TRUE,FALSE); - categoryLabel[SEARCH_INDEX_FUNCTIONS] = theTranslator->trFunctions(); - categoryLabel[SEARCH_INDEX_VARIABLES] = theTranslator->trVariables(); - categoryLabel[SEARCH_INDEX_TYPEDEFS] = theTranslator->trTypedefs(); - categoryLabel[SEARCH_INDEX_ENUMS] = theTranslator->trEnumerations(); - categoryLabel[SEARCH_INDEX_ENUMVALUES] = theTranslator->trEnumerationValues(); - categoryLabel[SEARCH_INDEX_PROPERTIES] = theTranslator->trProperties(); - categoryLabel[SEARCH_INDEX_EVENTS] = theTranslator->trEvents(); - categoryLabel[SEARCH_INDEX_RELATED] = theTranslator->trFriends(); - categoryLabel[SEARCH_INDEX_DEFINES] = theTranslator->trDefines(); - categoryLabel[SEARCH_INDEX_GROUPS] = theTranslator->trGroup(TRUE,FALSE); - categoryLabel[SEARCH_INDEX_PAGES] = theTranslator->trPage(TRUE,FALSE); - } - QCString categoryLabel[NUM_SEARCH_INDICES]; -}; - -void writeJavascriptSearchIndex() -{ - if (!Config_getBool("GENERATE_HTML")) return; + // set index names + g_searchIndexInfo[SEARCH_INDEX_ALL].name = "all"; + g_searchIndexInfo[SEARCH_INDEX_CLASSES].name = "classes"; + g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].name = "namespaces"; + g_searchIndexInfo[SEARCH_INDEX_FILES].name = "files"; + g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].name = "functions"; + g_searchIndexInfo[SEARCH_INDEX_VARIABLES].name = "variables"; + g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].name = "typedefs"; + g_searchIndexInfo[SEARCH_INDEX_ENUMS].name = "enums"; + g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].name = "enumvalues"; + g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].name = "properties"; + g_searchIndexInfo[SEARCH_INDEX_EVENTS].name = "events"; + g_searchIndexInfo[SEARCH_INDEX_RELATED].name = "related"; + g_searchIndexInfo[SEARCH_INDEX_DEFINES].name = "defines"; + g_searchIndexInfo[SEARCH_INDEX_GROUPS].name = "groups"; + g_searchIndexInfo[SEARCH_INDEX_PAGES].name = "pages"; + + // set index texts + g_searchIndexInfo[SEARCH_INDEX_ALL].text = theTranslator->trAll(); + g_searchIndexInfo[SEARCH_INDEX_CLASSES].text = theTranslator->trClasses(); + g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].text = theTranslator->trNamespace(TRUE,FALSE); + g_searchIndexInfo[SEARCH_INDEX_FILES].text = theTranslator->trFile(TRUE,FALSE); + g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].text = theTranslator->trFunctions(); + g_searchIndexInfo[SEARCH_INDEX_VARIABLES].text = theTranslator->trVariables(); + g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].text = theTranslator->trTypedefs(); + g_searchIndexInfo[SEARCH_INDEX_ENUMS].text = theTranslator->trEnumerations(); + g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].text = theTranslator->trEnumerationValues(); + g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].text = theTranslator->trProperties(); + g_searchIndexInfo[SEARCH_INDEX_EVENTS].text = theTranslator->trEvents(); + g_searchIndexInfo[SEARCH_INDEX_RELATED].text = theTranslator->trFriends(); + g_searchIndexInfo[SEARCH_INDEX_DEFINES].text = theTranslator->trDefines(); + g_searchIndexInfo[SEARCH_INDEX_GROUPS].text = theTranslator->trGroup(TRUE,FALSE); + g_searchIndexInfo[SEARCH_INDEX_PAGES].text = theTranslator->trPage(TRUE,FALSE); + + // add symbols to letter -> symbol list map // index classes ClassSDict::Iterator cli(*Doxygen::classSDict); @@ -850,10 +761,8 @@ void writeJavascriptSearchIndex() uint letter = getUtf8CodeToLower(cd->localName(),0); if (cd->isLinkable() && isId(letter)) { - g_searchIndexSymbols[SEARCH_INDEX_ALL].append(letter,cd); - g_searchIndexSymbols[SEARCH_INDEX_CLASSES].append(letter,cd); - g_searchIndexCount[SEARCH_INDEX_ALL]++; - g_searchIndexCount[SEARCH_INDEX_CLASSES]++; + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,cd); + g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd); } } @@ -865,10 +774,8 @@ void writeJavascriptSearchIndex() uint letter = getUtf8CodeToLower(nd->name(),0); if (nd->isLinkable() && isId(letter)) { - g_searchIndexSymbols[SEARCH_INDEX_ALL].append(letter,nd); - g_searchIndexSymbols[SEARCH_INDEX_NAMESPACES].append(letter,nd); - g_searchIndexCount[SEARCH_INDEX_ALL]++; - g_searchIndexCount[SEARCH_INDEX_NAMESPACES]++; + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,nd); + g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].symbolList.append(letter,nd); } } @@ -884,10 +791,8 @@ void writeJavascriptSearchIndex() uint letter = getUtf8CodeToLower(fd->name(),0); if (fd->isLinkable() && isId(letter)) { - g_searchIndexSymbols[SEARCH_INDEX_ALL].append(letter,fd); - g_searchIndexSymbols[SEARCH_INDEX_FILES].append(letter,fd); - g_searchIndexCount[SEARCH_INDEX_ALL]++; - g_searchIndexCount[SEARCH_INDEX_FILES]++; + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,fd); + g_searchIndexInfo[SEARCH_INDEX_FILES].symbolList.append(letter,fd); } } } @@ -904,7 +809,7 @@ void writeJavascriptSearchIndex() // for each member definition for (mni.toFirst();(md=mni.current());++mni) { - addMemberToSearchIndex(g_searchIndexSymbols,g_searchIndexCount,md); + addMemberToSearchIndex(md); } } } @@ -921,7 +826,7 @@ void writeJavascriptSearchIndex() // for each member definition for (mni.toFirst();(md=mni.current());++mni) { - addMemberToSearchIndex(g_searchIndexSymbols,g_searchIndexCount,md); + addMemberToSearchIndex(md); } } } @@ -940,10 +845,8 @@ void writeJavascriptSearchIndex() uint letter = charCode<128 ? tolower(charCode) : charCode; if (isId(letter)) { - g_searchIndexSymbols[SEARCH_INDEX_ALL].append(letter,gd); - g_searchIndexSymbols[SEARCH_INDEX_GROUPS].append(letter,gd); - g_searchIndexCount[SEARCH_INDEX_ALL]++; - g_searchIndexCount[SEARCH_INDEX_GROUPS]++; + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,gd); + g_searchIndexInfo[SEARCH_INDEX_GROUPS].symbolList.append(letter,gd); } } } @@ -963,10 +866,8 @@ void writeJavascriptSearchIndex() uint letter = charCode<128 ? tolower(charCode) : charCode; if (isId(letter)) { - g_searchIndexSymbols[SEARCH_INDEX_ALL].append(letter,pd); - g_searchIndexSymbols[SEARCH_INDEX_PAGES].append(letter,pd); - g_searchIndexCount[SEARCH_INDEX_ALL]++; - g_searchIndexCount[SEARCH_INDEX_PAGES]++; + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,pd); + g_searchIndexInfo[SEARCH_INDEX_PAGES].symbolList.append(letter,pd); } } } @@ -980,38 +881,40 @@ void writeJavascriptSearchIndex() uint letter = charCode<128 ? tolower(charCode) : charCode; if (isId(letter)) { - g_searchIndexSymbols[SEARCH_INDEX_ALL].append(letter,Doxygen::mainPage); - g_searchIndexSymbols[SEARCH_INDEX_PAGES].append(letter,Doxygen::mainPage); - g_searchIndexCount[SEARCH_INDEX_ALL]++; - g_searchIndexCount[SEARCH_INDEX_PAGES]++; + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,Doxygen::mainPage); + g_searchIndexInfo[SEARCH_INDEX_PAGES].symbolList.append(letter,Doxygen::mainPage); } } } - + // sort all lists int i; for (i=0;i::Iterator it(g_searchIndexSymbols[i]); + SIntDict::Iterator it(g_searchIndexInfo[i].symbolList); SearchIndexList *sl; for (it.toFirst();(sl=it.current());++it) { sl->sort(); } } +} +void writeJavascriptSearchIndex() +{ + int i; // write index files QCString searchDirName = Config_getString("HTML_OUTPUT")+"/search"; for (i=0;i::Iterator it(g_searchIndexSymbols[i]); + SIntDict::Iterator it(g_searchIndexInfo[i].symbolList); SearchIndexList *sl; int p=0; for (it.toFirst();(sl=it.current());++it,++p) // for each letter { QCString baseName; - baseName.sprintf("%s_%x",g_searchIndexName[i],p); + baseName.sprintf("%s_%x",g_searchIndexInfo[i].name.data(),p); QCString fileName = searchDirName + "/"+baseName+".html"; QCString dataFileName = searchDirName + "/"+baseName+".js"; @@ -1083,17 +986,7 @@ void writeJavascriptSearchIndex() } firstEntry=FALSE; - QCString dispName = d->localName(); - if (d->definitionType()==Definition::TypeGroup) - { - dispName = ((GroupDef*)d)->groupTitle(); - } - else if (d->definitionType()==Definition::TypePage) - { - dispName = ((PageDef*)d)->title(); - } - ti << " ['" << searchId(dispName) << "',['" - << convertToXML(dispName) << "',["; + ti << " ['" << dl->id() << "',['" << convertToXML(dl->name()) << "',["; if (dl->count()==1) // item with a unique name { @@ -1274,12 +1167,12 @@ void writeJavascriptSearchIndex() int j=0; for (i=0;i0) + if (g_searchIndexInfo[i].symbolList.count()>0) { if (!first) t << "," << endl; t << " " << j << ": \""; - SIntDict::Iterator it(g_searchIndexSymbols[i]); + SIntDict::Iterator it(g_searchIndexInfo[i].symbolList); SearchIndexList *sl; for (it.toFirst();(sl=it.current());++it) // for each letter { @@ -1298,10 +1191,10 @@ void writeJavascriptSearchIndex() j=0; for (i=0;i0) + if (g_searchIndexInfo[i].symbolList.count()>0) { if (!first) t << "," << endl; - t << " " << j << ": \"" << g_searchIndexName[i] << "\""; + t << " " << j << ": \"" << g_searchIndexInfo[i].name << "\""; first=FALSE; j++; } @@ -1311,14 +1204,13 @@ void writeJavascriptSearchIndex() t << "var indexSectionLabels =" << endl; t << "{" << endl; first=TRUE; - static SearchIndexCategoryMapping map; j=0; for (i=0;i0) + if (g_searchIndexInfo[i].symbolList.count()>0) { if (!first) t << "," << endl; - t << " " << j << ": \"" << convertToXML(map.categoryLabel[i]) << "\""; + t << " " << j << ": \"" << convertToXML(g_searchIndexInfo[i].text) << "\""; first=FALSE; j++; } @@ -1352,6 +1244,55 @@ void writeJavascriptSearchIndex() Doxygen::indexList->addStyleSheetFile("search/search.js"); } +const SearchIndexInfo *getSearchIndices() +{ + return g_searchIndexInfo; +} + +//--------------------------------------------------------------------------------------------- + +SearchIndexList::SearchIndexList(uint letter) + : SDict< SearchDefinitionList >(17,FALSE), m_letter(letter) +{ + setAutoDelete(TRUE); +} + +SearchIndexList::~SearchIndexList() +{ +} + +void SearchIndexList::append(Definition *d) +{ + SearchDefinitionList *l = find(d->name()); + if (l==0) + { + QCString dispName = d->localName(); + if (d->definitionType()==Definition::TypeGroup) + { + dispName = ((GroupDef*)d)->groupTitle(); + } + else if (d->definitionType()==Definition::TypePage) + { + dispName = ((PageDef*)d)->title(); + } + l=new SearchDefinitionList(searchId(dispName),dispName); + SDict< SearchDefinitionList >::append(d->name(),l); + } + l->append(d); +} + +uint SearchIndexList::letter() const +{ + return m_letter; +} + +int SearchIndexList::compareValues(const SearchDefinitionList *md1, const SearchDefinitionList *md2) const +{ + QCString n1 = md1->getFirst()->localName(); + QCString n2 = md2->getFirst()->localName(); + return qstricmp(n1.data(),n2.data()); +} + //--------------------------------------------------------------------------------------------- void initSearchIndexer() diff --git a/src/searchindex.h b/src/searchindex.h index b9f45c6f879..e491f4754aa 100644 --- a/src/searchindex.h +++ b/src/searchindex.h @@ -23,6 +23,9 @@ #include #include #include +#include "sortdict.h" +#include "definition.h" +#include "util.h" class FTextStream; class Definition; @@ -109,6 +112,56 @@ class SearchIndexExternal : public SearchIndexIntf //------- client side search index ---------------------- +#define SEARCH_INDEX_ALL 0 +#define SEARCH_INDEX_CLASSES 1 +#define SEARCH_INDEX_NAMESPACES 2 +#define SEARCH_INDEX_FILES 3 +#define SEARCH_INDEX_FUNCTIONS 4 +#define SEARCH_INDEX_VARIABLES 5 +#define SEARCH_INDEX_TYPEDEFS 6 +#define SEARCH_INDEX_ENUMS 7 +#define SEARCH_INDEX_ENUMVALUES 8 +#define SEARCH_INDEX_PROPERTIES 9 +#define SEARCH_INDEX_EVENTS 10 +#define SEARCH_INDEX_RELATED 11 +#define SEARCH_INDEX_DEFINES 12 +#define SEARCH_INDEX_GROUPS 13 +#define SEARCH_INDEX_PAGES 14 +#define NUM_SEARCH_INDICES 15 + +class SearchDefinitionList : public QList +{ + public: + SearchDefinitionList(const QCString &id,const QCString &name) : m_id(id), m_name(name) {} + QCString id() const { return m_id; } + QCString name() const { return m_name; } + private: + QCString m_id; + QCString m_name; +}; + +class SearchIndexList : public SDict< SearchDefinitionList > +{ + public: + typedef Definition ElementType; + SearchIndexList(uint letter); + ~SearchIndexList(); + void append(Definition *d); + uint letter() const; + private: + int compareValues(const SearchDefinitionList *md1, const SearchDefinitionList *md2) const; + uint m_letter; +}; + +struct SearchIndexInfo +{ + LetterToIndexMap symbolList; + QCString name; + QCString text; +}; + +void createJavascriptSearchIndex(); void writeJavascriptSearchIndex(); +const SearchIndexInfo *getSearchIndices(); #endif diff --git a/src/template.cpp b/src/template.cpp index 5102978275e..ce9493b9bf6 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -98,6 +98,34 @@ static QValueList split(const QCString &str,const QCString &sep, //---------------------------------------------------------------------------- +/** Strips spaces surrounding `=` from string \a in, so + * `foo = 10 bar=5 baz= 'hello'` will become `foo=10 bar=5 baz='hello'` + */ +static void removeSpacesAroundEquals(QCString &in) +{ + const char *p=in.data(); + char *q = in.data(); + char c; + while ((c=*p++)) + { + if (c==' ') // found a space, see if there is a = as well + { + const char *t = p; + bool found=FALSE; + while (*t==' ' || *t=='=') { if (*t++=='=') found=TRUE; } + if (found) + { + c='='; + p=t; // move p to end of '\s*=\s*' sequence + } + } + *q++=c; + } + if (q TRACE(("{TemplateNodeWith(%s)\n",data.data())); m_args.setAutoDelete(TRUE); ExpressionParser expParser(parser,line); - QValueList args = split(data," "); + QCString filteredData = data; + removeSpacesAroundEquals(filteredData); + QValueList args = split(filteredData," "); QValueListIterator it = args.begin(); while (it!=args.end()) { diff --git a/templates/html/htmlallmembers.tpl b/templates/html/htmlallmembers.tpl index 98f88d653ed..e4b846009f5 100644 --- a/templates/html/htmlallmembers.tpl +++ b/templates/html/htmlallmembers.tpl @@ -9,11 +9,13 @@

{{ tr.theListOfAllMembers }} {{ compound.name }}{{ tr.incInheritedMembers }}

{% for mi in compound.allMembersList %} - + {# TODO: objective-C #} - {% endfor %} diff --git a/templates/html/htmlbase.tpl b/templates/html/htmlbase.tpl index d394b45a9bf..21911861f9c 100644 --- a/templates/html/htmlbase.tpl +++ b/templates/html/htmlbase.tpl @@ -21,6 +21,9 @@ {% endif %} {% if config.SEARCHENGINE %} + {% if not config.SERVER_BASED_SEARCH %} + + {% endif %} {% if config.SERVER_BASED_SEARCH %} + + + +
+
{{ tr.loading }}
+
+ +
{{ tr.searching }}
+
{{ tr.noMatches }}
+ +
+ + diff --git a/templates/html/htmltabs.tpl b/templates/html/htmltabs.tpl index 9ce8c44de54..4c48f54a920 100644 --- a/templates/html/htmltabs.tpl +++ b/templates/html/htmltabs.tpl @@ -69,6 +69,7 @@ {# second navigation row #} +{% if page.highlight=='namespace' or page.highlight=='classes' or page.highlight=='files' %} +{% endif %}
{% with obj=mi.member text=mi.ambiguityScope|append:mi.member.name %} + {% with obj=mi.member text=mi.ambiguityScope|append:mi.member.name %} {% include 'htmlobjlink.tpl' %} {% endwith %} + {# TODO: add arguments #} + {# TODO: add column with scope #}