From 490b7178adcf627892b0686b80016422e64dcfa3 Mon Sep 17 00:00:00 2001
From: Dimitri van Heesch <dimitri@stack.nl>
Date: Sun, 5 Aug 2001 12:03:04 +0000
Subject: Release-1.2.9.1

---
 Doxyfile                           |   2 +-
 INSTALL                            |   4 +-
 README                             |   4 +-
 VERSION                            |   2 +-
 addon/doxywizard/doxywizard.cpp    |   4 +-
 addon/xmlparse/basehandler.h       |  15 ++
 addon/xmlparse/compoundhandler.cpp |  15 ++
 addon/xmlparse/compoundhandler.h   |  14 ++
 addon/xmlparse/dochandler.cpp      |  54 +++++++
 addon/xmlparse/dochandler.h        | 106 ++++++++++++-
 addon/xmlparse/main.cpp            |  15 ++
 addon/xmlparse/mainhandler.cpp     |  15 ++
 addon/xmlparse/mainhandler.h       |  15 ++
 addon/xmlparse/memberhandler.cpp   |  15 ++
 addon/xmlparse/memberhandler.h     |  15 ++
 addon/xmlparse/paramhandler.cpp    |  15 ++
 addon/xmlparse/paramhandler.h      |  15 ++
 addon/xmlparse/sectionhandler.cpp  |  15 ++
 addon/xmlparse/sectionhandler.h    |  15 ++
 doc/commands.doc                   |  57 ++++++-
 packages/rpm/doxygen.spec          |   4 +-
 src/classdef.cpp                   |  23 +--
 src/classdef.h                     |   2 +-
 src/classlist.cpp                  |   8 +-
 src/declinfo.h                     |   1 -
 src/declinfo.l                     |   6 +-
 src/definition.cpp                 |   9 +-
 src/doc.l                          |  13 +-
 src/doxygen.cpp                    | 295 ++++++++++++++++++------------------
 src/htmlgen.h                      |   4 +-
 src/index.cpp                      |   6 +-
 src/latexgen.cpp                   |   6 +-
 src/latexgen.h                     |   4 +-
 src/mangen.h                       |   4 +-
 src/memberdef.cpp                  |  13 +-
 src/memberdef.h                    |   1 +
 src/rtfgen.cpp                     |   8 +-
 src/scanner.l                      | 125 +++++++++++++++-
 src/util.cpp                       | 300 ++++++++++++++++++++++++++++++-------
 src/util.h                         |   2 +
 src/xmlgen.cpp                     |   4 +-
 41 files changed, 973 insertions(+), 277 deletions(-)

diff --git a/Doxyfile b/Doxyfile
index 3ee43b2..a572e61 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -110,7 +110,7 @@ COMPACT_LATEX          = NO
 PAPER_TYPE             = a4wide
 EXTRA_PACKAGES         = 
 LATEX_HEADER           = 
-PDF_HYPERLINKS         = NO
+PDF_HYPERLINKS         = YES
 USE_PDFLATEX           = NO
 LATEX_BATCHMODE        = NO
 #---------------------------------------------------------------------------
diff --git a/INSTALL b/INSTALL
index a4c0bfc..e0809c2 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,6 +1,6 @@
-DOXYGEN Version 1.2.9
+DOXYGEN Version 1.2.9.1
 
 Please read the installation section of the manual for instructions.
 
 --------
-Dimitri van Heesch (01 August 2001)
+Dimitri van Heesch (05 August 2001)
diff --git a/README b/README
index 9dcc607..f6bbb72 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-DOXYGEN Version 1.2.9
+DOXYGEN Version 1.2.9.1
 
 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) (01 August 2001)
+Dimitri van Heesch (dimitri@stack.nl) (05 August 2001)
diff --git a/VERSION b/VERSION
index 9d4f823..140a505 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.9
+1.2.9.1
diff --git a/addon/doxywizard/doxywizard.cpp b/addon/doxywizard/doxywizard.cpp
index 3fcde0b..1a31b1a 100644
--- a/addon/doxywizard/doxywizard.cpp
+++ b/addon/doxywizard/doxywizard.cpp
@@ -62,7 +62,7 @@ static bool loadConfig( QString loadFile )
 
   // parse the config file
   // this will initialize the various Config data members
-  if (Config::instance()->parse(loadFile))
+  if (!Config::instance()->parse(loadFile))
   {
     QMessageBox::warning(0,
                          "Warning","Cannot open or read input "+loadFile+"!",
@@ -89,7 +89,7 @@ static bool saveConfig( QString saveFile )
     return FALSE; // failure
   }
 
-  Config::instance()->writeTemplate(&f,TRUE,TRUE); // write brief config file
+  Config::instance()->writeTemplate(&f,TRUE,FALSE); // write brief config file
 
   return TRUE; // success
 }
diff --git a/addon/xmlparse/basehandler.h b/addon/xmlparse/basehandler.h
index 2d037e0..0bf7c68 100644
--- a/addon/xmlparse/basehandler.h
+++ b/addon/xmlparse/basehandler.h
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #ifndef _BASEHANDLER_H
 #define _BASEHANDLER_H
 
diff --git a/addon/xmlparse/compoundhandler.cpp b/addon/xmlparse/compoundhandler.cpp
index 4949f63..c299397 100644
--- a/addon/xmlparse/compoundhandler.cpp
+++ b/addon/xmlparse/compoundhandler.cpp
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #include "mainhandler.h"
 #include "compoundhandler.h"
 #include "dochandler.h"
diff --git a/addon/xmlparse/compoundhandler.h b/addon/xmlparse/compoundhandler.h
index cd7da55..29556a0 100644
--- a/addon/xmlparse/compoundhandler.h
+++ b/addon/xmlparse/compoundhandler.h
@@ -1,3 +1,17 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
 #ifndef _COMPOUNDHANDLER_H
 #define _COMPOUNDHANDLER_H
 
diff --git a/addon/xmlparse/dochandler.cpp b/addon/xmlparse/dochandler.cpp
index c9a96c4..4e91d8f 100644
--- a/addon/xmlparse/dochandler.cpp
+++ b/addon/xmlparse/dochandler.cpp
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #include "dochandler.h"
 
 //----------------------------------------------------------------------
@@ -218,6 +233,37 @@ void ListHandler::startListItem(const QXmlAttributes& attrib)
 }
 
 //----------------------------------------------------------------------
+// ParameterHandler
+//----------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------
+// ParameterListHandler
+//----------------------------------------------------------------------
+
+ParameterListHandler::ParameterListHandler(IBaseHandler *parent) 
+  : DocNode(ParameterList), m_parent(parent)
+{
+  addEndHandler("parameterlist",this,&ParameterListHandler::endParameterList);
+  m_parameters.setAutoDelete(TRUE);
+  m_curParam=0;
+}
+
+ParameterListHandler::~ParameterListHandler()
+{
+}
+
+void ParameterListHandler::startParameterList(const QXmlAttributes& /*attrib*/)
+{
+  m_parent->setDelegate(this);
+}
+
+void ParameterListHandler::endParameterList()
+{
+  m_parent->setDelegate(0);
+}
+
+//----------------------------------------------------------------------
 // ParagraphHandler
 //----------------------------------------------------------------------
 
@@ -268,6 +314,14 @@ void ParagraphHandler::startOrderedList(const QXmlAttributes& attrib)
   m_children.append(listHandler);
 }
 
+void ParagraphHandler::startParameterList(const QXmlAttributes& attrib)
+{
+  addTextNode();
+  ParameterListHandler *parListHandler = new ParameterListHandler(this);
+  parListHandler->startParameterList(attrib);
+  m_children.append(parListHandler);
+}
+
 void ParagraphHandler::addTextNode()
 {
   if (!m_curString.isEmpty())
diff --git a/addon/xmlparse/dochandler.h b/addon/xmlparse/dochandler.h
index 761842f..376d6f8 100644
--- a/addon/xmlparse/dochandler.h
+++ b/addon/xmlparse/dochandler.h
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #ifndef _DOCHANDLER_H
 #define _DOCHANDLER_H
 
@@ -7,6 +22,13 @@
 
 #include "basehandler.h"
 
+class ParagraphHandler;
+
+//-----------------------------------------------------------------------------
+
+/*! \brief Node of a structured documentation tree.
+ *
+ */
 class DocNode
 {
   public:
@@ -28,7 +50,8 @@ class DocNode
       MarkupModifier,
       ItemizedList,
       OrderedList,
-      ListItem
+      ListItem,
+      ParameterList
     };
     DocNode(NodeKind k) : m_kind(k) {}
     virtual ~DocNode() {}
@@ -37,6 +60,12 @@ class DocNode
     NodeKind m_kind;
 };
 
+//-----------------------------------------------------------------------------
+
+
+/*! \brief Node representing a piece of text.
+ *
+ */
 class TextNode : public DocNode
 {
   public:
@@ -48,6 +77,11 @@ class TextNode : public DocNode
     int m_markup;
 };
 
+//-----------------------------------------------------------------------------
+
+/*! \brief Node representing a change in the markup style.
+ *
+ */
 class MarkupModifierNode : public DocNode
 {
   public:
@@ -59,6 +93,12 @@ class MarkupModifierNode : public DocNode
     bool m_enabled;
 };
 
+
+//-----------------------------------------------------------------------------
+
+/*! \brief Handles markup commands in the XML input. 
+ *
+ */
 class MarkupHandler : public BaseFallBackHandler<MarkupHandler>
 {
   public:
@@ -90,6 +130,12 @@ class MarkupHandler : public BaseFallBackHandler<MarkupHandler>
     int             m_curMarkup;
 };
 
+
+//-----------------------------------------------------------------------------
+
+/*! \brief Node representing a list item.
+ *
+ */
 class ListItemHandler : public DocNode, public BaseHandler<ListItemHandler>
 {
   public:
@@ -104,6 +150,12 @@ class ListItemHandler : public DocNode, public BaseHandler<ListItemHandler>
     QList<DocNode>  m_children;
 };
 
+
+//-----------------------------------------------------------------------------
+
+/*! \brief Node representing list of items.
+ *
+ */
 class ListHandler : public DocNode, public BaseHandler<ListHandler>
 {
   public:
@@ -118,6 +170,53 @@ class ListHandler : public DocNode, public BaseHandler<ListHandler>
     QList<DocNode>  m_children;
 };
 
+
+//-----------------------------------------------------------------------------
+
+/*! \brief Node representing a parameter.
+ *
+ */
+class ParameterHandler : public DocNode, 
+                         public BaseHandler<ParameterHandler>
+{
+  public:
+    ParameterHandler(IBaseHandler *parent);
+    virtual ~ParameterHandler();
+    virtual void startParameterList(const QXmlAttributes& attrib);
+    virtual void endParameterList();
+
+  private:
+    IBaseHandler     *m_parent;
+    QString           m_name;
+    ParagraphHandler *m_description;
+};
+
+
+//-----------------------------------------------------------------------------
+
+/* \brief Node representing a parameter list.
+ *
+ */
+class ParameterListHandler : public DocNode, 
+                             public BaseHandler<ParameterListHandler>
+{
+  public:
+    ParameterListHandler(IBaseHandler *parent);
+    virtual ~ParameterListHandler();
+    virtual void startParameterList(const QXmlAttributes& attrib);
+    virtual void endParameterList();
+
+  private:
+    IBaseHandler            *m_parent;
+    QList<ParameterHandler>  m_parameters;
+    ParameterHandler        *m_curParam;
+};
+
+//-----------------------------------------------------------------------------
+
+/*! \brief Node representing a paragraph of text and commands.
+ *
+ */
 class ParagraphHandler : public DocNode, public BaseHandler<ParagraphHandler>
 {
   public:
@@ -125,6 +224,7 @@ class ParagraphHandler : public DocNode, public BaseHandler<ParagraphHandler>
     virtual void endParagraph();
     virtual void startItemizedList(const QXmlAttributes& attrib);
     virtual void startOrderedList(const QXmlAttributes& attrib);
+    virtual void startParameterList(const QXmlAttributes& attrib);
 
     ParagraphHandler(IBaseHandler *parent);
     virtual ~ParagraphHandler();
@@ -136,7 +236,11 @@ class ParagraphHandler : public DocNode, public BaseHandler<ParagraphHandler>
     MarkupHandler  *m_markupHandler;
 };
 
+//-----------------------------------------------------------------------------
 
+/*! \brief Node representing a documentation block.
+ *
+ */
 class DocHandler : public BaseHandler<DocHandler>
 {
   public:
diff --git a/addon/xmlparse/main.cpp b/addon/xmlparse/main.cpp
index 82cc849..60f4142 100644
--- a/addon/xmlparse/main.cpp
+++ b/addon/xmlparse/main.cpp
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #include "mainhandler.h"
 
 #include <qstring.h>
diff --git a/addon/xmlparse/mainhandler.cpp b/addon/xmlparse/mainhandler.cpp
index b062578..8a5d449 100644
--- a/addon/xmlparse/mainhandler.cpp
+++ b/addon/xmlparse/mainhandler.cpp
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #include "mainhandler.h"
 
 void MainHandler::startCompound(const QXmlAttributes& attrib)
diff --git a/addon/xmlparse/mainhandler.h b/addon/xmlparse/mainhandler.h
index 20eedc3..75a3b98 100644
--- a/addon/xmlparse/mainhandler.h
+++ b/addon/xmlparse/mainhandler.h
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #ifndef _MAINHANDLER_H
 #define _MAINHANDLER_H
 
diff --git a/addon/xmlparse/memberhandler.cpp b/addon/xmlparse/memberhandler.cpp
index 1130f8d..4cbe4a6 100644
--- a/addon/xmlparse/memberhandler.cpp
+++ b/addon/xmlparse/memberhandler.cpp
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #include "memberhandler.h"
 #include "sectionhandler.h"
 #include "dochandler.h"
diff --git a/addon/xmlparse/memberhandler.h b/addon/xmlparse/memberhandler.h
index 5f19ee2..e18e59c 100644
--- a/addon/xmlparse/memberhandler.h
+++ b/addon/xmlparse/memberhandler.h
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #ifndef _MEMBERHANDLER_H
 #define _MEMBERHANDLER_H
 
diff --git a/addon/xmlparse/paramhandler.cpp b/addon/xmlparse/paramhandler.cpp
index 3563ebd..a800195 100644
--- a/addon/xmlparse/paramhandler.cpp
+++ b/addon/xmlparse/paramhandler.cpp
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #include "paramhandler.h"
 #include "memberhandler.h"
 
diff --git a/addon/xmlparse/paramhandler.h b/addon/xmlparse/paramhandler.h
index 062bab1..f93f83f 100644
--- a/addon/xmlparse/paramhandler.h
+++ b/addon/xmlparse/paramhandler.h
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #ifndef _PARAMHANDLER_H
 #define _PARAMHANDLER_H
 
diff --git a/addon/xmlparse/sectionhandler.cpp b/addon/xmlparse/sectionhandler.cpp
index 0b63832..80db178 100644
--- a/addon/xmlparse/sectionhandler.cpp
+++ b/addon/xmlparse/sectionhandler.cpp
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #include "compoundhandler.h"
 #include "sectionhandler.h"
 
diff --git a/addon/xmlparse/sectionhandler.h b/addon/xmlparse/sectionhandler.h
index b2d1ce1..5a4ab2a 100644
--- a/addon/xmlparse/sectionhandler.h
+++ b/addon/xmlparse/sectionhandler.h
@@ -1,3 +1,18 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * 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.
+ *
+ */
+
 #ifndef _SECTIONHANDLER_H
 #define _SECTIONHANDLER_H
 
diff --git a/doc/commands.doc b/doc/commands.doc
index bfee043..cd2a634 100644
--- a/doc/commands.doc
+++ b/doc/commands.doc
@@ -62,6 +62,8 @@ documentation:
 <li> \refitem cmddeprecated \deprecated
 <li> \refitem cmddontinclude \dontinclude
 <li> \refitem cmde \e
+<li> \refitem cmdelse \else
+<li> \refitem cmdelseif \elseif
 <li> \refitem cmdem \em
 <li> \refitem cmdendcode \endcode
 <li> \refitem cmdendhtmlonly \endhtmlonly
@@ -81,6 +83,7 @@ documentation:
 <li> \refitem cmdhtmlinclude \htmlinclude
 <li> \refitem cmdhtmlonly \htmlonly
 <li> \refitem cmdif \if
+<li> \refitem cmdifnot \\ifnot
 <li> \refitem cmdimage \image
 <li> \refitem cmdinclude \include
 <li> \refitem cmdingroup \ingroup
@@ -663,15 +666,40 @@ Public/Protected/Private/... section.
   a deprecated entity. Can be used to describe alternatives, 
   expected life span, etc.
 
+<hr>
+\subsection cmdelse \else 
+
+  \addindex \else
+  Starts a conditional section if the previous conditional section 
+  was not enabled. The previous section should have been started with 
+  a \c \\if, \c \\ifnot, or \c \\elseif command.
+
+  \sa \ref cmdif "\\if", \ref cmdifnot "\\ifnot", \ref cmdelseif "\\elseif",
+      \ref cmdendif "\\endif."
+
+<hr>
+\subsection cmdelseif \elseif <section-label>
+
+  \addindex \elseif
+  Starts a conditional documentation section if the previous section 
+  was not enabled. A conditional section is
+  disabled by default. To enable it you must put the
+  section-label after the \ref cfg_enabled_sections "ENABLED_SECTIONS" 
+  tag in the configuration
+  file. Conditional blocks can be nested. A nested section is
+  only enabled if all enclosing sections are enabled as well.
+
+  \sa sections \ref cmdendif "\\endif", \ref cmdifnot "\\ifnot", 
+              \ref cmdelse "\\else", and \ref cmdelseif "\\elseif".
 
 <hr>
 \subsection cmdendif \endif 
 
-  \addindex \endif
-  Ends a conditional section that was started with \c \if.
-  For each \c \if one and only one matching \c \endif must follow.
+  \addindex \\endif
+  Ends a conditional section that was started with \c \\if or \c \\ifnot
+  For each \c \\if or \c \\ifnot one and only one matching \c \\endif must follow.
 
-  \sa \ref cmdif "\\if"
+  \sa \ref cmdif "\\if", and \ref cmdifnot "\\ifnot".
 
 <hr>
 \subsection cmdexception \exception <exception-object> { exception description }
@@ -694,9 +722,9 @@ Public/Protected/Private/... section.
 <hr>
 \subsection cmdif \if <section-label>
 
-  \addindex \if
+  \addindex \\if
   Starts a conditional documentation section. The section ends 
-  with a matching \c \endif command. A conditional section is
+  with a matching \c \\endif command. A conditional section is
   disabled by default. To enable it you must put the
   section-label after the \ref cfg_enabled_sections "ENABLED_SECTIONS" 
   tag in the configuration
@@ -720,7 +748,22 @@ Public/Protected/Private/... section.
    */
 \endverbatim  
 
-  \sa section \ref cmdendif "\\endif".
+  \sa sections \ref cmdendif "\\endif", \ref cmdifnot "\\ifnot", 
+              \ref cmdelse "\\else", and \ref cmdelseif "\\elseif".
+
+<hr>
+\subsection cmdifnot \ifnot <section-label>
+
+  \addindex \ifnot
+  Starts a conditional documentation section. The section ends 
+  with a matching \c \\endif command. This conditional section is
+  enabled by default. To disable it you must put the
+  section-label after the \ref cfg_enabled_sections "ENABLED_SECTIONS" 
+  tag in the configuration
+  file. 
+
+  \sa sections \ref cmdendif "\\endif", \ref cmdif "\\if", 
+              \ref cmdelse "\\else", and \ref cmdelseif "\\elseif".
 
 <hr>
 \subsection cmdinvariant \invariant { description of invariant }
diff --git a/packages/rpm/doxygen.spec b/packages/rpm/doxygen.spec
index e84f38d..c802b39 100644
--- a/packages/rpm/doxygen.spec
+++ b/packages/rpm/doxygen.spec
@@ -1,5 +1,5 @@
 Name: doxygen
-Version: 1.2.9
+Version: 1.2.9.1
 Summary: documentation system for C, C++ and IDL
 Release: 4
 Source: doxygen-%{version}.src.tar.gz
@@ -41,7 +41,7 @@ Autor:
 %setup -n doxygen-%{version}
 
 %build
-CFLAGS="$RPM_OPT_FLAGS" ./configure --with-doxywizard --with-xmlgen
+CFLAGS="$RPM_OPT_FLAGS" ./configure --with-doxywizard 
 # the next path is Suse specific
 QTDIR=/usr/lib/qt2
 PATH=${QTDIR}/bin:$PATH
diff --git a/src/classdef.cpp b/src/classdef.cpp
index 0a600a2..c0feb10 100644
--- a/src/classdef.cpp
+++ b/src/classdef.cpp
@@ -88,15 +88,15 @@ ClassDef::ClassDef(
   m_memberGroupList->setAutoDelete(TRUE);
   m_memberGroupDict = new MemberGroupDict(17);
   m_innerClasses = new ClassSDict(17);
-  int i=name().findRev("::");
-  if (i==-1)
-  {
-    m_scopelessName=name();
-  }
-  else
-  {
-    m_scopelessName=name().right(name().length()-i-2);
-  }
+  //int i=name().findRev("::"); // TODO: broken if A<N::C> is the class name
+  //if (i==-1)
+  //{
+  //  m_scopelessName=name();
+  //}
+  //else
+  //{
+  //  m_scopelessName=name().right(name().length()-i-2);
+  //}
   m_subGrouping=TRUE;
   m_isTemplBaseClass=-1;
   m_templateInstances = 0;
@@ -415,7 +415,7 @@ void ClassDef::insertMember(MemberDef *md)
                   enumValMembers.append(md);
                 break;
               case MemberDef::Function:
-                if (md->name()==m_scopelessName ||         // constructor
+                if (md->name()==localName() ||         // constructor
                     (md->name().find('~')!=-1 &&  // hack to detect destructor
                      md->name().find("operator")==-1
                     )
@@ -2232,6 +2232,7 @@ void ClassDef::getTemplateParameterLists(QList<ArgumentList> &lists) const
 QCString ClassDef::qualifiedNameWithTemplateParameters(
     QList<ArgumentList> *actualParams) const
 {
+  //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data());
   QCString scName;
   Definition *d=getOuterScope();
   if (d)
@@ -2268,7 +2269,7 @@ QCString ClassDef::qualifiedNameWithTemplateParameters(
       }
     }
   }
-  //printf("scope=%s qualifiedName=%s\n",name().data(),scName.data());
+  //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data());
   return scName;
 }
 
diff --git a/src/classdef.h b/src/classdef.h
index 924c56f..939cd90 100644
--- a/src/classdef.h
+++ b/src/classdef.h
@@ -325,7 +325,7 @@ class ClassDef : public Definition
     /*! Bare name of the class without any scoping prefixes 
      *  (like for nested classes and classes inside namespaces)
      */ 
-    QCString m_scopelessName;              
+    //QCString m_scopelessName;              
 
     /*! List of base class (or super-classes) from which this class derives
      *  directly. 
diff --git a/src/classlist.cpp b/src/classlist.cpp
index ca05275..7c69d73 100644
--- a/src/classlist.cpp
+++ b/src/classlist.cpp
@@ -35,8 +35,8 @@ int ClassList::compareItems(GCI item1, GCI item2)
 {
   ClassDef *c1=(ClassDef *)item1;
   ClassDef *c2=(ClassDef *)item2;
-  return stricmp(c1->name().data()+getPrefixIndex(c1->name()),
-                 c2->name().data()+getPrefixIndex(c2->name())
+  return stricmp(c1->name().data()+getPrefixIndex(c1->localName()),
+                 c2->name().data()+getPrefixIndex(c2->localName())
                 );
 }
 
@@ -44,8 +44,8 @@ int ClassSDict::compareItems(GCI item1, GCI item2)
 {
   ClassDef *c1=(ClassDef *)item1;
   ClassDef *c2=(ClassDef *)item2;
-  return stricmp(c1->name().data()+getPrefixIndex(c1->name()),
-                 c2->name().data()+getPrefixIndex(c2->name())
+  return stricmp(c1->name().data()+getPrefixIndex(c1->localName()),
+                 c2->name().data()+getPrefixIndex(c2->localName())
                 );
 }
 
diff --git a/src/declinfo.h b/src/declinfo.h
index b337aae..0b183d7 100644
--- a/src/declinfo.h
+++ b/src/declinfo.h
@@ -23,7 +23,6 @@
 
 extern void parseFuncDecl(const QCString &decl,
                           QCString &clName,
-                          QCString &classTempList,
                           QCString &type,
                           QCString &name,
                           QCString &args,
diff --git a/src/declinfo.l b/src/declinfo.l
index 5548b56..d06f824 100644
--- a/src/declinfo.l
+++ b/src/declinfo.l
@@ -206,7 +206,7 @@ ID	([a-z_A-Z][a-z_A-Z0-9]*)|(@[0-9]+)
 /*@ ----------------------------------------------------------------------------
  */
 
-void parseFuncDecl(const QCString &decl,QCString &cl,QCString &ctl,QCString &t,
+void parseFuncDecl(const QCString &decl,QCString &cl,QCString &t,
                    QCString &n,QCString &a,QCString &ftl,QCString &exc)
 {
   inputString   = decl;
@@ -256,9 +256,11 @@ void parseFuncDecl(const QCString &decl,QCString &cl,QCString &ctl,QCString &t,
 	cl+=c;
     }
   }
-#endif
   cl=stripTemplateSpecifiersFromScope(removeRedundantWhiteSpace(scope),FALSE); 
   ctl.resize(0);
+#endif
+
+  cl=scope;
   n=removeRedundantWhiteSpace(name);
   int il,ir;
   if ((il=n.find('<'))!=-1 && (ir=n.findRev('>'))!=-1)
diff --git a/src/definition.cpp b/src/definition.cpp
index e4ea9c3..fc764f7 100644
--- a/src/definition.cpp
+++ b/src/definition.cpp
@@ -34,12 +34,7 @@ Definition::Definition(const char *df,int dl,
   m_defFileName = df;
   m_defLine = dl;
   m_name=name; 
-  m_localName=name;
-  int i=m_localName.findRev("::");
-  if (i!=-1)
-  {
-    m_localName=m_localName.right(m_localName.length()-i-2);
-  }
+  m_localName=stripScope(name);
   m_brief=b; 
   m_doc=d; 
   m_sectionDict=0, 
@@ -451,7 +446,7 @@ void Definition::addInnerCompound(Definition *)
 
 QCString Definition::qualifiedName() const
 {
-  //printf("start Definition::qualifiedName()\n");
+  //printf("start Definition::qualifiedName() localName=%s\n",m_localName.data());
   if (m_outerScope==0) 
   {
     if (m_localName=="<globalScope>") return "";
diff --git a/src/doc.l b/src/doc.l
index 2d7ddbe..974f54b 100644
--- a/src/doc.l
+++ b/src/doc.l
@@ -892,7 +892,6 @@ OPMASK    ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG})
 %x      DocEmphasis
 %x      DocBold
 %x      DocCode
-%x	DocIf
 %x      DocCodeBlock
 %x      DocInternal
 %x      DocLink
@@ -1506,9 +1505,7 @@ OPMASK    ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG})
 					    inParamBlock=TRUE;
 					    currentListIndent.push("D");
 					    outDoc->startParamList();
-					    outDoc->startBold();
 					    scanString(theTranslator->trParameters()+": ");
-					    outDoc->endBold();
   					    outDoc->endDescTitle();
   					    outDoc->writeDescItem();
 					    outDoc->startDescTable();
@@ -1532,9 +1529,7 @@ OPMASK    ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG})
 					    inRetValBlock=TRUE;
 					    currentListIndent.push("D");
 					    outDoc->startParamList();
-					    outDoc->startBold();
 					    scanString(theTranslator->trReturnValues()+": ");
-					    outDoc->endBold();
   					    outDoc->endDescTitle();
   					    outDoc->writeDescItem();
 					    outDoc->startDescTable();
@@ -1558,9 +1553,7 @@ OPMASK    ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG})
 					    inExceptionBlock=TRUE;
 					    currentListIndent.push("D");
 					    outDoc->startParamList();
-					    outDoc->startBold();
 					    scanString(theTranslator->trExceptions()+": ");
-					    outDoc->endBold();
   					    outDoc->endDescTitle();
 					    outDoc->writeDescItem();
 					    outDoc->startDescTable();
@@ -1574,18 +1567,14 @@ OPMASK    ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG})
 <DocScan>"\\capt".*
 <DocParam>({DOCPARAM}{BN}*","{BN}*)*{DOCPARAM}{BSEP}* {
 					  outDoc->startDescTableTitle();
-					  outDoc->startEmphasis();
   					  outDoc->docify(substitute(yytext,"\"","").stripWhiteSpace()); 
-					  outDoc->endEmphasis();
 					  outDoc->endDescTableTitle();
 					  outDoc->startDescTableData();
 					  BEGIN(DocScan);
   					}
 <DocException>{SCOPENAME}		{
 					  outDoc->startDescTableTitle();
-					  outDoc->startEmphasis();
   					  outDoc->docify(yytext); 
-					  outDoc->endEmphasis();
 					  outDoc->endDescTableTitle();
 					  outDoc->startDescTableData();
 					  BEGIN(DocScan);
@@ -1646,6 +1635,7 @@ OPMASK    ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG})
 <DocScan>{CMD}"refitem"/{BN}		{
   					  BEGIN(DocRefItem);
   					}
+  /*
 <DocScan>{CMD}"if"/{BN}			{
   					  outDoc->pushGeneratorState();
 					  depthIf++;
@@ -1671,6 +1661,7 @@ OPMASK    ({B}*{OPNORM}({OPARG}?))|({OPCAST}{OPARG})
 					  }
 					  BEGIN(DocScan);
   					}
+  */
 <DocRefName>{SCOPENAME}|{FILE}		{
   					  QCString ref=yytext;
 					  SectionInfo *sec;
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index a0dd54c..70f7d98 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -353,6 +353,7 @@ static void addRefItem(int todoId,int testId,int bugId,const char *prefix,
     doc += "</dt>\n<dd>";
     doc += item->text;
     doc += "</dd></dl>\n";
+    //printf("Test page: %s\n",doc.data());
     addRelatedPage("test",theTranslator->trTestList(),doc,0,"generated",1,0,0,0);
 
     item->written=TRUE;
@@ -675,34 +676,29 @@ static Definition *findScope(Entry *root,int level=0)
 static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n)
 {
   //printf("findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data());
-  QCString name(n);
-  if (startScope==0) startScope=Doxygen::globalScope;
-  int i = name.find("::");
-  if (i==-1) 
-  {
-    return startScope;
-  }
-
-  QCString scope=stripTemplateSpecifiersFromScope(name,FALSE);
-  //printf("name=%s -> scope=%s\n",name.data(),scope.data());
-  while ((i = scope.find("::"))!=-1)
-  {
-    //int ti = name.find('<');
-    //if (ti!=-1 && ti<i) i=ti; // strip template specifiers
-    QCString nestedNameSpecifier = scope.left(i);
-    //Definition *oldScope = startScope;
-    startScope = startScope->findInnerCompound(nestedNameSpecifier);
-    //printf("Trying %s result=%p\n",nestedNameSpecifier.data(),startScope);
-    if (startScope==0) 
+  Definition *resultScope=startScope;
+  if (resultScope==0) resultScope=Doxygen::globalScope;
+  QCString scope=stripTemplateSpecifiersFromScope(n,FALSE);
+  int l1=0,i1;
+  i1=getScopeFragment(scope,0,&l1);
+  if (i1==-1) return resultScope;
+  int p=i1+l1,l2=0,i2;
+  while ((i2=getScopeFragment(scope,p,&l2))!=-1)
+  {
+    QCString nestedNameSpecifier = scope.mid(i1,l1);
+    //Definition *oldScope = resultScope;
+    resultScope = resultScope->findInnerCompound(nestedNameSpecifier);
+    if (resultScope==0) 
     {
       //printf("name %s not found in scope %s\n",nestedNameSpecifier.data(),oldScope->name().data());
       return 0;
     }
-    scope = scope.right(scope.length()-i-2);
-    //printf("scope=%s\n",scope.data());
+    i1=i2;
+    l1=l2;
+    p=i2+l2;
   }
-  //printf("findScopeFromQualifiedName() result=%s\n",startScope ? startScope->name().data() : 0);
-  return startScope;
+  //printf("scope %s\n",resultScope->name().data());
+  return resultScope;
 }
 
 ArgumentList *getTemplateArgumentsFromName(
@@ -834,6 +830,15 @@ static void buildClassList(Entry *root)
         addClassToGroups(root,cd);
         cd->setRefItems(root->todoId,root->testId,root->bugId);
         if (!root->subGrouping) cd->setSubGrouping(FALSE);
+
+        if (cd->templateArguments()==0) 
+        {
+          // this happens if a template class declared with @class is found
+          // before the actual definition.
+          ArgumentList *tArgList = 
+            getTemplateArgumentsFromName(fullName,root->tArgLists);
+          cd->setTemplateArguments(tArgList);
+        }
       }
       else // new class
       {
@@ -1981,6 +1986,7 @@ static void buildMemberList(Entry *root)
 
         addMemberToGroups(root,md);
         root->section = Entry::EMPTY_SEC;
+        md->setRefItems(root->todoId,root->testId,root->bugId);
       }
       else if (root->parent && 
                !(root->parent->section & Entry::COMPOUND_MASK) &&
@@ -2015,10 +2021,12 @@ static void buildMemberList(Entry *root)
             QCString nsName,rnsName;
             if (nd)  nsName  = nd->name().copy();
             if (rnd) rnsName = rnd->name().copy();
+            //printf("matching arguments for %s\n",md->name().data());
             if ( 
                 matchArguments(md->argumentList(),root->argList,0,nsName)
                )
             {
+              //printf("match!\n");
               // see if we need to create a new member
               found=(nd && rnd && nsName==rnsName) ||   // members are in the same namespace
                     ((fd!=0 &&                          // no external reference and
@@ -3206,8 +3214,96 @@ static void computeMemberReferences()
 
 //----------------------------------------------------------------------
 
+static void addClassMemberTodoTestBufReferences(Definition *compound)
+{
+  MemberNameListIterator mnli(Doxygen::memberNameList);
+  MemberName *mn=0;
+  for (mnli.toFirst();(mn=mnli.current());++mnli)
+  {
+    MemberNameIterator mni(*mn);
+    MemberDef *md=0;
+    for (mni.toFirst();(md=mni.current());++mni)
+    {
+      Definition *d=md->getClassDef();
+      QCString scopeName;
+      if (d) scopeName=d->name();
+      if (d==0) d=md->getGroupDef();
+      if (d==0) d=md->getFileDef();
+      if (compound==d || (compound==0 && d!=0 && !md->visited))
+      {
+        QCString memLabel;
+        md->visited=TRUE;
+        if (Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) 
+        {
+          memLabel=theTranslator->trField(TRUE,TRUE);
+        }
+        else
+        {
+          memLabel=theTranslator->trMember(TRUE,TRUE);
+        }
+        addRefItem(md->todoId(),md->testId(),md->bugId(),memLabel,d->getOutputFileBase()+":"+md->anchor(),scopeName+"::"+md->name(),md->argsString());
+      }
+    }
+  }
+}
+
+static void addFileMemberTodoTestBufReferences(Definition *compound)
+{
+  MemberNameListIterator fnli(Doxygen::functionNameList);
+  MemberName *mn=0;
+  for (fnli.toFirst();(mn=fnli.current());++fnli)
+  {
+    MemberNameIterator mni(*mn);
+    MemberDef *md=0;
+    for (mni.toFirst();(md=mni.current());++mni)
+    {
+      Definition *d=md->getNamespaceDef();
+      QCString scopeName;
+      if (d) scopeName=d->name();
+      if (d==0) d=md->getGroupDef();
+      if (d==0) d=md->getFileDef();
+      if (compound==d || (compound==0 && d!=0 && !md->visited))
+      {
+        QCString memLabel;
+        md->visited=TRUE;
+        if (Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) 
+        {
+          memLabel=theTranslator->trGlobal(TRUE,TRUE);
+        }
+        else
+        {
+          memLabel=theTranslator->trMember(TRUE,TRUE);
+        }
+        addRefItem(md->todoId(),md->testId(),md->bugId(),memLabel,d->getOutputFileBase()+":"+md->anchor(),md->name(),md->argsString());
+      }
+    }
+  }
+}
+
 static void addTodoTestBugReferences()
 {
+  MemberNameListIterator mnli(Doxygen::memberNameList);
+  MemberName *mn=0;
+  for (mnli.toFirst();(mn=mnli.current());++mnli)
+  {
+    MemberNameIterator mni(*mn);
+    MemberDef *md=0;
+    for (mni.toFirst();(md=mni.current());++mni)
+    {
+      md->visited=FALSE;
+    }
+  }
+  MemberNameListIterator fnli(Doxygen::functionNameList);
+  for (fnli.toFirst();(mn=fnli.current());++fnli)
+  {
+    MemberNameIterator mni(*mn);
+    MemberDef *md=0;
+    for (mni.toFirst();(md=mni.current());++mni)
+    {
+      md->visited=FALSE;
+    }
+  }
+
   ClassSDict::Iterator cli(Doxygen::classSDict);
   ClassDef *cd=0;
   for (cli.toFirst();(cd=cli.current());++cli)
@@ -3216,6 +3312,7 @@ static void addTodoTestBugReferences()
                theTranslator->trClass(TRUE,TRUE),
                cd->getOutputFileBase(),cd->name()
               );
+    addClassMemberTodoTestBufReferences(cd);
   } 
   FileName *fn=Doxygen::inputNameList.first();
   while (fn)
@@ -3226,6 +3323,7 @@ static void addTodoTestBugReferences()
       addRefItem(fd->todoId(),fd->testId(),fd->bugId(),
                  theTranslator->trFile(TRUE,TRUE),
                  fd->getOutputFileBase(),fd->name());
+      addFileMemberTodoTestBufReferences(fd);
       fd=fn->next();
     }
     fn=Doxygen::inputNameList.next();
@@ -3236,6 +3334,7 @@ static void addTodoTestBugReferences()
     addRefItem(nd->todoId(),nd->testId(),nd->bugId(),
                theTranslator->trNamespace(TRUE,TRUE),
                nd->getOutputFileBase(),nd->name());
+    addFileMemberTodoTestBufReferences(nd);
     nd=Doxygen::namespaceList.next();
   }
   GroupDef *gd=Doxygen::groupList.first();
@@ -3244,6 +3343,7 @@ static void addTodoTestBugReferences()
     addRefItem(gd->todoId(),gd->testId(),gd->bugId(),
                theTranslator->trGroup(TRUE,TRUE),
                gd->getOutputFileBase(),gd->groupTitle());
+    addFileMemberTodoTestBufReferences(gd);
     gd=Doxygen::groupList.next();
   }
   PageSDictIterator pdi(*Doxygen::pageSDict);
@@ -3254,62 +3354,8 @@ static void addTodoTestBugReferences()
                theTranslator->trPage(TRUE,TRUE),
                pi->name,pi->title);
   }
-  MemberNameListIterator mnli(Doxygen::memberNameList);
-  MemberName *mn=0;
-  for (mnli.toFirst();(mn=mnli.current());++mnli)
-  {
-    MemberNameIterator mni(*mn);
-    MemberDef *md=0;
-    for (mni.toFirst();(md=mni.current());++mni)
-    {
-      Definition *d=md->getClassDef();
-      QCString scopeName;
-      if (d) scopeName=d->name();
-      if (d==0) d=md->getGroupDef();
-      if (d==0) d=md->getFileDef();
-      // TODO: i18n this
-      QCString memLabel;
-      if (Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) 
-      {
-        memLabel=theTranslator->trField(TRUE,TRUE);
-      }
-      else
-      {
-        memLabel=theTranslator->trMember(TRUE,TRUE);
-      }
-      if (d)
-      {
-        addRefItem(md->todoId(),md->testId(),md->bugId(),memLabel,d->getOutputFileBase()+":"+md->anchor(),scopeName+"::"+md->name(),md->argsString());
-      }
-    }
-  }
-  MemberNameListIterator fnli(Doxygen::functionNameList);
-  for (fnli.toFirst();(mn=fnli.current());++fnli)
-  {
-    MemberNameIterator mni(*mn);
-    MemberDef *md=0;
-    for (mni.toFirst();(md=mni.current());++mni)
-    {
-      Definition *d=md->getNamespaceDef();
-      QCString scopeName;
-      if (d) scopeName=d->name();
-      if (d==0) d=md->getGroupDef();
-      if (d==0) d=md->getFileDef();
-      QCString memLabel;
-      if (Config_getBool("OPTIMIZE_OUTPUT_FOR_C")) 
-      {
-        memLabel=theTranslator->trGlobal(TRUE,TRUE);
-      }
-      else
-      {
-        memLabel=theTranslator->trMember(TRUE,TRUE);
-      }
-      if (d)
-      {
-        addRefItem(md->todoId(),md->testId(),md->bugId(),memLabel,d->getOutputFileBase()+":"+md->anchor(),md->name(),md->argsString());
-      }  
-    }
-  }
+  addClassMemberTodoTestBufReferences(0);
+  addFileMemberTodoTestBufReferences(0);
 }
 
 
@@ -3458,29 +3504,10 @@ static void addMemberDocs(Entry *root,
 // find a class definition given the scope name and (optionally) a 
 // template list specifier
 
-static ClassDef *findSimpleClassDefinition(const char *scopeName,const char *classTempList)
-{
-  ClassDef *tcd=0;
-  if (classTempList) // try to find the correct specialization
-  {
-    tcd=getClass(
-          insertTemplateSpecifierInScope(
-            scopeName,
-            classTempList
-          )
-        ); // try specialization
-  }
-  if (tcd==0)
-  {
-    tcd=getClass(scopeName); // try general class
-  }
-  return tcd;
-}
-
 static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd,
-                         const char *scopeName,const char *classTempList)
+                         const char *scopeName)
 {
-  ClassDef *tcd = findSimpleClassDefinition(scopeName,classTempList);
+  ClassDef *tcd = getClass(scopeName);
   if (tcd==0) // try using declaration
   {
     ClassList *cl = 0;
@@ -3507,7 +3534,7 @@ static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd,
           if (rightScopeMatch(cd->name(),scope))
           {
             //printf("Trying to find `%s'\n",(cd->name()+scName.right(scName.length()-scopeOffset)).data());
-            tcd = findSimpleClassDefinition(cd->name()+scName.right(scName.length()-scopeOffset),classTempList); 
+            tcd = getClass(cd->name()+scName.right(scName.length()-scopeOffset)); 
           }
           scopeOffset=scName.findRev("::",scopeOffset-1);
         } while (scopeOffset>=0 && tcd==0);
@@ -3532,7 +3559,7 @@ static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd,
       for (;(nd=nli.current()) && tcd==0;++nli)
       {
         //printf("Trying with scope=%s\n",nd->name().data());
-        tcd = findSimpleClassDefinition(nd->name()+"::"+scopeName,classTempList); 
+        tcd = getClass(nd->name()+"::"+scopeName); 
       }
     }
   }
@@ -3708,34 +3735,6 @@ static void substituteTemplatesInArgList(
 }
 
 
-static QCString mergeScopes(const QCString &leftScope,const QCString &rightScope)
-{
-  // case leftScope=="A" rightScope=="A::B" => result = "A::B"
-  if (leftScopeMatch(rightScope,leftScope)) return rightScope;
-  QCString result;
-  int i=0,p=leftScope.length();
-
-  // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
-  // case leftScope=="A::B" rightScope=="B" => result = "A::B"
-  bool found=FALSE;
-  while ((i=leftScope.findRev("::",p))!=-1)
-  {
-    if (leftScopeMatch(rightScope,leftScope.right(leftScope.length()-i-2)))
-    {
-      result = leftScope.left(i+2)+rightScope;
-      found=TRUE;
-    }
-    p=i-1;
-  }
-  if (found) return result;
-
-  // case leftScope=="A" rightScope=="B" => result = "A::B"
-  result=leftScope.copy();
-  if (!result.isEmpty() && !rightScope.isEmpty()) result+="::";
-  result+=rightScope;
-  return result;
-}
-
 
 /*! This function tries to find a member (in a documented class/file/namespace) 
  * that corresponds to the function/variable declaration given in \a funcDecl.
@@ -3774,7 +3773,7 @@ static void findMember(Entry *root,
   QCString scopeName;
   QCString className;
   QCString namespaceName;
-  QCString classTempList;
+  //QCString classTempList;
   QCString funcType;
   QCString funcName;
   QCString funcArgs;
@@ -3816,7 +3815,19 @@ static void findMember(Entry *root,
       done=FALSE;
     }
   } while (!done);
-  
+
+  if (isFriend)
+  {
+    if (funcDecl.left(6)=="class ")
+    {
+      funcDecl=funcDecl.right(funcDecl.length()-6);
+    }
+    else if (funcDecl.left(7)=="struct ")
+    {
+      funcDecl=funcDecl.right(funcDecl.length()-7);
+    }
+  }
+
   // delete any ; from the function declaration
   int sep;
   while ((sep=funcDecl.find(';'))!=-1)
@@ -3837,12 +3848,12 @@ static void findMember(Entry *root,
             );
   
   // extract information from the declarations
-  parseFuncDecl(funcDecl,scopeName,classTempList,funcType,funcName,
+  parseFuncDecl(funcDecl,scopeName,funcType,funcName,
                 funcArgs,funcTempList,exceptions
                );
   //printf("scopeName=`%s' funcType=`%s' funcName=`%s'\n",
   //    scopeName.data(),funcType.data(),funcName.data());
-  
+
   // the class name can also be a namespace name, we decide this later.
   // if a related class name is specified and the class name could
   // not be derived from the function declaration, then use the
@@ -3852,11 +3863,10 @@ static void findMember(Entry *root,
   if (!related.isEmpty() && !isRelated) 
   {                             // related member, prefix user specified scope
     isRelated=TRUE;
-    //scopeName=resolveDefines(related);
-    if (!scopeName.isEmpty() && scopeName!=related)
-      scopeName+="::"+related;
+    if (getClass(related)==0 && !scopeName.isEmpty())
+      scopeName= mergeScopes(scopeName,related);
     else 
-      scopeName=related.copy();
+      scopeName = related.copy();
   }
 
   if (related.isEmpty() && root->parent && 
@@ -3864,8 +3874,9 @@ static void findMember(Entry *root,
       !root->parent->name.isEmpty())
   {
     scopeName = mergeScopes(root->parent->name,scopeName);
-    scopeName = stripTemplateSpecifiersFromScope(scopeName);
   }
+  scopeName=stripTemplateSpecifiersFromScope(
+      removeRedundantWhiteSpace(scopeName),FALSE); 
   
   // split scope into a namespace and a class part
   extractNamespaceName(scopeName,className,namespaceName);
@@ -3966,7 +3977,6 @@ static void findMember(Entry *root,
            "findMember() Parse results:\n"
            "  namespaceName=`%s'\n"
            "  className=`%s`\n"
-           "  classTempList=`%s'\n"
            "  funcType=`%s'\n"
            "  funcName=`%s'\n"
            "  funcArgs=`%s'\n"
@@ -3977,7 +3987,7 @@ static void findMember(Entry *root,
            "  isRelated=%d\n"
            "  isFriend=%d\n"
            "  isFunc=%d\n\n",
-           namespaceName.data(),className.data(),classTempList.data(),
+           namespaceName.data(),className.data(),
            funcType.data(),funcName.data(),funcArgs.data(),funcTempList.data(),
            funcDecl.data(),related.data(),exceptions.data(),isRelated,isFriend,
            isFunc
@@ -4019,7 +4029,7 @@ static void findMember(Entry *root,
           NamespaceDef *nd=0;
           if (!namespaceName.isEmpty()) nd=getResolvedNamespace(namespaceName);
 
-          ClassDef *tcd=findClassDefinition(fd,nd,scopeName,classTempList);
+          ClassDef *tcd=findClassDefinition(fd,nd,scopeName);
 
           if (cd && tcd==cd) // member's classes match
           {
@@ -4241,6 +4251,7 @@ static void findMember(Entry *root,
     {
       if (className.isEmpty()) className=related.copy();
       ClassDef *cd;
+      //printf("scopeName=`%s'\n",scopeName.data());
       if ((cd=getClass(scopeName)))
       {
         bool newMember=TRUE; // assume we have a new member
diff --git a/src/htmlgen.h b/src/htmlgen.h
index a471433..9bc9ffb 100644
--- a/src/htmlgen.h
+++ b/src/htmlgen.h
@@ -209,9 +209,9 @@ class HtmlGenerator : public OutputGenerator
     void endDescTable()
     { t << "</table>" << endl; }
     void startDescTableTitle()
-    { t << "<tr><td valign=top>"; }
+    { t << "<tr><td valign=top><em>"; }
     void endDescTableTitle()
-    { t << endl << "&nbsp;</td>"; }
+    { t << endl << "</em>&nbsp;</td>"; }
     void startDescTableData()
     { t << "<td>" << endl; }
     void endDescTableData()
diff --git a/src/index.cpp b/src/index.cpp
index 2f149dd..5e3e53f 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -1194,7 +1194,7 @@ void writeAlphabeticalClassList(OutputList &ol)
   {
     if (cd->isLinkableInProject() && cd->templateMaster()==0)
     {
-      int index = getPrefixIndex(cd->name());
+      int index = getPrefixIndex(cd->localName());
       if (toupper(cd->name().at(index))!=startLetter) // new begin letter => new header
       {
         startLetter=toupper(cd->name().at(index));
@@ -1227,7 +1227,7 @@ void writeAlphabeticalClassList(OutputList &ol)
   {
     if (cd->isLinkableInProject() && cd->templateMaster()==0)
     {
-      int index = getPrefixIndex(cd->name());
+      int index = getPrefixIndex(cd->localName());
       if (toupper(cd->name().at(index))!=startLetter)
       {
         // insert a new header using a dummy class pointer.
@@ -1275,7 +1275,7 @@ void writeAlphabeticalClassList(OutputList &ol)
         if (cd)
         {
           //printf("head ClassDef=%p %s\n",cd,cd ? cd->name().data() : "<none>");
-          int index = getPrefixIndex(cd->name());
+          int index = getPrefixIndex(cd->localName());
           startLetter=toupper(cd->name().at(index));
           char s[2]; s[0]=startLetter; s[1]=0;
           ol.writeIndexHeading(s);
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index fb7777e..7ffa258 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -540,7 +540,7 @@ void LatexGenerator::startIndexSection(IndexSections is)
         bool found=FALSE;
         for (cli.toFirst();(cd=cli.current()) && !found;++cli)
         {
-          if (cd->isLinkableInProject())
+          if (cd->isLinkableInProject() && cd->templateMaster()==0)
           {
             if (compactLatex) t << "\\section"; else t << "\\chapter";
             t << "{"; //Compound Documentation}\n";
@@ -711,7 +711,7 @@ void LatexGenerator::endIndexSection(IndexSections is)
         bool found=FALSE;
         for (cli.toFirst();(cd=cli.current()) && !found;++cli)
         {
-          if (cd->isLinkableInProject())
+          if (cd->isLinkableInProject() && cd->templateMaster()==0)
           {
             t << "}\n\\input{" << cd->getOutputFileBase() << "}\n";
             found=TRUE;
@@ -719,7 +719,7 @@ void LatexGenerator::endIndexSection(IndexSections is)
         }
         for (;(cd=cli.current());++cli)
         {
-          if (cd->isLinkableInProject())
+          if (cd->isLinkableInProject() && cd->templateMaster()==0)
           {
             if (compactLatex) t << "\\input"; else t << "\\include";
             t << "{" << cd->getOutputFileBase() << "}\n";
diff --git a/src/latexgen.h b/src/latexgen.h
index 2e2c8e4..f2fca5a 100644
--- a/src/latexgen.h
+++ b/src/latexgen.h
@@ -217,9 +217,9 @@ class LatexGenerator : public OutputGenerator
     void endDescTable()
     { t << "\\end{description}" << endl; }
     void startDescTableTitle()
-    { t << "\\item[" << endl; }
+    { t << "\\item[{\\em " << endl; }
     void endDescTableTitle()
-    { t << "]"; }
+    { t << "}]"; }
     void startDescTableData() {}
     void endDescTableData() {}
     void lastIndexPage() {}
diff --git a/src/mangen.h b/src/mangen.h
index 4d0f774..92fcc3a 100644
--- a/src/mangen.h
+++ b/src/mangen.h
@@ -201,8 +201,8 @@ class ManGenerator : public OutputGenerator
     
     void startDescTable() {}
     void endDescTable() {}
-    void startDescTableTitle() { writeListItem(); startBold(); }
-    void endDescTableTitle() { endBold(); }
+    void startDescTableTitle() { writeListItem(); startBold(); startEmphasis(); }
+    void endDescTableTitle() { endEmphasis(); endBold(); }
     void startDescTableData() { t << endl; firstCol=TRUE; }
     void endDescTableData() {}
 
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 3b22fd7..9c04b94 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -553,7 +553,8 @@ bool MemberDef::isBriefSectionVisible() const
     // only include members that are non-private unless EXTRACT_PRIVATE is
     // set to YES or the member is part of a group
     bool visibleIfPrivate = (protection()!=Private || 
-                             Config_getBool("EXTRACT_PRIVATE")
+                             Config_getBool("EXTRACT_PRIVATE") ||
+                             mtype==Friend
                             );
     
     bool visible = visibleIfStatic && visibleIfDocumented && 
@@ -666,7 +667,7 @@ void MemberDef::writeDeclaration(OutputList &ol,
   if (tArgList)
   {
     writeTemplatePrefix(ol,tArgList);
-    ol.lineBreak();
+    //ol.lineBreak();
   }
 
   QCString ltype(type);
@@ -879,7 +880,8 @@ bool MemberDef::isDetailedSectionLinkable() const
   // only include members that are non-private unless EXTRACT_PRIVATE is
   // set to YES or the member is part of a group
   bool privateFilter = (protection()!=Private || 
-                           Config_getBool("EXTRACT_PRIVATE")
+                           Config_getBool("EXTRACT_PRIVATE") ||
+                           mtype==Friend
                           );
 
   // member is part of an anonymous scope that is the type of
@@ -1198,9 +1200,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
         if (a->hasDocumentation())
         {
           ol.startDescTableTitle();
-          ol.startEmphasis();
           ol.docify(a->name);
-          ol.endEmphasis();
           ol.endDescTableTitle();
           ol.startDescTableData();
           parseDoc(ol,m_defFileName,m_defLine,scopeName,name(),a->docs+"\n");
@@ -1475,7 +1475,8 @@ bool MemberDef::isLinkableInProject() const
   return !name().isEmpty() && name().at(0)!='@' &&
          ((hasDocumentation() && !isReference())  
          ) && 
-         (prot!=Private || Config_getBool("EXTRACT_PRIVATE")) && // not a private class member
+         (prot!=Private || Config_getBool("EXTRACT_PRIVATE") || 
+          mtype==Friend) && // not a hidden member due to protection
          (classDef!=0 || Config_getBool("EXTRACT_STATIC") || 
           !isStatic()); // not a static file/namespace member
 }
diff --git a/src/memberdef.h b/src/memberdef.h
index 6fa3b37..9f28afc 100644
--- a/src/memberdef.h
+++ b/src/memberdef.h
@@ -231,6 +231,7 @@ class MemberDef : public Definition
                ArgumentList *actualArgs);
     void setTemplateMaster(MemberDef *mt) { m_templateMaster=mt; }
         
+    bool visited;
     
   private:
     ClassDef   *classDef;     // member of or related to 
diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp
index 4605ae6..e79646b 100644
--- a/src/rtfgen.cpp
+++ b/src/rtfgen.cpp
@@ -1005,7 +1005,7 @@ void RTFGenerator::startIndexSection(IndexSections is)
         bool found=FALSE;
         for (cli.toFirst();(cd=cli.current()) && !found;++cli)
         {
-          if (cd->isLinkableInProject())
+          if (cd->isLinkableInProject() && cd->templateMaster()==0)
           {
             beginRTFChapter();
             found=TRUE;
@@ -1238,7 +1238,7 @@ void RTFGenerator::endIndexSection(IndexSections is)
         t << "{\\tc \\v " << theTranslator->trClassDocumentation() << "}"<< endl;
         for (cli.toFirst();(cd=cli.current()) && !found;++cli)
         {
-          if (cd->isLinkableInProject())
+          if (cd->isLinkableInProject() && cd->templateMaster()==0)
           {
             t << "\\par " << Rtf_Style_Reset << endl;
             t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
@@ -1249,7 +1249,7 @@ void RTFGenerator::endIndexSection(IndexSections is)
         }
         for (;(cd=cli.current());++cli)
         {
-          if (cd->isLinkableInProject())
+          if (cd->isLinkableInProject() && cd->templateMaster()==0)
           {
             t << "\\par " << Rtf_Style_Reset << endl;
             beginRTFSection();
@@ -2230,11 +2230,13 @@ void RTFGenerator::startDescTableTitle()
   //t << Rtf_BList_DepthStyle() << endl;
   DBG_RTF(t << "{\\comment (startDescTableTitle) }"    << endl)
   startBold();
+  startEmphasis();
 }
 
 void RTFGenerator::endDescTableTitle()
 {
   DBG_RTF(t << "{\\comment (endDescTableTitle) }"    << endl)
+  endEmphasis();
   endBold();
   t << "  ";
 }
diff --git a/src/scanner.l b/src/scanner.l
index 239af2e..9f60f21 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -76,6 +76,7 @@ static int              lastAnchorContext;
 static int              lastInitializerContext;
 static int              lastClassTemplSpecContext;
 static int              lastSkipHtmlCommentContext;
+static int              lastIfContext;
 static int              nextDefContext;
 static int              overloadContext;
 static Protection	protection;
@@ -84,7 +85,6 @@ static int		sharpCount   = 0 ;
 static int		roundCount   = 0 ;
 static int		curlyCount   = 0 ;
 static int		squareCount  = 0 ;
-static int              ifCount      = 0 ;
 static int              padCount     = 0 ;
 static int              todoStartContext = 0;
 static QCString         todoString;
@@ -148,6 +148,8 @@ static Grouping  lastDefGroup( "", Grouping::GROUPING_LOWEST );
 static bool             insideFormula;
 static bool  	        insideTryBlock=FALSE;
 
+static int              depthIf;
+
 //-----------------------------------------------------------------------------
 
 static void initParser()
@@ -161,7 +163,6 @@ static void initParser()
   sharpCount = 0;
   roundCount = 0;
   curlyCount = 0;
-  ifCount = 0;
   memberGroupId = NOGROUP;
   mtype = Method;
   gstat = FALSE;
@@ -171,6 +172,8 @@ static void initParser()
   autoGroupStack.clear();
   insideTryBlock = FALSE;
   insideIDL = FALSE;
+  autoGroupStack.setAutoDelete(TRUE);
+  lastDefGroup.groupname.resize(0);
 }
 
 static void initEntry()
@@ -481,6 +484,9 @@ TITLE     [tT][iI][tT][lL][eE]
 %x      SkipSharp
 %x	SkipRound
 %x	SkipSquare
+%x	SkipSection
+%x	IfGuard
+%x	IfNotGuard
 %x	TypedefName
 %x	TryFunctionBlock
 %x	TryFunctionBlockEnd
@@ -1297,7 +1303,7 @@ TITLE     [tT][iI][tT][lL][eE]
 					    BEGIN(AfterDoc);
 					  }
   					}
-<FindMembers,FindFields>"//"([!/]?){B}*{CMD}"{"|"/*"([!*]?){B}*{CMD}"{"	{
+<FindMembers,FindFields>("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{")	{
   					  startGroup();
 					  tmpDocType=-1;
 					  if (current_root->section & Entry::SCOPE_MASK)
@@ -2624,7 +2630,9 @@ TITLE     [tT][iI][tT][lL][eE]
 					    current->inside = current_root->name+"::";
 					  BEGIN( LineDoc );
 					}
-<FindMembers>"extern"{BN}+"\"C"("++")?"\""{BN}*("{")?
+<FindMembers>"extern"{BN}+"\"C"("++")?"\""{BN}*("{")?  {
+					  lineCount();
+					}
 <FindMembers>"{"			{
   					  current->type.resize(0);
   					  current->name.resize(0);
@@ -3411,6 +3419,102 @@ TITLE     [tT][iI][tT][lL][eE]
 <PageDocTitle>\n			{ yyLineNr++; current->args+=" "; }
 <PageDocTitle>[^\n\<]			{ current->args+=yytext; }
 <PageDocTitle>"</"{TITLE}">"		{ BEGIN( PageDoc ); }
+
+  /* escaped versions of the conditional commands (for putting them in the docs) */
+<ClassDoc,Doc,AfterDoc,PageDoc,ExampleDoc>{CMD}{CMD}"if"/[^a-z_A-Z0-9]     { current->doc+=&yytext[1]; }
+<ClassDoc,Doc,AfterDoc,PageDoc,ExampleDoc>{CMD}{CMD}"ifnot"/[^a-z_A-Z0-9]  { current->doc+=&yytext[1]; }
+<ClassDoc,Doc,AfterDoc,PageDoc,ExampleDoc>{CMD}{CMD}"elseif"/[^a-z_A-Z0-9] { current->doc+=&yytext[1]; }
+<ClassDoc,Doc,AfterDoc,PageDoc,ExampleDoc>{CMD}{CMD}"else"/[^a-z_A-Z0-9]   { current->doc+=&yytext[1]; }
+<ClassDoc,Doc,AfterDoc,PageDoc,ExampleDoc>{CMD}{CMD}"endif"/[^a-z_A-Z0-9]  { current->doc+=&yytext[1]; }
+<LineDoc,JavaDoc>{CMD}{CMD}"if"/[^a-z_A-Z0-9]     { current->brief+=&yytext[1]; }
+<LineDoc,JavaDoc>{CMD}{CMD}"ifnot"/[^a-z_A-Z0-9]  { current->brief+=&yytext[1]; }
+<LineDoc,JavaDoc>{CMD}{CMD}"elseif"/[^a-z_A-Z0-9] { current->brief+=&yytext[1]; }
+<LineDoc,JavaDoc>{CMD}{CMD}"else"/[^a-z_A-Z0-9]   { current->brief+=&yytext[1]; }
+<LineDoc,JavaDoc>{CMD}{CMD}"endif"/[^a-z_A-Z0-9]  { current->brief+=&yytext[1]; }
+
+  /* conditional commands */
+<ClassDoc,LineDoc,Doc,JavaDoc,AfterDoc,PageDoc,ExampleDoc>{CMD}"if"{B}+ {
+                                          lastIfContext = YY_START;
+					  BEGIN(IfGuard);
+  					}
+<ClassDoc,LineDoc,Doc,JavaDoc,AfterDoc,PageDoc,ExampleDoc>{CMD}"ifnot"{B}+ {
+                                          lastIfContext = YY_START;
+					  BEGIN(IfNotGuard);
+  					}
+<ClassDoc,LineDoc,Doc,JavaDoc,AfterDoc,PageDoc,ExampleDoc>{CMD}"if"(\r?)\n |
+<IfGuard>\n				{
+  					  warn(yyFileName,yyLineNr,"Missing guard for if statement!");
+					  yyLineNr++;
+					}  
+<IfGuard>[^\n\t ]+			{
+  					  if (Config_getList("ENABLED_SECTIONS").find(yytext)==-1) // not enabled
+					  {
+					    BEGIN(SkipSection);
+  					    depthIf=1;
+					  }
+					  else // section enabled
+					  {
+					    BEGIN(lastIfContext);
+					  }
+  					}
+<IfNotGuard>\n				{
+  					  warn(yyFileName,yyLineNr,"Missing guard for ifnot statement!");
+					  yyLineNr++;
+					}  
+<IfNotGuard>[^\n\t ]+			{
+  					  if (Config_getList("ENABLED_SECTIONS").find(yytext)==-1) // not enabled
+					  {
+					    BEGIN(lastIfContext);
+					  }
+					  else // section enabled
+					  {
+  					    depthIf=1;
+					    BEGIN(SkipSection);
+					  }
+  					}
+<SkipSection>{CMD}"if"/[^a-z_A-Z0-9]	{
+  					  depthIf++;
+  					}
+<SkipSection>{CMD}"endif"/[^a-z_A-Z0-9]	{
+  					  if (--depthIf<=0)
+					  {
+					    BEGIN(lastIfContext);
+					  }
+  					}
+<SkipSection>{CMD}"else"/[^a-z_A-Z0-9]	{
+  					  if (depthIf==1)
+					  {
+					    depthIf=0;
+					    BEGIN(lastIfContext);
+					  }
+  					}
+<SkipSection>{CMD}"elseif"/[^a-z_A-Z0-9] {
+  					  if (depthIf==1)
+					  {
+					    BEGIN(IfGuard);
+					  }
+  					}
+<SkipSection>"*/"			{
+  					  unput('/');unput('*');
+					  BEGIN( lastIfContext );
+  					}
+<SkipSection>\n				{
+  					  yyLineNr++;
+  					}
+<SkipSection>"//"|"*/"			  					
+<ClassDoc,Doc,JavaDoc,AfterDoc,PageDoc,ExampleDoc>{CMD}"elseif"/[^a-z_A-Z0-9] {
+                                          // previous section enabled => absorb else
+  					}
+<ClassDoc,Doc,JavaDoc,AfterDoc,PageDoc,ExampleDoc>{CMD}"else"/[^a-z_A-Z0-9] {
+                                          // section was enable => skip now
+  					  depthIf=1;
+  					  BEGIN(SkipSection);
+  					}
+<ClassDoc,Doc,JavaDoc,AfterDoc,PageDoc,ExampleDoc>{CMD}"endif"/[^a-z_A-Z0-9] {
+                                          // section enabled => absorb endif
+  					}
+
+
 <ClassDoc,LineDoc,Doc,JavaDoc,AfterDoc>{CMD}"ingroup"{B}+   { 
   					  lastGroupContext = YY_START;
   					  lineCount();
@@ -3868,7 +3972,9 @@ static void parseCompounds(Entry *rt)
       //  ce->name.data(),ce->program.data());
       // init scanner state
       padCount=0;
+      depthIf = 0;
       inputString = ce->program;
+      lastDefGroup.groupname.resize(0);
       inputPosition = 0;
       scanYYrestart( scanYYin ) ;
       if (ce->section==Entry::ENUM_SEC)
@@ -3900,6 +4006,11 @@ static void parseCompounds(Entry *rt)
       scanYYlex() ;
       delete current; current=0;
       ce->program.resize(0);
+
+      if (depthIf>0)
+      {
+	warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
+      }
     }
     parseCompounds(ce);
   }
@@ -3911,6 +4022,7 @@ void parseMain(Entry *rt)
 {
   initParser();
   anonCount     = 0;
+  depthIf       = 0;
   protection    = Public;
   mtype         = Method;
   gstat         = FALSE;
@@ -3920,10 +4032,13 @@ void parseMain(Entry *rt)
   current       = new Entry;
   inputString   = rt->program;
   inputPosition = 0;
-  ifCount=0;
   scanYYrestart( scanYYin );
   BEGIN( FindMembers );
   scanYYlex();
+  if (depthIf>0)
+  {
+    warn(yyFileName,yyLineNr,"Documentation block ended in the middle of a conditional section!");
+  }
   rt->program.resize(0);
   delete current; current=0;
   parseCompounds(rt);
diff --git a/src/util.cpp b/src/util.cpp
index 576e1c1..e766b3f 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -557,7 +557,7 @@ QCString removeRedundantWhiteSpace(const QCString &s)
     {
       result+=" >"; // insert extra space for layouting (nested) templates
     }
-    else if (i>0 && i<l-1 && c==',' && isId(s.at(i-1)) && isId(s.at(i+1)))
+    else if (i>0 && i<l-1 && c==',' && !isspace(s.at(i-1)) && isId(s.at(i+1)))
     {
       result+=", ";
     }
@@ -1014,28 +1014,71 @@ int minClassDistance(ClassDef *cd,ClassDef *bcd,int level)
 //}
 
 // strip any template specifiers that follow className in string s
-static QCString trimTemplateSpecifiers(const QCString &className,const QCString &s)
+static QCString trimTemplateSpecifiers(
+     const QCString &namespaceName,
+     const QCString &className,
+     const QCString &s
+)
 {
-  //printf("trimTemplateSpecifiers(%s,%s)\n",className.data(),s.data());
-  ClassDef *cd=getClass(className);
-  if (cd==0) return s;
+  //printf("trimTemplateSpecifiers(%s,%s,%s)\n",namespaceName.data(),className.data(),s.data());
+  QCString scopeName=mergeScopes(namespaceName,className);
+  ClassDef *cd=getClass(scopeName);
+  if (cd==0) return s; // should not happen, but guard anyway.
 
+  QCString result=s;
+
+  int i=className.length()-1;
+  if (className.at(i)=='>') // template specialization
+  {
+    // replace unspecialized occurrences in s, with their specialized versions.
+    int count=1;
+    int cl=i+1;
+    while (i>=0)
+    {
+      char c=className.at(i);
+      if (c=='>') count++,i--;
+      else if (c=='<') { count--; if (count==0) break; }
+      else i--;
+    }
+    QCString unspecClassName=className.left(i);
+    int l=i;
+    int p=0;
+    while ((i=result.find(unspecClassName,p))!=-1)
+    {
+      if (result.at(i+l)!='<') // unspecialized version
+      {
+        result=result.left(i)+className+result.right(result.length()-i-l);
+        l=cl;
+      }
+      p=i+l;
+    }
+  }
+
+  //printf("result after specialization: %s\n",result.data());
+  
   QCString qualName=cd->qualifiedNameWithTemplateParameters();
   //printf("QualifiedName = %s\n",qualName.data());
   // We strip the template arguments following className (if any)
-  QCString result=s;
   if (!qualName.isEmpty()) // there is a class name
   {
-    int i,p=0;
-    // TODO: also try smaller parts of the qualName, since we 
-    // could be inside a namespace or class.
-    while ((i=result.find(qualName,p))!=-1) // class name is in the argument type
+    int is,ps=0;
+    int p=0,l,i;
+
+    while ((is=getScopeFragment(qualName,ps,&l))!=-1)
     {
-      int ql=qualName.length();
-      result=result.left(i)+cd->name()+result.right(result.length()-i-ql);
-      p=i+cd->name().length();
+      QCString qualNamePart = qualName.right(qualName.length()-is);
+      //printf("qualNamePart=%s\n",qualNamePart.data());
+      while ((i=result.find(qualNamePart,p))!=-1)
+      {
+        int ql=qualNamePart.length();
+        result=result.left(i)+cd->name()+result.right(result.length()-i-ql);
+        p=i+cd->name().length();
+      }
+      ps=is+l;
     }
   }
+  //printf("result=%s\n",result.data());
+    
   return result;
 }
 
@@ -1203,9 +1246,9 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
   //       before matching. This should use className and namespaceName
   //       and usingNamespaces and usingClass to determine which typedefs
   //       are in-scope, so it will not be very efficient :-(
-  
-  QCString srcAType=trimTemplateSpecifiers(className,srcA->type);
-  QCString dstAType=trimTemplateSpecifiers(className,dstA->type);
+
+  QCString srcAType=trimTemplateSpecifiers(namespaceName,className,srcA->type);
+  QCString dstAType=trimTemplateSpecifiers(namespaceName,className,dstA->type);
   if (srcAType.left(6)=="class ") srcAType=srcAType.right(srcAType.length()-6);
   if (dstAType.left(6)=="class ") dstAType=dstAType.right(dstAType.length()-6);
   
@@ -1235,6 +1278,9 @@ static bool matchArgument(const Argument *srcA,const Argument *dstA,
   stripIrrelevantConstVolatile(srcAType);
   stripIrrelevantConstVolatile(dstAType);
 
+  srcAType = removeRedundantWhiteSpace(srcAType);
+  dstAType = removeRedundantWhiteSpace(dstAType);
+
   //srcAType=stripTemplateSpecifiersFromScope(srcAType,FALSE);
   //dstAType=stripTemplateSpecifiersFromScope(dstAType,FALSE);
 
@@ -1446,9 +1492,23 @@ static void mergeArgument(Argument *srcA,Argument *dstA,
     dstA->type+=dstA->name;
     dstA->name.resize(0);
   } 
+  if (srcA->name=="const" || srcA->name=="volatile")
+  {
+    srcA->type+=" ";
+    srcA->type+=srcA->name;
+    srcA->type=removeRedundantWhiteSpace(srcA->type);
+    srcA->name.resize(0);
+  }
+  if (dstA->name=="const" || dstA->name=="volatile")
+  {
+    dstA->type+=" ";
+    dstA->type+=dstA->name;
+    dstA->type=removeRedundantWhiteSpace(dstA->type);
+    dstA->name.resize(0);
+  }
   
-  QCString srcAType=trimTemplateSpecifiers(className,srcA->type);
-  QCString dstAType=trimTemplateSpecifiers(className,dstA->type);
+  QCString srcAType=trimTemplateSpecifiers(namespaceName,className,srcA->type);
+  QCString dstAType=trimTemplateSpecifiers(namespaceName,className,dstA->type);
   if (srcAType.left(6)=="class ") srcAType=srcAType.right(srcAType.length()-6);
   if (dstAType.left(6)=="class ") dstAType=dstAType.right(dstAType.length()-6);
 
@@ -1617,10 +1677,16 @@ static void mergeArgument(Argument *srcA,Argument *dstA,
     if (i>0 && i<(int)srcAType.length()-1 && srcAType.at(i)!=':') 
       // there is (probably) a name
     {
-      srcA->name=srcAType.right(srcAType.length()-i-1);
-      srcA->type=srcAType.left(i+1).stripWhiteSpace();
-      dstA->name=dstAType.right(dstAType.length()-i-1);
-      dstA->type=dstAType.left(i+1).stripWhiteSpace();
+      QCString srcAName=srcAType.right(srcAType.length()-i-1);
+      QCString dstAName=dstAType.right(dstAType.length()-i-1);
+      if (srcAName!="const" && srcAName!="volatile" &&
+          dstAName!="const" && dstAName!="volatile")
+      {
+        srcA->name=srcAName;
+        srcA->type=srcAType.left(i+1).stripWhiteSpace();
+        dstA->name=dstAName;
+        dstA->type=dstAType.left(i+1).stripWhiteSpace();
+      }
     } 
   }
   else if (!dstA->name.isEmpty())
@@ -1655,11 +1721,11 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl,
   QCString namespaceName=ns;
 
   // strip template specialization from class name if present
-  int til=className.find('<'),tir=className.find('>');
-  if (til!=-1 && tir!=-1 && tir>til) 
-  {
-    className=className.left(til)+className.right(className.length()-tir-1);
-  }
+  //int til=className.find('<'),tir=className.find('>');
+  //if (til!=-1 && tir!=-1 && tir>til) 
+  //{
+  //  className=className.left(til)+className.right(className.length()-tir-1);
+  //}
 
   //printf("matchArguments(%s,%s) className=%s namespaceName=%s checkCV=%d usingNamespaces=%d usingClasses=%d\n",
   //    srcAl ? argListToString(srcAl).data() : "",
@@ -2670,24 +2736,22 @@ QCString substituteKeywords(const QCString &s,const char *title)
  */ 
 int getPrefixIndex(const QCString &name)
 {
-  int ni = name.findRev("::");
-  if (ni==-1) ni=0; else ni+=2;
   //printf("getPrefixIndex(%s) ni=%d\n",name.data(),ni);
   QStrList &sl = Config_getList("IGNORE_PREFIX");
   char *s = sl.first();
   while (s)
   {
     const char *ps=s;
-    const char *pd=name.data()+ni;
+    const char *pd=name.data();
     int i=0;
     while (*ps!=0 && *pd!=0 && *ps==*pd) ps++,pd++,i++;
     if (*ps==0 && *pd!=0)
     {
-      return ni+i;
+      return i;
     }
     s = sl.next();
   }
-  return ni;
+  return 0;
 }
 
 //----------------------------------------------------------------------------
@@ -2868,17 +2932,52 @@ QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &te
   return result;
 }
 
+/*! Strips the scope from a name. Examples: A::B will return A
+ *  and A<T>::B<N::C<D> > will return A<T>.
+ *  \todo deal with cases like A< s<<2 >::B
+ */
 QCString stripScope(const char *name)
 {
   QCString result = name;
-  int ti=result.find('<'); // find start of template
-  if (ti==-1) ti=result.length();
-  int i = ti>2 ? result.findRev("::",ti-2) : -1; // find scope just before template
-  if (i!=-1) // found scope
+  int l=result.length();
+  int p=l-1;
+  bool done;
+  int count;
+
+  while (p>=0)
   {
-    result=result.right(result.length()-i-2);
+    char c=result.at(p);
+    switch (c)
+    {
+      case ':': 
+        //printf("stripScope(%s)=%s\n",name,result.right(l-p-1).data());
+        return result.right(l-p-1);
+      case '>':
+        count=1;
+        done=FALSE;
+        //printf("pos < = %d\n",p);
+        p--;
+        while (p>=0 && !done)
+        {
+          c=result.at(p--);
+          switch (c)
+          {
+            case '>': count++; break;
+            case '<': count--; if (count<=0) done=TRUE; break;
+            default: 
+              //printf("c=%c count=%d\n",c,count);
+              break;
+          }
+        }
+        //printf("pos > = %d\n",p+1);
+        break;
+      default:
+        p--;
+    }
   }
-  return result;
+  //printf("stripScope(%s)=%s\n",name,name);
+  return name;
+  
 }
 
 /*! Converts a string to an XML-encoded string */
@@ -3015,6 +3114,8 @@ bool extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCStr
 QCString substituteTemplateArgumentsInString(
        const QCString &name,ArgumentList *formalArgs,ArgumentList *actualArgs)
 {
+  //printf("substituteTemplateArgumentsInString(name=%s formal=%s actualArg=%s)\n",
+  //    name.data(),argListToString(formalArgs).data(),argListToString(actualArgs).data());
   if (formalArgs==0) return name;
   QCString result;
   static QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*");
@@ -3036,16 +3137,19 @@ QCString substituteTemplateArgumentsInString(
         ++formAli,actArg=actualArgs->next()
         )
     {
-      if (formArg->name==n && actArg && !actArg->type.isEmpty()) // base class is a template argument
-      {
-        // replace formal argument with the actual argument of the instance
-        result += actArg->type; 
-        found=TRUE;
-      }
-      else if (formArg->name==n && actArg==0 && !formArg->defval.isEmpty())
+      if (formArg->type=="class" || formArg->type=="typename")
       {
-        result += formArg->defval;
-        found=TRUE;
+        if (formArg->name==n && actArg && !actArg->type.isEmpty()) // base class is a template argument
+        {
+          // replace formal argument with the actual argument of the instance
+          result += actArg->type; 
+          found=TRUE;
+        }
+        else if (formArg->name==n && actArg==0 && !formArg->defval.isEmpty())
+        {
+          result += formArg->defval;
+          found=TRUE;
+        }
       }
     }
     if (!found) result += n;
@@ -3109,10 +3213,8 @@ QCString stripTemplateSpecifiersFromScope(const QCString &fullName,
   int p=0;
   int l=fullName.length();
   int i=fullName.find('<');
-  int si= i==-1 ? -1 : fullName.find("::",i);
-  while (i!=-1 && (!parentOnly || i<si))
+  while (i!=-1)
   {
-    result+=fullName.mid(p,i-p);
     //printf("1:result+=%s\n",fullName.mid(p,i-p).data());
     int e=i+1;
     bool done=FALSE;
@@ -3130,18 +3232,112 @@ QCString stripTemplateSpecifiersFromScope(const QCString &fullName,
         done = count==0;
       }
     }
+    int si= fullName.find("::",e);
+
+    if (parentOnly && si==-1) break; 
+       // we only do the parent scope, so we stop here if needed
+
+    result+=fullName.mid(p,i-p);
     //printf("  trying %s\n",(result+fullName.mid(i,e-i)).data());
-    if (getClass(result+fullName.mid(i,e-i))!=0)
+    if (getClass(result+fullName.mid(i,e-i))!=0) 
     {
       result+=fullName.mid(i,e-i);
       //printf("2:result+=%s\n",fullName.mid(i,e-i-1).data());
     }
     p=e;
     i=fullName.find('<',p);
-    si= i==-1 ? -1 : fullName.find("::",i);
   }
   result+=fullName.right(l-p);
   //printf("3:result+=%s\n",fullName.right(l-p).data());
   return result;
 }
 
+/*! Merges two scope parts together. The parts may (partially) overlap.
+ *  Example1: \c A::B and \c B::C will result in \c A::B::C <br>
+ *  Example2: \c A and \c B will be \c A::B <br>
+ *  Example3: \c A::B and B will be \c A::B
+ *  
+ *  @param leftScope the left hand part of the scope.
+ *  @param rightScope the right hand part of the scope.
+ *  @returns the merged scope. 
+ */
+QCString mergeScopes(const QCString &leftScope,const QCString &rightScope)
+{
+  // case leftScope=="A" rightScope=="A::B" => result = "A::B"
+  if (leftScopeMatch(rightScope,leftScope)) return rightScope;
+  QCString result;
+  int i=0,p=leftScope.length();
+
+  // case leftScope=="A::B" rightScope=="B::C" => result = "A::B::C"
+  // case leftScope=="A::B" rightScope=="B" => result = "A::B"
+  bool found=FALSE;
+  while ((i=leftScope.findRev("::",p))!=-1)
+  {
+    if (leftScopeMatch(rightScope,leftScope.right(leftScope.length()-i-2)))
+    {
+      result = leftScope.left(i+2)+rightScope;
+      found=TRUE;
+    }
+    p=i-1;
+  }
+  if (found) return result;
+
+  // case leftScope=="A" rightScope=="B" => result = "A::B"
+  result=leftScope.copy();
+  if (!result.isEmpty() && !rightScope.isEmpty()) result+="::";
+  result+=rightScope;
+  return result;
+}
+
+/*! Returns a fragment from scope \a s, starting at position \a p.
+ *
+ *  @param s the scope name as a string.
+ *  @param p the start position (0 is the first).
+ *  @param l the resulting length of the fragment.
+ *  @returns the location of the fragment, or -1 if non is found.
+ */
+int getScopeFragment(const QCString &s,int p,int *l)
+{
+  int sl=s.length();
+  int sp=p;
+  int count=0;
+  bool done;
+  if (sp>=sl) return -1;
+  while (sp<sl)
+  {
+    char c=s.at(sp);
+    if (c==':') sp++,p++; else break;
+  }
+  while (sp<sl)
+  {
+    char c=s.at(sp);
+    switch (c)
+    {
+      case ':': // found next part
+        goto found;
+      case '<': // skip template specifier
+        count=1;sp++;
+        done=FALSE;
+        while (sp<sl && !done)
+        {
+          // TODO: deal with << and >> operators!
+          char c=s.at(sp++);
+          switch(c)
+          {
+            case '<': count++; break;
+            case '>': count--; if (count==0) done=TRUE; break;
+            default: break;
+          }
+        }
+        break;
+      default:
+        sp++;
+        break;
+    }
+  }
+found:
+  *l=sp-p;
+  //printf("getScopeFragment(%s,%d)=%s\n",s.data(),p,s.mid(p,*l).data());
+  return p;
+}
+
diff --git a/src/util.h b/src/util.h
index e15f516..04fd752 100644
--- a/src/util.h
+++ b/src/util.h
@@ -160,6 +160,8 @@ QList<ArgumentList> *copyArgumentLists(const QList<ArgumentList> *srcLists);
 QCString stripTemplateSpecifiersFromScope(const QCString &fullName,
                                           bool parentOnly=TRUE);
 QCString resolveTypeDef(Definition *d,const QCString &name);
+QCString mergeScopes(const QCString &leftScope,const QCString &rightScope);
+int getScopeFragment(const QCString &s,int p,int *l);
 
 #endif
 
diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp
index 8b9ed39..3b9d404 100644
--- a/src/xmlgen.cpp
+++ b/src/xmlgen.cpp
@@ -38,8 +38,8 @@ static inline void writeXMLString(QTextStream &t,const char *s)
   t << convertToXML(s);
 }
 
-static void writeXMLLink(QTextStream &t,const char *compoundId,const char *memId,
-                  const char *text)
+static void writeXMLLink(QTextStream &t,const char *compoundId,
+                  const char *memId,const char *text)
 {
   if (memId==0)
   {
-- 
cgit v0.12