X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=documentor%2Fsrc%2FDocumentor.ec;h=7dfc77e367c0be86ad8b08a76354a1800c0be4b4;hb=12cb9288a539df89d4b4e7bdb21cd78da2cd10e3;hp=21959e3c866a86a77310c4d3485753a4ab8dd3e3;hpb=331c2ad06c24a2a037e9495122ea5a2410c83ece;p=sdk diff --git a/documentor/src/Documentor.ec b/documentor/src/Documentor.ec index 21959e3..7dfc77e 100644 --- a/documentor/src/Documentor.ec +++ b/documentor/src/Documentor.ec @@ -1,9 +1,18 @@ import "ecere" +#if !defined(EAR_TO_ECON_ECDOC) import "ec" import "HTMLView" import "IDESettings" import "SettingsDialog" +IDESettings ideSettings; + +IDESettingsContainer settingsContainer +{ + dataOwner = &ideSettings; + dataClass = class(IDESettings); +}; + static Context globalContext { }; static OldList defines { }; static OldList imports { }; @@ -45,15 +54,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; @@ -77,9 +77,11 @@ void GetTemplateString(Class c, char * templateString) Class pc; char * d = templateString + strlen(templateString); curName[len] = 0; + TrimLSpaces(curName, curName); + TrimRSpaces(curName, curName); pc = eSystem_FindClass(m, curName); if(pc) - sprintf(d, "%s", pc, pc.name); + sprintf(d, "%s%s", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name); else strcat(d, curName); } @@ -100,7 +102,7 @@ void GetTemplateString(Class c, char * templateString) strcat(templateString, curName); len = 0; } - else if(ch != ' ') + else curName[len++] = ch; } } @@ -407,14 +409,16 @@ void DocPrintType(Type type, char * string, bool printName, bool fullName) _PrintType(type, string, printName, true, fullName); } +Map 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); @@ -427,9 +431,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); @@ -469,6 +474,7 @@ public: enum DocumentationType { + unset, nameSpaceDoc, classDoc, functionDoc, @@ -477,6 +483,7 @@ enum DocumentationType enum DocumentationItem { + unset, description, usage, remarks, @@ -493,14 +500,60 @@ enum DocumentationItem static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data) { + char hex[20]; + fileName[0] = 0; + sprintf(hex, "%p", module); + strcat(fileName, hex); + strcat(fileName, "/"); + sprintf(hex, "%p", object); + strcat(fileName, hex); + strcat(fileName, "/"); + sprintf(hex, "%p", data); + strcat(fileName, hex); + strcat(fileName, "/"); + if(type == nameSpaceDoc) + strcat(fileName, "namespace"); + else if(type == functionDoc) + strcat(fileName, "function"); + else if(type == classDoc) + strcat(fileName, "class"); + else if(type == methodDoc) + strcat(fileName, "method"); + strcat(fileName, "/"); + if(item == description) + strcat(fileName, "description"); + else if(item == usage) + strcat(fileName, "usage"); + else if(item == remarks) + strcat(fileName, "remarks"); + else if(item == example) + strcat(fileName, "example"); + else if(item == seeAlso) + strcat(fileName, "seeAlso"); + else if(item == enumerationValue) + strcat(fileName, "enumerationValue"); + else if(item == definition) + strcat(fileName, "definition"); + else if(item == conversion) + strcat(fileName, "conversion"); + else if(item == memberDescription) + strcat(fileName, "memberDescription"); + else if(item == propertyDescription) + strcat(fileName, "propertyDescription"); + else if(item == parameter) + strcat(fileName, "parameter"); + else if(item == returnValue) + strcat(fileName, "returnValue"); +} + +static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data) +{ + char docPath[MAX_LOCATION]; NameSpace * nameSpace, * ns; Class cl = null; Method method = null; GlobalFunction function = null; char nsName[1024], temp[1024]; - char docFile[1024]; - - switch(type) { case nameSpaceDoc: nameSpace = object; break; @@ -510,125 +563,221 @@ static void FigureFileName(char * fileName, Module module, DocumentationType typ } nsName[0] = 0; + temp[0] = 0; ns = nameSpace; while(ns && ns->name) { - strcpy(temp, "namespaces/"); - strcat(temp, ns->name); + strcpy(temp, ns->name); strcat(temp, "/"); strcat(temp, nsName); strcpy(nsName, temp); ns = ns->parent; } - sprintf(docFile, "%s.eCdoc", (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name); - if(strchr(docFile, DIR_SEP)) - { - GetLastDirectory(docFile, temp); - strcpy(docFile, temp); - } - - sprintf(fileName, "<%s/%s>", settings.docDir, docFile); // Note that in the ecereIDE.ini file, there can be no quotes around the path, and there needs to be the final backslash. Otherwise this does not work. - strcat(fileName, nsName); + docPath[0] = 0; + PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name); + //ChangeExtension(docPath, "eCdoc", docPath); + PathCatSlash(docPath, nsName); if(cl) { - strcat(fileName, "classes/"); - strcat(fileName, cl.name); - strcat(fileName, "/"); - } - - if(method) - { - strcat(fileName, "methods/"); - strcat(fileName, method.name); - strcat(fileName, "/"); - } - else if(function) - { - const char * name = RSearchString(function.name, "::", strlen(function.name), true, false); - if(name) name += 2; else name = function.name; - strcat(fileName, "functions/"); - strcat(fileName, name); - strcat(fileName, "/"); - } - - switch(item) - { - case description: strcat(fileName, "description"); break; - case usage: strcat(fileName, "usage"); break; - case remarks: strcat(fileName, "remarks"); break; - case example: strcat(fileName, "example"); break; - case seeAlso: strcat(fileName, "seeAlso"); break; - case returnValue: strcat(fileName, "returnValue"); break; - case enumerationValue: - strcat(fileName, "enumeration values/"); - strcat(fileName, ((NamedLink)data).name); - break; - case definition: - strcat(fileName, "definitions/"); - strcat(fileName, ((Definition)data).name); - break; - case conversion: - { - const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false); - if(name) name += 2; else name = ((Property)data).name; - strcat(fileName, "conversions/"); - strcat(fileName, name); - break; - } - case memberDescription: - strcat(fileName, "data members/"); - strcat(fileName, ((DataMember)data).name); - break; - case propertyDescription: - strcat(fileName, "properties/"); - strcat(fileName, ((Property)data).name); - break; - case parameter: - { - int count; - char name[1024]; - Type prev; - strcat(fileName, "parameters/"); - for(prev = data, count = 0; prev; prev = prev.prev, count++); - sprintf(name, "%s.%d", ((Type)data).name, count); - strcat(fileName, name); - break; - } + char * name = getDocFileNameFromTypeName(cl.name); + PathCatSlash(docPath, name); + delete name; } + else + PathCatSlash(docPath, "_global-defs"); + ChangeExtension(docPath, "econ", docPath); + + path[0] = 0; + strcpy(path, ideSettings.docDir); + PathCatSlash(path, docPath); } static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data) { - char fileName[MAX_LOCATION]; String contents = null; - File file; + NamespaceDoc nsDoc = null; + ClassDoc clDoc = null; + FunctionDoc fnDoc = null; + MethodDoc mdDoc = null; + String s = null; + char filePath[MAX_LOCATION]; + Method method = null; + GlobalFunction function = null; + + ItemDoc doc = getDoc(filePath, module, type, object, item, data, false); - FigureFileName(fileName, module, type, object, item, data); - file = FileOpen(fileName, read); - if(file) + switch(type) { - uint len; - if((len = file.GetSize())) + case functionDoc: function = object; break; + case methodDoc: method = object; break; + } + + if(doc) + { + if(eClass_IsDerived(doc._class, class(ClassDoc))) { - contents = new char[len+1]; - file.Read(contents, 1, len); - contents[len] = '\0'; + clDoc = (ClassDoc)doc; + } + else if(eClass_IsDerived(doc._class, class(NamespaceDoc))) + { + nsDoc = (NamespaceDoc)doc; } - delete file; } - if(contents) + + if(clDoc || nsDoc) { - int c; - for(c = 0; contents[c]; c++) - if(!isspace(contents[c])) break; - if(!contents[c]) - delete contents; + ItemDoc itDoc = null; + if(type == functionDoc) + { + MapIterator 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)) + fnDoc = it.data; + } + else if(type == methodDoc) + { + MapIterator it { map = clDoc.methods }; + if(it.Index(method.name, false)) + mdDoc = it.data; + } + + switch(item) + { + case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break; + case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break; + case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break; + case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break; + case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break; + case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break; + case enumerationValue: + if(clDoc && clDoc.values) + { + itDoc = clDoc.values[((NamedLink)data).name]; + if(itDoc) s = itDoc.description; + } + break; + case definition: + if(nsDoc && nsDoc.defines) + { + itDoc = nsDoc.defines[((Definition)data).name]; + if(itDoc) s = itDoc.description; + } + break; + case conversion: + if(clDoc && clDoc.conversions) + { + 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[name]; + if(itDoc) s = itDoc.description; + } + break; + case memberDescription: + if(clDoc && clDoc.fields) + { + itDoc = clDoc.fields[((DataMember)data).name]; + if(itDoc) s = itDoc.description; + } + break; + case propertyDescription: + if(clDoc && clDoc.properties) + { + itDoc = clDoc.properties[((Property)data).name]; + if(itDoc) s = itDoc.description; + } + break; + case parameter: + if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters)) + { + char * name = ((Type)data).name; + itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ; + if(itDoc) s = itDoc.description; + } + break; + } + if(s) + contents = CopyString(s); } 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; + Class cl = null; + Method method = null; + DocCacheEntry entry; + Time now; + + switch(type) + { + case classDoc: cl = (Class)object; break; + case methodDoc: method = object; cl = method._class; break; + } + + FigureFilePath(filePath, module, type, object, item, data); + + entry = docCache[filePath]; + if(entry) + doc = entry.doc; + + if(!doc) + { + File f = FileOpen(filePath, read); + if(f) + { + ECONParser parser { f = f }; + JSONResult jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc); + delete parser; + delete f; + + if(jsonResult != success) + { + PrintLn("error: problem parsing file: ", filePath); + delete doc; + } + } + if(!doc) + doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { }; + } + + incref doc; // Reference to return + + now = GetTime(); + // Add to the cache + if(entry) + entry.timeStamp = now; + else + { + 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 it { map = docCache }; + Array toRemove { }; + for(entry : docCache; now - entry.timeStamp > 30) + toRemove.Add(&entry); + while(toRemove.count) + { + if(it.Index(toRemove.lastIterator.data, false)) + { + delete it.data; + it.Remove(); + } + toRemove.Remove(toRemove.lastIterator.pointer); + } + delete toRemove; + } + return doc; +} class APIPageNameSpace : APIPage { @@ -689,17 +838,18 @@ class APIPageNameSpace : APIPage char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null); if(desc) { - f.Printf($"

Description



\n"); + f.Printf($"

Description


\n"); if(editing) { char fileName[MAX_LOCATION]; FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null); f.Printf("", fileName); f.Puts(desc); - f.Printf("

"); + f.Printf(""); } else - f.Printf("%s

", desc); + f.Printf("%s", desc); + f.Printf("


"); delete desc; } } @@ -712,7 +862,7 @@ class APIPageNameSpace : APIPage char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null); if(first) { - f.Printf($"

Sub Namespaces



\n"); + f.Printf($"

Sub Namespaces


\n"); f.Printf("\n"); first = false; } @@ -735,7 +885,7 @@ class APIPageNameSpace : APIPage f.Printf("
\n"); } if(!first) - f.Printf("

\n"); + f.Printf("

\n"); } if(nameSpace->classes.first) @@ -744,13 +894,14 @@ class APIPageNameSpace : APIPage for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next) { Class cl = link.data; - if(!cl.templateClass) + Module module = cl.module ? cl.module : this.module; + if(!cl.templateClass) // && !cl.internalDecl) { char * desc = ReadDoc(module, classDoc, cl, description, null); if(first) { - f.Printf($"

Classes



\n"); + f.Printf($"

Classes


\n"); f.Printf("\n"); first = false; } @@ -776,7 +927,7 @@ class APIPageNameSpace : APIPage } } if(!first) - f.Printf("

\n"); + f.Printf("

\n"); } if(nameSpace->functions.first) @@ -785,12 +936,13 @@ class APIPageNameSpace : APIPage for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next) { GlobalFunction function = link.data; + Module module = function.module ? function.module : this.module; char * desc = ReadDoc(module, functionDoc, function, description, null); const char * name = RSearchString(function.name, "::", strlen(function.name), true, false); if(name) name += 2; else name = function.name; if(first) { - f.Printf($"

Functions



\n"); + f.Printf($"

Functions


\n"); f.Printf("\n"); first = false; } @@ -813,7 +965,7 @@ class APIPageNameSpace : APIPage f.Printf("
\n"); } if(!first) - f.Printf("

\n"); + f.Printf("

\n"); } if(nameSpace->defines.first) @@ -825,7 +977,7 @@ class APIPageNameSpace : APIPage char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def); if(first) { - f.Printf($"

Definitions



\n"); + f.Printf($"

Definitions


\n"); f.Printf("\n"); first = false; } @@ -849,7 +1001,7 @@ class APIPageNameSpace : APIPage f.Printf("
\n"); } if(!first) - f.Printf("

\n"); + f.Printf("

\n"); } f.Printf("\n"); @@ -943,17 +1095,18 @@ class APIPageClass : APIPage char * desc = ReadDoc(module, classDoc, cl, description, null); if(desc) { - f.Printf($"

Description



\n"); + f.Printf($"

Description


\n"); if(editing) { char fileName[MAX_LOCATION]; FigureFileName(fileName, module, classDoc, cl, description, null); f.Printf("", fileName); f.Puts(desc); - f.Printf("

"); + f.Printf(""); } else - f.Printf("%s

", desc); + f.Printf("%s", desc); + f.Printf("


"); delete desc; } } @@ -965,7 +1118,7 @@ class APIPageClass : APIPage { NamedLink item; - f.Printf($"

Enumeration Values



\n"); + f.Printf($"

Enumeration Values


\n"); f.Printf("\n"); for(item = enumeration.values.first; item; item = item.next) @@ -1034,7 +1187,7 @@ class APIPageClass : APIPage if(cl.conversions.first) { - f.Printf($"

Conversions



\n"); + f.Printf($"

Conversions


\n"); f.Printf("
\n"); for(prop = cl.conversions.first; prop; prop = prop.next) { @@ -1072,7 +1225,7 @@ class APIPageClass : APIPage FreeType(type); } } - f.Printf("

\n"); + f.Printf("

\n"); } if(cl.membersAndProperties.first) @@ -1084,7 +1237,7 @@ class APIPageClass : APIPage { if(first) { - f.Printf($"

Properties and Members



\n"); + f.Printf($"

Properties and Members


\n"); f.Printf("\n"); first = false; } @@ -1124,7 +1277,7 @@ class APIPageClass : APIPage } } if(!first) - f.Printf("

\n"); + f.Printf("

\n"); } if(cl.methods.first) @@ -1138,7 +1291,7 @@ class APIPageClass : APIPage char * desc = ReadDoc(module, methodDoc, method, description, null); if(first) { - f.Printf($"

Virtual Methods



\n"); + f.Printf($"

Virtual Methods


\n"); f.Printf("\n"); first = false; } @@ -1165,7 +1318,7 @@ class APIPageClass : APIPage } } if(!first) - f.Printf("

\n"); + f.Printf("

\n"); // Non-Virtual Methods first = true; @@ -1176,7 +1329,7 @@ class APIPageClass : APIPage char * desc = ReadDoc(module, methodDoc, method, description, null); if(first) { - f.Printf($"

Non-Virtual Methods



\n"); + f.Printf($"

Non-Virtual Methods


\n"); f.Printf("\n"); first = false; } @@ -1205,13 +1358,13 @@ class APIPageClass : APIPage } } if(!first) - f.Printf("

\n"); + f.Printf("

\n"); } { char * usageDoc = ReadDoc(module, classDoc, cl, usage, null); if(usageDoc) { - f.Printf($"

Usage


\n"); + f.Printf($"

Usage


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1222,7 +1375,7 @@ class APIPageClass : APIPage } else f.Printf("
%s\n", usageDoc); - f.Printf("

\n"); + f.Printf("


\n"); delete usageDoc; } } @@ -1230,7 +1383,7 @@ class APIPageClass : APIPage char * exampleDoc = ReadDoc(module, classDoc, cl, example, null); if(exampleDoc) { - f.Printf($"

Example


\n"); + f.Printf($"

Example


\n"); f.Printf($"\n"); f.Printf("
\n"); if(editing) @@ -1245,7 +1398,7 @@ class APIPageClass : APIPage f.Printf("\n", exampleDoc); // bgcolor=#CFC9C0 f.Printf("
%s
\n"); - f.Printf("
\n"); + f.Printf("

\n"); delete exampleDoc; } } @@ -1254,7 +1407,7 @@ class APIPageClass : APIPage if(remarksDoc) { - f.Printf($"

Remarks


\n"); + f.Printf($"

Remarks


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1265,7 +1418,7 @@ class APIPageClass : APIPage } else f.Printf("
%s\n", remarksDoc); - f.Printf("

\n"); + f.Printf("


\n"); delete remarksDoc; } } @@ -1282,8 +1435,7 @@ class APIPageClass : APIPage { if(first) { - f.Printf($"

Derived Classes


\n"); - f.Printf("
"); + f.Printf($"

Derived Classes


\n"); first = false; } else @@ -1298,7 +1450,7 @@ class APIPageClass : APIPage char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null); if(seeAlsoDoc) { - f.Printf($"

See Also


\n"); + f.Printf($"

See Also

\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1377,7 +1529,7 @@ class APIPageMethod : APIPage char * desc = ReadDoc(module, methodDoc, method, description, null); if(desc) { - f.Printf($"

Description



\n"); + f.Printf($"

Description


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1388,6 +1540,7 @@ class APIPageMethod : APIPage } else f.Printf("%s", desc); + f.Printf("

"); delete desc; } } @@ -1395,7 +1548,7 @@ class APIPageMethod : APIPage f.Printf("

\n"); if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType) { - f.Printf($"

Parameters



\n"); + f.Printf($"

Parameters


\n"); } if((method.dataType.returnType && method.dataType.returnType.kind != voidType) || (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)) @@ -1471,7 +1624,7 @@ class APIPageMethod : APIPage char * usageDoc = ReadDoc(module, methodDoc, method, usage, null); if(usageDoc) { - f.Printf($"

Usage


\n"); + f.Printf($"

Usage


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1482,7 +1635,7 @@ class APIPageMethod : APIPage } else f.Printf("
%s\n", usageDoc); - f.Printf("

\n"); + f.Printf("


\n"); delete usageDoc; } } @@ -1490,7 +1643,7 @@ class APIPageMethod : APIPage char * exampleDoc = ReadDoc(module, methodDoc, method, example, null); if(exampleDoc) { - f.Printf($"

Example


\n"); + f.Printf($"

Example


\n"); f.Printf($"\n"); f.Printf("
\n"); if(editing) @@ -1504,7 +1657,7 @@ class APIPageMethod : APIPage else f.Printf("\n", exampleDoc); // bgcolor=#CFC9C0 f.Printf("
%s
\n"); - f.Printf("
\n"); + f.Printf("

\n"); delete exampleDoc; } } @@ -1512,7 +1665,7 @@ class APIPageMethod : APIPage char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null); if(remarksDoc) { - f.Printf($"

Remarks


\n"); + f.Printf($"

Remarks


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1523,7 +1676,7 @@ class APIPageMethod : APIPage } else f.Printf("
%s\n", method, remarksDoc); - f.Printf("

\n"); + f.Printf("


\n"); delete remarksDoc; } } @@ -1531,7 +1684,7 @@ class APIPageMethod : APIPage char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null); if(seeAlsoDoc) { - f.Printf($"

See Also


\n"); + f.Printf($"

See Also


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1543,7 +1696,7 @@ class APIPageMethod : APIPage else f.Printf("
%s\n", method, seeAlsoDoc); - f.Printf("

\n"); + f.Printf("


\n"); delete seeAlsoDoc; } } @@ -1610,7 +1763,7 @@ class APIPageFunction : APIPage char * desc = ReadDoc(module, functionDoc, function, description, null); if(desc) { - f.Printf($"

Description



\n"); + f.Printf($"

Description


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1622,12 +1775,13 @@ class APIPageFunction : APIPage else f.Printf("%s", desc); delete desc; + f.Printf("

"); } } f.Printf("

\n"); if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType) { - f.Printf($"

Parameters



\n"); + f.Printf($"

Parameters


\n"); } if((function.dataType.returnType && function.dataType.returnType.kind != voidType) || (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)) @@ -1703,7 +1857,7 @@ class APIPageFunction : APIPage char * usageDoc = ReadDoc(module, functionDoc, function, usage, null); if(usageDoc) { - f.Printf($"

Usage


\n"); + f.Printf($"

Usage


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1714,7 +1868,7 @@ class APIPageFunction : APIPage } else f.Printf("
%s\n", usageDoc); - f.Printf("

\n"); + f.Printf("


\n"); delete usageDoc; } } @@ -1722,7 +1876,7 @@ class APIPageFunction : APIPage char * exampleDoc = ReadDoc(module, functionDoc, function, example, null); if(exampleDoc) { - f.Printf($"

Example


\n"); + f.Printf($"

Example


\n"); f.Printf($"\n"); f.Printf("
\n"); if(editing) @@ -1736,7 +1890,7 @@ class APIPageFunction : APIPage else f.Printf("\n", exampleDoc); // bgcolor=#CFC9C0 f.Printf("
%s
\n"); - f.Printf("
\n"); + f.Printf("

\n"); delete exampleDoc; } } @@ -1744,7 +1898,7 @@ class APIPageFunction : APIPage char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null); if(remarksDoc) { - f.Printf($"

Remarks


\n"); + f.Printf($"

Remarks


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1755,7 +1909,7 @@ class APIPageFunction : APIPage } else f.Printf("
%s\n", remarksDoc); - f.Printf("

\n"); + f.Printf("


\n"); delete remarksDoc; } } @@ -1763,7 +1917,7 @@ class APIPageFunction : APIPage char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null); if(seeAlsoDoc) { - f.Printf($"

See Also


\n"); + f.Printf($"

See Also


\n"); if(editing) { char fileName[MAX_LOCATION]; @@ -1774,7 +1928,7 @@ class APIPageFunction : APIPage } else f.Printf("
%s\n", seeAlsoDoc); - f.Printf("

\n"); + f.Printf("


\n"); delete seeAlsoDoc; } } @@ -1841,7 +1995,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); @@ -2230,6 +2384,7 @@ class MainForm : Window static char symbolsDir[MAX_LOCATION]; history.size = 0; + modulesAdded.RemoveAll(); FreeContext(globalContext); FreeExcludedSymbols(excludedSymbols); @@ -2403,6 +2558,16 @@ class MainForm : Window bool dontRecordHistory; Module homeModule; + bool OnKeyHit(Key key, unichar ch) + { + switch(key) + { + case altLeft: Back(); return false; + case altRight: Forward(); return false; + } + return true; + } + bool Forward() { if(historyPos < history.count-1) @@ -2484,31 +2649,27 @@ class HelpView : HTMLView { // Writability test { - char docFile[MAX_LOCATION]; - Archive archive; - Module module = page ? page.GetModule() : null; - NameSpace * ns = page ? page.GetNameSpace() : null; - - sprintf(docFile, "%s/%s.eCdoc", settings.docDir, (!module || !module.name || (ns && ns->name && !strcmp(ns->name, "namespaces/ecere/namespaces/com"))) ? "ecereCOM" : module.name); - if(FileExists(docFile)) - { - archive = ArchiveOpen(docFile, { true } ); - readOnly = archive == null; - delete archive; - } - else + char docDir[MAX_LOCATION]; + readOnly = true; + strcpy(docDir, ideSettings.docDir); + if(FileExists(docDir).isDirectory) { - readOnly = true; - archive = ArchiveOpen(docFile, { true } ); - if(archive) + PathCatSlash(docDir, "___docWriteTest"); + if(FileExists(docDir).isDirectory) { - // Must create root directory on archive creation - ArchiveDir dir = archive.OpenDirectory("", null, replace); - if(dir) + RemoveDir(docDir); + if(!FileExists(docDir)) readOnly = false; - delete dir; } - delete archive; + else + { + MakeDir(docDir); + if(FileExists(docDir).isDirectory) + { + readOnly = false; + RemoveDir(docDir); + } + } } } @@ -2529,68 +2690,403 @@ class HelpView : HTMLView void SaveEdit() { - char archiveFile[MAX_LOCATION]; - char fileName[MAX_FILENAME]; - char directory[MAX_LOCATION]; - const char * location; - Archive archive = null; - if(SplitArchivePath(editString, archiveFile, &location)) + Block block; + bool empty = true; + String contents = null; + uint len; + TempFile f { }; + for(block = textBlock.parent.subBlocks.first; block; block = block.next) { - GetLastDirectory(location, fileName); - StripLastDirectory(location, directory); - archive = ArchiveOpen(archiveFile, { true } ); + if(block.type == TEXT && block.textLen) + { + empty = false; + break; + } } + if(!empty) { - TempFile f { }; - ArchiveDir dir = archive ? archive.OpenDirectory(directory, null, replace) : null; - Block block; - bool empty = true; for(block = textBlock.parent.subBlocks.first; block; block = block.next) { - if(block.type == TEXT && block.textLen) + if(block.type == BR) + f.Puts("
"); + else if(block.type == TEXT) + f.Write(block.text, 1, block.textLen); + } + } + f.Seek(0, start); + if((len = f.GetSize())) + { + contents = new char[len+1]; + f.Read(contents, 1, len); + contents[len] = '\0'; + } + + { + char docPath[MAX_LOCATION]; + char temp[MAX_LOCATION]; + char part[MAX_FILENAME]; + Module module; + void * object; + void * data; + DocumentationType type; + DocumentationItem item; + ItemDoc doc; + NamespaceDoc nsDoc = null; + ClassDoc clDoc = null; + FunctionDoc fnDoc = null; + MethodDoc mdDoc = null; + Class cl = null; + Method method = null; + GlobalFunction function = null; + + strcpy(temp, editString); + SplitDirectory(temp, part, temp); + module = (Module)strtoull(part, null, 16); + SplitDirectory(temp, part, temp); + object = (void *)strtoull(part, null, 16); + SplitDirectory(temp, part, temp); + data = (void *)strtoull(part, null, 16); + SplitDirectory(temp, part, temp); + if(!strcmp(part, "namespace")) + type = nameSpaceDoc; + else if(!strcmp(part, "function")) + type = functionDoc; + else if(!strcmp(part, "class")) + type = classDoc; + else if(!strcmp(part, "method")) + type = methodDoc; + SplitDirectory(temp, part, temp); + if(!strcmp(part, "description")) + item = description; + else if(!strcmp(part, "usage")) + item = usage; + else if(!strcmp(part, "remarks")) + item = remarks; + else if(!strcmp(part, "example")) + item = example; + else if(!strcmp(part, "seeAlso")) + item = seeAlso; + else if(!strcmp(part, "enumerationValue")) + item = enumerationValue; + else if(!strcmp(part, "definition")) + item = definition; + else if(!strcmp(part, "conversion")) + item = conversion; + else if(!strcmp(part, "memberDescription")) + item = memberDescription; + else if(!strcmp(part, "propertyDescription")) + item = propertyDescription; + else if(!strcmp(part, "parameter")) + item = parameter; + else if(!strcmp(part, "returnValue")) + item = returnValue; + + doc = getDoc(docPath, module, type, object, item, data, !empty && contents); + + /* Why invalidate this entry here? + { + MapIterator it { map = docCache }; + if(it.Index(docPath, false)) { - empty = false; - break; + delete it.data; + it.Remove(); } + }*/ + + switch(type) + { + case classDoc: cl = (Class)object; break; + case functionDoc: function = object; break; + case methodDoc: method = object; cl = method._class; break; } - if(!empty) + + if(doc) { - for(block = textBlock.parent.subBlocks.first; block; block = block.next) + if(eClass_IsDerived(doc._class, class(ClassDoc))) + { + clDoc = (ClassDoc)doc; + } + else if(eClass_IsDerived(doc._class, class(NamespaceDoc))) { - if(block.type == BR) - f.Puts("
"); - else if(block.type == TEXT) - f.Write(block.text, 1, block.textLen); + nsDoc = (NamespaceDoc)doc; } } - f.Seek(0, start); - if(dir) - dir.AddFromFile(fileName, f, null, replace, 0, null, null); - delete dir; - delete archive; - delete f; - if(empty) + + if(clDoc || nsDoc) { - Block parent = textBlock.parent; - while((block = parent.subBlocks.first)) + if(type == functionDoc) + { + const char * name = RSearchString(function.name, "::", strlen(function.name), true, false); + if(name) name += 2; else name = function.name; + fnDoc = nsDoc.functions ? nsDoc.functions[name] : null; + if(!empty && !fnDoc) + { + if(!nsDoc.functions) nsDoc.functions = { }; + nsDoc.functions[name] = fnDoc = { }; + } + } + else if(type == methodDoc) + { + mdDoc = clDoc.methods ? clDoc.methods[method.name] : null; + if(!empty && !mdDoc) + { + if(!clDoc.methods && !empty) clDoc.methods = { }; + clDoc.methods[method.name] = mdDoc = { }; + } + } + + if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc)) + { + switch(item) + { + 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: + { + 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 it { map = clDoc.values }; + if(it.Index(((NamedLink)data).name, false)) + it.Remove(); + delete itDoc; + } + } + break; + } + case definition: + { + 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 it { map = nsDoc.defines }; + if(it.Index(((Definition)data).name, false)) + it.Remove(); + delete itDoc; + } + } + 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; + 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 it { map = clDoc.conversions }; + if(it.Index(name, false)) + it.Remove(); + delete itDoc; + } + } + break; + } + case memberDescription: + { + 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 it { map = clDoc.fields }; + if(it.Index(((DataMember)data).name, false)) + it.Remove(); + delete itDoc; + } + } + break; + } + case propertyDescription: + { + PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null; + if(!empty || itDoc) + { + if(!empty && !itDoc) + { + if(!clDoc.properties) clDoc.properties = { }; + clDoc.properties[((Property)data).name] = itDoc = { }; + } + itDoc.description = contents, contents = null; + if(itDoc.isEmpty) + { + MapIterator it { map = clDoc.properties }; + if(it.Index(((Property)data).name, false)) + it.Remove(); + delete itDoc; + } + } + break; + } + case parameter: + { + if(type == functionDoc || type == methodDoc) + { + Map * 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 it { map = *parameters }; + if(it.Index(((Type)data).name, false)) + it.Remove(); + delete itDoc; + } + } + } + break; + } + } + } + } + + if(type == functionDoc && fnDoc && fnDoc.isEmpty) + { + MapIterator 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 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) + { + char dirPath[MAX_LOCATION]; + StripLastDirectory(docPath, dirPath); + if(FileExists(docPath)) + DeleteFile(docPath); + if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty)) { - parent.subBlocks.Remove(block); - delete block; + File f; + if(!FileExists(dirPath)) + MakeDir(dirPath); + if((f = FileOpen(docPath, write))) + { + WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0); + delete f; + } + else + PrintLn("error: writeClassDocFile -- problem opening file: ", docPath); } - textBlock = Block { type = TEXT, parent = parent, font = parent.font }; - textBlock.text = CopyString($"[Add Text]"); - textBlock.textLen = strlen(textBlock.text); - parent.subBlocks.Add(textBlock); } + delete doc; + delete contents; + } - edit = false; - if(created) + if(empty) + { + Block parent = textBlock.parent; + while((block = parent.subBlocks.first)) { - ComputeMinSizes(); - ComputeSizes(); - PositionCaret(true); - Update(null); + parent.subBlocks.Remove(block); + delete block; } + textBlock = Block { type = TEXT, parent = parent, font = parent.font }; + textBlock.text = CopyString($"[Add Text]"); + textBlock.textLen = strlen(textBlock.text); + parent.subBlocks.Add(textBlock); + } + + edit = false; + if(created) + { + ComputeMinSizes(); + ComputeSizes(); + PositionCaret(true); + Update(null); } } @@ -2761,6 +3257,9 @@ class HelpView : HTMLView // dialog.Create(); edit = true; // PositionCaret(true); + + // TOCHECK: Adding this here seemed to fixed caret positioning bugs + ComputeSizes(); } return true; } @@ -3658,6 +4157,7 @@ class HelpView : HTMLView char * text = textBlock.text; int maxW; Block block = textBlock; + int xOffset = 0; while(block && block.type != TD) block = block.parent; if(block) { @@ -3673,11 +4173,19 @@ class HelpView : HTMLView display.FontExtent(textBlock.font.font, " ", 1, null, &th); + // Work around to re-align with first line having different indentation because of    before of current block + { + Block parent = textBlock.parent; + while(parent && parent.type == ANCHOR) parent = parent.parent; + if(parent && parent.subBlocks.first && ((Block)parent.subBlocks.first).type == TEXT) + xOffset = sx - ((Block)parent.subBlocks.first).startX; + } + while(textPos < textBlock.textLen) { int startPos = textPos; int width = 0; - int x = 0; + int x = xOffset; bool lineComplete = false; for(; textPos of current block + { + Block parent = textBlock.parent; + while(parent && parent.type == ANCHOR) parent = parent.parent; + if(parent && parent.subBlocks.first && ((Block)parent.subBlocks.first).type == TEXT) + xOffset = sx - ((Block)parent.subBlocks.first).startX; + } + display.FontExtent(textBlock.font.font, " ", 1, &space, &th); //space = space/2+2; space = 2; @@ -3796,7 +4313,7 @@ class HelpView : HTMLView while(textPos < textBlock.textLen) { int width = 0; - int x = 0; + int x = xOffset; bool lineComplete = false; for(; textPos= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space) { int c, numBytes; @@ -3873,9 +4390,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 { @@ -3889,23 +4406,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(); } @@ -3984,3 +4501,197 @@ Thread commandThread return 0; } }; +#endif // !defined(EAR_TO_ECON_ECDOC) + +class ItemDoc +{ +public: + property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } } + property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } } +private: + char * name; + char * description; + property bool isEmpty + { + get + { + return !( + (name && *name) || + (description && *description)); + } + } + ~ItemDoc() + { + delete name; + delete description; + } +} + +class MoreDoc : ItemDoc +{ +public: + property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } } + property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } } + property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } } + property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } } +private: + char * usage; + char * example; + char * remarks; + char * also; + property bool isEmpty + { + get + { + return !( + (usage && *usage) || + (example && *example) || + (remarks && *remarks) || + (also && *also) || + !ItemDoc::isEmpty); + } + } + ~MoreDoc() + { + delete usage; + delete example; + delete remarks; + delete also; + } +} + +class NamespaceDoc : ItemDoc +{ +public: + Map defines; + Map functions; +private: + property bool isEmpty + { + get + { + return !( + (defines && defines.count) || + (functions && functions.count) || + !ItemDoc::isEmpty); + } + } + ~NamespaceDoc() + { + delete defines; + delete functions; + } +} + +class DefineDoc : ItemDoc { } + +class FunctionDoc : MoreDoc +{ +public: + Map parameters; + property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } } +private: + char * returnValue; + property bool isEmpty + { + get + { + return !( + (parameters && parameters.count) || + (returnValue && *returnValue) || + !MoreDoc::isEmpty); + } + } + ~FunctionDoc() + { + delete parameters; + delete returnValue; + } +} + +class ParameterDoc : ItemDoc +{ +public: + uint position; +} + +class ClassDoc : MoreDoc +{ +public: + Map values; + Map fields; + Map properties; + Map conversions; + Map methods; +private: + property bool isEmpty + { + get + { + return !( + (values && values.count) || + (fields && fields.count) || + (properties && properties.count) || + (conversions && conversions.count) || + (methods && methods.count) || + !MoreDoc::isEmpty); + } + } + ~ClassDoc() + { + delete values; + delete fields; + delete properties; + delete conversions; + delete methods; + } +} + +class ValueDoc : ItemDoc { } + +class FieldDoc : ItemDoc { } + +class PropertyDoc : ItemDoc { } + +class ConversionDoc : ItemDoc { } + +class MethodDoc : FunctionDoc { } + +char * getDocFileNameFromTypeName(const char * typeName) +{ + char * docFileName = new char[MAX_FILENAME]; + const char * swap = "pointer"; + const char * s = typeName; + char * d = docFileName; + const char * end = s + strlen(typeName); + int swapLen = strlen(swap); + for(; s < end; s++) + { + if(*s == ' ') + *d = '-'; + else if(*s == '*') + { + strcpy(d, swap); + d += swapLen; + } + else + *d = *s; + d++; + } + *d = '\0'; + return docFileName; +} + +class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data' +{ +public: + Time timeStamp; // Should this be last accessed, or last retrieved? + ItemDoc doc; + + ~DocCacheEntry() + { + delete doc; + } +} + +Map docCache { };