My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
definition.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 <qregexp.h>
20 #include "md5.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <assert.h>
24 #include "config.h"
25 #include "definition.h"
26 #include "doxygen.h"
27 #include "language.h"
28 #include "message.h"
29 #include "outputlist.h"
30 #include "code.h"
31 #include "util.h"
32 #include "groupdef.h"
33 #include "pagedef.h"
34 #include "section.h"
35 #include "htags.h"
36 #include "parserintf.h"
37 #include "marshal.h"
38 #include "debug.h"
39 #include "vhdldocgen.h"
40 #include "memberlist.h"
41 #include "namespacedef.h"
42 #include "filedef.h"
43 #include "dirdef.h"
44 
45 #define START_MARKER 0x4445465B // DEF[
46 #define END_MARKER 0x4445465D // DEF]
47 
48 //-----------------------------------------------------------------------------------------
49 
50 
53 {
54  public:
57  void init(const char *df, const char *n);
58 
59  SectionDict *sectionDict; // dictionary of all sections, not accessible
60 
63  QList<ListItemInfo> *xrefListItems;
65 
66  DocInfo *details; // not exported
67  DocInfo *inbodyDocs; // not exported
68  BriefInfo *brief; // not exported
69  BodyInfo *body; // not exported
70  QCString briefSignatures;
71  QCString docSignatures;
72 
73  QCString localName; // local (unqualified) name of the definition
74  // in the future m_name should become m_localName
75  QCString qualifiedName;
76  QCString ref; // reference to external documentation
77 
78  bool hidden;
80 
81  Definition *outerScope; // not owner
82 
83  // where the item was found
84  QCString defFileName;
85  QCString defFileExt;
86 
88 
89  QCString id; // clang unique id
90 };
91 
93  : sectionDict(0), sourceRefByDict(0), sourceRefsDict(0),
94  xrefListItems(0), partOfGroups(0),
95  details(0), inbodyDocs(0), brief(0), body(0), hidden(FALSE), isArtificial(FALSE),
96  outerScope(0), lang(SrcLangExt_Unknown)
97 {
98 }
99 
101 {
102  delete sectionDict;
103  delete sourceRefByDict;
104  delete sourceRefsDict;
105  delete partOfGroups;
106  delete xrefListItems;
107  delete brief;
108  delete details;
109  delete body;
110  delete inbodyDocs;
111 }
112 
113 void DefinitionImpl::init(const char *df, const char *n)
114 {
115  defFileName = df;
116  int lastDot = defFileName.findRev('.');
117  if (lastDot!=-1)
118  {
119  defFileExt = defFileName.mid(lastDot);
120  }
121  QCString name = n;
122  if (name!="<globalScope>")
123  {
124  //extractNamespaceName(m_name,m_localName,ns);
126  }
127  else
128  {
129  localName=n;
130  }
131  //printf("m_localName=%s\n",m_localName.data());
132 
133  brief = 0;
134  details = 0;
135  body = 0;
136  inbodyDocs = 0;
137  sourceRefByDict = 0;
138  sourceRefsDict = 0;
139  sectionDict = 0,
141  partOfGroups = 0;
142  xrefListItems = 0;
143  hidden = FALSE;
144  isArtificial = FALSE;
146 }
147 
148 //-----------------------------------------------------------------------------------------
149 
150 static bool matchExcludedSymbols(const char *name)
151 {
152  static QStrList &exclSyms = Config_getList(EXCLUDE_SYMBOLS);
153  if (exclSyms.count()==0) return FALSE; // nothing specified
154  const char *pat = exclSyms.first();
155  QCString symName = name;
156  while (pat)
157  {
158  QCString pattern = pat;
159  bool forceStart=FALSE;
160  bool forceEnd=FALSE;
161  if (pattern.at(0)=='^')
162  pattern=pattern.mid(1),forceStart=TRUE;
163  if (pattern.at(pattern.length()-1)=='$')
164  pattern=pattern.left(pattern.length()-1),forceEnd=TRUE;
165  if (pattern.find('*')!=-1) // wildcard mode
166  {
167  QRegExp re(substitute(pattern,"*",".*"),TRUE);
168  int i,pl;
169  i = re.match(symName,0,&pl);
170  //printf(" %d = re.match(%s) pattern=%s\n",i,symName.data(),pattern.data());
171  if (i!=-1) // wildcard match
172  {
173  int sl=symName.length();
174  // check if it is a whole word match
175  if ((i==0 || pattern.at(0)=='*' || (!isId(symName.at(i-1)) && !forceStart)) &&
176  (i+pl==sl || pattern.at(i+pl)=='*' || (!isId(symName.at(i+pl)) && !forceEnd))
177  )
178  {
179  //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i);
180  return TRUE;
181  }
182  }
183  }
184  else if (!pattern.isEmpty()) // match words
185  {
186  int i = symName.find(pattern);
187  if (i!=-1) // we have a match!
188  {
189  int pl=pattern.length();
190  int sl=symName.length();
191  // check if it is a whole word match
192  if ((i==0 || (!isId(symName.at(i-1)) && !forceStart)) &&
193  (i+pl==sl || (!isId(symName.at(i+pl)) && !forceEnd))
194  )
195  {
196  //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i);
197  return TRUE;
198  }
199  }
200  }
201  pat = exclSyms.next();
202  }
203  //printf("--> name=%s: no match\n",name);
204  return FALSE;
205 }
206 
207 void Definition::addToMap(const char *name,Definition *d)
208 {
209  bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
210  QCString symbolName = name;
211  int index=computeQualifiedIndex(symbolName);
212  if (!vhdlOpt && index!=-1) symbolName=symbolName.mid(index+2);
213  if (!symbolName.isEmpty())
214  {
215  //printf("******* adding symbol `%s' (%p)\n",symbolName.data(),d);
216  DefinitionIntf *di=Doxygen::symbolMap->find(symbolName);
217  //printf(" addToMap(%p): looking for symbol %s: %p\n",d,symbolName.data(),di);
218  if (di==0) // new Symbol
219  {
220  //printf(" new symbol!\n");
221  Doxygen::symbolMap->insert(symbolName,d);
222  }
223  else // existing symbol
224  {
225  //printf(" existing symbol: ");
226  if (di->definitionType()==DefinitionIntf::TypeSymbolList) // already multiple symbols
227  {
228  //printf("adding to exiting list\n");
229  DefinitionList *dl = (DefinitionList*)di;
230  dl->append(d);
231  }
232  else // going from one to two symbols
233  {
234  Doxygen::symbolMap->take(symbolName);
235  DefinitionList *dl = new DefinitionList;
236  //printf("replacing symbol by list %p with elements %p and %p\n",dl,di,d);
237  dl->append((Definition*)di);
238  dl->append(d);
239  Doxygen::symbolMap->insert(symbolName,dl);
240  }
241  }
242 
243  // auto resize if needed
244  static int sizeIndex=9;
245  if (Doxygen::symbolMap->size()>SDict_primes[sizeIndex])
246  {
247  Doxygen::symbolMap->resize(SDict_primes[++sizeIndex]);
248  }
249 
250  d->_setSymbolName(symbolName);
251  }
252 }
253 
255 {
256  QCString symbolName = d->m_symbolName;
257  if (!symbolName.isEmpty())
258  {
259  //printf("******* removing symbol `%s' (%p)\n",symbolName.data(),d);
260  DefinitionIntf *di=Doxygen::symbolMap->find(symbolName);
261  if (di)
262  {
263  if (di!=d) // symbolName not unique
264  {
265  //printf(" removing from list: %p!\n",di);
266  DefinitionList *dl = (DefinitionList*)di;
267  bool b = dl->removeRef(d);
268  ASSERT(b==TRUE);
269  if (dl->isEmpty())
270  {
271  Doxygen::symbolMap->take(symbolName);
272  }
273  }
274  else // symbolName unique
275  {
276  //printf(" removing symbol %p\n",di);
277  Doxygen::symbolMap->take(symbolName);
278  }
279  }
280  }
281 }
282 
283 Definition::Definition(const char *df,int dl,int dc,
284  const char *name,const char *b,
285  const char *d,bool isSymbol) : m_cookie(0)
286 {
287  m_name = name;
288  m_defLine = dl;
289  m_defColumn = dc;
290  m_impl = new DefinitionImpl;
291  m_impl->init(df,name);
292  m_isSymbol = isSymbol;
293  if (isSymbol) addToMap(name,this);
294  _setBriefDescription(b,df,dl);
295  _setDocumentation(d,df,dl,TRUE,FALSE);
296  if (matchExcludedSymbols(name))
297  {
298  m_impl->hidden = TRUE;
299  }
300 }
301 
303 {
304  m_name = d.m_name;
305  m_defLine = d.m_defLine;
306  m_impl = new DefinitionImpl;
307  *m_impl = *d.m_impl;
308  m_impl->sectionDict = 0;
309  m_impl->sourceRefByDict = 0;
310  m_impl->sourceRefsDict = 0;
311  m_impl->partOfGroups = 0;
312  m_impl->xrefListItems = 0;
313  m_impl->brief = 0;
314  m_impl->details = 0;
315  m_impl->body = 0;
316  m_impl->inbodyDocs = 0;
317  if (d.m_impl->sectionDict)
318  {
319  m_impl->sectionDict = new SectionDict(17);
321  SectionInfo *si;
322  for (it.toFirst();(si=it.current());++it)
323  {
324  m_impl->sectionDict->append(si->label,si);
325  }
326  }
327  if (d.m_impl->sourceRefByDict)
328  {
331  MemberDef *md;
332  for (it.toFirst();(md=it.current());++it)
333  {
334  m_impl->sourceRefByDict->append(it.currentKey(),md);
335  }
336  }
337  if (d.m_impl->sourceRefsDict)
338  {
341  MemberDef *md;
342  for (it.toFirst();(md=it.current());++it)
343  {
344  m_impl->sourceRefsDict->append(it.currentKey(),md);
345  }
346  }
347  if (d.m_impl->partOfGroups)
348  {
350  GroupDef *gd;
351  for (it.toFirst();(gd=it.current());++it)
352  {
353  makePartOfGroup(gd);
354  }
355  }
356  if (d.m_impl->xrefListItems)
357  {
359  }
360  if (d.m_impl->brief)
361  {
362  m_impl->brief = new BriefInfo(*d.m_impl->brief);
363  }
364  if (d.m_impl->details)
365  {
366  m_impl->details = new DocInfo(*d.m_impl->details);
367  }
368  if (d.m_impl->body)
369  {
370  m_impl->body = new BodyInfo(*d.m_impl->body);
371  }
372  if (d.m_impl->inbodyDocs)
373  {
375  }
376 
378  if (m_isSymbol) addToMap(m_name,this);
379 }
380 
382 {
383  if (m_isSymbol)
384  {
385  removeFromMap(this);
386  }
387  if (m_impl)
388  {
389  delete m_impl;
390  m_impl=0;
391  }
392  delete m_cookie;
393  m_cookie=0;
394 }
395 
396 void Definition::setName(const char *name)
397 {
398  if (name==0) return;
399  m_name = name;
400 }
401 
402 void Definition::setId(const char *id)
403 {
404  if (id==0) return;
405  m_impl->id = id;
407  {
408  //printf("Definition::setId '%s'->'%s'\n",id,m_name.data());
409  Doxygen::clangUsrMap->insert(id,this);
410  }
411 }
412 
413 QCString Definition::id() const
414 {
415  return m_impl->id;
416 }
417 
418 void Definition::addSectionsToDefinition(QList<SectionInfo> *anchorList)
419 {
420  if (!anchorList) return;
421  //printf("%s: addSectionsToDefinition(%d)\n",name().data(),anchorList->count());
422  QListIterator<SectionInfo> it(*anchorList);
423  SectionInfo *si;
424  for (;(si=it.current());++it)
425  {
426  //printf("Add section `%s' to definition `%s'\n",
427  // si->label.data(),name().data());
429  //printf("===== label=%s gsi=%p\n",si->label.data(),gsi);
430  if (gsi==0)
431  {
432  gsi = new SectionInfo(*si);
434  }
435  if (m_impl->sectionDict==0)
436  {
437  m_impl->sectionDict = new SectionDict(17);
438  }
439  if (m_impl->sectionDict->find(gsi->label)==0)
440  {
441  m_impl->sectionDict->append(gsi->label,gsi);
442  gsi->definition = this;
443  }
444  }
445 }
446 
448 {
449  //printf("Definition::hasSections(%s) #sections=%d\n",name().data(),
450  // m_impl->sectionDict ? m_impl->sectionDict->count() : 0);
451  if (m_impl->sectionDict==0) return FALSE;
453  SectionInfo *si;
454  for (li.toFirst();(si=li.current());++li)
455  {
456  if (si->type==SectionInfo::Section ||
460  {
461  return TRUE;
462  }
463  }
464  return FALSE;
465 }
466 
468 {
469  if (m_impl->sectionDict==0) return;
470  //printf("Definition::addSectionsToIndex()\n");
472  SectionInfo *si;
473  int level=1;
474  for (li.toFirst();(si=li.current());++li)
475  {
476  if (si->type==SectionInfo::Section ||
480  {
481  //printf(" level=%d title=%s\n",level,si->title.data());
482  int nextLevel = (int)si->type;
483  int i;
484  if (nextLevel>level)
485  {
486  for (i=level;i<nextLevel;i++)
487  {
489  }
490  }
491  else if (nextLevel<level)
492  {
493  for (i=nextLevel;i<level;i++)
494  {
496  }
497  }
498  QCString title = si->title;
499  if (title.isEmpty()) title = si->label;
500  // determine if there is a next level inside this item
501  ++li;
502  bool isDir = ((li.current()) ? (int)(li.current()->type > nextLevel):FALSE);
503  --li;
504  Doxygen::indexList->addContentsItem(isDir,title,
505  getReference(),
507  si->label,
508  FALSE,
509  TRUE);
510  level = nextLevel;
511  }
512  }
513  while (level>1)
514  {
516  level--;
517  }
518 }
519 
521 {
522  if (m_impl->sectionDict)
523  {
524  //printf("%s: writeDocAnchorsToTagFile(%d)\n",name().data(),m_impl->sectionDict->count());
526  SectionInfo *si;
527  for (;(si=sdi.current());++sdi)
528  {
529  if (!si->generated && si->ref.isEmpty())
530  {
531  //printf("write an entry!\n");
532  if (definitionType()==TypeMember) tagFile << " ";
533  tagFile << " <docanchor file=\"" << si->fileName << "\"";
534  if (!si->title.isEmpty())
535  {
536  tagFile << " title=\"" << convertToXML(si->title) << "\"";
537  }
538  tagFile << ">" << si->label << "</docanchor>" << endl;
539  }
540  }
541  }
542 }
543 
544 bool Definition::_docsAlreadyAdded(const QCString &doc,QCString &sigList)
545 {
546  uchar md5_sig[16];
547  QCString sigStr(33);
548  // to avoid mismatches due to differences in indenting, we first remove
549  // double whitespaces...
550  QCString docStr = doc.simplifyWhiteSpace();
551  MD5Buffer((const unsigned char *)docStr.data(),docStr.length(),md5_sig);
552  MD5SigToString(md5_sig,sigStr.rawData(),33);
553  //printf("%s:_docsAlreadyAdded doc='%s' sig='%s' docSigs='%s'\n",
554  // name().data(),doc.data(),sigStr.data(),sigList.data());
555  if (sigList.find(sigStr)==-1) // new docs, add signature to prevent re-adding it
556  {
557  sigList+=":"+sigStr;
558  return FALSE;
559  }
560  else
561  {
562  return TRUE;
563  }
564 }
565 
566 void Definition::_setDocumentation(const char *d,const char *docFile,int docLine,
567  bool stripWhiteSpace,bool atTop)
568 {
569  //printf("%s::setDocumentation(%s,%s,%d,%d)\n",name().data(),d,docFile,docLine,stripWhiteSpace);
570  if (d==0) return;
571  QCString doc = d;
572  if (stripWhiteSpace)
573  {
574  doc = stripLeadingAndTrailingEmptyLines(doc,docLine);
575  }
576  else // don't strip whitespace
577  {
578  doc=d;
579  }
581  {
582  //printf("setting docs for %s: `%s'\n",name().data(),m_doc.data());
583  if (m_impl->details==0)
584  {
585  m_impl->details = new DocInfo;
586  }
587  if (m_impl->details->doc.isEmpty()) // fresh detailed description
588  {
589  m_impl->details->doc = doc;
590  }
591  else if (atTop) // another detailed description, append it to the start
592  {
593  m_impl->details->doc = doc+"\n\n"+m_impl->details->doc;
594  }
595  else // another detailed description, append it to the end
596  {
597  m_impl->details->doc += "\n\n"+doc;
598  }
599  if (docLine!=-1) // store location if valid
600  {
603  }
604  else
605  {
607  m_impl->details->line = 1;
608  }
609  }
610 }
611 
612 void Definition::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace)
613 {
614  if (d==0) return;
615  _setDocumentation(d,docFile,docLine,stripWhiteSpace,FALSE);
616 }
617 
618 #define uni_isupper(c) (QChar(c).category()==QChar::Letter_Uppercase)
619 
620 // do a UTF-8 aware search for the last real character and return TRUE
621 // if that is a multibyte one.
622 static bool lastCharIsMultibyte(const QCString &s)
623 {
624  int l = s.length();
625  int p = 0;
626  int pp = -1;
627  while ((p=nextUtf8CharPosition(s,l,p))<l) pp=p;
628  if (pp==-1 || ((uchar)s[pp])<0x80) return FALSE;
629  return TRUE;
630 }
631 
632 void Definition::_setBriefDescription(const char *b,const char *briefFile,int briefLine)
633 {
634  static QCString outputLanguage = Config_getEnum(OUTPUT_LANGUAGE);
635  static bool needsDot = outputLanguage!="Japanese" &&
636  outputLanguage!="Chinese" &&
637  outputLanguage!="Korean";
638  QCString brief = b;
639  brief = brief.stripWhiteSpace();
640  if (brief.isEmpty()) return;
641  int bl = brief.length();
642  if (bl>0 && needsDot) // add punctuation if needed
643  {
644  int c = brief.at(bl-1);
645  switch(c)
646  {
647  case '.': case '!': case '?': case '>': case ':': case ')': break;
648  default:
649  if (uni_isupper(brief.at(0)) && !lastCharIsMultibyte(brief)) brief+='.';
650  break;
651  }
652  }
653 
655  {
656  if (m_impl->brief && !m_impl->brief->doc.isEmpty())
657  {
658  //printf("adding to details\n");
659  _setDocumentation(brief,briefFile,briefLine,FALSE,TRUE);
660  }
661  else
662  {
663  //fprintf(stderr,"Definition::setBriefDescription(%s,%s,%d)\n",b,briefFile,briefLine);
664  if (m_impl->brief==0)
665  {
666  m_impl->brief = new BriefInfo;
667  }
668  m_impl->brief->doc=brief;
669  if (briefLine!=-1)
670  {
673  }
674  else
675  {
677  m_impl->brief->line = 1;
678  }
679  }
680  }
681  else
682  {
683  //printf("do nothing!\n");
684  }
685 }
686 
687 void Definition::setBriefDescription(const char *b,const char *briefFile,int briefLine)
688 {
689  if (b==0) return;
690  _setBriefDescription(b,briefFile,briefLine);
691 }
692 
693 void Definition::_setInbodyDocumentation(const char *doc,const char *inbodyFile,int inbodyLine)
694 {
695  if (m_impl->inbodyDocs==0)
696  {
697  m_impl->inbodyDocs = new DocInfo;
698  }
699  if (m_impl->inbodyDocs->doc.isEmpty()) // fresh inbody docs
700  {
701  m_impl->inbodyDocs->doc = doc;
704  }
705  else // another inbody documentation fragment, append this to the end
706  {
707  m_impl->inbodyDocs->doc += QCString("\n\n")+doc;
708  }
709 }
710 
711 void Definition::setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine)
712 {
713  if (d==0) return;
714  _setInbodyDocumentation(d,inbodyFile,inbodyLine);
715 }
716 
728 bool readCodeFragment(const char *fileName,
729  int &startLine,int &endLine,QCString &result)
730 {
731  static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
732  static int tabSize = Config_getInt(TAB_SIZE);
733  //printf("readCodeFragment(%s,%d,%d)\n",fileName,startLine,endLine);
734  if (fileName==0 || fileName[0]==0) return FALSE; // not a valid file name
735  QCString filter = getFileFilter(fileName,TRUE);
736  FILE *f=0;
737  bool usePipe = !filter.isEmpty() && filterSourceFiles;
738  SrcLangExt lang = getLanguageFromFileName(fileName);
739  if (!usePipe) // no filter given or wanted
740  {
741  f = portable_fopen(fileName,"r");
742  }
743  else // use filter
744  {
745  QCString cmd=filter+" \""+fileName+"\"";
746  Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd));
747  f = portable_popen(cmd,"r");
748  }
749  bool found = lang==SrcLangExt_VHDL ||
750  lang==SrcLangExt_Tcl ||
751  lang==SrcLangExt_Python ||
752  lang==SrcLangExt_Fortran;
753  // for VHDL, TCL, Python, and Fortran no bracket search is possible
754  if (f)
755  {
756  int c=0;
757  int col=0;
758  int lineNr=1;
759  // skip until the startLine has reached
760  while (lineNr<startLine && !feof(f))
761  {
762  while ((c=fgetc(f))!='\n' && c!=EOF) /* skip */;
763  lineNr++;
764  if (found && c == '\n') c = '\0';
765  }
766  if (!feof(f))
767  {
768  // skip until the opening bracket or lonely : is found
769  char cn=0;
770  while (lineNr<=endLine && !feof(f) && !found)
771  {
772  int pc=0;
773  while ((c=fgetc(f))!='{' && c!=':' && c!=EOF) // } so vi matching brackets has no problem
774  {
775  //printf("parsing char `%c'\n",c);
776  if (c=='\n')
777  {
778  lineNr++,col=0;
779  }
780  else if (c=='\t')
781  {
782  col+=tabSize - (col%tabSize);
783  }
784  else if (pc=='/' && c=='/') // skip single line comment
785  {
786  while ((c=fgetc(f))!='\n' && c!=EOF) pc=c;
787  if (c=='\n') lineNr++,col=0;
788  }
789  else if (pc=='/' && c=='*') // skip C style comment
790  {
791  while (((c=fgetc(f))!='/' || pc!='*') && c!=EOF)
792  {
793  if (c=='\n') lineNr++,col=0;
794  pc=c;
795  }
796  }
797  else
798  {
799  col++;
800  }
801  pc = c;
802  }
803  if (c==':')
804  {
805  cn=fgetc(f);
806  if (cn!=':') found=TRUE;
807  }
808  else if (c=='{') // } so vi matching brackets has no problem
809  {
810  found=TRUE;
811  }
812  }
813  //printf(" -> readCodeFragment(%s,%d,%d) lineNr=%d\n",fileName,startLine,endLine,lineNr);
814  if (found)
815  {
816  // For code with more than one line,
817  // fill the line with spaces until we are at the right column
818  // so that the opening brace lines up with the closing brace
819  if (endLine!=startLine)
820  {
821  QCString spaces;
822  spaces.fill(' ',col);
823  result+=spaces;
824  }
825  // copy until end of line
826  if (c) result+=c;
827  startLine=lineNr;
828  if (c==':')
829  {
830  result+=cn;
831  if (cn=='\n') lineNr++;
832  }
833  const int maxLineLength=4096;
834  char lineStr[maxLineLength];
835  do
836  {
837  //printf("reading line %d in range %d-%d\n",lineNr,startLine,endLine);
838  int size_read;
839  do
840  {
841  // read up to maxLineLength-1 bytes, the last byte being zero
842  char *p = fgets(lineStr, maxLineLength,f);
843  //printf(" read %s",p);
844  if (p)
845  {
846  size_read=qstrlen(p);
847  }
848  else // nothing read
849  {
850  size_read=-1;
851  lineStr[0]='\0';
852  }
853  result+=lineStr;
854  } while (size_read == (maxLineLength-1));
855 
856  lineNr++;
857  } while (lineNr<=endLine && !feof(f));
858 
859  // strip stuff after closing bracket
860  int newLineIndex = result.findRev('\n');
861  int braceIndex = result.findRev('}');
862  if (braceIndex > newLineIndex)
863  {
864  result.truncate(braceIndex+1);
865  }
866  endLine=lineNr-1;
867  }
868  }
869  if (usePipe)
870  {
871  portable_pclose(f);
872  Debug::print(Debug::FilterOutput, 0, "Filter output\n");
873  Debug::print(Debug::FilterOutput,0,"-------------\n%s\n-------------\n",qPrint(result));
874  }
875  else
876  {
877  fclose(f);
878  }
879  }
880  result = transcodeCharacterStringToUTF8(result);
881  if (!result.isEmpty() && result.at(result.length()-1)!='\n') result += "\n";
882  //fprintf(stderr,"readCodeFragement(%d-%d)=%s\n",startLine,endLine,result.data());
883  return found;
884 }
885 
887 {
888  ASSERT(definitionType()!=Definition::TypeFile); // file overloads this method
889  QCString fn;
890  static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
891  if (sourceBrowser &&
893  {
895  }
896  return fn;
897 }
898 
900 {
901  const int maxAnchorStrLen = 20;
902  char anchorStr[maxAnchorStrLen];
903  anchorStr[0]='\0';
904  if (m_impl->body && m_impl->body->startLine!=-1)
905  {
906  if (Htags::useHtags)
907  {
908  qsnprintf(anchorStr,maxAnchorStrLen,"L%d",m_impl->body->startLine);
909  }
910  else
911  {
912  qsnprintf(anchorStr,maxAnchorStrLen,"l%05d",m_impl->body->startLine);
913  }
914  }
915  return anchorStr;
916 }
917 
920 {
921  static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE);
922  static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE);
923  ol.pushGeneratorState();
924  //printf("Definition::writeSourceRef %d %p\n",bodyLine,bodyDef);
925  QCString fn = getSourceFileBase();
926  if (!fn.isEmpty())
927  {
928  QCString refText = theTranslator->trDefinedAtLineInSourceFile();
929  int lineMarkerPos = refText.find("@0");
930  int fileMarkerPos = refText.find("@1");
931  if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this.
932  {
933  QCString lineStr;
934  lineStr.sprintf("%d",m_impl->body->startLine);
935  QCString anchorStr = getSourceAnchor();
936  ol.startParagraph();
937  if (lineMarkerPos<fileMarkerPos) // line marker before file marker
938  {
939  // write text left from linePos marker
940  ol.parseText(refText.left(lineMarkerPos));
941  ol.pushGeneratorState();
943  if (!latexSourceCode)
944  {
946  }
947  if (!rtfSourceCode)
948  {
950  }
951  // write line link (HTML, LaTeX optionally, RTF optionally)
952  ol.writeObjectLink(0,fn,anchorStr,lineStr);
953  ol.enableAll();
955  if (latexSourceCode)
956  {
958  }
959  if (rtfSourceCode)
960  {
962  }
963  // write normal text (Man, Latex optionally, RTF optionally)
964  ol.docify(lineStr);
965  ol.popGeneratorState();
966 
967  // write text between markers
968  ol.parseText(refText.mid(lineMarkerPos+2,
969  fileMarkerPos-lineMarkerPos-2));
970 
971  ol.pushGeneratorState();
973  if (!latexSourceCode)
974  {
976  }
977  if (!rtfSourceCode)
978  {
980  }
981  // write file link (HTML, LaTeX optionally, RTF optionally)
982  ol.writeObjectLink(0,fn,0,m_impl->body->fileDef->name());
983  ol.enableAll();
985  if (latexSourceCode)
986  {
988  }
989  if (rtfSourceCode)
990  {
992  }
993  // write normal text (Man, Latex optionally, RTF optionally)
994  ol.docify(m_impl->body->fileDef->name());
995  ol.popGeneratorState();
996 
997  // write text right from file marker
998  ol.parseText(refText.right(
999  refText.length()-fileMarkerPos-2));
1000  }
1001  else // file marker before line marker
1002  {
1003  // write text left from file marker
1004  ol.parseText(refText.left(fileMarkerPos));
1005  ol.pushGeneratorState();
1007  if (!latexSourceCode)
1008  {
1010  }
1011  if (!rtfSourceCode)
1012  {
1014  }
1015  // write file link (HTML only)
1016  ol.writeObjectLink(0,fn,0,m_impl->body->fileDef->name());
1017  ol.enableAll();
1019  if (latexSourceCode)
1020  {
1022  }
1023  if (rtfSourceCode)
1024  {
1026  }
1027  // write normal text (RTF/Latex/Man only)
1028  ol.docify(m_impl->body->fileDef->name());
1029  ol.popGeneratorState();
1030 
1031  // write text between markers
1032  ol.parseText(refText.mid(fileMarkerPos+2,
1033  lineMarkerPos-fileMarkerPos-2));
1034 
1035  ol.pushGeneratorState();
1037  if (!latexSourceCode)
1038  {
1040  }
1041  if (!rtfSourceCode)
1042  {
1044  }
1046  // write line link (HTML only)
1047  ol.writeObjectLink(0,fn,anchorStr,lineStr);
1048  ol.enableAll();
1050  if (latexSourceCode)
1051  {
1053  }
1054  if (rtfSourceCode)
1055  {
1057  }
1058  // write normal text (Latex/Man only)
1059  ol.docify(lineStr);
1060  ol.popGeneratorState();
1061 
1062  // write text right from linePos marker
1063  ol.parseText(refText.right(
1064  refText.length()-lineMarkerPos-2));
1065  }
1066  ol.endParagraph();
1067  }
1068  else
1069  {
1070  err("translation error: invalid markers in trDefinedInSourceFile()\n");
1071  }
1072  }
1073  ol.popGeneratorState();
1074 }
1075 
1076 void Definition::setBodySegment(int bls,int ble)
1077 {
1078  //printf("setBodySegment(%d,%d) for %s\n",bls,ble,name().data());
1079  if (m_impl->body==0) m_impl->body = new BodyInfo;
1080  m_impl->body->startLine=bls;
1081  m_impl->body->endLine=ble;
1082 }
1083 
1085 {
1086  if (m_impl->body==0) m_impl->body = new BodyInfo;
1087  m_impl->body->fileDef=fd;
1088 }
1089 
1091 {
1092  return m_impl->body && m_impl->body->startLine!=-1 &&
1094  m_impl->body->fileDef;
1095 }
1096 
1098 void Definition::writeInlineCode(OutputList &ol,const char *scopeName)
1099 {
1100  static bool inlineSources = Config_getBool(INLINE_SOURCES);
1101  ol.pushGeneratorState();
1102  //printf("Source Fragment %s: %d-%d bodyDef=%p\n",name().data(),
1103  // m_startBodyLine,m_endBodyLine,m_bodyDef);
1104  if (inlineSources && hasSources())
1105  {
1106  QCString codeFragment;
1107  int actualStart=m_impl->body->startLine,actualEnd=m_impl->body->endLine;
1109  actualStart,actualEnd,codeFragment)
1110  )
1111  {
1112  //printf("Adding code fragement '%s' ext='%s'\n",
1113  // codeFragment.data(),m_impl->defFileExt.data());
1115  pIntf->resetCodeParserState();
1116  //printf("Read:\n`%s'\n\n",codeFragment.data());
1117  MemberDef *thisMd = 0;
1118  if (definitionType()==TypeMember) thisMd = (MemberDef *)this;
1119 
1120  ol.startCodeFragment();
1121  pIntf->parseCode(ol, // codeOutIntf
1122  scopeName, // scope
1123  codeFragment, // input
1124  m_impl->lang, // lang
1125  FALSE, // isExample
1126  0, // exampleName
1127  m_impl->body->fileDef, // fileDef
1128  actualStart, // startLine
1129  actualEnd, // endLine
1130  TRUE, // inlineFragment
1131  thisMd, // memberDef
1132  TRUE // show line numbers
1133  );
1134  ol.endCodeFragment();
1135  }
1136  }
1137  ol.popGeneratorState();
1138 }
1139 
1143 void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName,
1144  const QCString &text,MemberSDict *members,bool /*funcOnly*/)
1145 {
1146  static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE);
1147  static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE);
1148  static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1149  static bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE);
1150  ol.pushGeneratorState();
1151  if (members)
1152  {
1153  members->sort();
1154 
1155  ol.startParagraph();
1156  ol.parseText(text);
1157  ol.docify(" ");
1158 
1159  QCString ldefLine=theTranslator->trWriteList(members->count());
1160 
1161  QRegExp marker("@[0-9]+");
1162  int index=0,newIndex,matchLen;
1163  // now replace all markers in inheritLine with links to the classes
1164  while ((newIndex=marker.match(ldefLine,index,&matchLen))!=-1)
1165  {
1166  bool ok;
1167  ol.parseText(ldefLine.mid(index,newIndex-index));
1168  uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
1169  MemberDef *md=members->at(entryIndex);
1170  if (ok && md)
1171  {
1172  QCString scope=md->getScopeString();
1173  QCString name=md->name();
1174  //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName);
1175  if (!scope.isEmpty() && scope!=scopeName)
1176  {
1177  name.prepend(scope+getLanguageSpecificSeparator(m_impl->lang));
1178  }
1179  if (!md->isObjCMethod() &&
1180  (md->isFunction() || md->isSlot() ||
1181  md->isPrototype() || md->isSignal()
1182  )
1183  )
1184  {
1185  name+="()";
1186  }
1187  //Definition *d = md->getOutputFileBase();
1188  //if (d==Doxygen::globalScope) d=md->getBodyDef();
1189  if (sourceBrowser &&
1190  !(md->isLinkable() && !refLinkSource) &&
1191  md->getStartBodyLine()!=-1 &&
1192  md->getBodyDef()
1193  )
1194  {
1195  //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope);
1196  // for HTML write a real link
1197  ol.pushGeneratorState();
1198  //ol.disableAllBut(OutputGenerator::Html);
1199 
1201  if (!latexSourceCode)
1202  {
1204  }
1205  if (!rtfSourceCode)
1206  {
1208  }
1209  const int maxLineNrStr = 10;
1210  char anchorStr[maxLineNrStr];
1211  qsnprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine());
1212  //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data());
1213  ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name);
1214  ol.popGeneratorState();
1215 
1216  // for the other output formats just mention the name
1217  ol.pushGeneratorState();
1219  if (latexSourceCode)
1220  {
1222  }
1223  if (rtfSourceCode)
1224  {
1226  }
1227  ol.docify(name);
1228  ol.popGeneratorState();
1229  }
1230  else if (md->isLinkable() /*&& d && d->isLinkable()*/)
1231  {
1232  // for HTML write a real link
1233  ol.pushGeneratorState();
1234  //ol.disableAllBut(OutputGenerator::Html);
1236  if (!latexSourceCode)
1237  {
1239  }
1240  if (!rtfSourceCode)
1241  {
1243  }
1244 
1245  ol.writeObjectLink(md->getReference(),
1246  md->getOutputFileBase(),
1247  md->anchor(),name);
1248  ol.popGeneratorState();
1249 
1250  // for the other output formats just mention the name
1251  ol.pushGeneratorState();
1253  if (latexSourceCode)
1254  {
1256  }
1257  if (rtfSourceCode)
1258  {
1260  }
1261  ol.docify(name);
1262  ol.popGeneratorState();
1263  }
1264  else
1265  {
1266  ol.docify(name);
1267  }
1268  }
1269  index=newIndex+matchLen;
1270  }
1271  ol.parseText(ldefLine.right(ldefLine.length()-index));
1272  ol.writeString(".");
1273  ol.endParagraph();
1274  }
1275  ol.popGeneratorState();
1276 }
1277 
1278 void Definition::writeSourceReffedBy(OutputList &ol,const char *scopeName)
1279 {
1280  if (Config_getBool(REFERENCED_BY_RELATION))
1281  {
1283  }
1284 }
1285 
1286 void Definition::writeSourceRefs(OutputList &ol,const char *scopeName)
1287 {
1288  if (Config_getBool(REFERENCES_RELATION))
1289  {
1291  }
1292 }
1293 
1295 {
1296  static bool extractAll = Config_getBool(EXTRACT_ALL);
1297  //static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1298  bool hasDocs =
1299  (m_impl->details && !m_impl->details->doc.isEmpty()) || // has detailed docs
1300  (m_impl->brief && !m_impl->brief->doc.isEmpty()) || // has brief description
1301  (m_impl->inbodyDocs && !m_impl->inbodyDocs->doc.isEmpty()) || // has inbody docs
1302  extractAll //|| // extract everything
1303  // (sourceBrowser && m_impl->body &&
1304  // m_impl->body->startLine!=-1 && m_impl->body->fileDef)
1305  ; // link to definition
1306  return hasDocs;
1307 }
1308 
1310 {
1311  bool hasDocs =
1312  (m_impl->details && !m_impl->details->doc.isEmpty()) ||
1313  (m_impl->brief && !m_impl->brief->doc.isEmpty()) ||
1314  (m_impl->inbodyDocs && !m_impl->inbodyDocs->doc.isEmpty());
1315  return hasDocs;
1316 }
1317 
1318 
1320 {
1321  if (md)
1322  {
1323  QCString name = md->name();
1324  QCString scope = md->getScopeString();
1325 
1326  if (!scope.isEmpty())
1327  {
1328  name.prepend(scope+"::");
1329  }
1330 
1331  if (m_impl->sourceRefByDict==0)
1332  {
1334  }
1335  if (m_impl->sourceRefByDict->find(name)==0)
1336  {
1337  m_impl->sourceRefByDict->append(name,md);
1338  }
1339  }
1340 }
1341 
1343 {
1344  if (md)
1345  {
1346  QCString name = md->name();
1347  QCString scope = md->getScopeString();
1348 
1349  if (!scope.isEmpty())
1350  {
1351  name.prepend(scope+"::");
1352  }
1353 
1354  if (m_impl->sourceRefsDict==0)
1355  {
1357  }
1358  if (m_impl->sourceRefsDict->find(name)==0)
1359  {
1360  m_impl->sourceRefsDict->append(name,md);
1361  }
1362  }
1363 }
1364 
1366 {
1367  return 0;
1368 }
1369 
1371 {
1372  err("Definition::addInnerCompound() called\n");
1373 }
1374 
1376 {
1377  //static int count=0;
1378  //count++;
1379  if (!m_impl->qualifiedName.isEmpty())
1380  {
1381  //count--;
1382  return m_impl->qualifiedName;
1383  }
1384 
1385  //printf("start %s::qualifiedName() localName=%s\n",name().data(),m_impl->localName.data());
1386  if (m_impl->outerScope==0)
1387  {
1388  if (m_impl->localName=="<globalScope>")
1389  {
1390  //count--;
1391  return "";
1392  }
1393  else
1394  {
1395  //count--;
1396  return m_impl->localName;
1397  }
1398  }
1399 
1400  if (m_impl->outerScope->name()=="<globalScope>")
1401  {
1403  }
1404  else
1405  {
1408  m_impl->localName;
1409  }
1410  //printf("end %s::qualifiedName()=%s\n",name().data(),m_impl->qualifiedName.data());
1411  //count--;
1412  return m_impl->qualifiedName;
1413 }
1414 
1416 {
1417  //printf("%s::setOuterScope(%s)\n",name().data(),d?d->name().data():"<none>");
1419  bool found=false;
1420  // make sure that we are not creating a recursive scope relation.
1421  while (p && !found)
1422  {
1423  found = (p==d);
1424  p = p->m_impl->outerScope;
1425  }
1426  if (!found)
1427  {
1428  m_impl->qualifiedName.resize(0); // flush cached scope name
1429  m_impl->outerScope = d;
1430  }
1431  m_impl->hidden = m_impl->hidden || d->isHidden();
1432 }
1433 
1434 QCString Definition::localName() const
1435 {
1436  return m_impl->localName;
1437 }
1438 
1440 {
1442  m_impl->partOfGroups->append(gd);
1443 }
1444 
1445 void Definition::setRefItems(const QList<ListItemInfo> *sli)
1446 {
1447  //printf("%s::setRefItems()\n",name().data());
1448  if (sli)
1449  {
1450  // deep copy the list
1451  if (m_impl->xrefListItems==0)
1452  {
1453  m_impl->xrefListItems=new QList<ListItemInfo>;
1454  m_impl->xrefListItems->setAutoDelete(TRUE);
1455  }
1456  QListIterator<ListItemInfo> slii(*sli);
1457  ListItemInfo *lii;
1458  for (slii.toFirst();(lii=slii.current());++slii)
1459  {
1460  m_impl->xrefListItems->append(new ListItemInfo(*lii));
1461  }
1462  }
1463 }
1464 
1466 {
1467  //printf("%s::mergeRefItems()\n",name().data());
1468  QList<ListItemInfo> *xrefList = d->xrefListItems();
1469  if (xrefList!=0)
1470  {
1471  // deep copy the list
1472  if (m_impl->xrefListItems==0)
1473  {
1474  m_impl->xrefListItems=new QList<ListItemInfo>;
1475  m_impl->xrefListItems->setAutoDelete(TRUE);
1476  }
1477  QListIterator<ListItemInfo> slii(*xrefList);
1478  ListItemInfo *lii;
1479  for (slii.toFirst();(lii=slii.current());++slii)
1480  {
1481  if (_getXRefListId(lii->type)==-1)
1482  {
1483  m_impl->xrefListItems->append(new ListItemInfo(*lii));
1484  }
1485  }
1486  }
1487 }
1488 
1489 int Definition::_getXRefListId(const char *listName) const
1490 {
1491  if (m_impl->xrefListItems)
1492  {
1493  QListIterator<ListItemInfo> slii(*m_impl->xrefListItems);
1494  ListItemInfo *lii;
1495  for (slii.toFirst();(lii=slii.current());++slii)
1496  {
1497  if (qstrcmp(lii->type,listName)==0)
1498  {
1499  return lii->itemId;
1500  }
1501  }
1502  }
1503  return -1;
1504 }
1505 
1506 QList<ListItemInfo> *Definition::xrefListItems() const
1507 {
1508  return m_impl->xrefListItems;
1509 }
1510 
1512 {
1513  QCString result;
1515  {
1516  result = m_impl->outerScope->pathFragment();
1517  }
1518  if (isLinkable())
1519  {
1520  if (!result.isEmpty()) result+="/";
1521  if (definitionType()==Definition::TypeGroup && ((const GroupDef*)this)->groupTitle())
1522  {
1523  result+=((const GroupDef*)this)->groupTitle();
1524  }
1525  else if (definitionType()==Definition::TypePage && !((const PageDef*)this)->title().isEmpty())
1526  {
1527  result+=((const PageDef*)this)->title();
1528  }
1529  else
1530  {
1531  result+=m_impl->localName;
1532  }
1533  }
1534  else
1535  {
1536  result+=m_impl->localName;
1537  }
1538  return result;
1539 }
1540 
1541 //----------------------------------------------------------------------------------------
1542 
1543 // TODO: move to htmlgen
1548 {
1549  QCString result;
1550  Definition *outerScope = getOuterScope();
1551  QCString locName = localName();
1552  if (outerScope && outerScope!=Doxygen::globalScope)
1553  {
1554  result+=outerScope->navigationPathAsString();
1555  }
1556  else if (definitionType()==Definition::TypeFile && ((const FileDef*)this)->getDirDef())
1557  {
1558  result+=((const FileDef*)this)->getDirDef()->navigationPathAsString();
1559  }
1560  result+="<li class=\"navelem\">";
1561  if (isLinkable())
1562  {
1563  if (definitionType()==Definition::TypeGroup && ((const GroupDef*)this)->groupTitle())
1564  {
1565  result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
1566  convertToHtml(((const GroupDef*)this)->groupTitle())+"</a>";
1567  }
1568  else if (definitionType()==Definition::TypePage && !((const PageDef*)this)->title().isEmpty())
1569  {
1570  result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
1571  convertToHtml(((const PageDef*)this)->title())+"</a>";
1572  }
1574  {
1575  QCString name = locName;
1576  if (name.right(2)=="-p" /*|| name.right(2)=="-g"*/)
1577  {
1578  name = name.left(name.length()-2);
1579  }
1580  result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension;
1581  if (!anchor().isEmpty()) result+="#"+anchor();
1582  result+="\">"+convertToHtml(name)+"</a>";
1583  }
1584  else
1585  {
1586  result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+
1587  convertToHtml(locName)+"</a>";
1588  }
1589  }
1590  else
1591  {
1592  result+="<b>"+convertToHtml(locName)+"</b>";
1593  }
1594  result+="</li>";
1595  return result;
1596 }
1597 
1598 // TODO: move to htmlgen
1600 {
1601  ol.pushGeneratorState();
1603 
1604  QCString navPath;
1605  navPath += "<div id=\"nav-path\" class=\"navpath\">\n"
1606  " <ul>\n";
1607  navPath += navigationPathAsString();
1608  navPath += " </ul>\n"
1609  "</div>\n";
1610  ol.writeNavigationPath(navPath);
1611 
1612  ol.popGeneratorState();
1613 }
1614 
1615 // TODO: move to htmlgen
1617 {
1618  SectionDict *sectionDict = m_impl->sectionDict;
1619  if (sectionDict==0) return;
1620  ol.pushGeneratorState();
1622  ol.writeString("<div class=\"toc\">");
1623  ol.writeString("<h3>");
1625  ol.writeString("</h3>\n");
1626  ol.writeString("<ul>");
1627  SDict<SectionInfo>::Iterator li(*sectionDict);
1628  SectionInfo *si;
1629  int level=1,l;
1630  char cs[2];
1631  cs[1]='\0';
1632  bool inLi[5]={ FALSE, FALSE, FALSE, FALSE };
1633  for (li.toFirst();(si=li.current());++li)
1634  {
1635  if (si->type==SectionInfo::Section ||
1636  si->type==SectionInfo::Subsection ||
1639  {
1640  //printf(" level=%d title=%s\n",level,si->title.data());
1641  int nextLevel = (int)si->type;
1642  if (nextLevel>level)
1643  {
1644  for (l=level;l<nextLevel;l++)
1645  {
1646  ol.writeString("<ul>");
1647  }
1648  }
1649  else if (nextLevel<level)
1650  {
1651  for (l=level;l>nextLevel;l--)
1652  {
1653  if (inLi[l]) ol.writeString("</li>\n");
1654  inLi[l]=FALSE;
1655  ol.writeString("</ul>\n");
1656  }
1657  }
1658  cs[0]='0'+nextLevel;
1659  if (inLi[nextLevel]) ol.writeString("</li>\n");
1660  QCString titleDoc = convertToHtml(si->title);
1661  ol.writeString("<li class=\"level"+QCString(cs)+"\"><a href=\"#"+si->label+"\">"+(si->title.isEmpty()?si->label:titleDoc)+"</a>");
1662  inLi[nextLevel]=TRUE;
1663  level = nextLevel;
1664  }
1665  }
1666  while (level>1)
1667  {
1668  if (inLi[level]) ol.writeString("</li>\n");
1669  inLi[level]=FALSE;
1670  ol.writeString("</ul>\n");
1671  level--;
1672  }
1673  if (inLi[level]) ol.writeString("</li>\n");
1674  inLi[level]=FALSE;
1675  ol.writeString("</ul>\n");
1676  ol.writeString("</div>\n");
1677  ol.popGeneratorState();
1678 }
1679 
1680 //----------------------------------------------------------------------------------------
1681 
1682 
1683 QCString Definition::symbolName() const
1684 {
1685  return m_symbolName;
1686 }
1687 
1688 //----------------------
1689 
1690 QCString Definition::documentation() const
1691 {
1692  return m_impl->details ? m_impl->details->doc : QCString("");
1693 }
1694 
1696 {
1697  return m_impl->details ? m_impl->details->line : 1;
1698 }
1699 
1700 QCString Definition::docFile() const
1701 {
1702  return m_impl->details ? m_impl->details->file : QCString("<"+m_name+">");
1703 }
1704 
1705 //----------------------------------------------------------------------------
1706 // strips w from s iff s starts with w
1707 static bool stripWord(QCString &s,QCString w)
1708 {
1709  bool success=FALSE;
1710  if (s.left(w.length())==w)
1711  {
1712  success=TRUE;
1713  s=s.right(s.length()-w.length());
1714  }
1715  return success;
1716 }
1717 
1718 //----------------------------------------------------------------------------
1719 // some quasi intelligent brief description abbreviator :^)
1720 QCString abbreviate(const char *s,const char *name)
1721 {
1722  QCString scopelessName=name;
1723  int i=scopelessName.findRev("::");
1724  if (i!=-1) scopelessName=scopelessName.mid(i+2);
1725  QCString result=s;
1726  result=result.stripWhiteSpace();
1727  // strip trailing .
1728  if (!result.isEmpty() && result.at(result.length()-1)=='.')
1729  result=result.left(result.length()-1);
1730 
1731  // strip any predefined prefix
1732  QStrList &briefDescAbbrev = Config_getList(ABBREVIATE_BRIEF);
1733  const char *p = briefDescAbbrev.first();
1734  while (p)
1735  {
1736  QCString s = p;
1737  s.replace(QRegExp("\\$name"), scopelessName); // replace $name with entity name
1738  s += " ";
1739  stripWord(result,s);
1740  p = briefDescAbbrev.next();
1741  }
1742 
1743  // capitalize first word
1744  if (!result.isEmpty())
1745  {
1746  int c=result[0];
1747  if (c>='a' && c<='z') c+='A'-'a';
1748  result[0]=c;
1749  }
1750  return result;
1751 }
1752 
1753 
1754 //----------------------
1755 
1756 QCString Definition::briefDescription(bool abbr) const
1757 {
1758  //printf("%s::briefDescription(%d)='%s'\n",name().data(),abbr,m_impl->brief?m_impl->brief->doc.data():"<none>");
1759  return m_impl->brief ?
1760  (abbr ? abbreviate(m_impl->brief->doc,displayName()) : m_impl->brief->doc) :
1761  QCString("");
1762 }
1763 
1765 {
1766  if (m_impl->brief)
1767  {
1768  if (m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty())
1769  {
1770  static bool reentering=FALSE;
1771  if (!reentering)
1772  {
1773  MemberDef *md = definitionType()==TypeMember ? (MemberDef*)this : 0;
1774  const Definition *scope = definitionType()==TypeMember ? getOuterScope() : this;
1775  reentering=TRUE; // prevent requests for tooltips while parsing a tooltip
1777  scope,md,
1778  m_impl->brief->doc,
1779  m_impl->brief->file,
1780  m_impl->brief->line);
1781  reentering=FALSE;
1782  }
1783  }
1784  return m_impl->brief->tooltip;
1785  }
1786  return QCString("");
1787 }
1788 
1790 {
1791  return m_impl->brief ? m_impl->brief->line : 1;
1792 }
1793 
1794 QCString Definition::briefFile() const
1795 {
1796  return m_impl->brief ? m_impl->brief->file : QCString("<"+m_name+">");
1797 }
1798 
1799 //----------------------
1800 
1802 {
1803  return m_impl->inbodyDocs ? m_impl->inbodyDocs->doc : QCString("");
1804 }
1805 
1807 {
1808  return m_impl->inbodyDocs ? m_impl->inbodyDocs->line : 1;
1809 }
1810 
1811 QCString Definition::inbodyFile() const
1812 {
1813  return m_impl->inbodyDocs ? m_impl->inbodyDocs->file : QCString("<"+m_name+">");
1814 }
1815 
1816 
1817 //----------------------
1818 
1820 {
1821  return m_impl->defFileName;
1822 }
1823 
1825 {
1826  return m_impl->defFileExt;
1827 }
1828 
1830 {
1831  return m_impl->hidden;
1832 }
1833 
1835 {
1836  return isLinkableInProject() && !m_impl->hidden;
1837 }
1838 
1840 {
1841  return isLinkable() && !m_impl->hidden;
1842 }
1843 
1845 {
1846  return m_impl->isArtificial;
1847 }
1848 
1849 QCString Definition::getReference() const
1850 {
1851  return m_impl->ref;
1852 }
1853 
1855 {
1856  return !m_impl->ref.isEmpty();
1857 }
1858 
1860 {
1861  return m_impl->body ? m_impl->body->startLine : -1;
1862 }
1863 
1865 {
1866  return m_impl->body ? m_impl->body->endLine : -1;
1867 }
1868 
1870 {
1871  return m_impl->body ? m_impl->body->fileDef : 0;
1872 }
1873 
1875 {
1876  return m_impl->partOfGroups;
1877 }
1878 
1880 {
1881  GroupList *gl = partOfGroups();
1882  if (gl)
1883  {
1884  GroupListIterator gli(*gl);
1885  GroupDef *gd;
1886  for (gli.toFirst();(gd=gli.current());++gli)
1887  {
1888  if (gd->isLinkable()) return TRUE;
1889  }
1890  }
1891  return FALSE;
1892 }
1893 
1895 {
1896  return m_impl->outerScope;
1897 }
1898 
1900 {
1901  return m_impl->sourceRefsDict;
1902 }
1903 
1905 {
1906  return m_impl->sourceRefByDict;
1907 }
1908 
1909 void Definition::setReference(const char *r)
1910 {
1911  m_impl->ref=r;
1912 }
1913 
1915 {
1916  return m_impl->lang;
1917 }
1918 
1920 {
1921  m_impl->hidden = m_impl->hidden || b;
1922 }
1923 
1925 {
1926  m_impl->isArtificial = b;
1927 }
1928 
1929 void Definition::setLocalName(const QCString name)
1930 {
1931  m_impl->localName=name;
1932 }
1933 
1935 {
1936  m_impl->lang=lang;
1937 }
1938 
1939 
1940 void Definition::_setSymbolName(const QCString &name)
1941 {
1942  m_symbolName=name;
1943 }
1944 
1946 {
1947  static bool briefMemberDesc = Config_getBool(BRIEF_MEMBER_DESC);
1948  return !briefDescription().isEmpty() && briefMemberDesc;
1949 }
1950 
1951 QCString Definition::externalReference(const QCString &relPath) const
1952 {
1953  QCString ref = getReference();
1954  if (!ref.isEmpty())
1955  {
1956  QCString *dest = Doxygen::tagDestinationDict[ref];
1957  if (dest)
1958  {
1959  QCString result = *dest;
1960  int l = result.length();
1961  if (!relPath.isEmpty() && l>0 && result.at(0)=='.')
1962  { // relative path -> prepend relPath.
1963  result.prepend(relPath);
1964  l+=relPath.length();
1965  }
1966  if (l>0 && result.at(l-1)!='/') result+='/';
1967  return result;
1968  }
1969  }
1970  return relPath;
1971 }
1972 
1973 
1974