################################################
##
## This first part adds support for \innamespace to the commentscanner.
## The namespace is stored in the same way as \relates and \memberof,
## since they are mutually exclusive anyway.
##
################################################
Index: src/entry.h
===================================================================
--- src/entry.h	(revision 673)
+++ src/entry.h	(working copy)
@@ -33,7 +33,7 @@
 enum Protection { Public, Protected, Private, Package } ;
 enum Specifier { Normal, Virtual, Pure } ;
 enum MethodTypes { Method, Signal, Slot, DCOP, Property, Event };
-enum RelatesType { Simple, Duplicate, MemberOf };
+enum RelatesType { Simple, Duplicate, MemberOf, InNamespace };
 enum Relationship { Member, Related, Foreign };
 
 struct ListItemInfo
Index: src/commentscan.l
===================================================================
--- src/commentscan.l	(revision 673)
+++ src/commentscan.l	(working copy)
@@ -80,6 +80,7 @@
 static bool handleRelated(const QCString &);
 static bool handleRelatedAlso(const QCString &);
 static bool handleMemberOf(const QCString &);
+static bool handleInNamespace(const QCString &);
 static bool handleRefItem(const QCString &);
 static bool handleSection(const QCString &);
 static bool handleAnchor(const QCString &);
@@ -202,6 +203,7 @@
   { "extends",         &handleExtends,          TRUE  },
   { "implements",      &handleExtends,          TRUE  },
   { "memberof",        &handleMemberOf,         TRUE  },
+  { "innamespace",     &handleInNamespace,      TRUE  },
   { "arg",             0,                       TRUE  },
   { "attention",       0,                       TRUE  },
   { "author",          0,                       TRUE  },
@@ -2110,6 +2112,13 @@
   return FALSE;
 }
 
+static bool handleInNamespace(const QCString &)
+{
+  current->relatesType = InNamespace;
+  BEGIN(RelatesParam1);
+  return FALSE;
+}
+
 static bool handleRefItem(const QCString &)
 {
   addOutput("@refitem ");
################################################
##
## The next part of the patch makes doxygen.cpp properly handle the
## InNamespace RelatesType.
##
################################################
Index: src/doxygen.cpp
===================================================================
--- src/doxygen.cpp	(revision 673)
+++ src/doxygen.cpp	(working copy)
##
## We need limits.h to pass INT_MAX to buildScopeFromQualifiedName to
## make it build namespaces for the entire name instead of just the first
## so many elements. Some other large number will probably also suffice
## if this extra include is considered a problem
##
@@ -29,6 +29,7 @@
 #include <qtextcodec.h>
 #include <unistd.h>
 #include <errno.h>
+#include <limits.h>
 
 #include "version.h"
 #include "doxygen.h"
@@ -1060,32 +1061,28 @@ void addClassToContext(EntryNav *rootNav)
   //NamespaceDef *nd = 0;
   FileDef *fd = rootNav->fileDef();

##
## Prepending the scope (which was done below) is not useful. Since it
## already happens in the scanner, the leftScopeMatch() below would
## always return false anyway (except perhaps when some template
## specifiers are involved, but that would only result in prepending the
## scope twice then.
##
-  QCString scName;
-  if (rootNav->parent()->section()&Entry::SCOPE_MASK)
-  {
-     scName=rootNav->parent()->name();
-  }
+  if (root->relatesType == InNamespace && !root->relates.isEmpty())
+  {
+    // Force the scope to be created if this is not the case. This
+    // allows a \innamespace to create new namespaces
+    buildScopeFromQualifiedName(root->relates, INT_MAX);
+  } 
+
+  // root->name contains the qualified name already (scope is prepended
+  // by prependScope in scanner.l).
-  // name without parent's scope: TODO: is this still true?
   QCString fullName = root->name;
 
   // strip off any template parameters (but not those for specializations)
   fullName=stripTemplateSpecifiersFromScope(fullName);
 
-  // name with scope
-  QCString qualifiedName = fullName;
-  if (!scName.isEmpty() && !leftScopeMatch(fullName,scName))
-  {
-    qualifiedName.prepend(scName+"::");
-  }
+  ClassDef *cd = getClass(fullName);
 
-  ClassDef *cd = getClass(qualifiedName);
-
-  Debug::print(Debug::Classes,0, "  Found class with name %s (qualifiedName=%s -> cd=%p)\n",
-      cd ? cd->name().data() : root->name.data(), qualifiedName.data(),cd);
+  Debug::print(Debug::Classes,0, "  Found class with name %s -> cd=%p\n",
+      cd ? cd->name().data() : root->name.data(), fullName.data(),cd);
   
   if (cd) 
   {
##
## This value was only used in commented out code below
##
-    fullName=cd->name();
+    //fullName=cd->name();
     Debug::print(Debug::Classes,0,"  Existing class %s!\n",cd->name().data());
     //if (cd->templateArguments()==0)
     //{
@@ -1341,6 +1338,13 @@ void buildNamespaceList(EntryNav *rootNav)
       fName=substitute(fName,".","::");
     }
 
+    if (root->relatesType == InNamespace && !root->relates.isEmpty())
+    {
+      // Force the scope to be created if this is not the case. This
+      // allows a \innamespace to create new namespaces
+      buildScopeFromQualifiedName(root->relates, INT_MAX);
+    } 
+
     QCString fullName = stripAnonymousNamespaceScope(fName);
     if (!fullName.isEmpty())
     {
@@ -2820,8 +2824,20 @@ void buildFunctionList(EntryNav *rootNav)
     bool isFriend=root->type.find("friend ")!=-1;
     QCString rname = removeRedundantWhiteSpace(root->name);
     //printf("rname=%s\n",rname.data());
+    
+    QCString scope;
+    if (root->relatesType == InNamespace && !root->relates.isEmpty())
+    {
+      scope = root->relates;
+      // Force the scope to be created if this is not the case. This
+      // allows a \innamespace to create new namespaces
+      buildScopeFromQualifiedName(scope, INT_MAX);
+    } 
+    else
+    {
+      scope=rootNav->parent()->name(); //stripAnonymousNamespaceScope(root->parent->name);
+    }
 
-    QCString scope=rootNav->parent()->name(); //stripAnonymousNamespaceScope(root->parent->name);
     if (!rname.isEmpty() && scope.find('@')==-1)
     {
       
@@ -2840,7 +2857,6 @@ void buildFunctionList(EntryNav *rootNav)
##
## This variable was used only a lot further below, so the declaration
## is moved there. It used to be set by some code just below here, but
## that code is now commented out.
##
         rname=rname.right(rname.length()-rootNav->parent()->name().length()-2); 
       }
 
-      NamespaceDef *nd = 0;
       bool isMember=FALSE;
       if (memIndex!=-1)
       {
@@ -2887,7 +2903,7 @@ void buildFunctionList(EntryNav *rootNav)
##
## This check prevents functions that are marked \related or \memberof
## from being listed as normal functions. Functions marked \relatedalso
## or \innamespace should still be listed of course.
##
                  || rootNav->parent()->section()==Entry::OBJCIMPL_SEC
                 ) &&
                !isMember &&
-               (root->relates.isEmpty() || root->relatesType == Duplicate) &&
+               (root->relates.isEmpty() || root->relatesType == Duplicate || root->relatesType == InNamespace) &&
                root->type.left(7)!="extern " && root->type.left(8)!="typedef " 
               )
       // no member => unrelated function 
@@ -2908,15 +2924,8 @@ void buildFunctionList(EntryNav *rootNav)
##
## This code handles merging the current Entry into a previously created
## MemberDef for this (non-member) function.
##
## In the original code, scope has the following value:
##  scope=rootNav->parent()->name(); //stripAnonymousNamespaceScope(root->parent->name);
##  if (!rname.isEmpty() && scope.find('@')==-1)
##    scope=stripTemplateSpecifiersFromScope(scope,FALSE);
##
## This means that the leftScopeMatch below should really always return
## false. The only reason this could be different that I can see is when
## template specifiers are involved and then the scope would only be
## added twice. Removing this code seems like a good idea and is also
## required to allow scope to be anything else than
## rootNav->parent()->name()
##
## Finally, some testing confirms that this code does not execute for
## the codebases on which I tested, amongst which the llvm code, which
## is a pretty big (~20 minute doxygen run) C++ codebase using
## namespaces and templates quite heavily.
##
             NamespaceDef *mnd = md->getNamespaceDef();
             NamespaceDef *rnd = 0;
             //printf("root namespace=%s\n",rootNav->parent()->name().data());
-            QCString fullScope = scope;
-            QCString parentScope = rootNav->parent()->name();
-            if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope))
-            {
-              if (!scope.isEmpty()) fullScope.prepend("::");
-              fullScope.prepend(parentScope);
-            }
-            //printf("fullScope=%s\n",fullScope.data());
-            rnd = getResolvedNamespace(fullScope);
+            rnd = getResolvedNamespace(scope);
+
             FileDef *mfd = md->getFileDef();
             QCString nsName,rnsName;
             if (mnd)  nsName = mnd->name().copy();
@@ -3038,17 +3047,8 @@ void buildFunctionList(EntryNav *rootNav)
##
## This code handles creating a new MemberDef for this (non-member)
## function.
##
## This is a similar story, though the original code had a check on the
## parent's section which is now missing. If it is really required, then
## this code could be reinstated, prepended by an unconditional 
##   if (root->relatesType == InNamespace)
##     nd = getResolvedNamespace(scope);
##   else
## 
## However, if scope was not a namespace but a class (are there other
## options anyway?) then isMember would have been set already above and
## this code would never be exectued at all.
           md->setMemberSpecifiers(root->spec);
           md->setMemberGroupId(root->mGrpId);

-          // see if the function is inside a namespace that was not part of
-          // the name already (in that case nd should be non-zero already)
-          if (nd==0 && rootNav->parent()->section() == Entry::NAMESPACE_SEC )
-          {
-            //QCString nscope=removeAnonymousScopes(rootNav->parent()->name());
-            QCString nscope=rootNav->parent()->name();
-            if (!nscope.isEmpty())
-            {
-              nd = getResolvedNamespace(nscope);
-            }
-          }
+          NamespaceDef *nd = 0;
+          nd = getResolvedNamespace(scope);
 
           if (!scope.isEmpty())
           {
@@ -5781,7 +5781,7 @@ void findMember(EntryNav *rootNav,
##
## This check sees if a function is a related function and should be
## addded to a class.
##
         }
       }
     }
-    else if (isRelated && !root->relates.isEmpty())
+    else if (isRelated && isRelated != InNamespace && !root->relates.isEmpty())
     {
       Debug::print(Debug::FindMembers,0,"2. related function\n"
               "  scopeName=%s className=%s\n",scopeName.data(),className.data());
################################################
##
## This part ensures that namespaces and classes with \innamespace get
## the right scope prepended. This has to happen in the scanner, so any
## child classes or namespaces can be named properly. This does not
## happen for functions, since ## they are produced by the scanner with
## an unqualified name.
## 
################################################
Index: src/scanner.l
===================================================================
--- src/scanner.l	(revision 673)
+++ src/scanner.l	(working copy)
@@ -347,8 +347,17 @@
 
 static void prependScope()
 {
-  if (current_root->section & Entry::SCOPE_MASK)
+  printf("PS: %s / %s\n", current->name.data(), current->relates.data());
+  if (!current->relates.isEmpty() && current->relatesType == InNamespace)
   {
+    // If the namespace was overriden using \innamespace, then prepend
+    // the given namespace instead of the parent one.
+    // We must do this early, so that any members of current (which can
+    // be a class or namespace) will get the right scope names.
+    current->name.prepend(current->relates + "::");
+  }
+  else if (current_root->section & Entry::SCOPE_MASK)
+  {
     //printf("--- prependScope %s to %s\n",current_root->name.data(),current->name.data());
     current->name.prepend(current_root->name+"::");
     if (current_root->tArgLists)
@@ -2985,7 +2994,7 @@
 					    QCString &cn = current->name;
 					    QCString rn = current_root->name.copy();
 					    //printf("cn=`%s' rn=`%s'\n",cn.data(),rn.data());
-					    if (!cn.isEmpty() && !rn.isEmpty())
+					    if (!cn.isEmpty() && (!rn.isEmpty() || current->relatesType == InNamespace && !current->relates.isEmpty()))
 					    {
 					      prependScope();
 					    }
################################################
## 
## The final part contains documentation and an example.
##
################################################
Index: doc/commands.doc
===================================================================
--- doc/commands.doc	(revision 673)
+++ doc/commands.doc	(working copy)
@@ -1,5 +1,5 @@
 /******************************************************************************
- *
+*
  * 
  *
  * Copyright (C) 1997-2008 by Dimitri van Heesch.
@@ -102,6 +102,7 @@
 \refitem cmdinclude \\include
 \refitem cmdincludelineno \\includelineno
 \refitem cmdingroup \\ingroup
+\refitem cmdinnamespace \\innamespace
 \refitem cmdinternal \\internal
 \refitem cmdinvariant \\invariant
 \refitem cmdinterface \\interface
@@ -504,6 +505,34 @@
   \ref cmdaddtogroup "\\addtogroup" and \ref cmdweakgroup "\\weakgroup"
 
 <hr>
+\section cmdinnamespace \\innamespace <name>
+
+  \addindex \\innamespace
+  This command puts a function, class, namespace or method in the
+  namespace \<name\>, as if it was declared inside the namespace. The
+  namespace does not need to exist or be documented.
+
+  Any scope of the original definition that is derived from the location
+  of the definition (e.g., the namespace in which a function is declared).
+  This means that using \\innamespace on an inline method definition
+  will remove the class scope and turn it into a function inside
+  \<name\>.  Any scope derived from the name of the definition (e.g.,
+  the classname on a method that is defined outside the class
+  declaration for example) is preserved.
+
+  This can be useful when the programming language does not support 
+  the concept of namespaces natively (e.g. C or PHP).
+
+  This command is mutually exclusive with \ref cmdmemberof "\\memberof",
+  \ref cmdrelates "\\relates" and \ref cmdrelatesalso "\\relatesalso".
+
+  The file \c manual.c in the example directory shows how to use this command.
+  \htmlonly
+  Click <a href="$(DOXYGEN_DOCDIR)/examples/manual/html/index.html">here</a> 
+  for the corresponding HTML documentation that is generated by doxygen.
+  \endhtmlonly
+
+<hr>
 \section cmdinterface \\interface <name> [<header-file>] [<header-name>]
 
   \addindex \\interface
Index: examples/manual.c
===================================================================
--- examples/manual.c	(revision 673)
+++ examples/manual.c	(working copy)
@@ -33,6 +33,7 @@
 /*!
  * Vehicle class.
  * \extends Object
+ * \innamespace Traffic
  */
 struct Vehicle
 {
@@ -42,14 +43,14 @@
 
 /*!
  * Starts the vehicle.
- * \public \memberof Vehicle
+ * \public \memberof Traffic::Vehicle
  */
 void vehicleStart(Vehicle *obj);
 
 
 /*!
  * Stops the vehicle.
- * \public \memberof Vehicle
+ * \public \memberof Traffic::Vehicle
  */
 void vehicleStop(Vehicle *obj);
 
@@ -57,6 +58,7 @@
 /*!
  * Car class.
  * \extends Vehicle
+ * \innamespace Traffic
  */
 struct Car
 {
@@ -67,6 +69,7 @@
 /*!
  * Truck class.
  * \extends Vehicle
+ * \innamespace Traffic
  */
 struct Truck
 {
