documentor: Improved spacing
[sdk] / documentor / src / Documentor.ec
index 0b7bb5e..7e1244a 100644 (file)
@@ -46,15 +46,6 @@ static const char * iconNames[CodeObjectType] =
    "<:ecere>constructs/propertyPrivate.png"
 };
 
-IDESettings settings { }; // instantiate the IDESettings class from the IDESettings.ec file. Do this at a global level so that all methods can access settings.
-
-IDESettingsContainer settingsContainer
-{
-   driver = "JSON";
-   data = settings;
-   dataOwner = &settings;
-};
-
 void GetTemplateString(Class c, char * templateString)
 {
    Module m = c.module.application;
@@ -410,14 +401,16 @@ void DocPrintType(Type type, char * string, bool printName, bool fullName)
       _PrintType(type, string, printName, true, fullName);
 }
 
+Map<String, bool> modulesAdded { };
 void AddComponents(Module module, bool isDll)
 {
    DataRow row = null;
    SubModule m;
 
-   if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
+   if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")) && !modulesAdded["ecereCOM"])
    {
       row = mainForm.browser.AddRow();
+      modulesAdded["ecereCOM"] = true;
       row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
       row.tag = (int64)null;
       AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
@@ -430,9 +423,10 @@ void AddComponents(Module module, bool isDll)
    }
 
    // PUT MODULE DESCRIPTION HERE
-   if(module.name && strcmp(module.name, "ecereCOM"))
+   if(module.name && !modulesAdded[module.name] && strcmp(module.name, "ecereCOM"))
    {
       row = mainForm.browser.AddRow();
+      modulesAdded[module.name] = true;
       row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
       row.tag = (int64)module;
       AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
@@ -587,14 +581,13 @@ static void FigureFilePath(char * path, Module module, DocumentationType type, v
    ChangeExtension(docPath, "econ", docPath);
 
    path[0] = 0;
-   strcpy(path, settings.docDir);
+   strcpy(path, ideSettings.docDir);
    PathCatSlash(path, docPath);
 }
 
 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
 {
    String contents = null;
-   bool docRetrieved = false;
    NamespaceDoc nsDoc = null;
    ClassDoc clDoc = null;
    FunctionDoc fnDoc = null;
@@ -617,16 +610,14 @@ static char * ReadDoc(Module module, DocumentationType type, void * object, Docu
       if(eClass_IsDerived(doc._class, class(ClassDoc)))
       {
          clDoc = (ClassDoc)doc;
-         docRetrieved = true;
       }
       else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
       {
          nsDoc = (NamespaceDoc)doc;
-         docRetrieved = true;
       }
    }
 
-   if(docRetrieved)
+   if(clDoc || nsDoc)
    {
       ItemDoc itDoc = null;
       if(type == functionDoc)
@@ -692,20 +683,9 @@ static char * ReadDoc(Module module, DocumentationType type, void * object, Docu
          case parameter:
             if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters))
             {
-               Type prev;
-               char * name;
-               for(prev = data; prev; prev = prev.prev);
-               name = ((Type)data).name;
-               if(type == functionDoc)
-               {
-                  itDoc = fnDoc.parameters[name];
-                  if(itDoc) s = itDoc.description;
-               }
-               else if(type == methodDoc)
-               {
-                  itDoc = mdDoc.parameters[name];
-                  if(itDoc) s = itDoc.description;
-               }
+               char * name = ((Type)data).name;
+               itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ;
+               if(itDoc) s = itDoc.description;
             }
             break;
       }
@@ -714,20 +694,17 @@ static char * ReadDoc(Module module, DocumentationType type, void * object, Docu
    }
    if(editing && !contents && !readOnly)
       contents = CopyString($"[Add Text]");
+   delete doc;
    return contents;
 }
-
+               // The filePath is returned!
 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
 {
    ItemDoc doc = null;
-   bool docRetrieved = false;
-   File f;
-   NamespaceDoc nsDoc = null;
-   ClassDoc clDoc = null;
-
-   char docPath[MAX_LOCATION];
    Class cl = null;
    Method method = null;
+   DocCacheEntry entry;
+   Time now;
 
    switch(type)
    {
@@ -737,72 +714,49 @@ ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * ob
 
    FigureFilePath(filePath, module, type, object, item, data);
 
-   if(docCache[filePath])
-   {
-      DocCacheEntry entry = docCache[docPath];
-      if(cl && eClass_IsDerived(entry.doc._class, class(ClassDoc)))
-      {
-         clDoc = (ClassDoc)entry.doc;
-         docRetrieved = true;
-      }
-      else if(!cl && eClass_IsDerived(entry.doc._class, class(NamespaceDoc)))
-      {
-         nsDoc = (NamespaceDoc)entry.doc;
-         docRetrieved = true;
-      }
-   }
+   entry = docCache[filePath];
+   if(entry)
+      doc = entry.doc;
 
-   if(!docRetrieved)
+   if(!doc)
    {
-      f = FileOpen(filePath, read);
+      File f = FileOpen(filePath, read);
       if(f)
       {
-         JSONParser parser { f = f, eCON = true };
-         JSONResult jsonResult;
-         jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), cl ? &clDoc : &nsDoc);
+         ECONParser parser { f = f };
+         JSONResult jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
          delete parser;
          delete f;
 
-         if(jsonResult == success)
-         {
-            docRetrieved = true;
-            docCache[docPath] = { added = GetTime(), doc = cl ? clDoc : nsDoc };
-         }
-         else
+         if(jsonResult != success)
          {
             PrintLn("error: problem parsing file: ", filePath);
-            delete clDoc;
-            delete nsDoc;
+            delete doc;
          }
       }
+      if(!doc)
+         doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
    }
 
-   if(!docRetrieved)
-   {
-      if(cl)
-         clDoc = { };
-      else
-         nsDoc = { };
-      doc = cl ? clDoc : nsDoc;
-      docCache[docPath] = { added = GetTime(), doc = cl ? clDoc : nsDoc };
-      docRetrieved = true;
-   }
+   incref doc;    // Reference to return
+
+   now = GetTime();
+   // Add to the cache
+   if(entry)
+      entry.timeStamp = now;
    else
    {
-      doc = cl ? clDoc : nsDoc;
+      docCache[filePath] = { now, doc };
+      incref doc; // Reference for the cache
    }
 
    //void pruneDocCache()
+   // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
    {
-      MapIterator<const String, DocCacheEntry> it { map = docCache };
+      MapIterator<String, DocCacheEntry> it { map = docCache };
       Array<const String> toRemove { };
-      Time now = GetTime();
-      for(entry : docCache)
-      {
-         Time diff = now - entry.added;
-         if(diff > 60*0.5)
-            toRemove.Add(&entry);
-      }
+      for(entry : docCache; now - entry.timeStamp > 30)
+         toRemove.Add(&entry);
       while(toRemove.count)
       {
          if(it.Index(toRemove.lastIterator.data, false))
@@ -876,17 +830,18 @@ class APIPageNameSpace : APIPage
          char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
          if(desc)
          {
-            f.Printf($"<H3>Description</H3><br><br>\n");
+            f.Printf($"<H3>Description</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
                FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
                f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
                f.Puts(desc);
-               f.Printf("</a><br><br>");
+               f.Printf("</a>");
             }
             else
-               f.Printf("%s<br><br>", desc);
+               f.Printf("%s", desc);
+            f.Printf("<br><br><br>");
             delete desc;
          }
       }
@@ -899,7 +854,7 @@ class APIPageNameSpace : APIPage
             char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
             if(first)
             {
-               f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
+               f.Printf($"<H3>Sub Namespaces</H3><BR>\n");
                f.Printf("<TABLE>\n");
                first = false;
             }
@@ -922,7 +877,7 @@ class APIPageNameSpace : APIPage
             f.Printf("</TR><br>\n");
          }
          if(!first)
-            f.Printf("</TABLE><br>\n");
+            f.Printf("</TABLE><br><br>\n");
       }
 
       if(nameSpace->classes.first)
@@ -931,13 +886,13 @@ class APIPageNameSpace : APIPage
          for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
          {
             Class cl = link.data;
-            if(!cl.templateClass)
+            if(!cl.templateClass && !cl.internalDecl)
             {
                char * desc = ReadDoc(module, classDoc, cl, description, null);
 
                if(first)
                {
-                  f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
+                  f.Printf($"<a name=Classes></a><H3>Classes</H3><BR>\n");
                   f.Printf("<TABLE>\n");
                   first = false;
                }
@@ -963,7 +918,7 @@ class APIPageNameSpace : APIPage
             }
          }
          if(!first)
-            f.Printf("</TABLE><br>\n");
+            f.Printf("</TABLE><br><br>\n");
       }
 
       if(nameSpace->functions.first)
@@ -977,7 +932,7 @@ class APIPageNameSpace : APIPage
             if(name) name += 2; else name = function.name;
             if(first)
             {
-               f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
+               f.Printf($"<a name=Functions></a><H3>Functions</H3><BR>\n");
                f.Printf("<TABLE>\n");
                first = false;
             }
@@ -1000,7 +955,7 @@ class APIPageNameSpace : APIPage
             f.Printf("</TR><br>\n");
          }
          if(!first)
-            f.Printf("</TABLE><br>\n");
+            f.Printf("</TABLE><br><br>\n");
       }
 
       if(nameSpace->defines.first)
@@ -1012,7 +967,7 @@ class APIPageNameSpace : APIPage
             char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
             if(first)
             {
-               f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
+               f.Printf($"<a name=Definitions></a><H3>Definitions</H3><BR>\n");
                f.Printf("<TABLE>\n");
                first = false;
             }
@@ -1036,7 +991,7 @@ class APIPageNameSpace : APIPage
             f.Printf("</TR><br>\n");
          }
          if(!first)
-            f.Printf("</TABLE><br>\n");
+            f.Printf("</TABLE><br><br>\n");
       }
 
       f.Printf("</FONT></BODY></HTML>\n");
@@ -1130,17 +1085,18 @@ class APIPageClass : APIPage
          char * desc = ReadDoc(module, classDoc, cl, description, null);
          if(desc)
          {
-            f.Printf($"<br><H3>Description</H3><br><br>\n");
+            f.Printf($"<br><H3>Description</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
                FigureFileName(fileName, module, classDoc, cl, description, null);
                f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
                f.Puts(desc);
-               f.Printf("</a><br><br>");
+               f.Printf("</a>");
             }
             else
-               f.Printf("%s<br><br>", desc);
+               f.Printf("%s", desc);
+            f.Printf("<br><br><br>");
             delete desc;
          }
       }
@@ -1152,7 +1108,7 @@ class APIPageClass : APIPage
          {
             NamedLink item;
 
-            f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
+            f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><BR>\n");
             f.Printf("<TABLE>\n");
 
             for(item = enumeration.values.first; item; item = item.next)
@@ -1221,7 +1177,7 @@ class APIPageClass : APIPage
 
       if(cl.conversions.first)
       {
-         f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
+         f.Printf($"<a name=Conversions></a><H3>Conversions</H3><BR>\n");
          f.Printf("<TABLE>\n");
          for(prop = cl.conversions.first; prop; prop = prop.next)
          {
@@ -1259,7 +1215,7 @@ class APIPageClass : APIPage
                FreeType(type);
             }
          }
-         f.Printf("</TABLE><br>\n");
+         f.Printf("</TABLE><br><br>\n");
       }
 
       if(cl.membersAndProperties.first)
@@ -1271,7 +1227,7 @@ class APIPageClass : APIPage
             {
                if(first)
                {
-                  f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
+                  f.Printf($"<a name=Members></a><H3>Properties and Members</H3><BR>\n");
                   f.Printf("<TABLE>\n");
                   first = false;
                }
@@ -1311,7 +1267,7 @@ class APIPageClass : APIPage
             }
          }
          if(!first)
-            f.Printf("</TABLE><br>\n");
+            f.Printf("</TABLE><br><br>\n");
       }
 
       if(cl.methods.first)
@@ -1325,7 +1281,7 @@ class APIPageClass : APIPage
                char * desc = ReadDoc(module, methodDoc, method, description, null);
                if(first)
                {
-                  f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
+                  f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><BR>\n");
                   f.Printf("<TABLE>\n");
                   first = false;
                }
@@ -1352,7 +1308,7 @@ class APIPageClass : APIPage
             }
          }
          if(!first)
-            f.Printf("</TABLE><br>\n");
+            f.Printf("</TABLE><br><br>\n");
 
          // Non-Virtual Methods
          first = true;
@@ -1363,7 +1319,7 @@ class APIPageClass : APIPage
                char * desc = ReadDoc(module, methodDoc, method, description, null);
                if(first)
                {
-                  f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
+                  f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><BR>\n");
                   f.Printf("<TABLE>\n");
                   first = false;
                }
@@ -1392,13 +1348,13 @@ class APIPageClass : APIPage
             }
          }
          if(!first)
-            f.Printf("</TABLE><br>\n");
+            f.Printf("</TABLE><br><br>\n");
       }
       {
          char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
          if(usageDoc)
          {
-            f.Printf($"<H3>Usage</H3><br>\n");
+            f.Printf($"<H3>Usage</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1409,7 +1365,7 @@ class APIPageClass : APIPage
             }
             else
                f.Printf("<br>%s\n", usageDoc);
-            f.Printf("<br><br>\n");
+            f.Printf("<br><br><br>\n");
             delete usageDoc;
          }
       }
@@ -1417,7 +1373,7 @@ class APIPageClass : APIPage
          char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
          if(exampleDoc)
          {
-            f.Printf($"<H3>Example</H3><br>\n");
+            f.Printf($"<H3>Example</H3><BR>\n");
             f.Printf($"<FONT face=\"Courier New\">\n");
             f.Printf("<br><TABLE>\n");
             if(editing)
@@ -1432,7 +1388,7 @@ class APIPageClass : APIPage
                f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc);   // bgcolor=#CFC9C0
 
             f.Printf("</TABLE></FONT>\n");
-            f.Printf("<br>\n");
+            f.Printf("<br><br>\n");
             delete exampleDoc;
          }
       }
@@ -1441,7 +1397,7 @@ class APIPageClass : APIPage
 
          if(remarksDoc)
          {
-            f.Printf($"<H3>Remarks</H3><br>\n");
+            f.Printf($"<H3>Remarks</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1452,7 +1408,7 @@ class APIPageClass : APIPage
             }
             else
                f.Printf("<br>%s\n", remarksDoc);
-            f.Printf("<br><br>\n");
+            f.Printf("<br><br><br>\n");
             delete remarksDoc;
          }
       }
@@ -1469,8 +1425,7 @@ class APIPageClass : APIPage
             {
                if(first)
                {
-                  f.Printf($"<H3>Derived Classes</H3><br>\n");
-                  f.Printf("<br>");
+                  f.Printf($"<H3>Derived Classes</H3><BR>\n");
                   first = false;
                }
                else
@@ -1485,7 +1440,7 @@ class APIPageClass : APIPage
          char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
          if(seeAlsoDoc)
          {
-            f.Printf($"<H3>See Also</H3><br>\n");
+            f.Printf($"<H3>See Also</H3>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1564,7 +1519,7 @@ class APIPageMethod : APIPage
          char * desc = ReadDoc(module, methodDoc, method, description, null);
          if(desc)
          {
-            f.Printf($"<br><br><H3>Description</H3><br><br>\n");
+            f.Printf($"<br><br><H3>Description</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1575,6 +1530,7 @@ class APIPageMethod : APIPage
             }
             else
                f.Printf("%s", desc);
+            f.Printf("<BR><BR>");
             delete desc;
          }
       }
@@ -1582,7 +1538,7 @@ class APIPageMethod : APIPage
       f.Printf("<br><br>\n");
       if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
       {
-         f.Printf($"<H3>Parameters</H3><br><br>\n");
+         f.Printf($"<H3>Parameters</H3><BR>\n");
       }
       if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
          (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
@@ -1658,7 +1614,7 @@ class APIPageMethod : APIPage
          char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
          if(usageDoc)
          {
-            f.Printf($"<H3>Usage</H3><br>\n");
+            f.Printf($"<H3>Usage</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1669,7 +1625,7 @@ class APIPageMethod : APIPage
             }
             else
                f.Printf("<br>%s\n", usageDoc);
-            f.Printf("<br><br>\n");
+            f.Printf("<br><br><br>\n");
             delete usageDoc;
          }
       }
@@ -1677,7 +1633,7 @@ class APIPageMethod : APIPage
          char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
          if(exampleDoc)
          {
-            f.Printf($"<H3>Example</H3><br>\n");
+            f.Printf($"<H3>Example</H3><BR>\n");
             f.Printf($"<FONT face=\"Courier New\">\n");
             f.Printf("<br><TABLE>\n");
             if(editing)
@@ -1691,7 +1647,7 @@ class APIPageMethod : APIPage
             else
                f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc);   // bgcolor=#CFC9C0
             f.Printf("</TABLE></FONT>\n");
-            f.Printf("<br>\n");
+            f.Printf("<br><br>\n");
             delete exampleDoc;
          }
       }
@@ -1699,7 +1655,7 @@ class APIPageMethod : APIPage
          char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
          if(remarksDoc)
          {
-            f.Printf($"<H3>Remarks</H3><br>\n");
+            f.Printf($"<H3>Remarks</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1710,7 +1666,7 @@ class APIPageMethod : APIPage
             }
             else
                f.Printf("<br>%s\n", method, remarksDoc);
-            f.Printf("<br><br>\n");
+            f.Printf("<br><br><br>\n");
             delete remarksDoc;
          }
       }
@@ -1718,7 +1674,7 @@ class APIPageMethod : APIPage
          char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
          if(seeAlsoDoc)
          {
-            f.Printf($"<H3>See Also</H3><br>\n");
+            f.Printf($"<H3>See Also</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1730,7 +1686,7 @@ class APIPageMethod : APIPage
             else
                f.Printf("<br>%s\n", method, seeAlsoDoc);
 
-            f.Printf("<br><br>\n");
+            f.Printf("<br><br><br>\n");
             delete seeAlsoDoc;
          }
       }
@@ -1797,7 +1753,7 @@ class APIPageFunction : APIPage
          char * desc = ReadDoc(module, functionDoc, function, description, null);
          if(desc)
          {
-            f.Printf($"<br><br><H3>Description</H3><br><br>\n");
+            f.Printf($"<br><br><H3>Description</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1809,12 +1765,13 @@ class APIPageFunction : APIPage
             else
                f.Printf("%s", desc);
             delete desc;
+            f.Printf("<BR><BR>");
          }
       }
       f.Printf("<br><br>\n");
       if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
       {
-         f.Printf($"<H3>Parameters</H3><br><br>\n");
+         f.Printf($"<H3>Parameters</H3><BR>\n");
       }
       if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
          (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
@@ -1890,7 +1847,7 @@ class APIPageFunction : APIPage
          char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
          if(usageDoc)
          {
-            f.Printf($"<H3>Usage</H3><br>\n");
+            f.Printf($"<H3>Usage</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1901,7 +1858,7 @@ class APIPageFunction : APIPage
             }
             else
                f.Printf("<br>%s\n", usageDoc);
-            f.Printf("<br><br>\n");
+            f.Printf("<br><br><br>\n");
             delete usageDoc;
          }
       }
@@ -1909,7 +1866,7 @@ class APIPageFunction : APIPage
          char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
          if(exampleDoc)
          {
-            f.Printf($"<H3>Example</H3><br>\n");
+            f.Printf($"<H3>Example</H3><BR>\n");
             f.Printf($"<FONT face=\"Courier New\">\n");
             f.Printf("<br><TABLE>\n");
             if(editing)
@@ -1923,7 +1880,7 @@ class APIPageFunction : APIPage
             else
                f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc);   // bgcolor=#CFC9C0
             f.Printf("</TABLE></FONT>\n");
-            f.Printf("<br>\n");
+            f.Printf("<br><br>\n");
             delete exampleDoc;
          }
       }
@@ -1931,7 +1888,7 @@ class APIPageFunction : APIPage
          char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
          if(remarksDoc)
          {
-            f.Printf($"<H3>Remarks</H3><br>\n");
+            f.Printf($"<H3>Remarks</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1942,7 +1899,7 @@ class APIPageFunction : APIPage
             }
             else
                f.Printf("<br>%s\n", remarksDoc);
-            f.Printf("<br><br>\n");
+            f.Printf("<br><br><br>\n");
             delete remarksDoc;
          }
       }
@@ -1950,7 +1907,7 @@ class APIPageFunction : APIPage
          char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
          if(seeAlsoDoc)
          {
-            f.Printf($"<H3>See Also</H3><br>\n");
+            f.Printf($"<H3>See Also</H3><BR>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1961,7 +1918,7 @@ class APIPageFunction : APIPage
             }
             else
                f.Printf("<br>%s\n", seeAlsoDoc);
-            f.Printf("<br><br>\n");
+            f.Printf("<br><br><br>\n");
             delete seeAlsoDoc;
          }
       }
@@ -2028,7 +1985,7 @@ static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpa
             for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
             {
                cl = link.data;
-               if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
+               if(!cl.templateClass && !cl.internalDecl && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
                {
                   if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
                   AddClass(classesRow, module, cl, nsName, showPrivate);
@@ -2417,6 +2374,7 @@ class MainForm : Window
       static char symbolsDir[MAX_LOCATION];
 
       history.size = 0;
+      modulesAdded.RemoveAll();
 
       FreeContext(globalContext);
       FreeExcludedSymbols(excludedSymbols);
@@ -2673,7 +2631,7 @@ class HelpView : HTMLView
          {
             char docDir[MAX_LOCATION];
             readOnly = true;
-            strcpy(docDir, settings.docDir);
+            strcpy(docDir, ideSettings.docDir);
             if(FileExists(docDir).isDirectory)
             {
                PathCatSlash(docDir, "___docWriteTest");
@@ -2742,8 +2700,9 @@ class HelpView : HTMLView
          f.Read(contents, 1, len);
          contents[len] = '\0';
       }
-      if(!empty && contents)
+
       {
+         char docPath[MAX_LOCATION];
          char temp[MAX_LOCATION];
          char part[MAX_FILENAME];
          Module module;
@@ -2752,12 +2711,10 @@ class HelpView : HTMLView
          DocumentationType type;
          DocumentationItem item;
          ItemDoc doc;
-         bool docRetrieved = false;
          NamespaceDoc nsDoc = null;
          ClassDoc clDoc = null;
          FunctionDoc fnDoc = null;
          MethodDoc mdDoc = null;
-         //char filePath[MAX_LOCATION];
          Class cl = null;
          Method method = null;
          GlobalFunction function = null;
@@ -2804,17 +2761,17 @@ class HelpView : HTMLView
          else if(!strcmp(part, "returnValue"))
             item = returnValue;
 
-         doc = getDoc(temp, module, type, object, item, data, true);
+         doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
 
+         /* Why invalidate this entry here?
          {
             MapIterator<const String, DocCacheEntry> it { map = docCache };
-            if(it.Index(temp, false))
+            if(it.Index(docPath, false))
             {
-               it.data.doc = null;
                delete it.data;
                it.Remove();
             }
-         }
+         }*/
 
          switch(type)
          {
@@ -2823,200 +2780,266 @@ class HelpView : HTMLView
             case methodDoc:    method = object; cl = method._class; break;
          }
 
-         if(eClass_IsDerived(doc._class, class(ClassDoc)))
-         {
-            clDoc = (ClassDoc)doc;
-            docRetrieved = true;
-         }
-         else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
+         if(doc)
          {
-            nsDoc = (NamespaceDoc)doc;
-            docRetrieved = true;
+            if(eClass_IsDerived(doc._class, class(ClassDoc)))
+            {
+               clDoc = (ClassDoc)doc;
+            }
+            else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
+            {
+               nsDoc = (NamespaceDoc)doc;
+            }
          }
 
-         if(docRetrieved)
+         if(clDoc || nsDoc)
          {
             if(type == functionDoc)
             {
                const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
                if(name) name += 2; else name = function.name;
-               if(!nsDoc.functions) nsDoc.functions = { };
-               fnDoc = nsDoc.functions[name];
-               if(!fnDoc)
+               fnDoc = nsDoc.functions ? nsDoc.functions[name] : null;
+               if(!empty && !fnDoc)
                {
-                  fnDoc = { };
-                  nsDoc.functions[name] = fnDoc;
+                  if(!nsDoc.functions) nsDoc.functions = { };
+                  nsDoc.functions[name] = fnDoc = { };
                }
             }
             else if(type == methodDoc)
             {
-               if(!clDoc.methods) clDoc.methods = { };
-               mdDoc = clDoc.methods[method.name];
-               if(!mdDoc)
+               mdDoc = clDoc.methods ? clDoc.methods[method.name] : null;
+               if(!empty && !mdDoc)
                {
-                  mdDoc = { };
-                  clDoc.methods[method.name] = mdDoc;
+                  if(!clDoc.methods && !empty) clDoc.methods = { };
+                  clDoc.methods[method.name] = mdDoc = { };
                }
             }
 
-            switch(item)
+            if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
             {
-               case description:
-                  if(type == methodDoc) { mdDoc.description = contents; contents = null; }
-                  else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
-                  else if(type == classDoc) { clDoc.description = contents; contents = null; }
-                  else { nsDoc.description = contents; contents = null; }
-                  break;
-               case usage:
-                  if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
-                  else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
-                  else if(type == classDoc) { clDoc.usage = contents; contents = null; }
-                  break;
-               case remarks:
-                  if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
-                  else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
-                  else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
-                  break;
-               case example:
-                  if(type == methodDoc) { mdDoc.example = contents; contents = null; }
-                  else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
-                  else if(type == classDoc) { clDoc.example = contents; contents = null; }
-                  break;
-               case seeAlso:
-                  if(type == methodDoc) { mdDoc.also = contents; contents = null; }
-                  else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
-                  else if(type == classDoc) { clDoc.also = contents; contents = null; }
-                  break;
-               case returnValue:
-                  if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
-                  else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
-                  break;
-               case enumerationValue:
+               switch(item)
                {
-                  ValueDoc itDoc;
-                  if(!clDoc.values) clDoc.values = { };
-                  itDoc = clDoc.values[((NamedLink)data).name];
-                  if(!itDoc)
-                  {
-                     itDoc = { };
-                     clDoc.values[((NamedLink)data).name] = itDoc;
-                  }
-                  itDoc.description = contents; contents = null;
-                  break;
-               }
-               case definition:
-               {
-                  DefineDoc itDoc;
-                  if(!nsDoc.defines) nsDoc.defines = { };
-                  itDoc = nsDoc.defines[((Definition)data).name];
-                  if(!itDoc)
+                  case description:
+                     if(type == methodDoc) { mdDoc.description = contents; contents = null; }
+                     else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
+                     else if(type == classDoc) { clDoc.description = contents; contents = null; }
+                     else { nsDoc.description = contents; contents = null; }
+                     break;
+                  case usage:
+                     if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
+                     else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
+                     else if(type == classDoc) { clDoc.usage = contents; contents = null; }
+                     break;
+                  case remarks:
+                     if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
+                     else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
+                     else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
+                     break;
+                  case example:
+                     if(type == methodDoc) { mdDoc.example = contents; contents = null; }
+                     else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
+                     else if(type == classDoc) { clDoc.example = contents; contents = null; }
+                     break;
+                  case seeAlso:
+                     if(type == methodDoc) { mdDoc.also = contents; contents = null; }
+                     else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
+                     else if(type == classDoc) { clDoc.also = contents; contents = null; }
+                     break;
+                  case returnValue:
+                     if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
+                     else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
+                     break;
+                  case enumerationValue:
                   {
-                     itDoc = { };
-                     nsDoc.defines[((Definition)data).name] = itDoc;
+                     ValueDoc itDoc = clDoc.values ? clDoc.values[((NamedLink)data).name] : null;
+                     if(!empty || itDoc)
+                     {
+                        if(!empty && !itDoc)
+                        {
+                           if(!clDoc.values) clDoc.values = { };
+                           clDoc.values[((NamedLink)data).name] = itDoc = { };
+                        }
+                        itDoc.description = contents; contents = null;
+                        if(itDoc.isEmpty)
+                        {
+                           MapIterator<String, ValueDoc> it { map = clDoc.values };
+                           if(it.Index(((NamedLink)data).name, false))
+                              it.Remove();
+                           delete itDoc;
+                        }
+                     }
+                     break;
                   }
-                  itDoc.description = contents; contents = null;
-                  break;
-               }
-               case conversion:
-               {
-                  ConversionDoc itDoc;
-                  const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
-                  if(name) name += 2; else name = ((Property)data).name;
-                  if(!clDoc.conversions) clDoc.conversions = { };
-                  itDoc = clDoc.conversions[name];
-                  if(!itDoc)
+                  case definition:
                   {
-                     itDoc = { };
-                     clDoc.conversions[name] = itDoc;
+                     DefineDoc itDoc = nsDoc.defines ? nsDoc.defines[((Definition)data).name] : null;
+                     if(!empty || itDoc)
+                     {
+                        if(!empty && !itDoc)
+                        {
+                           if(!nsDoc.defines) nsDoc.defines = { };
+                           nsDoc.defines[((Definition)data).name] = itDoc = { };
+                        }
+                        itDoc.description = contents; contents = null;
+                        if(itDoc.isEmpty)
+                        {
+                           MapIterator<String, DefineDoc> it { map = nsDoc.defines };
+                           if(it.Index(((Definition)data).name, false))
+                              it.Remove();
+                           delete itDoc;
+                        }
+                     }
+                     break;
                   }
-                  itDoc.description = contents; contents = null;
-                  break;
-               }
-               case memberDescription:
-               {
-                  FieldDoc itDoc;
-                  if(!clDoc.fields) clDoc.fields = { };
-                  itDoc = clDoc.fields[((DataMember)data).name];
-                  if(!itDoc)
+                  case conversion:
                   {
-                     itDoc = { };
-                     clDoc.fields[((DataMember)data).name] = itDoc;
+                     ConversionDoc itDoc;
+                     const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
+                     if(name) name += 2; else name = ((Property)data).name;
+                     itDoc = clDoc.conversions ? clDoc.conversions[name] : null;
+                     if(!empty || itDoc)
+                     {
+                        if(!empty && !itDoc)
+                        {
+                           if(!clDoc.conversions) clDoc.conversions = { };
+                           clDoc.conversions[name] = itDoc = { };
+                        }
+                        itDoc.description = contents; contents = null;
+                        if(itDoc.isEmpty)
+                        {
+                           MapIterator<String, ConversionDoc> it { map = clDoc.conversions };
+                           if(it.Index(name, false))
+                              it.Remove();
+                           delete itDoc;
+                        }
+                     }
+                     break;
                   }
-                  itDoc.description = contents; contents = null;
-                  break;
-               }
-               case propertyDescription:
-               {
-                  PropertyDoc itDoc;
-                  if(!clDoc.properties) clDoc.properties = { };
-                  itDoc = clDoc.properties[((Property)data).name];
-                  if(!itDoc)
+                  case memberDescription:
                   {
-                     itDoc = { };
-                     clDoc.properties[((Property)data).name] = itDoc;
+                     FieldDoc itDoc = clDoc.fields ? clDoc.fields[((DataMember)data).name] : null;
+                     if(!empty || itDoc)
+                     {
+                        if(!empty && !itDoc)
+                        {
+                           if(!clDoc.fields) clDoc.fields = { };
+                           clDoc.fields[((DataMember)data).name] = itDoc = { };
+                        }
+                        itDoc.description = contents; contents = null;
+                        if(itDoc.isEmpty)
+                        {
+                           MapIterator<String, FieldDoc> it { map = clDoc.fields };
+                           if(it.Index(((DataMember)data).name, false))
+                              it.Remove();
+                           delete itDoc;
+                        }
+                     }
+                     break;
                   }
-                  itDoc.description = contents; contents = null;
-                  break;
-               }
-               case parameter:
-               {
-                  ParameterDoc itDoc;
-                  char * name;
-                  Type prev;
-                  for(prev = data; prev; prev = prev.prev);
-                  name = ((Type)data).name;
-                  if(type == functionDoc)
+                  case propertyDescription:
                   {
-                     if(!fnDoc.parameters) fnDoc.parameters = { };
-                     itDoc = fnDoc.parameters[name];
-                     if(!itDoc)
+                     PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null;
+                     if(!empty || itDoc)
                      {
-                        itDoc = { };
-                        fnDoc.parameters[name] = itDoc;
+                        if(!empty && !itDoc)
+                        {
+                           if(!clDoc.properties) clDoc.properties = { };
+                           clDoc.properties[((Property)data).name] = itDoc = { };
+                        }
+                        itDoc.description = contents, contents = null;
+                        if(itDoc.isEmpty)
+                        {
+                           MapIterator<String, PropertyDoc> it { map = clDoc.properties };
+                           if(it.Index(((Property)data).name, false))
+                              it.Remove();
+                           delete itDoc;
+                        }
                      }
-                     itDoc.description = contents; contents = null;
+                     break;
                   }
-                  else if(type == methodDoc)
+                  case parameter:
                   {
-                     if(!mdDoc.parameters) mdDoc.parameters = { };
-                     itDoc = mdDoc.parameters[name];
-                     if(!itDoc)
+                     if(type == functionDoc || type == methodDoc)
                      {
-                        itDoc = { };
-                        mdDoc.parameters[name] = itDoc;
+                        Map<String, ParameterDoc> * parameters = (type == functionDoc) ? &fnDoc.parameters : &mdDoc.parameters;
+                        char * name = ((Type)data).name;
+                        ParameterDoc itDoc = *parameters ? (*parameters)[name] : null;
+                        int position = 0;
+                        Type prev = data;
+                        while(prev) position++, prev = prev.prev;
+
+                        if(!empty || itDoc)
+                        {
+                           if(!empty && !itDoc)
+                           {
+                              if(!*parameters) *parameters = { };
+                              (*parameters)[name] = itDoc = { };
+                           }
+                           itDoc.description = contents; contents = null;
+                           itDoc.position = position;
+                           if(itDoc.isEmpty)
+                           {
+                              MapIterator<String, ParameterDoc> it { map = *parameters };
+                              if(it.Index(((Type)data).name, false))
+                                 it.Remove();
+                              delete itDoc;
+                           }
+                        }
                      }
-                     itDoc.description = contents; contents = null;
+                     break;
                   }
-                  break;
                }
             }
          }
 
+         if(type == functionDoc && fnDoc && fnDoc.isEmpty)
+         {
+            MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
+            const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
+            if(name) name += 2; else name = function.name;
+            if(it.Index(name, false))
+               it.Remove();
+            delete fnDoc;
+         }
+         else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
+         {
+            MapIterator<String, MethodDoc> it { map = clDoc.methods };
+            if(it.Index(method.name, false))
+               it.Remove();
+            delete mdDoc;
+         }
+         if(nsDoc)
+         {
+            if(nsDoc.functions && !nsDoc.functions.count) delete nsDoc.functions;
+            if(nsDoc.defines && !nsDoc.defines.count) delete nsDoc.defines;
+         }
+         if(clDoc)
+         {
+            if(clDoc && clDoc.conversions && !clDoc.conversions.count) delete clDoc.conversions;
+            if(clDoc && clDoc.properties && !clDoc.properties.count) delete clDoc.properties;
+            if(clDoc && clDoc.fields && !clDoc.fields.count) delete clDoc.fields;
+            if(clDoc && clDoc.methods && !clDoc.methods.count) delete clDoc.methods;
+            if(clDoc && clDoc.values && !clDoc.values.count) delete clDoc.values;
+         }
+
+         if(clDoc || nsDoc)
          {
-            File f;
-            char filePath[MAX_LOCATION];
             char dirPath[MAX_LOCATION];
-            strcpy(filePath, temp);
-            StripLastDirectory(filePath, dirPath);
-            if(FileExists(filePath))
-               DeleteFile(filePath);
-            if(cl ? !clDoc.isEmpty : !nsDoc.isEmpty)
+            StripLastDirectory(docPath, dirPath);
+            if(FileExists(docPath))
+               DeleteFile(docPath);
+            if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
             {
+               File f;
                if(!FileExists(dirPath))
                   MakeDir(dirPath);
-               f = FileOpen(filePath, write);
-               if(f)
+               if((f = FileOpen(docPath, write)))
                {
-                  if(cl)
-                     WriteECONObject(f, class(ClassDoc), clDoc, 0);
-                  else
-                     WriteECONObject(f, class(NamespaceDoc), nsDoc, 0);
+                  WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
                   delete f;
                }
                else
-               {
-                  PrintLn("error: writeClassDocFile -- problem opening file: ", filePath);
-               }
+                  PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
             }
          }
          delete doc;
@@ -4326,9 +4349,9 @@ class Documentor : GuiApplication
 
       SetGlobalData(globalData);
 
-      settingsContainer.dataOwner = &settings;
+      settingsContainer.dataOwner = &ideSettings;
       settingsContainer.Load();
-      if(!settings.docDir || !settings.docDir[0] )
+      if(!ideSettings.docDir || !ideSettings.docDir[0] )
       {
          if(os == win32) // if Windows OS then
          {
@@ -4342,23 +4365,23 @@ class Documentor : GuiApplication
             if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
             {
                PathCat(programFilesDir, "ECERE SDK\\doc");
-               settings.docDir = programFilesDir;
+               ideSettings.docDir = programFilesDir;
             }
             else if(homeDrive[0])
             {
                PathCat(homeDrive, "ECERE SDK\\doc");
-               settings.docDir = homeDrive;
+               ideSettings.docDir = homeDrive;
             }
             else if(winDir[0])
             {
                PathCat(winDir, "..\\ECERE SDK\\doc");
-               settings.docDir = winDir;
+               ideSettings.docDir = winDir;
             }
             else
-               settings.docDir = "C:\\ECERE SDK\\doc";
+               ideSettings.docDir = "C:\\ECERE SDK\\doc";
          }
          else // if Os is Linux, or Mac OSX or something else
-            settings.docDir = "/usr/share/ecere/doc/";
+            ideSettings.docDir = "/usr/share/ecere/doc/";
          settingsContainer.Save();
       }
 
@@ -4618,9 +4641,10 @@ char * getDocFileNameFromTypeName(const char * typeName)
    return docFileName;
 }
 
-class DocCacheEntry
+class DocCacheEntry //: struct      // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
 {
-   Time added;
+public:
+   Time timeStamp;      // Should this be last accessed, or last retrieved?
    ItemDoc doc;
 
    ~DocCacheEntry()
@@ -4629,4 +4653,4 @@ class DocCacheEntry
    }
 }
 
-Map<const String, DocCacheEntry> docCache { };
+Map<String, DocCacheEntry> docCache { };