definition.cpp 20.6 KB
Newer Older
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1 2
/******************************************************************************
 *
3
 * 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
4
 *
5
 * Copyright (C) 1997-2003 by Dimitri van Heesch.
Dimitri van Heesch's avatar
Dimitri van Heesch committed
6 7 8 9 10 11 12
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation under the terms of the GNU General Public License is hereby 
 * granted. No representations are made about the suitability of this software 
 * for any purpose. It is provided "as is" without express or implied warranty.
 * See the GNU General Public License for more details.
 *
Dimitri van Heesch's avatar
Dimitri van Heesch committed
13 14
 * Documents produced by Doxygen are derivative works derived from the
 * input used in their production; they are not affected by this license.
Dimitri van Heesch's avatar
Dimitri van Heesch committed
15 16 17
 *
 */

18
#include "qtbc.h"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
19
#include <ctype.h>
20
#include <qregexp.h>
21 22
#include <stdio.h>
#include <stdlib.h>
23
#include "config.h"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
24
#include "definition.h"
25
#include "doxygen.h"
26 27 28
#include "language.h"
#include "message.h"
#include "outputlist.h"
29
#include "code.h"
30
#include "util.h"
31
#include "groupdef.h"
32
#include "section.h"
33

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
#if defined(_MSC_VER) || defined(__BORLANDC__)
#define popen _popen
#define pclose _pclose
#endif

static void addToMap(const char *name,Definition *d)
{
  QCString symbolName = name;
  int index=symbolName.findRev("::");
  if (index!=-1) symbolName=symbolName.mid(index+2);
  if (!symbolName.isEmpty()) 
  {
    DefinitionList *dl=Doxygen::symbolMap->find(symbolName);
    if (dl==0)
    {
      dl = new DefinitionList;
      Doxygen::symbolMap->append(symbolName,dl);
    }
    //printf("******* adding symbol `%s'\n",symbolName.data());
    dl->append(d);
54
    d->setSymbolName(symbolName);
55 56 57 58 59
  }
}

static void removeFromMap(Definition *d)
{
60
  QCString symbolName = d->symbolName();
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
  int index=symbolName.findRev("::");
  if (index!=-1) symbolName=symbolName.mid(index+2);
  if (!symbolName.isEmpty()) 
  {
    //printf("******* removing symbol `%s'\n",symbolName.data());
    DefinitionList *dl=Doxygen::symbolMap->find(symbolName);
    if (dl)
    {
      ASSERT(dl!=0);
      bool b = dl->removeRef(d);
      ASSERT(b==TRUE);
    }
  }
}

76 77
Definition::Definition(const char *df,int dl,
                       const char *name,const char *b,const char *d)
78
{
79
  //QCString ns;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
80 81 82
  m_defFileName = df;
  m_defLine = dl;
  m_name=name; 
83
  if (m_name!="<globalScope>") 
84 85
  {
    //extractNamespaceName(m_name,m_localName,ns);
86
    m_localName=stripScope(name);
87
  }
88
  else
89
  {
90
    m_localName=name;
91
  }
92
  //printf("m_localName=%s\n",m_localName.data());
Dimitri van Heesch's avatar
Dimitri van Heesch committed
93 94 95 96 97
  m_brief=b; 
  m_doc=d; 
  m_sectionDict=0, 
  m_startBodyLine=m_endBodyLine=-1, 
  m_bodyDef=0;
98 99
  m_sourceRefByDict=0;
  m_sourceRefsDict=0;
100 101
  m_todoId=0;
  m_testId=0;
102
  m_bugId=0;
103
  m_deprecatedId=0;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
104
  m_outerScope=Doxygen::globalScope;
105
  m_partOfGroups=0;
106
  m_xrefListItems=0;
107
  m_briefLine=1;
108 109 110
  m_briefFile=(QCString)"<"+name+">";
  m_docLine=1;
  m_docFile=(QCString)"<"+name+">";
111
  addToMap(name,this);
112 113 114 115
}

Definition::~Definition()
{
116
  removeFromMap(this);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
117
  delete m_sectionDict;
118 119
  delete m_sourceRefByDict;
  delete m_sourceRefsDict;
120
  delete m_partOfGroups;
121
  delete m_xrefListItems;
122
}
Dimitri van Heesch's avatar
Dimitri van Heesch committed
123

124
void Definition::addSectionsToDefinition(QList<SectionInfo> *anchorList)
125 126
{
  if (!anchorList) return;
127
  //printf("%s: addSectionsToDefinition(%d)\n",name().data(),anchorList->count());
128 129
  SectionInfo *si=anchorList->first();
  while (si)
130
  {
131 132 133 134
    //printf("Add section `%s' to definition `%s'\n",
    //    si->label.data(),name().data());
    SectionInfo *gsi=Doxygen::sectionDict.find(si->label);
    if (gsi==0)
135
    {
136 137
      gsi = new SectionInfo(*si);
      Doxygen::sectionDict.insert(si->label,gsi);
138
    }
139 140 141 142 143
    if (m_sectionDict==0) 
    {
      m_sectionDict = new SectionDict(17);
    }
    if (m_sectionDict->find(gsi->label)==0)
144
    {
145 146
      m_sectionDict->insert(gsi->label,gsi);
      gsi->definition = this;
147
    }
148
    si=anchorList->next();
149 150
  }
}
151

152 153
void Definition::writeDocAnchorsToTagFile()
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
154
  if (!Config_getString("GENERATE_TAGFILE").isEmpty() && m_sectionDict)
155
  {
156
    //printf("%s: writeDocAnchorsToTagFile(%d)\n",name().data(),m_sectionDict->count());
Dimitri van Heesch's avatar
Dimitri van Heesch committed
157
    QDictIterator<SectionInfo> sdi(*m_sectionDict);
158 159 160
    SectionInfo *si;
    for (;(si=sdi.current());++sdi)
    {
161 162
      if (!si->generated)
      {
163
        //printf("write an entry!\n");
164 165 166
        if (definitionType()==TypeMember) Doxygen::tagFile << "  ";
        Doxygen::tagFile << "    <docanchor>" << si->label << "</docanchor>" << endl;
      }
167 168 169 170
    }
  }
}

171
void Definition::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace) 
172
{ 
173
  if (d==0) return;
174
  //printf("Definition::setDocumentation(%s,%s,%d,%d)\n",d,docFile,docLine,stripWhiteSpace);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
175
  QCString doc;
176
  if (stripWhiteSpace)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
177 178 179 180 181 182 183 184 185 186 187 188 189
  {
    // strip leading empty lines in front of the text, but not the 
    // leading spaces in front of the first line, so list items are 
    // parsed with the correct indent
    const char *p=d;
    char c;
    int s=0,so=0;
    while ((c=*p) && (c==' ' || c=='\r' || c=='\n'))
    {
      if (c=='\n') so=s; 
      p++;
      s++;
    }
190
    if (c=='\0') return;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
191
    doc=d+so;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
192
    // zero any trailing whitespace
Dimitri van Heesch's avatar
Dimitri van Heesch committed
193 194
    int e=doc.length()-1;
    while (e>=0 && (c=doc.at(e)) && (c==' ' || c=='\r' || c=='\n'))
Dimitri van Heesch's avatar
Dimitri van Heesch committed
195
    {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
196
      doc.at(e)='\0';
Dimitri van Heesch's avatar
Dimitri van Heesch committed
197 198 199
      e--;
    }
  }
200 201
  else // don't strip whitespace
  {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
202
    doc=d;
203 204
  }
  //printf("setting docs for %s: `%s'\n",name().data(),m_doc.data());
Dimitri van Heesch's avatar
Dimitri van Heesch committed
205
  m_doc=doc;
206 207 208
  m_docFile = docFile;
  m_docLine = docLine;
}
209

210
void Definition::setBriefDescription(const char *b,const char *briefFile,int briefLine) 
211
{ 
212 213
  if (b==0) return;
  //printf("Definition::setBriefDescription(%s,%s,%d)\n",b,briefFile,briefLine);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
214
  m_brief=QCString(b).stripWhiteSpace();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
215
  int bl=m_brief.length(); 
216 217
  if (bl>0) // add puntuation if needed
  {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
218
    switch(m_brief.at(bl-1))
219 220
    {
      case '.': case '!': case '?': break;
221 222 223
      default: 
        if (isupper(m_brief.at(0))) m_brief+='.'; 
        break;
224 225
    }
  }
226 227
  m_briefFile = briefFile;
  m_briefLine = briefLine;
228
}
229

230
/*! Reads a fragment of code from file \a fileName starting at 
231
 * line \a startLine and ending at line \a endLine (inclusive). The fragment is
232 233 234 235 236 237 238 239 240 241 242 243 244
 * stored in \a result. If FALSE is returned the code fragment could not be
 * found.
 *
 * The file is scanned for a opening bracket ('{') from \a startLine onward.
 * The line actually containing the bracket is returned via startLine.
 * The file is scanned for a closing bracket ('}') from \a endLine backward.
 * The line actually containing the bracket is returned via endLine.
 */
static bool readCodeFragment(const char *fileName,
                      int &startLine,int &endLine,QCString &result)
{
  //printf("readCodeFragment(%s,%d,%d)\n",fileName,startLine,endLine);
  if (fileName==0 || fileName[0]==0) return FALSE; // not a valid file name
245 246
  QCString cmd=Config_getString("INPUT_FILTER")+" \""+fileName+"\"";
  FILE *f = Config_getBool("FILTER_SOURCE_FILES") ? popen(cmd,"r") : fopen(fileName,"r");
247
  bool found=FALSE;
248
  if (f)
249 250
  {
    int c=0;
251
    int col=0;
252 253
    int lineNr=1;
    // skip until the startLine has reached
254
    while (lineNr<startLine && !feof(f))
255
    {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
256
      while ((c=fgetc(f))!='\n' && c!=EOF) /* skip */;
257 258
      lineNr++; 
    }
259
    if (!feof(f))
260
    {
261
      // skip until the opening bracket or lonely : is found
Dimitri van Heesch's avatar
Dimitri van Heesch committed
262
      char cn=0;
263
      while (lineNr<=endLine && !feof(f) && !found)
264
      {
265
        while ((c=fgetc(f))!='{' && c!=':' && c!=EOF) 
266
        {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
267
          //printf("parsing char `%c'\n",c);
268 269 270 271 272 273
          if (c=='\n') 
          {
            lineNr++,col=0; 
          }
          else if (c=='\t') 
          {
274
            col+=Config_getInt("TAB_SIZE") - (col%Config_getInt("TAB_SIZE"));
275 276 277 278 279 280
          }
          else
          {
            col++;
          }
        }
281 282
        if (c==':')
        {
283
          cn=fgetc(f);
284 285 286 287 288 289
          if (cn!=':') found=TRUE;
        }
        else if (c=='{')
        {
          found=TRUE;
        }
290
      }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
291
      //printf(" -> readCodeFragment(%s,%d,%d) lineNr=%d\n",fileName,startLine,endLine,lineNr);
292
      if (found) 
293
      {
294 295 296 297 298 299 300 301 302
        // For code with more than one line,
        // fill the line with spaces until we are at the right column
        // so that the opening brace lines up with the closing brace
        if (endLine!=startLine)
        {
          QCString spaces;
          spaces.fill(' ',col);
          result+=spaces;
        }
303 304
        // copy until end of line
        result+=c;
305
        if (c==':') result+=cn;
306 307 308
        startLine=lineNr;
        const int maxLineLength=4096;
        char lineStr[maxLineLength];
309
        do 
310
        {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
311
          //printf("reading line %d in range %d-%d\n",lineNr,startLine,endLine);
312
          int size_read;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
313 314
          do 
          {
315
            // read up to maxLineLength-1 bytes, the last byte being zero
316
            char *p = fgets(lineStr, maxLineLength,f);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
317 318 319 320 321 322 323 324 325
            //printf("  read %s",p);
            if (p) 
            {
              size_read=qstrlen(p); 
            }
            else 
            {
              size_read=-1;
            }
326 327 328
            result+=lineStr;
          } while (size_read == (maxLineLength-1));

329
          lineNr++; 
330
        } while (lineNr<=endLine && !feof(f));
331

332 333 334 335
        // strip stuff after closing bracket
        int newLineIndex = result.findRev('\n');
        int braceIndex   = result.findRev('}');
        if (braceIndex > newLineIndex) 
336
        {
337
          result.truncate(braceIndex+1);
338
        }
339
        endLine=lineNr-1;
340 341
      }
    }
342
    if (Config_getBool("FILTER_SOURCE_FILES")) pclose(f); else fclose(f);
343
  }
344
  return found;
345 346
}

347
/*! Write a reference to the source code defining this definition */
348
void Definition::writeSourceDef(OutputList &ol,const char *)
349
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
350
  ol.pushGeneratorState();
351
  //printf("Definition::writeSourceRef %d %p\n",bodyLine,bodyDef);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
352
  if (Config_getBool("SOURCE_BROWSER") && m_startBodyLine!=-1 && m_bodyDef)
353
  {
354
    ol.disable(OutputGenerator::RTF);
355
    ol.newParagraph();
356
    ol.enableAll();
357 358 359 360 361 362

    QCString refText = theTranslator->trDefinedAtLineInSourceFile();
    int lineMarkerPos = refText.find("@0");
    int fileMarkerPos = refText.find("@1");
    if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this.
    {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
363
      QCString lineStr,anchorStr;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
364 365
      lineStr.sprintf("%d",m_startBodyLine);
      anchorStr.sprintf("l%05d",m_startBodyLine);
366 367 368
      if (lineMarkerPos<fileMarkerPos) // line marker before file marker
      {
        // write text left from linePos marker
369
        ol.parseText(refText.left(lineMarkerPos)); 
370 371
        ol.disableAllBut(OutputGenerator::Html); 
        // write line link (HTML only)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
372
        ol.writeObjectLink(0,m_bodyDef->getSourceFileBase(),
373 374 375 376 377 378 379 380
            anchorStr,lineStr);
        ol.enableAll();
        ol.disable(OutputGenerator::Html);
        // write normal text (Latex/Man only)
        ol.docify(lineStr);
        ol.enableAll();
        
        // write text between markers
381
        ol.parseText(refText.mid(lineMarkerPos+2,
382 383 384 385
              fileMarkerPos-lineMarkerPos-2));

        ol.disableAllBut(OutputGenerator::Html); 
        // write file link (HTML only)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
386 387
        ol.writeObjectLink(0,m_bodyDef->getSourceFileBase(),
            0,m_bodyDef->name());
388 389 390
        ol.enableAll();
        ol.disable(OutputGenerator::Html);
        // write normal text (Latex/Man only)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
391
        ol.docify(m_bodyDef->name());
392 393 394
        ol.enableAll();
        
        // write text right from file marker
395
        ol.parseText(refText.right(
396 397 398 399 400
              refText.length()-fileMarkerPos-2)); 
      }
      else // file marker before line marker
      {
        // write text left from file marker
401
        ol.parseText(refText.left(fileMarkerPos)); 
402 403
        ol.disableAllBut(OutputGenerator::Html); 
        // write file link (HTML only)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
404 405
        ol.writeObjectLink(0,m_bodyDef->getSourceFileBase(),
            0,m_bodyDef->name());
406 407 408
        ol.enableAll();
        ol.disable(OutputGenerator::Html);
        // write normal text (Latex/Man only)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
409
        ol.docify(m_bodyDef->name());
410 411 412
        ol.enableAll();
        
        // write text between markers
413
        ol.parseText(refText.mid(fileMarkerPos+2,
414 415 416 417
              lineMarkerPos-fileMarkerPos-2)); 

        ol.disableAllBut(OutputGenerator::Html); 
        // write line link (HTML only)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
418
        ol.writeObjectLink(0,m_bodyDef->getSourceFileBase(),
419 420 421 422 423 424 425 426
            anchorStr,lineStr);
        ol.enableAll();
        ol.disable(OutputGenerator::Html);
        // write normal text (Latex/Man only)
        ol.docify(lineStr);
        ol.enableAll();

        // write text right from linePos marker
427
        ol.parseText(refText.right(
428 429 430 431 432 433 434
              refText.length()-lineMarkerPos-2)); 
      }
    }
    else
    {
      err("Error: translation error: invalid markers in trDefinedInSourceFile()\n");
    }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
435 436 437 438

    ol.disableAllBut(OutputGenerator::RTF);
    ol.newParagraph();
    ol.enableAll();
439
  }
440 441 442 443 444 445 446
  ol.popGeneratorState();
}

/*! Write code of this definition into the documentation */
void Definition::writeInlineCode(OutputList &ol,const char *scopeName)
{
  ol.pushGeneratorState();
447
  //printf("Source Fragment %s: %d-%d bodyDef=%p\n",name().data(),
Dimitri van Heesch's avatar
Dimitri van Heesch committed
448
  //        m_startBodyLine,m_endBodyLine,m_bodyDef);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
449 450
  if (Config_getBool("INLINE_SOURCES") && m_startBodyLine!=-1 && 
      m_endBodyLine>=m_startBodyLine && m_bodyDef)
451 452
  {
    QCString codeFragment;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
453 454
    int actualStart=m_startBodyLine,actualEnd=m_endBodyLine;
    if (readCodeFragment(m_bodyDef->absFilePath(),
455 456 457
          actualStart,actualEnd,codeFragment)
       )
    {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
458
      initParseCodeContext();
459
      //printf("Read:\n`%s'\n\n",codeFragment.data());
460
      if (definitionType()==TypeMember) setParameterList((MemberDef *)this);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
461
      ol.newParagraph();
462 463
      ol.startCodeFragment();
      parseCode(ol,scopeName,codeFragment,FALSE,0,
Dimitri van Heesch's avatar
Dimitri van Heesch committed
464
          m_bodyDef,actualStart,actualEnd,TRUE);
465 466 467
      ol.endCodeFragment();
    }
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
468
  ol.popGeneratorState();
469 470
}

471 472 473
/*! Write a reference to the source code fragments in which this 
 *  definition is used.
 */
474
void Definition::writeSourceRefList(OutputList &ol,const char *scopeName,
475
    const QCString &text,MemberSDict *members,bool /*funcOnly*/)
476 477
{
  ol.pushGeneratorState();
478
  if (Config_getBool("SOURCE_BROWSER") && members)
479 480
  {
    ol.newParagraph();
481
    ol.parseText(text);
482 483
    ol.docify(" ");

484
    QCString ldefLine=theTranslator->trWriteList(members->count());
485 486 487 488

    QRegExp marker("@[0-9]+");
    int index=0,newIndex,matchLen;
    // now replace all markers in inheritLine with links to the classes
489
    while ((newIndex=marker.match(ldefLine,index,&matchLen))!=-1)
490 491
    {
      bool ok;
492
      ol.parseText(ldefLine.mid(index,newIndex-index));
493
      uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
494
      MemberDef *md=members->at(entryIndex);
495 496 497 498
      if (ok && md)
      {
        QCString scope=md->getScopeString();
        QCString name=md->name();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
499
        //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName);
500 501
        if (!scope.isEmpty() && scope!=scopeName)
        {
502 503 504 505 506 507 508 509
          if (Config_getBool("OPTIMIZE_OUTPUT_JAVA"))
          {
            name.prepend(scope+".");
          }
          else
          {
            name.prepend(scope+"::");
          }
510
        }
511 512 513
        if (md->isFunction() || md->isSlot() || 
            md->isPrototype() || md->isSignal()
           ) name+="()";
514 515
        //Definition *d = md->getOutputFileBase();
        //if (d==Doxygen::globalScope) d=md->getBodyDef();
516 517
        if (md->getStartBodyLine()!=-1 && md->getBodyDef()) 
        {
518
          //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); 
519 520 521
          // for HTML write a real link
          ol.pushGeneratorState();
          ol.disableAllBut(OutputGenerator::Html);
522 523
          QCString lineStr,anchorStr;
          anchorStr.sprintf("l%05d",md->getStartBodyLine());
524
          //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data());
525
          ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name);
526 527 528 529 530 531 532
          ol.popGeneratorState();

          // for the other output formats just mention the name
          ol.pushGeneratorState();
          ol.disable(OutputGenerator::Html);
          ol.docify(name);
          ol.popGeneratorState();
533
        }
534
        else if (md->isLinkable() /*&& d && d->isLinkable()*/)
535 536 537 538
        {
          // for HTML write a real link
          ol.pushGeneratorState();
          ol.disableAllBut(OutputGenerator::Html);
539 540
          ol.writeObjectLink(md->getReference(),
                             md->getOutputFileBase(),
541 542 543 544 545 546 547 548 549
                             md->anchor(),name);
          ol.popGeneratorState();

          // for the other output formats just mention the name
          ol.pushGeneratorState();
          ol.disable(OutputGenerator::Html);
          ol.docify(name);
          ol.popGeneratorState();
        }
550 551 552 553 554 555 556
        else
        {
          ol.docify(name);
        }
      }
      index=newIndex+matchLen;
    } 
557
    ol.parseText(ldefLine.right(ldefLine.length()-index));
558 559 560 561 562
    ol.writeString(".");
  }
  ol.popGeneratorState();
}

563 564
void Definition::writeSourceReffedBy(OutputList &ol,const char *scopeName)
{
565
  writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),m_sourceRefByDict,FALSE);
566 567 568 569
}

void Definition::writeSourceRefs(OutputList &ol,const char *scopeName)
{
570
  writeSourceRefList(ol,scopeName,theTranslator->trReferences(),m_sourceRefsDict,TRUE);
571 572
}

573
bool Definition::hasDocumentation() const
574
{ 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
575 576
  return !m_doc.isEmpty() ||             // has detailed docs
         !m_brief.isEmpty() ||           // has brief description
577
         Config_getBool("EXTRACT_ALL");       // extract everything
578 579
}

580
void Definition::addSourceReferencedBy(MemberDef *md)
581 582 583
{
  if (md)
  {
584 585
    QCString name  = md->name();
    QCString scope = md->getScopeString();
586 587 588 589 590 591

    if (!scope.isEmpty())
    {
      name.prepend(scope+"::");
    }

592
    if (m_sourceRefByDict==0)
593
    {
594
      m_sourceRefByDict = new MemberSDict;
595
    }
596
    if (m_sourceRefByDict->find(name)==0)
597
    {
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
      m_sourceRefByDict->inSort(name,md);
    }
  }
}

void Definition::addSourceReferences(MemberDef *md)
{
  if (md)
  {
    QCString name  = md->name();
    QCString scope = md->getScopeString();

    if (!scope.isEmpty())
    {
      name.prepend(scope+"::");
    }

    if (m_sourceRefsDict==0)
    {
      m_sourceRefsDict = new MemberSDict;
    }
    if (m_sourceRefsDict->find(name)==0)
    {
621
      //printf("Adding reference %s->%s\n",md->name().data(),name.data());
622
      m_sourceRefsDict->inSort(name,md);
623 624 625 626
    }
  }
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
627 628 629 630 631 632 633 634 635 636 637 638
Definition *Definition::findInnerCompound(const char *)
{
  return 0;
}

void Definition::addInnerCompound(Definition *)
{
  err("Error: Definition::addInnerCompound() called\n");
}

QCString Definition::qualifiedName() const
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
639
  //printf("start Definition::qualifiedName() localName=%s\n",m_localName.data());
640 641 642 643 644
  if (m_outerScope==0) 
  {
    if (m_localName=="<globalScope>") return "";
    else return m_localName; 
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663

  QCString qualifiedName;
  if (m_outerScope->name()=="<globalScope>")
  {
    qualifiedName = m_localName.copy();
  }
  else
  {
    qualifiedName = m_outerScope->qualifiedName()+"::"+m_localName;
  }
  //printf("end Definition::qualifiedName()=%s\n",qualifiedName.data());
  return qualifiedName;
};

QCString Definition::localName() const
{
  return m_localName;
}

664 665 666 667 668 669 670
void Definition::setBodySegment(int bls,int ble) 
{
  //printf("setBodySegment(%d,%d) for %s\n",bls,ble,name().data());
  m_startBodyLine=bls; 
  m_endBodyLine=ble; 
}

671 672 673 674 675 676
void Definition::makePartOfGroup(GroupDef *gd)
{
  if (m_partOfGroups==0) m_partOfGroups = new GroupList;
  m_partOfGroups->append(gd);
}

677 678 679 680 681
void Definition::setRefItems(const QList<ListItemInfo> *sli)
{
  if (sli)
  {
    // deep copy the list
682
    if (m_xrefListItems==0) 
683
    {
684 685
      m_xrefListItems=new QList<ListItemInfo>;
      m_xrefListItems->setAutoDelete(TRUE);
686 687 688 689 690
    }
    QListIterator<ListItemInfo> slii(*sli);
    ListItemInfo *lii;
    for (slii.toFirst();(lii=slii.current());++slii)
    {
691
      m_xrefListItems->append(new ListItemInfo(*lii));
692 693 694 695
    } 
  }
}

696 697
void Definition::mergeRefItems(Definition *d)
{
698
  if (d->xrefListItems())
699 700
  {
    // deep copy the list
701
    if (m_xrefListItems==0) 
702
    {
703 704
      m_xrefListItems=new QList<ListItemInfo>;
      m_xrefListItems->setAutoDelete(TRUE);
705
    }
706
    QListIterator<ListItemInfo> slii(*d->xrefListItems());
707 708 709
    ListItemInfo *lii;
    for (slii.toFirst();(lii=slii.current());++slii)
    {
710
      if (getXRefListId(lii->type)==-1)
711
      {
712
        m_xrefListItems->append(new ListItemInfo(*lii));
713 714 715 716 717
      }
    } 
  }
}

718
int Definition::getXRefListId(const char *listName) const
719
{
720
  if (m_xrefListItems)
721
  {
722
    QListIterator<ListItemInfo> slii(*m_xrefListItems);
723 724 725 726 727 728 729 730 731 732 733 734
    ListItemInfo *lii;
    for (slii.toFirst();(lii=slii.current());++slii)
    {
      if (strcmp(lii->type,listName)==0)
      {
        return lii->itemId;
      }
    }
  }
  return -1;
}

735
const QList<ListItemInfo> *Definition::xrefListItems() const
736
{
737
  return m_xrefListItems;
738
}
739

740 741 742 743 744 745 746 747 748 749 750 751 752

QCString Definition::convertNameToFile(const char *name,bool allowDots) const
{
  if (!m_ref.isEmpty())
  {
    return name;
  }
  else
  {
    return ::convertNameToFile(name,allowDots);
  }
}