From 04dd14e8f14f65481ef7ed7a29e79a30c5fe301d Mon Sep 17 00:00:00 2001
From: Dimitri van Heesch <dimitri@stack.nl>
Date: Tue, 24 Dec 2002 19:52:54 +0000
Subject: Release-1.3-rc2-20021224

---
 INSTALL                   |   4 +-
 README                    |   4 +-
 VERSION                   |   2 +-
 doc/faq.doc               |   6 +-
 doc/index.doc             |   5 +-
 packages/rpm/doxygen.spec |   2 +-
 src/commentcnv.l          |  14 ++-
 src/definition.cpp        |  22 +++++
 src/definition.h          |   1 +
 src/docparser.cpp         | 227 +++++++++++++++++++++++++++++++++++++---------
 src/docparser.h           |   1 +
 src/doctokenizer.l        |  17 ++--
 src/doxygen.cpp           |   4 +-
 src/htmldocvisitor.cpp    |  42 +++++----
 src/memberdef.cpp         |  11 ++-
 src/rtfstyle.cpp          |   2 +-
 src/scanner.l             |  12 +--
 src/translator_de.h       |   2 +-
 src/translator_en.h       |  14 +--
 src/translator_sr.h       |  16 ++++
 src/util.cpp              |  33 +++++--
 src/xmlgen.cpp            |  13 ++-
 22 files changed, 347 insertions(+), 107 deletions(-)

diff --git a/INSTALL b/INSTALL
index 8a8268d..5cc30f1 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
-DOXYGEN Version 1.3-rc2
+DOXYGEN Version 1.3-rc2-20021224
 
 Please read the installation section of the manual 
 (http://www.doxygen.org/install.html) for instructions.
 
 --------
-Dimitri van Heesch (16 December 2002)
+Dimitri van Heesch (24 December 2002)
diff --git a/README b/README
index 8d3f63c..a41922f 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-DOXYGEN Version 1.3_rc2
+DOXYGEN Version 1.3_rc2_20021224
 
 Please read INSTALL for compilation instructions.
 
@@ -17,4 +17,4 @@ to subscribe to the lists or to visit the archives.
 
 Enjoy,
 
-Dimitri van Heesch (dimitri@stack.nl) (16 December 2002)
+Dimitri van Heesch (dimitri@stack.nl) (24 December 2002)
diff --git a/VERSION b/VERSION
index 87c744a..f634979 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3-rc2
+1.3-rc2-20021224
diff --git a/doc/faq.doc b/doc/faq.doc
index 56b1039..576daaf 100644
--- a/doc/faq.doc
+++ b/doc/faq.doc
@@ -62,7 +62,8 @@ PREDEFINED             = MY_MACRO()=
       manual for more information.
   </ol> 
 
-<li><b>When I set EXTRACT_ALL to NO none of my functions are shown in the documentation.</b></li>
+<li><b>When I set EXTRACT_ALL to NO none of my functions are shown in the 
+    documentation.</b></li>
 
 In order for global functions, variables, enums, typedefs, and defines 
 to be documented you should document the file in which these commands are
@@ -72,6 +73,9 @@ command.
 Alternatively, you can put all members in a group (or module)
 using the \\ingroup command and then document the group using a comment
 block containing the \\defgroup command.
+
+For member functions or functions that are part of a namespace you should
+document either the class or namespace.
  
 <li><b>How can I make doxygen ignore some code fragment?</b>
 <p>
diff --git a/doc/index.doc b/doc/index.doc
index b04cc8a..59281a6 100644
--- a/doc/index.doc
+++ b/doc/index.doc
@@ -181,8 +181,9 @@ Thanks go to:
     All language maintainers for providing translations into many languages.
 <li>Erik Jan Lingen of <a href="http://www.habanera.nl/">Habanera</a>, Mark
     Roddy, Paul Schwartz, Charles Duffy, Vadym Voznyuk, Philip Walton,
-    Dwight Browne, Andreas Fredriksson, Karel Lindveld, and Ivan Lee 
-    for donating money.
+    Dwight Browne, Andreas Fredriksson, Karel Lindveld, Ivan Lee, Albert
+    Vernon, Adam McKee, Vijapurapu Anatharac, Ben Hunsberger and 
+    Walter Wartenweiler for donating money.
 <li>The Comms group of <a href="http://www.symbian.com">Symbian</a> for donating
     an ultra cool <a href="http://www.psion.com/revoplus">Revo plus</a> 
     organizer!
diff --git a/packages/rpm/doxygen.spec b/packages/rpm/doxygen.spec
index d8de065..669384c 100644
--- a/packages/rpm/doxygen.spec
+++ b/packages/rpm/doxygen.spec
@@ -1,6 +1,6 @@
 Summary: A documentation system for C/C++.
 Name: doxygen
-Version: 1.3_rc2
+Version: 1.3_rc2_20021224
 Release: 1
 Epoch: 1
 Source0: ftp://ftp.stack.nl/pub/users/dimitri/%{name}-%{version}.src.tar.gz
diff --git a/src/commentcnv.l b/src/commentcnv.l
index b0fed8d..4e3e8e3 100644
--- a/src/commentcnv.l
+++ b/src/commentcnv.l
@@ -41,7 +41,7 @@ static void replaceCommentMarker(const char *s,int len)
     p++;
   }
   // replace start of comment marker by spaces
-  while ((c=*p) && (c=='/' || c=='!')) 
+  while ((c=*p) && (c=='/' || c=='!' || c=='#')) 
   {
     g_outBuf->addChar(' ');
     p++;
@@ -109,6 +109,12 @@ static int yyread(char *buf,int max_size)
 				     copyToOutput(yytext+i,yyleng-i); 
 				     BEGIN(SComment); 
                                    }
+<Scan>"//##Documentation".*\n	   { /* Start of Rational Rose ANSI C++ comment block */
+                                     int i=17; //=strlen("//##Documentation");
+				     copyToOutput("/**",3);
+				     copyToOutput(yytext+i,yyleng-i);
+				     BEGIN(SComment);
+  				   }
 <Scan>"//".*\n		           { /* one line C++ comment */ 
   				     copyToOutput(yytext,yyleng); 
 				   }
@@ -180,6 +186,12 @@ static int yyread(char *buf,int max_size)
 <SComment>\n[ \t]*"//!".*/\n       { 
                                      replaceCommentMarker(yytext,yyleng); 
                                    }
+<SComment>^[ \t]*"//##".*/\n       {
+                                     replaceCommentMarker(yytext,yyleng);
+                                   }
+<SComment>\n[ \t]*"//##".*/\n      {
+                                     replaceCommentMarker(yytext,yyleng);
+                                   }
 <SComment>\n			   { /* end of special comment */
                                      copyToOutput(" */",3); 
 				     copyToOutput(yytext,yyleng); 
diff --git a/src/definition.cpp b/src/definition.cpp
index 46d66a9..3f1ff1b 100644
--- a/src/definition.cpp
+++ b/src/definition.cpp
@@ -620,6 +620,28 @@ void Definition::setRefItems(const QList<ListItemInfo> *sli)
   }
 }
 
+void Definition::mergeRefItems(Definition *d)
+{
+  if (d->specialListItems())
+  {
+    // deep copy the list
+    if (m_specialListItems==0) 
+    {
+      m_specialListItems=new QList<ListItemInfo>;
+      m_specialListItems->setAutoDelete(TRUE);
+    }
+    QListIterator<ListItemInfo> slii(*d->specialListItems());
+    ListItemInfo *lii;
+    for (slii.toFirst();(lii=slii.current());++slii)
+    {
+      if (getSpecialListId(lii->type)==-1)
+      {
+        m_specialListItems->append(new ListItemInfo(*lii));
+      }
+    } 
+  }
+}
+
 int Definition::getSpecialListId(const char *listName) const
 {
   if (m_specialListItems)
diff --git a/src/definition.h b/src/definition.h
index 88c9628..0fc367c 100644
--- a/src/definition.h
+++ b/src/definition.h
@@ -113,6 +113,7 @@ class Definition
     //int testId() const { return m_testId; }
     //int bugId() const { return m_bugId; }
     void setRefItems(const QList<ListItemInfo> *sli);
+    void mergeRefItems(Definition *d);
     int getSpecialListId(const char *listName) const;
     const QList<ListItemInfo> *specialListItems() const;
 
diff --git a/src/docparser.cpp b/src/docparser.cpp
index 2f9bda7..42919fd 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -69,13 +69,14 @@ static uint     g_includeFileOffset;
 static uint     g_includeFileLength;
 
 // parser state
-static QString               g_context;
+static QString                g_context;
 static bool                   g_inSeeBlock;
 static bool                   g_insideHtmlLink;
 static QStack<DocNode>        g_nodeStack;
 static QStack<DocStyleChange> g_styleStack;
+static QStack<DocStyleChange> g_initialStyleStack;
 static QList<Definition>      g_copyStack;
-static QString               g_fileName;
+static QString                g_fileName;
 
 struct DocParserContext
 {
@@ -84,6 +85,7 @@ struct DocParserContext
   bool insideHtmlLink;
   QStack<DocNode> nodeStack;
   QStack<DocStyleChange> styleStack;
+  QStack<DocStyleChange> initialStyleStack;
   QList<Definition> copyStack;
   MemberDef *memberDef;
   QString fileName;
@@ -96,27 +98,29 @@ static QStack<DocParserContext> g_parserStack;
 static void docParserPushContext()
 {
   doctokenizerYYpushContext();
-  DocParserContext *ctx = new DocParserContext;
-  ctx->context        = g_context;
-  ctx->inSeeBlock     = g_inSeeBlock;
-  ctx->insideHtmlLink = g_insideHtmlLink;
-  ctx->nodeStack      = g_nodeStack;
-  ctx->styleStack     = g_styleStack;
-  ctx->copyStack      = g_copyStack;
-  ctx->fileName       = g_fileName;
+  DocParserContext *ctx   = new DocParserContext;
+  ctx->context            = g_context;
+  ctx->inSeeBlock         = g_inSeeBlock;
+  ctx->insideHtmlLink     = g_insideHtmlLink;
+  ctx->nodeStack          = g_nodeStack;
+  ctx->styleStack         = g_styleStack;
+  ctx->initialStyleStack  = g_initialStyleStack;
+  ctx->copyStack          = g_copyStack;
+  ctx->fileName           = g_fileName;
   g_parserStack.push(ctx);
 }
 
 static void docParserPopContext()
 {
   DocParserContext *ctx = g_parserStack.pop();
-  g_context        = ctx->context;
-  g_inSeeBlock     = ctx->inSeeBlock;
-  g_insideHtmlLink = ctx->insideHtmlLink;
-  g_nodeStack      = ctx->nodeStack;
-  g_styleStack     = ctx->styleStack;
-  g_copyStack      = ctx->copyStack;
-  g_fileName       = ctx->fileName;
+  g_context             = ctx->context;
+  g_inSeeBlock          = ctx->inSeeBlock;
+  g_insideHtmlLink      = ctx->insideHtmlLink;
+  g_nodeStack           = ctx->nodeStack;
+  g_styleStack          = ctx->styleStack;
+  g_initialStyleStack   = ctx->initialStyleStack;
+  g_copyStack           = ctx->copyStack;
+  g_fileName            = ctx->fileName;
   delete ctx;
   doctokenizerYYpopContext();
 }
@@ -296,7 +300,7 @@ static void checkUndocumentedParams()
             "Warning: The following parameters of "+
             scope + QString(g_memberDef->name()) + 
             QString(argListToString(al)) +
-            " are not documented:";
+            " are not documented:\n";
         for (ali.toFirst();(a=ali.current());++ali)
         {
           QString argName = g_memberDef->isDefine() ? a->type : a->name;
@@ -559,6 +563,9 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
          ) ? tok : RetVal_OK; 
 }
 
+/*! Called when a style change starts. For instance a \<b\> command is
+ *  encountered.
+ */
 static void handleStyleEnter(DocNode *parent,QList<DocNode> &children,
           DocStyleChange::Style s,const HtmlAttribList *attribs)
 {
@@ -568,6 +575,9 @@ static void handleStyleEnter(DocNode *parent,QList<DocNode> &children,
   g_styleStack.push(sc);
 }
 
+/*! Called when a style change ends. For instance a \</b\> command is
+ *  encountered.
+ */
 static void handleStyleLeave(DocNode *parent,QList<DocNode> &children,
          DocStyleChange::Style s,const char *tagName)
 {
@@ -577,8 +587,16 @@ static void handleStyleLeave(DocNode *parent,QList<DocNode> &children,
       g_styleStack.top()->position()!=g_nodeStack.count() // wrong position
      )
   {
-    warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </%s> tag without matching <%s> in the same paragraph",
-        tagName,tagName);
+    if (g_styleStack.isEmpty())
+    {
+      warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </%s> tag without matching <%s>",
+          tagName,tagName);
+    }
+    else
+    {
+      warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: found </%s> tag while expecting </%s>",
+          tagName,g_styleStack.top()->styleString());
+    }
   }
   else // end the section
   {
@@ -588,6 +606,10 @@ static void handleStyleLeave(DocNode *parent,QList<DocNode> &children,
   }
 }
 
+/*! Called at the end of a paragraph to close all open style changes
+ *  (e.g. a <b> without a </b>). The closed styles are pushed onto a stack
+ *  and entered again at the start of a new paragraph.
+ */
 static void handlePendingStyleCommands(DocNode *parent,QList<DocNode> &children)
 {
   if (!g_styleStack.isEmpty())
@@ -595,27 +617,53 @@ static void handlePendingStyleCommands(DocNode *parent,QList<DocNode> &children)
     DocStyleChange *sc = g_styleStack.top();
     while (sc && sc->position()>=g_nodeStack.count()) 
     { // there are unclosed style modifiers in the paragraph
-      const char *cmd="";
-      switch (sc->style())
-      {
-        case DocStyleChange::Bold:         cmd = "b"; break;
-        case DocStyleChange::Italic:       cmd = "em"; break;
-        case DocStyleChange::Code:         cmd = "code"; break;
-        case DocStyleChange::Center:       cmd = "center"; break;
-        case DocStyleChange::Small:        cmd = "small"; break;
-        case DocStyleChange::Subscript:    cmd = "subscript"; break;
-        case DocStyleChange::Superscript:  cmd = "superscript"; break;
-        case DocStyleChange::Preformatted: cmd = "pre"; break;
-      }
-      warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: end of paragraph without end of style "
-             "command </%s>",cmd);
       children.append(new DocStyleChange(parent,g_nodeStack.count(),sc->style(),FALSE));
+      g_initialStyleStack.push(sc);
       g_styleStack.pop();
       sc = g_styleStack.top();
     }
   }
 }
 
+static void handleInitialStyleCommands(DocPara *parent,QList<DocNode> &children)
+{
+  DocStyleChange *sc;
+  while ((sc=g_initialStyleStack.pop()))
+  {
+    handleStyleEnter(parent,children,sc->style(),&sc->attribs());
+  }
+}
+
+const char *DocStyleChange::styleString() const
+{
+  switch (m_style)
+  {
+    case DocStyleChange::Bold:         return "b"; 
+    case DocStyleChange::Italic:       return "em"; 
+    case DocStyleChange::Code:         return "code"; 
+    case DocStyleChange::Center:       return "center"; 
+    case DocStyleChange::Small:        return "small"; 
+    case DocStyleChange::Subscript:    return "subscript"; 
+    case DocStyleChange::Superscript:  return "superscript"; 
+    case DocStyleChange::Preformatted: return "pre"; 
+  }
+  return "<invalid>";
+}
+
+static void handleUnclosedStyleCommands()
+{
+  if (!g_initialStyleStack.isEmpty())
+  {
+    DocStyleChange *sc = g_initialStyleStack.top();
+    g_initialStyleStack.pop();
+    handleUnclosedStyleCommands();
+    warn_doc_error(g_fileName,doctokenizerYYlineno,
+             "Warning: end of comment block while expecting "
+             "command </%s>",sc->styleString());
+  }
+}
+
+
 static void handleLinkedWord(DocNode *parent,QList<DocNode> &children)
 {
   Definition *compound=0;
@@ -828,13 +876,13 @@ static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children
             {
               handleStyleEnter(parent,children,DocStyleChange::Preformatted,&g_token->attribs);
               parent->setInsidePreformatted(TRUE);
-              doctokenizerYYsetInsidePre(TRUE);
+              //doctokenizerYYsetInsidePre(TRUE);
             }
             else
             {
               handleStyleLeave(parent,children,DocStyleChange::Preformatted,tokenName);
               parent->setInsidePreformatted(FALSE);
-              doctokenizerYYsetInsidePre(FALSE);
+              //doctokenizerYYsetInsidePre(FALSE);
             }
             break;
           case HTML_CODE:
@@ -2394,8 +2442,78 @@ int DocHtmlDescTitle::parse()
       switch (tok)
       {
         case TK_COMMAND: 
-          warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <dt> tag",
-              g_token->name.data());
+          {
+            QString cmdName=g_token->name;
+            bool isJavaLink=FALSE;
+            switch (CmdMapper::map(cmdName))
+            {
+              case CMD_REF:
+                {
+                  int tok=doctokenizerYYlex();
+                  if (tok!=TK_WHITESPACE)
+                  {
+                    warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
+                        g_token->name.data());
+                  }
+                  else
+                  {
+                    doctokenizerYYsetStateRef();
+                    tok=doctokenizerYYlex(); // get the reference id
+                    if (tok!=TK_WORD)
+                    {
+                      warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
+                          tokToString(tok),cmdName.data());
+                    }
+                    else
+                    {
+                      DocRef *ref = new DocRef(this,g_token->name);
+                      m_children.append(ref);
+                      ref->parse();
+                    }
+                    doctokenizerYYsetStatePara();
+                  }
+                }
+                break;
+              case CMD_JAVALINK:
+                isJavaLink=TRUE;
+                // fall through
+              case CMD_LINK:
+                {
+                  int tok=doctokenizerYYlex();
+                  if (tok!=TK_WHITESPACE)
+                  {
+                    warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected whitespace after %s command",
+                        cmdName.data());
+                  }
+                  else
+                  {
+                    doctokenizerYYsetStateLink();
+                    tok=doctokenizerYYlex();
+                    if (tok!=TK_WORD)
+                    {
+                      warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected token %s as the argument of %s",
+                          tokToString(tok),cmdName.data());
+                    }
+                    else
+                    {
+                      doctokenizerYYsetStatePara();
+                      DocLink *lnk = new DocLink(this,g_token->name);
+                      m_children.append(lnk);
+                      QString leftOver = lnk->parse(isJavaLink);
+                      if (!leftOver.isEmpty())
+                      {
+                        m_children.append(new DocWord(this,leftOver));
+                      }
+                    }
+                  }
+                }
+
+                break;
+              default:
+                warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Illegal command %s as part of a <dt> tag",
+                               g_token->name.data());
+            }
+          }
           break;
         case TK_SYMBOL: 
           warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unsupported symbol %s found",
@@ -2413,6 +2531,17 @@ int DocHtmlDescTitle::parse()
             {
               // ignore </dt> tag.
             }
+            else if (tagId==HTML_DT)
+            {
+              // missing <dt> tag.
+              retval = RetVal_DescTitle;
+              goto endtitle;
+            }
+            else if (tagId==HTML_DL && g_token->endTag)
+            {
+              retval=RetVal_EndDesc;
+              goto endtitle;
+            }
             else
             {
               warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: Unexpected html tag <%s%s> found within <dt> context",
@@ -2518,7 +2647,7 @@ int DocHtmlDescList::parse()
     {
       retval=dd->parse();
     }
-    else
+    else if (retval!=RetVal_DescTitle)
     {
       // error
       break;
@@ -3630,7 +3759,7 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag
     case HTML_PRE:
       handleStyleEnter(this,m_children,DocStyleChange::Preformatted,&g_token->attribs);
       setInsidePreformatted(TRUE);
-      doctokenizerYYsetInsidePre(TRUE);
+      //doctokenizerYYsetInsidePre(TRUE);
       break;
     case HTML_P:
       retval=TK_NEWPARA;
@@ -3759,14 +3888,21 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag
       {
         HtmlAttribListIterator li(tagHtmlAttribs);
         HtmlAttrib *opt;
+        bool found=FALSE;
         for (li.toFirst();(opt=li.current());++li)
         {
+          //printf("option name=%s value=%s\n",opt->name.data(),opt->value.data());
           if (opt->name=="src" && !opt->value.isEmpty())
           {
             DocImage *img = new DocImage(this,opt->value,DocImage::Html);
             m_children.append(img);
+            found = TRUE;
           }
         }
+        if (!found)
+        {
+          warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: IMG tag does not have a SRC attribute!\n");
+        }
       }
       break;
     case HTML_UNKNOWN:
@@ -3849,9 +3985,9 @@ int DocPara::handleHtmlEndTag(const QString &tagName)
       handleStyleLeave(this,m_children,DocStyleChange::Small,"small");
       break;
     case HTML_PRE:
-      handleStyleLeave(this,m_children,DocStyleChange::Preformatted,"preformatted");
+      handleStyleLeave(this,m_children,DocStyleChange::Preformatted,"pre");
       setInsidePreformatted(FALSE);
-      doctokenizerYYsetInsidePre(FALSE);
+      //doctokenizerYYsetInsidePre(FALSE);
       break;
     case HTML_P:
       // ignore </p> tag
@@ -3918,6 +4054,7 @@ int DocPara::parse()
 {
   DBG(("DocPara::parse() start\n"));
   g_nodeStack.push(this);
+  handleInitialStyleCommands(this,m_children);
   int tok;
   int retval=0;
   while ((tok=doctokenizerYYlex())) // get the next token
@@ -4369,6 +4506,8 @@ void DocText::parse()
     }
   }
 
+  handleUnclosedStyleCommands();
+
   DocNode *n = g_nodeStack.pop();
   ASSERT(n==this);
 }
@@ -4423,6 +4562,8 @@ void DocRoot::parse()
     retval = in->parse();
   }
 
+  handleUnclosedStyleCommands();
+
   DocNode *n = g_nodeStack.pop();
   ASSERT(n==this);
 }
@@ -4443,6 +4584,7 @@ DocNode *validatingParseDoc(const char *fileName,int startLine,
   g_memberDef = md;
   g_nodeStack.clear();
   g_styleStack.clear();
+  g_initialStyleStack.clear();
   g_inSeeBlock = FALSE;
   g_insideHtmlLink = FALSE;
   g_includeFileText = "";
@@ -4491,6 +4633,7 @@ DocNode *validatingParseText(const char *input)
   g_memberDef = 0;
   g_nodeStack.clear();
   g_styleStack.clear();
+  g_initialStyleStack.clear();
   g_inSeeBlock = FALSE;
   g_insideHtmlLink = FALSE;
   g_includeFileText = "";
diff --git a/src/docparser.h b/src/docparser.h
index a505a6d..d7c83d2 100644
--- a/src/docparser.h
+++ b/src/docparser.h
@@ -283,6 +283,7 @@ class DocStyleChange : public DocNode
       { if (attribs) m_attribs=*attribs; }
     Kind kind() const { return Kind_StyleChange; }
     Style style() const { return m_style; }
+    const char *styleString() const;
     bool enable() const { return m_enable; }
     uint position() const { return m_position; }
     DocNode *parent() const { return m_parent; }
diff --git a/src/doctokenizer.l b/src/doctokenizer.l
index 390a666..de8937c 100644
--- a/src/doctokenizer.l
+++ b/src/doctokenizer.l
@@ -162,26 +162,27 @@ static void parseHtmlAttribs(const char *att)
     while (i<len && c==' ') { c=attribs.at(++i); } 
     if (attribs.at(i)=='=') // option has value
     {
-      i++;
+      c=attribs.at(++i);
       // skip spaces
       while (i<len && c==' ') { c=attribs.at(++i); } 
       if (attribs.at(i)=='\'') // option '...'
       {
-	i++;
+        c=attribs.at(++i);
 	startAttrib=i;
+	
 	// search for matching quote 
         while (i<len && c!='\'') { c=attribs.at(++i); } 
 	endAttrib=i;
-	i++;
+        c=attribs.at(++i);
       }
       else if (attribs.at(i)=='"') // option "..."
       {
-	i++;
+        c=attribs.at(++i);
 	startAttrib=i;
 	// search for matching quote 
         while (i<len && c!='"') { c=attribs.at(++i); } 
 	endAttrib=i;
-	i++;
+        c=attribs.at(++i);
       }
       else // value without any quotes
       {
@@ -189,7 +190,7 @@ static void parseHtmlAttribs(const char *att)
 	// search for separator
         while (i<len && c!=' ') { c=attribs.at(++i); } 
 	endAttrib=i;
-	i++;
+        c=attribs.at(++i);
       }
       opt.value  = attribs.mid(startAttrib,endAttrib-startAttrib); 
     }
@@ -378,7 +379,7 @@ LABELID   [a-z_A-Z][a-z_A-Z0-9\-]*
 			 g_token->isEMailAddr=FALSE;
 			 return TK_URL;
                        }
-<St_Para>[a-z_A-Z0-9.-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-])+[a-z_A-Z0-9\-]+ { // Mail address
+<St_Para>[a-z_A-Z0-9.-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+ { // Mail address
                          g_token->name=yytext;
 			 g_token->isEMailAddr=TRUE;
 			 return TK_URL;
@@ -598,7 +599,7 @@ LABELID   [a-z_A-Z][a-z_A-Z0-9\-]*
   			 return 0;
                        }
 
-<St_Ref>{ID}	       {
+<St_Ref>({ID}[.-])*{ID} {
   			 g_token->name=yytext;
 			 return TK_WORD;
   		       }
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index bf74941..5b184d8 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -2524,8 +2524,8 @@ static void transferFunctionDocumentation()
               //  mdec->setGroupDef(mdef->getGroupDef(),mdef->getGroupPri(),mdef->docFile(),mdef->docLine(),mdef->hasDocumentation());
               //}
 
-              mdec->setRefItems(mdef->specialListItems());
-              mdef->setRefItems(mdec->specialListItems());
+              mdec->mergeRefItems(mdef);
+              mdef->mergeRefItems(mdec);
 
               mdef->setMemberDeclaration(mdec);
               mdec->setMemberDefinition(mdef);
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index a5bcb1b..12f2654 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -166,7 +166,7 @@ void HtmlDocVisitor::visit(DocStyleChange *s)
       else
       {
         m_insidePre=FALSE;
-        m_t << "</pre>\n";
+        m_t << "</pre>";
       }
   }
 }
@@ -279,24 +279,26 @@ void HtmlDocVisitor::visitPre(DocAutoList *l)
 {
   if (l->isEnumList())
   {
-    m_t << "<ol>\n";
+    m_t << "<ol>";
   }
   else
   {
-    m_t << "<ul>\n";
+    m_t << "<ul>";
   }
+  if (!l->isPreformatted()) m_t << "\n";
 }
 
 void HtmlDocVisitor::visitPost(DocAutoList *l)
 {
   if (l->isEnumList())
   {
-    m_t << "</ol>\n";
+    m_t << "</ol>";
   }
   else
   {
-    m_t << "</ul>\n";
+    m_t << "</ul>";
   }
+  if (!l->isPreformatted()) m_t << "\n";
 }
 
 void HtmlDocVisitor::visitPre(DocAutoListItem *)
@@ -318,8 +320,11 @@ void HtmlDocVisitor::visitPost(DocPara *p)
   if (!p->isLast() &&            // omit <p> for last paragraph
       !(p->parent() &&           // and for parameter sections
         p->parent()->kind()==DocNode::Kind_ParamSect
-       )
-     ) m_t << "\n<p>\n";
+       ) 
+     ) 
+  {
+    m_t << "<p>";
+  }
 }
 
 void HtmlDocVisitor::visitPre(DocRoot *)
@@ -391,14 +396,16 @@ void HtmlDocVisitor::visitPost(DocTitle *)
   m_t << "</b></dt><dd>";
 }
 
-void HtmlDocVisitor::visitPre(DocSimpleList *)
+void HtmlDocVisitor::visitPre(DocSimpleList *sl)
 {
-  m_t << "<ul>\n";
+  m_t << "<ul>";
+  if (!sl->isPreformatted()) m_t << "\n";
 }
 
-void HtmlDocVisitor::visitPost(DocSimpleList *)
+void HtmlDocVisitor::visitPost(DocSimpleList *sl)
 {
-  m_t << "</ul>\n";
+  m_t << "</ul>";
+  if (!sl->isPreformatted()) m_t << "\n";
 }
 
 void HtmlDocVisitor::visitPre(DocSimpleListItem *)
@@ -406,9 +413,10 @@ void HtmlDocVisitor::visitPre(DocSimpleListItem *)
   m_t << "<li>";
 }
 
-void HtmlDocVisitor::visitPost(DocSimpleListItem *) 
+void HtmlDocVisitor::visitPost(DocSimpleListItem *li) 
 {
-  m_t << "</li>\n";
+  m_t << "</li>";
+  if (!li->isPreformatted()) m_t << "\n";
 }
 
 void HtmlDocVisitor::visitPre(DocSection *s)
@@ -435,14 +443,16 @@ void HtmlDocVisitor::visitPre(DocHtmlList *s)
 void HtmlDocVisitor::visitPost(DocHtmlList *s) 
 {
   if (s->type()==DocHtmlList::Ordered) 
-    m_t << "</ol>\n"; 
+    m_t << "</ol>"; 
   else 
-    m_t << "</ul>\n";
+    m_t << "</ul>";
+  if (!s->isPreformatted()) m_t << "\n";
 }
 
 void HtmlDocVisitor::visitPre(DocHtmlListItem *i)
 {
-  m_t << "<li" << htmlAttribsToString(i->attribs()) << ">\n";
+  m_t << "<li" << htmlAttribsToString(i->attribs()) << ">";
+  if (!i->isPreformatted()) m_t << "\n";
 }
 
 void HtmlDocVisitor::visitPost(DocHtmlListItem *) 
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 7015c08..bff8512 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -706,6 +706,11 @@ void MemberDef::writeDeclaration(OutputList &ol,
   if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;
   QCString cname  = d->name();
   QCString cfname = d->getOutputFileBase();
+  QCString osname = cname;
+  // in case of class members that are put in a group the name of the outerscope
+  // differs from the cname.
+  if (getOuterScope()) osname=getOuterScope()->name();
+  
 
   HtmlHelp *htmlHelp=0;
   bool hasHtmlHelp = Config_getBool("GENERATE_HTML") && Config_getBool("GENERATE_HTMLHELP");
@@ -926,7 +931,7 @@ void MemberDef::writeDeclaration(OutputList &ol,
       !annMemb)
   {
     ol.startMemberDescription();
-    ol.parseDoc(briefFile(),briefLine(),cname,this,briefDescription(),FALSE);
+    ol.parseDoc(briefFile(),briefLine(),osname,this,briefDescription(),FALSE);
     if (detailsVisible) 
     {
       ol.pushGeneratorState();
@@ -1590,8 +1595,8 @@ void MemberDef::warnIfUndocumented()
       (prot!=Private || Config_getBool("EXTRACT_PRIVATE"))
      )
   {
-   warn_undoc(m_defFileName,m_defLine,"Warning: Member %s of %s %s is not documented.",
-        name().data(),t,d->name().data());
+   warn_undoc(m_defFileName,m_defLine,"Warning: Member %s%s of %s %s is not documented.",
+        name().data(),argsString()?argsString():"",t,d->name().data());
   }
 }
 
diff --git a/src/rtfstyle.cpp b/src/rtfstyle.cpp
index 074872e..950b4ba 100644
--- a/src/rtfstyle.cpp
+++ b/src/rtfstyle.cpp
@@ -442,7 +442,7 @@ void loadStylesheet(const char *name, QDict<StyleData>& dict)
   {
     QCString s(4096); // string buffer of max line length
     s = t.readLine().stripWhiteSpace();
-    if (s.length()==0 || s.at(0)=='#') continue; // skip blanks & comments
+    if (s.isEmpty() || s.at(0)=='#') continue; // skip blanks & comments
     int sepLength;
     int sepStart = separator.match(s,0,&sepLength);
     if (sepStart<=0) // no valid assignment statement
diff --git a/src/scanner.l b/src/scanner.l
index 9f6d9fb..c6b4eaf 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -851,11 +851,6 @@ CHARLIT   (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
 <FindMembers>{BN}{1,80}			{
   					  lineCount();
   					}
-<FindMembers>{B}*"package"{BN}+ 	{ // Java package
-  					  lineCount();
-					  BEGIN(PackageName);
-
-  					}
 <PackageName>{ID}("."{ID})*		{
   					  //current->name = yytext;
                                           //current->fileName = yyFileName; 
@@ -1284,6 +1279,11 @@ CHARLIT   (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
 					    else // insideJava
 					      BEGIN(JavaImport);
 					  }
+					  else if (insideJava && strcmp(yytext,"package")==0)
+					  {
+  					    lineCount();
+					    BEGIN(PackageName);
+					  }
 					  else if (insideIDL && strcmp(yytext,"case")==0)
 					  {
 					    BEGIN(IDLUnionCase);
@@ -1913,7 +1913,7 @@ CHARLIT   (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
 					      current = new Entry(*current);
 					      if (current->section==Entry::NAMESPACE_SEC || 
 						  current->section==Entry::INTERFACE_SEC ||
-						  insideJava
+						  insideJava || insidePHP
 						 )
 					      { // namespaces and interfaces and java classes ends with a closing bracket without semicolon
 						current->reset();
diff --git a/src/translator_de.h b/src/translator_de.h
index 6134aaf..af7483a 100644
--- a/src/translator_de.h
+++ b/src/translator_de.h
@@ -101,7 +101,7 @@ class TranslatorGerman : public Translator
     {
       QCString result="\\usepackage{ngerman}\n";
       result+="\\usepackage{t1enc}% Trennung verbessern bei Umlauten\n";
-      result+="%\\usepackage[latin1]{inputenc}% Kodierung (cp850,latin1,ansinew)";
+      result+="%\\usepackage[latin1]{inputenc}% Kodierung (cp850,latin1,ansinew)\n";
       return result;
     }
 
diff --git a/src/translator_en.h b/src/translator_en.h
index b045524..8b4ab26 100644
--- a/src/translator_en.h
+++ b/src/translator_en.h
@@ -669,25 +669,25 @@ class TranslatorEnglish : public Translator
     }
     
     virtual QCString trPublicMembers()
-    { return "Public Methods"; }
+    { return "Public Member Functions"; }
     virtual QCString trPublicSlots()
     { return "Public Slots"; }
     virtual QCString trSignals()
     { return "Signals"; }
     virtual QCString trStaticPublicMembers()
-    { return "Static Public Methods"; }
+    { return "Static Public Member Functions"; }
     virtual QCString trProtectedMembers()
-    { return "Protected Methods"; }
+    { return "Protected Member Functions"; }
     virtual QCString trProtectedSlots()
     { return "Protected Slots"; }
     virtual QCString trStaticProtectedMembers()
-    { return "Static Protected Methods"; }
+    { return "Static Protected Member Functions"; }
     virtual QCString trPrivateMembers()
-    { return "Private Methods"; }
+    { return "Private Member Functions"; }
     virtual QCString trPrivateSlots()
     { return "Private Slots"; }
     virtual QCString trStaticPrivateMembers()
-    { return "Static Private Methods"; }
+    { return "Static Private Member Functions"; }
     
     /*! this function is used to produce a comma-separated list of items.
      *  use generateMarker(i) to indicate where item i should be put.
@@ -1126,7 +1126,7 @@ class TranslatorEnglish : public Translator
     /*! Used as a section header for KDE-2 IDL methods */
     virtual QCString trDCOPMethods()
     {
-      return "DCOP Methods";
+      return "DCOP Member Functions";
     }
 
 //////////////////////////////////////////////////////////////////////////
diff --git a/src/translator_sr.h b/src/translator_sr.h
index dab7d15..8822774 100644
--- a/src/translator_sr.h
+++ b/src/translator_sr.h
@@ -1414,7 +1414,23 @@ private:
     {
       return decode( "Spisak zastarelih funkcija �lanica" );
     } 
+//////////////////////////////////////////////////////////////////////////
+// new since 1.2.18
+//////////////////////////////////////////////////////////////////////////
 
+    /*! Used as a header for declaration section of the events found in 
+     * a C# program
+     */
+    virtual QCString trEvents()
+    {
+      return "Doga�aji";
+    }
+    /*! Header used for the documentation section of a class' events. */
+    virtual QCString trEventDocumentation()
+    {
+      return "Dokumentacija doga�aja";
+    }
+ 
 };
 
 #endif
diff --git a/src/util.cpp b/src/util.cpp
index 7487af3..f9bfea0 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -317,15 +317,16 @@ QCString generateMarker(int id)
  */
 QCString stripFromPath(const QCString &path)
 {
-  const char *s=Config_getList("STRIP_FROM_PATH").first();
+  QStrList &l = Config_getList("STRIP_FROM_PATH");
+  const char *s=l.first();
   while (s)
   {
     QCString prefix = s;
-    if (path.left(prefix.length())==prefix)
+    if (stricmp(path.left(prefix.length()),prefix)==0) // case insensitive compare
     {
       return path.right(path.length()-prefix.length());
     }
-    s = Config_getList("STRIP_FROM_PATH").next();
+    s = l.next();
   }
   return path;
 }
@@ -1687,11 +1688,11 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
           return FALSE; // more than a difference in name -> no match
         }
       }
-      else // maybe dst has a name while src has not
+      else  // maybe dst has a name while src has not
       {
         dstPos++;
         while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
-        if (dstPos!=dstAType.length()) 
+        if (dstPos!=dstAType.length() || !srcA->name.isEmpty()) 
         {
           NOMATCH
           return FALSE; // nope not a name -> no match
@@ -1718,13 +1719,17 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
       {
         srcPos++;
         while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
-        if (srcPos!=srcAType.length()) 
+        if (srcPos!=srcAType.length() || !dstA->name.isEmpty()) 
         {
           NOMATCH
           return FALSE; // nope not a name -> no match
         }
       }
     }
+    else
+    {
+      printf("something else!\n");
+    }
   }
   MATCH
   return TRUE;
@@ -2574,8 +2579,6 @@ bool resolveLink(/* in */ const char *scName,
                  /* out */ QCString &resAnchor
                 )
 {
-  //printf("resolveLink clName=`%s' lr=`%s'\n",scName,lr);
-
   *resContext=0;
   *resPageInfo=0;
   
@@ -2583,6 +2586,8 @@ bool resolveLink(/* in */ const char *scName,
   FileDef  *fd;
   GroupDef *gd;
   PageInfo *pi;
+  ClassDef *cd;
+  NamespaceDef *nd;
   bool ambig;
   if (linkRef.isEmpty()) // no reference name!
   {
@@ -2620,7 +2625,17 @@ bool resolveLink(/* in */ const char *scName,
     *resContext=fd;
     return TRUE;
   }
-  else // probably a class or member reference
+  else if ((cd=getClass(linkRef)))
+  {
+    *resContext=cd;
+    return TRUE;
+  }
+  else if ((nd=Doxygen::namespaceSDict.find(linkRef)))
+  {
+    *resContext=nd;
+    return TRUE;
+  }
+  else // probably a member reference
   {
     MemberDef *md;
     bool res = resolveRef(scName,lr,inSeeBlock,resContext,&md);
diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp
index c1574eb..8fade1a 100644
--- a/src/xmlgen.cpp
+++ b/src/xmlgen.cpp
@@ -58,7 +58,16 @@ inline void writeXMLCodeString(QTextStream &t,const char *s)
   char c;
   while ((c=*s++))
   {
-    if (c==' ') t << "<sp/>"; else t << c;
+    switch(c)
+    {
+      case ' ':  t << "<sp/>";  break;
+      case '<':  t << "&lt;";   break;
+      case '>':  t << "&gt;";   break;
+      case '&':  t << "&amp;";  break;
+      case '\'': t << "&apos;"; break; 
+      case '"':  t << "&quot;"; break;
+      default:   t << c;        break;         
+    }
   } 
 }
 
@@ -367,7 +376,7 @@ static void writeXMLDocBlock(QTextStream &t,
   QCString stext = text.stripWhiteSpace();
   if (stext.isEmpty()) return;
   // convert the documentation string into an abstract syntax tree
-  DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,stext,FALSE);
+  DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text+"\n",FALSE);
   // create a code generator
   XMLCodeGenerator *xmlCodeGen = new XMLCodeGenerator(t);
   // create a parse tree visitor for XML
-- 
cgit v0.12

