--- src/doxygen.cpp@@/main/LATEST	Tue Feb 28 23:12:43 2006
+++ src/doxygen.cpp	Tue Feb 28 23:28:57 2006
@@ -2180,6 +2180,191 @@
 }
 
 //----------------------------------------------------------------------
+// Searches the Entry tree for Variable documentation sections and
+// creates MemberDefs for any typedefs therein.
+
+static void buildTypedefList(Entry *root)
+{
+  if (!root->name.isEmpty() &&
+      (root->type.isEmpty() || compoundKeywordDict.find(root->type)==0) &&
+      ((root->section==Entry::VARIABLE_SEC    // it's a typedef
+       ) ||
+       (root->section==Entry::FUNCTION_SEC && // or maybe a function pointer typedef
+        findFunctionPtr(root->type)!=-1
+       ))
+     ) // documented typedef
+  {
+    Debug::print(Debug::Variables,0,
+                  "VARIABLE_SEC: \n"
+                  "  type=`%s' name=`%s' args=`%s' bodyLine=`%d' mGrpId=%d\n",
+                   root->type.data(),
+                   root->name.data(),
+                   root->args.data(),
+                   root->bodyLine,
+                   root->mGrpId
+                );
+    //printf("root->parent->name=%s\n",root->parent->name.data());
+
+    if (root->type.isEmpty() && root->name.find("operator")==-1 &&
+        (root->name.find('*')!=-1 || root->name.find('&')!=-1))
+    {
+      // recover from parse error caused by redundant braces 
+      // like in "int *(var[10]);", which is parsed as
+      // type="" name="int *" args="(var[10])"
+
+      root->type=root->name;
+      static const QRegExp reName("[a-z_A-Z][a-z_A-Z0-9]*");
+      int l;
+      int i=root->args.isEmpty() ? -1 : reName.match(root->args,0,&l);
+      root->name=root->args.mid(i,l);
+      root->args=root->args.mid(i+l,root->args.find(')',i+l)-i-l);
+      //printf("new: type=`%s' name=`%s' args=`%s'\n",
+      //    root->type.data(),root->name.data(),root->args.data());
+    }
+    else
+    {
+      int i=findFunctionPtr(root->type);
+      if (i!=-1) // function pointer
+      {
+        int ai = root->type.find('[',i);
+        if (ai>i) // function pointer array
+        {
+          root->args.prepend(root->type.right(root->type.length()-ai));
+          root->type=root->type.left(ai);
+        }
+        else if (root->type.find(')',i)!=-1) // function ptr, not variable like "int (*bla)[10]"
+        {
+          root->type=root->type.left(root->type.length()-1);
+          root->args.prepend(")");
+          //printf("root->type=%s root->args=%s\n",root->type.data(),root->args.data());
+        }
+      }
+    }
+    
+    QCString scope,name=removeRedundantWhiteSpace(root->name);
+
+    // find the scope of this variable 
+    Entry *p = root->parent;
+    while ((p->section & Entry::SCOPE_MASK))
+    {
+      QCString scopeName = p->name.copy();
+      if (!scopeName.isEmpty())
+      {
+        scope.prepend(scopeName);
+        break;
+      }
+      p=p->parent;
+    }
+    
+    MemberDef::MemberType mtype;
+    QCString type=root->type.stripWhiteSpace();
+    ClassDef *cd=0;
+
+    if (root->name.findRev("::")!=-1)
+    {
+      goto nextMember;
+               /* skip this member, because it is a 
+                * static variable definition (always?), which will be
+                * found in a class scope as well, but then we know the
+                * correct protection level, so only then it will be
+                * inserted in the correct list!
+                */
+    }
+
+    if (type.left(8)=="typedef ") 
+    {
+      mtype=MemberDef::Typedef;
+
+      QCString classScope=stripAnonymousNamespaceScope(scope);
+      classScope=stripTemplateSpecifiersFromScope(classScope,FALSE);
+      QCString annScopePrefix=scope.left(scope.length()-classScope.length());
+
+      bool isRelated=FALSE;
+      if (!root->relates.isEmpty()) // related variable
+      {
+        isRelated=TRUE;
+        if (getClass(root->relates)==0 && !scope.isEmpty())
+          scope=mergeScopes(scope,root->relates);
+        else 
+          scope=root->relates.copy();
+      }
+    
+      // note: changed from scope to classScope on 2-10-2005
+      if (!classScope.isEmpty() && !name.isEmpty() && (cd=getClass(classScope)))
+      {
+        MemberDef *md=0;
+
+        // if cd is an annonymous scope we insert the member 
+        // into a non-annonymous scope as well. This is needed to
+        // be able to refer to it using \var or \fn
+
+        //int indentDepth=0;
+        int si=scope.find('@');
+        //int anonyScopes = 0;
+        if (si!=-1) // anonymous scope
+        {
+          QCString pScope;
+          ClassDef *pcd=0;
+          pScope = scope.left(QMAX(si-2,0));
+          if (!pScope.isEmpty())
+            pScope.prepend(annScopePrefix);
+          else if (annScopePrefix.length()>2)
+            pScope=annScopePrefix.left(annScopePrefix.length()-2);
+          if (name.at(0)!='@')
+          {
+            if (!pScope.isEmpty() && (pcd=getClass(pScope)))
+            {
+              md=addVariableToClass(root,  // entry
+                                    pcd,   // class to add member to
+                                    mtype, // member type
+                                    name,  // member name
+                                    TRUE,  // from anonymous scope
+                                    0,     // from anonymous member
+                                    root->protection,
+                                    isRelated
+                 );
+            }
+            else // anonymous scope inside namespace or file => put variable in the global scope
+            {
+              if (mtype==MemberDef::Variable)
+              {
+                md=addVariableToFile(root,mtype,pScope,name,TRUE,0); 
+              }
+            }
+          }
+        }
+
+        //printf("name=`%s' scope=%s scope.right=%s indentDepth=%d anonyScopes=%d\n",
+        //                   name.data(),scope.data(),
+        //                   scope.right(scope.length()-si).data(),
+        //                   indentDepth,
+        //                   anonyScopes);
+        addVariableToClass(root,   // entry
+                           cd,     // class to add member to
+                           mtype,  // member type
+                           name,   // name of the member
+                           FALSE,  // from anonymous scope
+                           md,     // from anonymous member
+                           root->protection, 
+                           isRelated);
+      }
+      else if (!name.isEmpty()) // global variable
+      {
+        //printf("Inserting member in global scope %s!\n",scope.data());
+        addVariableToFile(root,mtype,scope,name,FALSE,/*0,*/0);
+      }
+    }
+  }
+nextMember:
+  EntryListIterator eli(*root->sublist);
+  Entry *e;
+  for (;(e=eli.current());++eli)
+  {
+    if (e->section!=Entry::ENUM_SEC) buildTypedefList(e);
+  }
+}
+
+//----------------------------------------------------------------------
 // Searches the Entry tree for Variable documentation sections.
 // If found they are stored in their class or in the global list.
 
@@ -2302,7 +2487,7 @@
     if (type=="@") 
       mtype=MemberDef::EnumValue;
     else if (type.left(8)=="typedef ") 
-      mtype=MemberDef::Typedef;
+      goto nextMember;
     else if (type.left(7)=="friend ")
       mtype=MemberDef::Friend;
     else if (root->mtype==Property)
@@ -8835,6 +9020,9 @@
 
   msg("Associating documentation with classes...\n");
   buildClassDocList(root);
+
+  msg("Associating documentation with typedefs...\n");
+  buildTypedefList(root);
 
   // build list of using declarations here (global list)
   buildListOfUsingDecls(root);
