searchindex.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  *
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby
9  * granted. No representations are made about the suitability of this software
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17 
18 #include <ctype.h>
19 #include <assert.h>
20 
21 #include <qfile.h>
22 #include <qregexp.h>
23 
24 #include "searchindex.h"
25 #include "config.h"
26 #include "util.h"
27 #include "doxygen.h"
28 #include "language.h"
29 #include "pagedef.h"
30 #include "growbuf.h"
31 #include "message.h"
32 #include "version.h"
33 #include "groupdef.h"
34 #include "classlist.h"
35 #include "filedef.h"
36 #include "memberdef.h"
37 #include "filename.h"
38 #include "membername.h"
39 #include "resourcemgr.h"
40 
41 // file format: (all multi-byte values are stored in big endian format)
42 // 4 byte header
43 // 256*256*4 byte index (4 bytes)
44 // for each index entry: a zero terminated list of words
45 // for each word: a \0 terminated string + 4 byte offset to the stats info
46 // padding bytes to align at 4 byte boundary
47 // for each word: the number of urls (4 bytes)
48 // + for each url containing the word 8 bytes statistics
49 // (4 bytes index to url string + 4 bytes frequency counter)
50 // for each url: a \0 terminated string
51 
52 const int numIndexEntries = 256*256;
53 
54 //--------------------------------------------------------------------
55 
56 IndexWord::IndexWord(const char *word) : m_word(word), m_urls(17)
57 {
59  //printf("IndexWord::IndexWord(%s)\n",word);
60 }
61 
62 void IndexWord::addUrlIndex(int idx,bool hiPriority)
63 {
64  //printf("IndexWord::addUrlIndex(%d,%d)\n",idx,hiPriority);
65  URLInfo *ui = m_urls.find(idx);
66  if (ui==0)
67  {
68  //printf("URLInfo::URLInfo(%d)\n",idx);
69  ui=new URLInfo(idx,0);
70  m_urls.insert(idx,ui);
71  }
72  ui->freq+=2;
73  if (hiPriority) ui->freq|=1; // mark as high priority document
74 }
75 
76 //--------------------------------------------------------------------
77 
79  m_words(328829), m_index(numIndexEntries), m_url2IdMap(10007), m_urls(10007), m_urlIndex(-1)
80 {
81  int i;
82  m_words.setAutoDelete(TRUE);
83  m_url2IdMap.setAutoDelete(TRUE);
86  for (i=0;i<numIndexEntries;i++) m_index.insert(i,new QList<IndexWord>);
87 }
88 
89 void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile)
90 {
91  if (ctx==0) return;
92  assert(!isSourceFile || ctx->definitionType()==Definition::TypeFile);
93  //printf("SearchIndex::setCurrentDoc(%s,%s,%s)\n",name,baseName,anchor);
94  QCString url=isSourceFile ? ((FileDef*)ctx)->getSourceFileBase() : ctx->getOutputFileBase();
95  url+=Config_getString("HTML_FILE_EXTENSION");
96  QCString baseUrl = url;
97  if (anchor) url+=QCString("#")+anchor;
98  if (!isSourceFile) baseUrl=url;
99  QCString name=ctx->qualifiedName();
100  if (ctx->definitionType()==Definition::TypeMember)
101  {
102  MemberDef *md = (MemberDef *)ctx;
103  name.prepend((md->getLanguage()==SrcLangExt_Fortran ?
106  }
107  else // compound type
108  {
109  SrcLangExt lang = ctx->getLanguage();
111  if (sep!="::")
112  {
113  name = substitute(name,"::",sep);
114  }
115  switch (ctx->definitionType())
116  {
118  {
119  PageDef *pd = (PageDef *)ctx;
120  if (!pd->title().isEmpty())
121  {
122  name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title();
123  }
124  else
125  {
126  name = theTranslator->trPage(TRUE,TRUE)+" "+pd->name();
127  }
128  }
129  break;
131  {
132  ClassDef *cd = (ClassDef *)ctx;
133  name.prepend(cd->compoundTypeString()+" ");
134  }
135  break;
137  {
138  if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp)
139  {
140  name = theTranslator->trPackage(name);
141  }
142  else if (lang==SrcLangExt_Fortran)
143  {
144  name.prepend(theTranslator->trModule(TRUE,TRUE)+" ");
145  }
146  else
147  {
149  }
150  }
151  break;
153  {
154  GroupDef *gd = (GroupDef *)ctx;
155  if (gd->groupTitle())
156  {
157  name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle();
158  }
159  else
160  {
161  name.prepend(theTranslator->trGroup(TRUE,TRUE)+" ");
162  }
163  }
164  break;
165  default:
166  break;
167  }
168  }
169 
170  int *pIndex = m_url2IdMap.find(baseUrl);
171  if (pIndex==0)
172  {
173  ++m_urlIndex;
174  m_url2IdMap.insert(baseUrl,new int(m_urlIndex));
175  m_urls.insert(m_urlIndex,new URL(name,url));
176  }
177  else
178  {
179  m_urls.insert(*pIndex,new URL(name,url));
180  }
181 }
182 
183 static int charsToIndex(const char *word)
184 {
185  if (word==0) return -1;
186 
187  // Fast string hashing algorithm
188  //register ushort h=0;
189  //const char *k = word;
190  //ushort mask=0xfc00;
191  //while ( *k )
192  //{
193  // h = (h&mask)^(h<<6)^(*k++);
194  //}
195  //return h;
196 
197  // Simple hashing that allows for substring searching
198  uint c1=((uchar *)word)[0];
199  if (c1==0) return -1;
200  uint c2=((uchar *)word)[1];
201  if (c2==0) return -1;
202  return c1*256+c2;
203 }
204 
205 void SearchIndex::addWord(const char *word,bool hiPriority,bool recurse)
206 {
207  static QRegExp nextPart("[_a-z:][A-Z]");
208  if (word==0 || word[0]=='\0') return;
209  QCString wStr = QCString(word).lower();
210  //printf("SearchIndex::addWord(%s,%d) wStr=%s\n",word,hiPriority,wStr.data());
211  IndexWord *w = m_words[wStr];
212  if (w==0)
213  {
214  int idx=charsToIndex(wStr);
215  //fprintf(stderr,"addWord(%s) at index %d\n",word,idx);
216  if (idx<0) return;
217  w = new IndexWord(wStr);
218  m_index[idx]->append(w);
219  m_words.insert(wStr,w);
220  }
221  w->addUrlIndex(m_urlIndex,hiPriority);
222  int i;
223  bool found=FALSE;
224  if (!recurse) // the first time we check if we can strip the prefix
225  {
226  i=getPrefixIndex(word);
227  if (i>0)
228  {
229  addWord(word+i,hiPriority,TRUE);
230  found=TRUE;
231  }
232  }
233  if (!found) // no prefix stripped
234  {
235  if ((i=nextPart.match(word))>=1)
236  {
237  addWord(word+i+1,hiPriority,TRUE);
238  }
239  }
240 }
241 
242 void SearchIndex::addWord(const char *word,bool hiPriority)
243 {
244  addWord(word,hiPriority,FALSE);
245 }
246 
247 static void writeInt(QFile &f,int index)
248 {
249  f.putch(((uint)index)>>24);
250  f.putch((((uint)index)>>16)&0xff);
251  f.putch((((uint)index)>>8)&0xff);
252  f.putch(((uint)index)&0xff);
253 }
254 
255 static void writeString(QFile &f,const char *s)
256 {
257  const char *p = s;
258  while (*p) f.putch(*p++);
259  f.putch(0);
260 }
261 
262 void SearchIndex::write(const char *fileName)
263 {
264  int i;
265  int size=4; // for the header
266  size+=4*numIndexEntries; // for the index
267  int wordsOffset = size;
268  // first pass: compute the size of the wordlist
269  for (i=0;i<numIndexEntries;i++)
270  {
271  QList<IndexWord> *wlist = m_index[i];
272  if (!wlist->isEmpty())
273  {
274  QListIterator<IndexWord> iwi(*wlist);
275  IndexWord *iw;
276  for (iwi.toFirst();(iw=iwi.current());++iwi)
277  {
278  int ws = iw->word().length()+1;
279  size+=ws+4; // word + url info list offset
280  }
281  size+=1; // zero list terminator
282  }
283  }
284 
285  // second pass: compute the offsets in the index
286  int indexOffsets[numIndexEntries];
287  int offset=wordsOffset;
288  for (i=0;i<numIndexEntries;i++)
289  {
290  QList<IndexWord> *wlist = m_index[i];
291  if (!wlist->isEmpty())
292  {
293  indexOffsets[i]=offset;
294  QListIterator<IndexWord> iwi(*wlist);
295  IndexWord *iw;
296  for (iwi.toFirst();(iw=iwi.current());++iwi)
297  {
298  offset+= iw->word().length()+1;
299  offset+=4; // word + offset to url info array
300  }
301  offset+=1; // zero list terminator
302  }
303  else
304  {
305  indexOffsets[i]=0;
306  }
307  }
308  int padding = size;
309  size = (size+3)&~3; // round up to 4 byte boundary
310  padding = size - padding;
311 
312  //int statsOffset = size;
313  //IndexWord *iw;
314  int *wordStatOffsets = new int[m_words.count()];
315 
316  int count=0;
317 
318  // third pass: compute offset to stats info for each word
319  for (i=0;i<numIndexEntries;i++)
320  {
321  QList<IndexWord> *wlist = m_index[i];
322  if (!wlist->isEmpty())
323  {
324  QListIterator<IndexWord> iwi(*wlist);
325  IndexWord *iw;
326  for (iwi.toFirst();(iw=iwi.current());++iwi)
327  {
328  //printf("wordStatOffsets[%d]=%d\n",count,size);
329  wordStatOffsets[count++] = size;
330  size+=4+iw->urls().count()*8; // count + (url_index,freq) per url
331  }
332  }
333  }
334  int *urlOffsets = new int[m_urls.count()];
335  //int urlsOffset = size;
337  URL *url;
338  for (udi.toFirst();(url=udi.current());++udi)
339  {
340  urlOffsets[udi.currentKey()]=size;
341  size+=url->name.length()+1+
342  url->url.length()+1;
343  }
344  //printf("Total size %x bytes (word=%x stats=%x urls=%x)\n",size,wordsOffset,statsOffset,urlsOffset);
345  QFile f(fileName);
346  if (f.open(IO_WriteOnly))
347  {
348  // write header
349  f.putch('D'); f.putch('O'); f.putch('X'); f.putch('S');
350  // write index
351  for (i=0;i<numIndexEntries;i++)
352  {
353  writeInt(f,indexOffsets[i]);
354  }
355  // write word lists
356  count=0;
357  for (i=0;i<numIndexEntries;i++)
358  {
359  QList<IndexWord> *wlist = m_index[i];
360  if (!wlist->isEmpty())
361  {
362  QListIterator<IndexWord> iwi(*wlist);
363  IndexWord *iw;
364  for (iwi.toFirst();(iw=iwi.current());++iwi)
365  {
366  writeString(f,iw->word());
367  writeInt(f,wordStatOffsets[count++]);
368  }
369  f.putch(0);
370  }
371  }
372  // write extra padding bytes
373  for (i=0;i<padding;i++) f.putch(0);
374  // write word statistics
375  for (i=0;i<numIndexEntries;i++)
376  {
377  QList<IndexWord> *wlist = m_index[i];
378  if (!wlist->isEmpty())
379  {
380  QListIterator<IndexWord> iwi(*wlist);
381  IndexWord *iw;
382  for (iwi.toFirst();(iw=iwi.current());++iwi)
383  {
384  int numUrls = iw->urls().count();
385  writeInt(f,numUrls);
386  QIntDictIterator<URLInfo> uli(iw->urls());
387  URLInfo *ui;
388  for (uli.toFirst();(ui=uli.current());++uli)
389  {
390  writeInt(f,urlOffsets[ui->urlIdx]);
391  writeInt(f,ui->freq);
392  }
393  }
394  }
395  }
396  // write urls
398  URL *url;
399  for (udi.toFirst();(url=udi.current());++udi)
400  {
401  writeString(f,url->name);
402  writeString(f,url->url);
403  }
404  }
405 
406  delete[] urlOffsets;
407  delete[] wordStatOffsets;
408 }
409 
410 
411 //---------------------------------------------------------------------------
412 // the following part is for writing an external search index
413 
415 {
423 };
424 
426 {
427  Private() : docEntries(12251) {}
430 };
431 
433 {
436  p->current=0;
437 }
438 
440 {
441  //printf("p->docEntries.count()=%d\n",p->docEntries.count());
442  delete p;
443 }
444 
446 {
447  if (ctx && ctx->definitionType()==Definition::TypeMember)
448  {
449  MemberDef *md = (MemberDef*)ctx;
450  if (md->isFunction())
451  return "function";
452  else if (md->isSlot())
453  return "slot";
454  else if (md->isSignal())
455  return "signal";
456  else if (md->isVariable())
457  return "variable";
458  else if (md->isTypedef())
459  return "typedef";
460  else if (md->isEnumerate())
461  return "enum";
462  else if (md->isEnumValue())
463  return "enumvalue";
464  else if (md->isProperty())
465  return "property";
466  else if (md->isEvent())
467  return "event";
468  else if (md->isRelated() || md->isForeign())
469  return "related";
470  else if (md->isFriend())
471  return "friend";
472  else if (md->isDefine())
473  return "define";
474  }
475  else if (ctx)
476  {
477  switch(ctx->definitionType())
478  {
479  case Definition::TypeClass:
480  return ((ClassDef*)ctx)->compoundTypeString();
482  return "file";
484  return "namespace";
486  return "group";
488  return "package";
490  return "page";
491  case Definition::TypeDir:
492  return "dir";
493  default:
494  break;
495  }
496  }
497  return "unknown";
498 }
499 
500 void SearchIndexExternal::setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile)
501 {
502  QCString extId = stripPath(Config_getString("EXTERNAL_SEARCH_ID"));
503  QCString baseName = isSourceFile ? ((FileDef*)ctx)->getSourceFileBase() : ctx->getOutputFileBase();
505  if (anchor) url+=QCString("#")+anchor;
506  QCString key = extId+";"+url;
507 
508  p->current = p->docEntries.find(key);
509  //printf("setCurrentDoc(url=%s,isSourceFile=%d) current=%p\n",url.data(),isSourceFile,p->current);
510  if (!p->current)
511  {
513  e->type = isSourceFile ? QCString("source") : definitionToName(ctx);
514  e->name = ctx->qualifiedName();
515  if (ctx->definitionType()==Definition::TypeMember)
516  {
517  e->args = ((MemberDef*)ctx)->argsString();
518  }
519  e->extId = extId;
520  e->url = url;
521  p->current = e;
522  p->docEntries.append(key,e);
523  //printf("searchIndexExt %s : %s\n",e->name.data(),e->url.data());
524  }
525 }
526 
527 void SearchIndexExternal::addWord(const char *word,bool hiPriority)
528 {
529  if (word==0 || !isId(*word) || p->current==0) return;
530  GrowBuf *pText = hiPriority ? &p->current->importantText : &p->current->normalText;
531  if (pText->getPos()>0) pText->addChar(' ');
532  pText->addStr(word);
533  //printf("addWord %s\n",word);
534 }
535 
537 {
538  QFile f(fileName);
539  if (f.open(IO_WriteOnly))
540  {
541  FTextStream t(&f);
542  t << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
543  t << "<add>" << endl;
546  for (it.toFirst();(doc=it.current());++it)
547  {
548  doc->normalText.addChar(0); // make sure buffer ends with a 0 terminator
549  doc->importantText.addChar(0); // make sure buffer ends with a 0 terminator
550  t << " <doc>" << endl;
551  t << " <field name=\"type\">" << doc->type << "</field>" << endl;
552  t << " <field name=\"name\">" << convertToXML(doc->name) << "</field>" << endl;
553  if (!doc->args.isEmpty())
554  {
555  t << " <field name=\"args\">" << convertToXML(doc->args) << "</field>" << endl;
556  }
557  if (!doc->extId.isEmpty())
558  {
559  t << " <field name=\"tag\">" << convertToXML(doc->extId) << "</field>" << endl;
560  }
561  t << " <field name=\"url\">" << convertToXML(doc->url) << "</field>" << endl;
562  t << " <field name=\"keywords\">" << convertToXML(doc->importantText.get()) << "</field>" << endl;
563  t << " <field name=\"text\">" << convertToXML(doc->normalText.get()) << "</field>" << endl;
564  t << " </doc>" << endl;
565  }
566  t << "</add>" << endl;
567  }
568  else
569  {
570  err("Failed to open file %s for writing!\n",fileName);
571  }
572 }
573 
574 //---------------------------------------------------------------------------
575 // the following part is for the javascript based search engine
576 
577 #include "memberdef.h"
578 #include "namespacedef.h"
579 #include "pagedef.h"
580 #include "classdef.h"
581 #include "filedef.h"
582 #include "language.h"
583 #include "doxygen.h"
584 #include "message.h"
585 
587 
589 {
590  static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS");
591  bool isLinkable = md->isLinkable();
592  ClassDef *cd=0;
593  NamespaceDef *nd=0;
594  FileDef *fd=0;
595  GroupDef *gd=0;
596  if (isLinkable &&
597  (
598  ((cd=md->getClassDef()) && cd->isLinkable() && cd->templateMaster()==0) ||
599  ((gd=md->getGroupDef()) && gd->isLinkable())
600  )
601  )
602  {
603  QCString n = md->name();
604  if (!n.isEmpty())
605  {
606  uint letter = getUtf8CodeToLower(n,0);
607  bool isFriendToHide = hideFriendCompounds &&
608  (QCString(md->typeString())=="friend class" ||
609  QCString(md->typeString())=="friend struct" ||
610  QCString(md->typeString())=="friend union");
611  if (!(md->isFriend() && isFriendToHide))
612  {
613  g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,md);
614  }
615  if (md->isFunction() || md->isSlot() || md->isSignal())
616  {
617  g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].symbolList.append(letter,md);
618  }
619  else if (md->isVariable())
620  {
621  g_searchIndexInfo[SEARCH_INDEX_VARIABLES].symbolList.append(letter,md);
622  }
623  else if (md->isTypedef())
624  {
625  g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].symbolList.append(letter,md);
626  }
627  else if (md->isEnumerate())
628  {
629  g_searchIndexInfo[SEARCH_INDEX_ENUMS].symbolList.append(letter,md);
630  }
631  else if (md->isEnumValue())
632  {
633  g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].symbolList.append(letter,md);
634  }
635  else if (md->isProperty())
636  {
637  g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].symbolList.append(letter,md);
638  }
639  else if (md->isEvent())
640  {
641  g_searchIndexInfo[SEARCH_INDEX_EVENTS].symbolList.append(letter,md);
642  }
643  else if (md->isRelated() || md->isForeign() ||
644  (md->isFriend() && !isFriendToHide))
645  {
646  g_searchIndexInfo[SEARCH_INDEX_RELATED].symbolList.append(letter,md);
647  }
648  }
649  }
650  else if (isLinkable &&
651  (((nd=md->getNamespaceDef()) && nd->isLinkable()) ||
652  ((fd=md->getFileDef()) && fd->isLinkable())
653  )
654  )
655  {
656  QCString n = md->name();
657  if (!n.isEmpty())
658  {
659  uint letter = getUtf8CodeToLower(n,0);
660  g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,md);
661 
662  if (md->isFunction())
663  {
664  g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].symbolList.append(letter,md);
665  }
666  else if (md->isVariable())
667  {
668  g_searchIndexInfo[SEARCH_INDEX_VARIABLES].symbolList.append(letter,md);
669  }
670  else if (md->isTypedef())
671  {
672  g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].symbolList.append(letter,md);
673  }
674  else if (md->isEnumerate())
675  {
676  g_searchIndexInfo[SEARCH_INDEX_ENUMS].symbolList.append(letter,md);
677  }
678  else if (md->isEnumValue())
679  {
680  g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].symbolList.append(letter,md);
681  }
682  else if (md->isDefine())
683  {
684  g_searchIndexInfo[SEARCH_INDEX_DEFINES].symbolList.append(letter,md);
685  }
686  }
687  }
688 }
689 
690 // see also function convertToId() in search.js, which should match in
691 // behaviour
692 static QCString searchId(const QCString &s)
693 {
694  int c;
695  uint i;
697  for (i=0;i<s.length();i++)
698  {
699  c=s.at(i);
700  if (c>0x7f || c<0) // part of multibyte character
701  {
702  result+=(char)c;
703  }
704  else if (isalnum(c)) // simply alpha numerical character
705  {
706  result+=(char)tolower(c);
707  }
708  else // other 'unprintable' characters
709  {
710  char val[4];
711  sprintf(val,"_%02x",(uchar)c);
712  result+=val;
713  }
714  }
715  return result;
716 }
717 
719 {
720  // set index names
721  g_searchIndexInfo[SEARCH_INDEX_ALL].name = "all";
722  g_searchIndexInfo[SEARCH_INDEX_CLASSES].name = "classes";
723  g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].name = "namespaces";
724  g_searchIndexInfo[SEARCH_INDEX_FILES].name = "files";
725  g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].name = "functions";
726  g_searchIndexInfo[SEARCH_INDEX_VARIABLES].name = "variables";
727  g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].name = "typedefs";
728  g_searchIndexInfo[SEARCH_INDEX_ENUMS].name = "enums";
729  g_searchIndexInfo[SEARCH_INDEX_ENUMVALUES].name = "enumvalues";
730  g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].name = "properties";
731  g_searchIndexInfo[SEARCH_INDEX_EVENTS].name = "events";
732  g_searchIndexInfo[SEARCH_INDEX_RELATED].name = "related";
733  g_searchIndexInfo[SEARCH_INDEX_DEFINES].name = "defines";
734  g_searchIndexInfo[SEARCH_INDEX_GROUPS].name = "groups";
735  g_searchIndexInfo[SEARCH_INDEX_PAGES].name = "pages";
736 
737  // set index texts
738  g_searchIndexInfo[SEARCH_INDEX_ALL].text = theTranslator->trAll();
739  g_searchIndexInfo[SEARCH_INDEX_CLASSES].text = theTranslator->trClasses();
741  g_searchIndexInfo[SEARCH_INDEX_FILES].text = theTranslator->trFile(TRUE,FALSE);
742  g_searchIndexInfo[SEARCH_INDEX_FUNCTIONS].text = theTranslator->trFunctions();
743  g_searchIndexInfo[SEARCH_INDEX_VARIABLES].text = theTranslator->trVariables();
744  g_searchIndexInfo[SEARCH_INDEX_TYPEDEFS].text = theTranslator->trTypedefs();
745  g_searchIndexInfo[SEARCH_INDEX_ENUMS].text = theTranslator->trEnumerations();
747  g_searchIndexInfo[SEARCH_INDEX_PROPERTIES].text = theTranslator->trProperties();
748  g_searchIndexInfo[SEARCH_INDEX_EVENTS].text = theTranslator->trEvents();
749  g_searchIndexInfo[SEARCH_INDEX_RELATED].text = theTranslator->trFriends();
750  g_searchIndexInfo[SEARCH_INDEX_DEFINES].text = theTranslator->trDefines();
751  g_searchIndexInfo[SEARCH_INDEX_GROUPS].text = theTranslator->trGroup(TRUE,FALSE);
752  g_searchIndexInfo[SEARCH_INDEX_PAGES].text = theTranslator->trPage(TRUE,FALSE);
753 
754  // add symbols to letter -> symbol list map
755 
756  // index classes
758  ClassDef *cd;
759  for (;(cd=cli.current());++cli)
760  {
761  uint letter = getUtf8CodeToLower(cd->localName(),0);
762  if (cd->isLinkable() && isId(letter))
763  {
764  g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,cd);
765  g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd);
766  }
767  }
768 
769  // index namespaces
771  NamespaceDef *nd;
772  for (;(nd=nli.current());++nli)
773  {
774  uint letter = getUtf8CodeToLower(nd->name(),0);
775  if (nd->isLinkable() && isId(letter))
776  {
777  g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,nd);
778  g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].symbolList.append(letter,nd);
779  }
780  }
781 
782  // index files
784  FileName *fn;
785  for (;(fn=fnli.current());++fnli)
786  {
787  FileNameIterator fni(*fn);
788  FileDef *fd;
789  for (;(fd=fni.current());++fni)
790  {
791  uint letter = getUtf8CodeToLower(fd->name(),0);
792  if (fd->isLinkable() && isId(letter))
793  {
794  g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,fd);
795  g_searchIndexInfo[SEARCH_INDEX_FILES].symbolList.append(letter,fd);
796  }
797  }
798  }
799 
800  // index class members
801  {
803  MemberName *mn;
804  // for each member name
805  for (mnli.toFirst();(mn=mnli.current());++mnli)
806  {
807  MemberDef *md;
808  MemberNameIterator mni(*mn);
809  // for each member definition
810  for (mni.toFirst();(md=mni.current());++mni)
811  {
813  }
814  }
815  }
816 
817  // index file/namespace members
818  {
820  MemberName *mn;
821  // for each member name
822  for (fnli.toFirst();(mn=fnli.current());++fnli)
823  {
824  MemberDef *md;
825  MemberNameIterator mni(*mn);
826  // for each member definition
827  for (mni.toFirst();(md=mni.current());++mni)
828  {
830  }
831  }
832  }
833 
834  // index groups
836  GroupDef *gd;
837  for (gli.toFirst();(gd=gli.current());++gli)
838  {
839  if (gd->isLinkable())
840  {
841  QCString title = gd->groupTitle();
842  if (!title.isEmpty()) // TODO: able searching for all word in the title
843  {
844  uchar charCode = title.at(0);
845  uint letter = charCode<128 ? tolower(charCode) : charCode;
846  if (isId(letter))
847  {
848  g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,gd);
849  g_searchIndexInfo[SEARCH_INDEX_GROUPS].symbolList.append(letter,gd);
850  }
851  }
852  }
853  }
854 
855  // index pages
857  PageDef *pd=0;
858  for (pdi.toFirst();(pd=pdi.current());++pdi)
859  {
860  if (pd->isLinkable())
861  {
862  QCString title = pd->title();
863  if (!title.isEmpty())
864  {
865  uchar charCode = title.at(0);
866  uint letter = charCode<128 ? tolower(charCode) : charCode;
867  if (isId(letter))
868  {
869  g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,pd);
870  g_searchIndexInfo[SEARCH_INDEX_PAGES].symbolList.append(letter,pd);
871  }
872  }
873  }
874  }
875  if (Doxygen::mainPage)
876  {
878  if (!title.isEmpty())
879  {
880  uchar charCode = title.at(0);
881  uint letter = charCode<128 ? tolower(charCode) : charCode;
882  if (isId(letter))
883  {
884  g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,Doxygen::mainPage);
885  g_searchIndexInfo[SEARCH_INDEX_PAGES].symbolList.append(letter,Doxygen::mainPage);
886  }
887  }
888  }
889 
890  // sort all lists
891  int i;
892  for (i=0;i<NUM_SEARCH_INDICES;i++)
893  {
894  SIntDict<SearchIndexList>::Iterator it(g_searchIndexInfo[i].symbolList);
895  SearchIndexList *sl;
896  for (it.toFirst();(sl=it.current());++it)
897  {
898  sl->sort();
899  }
900  }
901 }
902 
904 {
905  int i;
906  // write index files
907  QCString searchDirName = Config_getString("HTML_OUTPUT")+"/search";
908 
909  for (i=0;i<NUM_SEARCH_INDICES;i++) // for each index
910  {
911  SIntDict<SearchIndexList>::Iterator it(g_searchIndexInfo[i].symbolList);
912  SearchIndexList *sl;
913  int p=0;
914  for (it.toFirst();(sl=it.current());++it,++p) // for each letter
915  {
917  baseName.sprintf("%s_%x",g_searchIndexInfo[i].name.data(),p);
918 
919  QCString fileName = searchDirName + "/"+baseName+".html";
920  QCString dataFileName = searchDirName + "/"+baseName+".js";
921 
922  QFile outFile(fileName);
923  QFile dataOutFile(dataFileName);
924  if (outFile.open(IO_WriteOnly) && dataOutFile.open(IO_WriteOnly))
925  {
926  {
927  FTextStream t(&outFile);
928 
929  t << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\""
930  " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
931  t << "<html><head><title></title>" << endl;
932  t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl;
933  t << "<meta name=\"generator\" content=\"Doxygen " << versionString << "\"/>" << endl;
934  t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl;
935  t << "<script type=\"text/javascript\" src=\"" << baseName << ".js\"></script>" << endl;
936  t << "<script type=\"text/javascript\" src=\"search.js\"></script>" << endl;
937  t << "</head>" << endl;
938  t << "<body class=\"SRPage\">" << endl;
939  t << "<div id=\"SRIndex\">" << endl;
940  t << "<div class=\"SRStatus\" id=\"Loading\">" << theTranslator->trLoading() << "</div>" << endl;
941  t << "<div id=\"SRResults\"></div>" << endl; // here the results will be inserted
942  t << "<script type=\"text/javascript\"><!--" << endl;
943  t << "createResults();" << endl; // this function will insert the results
944  t << "--></script>" << endl;
945  t << "<div class=\"SRStatus\" id=\"Searching\">"
946  << theTranslator->trSearching() << "</div>" << endl;
947  t << "<div class=\"SRStatus\" id=\"NoMatches\">"
948  << theTranslator->trNoMatches() << "</div>" << endl;
949 
950  t << "<script type=\"text/javascript\"><!--" << endl;
951  t << "document.getElementById(\"Loading\").style.display=\"none\";" << endl;
952  t << "document.getElementById(\"NoMatches\").style.display=\"none\";" << endl;
953  t << "var searchResults = new SearchResults(\"searchResults\");" << endl;
954  t << "searchResults.Search();" << endl;
955  t << "--></script>" << endl;
956  t << "</div>" << endl; // SRIndex
957  t << "</body>" << endl;
958  t << "</html>" << endl;
959  }
960  FTextStream ti(&dataOutFile);
961 
962  ti << "var searchData=" << endl;
963  // format
964  // searchData[] = array of items
965  // searchData[x][0] = id
966  // searchData[x][1] = [ name + child1 + child2 + .. ]
967  // searchData[x][1][0] = name as shown
968  // searchData[x][1][y+1] = info for child y
969  // searchData[x][1][y+1][0] = url
970  // searchData[x][1][y+1][1] = 1 => target="_parent"
971  // searchData[x][1][y+1][2] = scope
972 
973  ti << "[" << endl;
974  bool firstEntry=TRUE;
975 
978  int itemCount=0;
979  for (li.toFirst();(dl=li.current());++li)
980  {
981  Definition *d = dl->getFirst();
982 
983  if (!firstEntry)
984  {
985  ti << "," << endl;
986  }
987  firstEntry=FALSE;
988 
989  ti << " ['" << dl->id() << "',['" << convertToXML(dl->name()) << "',[";
990 
991  if (dl->count()==1) // item with a unique name
992  {
993  MemberDef *md = 0;
994  bool isMemberDef = d->definitionType()==Definition::TypeMember;
995  if (isMemberDef) md = (MemberDef*)d;
996  QCString anchor = d->anchor();
997 
998  ti << "'" << externalRef("../",d->getReference(),TRUE)
1000  if (!anchor.isEmpty())
1001  {
1002  ti << "#" << anchor;
1003  }
1004  ti << "',";
1005 
1006  static bool extLinksInWindow = Config_getBool("EXT_LINKS_IN_WINDOW");
1007  if (!extLinksInWindow || d->getReference().isEmpty())
1008  {
1009  ti << "1,";
1010  }
1011  else
1012  {
1013  ti << "0,";
1014  }
1015 
1017  {
1018  ti << "'" << convertToXML(d->getOuterScope()->name()) << "'";
1019  }
1020  else if (md)
1021  {
1022  FileDef *fd = md->getBodyDef();
1023  if (fd==0) fd = md->getFileDef();
1024  if (fd)
1025  {
1026  ti << "'" << convertToXML(fd->localName()) << "'";
1027  }
1028  }
1029  else
1030  {
1031  ti << "''";
1032  }
1033  ti << "]]";
1034  }
1035  else // multiple items with the same name
1036  {
1037  QListIterator<Definition> di(*dl);
1038  bool overloadedFunction = FALSE;
1039  Definition *prevScope = 0;
1040  int childCount=0;
1041  for (di.toFirst();(d=di.current());)
1042  {
1043  ++di;
1044  Definition *scope = d->getOuterScope();
1045  Definition *next = di.current();
1046  Definition *nextScope = 0;
1047  MemberDef *md = 0;
1048  bool isMemberDef = d->definitionType()==Definition::TypeMember;
1049  if (isMemberDef) md = (MemberDef*)d;
1050  if (next) nextScope = next->getOuterScope();
1051  QCString anchor = d->anchor();
1052 
1053  if (childCount>0)
1054  {
1055  ti << "],[";
1056  }
1057  ti << "'" << externalRef("../",d->getReference(),TRUE)
1059  if (!anchor.isEmpty())
1060  {
1061  ti << "#" << anchor;
1062  }
1063  ti << "',";
1064 
1065  static bool extLinksInWindow = Config_getBool("EXT_LINKS_IN_WINDOW");
1066  if (!extLinksInWindow || d->getReference().isEmpty())
1067  {
1068  ti << "1,";
1069  }
1070  else
1071  {
1072  ti << "0,";
1073  }
1074  bool found=FALSE;
1075  overloadedFunction = ((prevScope!=0 && scope==prevScope) ||
1076  (scope && scope==nextScope)
1077  ) && md &&
1078  (md->isFunction() || md->isSlot());
1079  QCString prefix;
1080  if (md) prefix=convertToXML(md->localName());
1081  if (overloadedFunction) // overloaded member function
1082  {
1083  prefix+=convertToXML(md->argsString());
1084  // show argument list to disambiguate overloaded functions
1085  }
1086  else if (md) // unique member function
1087  {
1088  prefix+="()"; // only to show it is a function
1089  }
1090  QCString name;
1092  {
1093  name = convertToXML(((ClassDef*)d)->displayName());
1094  found = TRUE;
1095  }
1097  {
1098  name = convertToXML(((NamespaceDef*)d)->displayName());
1099  found = TRUE;
1100  }
1101  else if (scope==0 || scope==Doxygen::globalScope) // in global scope
1102  {
1103  if (md)
1104  {
1105  FileDef *fd = md->getBodyDef();
1106  if (fd==0) fd = md->getFileDef();
1107  if (fd)
1108  {
1109  if (!prefix.isEmpty()) prefix+=":&#160;";
1110  name = prefix + convertToXML(fd->localName());
1111  found = TRUE;
1112  }
1113  }
1114  }
1115  else if (md && (md->getClassDef() || md->getNamespaceDef()))
1116  // member in class or namespace scope
1117  {
1118  SrcLangExt lang = md->getLanguage();
1119  name = convertToXML(d->getOuterScope()->qualifiedName())
1121  found = TRUE;
1122  }
1123  else if (scope) // some thing else? -> show scope
1124  {
1125  name = prefix + convertToXML(scope->name());
1126  found = TRUE;
1127  }
1128  if (!found) // fallback
1129  {
1130  name = prefix + "("+theTranslator->trGlobalNamespace()+")";
1131  }
1132 
1133  ti << "'" << name << "'";
1134 
1135  prevScope = scope;
1136  childCount++;
1137  }
1138 
1139  ti << "]]";
1140  }
1141  ti << "]";
1142  itemCount++;
1143  }
1144  if (!firstEntry)
1145  {
1146  ti << endl;
1147  }
1148 
1149  ti << "];" << endl;
1150 
1151  }
1152  else
1153  {
1154  err("Failed to open file '%s' for writing...\n",fileName.data());
1155  }
1156  }
1157  }
1158 
1159  {
1160  QFile f(searchDirName+"/searchdata.js");
1161  if (f.open(IO_WriteOnly))
1162  {
1163  FTextStream t(&f);
1164  t << "var indexSectionsWithContent =" << endl;
1165  t << "{" << endl;
1166  bool first=TRUE;
1167  int j=0;
1168  for (i=0;i<NUM_SEARCH_INDICES;i++)
1169  {
1170  if (g_searchIndexInfo[i].symbolList.count()>0)
1171  {
1172  if (!first) t << "," << endl;
1173  t << " " << j << ": \"";
1174 
1175  SIntDict<SearchIndexList>::Iterator it(g_searchIndexInfo[i].symbolList);
1176  SearchIndexList *sl;
1177  for (it.toFirst();(sl=it.current());++it) // for each letter
1178  {
1179  t << QString( QChar( sl->letter() ) ).utf8();
1180  }
1181  t << "\"";
1182  first=FALSE;
1183  j++;
1184  }
1185  }
1186  if (!first) t << "\n";
1187  t << "};" << endl << endl;
1188  t << "var indexSectionNames =" << endl;
1189  t << "{" << endl;
1190  first=TRUE;
1191  j=0;
1192  for (i=0;i<NUM_SEARCH_INDICES;i++)
1193  {
1194  if (g_searchIndexInfo[i].symbolList.count()>0)
1195  {
1196  if (!first) t << "," << endl;
1197  t << " " << j << ": \"" << g_searchIndexInfo[i].name << "\"";
1198  first=FALSE;
1199  j++;
1200  }
1201  }
1202  if (!first) t << "\n";
1203  t << "};" << endl << endl;
1204  t << "var indexSectionLabels =" << endl;
1205  t << "{" << endl;
1206  first=TRUE;
1207  j=0;
1208  for (i=0;i<NUM_SEARCH_INDICES;i++)
1209  {
1210  if (g_searchIndexInfo[i].symbolList.count()>0)
1211  {
1212  if (!first) t << "," << endl;
1213  t << " " << j << ": \"" << convertToXML(g_searchIndexInfo[i].text) << "\"";
1214  first=FALSE;
1215  j++;
1216  }
1217  }
1218  if (!first) t << "\n";
1219  t << "};" << endl << endl;
1220  }
1221  ResourceMgr::instance().copyResource("search.js",searchDirName);
1222  }
1223  {
1224  QFile f(searchDirName+"/nomatches.html");
1225  if (f.open(IO_WriteOnly))
1226  {
1227  FTextStream t(&f);
1228  t << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
1229  "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl;
1230  t << "<html><head><title></title>" << endl;
1231  t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl;
1232  t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl;
1233  t << "<script type=\"text/javascript\" src=\"search.js\"></script>" << endl;
1234  t << "</head>" << endl;
1235  t << "<body class=\"SRPage\">" << endl;
1236  t << "<div id=\"SRIndex\">" << endl;
1237  t << "<div class=\"SRStatus\" id=\"NoMatches\">"
1238  << theTranslator->trNoMatches() << "</div>" << endl;
1239  t << "</div>" << endl;
1240  t << "</body>" << endl;
1241  t << "</html>" << endl;
1242  }
1243  }
1244  Doxygen::indexList->addStyleSheetFile("search/search.js");
1245 }
1246 
1248 {
1249  return g_searchIndexInfo;
1250 }
1251 
1252 //---------------------------------------------------------------------------------------------
1253 
1255  : SDict< SearchDefinitionList >(17,FALSE), m_letter(letter)
1256 {
1258 }
1259 
1261 {
1262 }
1263 
1265 {
1266  SearchDefinitionList *l = find(d->name());
1267  if (l==0)
1268  {
1269  QCString dispName = d->localName();
1271  {
1272  dispName = ((GroupDef*)d)->groupTitle();
1273  }
1274  else if (d->definitionType()==Definition::TypePage)
1275  {
1276  dispName = ((PageDef*)d)->title();
1277  }
1278  l=new SearchDefinitionList(searchId(dispName),dispName);
1280  }
1281  l->append(d);
1282 }
1283 
1285 {
1286  return m_letter;
1287 }
1288 
1290 {
1291  QCString n1 = md1->getFirst()->localName();
1292  QCString n2 = md2->getFirst()->localName();
1293  return qstricmp(n1.data(),n2.data());
1294 }
1295 
1296 //---------------------------------------------------------------------------------------------
1297 
1299 {
1300  static bool searchEngine = Config_getBool("SEARCHENGINE");
1301  static bool serverBasedSearch = Config_getBool("SERVER_BASED_SEARCH");
1302  static bool externalSearch = Config_getBool("EXTERNAL_SEARCH");
1303  if (searchEngine && serverBasedSearch)
1304  {
1305  if (externalSearch) // external tools produce search index and engine
1306  {
1308  }
1309  else // doxygen produces search index and engine
1310  {
1312  }
1313  }
1314  else // no search engine or pure javascript based search function
1315  {
1317  }
1318 }
1319 
1321 {
1322  delete Doxygen::searchIndex;
1323 }
1324 
1325 
static QCString name
Definition: declinfo.cpp:673
QCString convertToXML(const char *s)
Definition: util.cpp:5717
virtual QCString trTypedefs()=0
uint count() const
Definition: qintdict.h:54
static GroupSDict * groupSDict
Definition: doxygen.h:119
static MemberNameSDict * functionNameSDict
Definition: doxygen.h:116
bool isProperty() const
Definition: memberdef.cpp:4185
long currentKey() const
Definition: qintdict.h:95
bool isLinkable() const
Definition: groupdef.cpp:1645
static QCString scope
Definition: declinfo.cpp:668
virtual QCString trClasses()=0
void addWord(const char *word, bool hiPriority)
virtual QCString trFile(bool first_capital, bool singular)=0
void write(const char *file)
virtual QCString getReference() const
bool isLinkable() const
Definition: filedef.h:117
void addStr(const char *s)
Definition: growbuf.h:19
static QCString result
bool isEmpty() const
Definition: qcstring.h:189
QCString word() const
Definition: searchindex.h:62
The QRegExp class provides pattern matching using regular expressions or wildcards.
Definition: qregexp.h:46
bool isFriend() const
Definition: memberdef.cpp:4175
QCString title() const
Definition: pagedef.h:54
#define SEARCH_INDEX_EVENTS
Definition: searchindex.h:125
uint length() const
Definition: qcstring.h:195
virtual QCString trEnumerationValues()=0
void append(const type *d)
Definition: qlist.h:73
bool isEvent() const
Definition: memberdef.cpp:4190
#define IO_WriteOnly
Definition: qiodevice.h:62
static QCString htmlFileExtension
Definition: doxygen.h:130
static int charsToIndex(const char *word)
virtual QCString trNoMatches()=0
virtual QCString trFriends()=0
char & at(uint i) const
Definition: qcstring.h:326
void write(const char *file)
FileDef * getBodyDef() const
QCString compoundTypeString() const
Definition: classdef.cpp:3499
QDict< int > m_url2IdMap
Definition: searchindex.h:94
QVector< QList< IndexWord > > m_index
Definition: searchindex.h:93
const bool FALSE
Definition: qglobal.h:370
static FileNameList * inputNameList
Definition: doxygen.h:109
bool copyResource(const char *name, const char *targetDir) const
Definition: types.h:26
static ResourceMgr & instance()
Definition: resourcemgr.cpp:35
#define SEARCH_INDEX_PROPERTIES
Definition: searchindex.h:124
static void addMemberToSearchIndex(MemberDef *md)
QIntDict< URLInfo > m_urls
Definition: searchindex.h:66
#define SEARCH_INDEX_VARIABLES
Definition: searchindex.h:120
static QCString stripPath(const QCString &s)
Definition: tagreader.cpp:1287
int putch(int)
Definition: qfile.cpp:386
int compareValues(const SearchDefinitionList *md1, const SearchDefinitionList *md2) const
#define SEARCH_INDEX_GROUPS
Definition: searchindex.h:128
bool isDefine() const
Definition: memberdef.cpp:4170
uint getUtf8CodeToLower(const QCString &s, int idx)
Returns one unicode character as an unsigned integer from utf-8 string, making the character lower ca...
Definition: util.cpp:8276
The QString class provides an abstraction of Unicode text and the classic C null-terminated char arra...
Definition: qstring.h:350
bool isSignal() const
Definition: memberdef.cpp:4130
TFile * outFile
Definition: makeDST.cxx:36
Simplified and optimized version of QTextStream.
Definition: ftextstream.h:11
bool isSlot() const
Definition: memberdef.cpp:4135
#define SEARCH_INDEX_ALL
Definition: searchindex.h:115
bool isVariable() const
Definition: memberdef.cpp:4140
virtual QCString getOutputFileBase() const =0
const char * groupTitle() const
Definition: groupdef.h:54
SearchIndexList(uint letter)
The QChar class provides a light-weight Unicode character.
Definition: qstring.h:56
void append(const char *key, const T *d)
Definition: sortdict.h:135
SrcLangExt
Definition: types.h:41
static QStrList * l
Definition: config.cpp:1044
virtual QCString trModule(bool first_capital, bool singular)=0
unsigned char uchar
Definition: nybbler.cc:11
IndexWord(const char *word)
Definition: searchindex.cpp:56
virtual QCString trSubprogram(bool first_capital, bool singular)=0
virtual QCString trLoading()=0
static void writeString(QFile &f, const char *s)
#define SEARCH_INDEX_RELATED
Definition: searchindex.h:126
void setAutoDelete(bool val)
Definition: sortdict.h:222
QCString id() const
Definition: searchindex.h:136
void append(Definition *d)
FileDef * getFileDef() const
Definition: memberdef.cpp:4075
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
static NamespaceSDict * namespaceSDict
Definition: doxygen.h:120
static NamespaceDef * globalScope
Definition: doxygen.h:128
virtual QCString trGlobalNamespace()=0
ClassDef * templateMaster() const
Definition: classdef.cpp:4439
virtual DefType definitionType() const =0
def cli(ctx)
Definition: main.py:7
const char * typeString() const
Definition: memberdef.cpp:4035
QCString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Definition: util.cpp:8065
uint count() const
Definition: qlist.h:66
QAsciiDict< Entry > fn
static SearchIndexIntf * searchIndex
Definition: doxygen.h:133
void insert(long k, const type *d)
Definition: qintdict.h:57
QIntDict< URL > m_urls
Definition: searchindex.h:95
void addChar(char c)
Definition: growbuf.h:16
const QCString & name() const
Definition: definition.h:114
const double e
bool isEnumValue() const
Definition: memberdef.cpp:4150
int qstricmp(const char *str1, const char *str2)
Definition: qcstring.cpp:567
fileName
Definition: dumpTree.py:9
void createJavascriptSearchIndex()
QCString name() const
Definition: filedef.cpp:1193
def key(type, name=None)
Definition: graph.py:13
static QCString definitionToName(Definition *ctx)
bool isEmpty() const
Definition: qlist.h:67
virtual QCString trVariables()=0
void finializeSearchIndexer()
SrcLangExt getLanguage() const
std::void_t< T > n
bool open(int)
Definition: qfile_unix.cpp:134
void addStyleSheetFile(const char *name)
Definition: index.h:149
char versionString[]
Definition: version.cpp:1
bool isForeign() const
Definition: memberdef.cpp:4200
int m_urlIndex
Definition: searchindex.h:96
QCString & prepend(const char *s)
Definition: qcstring.cpp:387
virtual QCString trFunctions()=0
p
Definition: test.py:223
#define SEARCH_INDEX_PAGES
Definition: searchindex.h:129
bool isLinkable() const
#define SEARCH_INDEX_FILES
Definition: searchindex.h:118
A bunch of utility functions.
static PageSDict * pageSDict
Definition: doxygen.h:102
const char * data() const
Definition: qcstring.h:207
#define SEARCH_INDEX_ENUMS
Definition: searchindex.h:122
static SearchIndexInfo g_searchIndexInfo[NUM_SEARCH_INDICES]
bool isLinkable() const
Definition: classdef.cpp:2729
#define Config_getString(val)
Definition: config.cpp:660
static QCString searchId(const QCString &s)
type * current() const
Definition: qlist.h:146
#define Config_getBool(val)
Definition: config.cpp:664
ClassDef * getClassDef() const
Definition: memberdef.cpp:4070
type * getFirst() const
Definition: qlist.h:95
virtual QCString trGroup(bool first_capital, bool singular)=0
int getPrefixIndex(const QCString &name)
Definition: util.cpp:5144
virtual QCString qualifiedName() const
void initSearchIndexer()
const int numIndexEntries
Definition: searchindex.cpp:52
GrowBuf normalText
void err(const char *fmt,...)
Definition: message.cpp:226
#define SEARCH_INDEX_NAMESPACES
Definition: searchindex.h:117
SDict< SearchDocEntry > docEntries
#define SEARCH_INDEX_TYPEDEFS
Definition: searchindex.h:121
virtual QCString trEnumerations()=0
void addWord(const char *word, bool hiPriority)
virtual QCString trAll()=0
bool isLinkable() const
Definition: pagedef.h:45
int match(const QCString &str, int index=0, int *len=0, bool indexIsStart=TRUE) const
Definition: qregexp.cpp:649
The QFile class is an I/O device that operates on files.
Definition: qfile.h:50
virtual QCString trPage(bool first_capital, bool singular)=0
void setAutoDelete(bool enable)
Definition: qcollection.h:55
QCString & sprintf(const char *format,...)
Definition: qcstring.cpp:27
void setCurrentDoc(Definition *ctx, const char *anchor, bool isSourceFile)
Definition: searchindex.cpp:89
virtual QCString trEvents()=0
virtual Definition * getOuterScope() const
GroupDef * getGroupDef() const
Definition: memberdef.cpp:4095
virtual QCString trPackage(const char *name)=0
void sort()
Definition: sortdict.h:188
uint letter() const
const char * get()
Definition: growbuf.h:38
#define NUM_SEARCH_INDICES
Definition: searchindex.h:130
int freq
Definition: searchindex.h:53
static MemberNameSDict * memberNameSDict
Definition: doxygen.h:115
const QIntDict< URLInfo > & urls() const
Definition: searchindex.h:61
A model of a page symbol.
Definition: pagedef.h:29
void append(uint letter, typename T::ElementType *elem)
Definition: util.h:100
virtual QCString trNamespace(bool first_capital, bool singular)=0
static void writeInt(QFile &f, int index)
#define SEARCH_INDEX_DEFINES
Definition: searchindex.h:127
#define SEARCH_INDEX_FUNCTIONS
Definition: searchindex.h:119
type * current() const
Definition: qintdict.h:94
QCString doc
void setCurrentDoc(Definition *ctx, const char *anchor, bool isSourceFile)
QCString name
Definition: searchindex.h:44
NamespaceDef * getNamespaceDef() const
Definition: memberdef.cpp:4080
Translator * theTranslator
Definition: language.cpp:157
bool isId(int c)
Definition: util.h:224
bool isFunction() const
Definition: memberdef.cpp:4160
friend class Iterator
Definition: sortdict.h:289
QDict< IndexWord > m_words
Definition: searchindex.h:92
void addUrlIndex(int, bool)
Definition: searchindex.cpp:62
void writeJavascriptSearchIndex()
virtual QCString trProperties()=0
LetterToIndexMap< SearchIndexList > symbolList
Definition: searchindex.h:158
static QCString baseName
Definition: scanner.cpp:10890
bool isRelated() const
Definition: memberdef.cpp:4195
int getPos() const
Definition: growbuf.h:39
virtual QCString trSearching()=0
#define SEARCH_INDEX_ENUMVALUES
Definition: searchindex.h:123
const char * argsString() const
Definition: memberdef.cpp:4040
type * toFirst()
Definition: qintdict.h:92
QCString lower() const
Definition: qcstring.cpp:263
bool isTypedef() const
Definition: memberdef.cpp:4155
#define SEARCH_INDEX_CLASSES
Definition: searchindex.h:116
T * find(const char *key)
Definition: sortdict.h:232
const SearchIndexInfo * getSearchIndices()
QCString utf8() const
Definition: qstring.cpp:14507
unsigned uint
Definition: qglobal.h:351
static ClassSDict * classSDict
Definition: doxygen.h:99
bool isLinkable() const
Definition: memberdef.cpp:1161
static PageDef * mainPage
Definition: doxygen.h:103
virtual QCString trMember(bool first_capital, bool singular)=0
static QCString * s
Definition: config.cpp:1042
QCString localName() const
union ptb::content::word::word word
const bool TRUE
Definition: qglobal.h:371
static IndexList * indexList
Definition: doxygen.h:149
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition: util.cpp:5088
virtual QCString anchor() const =0
type * find(long k) const
Definition: qintdict.h:63
QTextStream & endl(QTextStream &s)
bool insert(uint i, const type *d)
Definition: qvector.h:61
bool isEnumerate() const
Definition: memberdef.cpp:4145
QCString url
Definition: searchindex.h:45
GrowBuf importantText
Definition: qlist.h:54
QCString externalRef(const QCString &relPath, const QCString &ref, bool href)
Definition: util.cpp:7856
QCString name() const
Definition: searchindex.h:137
type * toFirst()
Definition: qlist.h:135
virtual QCString trDefines()=0