2 #if !defined(EAR_TO_ECON_ECDOC)
6 import "SettingsDialog"
8 IDESettings ideSettings;
10 IDESettingsContainer settingsContainer
12 dataOwner = &ideSettings;
13 dataClass = class(IDESettings);
16 static Context globalContext { };
17 static OldList defines { };
18 static OldList imports { };
19 static NameSpace globalData;
20 static OldList excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left };
23 define app = (GuiApplication)__thisModule.application;
25 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
28 /*extern */int __ecereVMethodID_class_OnGetString;
32 static __attribute__((unused)) void Dummy()
35 a.OnGetString(null, null, null);
38 static bool editing = true;
40 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
42 static const char * iconNames[CodeObjectType] =
44 "<:ecere>constructs/class.png",
45 "<:ecere>constructs/data.png",
46 "<:ecere>constructs/method.png",
47 "<:ecere>constructs/event.png",
48 "<:ecere>constructs/property.png",
49 "<:ecere>constructs/namespace.png",
50 "<:ecere>constructs/dataType.png",
51 "<:ecere>constructs/enumValue.png",
52 "<:ecere>constructs/dataPrivate.png",
53 "<:ecere>constructs/methodPrivate.png",
54 "<:ecere>constructs/propertyPrivate.png"
57 void GetTemplateString(Class c, char * templateString)
59 Module m = c.module.application;
60 const char * n = c.name;
61 char * lt = strchr(n, '<');
67 memcpy(templateString, n, lt-n);
68 templateString[lt-n] = 0;
69 strcat(templateString, "</a>");
71 for(s = lt; (ch = *s); s++)
73 if(ch == '<' || ch == '>' || ch == ',')
78 char * d = templateString + strlen(templateString);
80 TrimLSpaces(curName, curName);
81 TrimRSpaces(curName, curName);
82 pc = eSystem_FindClass(m, curName);
84 sprintf(d, "%s<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name);
89 strcat(templateString, "<");
91 strcat(templateString, ">");
93 strcat(templateString, ", ");
100 curName[len++] = ' ';
102 strcat(templateString, curName);
110 // WARNING : This function expects a null terminated string since it recursively concatenate...
111 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
115 if(type.constant && (type.kind != pointerType && type.kind != arrayType))
116 strcat(string, "const ");
120 if(type._class && type._class.string)
123 strcat(string, type._class.string);
126 if(type._class.registered)
129 const char * s = type._class.registered.name;
130 sprintf(hex, "%p", type._class.registered.templateClass ? type._class.registered.templateClass : type._class.registered);
131 strcat(string, "<a href=\"api://");
133 strcat(string, "\" style=\"text-decoration: none;\">");
137 GetTemplateString(type._class.registered, n);
141 strcat(string, type._class.registered.name);
142 strcat(string, "</a>");
145 strcat(string, type._class.string);
152 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
153 if(funcType && funcType.kind == functionType)
156 DocPrintType(funcType.returnType, string, false, fullName);
157 strcat(string, "(*");
158 if(printName || funcType.thisClass)
161 if(funcType.thisClass)
163 strcat(string, funcType.thisClass.string);
164 strcat(string, "::");
167 strcat(string, type.name);
169 strcat(string, ")(");
170 for(param = funcType.params.first; param; param = param.next)
172 DocPrintType(param, string, false, fullName);
173 if(param.next) strcat(string, ", ");
179 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
180 if(string[strlen(string)-1] == '(')
183 strcat(string, " *");
187 case voidType: strcat(string, "void"); break;
188 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
189 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
190 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
191 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
192 case floatType: strcat(string, "float"); break;
193 case doubleType: strcat(string, "double"); break;
197 strcat(string, "struct ");
198 strcat(string, type.enumName);
200 else if(type.typeName)
202 strcat(string, type.typeName);
207 strcat(string, "struct ");
208 strcat(string,"(unnamed)");
211 strcat(string, "struct {");
212 for(member = type.members.first; member; member = member.next)
214 DocPrintType(member, string, true, fullName);
223 strcat(string, "union ");
224 strcat(string, type.enumName);
226 else if(type.typeName)
228 strcat(string, type.typeName);
232 strcat(string, "union ");
233 strcat(string,"(unnamed)");
239 strcat(string, "enum ");
240 strcat(string, type.enumName);
242 else if(type.typeName)
244 strcat(string, type.typeName);
247 strcat(string, "enum");
254 strcat(string, "dllexport ");
255 DocPrintType(type.returnType, string, false, fullName);
259 // DANGER: Testing This
265 strcat(string, type.name);
268 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
269 if(name) name += 2; else name = type.name;
270 strcat(string, "<b>");
271 strcat(string, name);
272 strcat(string, "</b>");
281 for(param = type.params.first; param; param = param.next)
283 DocPrintType(param, string, true, fullName);
284 if(param.next) strcat(string, ", ");
293 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
294 if(funcType && funcType.kind == functionType)
297 DocPrintType(funcType.returnType, string, false, fullName);
298 strcat(string, "(*");
299 if(printName || funcType.thisClass)
302 if(funcType.thisClass)
304 strcat(string, funcType.thisClass.string);
305 strcat(string, "::");
308 strcat(string, type.name);
310 strcat(string, ")(");
311 for(param = funcType.params.first; param; param = param.next)
313 DocPrintType(param, string, false, fullName);
314 if(param.next) strcat(string, ", ");
320 char baseType[1024], size[256];
321 Type arrayType = type;
325 while(arrayType.kind == TypeKind::arrayType)
328 if(arrayType.enumClass)
329 strcat(size, arrayType.enumClass.string);
330 else if(arrayType.arraySizeExp)
331 PrintExpression(arrayType.arraySizeExp, size);
332 //sprintf(string, "%s[%s]", baseType, size);
335 arrayType = arrayType.arrayType;
337 _PrintType(arrayType, baseType, printName, printFunction, fullName);
338 strcat(string, baseType);
339 strcat(string, size);
343 DocPrintType(type.arrayType, baseType, printName, fullName);
345 strcpy(size, type.enumClass.string);
346 else if(type.arraySizeExp)
347 PrintExpression(type.arraySizeExp, size);
348 //sprintf(string, "%s[%s]", baseType, size);
349 strcat(string, baseType);
351 strcat(string, size);
359 strcat(string, "...");
362 _PrintType(type.method.dataType, string, false, printFunction, fullName);
365 strcat(string, "subclass(");
366 strcat(string, type._class ? type._class.string : "int");
372 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
375 strcat(string, type.name);
380 void DocPrintType(Type type, char * string, bool printName, bool fullName)
383 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
384 if(funcType && funcType.kind == functionType && type != funcType)
388 DocPrintType(funcType.returnType, string, false, fullName);
390 _PrintType(type, string, printName, false, fullName);
394 strcat(string, type.name);
401 for(param = funcType.params.first; param; param = param.next)
403 DocPrintType(param, string, true, fullName);
404 if(param.next) strcat(string, ", ");
409 _PrintType(type, string, printName, true, fullName);
412 Map<String, bool> modulesAdded { };
413 void AddComponents(Module module, bool isDll)
418 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")) && !modulesAdded["ecereCOM"])
420 row = mainForm.browser.AddRow();
421 modulesAdded["ecereCOM"] = true;
422 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
423 row.tag = (int64)null;
424 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
427 for(m = module.modules.first; m; m = m.next)
429 if(m.importMode == publicAccess || !isDll)
430 AddComponents(m.module, true);
433 // PUT MODULE DESCRIPTION HERE
434 if(module.name && !modulesAdded[module.name] && strcmp(module.name, "ecereCOM"))
436 row = mainForm.browser.AddRow();
437 modulesAdded[module.name] = true;
438 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
439 row.tag = (int64)module;
440 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
442 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
454 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
459 virtual void Generate(File f)
464 virtual Module GetModule()
466 return page ? page.GetModule() : null;
469 virtual NameSpace * GetNameSpace()
471 return page ? page.GetNameSpace() : null;
475 enum DocumentationType
484 enum DocumentationItem
501 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
505 sprintf(hex, "%p", module);
506 strcat(fileName, hex);
507 strcat(fileName, "/");
508 sprintf(hex, "%p", object);
509 strcat(fileName, hex);
510 strcat(fileName, "/");
511 sprintf(hex, "%p", data);
512 strcat(fileName, hex);
513 strcat(fileName, "/");
514 if(type == nameSpaceDoc)
515 strcat(fileName, "namespace");
516 else if(type == functionDoc)
517 strcat(fileName, "function");
518 else if(type == classDoc)
519 strcat(fileName, "class");
520 else if(type == methodDoc)
521 strcat(fileName, "method");
522 strcat(fileName, "/");
523 if(item == description)
524 strcat(fileName, "description");
525 else if(item == usage)
526 strcat(fileName, "usage");
527 else if(item == remarks)
528 strcat(fileName, "remarks");
529 else if(item == example)
530 strcat(fileName, "example");
531 else if(item == seeAlso)
532 strcat(fileName, "seeAlso");
533 else if(item == enumerationValue)
534 strcat(fileName, "enumerationValue");
535 else if(item == definition)
536 strcat(fileName, "definition");
537 else if(item == conversion)
538 strcat(fileName, "conversion");
539 else if(item == memberDescription)
540 strcat(fileName, "memberDescription");
541 else if(item == propertyDescription)
542 strcat(fileName, "propertyDescription");
543 else if(item == parameter)
544 strcat(fileName, "parameter");
545 else if(item == returnValue)
546 strcat(fileName, "returnValue");
549 static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
551 char docPath[MAX_LOCATION];
552 NameSpace * nameSpace, * ns;
554 Method method = null;
555 GlobalFunction function = null;
556 char nsName[1024], temp[1024];
559 case nameSpaceDoc: nameSpace = object; break;
560 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
561 case functionDoc: function = object; nameSpace = function.nameSpace; break;
562 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
568 while(ns && ns->name)
570 strcpy(temp, ns->name);
572 strcat(temp, nsName);
573 strcpy(nsName, temp);
578 PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
579 //ChangeExtension(docPath, "eCdoc", docPath);
580 PathCatSlash(docPath, nsName);
583 char * name = getDocFileNameFromTypeName(cl.name);
584 PathCatSlash(docPath, name);
588 PathCatSlash(docPath, "_global-defs");
589 ChangeExtension(docPath, "econ", docPath);
592 strcpy(path, ideSettings.docDir);
593 PathCatSlash(path, docPath);
596 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
598 String contents = null;
599 NamespaceDoc nsDoc = null;
600 ClassDoc clDoc = null;
601 FunctionDoc fnDoc = null;
602 MethodDoc mdDoc = null;
604 char filePath[MAX_LOCATION];
605 Method method = null;
606 GlobalFunction function = null;
608 ItemDoc doc = getDoc(filePath, module, type, object, item, data, false);
612 case functionDoc: function = object; break;
613 case methodDoc: method = object; break;
618 if(eClass_IsDerived(doc._class, class(ClassDoc)))
620 clDoc = (ClassDoc)doc;
622 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
624 nsDoc = (NamespaceDoc)doc;
630 ItemDoc itDoc = null;
631 if(type == functionDoc)
633 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
634 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
635 if(name) name += 2; else name = function.name;
636 if(it.Index(name, false))
639 else if(type == methodDoc)
641 MapIterator<String, MethodDoc> it { map = clDoc.methods };
642 if(it.Index(method.name, false))
648 case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break;
649 case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break;
650 case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break;
651 case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break;
652 case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break;
653 case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break;
654 case enumerationValue:
655 if(clDoc && clDoc.values)
657 itDoc = clDoc.values[((NamedLink)data).name];
658 if(itDoc) s = itDoc.description;
662 if(nsDoc && nsDoc.defines)
664 itDoc = nsDoc.defines[((Definition)data).name];
665 if(itDoc) s = itDoc.description;
669 if(clDoc && clDoc.conversions)
671 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
672 if(name) name += 2; else name = ((Property)data).name;
673 itDoc = clDoc.conversions[name];
674 if(itDoc) s = itDoc.description;
677 case memberDescription:
678 if(clDoc && clDoc.fields)
680 itDoc = clDoc.fields[((DataMember)data).name];
681 if(itDoc) s = itDoc.description;
684 case propertyDescription:
685 if(clDoc && clDoc.properties)
687 itDoc = clDoc.properties[((Property)data).name];
688 if(itDoc) s = itDoc.description;
692 if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters))
694 char * name = ((Type)data).name;
695 itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ;
696 if(itDoc) s = itDoc.description;
701 contents = CopyString(s);
703 if(editing && !contents && !readOnly)
704 contents = CopyString($"[Add Text]");
708 // The filePath is returned!
709 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
713 Method method = null;
719 case classDoc: cl = (Class)object; break;
720 case methodDoc: method = object; cl = method._class; break;
723 FigureFilePath(filePath, module, type, object, item, data);
725 entry = docCache[filePath];
731 File f = FileOpen(filePath, read);
734 ECONParser parser { f = f };
735 JSONResult jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
739 if(jsonResult != success)
741 PrintLn("error: problem parsing file: ", filePath);
746 doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
749 incref doc; // Reference to return
754 entry.timeStamp = now;
757 docCache[filePath] = { now, doc };
758 incref doc; // Reference for the cache
761 //void pruneDocCache()
762 // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
764 MapIterator<String, DocCacheEntry> it { map = docCache };
765 Array<const String> toRemove { };
766 for(entry : docCache; now - entry.timeStamp > 30)
767 toRemove.Add(&entry);
768 while(toRemove.count)
770 if(it.Index(toRemove.lastIterator.data, false))
775 toRemove.Remove(toRemove.lastIterator.pointer);
782 class APIPageNameSpace : APIPage
784 NameSpace * nameSpace;
792 NameSpace * GetNameSpace()
797 void Generate(File f)
799 char nsName[1024], temp[1024];
805 while(ns && ns->name)
807 strcpy(temp, ns->name);
808 if(nsName[0]) strcat(temp, "::");
809 strcat(temp, nsName);
810 strcpy(nsName, temp);
813 // Generate Class Page
814 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
817 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
818 f.Printf($"Module: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", (module && module.name) ? module : null, (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
821 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
824 ns = nameSpace->parent;
825 while(ns && ns->name)
827 strcpy(temp, ns->name);
828 if(nsName[0]) strcat(temp, "::");
829 strcat(temp, nsName);
830 strcpy(nsName, temp);
834 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
838 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
841 f.Printf($"<H3>Description</H3><BR>\n");
844 char fileName[MAX_LOCATION];
845 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
846 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
851 f.Printf("%s", desc);
852 f.Printf("<br><br><br>");
857 if(nameSpace->nameSpaces.first)
860 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
862 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
865 f.Printf($"<H3>Sub Namespaces</H3><BR>\n");
866 f.Printf("<TABLE>\n");
870 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", iconNames[typeNameSpace], ns, ns->name);
875 char fileName[MAX_LOCATION];
876 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
877 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
879 f.Printf("</a></TD>");
882 f.Printf("<TD valign=top height=22> %s</TD>", desc);
885 f.Printf("</TR><br>\n");
888 f.Printf("</TABLE><br><br>\n");
891 if(nameSpace->classes.first)
894 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
896 Class cl = link.data;
897 Module module = cl.module ? cl.module : this.module;
898 if(!cl.templateClass) // && !cl.internalDecl)
900 char * desc = ReadDoc(module, classDoc, cl, description, null);
904 f.Printf($"<a name=Classes></a><H3>Classes</H3><BR>\n");
905 f.Printf("<TABLE>\n");
911 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? iconNames[typeDataType] : iconNames[typeClass], cl, cl.name);
916 char fileName[MAX_LOCATION];
917 FigureFileName(fileName, module, classDoc, cl, description, null);
918 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
920 f.Printf("</a></TD>");
923 f.Printf("<TD valign=top height=22>%s</TD>", desc);
930 f.Printf("</TABLE><br><br>\n");
933 if(nameSpace->functions.first)
936 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
938 GlobalFunction function = link.data;
939 Module module = function.module ? function.module : this.module;
940 char * desc = ReadDoc(module, functionDoc, function, description, null);
941 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
942 if(name) name += 2; else name = function.name;
945 f.Printf($"<a name=Functions></a><H3>Functions</H3><BR>\n");
946 f.Printf("<TABLE>\n");
950 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", iconNames[typeMethod], function, name);
955 char fileName[MAX_LOCATION];
956 FigureFileName(fileName, module, functionDoc, function, description, null);
957 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
959 f.Printf("</a></TD>");
962 f.Printf("<TD valign=top height=22> %s</TD>", desc);
965 f.Printf("</TR><br>\n");
968 f.Printf("</TABLE><br><br>\n");
971 if(nameSpace->defines.first)
974 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
976 DefinedExpression def = link.data;
977 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
980 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><BR>\n");
981 f.Printf("<TABLE>\n");
985 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", def, iconNames[typeData], def.name);
986 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
991 char fileName[MAX_LOCATION];
992 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
993 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
995 f.Printf("</a></TD>");
998 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1001 f.Printf("</TR><br>\n");
1004 f.Printf("</TABLE><br><br>\n");
1007 f.Printf("</FONT></BODY></HTML>\n");
1011 class APIPageClass : APIPage
1020 NameSpace * GetNameSpace()
1022 return cl.nameSpace;
1025 void Generate(File f)
1030 char nsName[1024], temp[1024];
1031 NameSpace * ns = cl.nameSpace;
1032 Module module = cl.module;
1035 while(ns && ns->name)
1037 strcpy(temp, ns->name);
1038 if(nsName[0]) strcat(temp, "::");
1039 strcat(temp, nsName);
1040 strcpy(nsName, temp);
1043 // Generate Class Page
1044 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1045 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1047 f.Printf($"Module: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", (module && module.name) ? module : null, (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
1049 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1052 const char * classType = null;
1056 classType = $"Bit Collection";
1059 classType = $"Enumeration";
1062 classType = $"Structure";
1065 classType = $"Class";
1068 classType = $"Class (No header)";
1071 classType = $"Unit";
1074 classType = $"Basic Data Type";
1077 f.Printf($"Type: %s<br>\n", classType);
1080 if(cl.type != systemClass && cl.base)
1082 f.Printf($"Base Class: ");
1083 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1085 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1087 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1088 f.Printf("%s", cl.dataTypeString);
1090 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1095 char * desc = ReadDoc(module, classDoc, cl, description, null);
1098 f.Printf($"<br><H3>Description</H3><BR>\n");
1101 char fileName[MAX_LOCATION];
1102 FigureFileName(fileName, module, classDoc, cl, description, null);
1103 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1108 f.Printf("%s", desc);
1109 f.Printf("<br><br><br>");
1114 if(cl.type == enumClass)
1116 EnumClassData enumeration = (EnumClassData)cl.data;
1117 if(enumeration.values.first)
1121 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><BR>\n");
1122 f.Printf("<TABLE>\n");
1124 for(item = enumeration.values.first; item; item = item.next)
1126 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1127 bool needClass = true;
1130 char tempString[1024];
1132 while(base.type == enumClass) base = base.base;
1134 if(base.type == systemClass ||
1135 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1138 base.dataType = ProcessTypeString(base.dataTypeString, false);
1140 if(base.dataType.kind != classType)
1145 PrintType(base.dataType, string, false, true);
1146 classSym = FindClass(string);
1147 dataClass = classSym ? classSym.registered : null;
1150 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1156 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", item, iconNames[typeEnumValue], item.name);
1157 if(dataClass.type == systemClass)
1160 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1163 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1165 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1167 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1172 char fileName[MAX_LOCATION];
1173 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1174 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1176 f.Printf("</a></TD>");
1179 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1184 f.Printf("</TABLE><BR>\n");
1188 if(cl.conversions.first)
1190 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><BR>\n");
1191 f.Printf("<TABLE>\n");
1192 for(prop = cl.conversions.first; prop; prop = prop.next)
1194 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1196 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1198 Type type = ProcessTypeString(prop.name, false);
1199 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1200 if(name) name += 2; else name = prop.name;
1205 DocPrintType(type, string, true, false);
1207 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1212 char fileName[MAX_LOCATION];
1213 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1214 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1216 f.Printf("</a></TD>");
1219 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1223 f.Printf("</TR>\n");
1228 f.Printf("</TABLE><br><br>\n");
1231 if(cl.membersAndProperties.first)
1234 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1236 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1240 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><BR>\n");
1241 f.Printf("<TABLE>\n");
1247 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1249 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1253 DocPrintType(prop.dataType, string, true, false);
1255 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeProperty], prop.name);
1256 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1261 char fileName[MAX_LOCATION];
1262 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1263 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1265 f.Printf("</a></TD>");
1268 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1271 f.Printf("</TR>\n");
1275 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1280 f.Printf("</TABLE><br><br>\n");
1283 if(cl.methods.first)
1287 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1289 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1291 char * desc = ReadDoc(module, methodDoc, method, description, null);
1294 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><BR>\n");
1295 f.Printf("<TABLE>\n");
1298 if(!method.dataType)
1299 ProcessMethodType(method);
1302 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", method.dataType.thisClass ? iconNames[typeEvent] : iconNames[typeMethod], method, method.name);
1307 char fileName[MAX_LOCATION];
1308 FigureFileName(fileName, module, methodDoc, method, description, null);
1309 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1311 f.Printf("</a></TD>");
1314 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1317 f.Printf("</TR><br>\n");
1321 f.Printf("</TABLE><br><br>\n");
1323 // Non-Virtual Methods
1325 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1327 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1329 char * desc = ReadDoc(module, methodDoc, method, description, null);
1332 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><BR>\n");
1333 f.Printf("<TABLE>\n");
1337 if(!method.dataType)
1338 ProcessMethodType(method);
1341 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", iconNames[typeMethod], method, method.name);
1346 char fileName[MAX_LOCATION];
1347 FigureFileName(fileName, module, methodDoc, method, description, null);
1348 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1350 f.Printf("</a></TD>");
1353 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1357 f.Printf("</TR><br>\n");
1361 f.Printf("</TABLE><br><br>\n");
1364 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1367 f.Printf($"<H3>Usage</H3><BR>\n");
1370 char fileName[MAX_LOCATION];
1371 FigureFileName(fileName, module, classDoc, cl, usage, null);
1372 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1377 f.Printf("<br>%s\n", usageDoc);
1378 f.Printf("<br><br><br>\n");
1383 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1386 f.Printf($"<H3>Example</H3><BR>\n");
1387 f.Printf($"<FONT face=\"Courier New\">\n");
1388 f.Printf("<br><TABLE>\n");
1391 char fileName[MAX_LOCATION];
1392 FigureFileName(fileName, module, classDoc, cl, example, null);
1393 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1395 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1398 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1400 f.Printf("</TABLE></FONT>\n");
1401 f.Printf("<br><br>\n");
1406 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1410 f.Printf($"<H3>Remarks</H3><BR>\n");
1413 char fileName[MAX_LOCATION];
1414 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1415 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1420 f.Printf("<br>%s\n", remarksDoc);
1421 f.Printf("<br><br><br>\n");
1426 if(cl.type != systemClass)
1430 for(c = cl.derivatives.first; c; c = c.next)
1432 Class deriv = c.data;
1433 // TO VERIFY: Does this properly check public status?
1434 if(eSystem_FindClass(componentsApp, deriv.fullName))
1438 f.Printf($"<H3>Derived Classes</H3><BR>\n");
1443 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1447 f.Printf("<br><br>\n");
1450 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1453 f.Printf($"<H3>See Also</H3>\n");
1456 char fileName[MAX_LOCATION];
1457 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1458 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1463 f.Printf("<br>%s\n", seeAlsoDoc);
1464 f.Printf("<br><br>\n");
1468 f.Printf("</FONT></BODY></HTML>\n");
1472 class APIPageMethod : APIPage
1478 return method._class.module;
1481 NameSpace * GetNameSpace()
1483 return method._class.nameSpace;
1486 void Generate(File f)
1488 Class cl = method._class;
1490 Module module = cl.module;
1492 char nsName[1024], temp[1024];
1493 NameSpace * ns = cl.nameSpace;
1496 while(ns && ns->name)
1498 strcpy(temp, ns->name);
1499 if(nsName[0]) strcat(temp, "::");
1500 strcat(temp, nsName);
1501 strcpy(nsName, temp);
1505 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1506 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1508 f.Printf($"Module: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", (module && module.name) ? module : null, (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
1510 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1511 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1512 if(method.dataType.staticMethod)
1514 f.Printf($"this pointer class: None<br>\n");
1516 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1518 f.Printf($"this pointer class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", method.dataType.thisClass.registered, method.dataType.thisClass.registered.name);
1521 // Generate Method Page
1523 if(!method.dataType.name)
1524 method.dataType.name = CopyString(method.name);
1525 DocPrintType(method.dataType, string, true, false);
1526 f.Printf("<br>%s", string);
1529 char * desc = ReadDoc(module, methodDoc, method, description, null);
1532 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1535 char fileName[MAX_LOCATION];
1536 FigureFileName(fileName, module, methodDoc, method, description, null);
1537 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1542 f.Printf("%s", desc);
1543 f.Printf("<BR><BR>");
1548 f.Printf("<br><br>\n");
1549 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1551 f.Printf($"<H3>Parameters</H3><BR>\n");
1553 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1554 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1556 f.Printf("<TABLE valign=center>\n");
1559 for(param = method.dataType.params.first; param; param = param.next)
1561 // ADD DESCRIPTION HERE
1562 if(param.kind != voidType)
1564 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1567 DocPrintType(param, string, false, false);
1569 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1570 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1575 char fileName[MAX_LOCATION];
1576 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1577 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1579 f.Printf("</a></TD>\n");
1582 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1586 f.Printf("</TR>\n");
1589 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1591 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1592 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1594 f.Printf("<TR><TD> </TD></TR>");
1597 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1599 DocPrintType(method.dataType.returnType, string, false, false);
1600 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1605 char fileName[MAX_LOCATION];
1606 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1607 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1609 f.Printf("</a> </TD>\n");
1612 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1615 f.Printf("</TR>\n");
1616 f.Printf("</TABLE>\n");
1618 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1619 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1621 f.Printf("</TABLE><br>\n");
1624 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1627 f.Printf($"<H3>Usage</H3><BR>\n");
1630 char fileName[MAX_LOCATION];
1631 FigureFileName(fileName, module, methodDoc, method, usage, null);
1632 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1637 f.Printf("<br>%s\n", usageDoc);
1638 f.Printf("<br><br><br>\n");
1643 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1646 f.Printf($"<H3>Example</H3><BR>\n");
1647 f.Printf($"<FONT face=\"Courier New\">\n");
1648 f.Printf("<br><TABLE>\n");
1651 char fileName[MAX_LOCATION];
1652 FigureFileName(fileName, module, methodDoc, method, example, null);
1653 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1655 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1658 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1659 f.Printf("</TABLE></FONT>\n");
1660 f.Printf("<br><br>\n");
1665 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1668 f.Printf($"<H3>Remarks</H3><BR>\n");
1671 char fileName[MAX_LOCATION];
1672 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1673 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1678 f.Printf("<br>%s\n", method, remarksDoc);
1679 f.Printf("<br><br><br>\n");
1684 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1687 f.Printf($"<H3>See Also</H3><BR>\n");
1690 char fileName[MAX_LOCATION];
1691 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1692 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1697 f.Printf("<br>%s\n", method, seeAlsoDoc);
1699 f.Printf("<br><br><br>\n");
1703 f.Printf("</FONT></BODY></HTML>\n");
1707 class APIPageFunction : APIPage
1709 GlobalFunction function;
1713 return function.module;
1716 NameSpace * GetNameSpace()
1718 return function.nameSpace;
1721 void Generate(File f)
1724 Module module = function.module;
1726 char nsName[1024], temp[1024];
1727 NameSpace * ns = function.nameSpace;
1730 while(ns && ns->name)
1732 strcpy(temp, ns->name);
1733 if(nsName[0]) strcat(temp, "::");
1734 strcat(temp, nsName);
1735 strcpy(nsName, temp);
1739 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1740 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1742 f.Printf($"Module: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", (module && module.name) ? module : null, (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
1745 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1747 if(!function.dataType)
1748 function.dataType = ProcessTypeString(function.dataTypeString, false);
1750 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1752 f.Printf($"this pointer class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.dataType.thisClass.registered, function.dataType.thisClass.registered.name);
1755 // Generate Method Page
1757 if(!function.dataType.name)
1758 function.dataType.name = CopyString(function.name);
1759 DocPrintType(function.dataType, string, true, false);
1760 f.Printf("<br>%s", string);
1763 char * desc = ReadDoc(module, functionDoc, function, description, null);
1766 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1769 char fileName[MAX_LOCATION];
1770 FigureFileName(fileName, module, functionDoc, function, description, null);
1771 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1776 f.Printf("%s", desc);
1778 f.Printf("<BR><BR>");
1781 f.Printf("<br><br>\n");
1782 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1784 f.Printf($"<H3>Parameters</H3><BR>\n");
1786 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1787 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1789 f.Printf("<TABLE valign=center>\n");
1792 for(param = function.dataType.params.first; param; param = param.next)
1794 // ADD DESCRIPTION HERE
1795 if(param.kind != voidType)
1797 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1800 DocPrintType(param, string, false, false);
1802 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1803 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1808 char fileName[MAX_LOCATION];
1809 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1810 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1813 f.Printf("</a> </TD>\n");
1816 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1819 f.Printf("</TR>\n");
1822 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1824 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1825 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1827 f.Printf("<TR><TD> </TD></TR>");
1830 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1832 DocPrintType(function.dataType.returnType, string, false, false);
1833 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1838 char fileName[MAX_LOCATION];
1839 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1840 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1842 f.Printf("</a> </TD>\n");
1845 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1848 f.Printf("</TR>\n");
1849 f.Printf("</TABLE>\n");
1851 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1852 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1854 f.Printf("</TABLE><br>\n");
1857 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1860 f.Printf($"<H3>Usage</H3><BR>\n");
1863 char fileName[MAX_LOCATION];
1864 FigureFileName(fileName, module, functionDoc, function, usage, null);
1865 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1870 f.Printf("<br>%s\n", usageDoc);
1871 f.Printf("<br><br><br>\n");
1876 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1879 f.Printf($"<H3>Example</H3><BR>\n");
1880 f.Printf($"<FONT face=\"Courier New\">\n");
1881 f.Printf("<br><TABLE>\n");
1884 char fileName[MAX_LOCATION];
1885 FigureFileName(fileName, module, functionDoc, function, example, null);
1886 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1888 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1891 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1892 f.Printf("</TABLE></FONT>\n");
1893 f.Printf("<br><br>\n");
1898 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1901 f.Printf($"<H3>Remarks</H3><BR>\n");
1904 char fileName[MAX_LOCATION];
1905 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1906 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1911 f.Printf("<br>%s\n", remarksDoc);
1912 f.Printf("<br><br><br>\n");
1917 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1920 f.Printf($"<H3>See Also</H3><BR>\n");
1923 char fileName[MAX_LOCATION];
1924 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1925 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1930 f.Printf("<br>%s\n", seeAlsoDoc);
1931 f.Printf("<br><br><br>\n");
1935 f.Printf("</FONT></BODY></HTML>\n");
1939 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1943 NameSpace * nameSpace = mainNameSpace;
1945 DataRow classesRow = null;
1946 DataRow functionsRow = null, definesRow = null;
1949 strcpy(nsName, parentName ? parentName : "");
1953 strcat(nsName, "::");
1954 strcat(nsName, nameSpace->name);
1959 row = parentRow.AddRow();
1960 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1961 row.tag = (int64)nameSpace;
1962 row.icon = mainForm.icons[typeNameSpace];
1966 // "Global NameSpace"
1968 page = parentRow.GetData(null);
1971 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1973 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1974 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1976 if(comNameSpace != null)
1978 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1980 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1982 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1987 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1989 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1991 if(nameSpace->classes.first)
1995 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1998 if(!cl.templateClass /*&& !cl.internalDecl*/ && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
2000 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
2001 AddClass(classesRow, module, cl, nsName, showPrivate);
2008 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2010 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2012 if(nameSpace->functions.first)
2016 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2019 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2021 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2023 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2024 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2031 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2033 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2035 if(nameSpace->defines.first)
2039 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2042 //if(def.module == module)
2044 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2046 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2047 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2055 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2059 if(!member.dataType)
2060 member.dataType = ProcessTypeString(member.dataTypeString, false);
2064 DocPrintType(member.dataType, string, true, false);
2066 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2067 for(c = 0; c<indent; c++)
2068 f.Printf(" ");
2069 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2070 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2071 if(member.type == normalMember)
2073 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2078 char fileName[MAX_LOCATION];
2079 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2080 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2082 f.Printf("</a></TD>");
2085 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2090 f.Printf("<TD valign=top height=22></TD>");
2092 if(member.type != normalMember)
2094 DataMember subMember;
2095 for(subMember = member.members.first; subMember; subMember = subMember.next)
2097 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2099 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2103 f.Printf("</TR><br>\n");
2106 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2109 if(member.type == normalMember)
2111 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2112 row.tag = (int64)member;
2117 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2118 row.icon = mainForm.icons[typeData];
2119 row.tag = (int64)member;
2121 for(m = member.members.first; m; m = m.next)
2123 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2124 AddDataMember(row, page, m);
2129 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2134 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2135 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2138 row = parentRow.AddRow();
2139 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2140 row.tag = (int64)cl;
2141 row.collapsed = true;
2142 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2145 if(cl.methods.first)
2147 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2149 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2152 if(!method.dataType)
2153 ProcessMethodType(method);
2154 if(method.type == virtualMethod)
2156 if(method.dataType.thisClass)
2158 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2159 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2160 mRow.tag = (int64)method;
2164 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2165 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2166 mRow.tag = (int64)method;
2171 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2172 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2173 mRow.tag = (int64)method;
2179 if(cl.membersAndProperties.first)
2181 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2183 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2186 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2190 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2191 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2192 mRow.tag = (int64)prop;
2196 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2197 AddDataMember(membersRow, page, (DataMember)prop);
2203 if(cl.conversions.first)
2205 for(prop = cl.conversions.first; prop; prop = prop.next)
2209 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2210 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2211 if(name) name += 2; else name = prop.name;
2212 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2213 mRow.tag = (int64)prop;
2216 if(cl.type == enumClass)
2218 EnumClassData enumeration = (EnumClassData)cl.data;
2220 for(item = enumeration.values.first; item; item = item.next)
2223 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2224 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2225 mRow.tag = (int64)item;
2230 class AddressBar : Window
2232 background = activeBorder;
2236 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2238 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2240 MainForm mainForm = (MainForm)parent;
2241 FileDialog fileDialog = mainForm.fileDialog;
2242 if(fileDialog.Modal() == ok)
2243 mainForm.OpenModule(fileDialog.filePath);
2249 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2252 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2254 ((MainForm)parent).Back();
2260 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2263 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2265 ((MainForm)parent).Forward();
2271 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2273 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2275 ((MainForm)parent).Home();
2279 /* TODO: Search (#143/#441)
2280 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2281 Update this in the NotifyUpdate. Enter goes to the exact match.
2283 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2287 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2289 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2291 if(!disabled && (SmartKey)key == enter)
2292 ((MainForm)parent).Go(editBox.contents);
2296 void NotifyUpdate(EditBox editBox)
2298 String location = ((MainForm)parent).view.location;
2299 disabled = !strcmp(location ? location : "", editBox.contents);
2304 bool OnKeyHit(Key key, unichar ch)
2307 ((MainForm)parent).view.MakeActive();
2312 class MainForm : Window
2314 size = { 1000, 600 };
2316 borderStyle = sizable;
2319 icon = { ":documentorIcon.png" };
2320 text = $"API Documentation Browser";
2322 BitmapResource icons[CodeObjectType];
2327 for(c = 0; c < CodeObjectType::enumSize; c++)
2329 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2331 browser.AddField(DataField { dataType = class(APIPage) });
2336 Menu fileMenu { menu, $"File", f };
2337 Array<FileFilter> fileFilters
2339 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2340 { $"eC Symbol files (*.sym)", "sym" }
2343 FileDialog fileDialog
2345 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2347 MenuItem fileOpenItem
2349 fileMenu, $"Open...", o, ctrlO;
2351 bool NotifySelect(MenuItem selection, Modifiers mods)
2353 if(fileDialog.Modal() == ok)
2355 OpenModule(fileDialog.filePath);
2360 MenuItem fileSettingsItem
2362 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2364 bool NotifySelect(MenuItem selection, Modifiers mods)
2366 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2376 MenuDivider { fileMenu };
2377 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2379 void OpenModule(const char * filePath)
2381 char moduleName[MAX_LOCATION];
2382 char extension[MAX_EXTENSION];
2383 Module module = null;
2384 static char symbolsDir[MAX_LOCATION];
2387 modulesAdded.RemoveAll();
2389 FreeContext(globalContext);
2390 FreeExcludedSymbols(excludedSymbols);
2391 ::defines.Free(FreeModuleDefine);
2392 imports.Free(FreeModuleImport);
2394 FreeGlobalData(globalData);
2398 FreeTypeData(componentsApp);
2399 delete componentsApp;
2402 componentsApp = __ecere_COM_Initialize(false, 1, null);
2403 SetPrivateModule(componentsApp);
2405 StripLastDirectory(filePath, symbolsDir);
2406 SetSymbolsDir(symbolsDir);
2408 GetExtension(filePath, extension);
2410 mainForm.browser.Clear();
2412 ImportModule(filePath, normalImport, publicAccess, false);
2414 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2415 componentsApp.name = CopyString(filePath);
2417 for(module = componentsApp.allModules.first; module; module = module.next)
2419 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2423 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2424 AddComponents(componentsApp, false);
2426 GetLastDirectory(filePath, moduleName);
2427 // Extension, path and lib prefix get removed in Module::name
2430 StripExtension(moduleName);
2431 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2433 int len = strlen(moduleName) - 3;
2434 memmove(moduleName, moduleName + 3, len);
2435 moduleName[len] = 0;
2439 for(module = componentsApp.allModules.first; module; module = module.next)
2441 if(module.name && (!strcmp(module.name, moduleName)))
2444 if(!module) module = componentsApp;
2445 homeModule = module;
2446 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2448 SetSymbolsDir(null);
2451 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2454 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2455 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2458 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2460 APIPage page = row.GetData(null);
2461 if(view.edit) view.OnLeftButtonDown(0,0,0);
2462 if(page && page.page) page = page.page;
2464 view.PositionCaret(true);
2465 if(page != view.page)
2467 Window activeChild = this.activeChild;
2469 // Back / Forward Support
2470 if(row && !dontRecordHistory)
2472 if(history.count > historyPos+1)
2473 history.count = historyPos+1;
2474 historyPos = history.count-1;
2475 addressBar.back.disabled = (historyPos == 0);
2476 addressBar.forward.disabled = (historyPos >= history.count-1);
2478 history.Add((Instance)(uint64)row.tag);
2479 historyPos = history.count-1;
2481 addressBar.back.disabled = (historyPos == 0);
2482 addressBar.forward.disabled = (historyPos >= history.count-1);
2488 activeChild.Activate();
2490 else if(!view.created)
2494 page = row.GetData(null);
2495 if(page && page.page)
2499 case 1: view.GoToAnchor("Classes"); break;
2500 case 2: view.GoToAnchor("Functions"); break;
2501 case 3: view.GoToAnchor("Definitions"); break;
2502 case 4: view.GoToAnchor("VirtualMethods"); break;
2503 case 5: view.GoToAnchor("Methods"); break;
2504 case 6: view.GoToAnchor("Members"); break;
2505 case 7: view.GoToAnchor("Conversions"); break;
2506 case 8: view.GoToAnchor("EnumerationValues"); break;
2510 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2511 view.GoToAnchor(hex);
2517 view.SetScrollPosition(0, 0);
2525 this, anchor = { top = 26, bottom = 0, right = 0 };
2530 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2533 bool OnClose(bool parentClosing)
2536 view.OnLeftButtonDown(0,0,0);
2542 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2543 //mainForm.OpenModule("ec");
2544 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2545 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2547 int index = mainForm.browser.currentRow.index;
2548 int rowHeight = mainForm.browser.rowHeight;
2549 int height = mainForm.browser.clientSize.h;
2551 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2556 Array<Instance> history { };
2558 bool dontRecordHistory;
2561 bool OnKeyHit(Key key, unichar ch)
2565 case altLeft: Back(); return false;
2566 case altRight: Forward(); return false;
2573 if(historyPos < history.count-1)
2577 addressBar.back.disabled = (historyPos == 0);
2578 addressBar.forward.disabled = (historyPos >= history.count-1);
2579 sprintf(location, "api://%p", history[historyPos]);
2580 dontRecordHistory = true;
2581 view.OnOpen(location);
2582 dontRecordHistory = false;
2594 addressBar.back.disabled = (historyPos == 0);
2595 addressBar.forward.disabled = (historyPos >= history.count-1);
2596 sprintf(location, "api://%p", history[historyPos]);
2597 dontRecordHistory = true;
2598 view.OnOpen(location);
2599 dontRecordHistory = false;
2607 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2611 class EditDialog : Window
2613 borderStyle = sizable;
2614 size = { 600, 400 };
2619 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2623 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2627 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2631 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2632 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2634 class HelpView : HTMLView
2638 hasVertScroll = true;
2639 hasHorzScroll = true;
2641 char editString[MAX_LOCATION];
2647 page = mainForm.browser.currentRow.GetData(null);
2652 char docDir[MAX_LOCATION];
2654 strcpy(docDir, ideSettings.docDir);
2655 if(FileExists(docDir).isDirectory)
2657 PathCatSlash(docDir, "___docWriteTest");
2658 if(FileExists(docDir).isDirectory)
2661 if(!FileExists(docDir))
2667 if(FileExists(docDir).isDirectory)
2679 GoToAnchor(page.label);
2681 if(page.page) page = page.page;
2684 return HTMLView::OnCreate();
2695 String contents = null;
2698 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2700 if(block.type == TEXT && block.textLen)
2708 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2710 if(block.type == BR)
2712 else if(block.type == TEXT)
2713 f.Write(block.text, 1, block.textLen);
2717 if((len = f.GetSize()))
2719 contents = new char[len+1];
2720 f.Read(contents, 1, len);
2721 contents[len] = '\0';
2725 char docPath[MAX_LOCATION];
2726 char temp[MAX_LOCATION];
2727 char part[MAX_FILENAME];
2731 DocumentationType type;
2732 DocumentationItem item;
2734 NamespaceDoc nsDoc = null;
2735 ClassDoc clDoc = null;
2736 FunctionDoc fnDoc = null;
2737 MethodDoc mdDoc = null;
2739 Method method = null;
2740 GlobalFunction function = null;
2742 strcpy(temp, editString);
2743 SplitDirectory(temp, part, temp);
2744 module = (Module)strtoull(part, null, 16);
2745 SplitDirectory(temp, part, temp);
2746 object = (void *)strtoull(part, null, 16);
2747 SplitDirectory(temp, part, temp);
2748 data = (void *)strtoull(part, null, 16);
2749 SplitDirectory(temp, part, temp);
2750 if(!strcmp(part, "namespace"))
2751 type = nameSpaceDoc;
2752 else if(!strcmp(part, "function"))
2754 else if(!strcmp(part, "class"))
2756 else if(!strcmp(part, "method"))
2758 SplitDirectory(temp, part, temp);
2759 if(!strcmp(part, "description"))
2761 else if(!strcmp(part, "usage"))
2763 else if(!strcmp(part, "remarks"))
2765 else if(!strcmp(part, "example"))
2767 else if(!strcmp(part, "seeAlso"))
2769 else if(!strcmp(part, "enumerationValue"))
2770 item = enumerationValue;
2771 else if(!strcmp(part, "definition"))
2773 else if(!strcmp(part, "conversion"))
2775 else if(!strcmp(part, "memberDescription"))
2776 item = memberDescription;
2777 else if(!strcmp(part, "propertyDescription"))
2778 item = propertyDescription;
2779 else if(!strcmp(part, "parameter"))
2781 else if(!strcmp(part, "returnValue"))
2784 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2786 /* Why invalidate this entry here?
2788 MapIterator<const String, DocCacheEntry> it { map = docCache };
2789 if(it.Index(docPath, false))
2798 case classDoc: cl = (Class)object; break;
2799 case functionDoc: function = object; break;
2800 case methodDoc: method = object; cl = method._class; break;
2805 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2807 clDoc = (ClassDoc)doc;
2809 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2811 nsDoc = (NamespaceDoc)doc;
2817 if(type == functionDoc)
2819 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2820 if(name) name += 2; else name = function.name;
2821 fnDoc = nsDoc.functions ? nsDoc.functions[name] : null;
2822 if(!empty && !fnDoc)
2824 if(!nsDoc.functions) nsDoc.functions = { };
2825 nsDoc.functions[name] = fnDoc = { };
2828 else if(type == methodDoc)
2830 mdDoc = clDoc.methods ? clDoc.methods[method.name] : null;
2831 if(!empty && !mdDoc)
2833 if(!clDoc.methods && !empty) clDoc.methods = { };
2834 clDoc.methods[method.name] = mdDoc = { };
2838 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2843 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2844 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2845 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2846 else { nsDoc.description = contents; contents = null; }
2849 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2850 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2851 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2854 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2855 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2856 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2859 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2860 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2861 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2864 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2865 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2866 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2869 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2870 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2872 case enumerationValue:
2874 ValueDoc itDoc = clDoc.values ? clDoc.values[((NamedLink)data).name] : null;
2877 if(!empty && !itDoc)
2879 if(!clDoc.values) clDoc.values = { };
2880 clDoc.values[((NamedLink)data).name] = itDoc = { };
2882 itDoc.description = contents; contents = null;
2885 MapIterator<String, ValueDoc> it { map = clDoc.values };
2886 if(it.Index(((NamedLink)data).name, false))
2895 DefineDoc itDoc = nsDoc.defines ? nsDoc.defines[((Definition)data).name] : null;
2898 if(!empty && !itDoc)
2900 if(!nsDoc.defines) nsDoc.defines = { };
2901 nsDoc.defines[((Definition)data).name] = itDoc = { };
2903 itDoc.description = contents; contents = null;
2906 MapIterator<String, DefineDoc> it { map = nsDoc.defines };
2907 if(it.Index(((Definition)data).name, false))
2916 ConversionDoc itDoc;
2917 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2918 if(name) name += 2; else name = ((Property)data).name;
2919 itDoc = clDoc.conversions ? clDoc.conversions[name] : null;
2922 if(!empty && !itDoc)
2924 if(!clDoc.conversions) clDoc.conversions = { };
2925 clDoc.conversions[name] = itDoc = { };
2927 itDoc.description = contents; contents = null;
2930 MapIterator<String, ConversionDoc> it { map = clDoc.conversions };
2931 if(it.Index(name, false))
2938 case memberDescription:
2940 FieldDoc itDoc = clDoc.fields ? clDoc.fields[((DataMember)data).name] : null;
2943 if(!empty && !itDoc)
2945 if(!clDoc.fields) clDoc.fields = { };
2946 clDoc.fields[((DataMember)data).name] = itDoc = { };
2948 itDoc.description = contents; contents = null;
2951 MapIterator<String, FieldDoc> it { map = clDoc.fields };
2952 if(it.Index(((DataMember)data).name, false))
2959 case propertyDescription:
2961 PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null;
2964 if(!empty && !itDoc)
2966 if(!clDoc.properties) clDoc.properties = { };
2967 clDoc.properties[((Property)data).name] = itDoc = { };
2969 itDoc.description = contents, contents = null;
2972 MapIterator<String, PropertyDoc> it { map = clDoc.properties };
2973 if(it.Index(((Property)data).name, false))
2982 if(type == functionDoc || type == methodDoc)
2984 Map<String, ParameterDoc> * parameters = (type == functionDoc) ? &fnDoc.parameters : &mdDoc.parameters;
2985 char * name = ((Type)data).name;
2986 ParameterDoc itDoc = *parameters ? (*parameters)[name] : null;
2989 while(prev) position++, prev = prev.prev;
2993 if(!empty && !itDoc)
2995 if(!*parameters) *parameters = { };
2996 (*parameters)[name] = itDoc = { };
2998 itDoc.description = contents; contents = null;
2999 itDoc.position = position;
3002 MapIterator<String, ParameterDoc> it { map = *parameters };
3003 if(it.Index(((Type)data).name, false))
3015 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
3017 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
3018 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
3019 if(name) name += 2; else name = function.name;
3020 if(it.Index(name, false))
3024 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
3026 MapIterator<String, MethodDoc> it { map = clDoc.methods };
3027 if(it.Index(method.name, false))
3033 if(nsDoc.functions && !nsDoc.functions.count) delete nsDoc.functions;
3034 if(nsDoc.defines && !nsDoc.defines.count) delete nsDoc.defines;
3038 if(clDoc && clDoc.conversions && !clDoc.conversions.count) delete clDoc.conversions;
3039 if(clDoc && clDoc.properties && !clDoc.properties.count) delete clDoc.properties;
3040 if(clDoc && clDoc.fields && !clDoc.fields.count) delete clDoc.fields;
3041 if(clDoc && clDoc.methods && !clDoc.methods.count) delete clDoc.methods;
3042 if(clDoc && clDoc.values && !clDoc.values.count) delete clDoc.values;
3047 char dirPath[MAX_LOCATION];
3048 StripLastDirectory(docPath, dirPath);
3049 if(FileExists(docPath))
3050 DeleteFile(docPath);
3051 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
3054 if(!FileExists(dirPath))
3056 if((f = FileOpen(docPath, write)))
3058 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3062 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3071 Block parent = textBlock.parent;
3072 while((block = parent.subBlocks.first))
3074 parent.subBlocks.Remove(block);
3077 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3078 textBlock.text = CopyString($"[Add Text]");
3079 textBlock.textLen = strlen(textBlock.text);
3080 parent.subBlocks.Add(textBlock);
3088 PositionCaret(true);
3093 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3097 if(edit && (!textBlock || overLink != textBlock.parent))
3101 HTMLView::OnLeftButtonDown(x, y, mods);
3102 selPosition = curPosition = 0;
3103 selBlock = textBlock;
3107 result = HTMLView::OnLeftButtonDown(x, y, mods);
3109 if(!edit && clickedLink)
3112 if(clickedLink == overLink && clickedLink.href)
3114 if(OnOpen(clickedLink.href))
3122 if(textBlock && overLink == textBlock.parent)
3124 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3125 selBlock = textBlock;
3126 PositionCaret(true);
3134 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3136 if(!edit || !textBlock || clickedLink != textBlock.parent)
3138 HTMLView::OnLeftButtonUp(x, y, mods);
3141 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3142 selBlock = textBlock;
3143 PositionCaret(true);
3154 bool OnMouseMove(int x, int y, Modifiers mods)
3156 if(edit && selecting)
3158 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3159 PositionCaret(true);
3162 return HTMLView::OnMouseMove(x, y, mods);
3165 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3167 if(edit && textBlock)
3173 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3174 selBlock = textBlock;
3175 for(c = curPosition; c >= 0; c--)
3178 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3179 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3180 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3186 for(c = start; c < textBlock.textLen; c += numBytes)
3188 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3189 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3192 selPosition = start;
3195 PositionCaret(true);
3203 bool OnOpen(char * href)
3205 if(!strncmp(href, "api://", 6))
3207 int64 tag = (int64)strtoull(href + 6, null, 16);
3208 DataRow row = mainForm.browser.FindSubRow(tag);
3212 mainForm.browser.SelectRow(row);
3213 while((row = row.parent))
3214 row.collapsed = false;
3215 row = mainForm.browser.currentRow;
3216 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3219 else if(!strncmp(href, "edit://", 7))
3222 int startX = clickedLink.startX, startY = clickedLink.startY;
3223 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3225 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3226 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3228 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3230 display.FontExtent(block.font.font, " ", 1, null, &th);
3233 block.parent.subBlocks.Insert(null, newBlock);
3238 block.parent.subBlocks.Insert(block, newBlock);
3239 startY += block.prev.height;
3241 newBlock.startX = startX;
3242 newBlock.startY = startY;
3243 newBlock.text = new0 char[1];
3247 textBlock = (Block)clickedLink.subBlocks.first;
3248 if(!strcmp(textBlock.text, $"[Add Text]"))
3250 textBlock.text[0] = 0;
3251 textBlock.textLen = 0;
3254 strcpy(editString, href + 7);
3255 selPosition = curPosition = 0;
3256 selBlock = textBlock;
3259 // PositionCaret(true);
3266 void DeleteSelection()
3268 if(textBlock != selBlock || curPosition != selPosition)
3270 if(textBlock == selBlock)
3272 // Within same block
3273 int start = Min(curPosition, selPosition);
3274 int end = Max(curPosition, selPosition);
3275 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3276 textBlock.textLen -= end-start;
3277 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3278 curPosition = start;
3279 selPosition = start;
3283 int startSel, endSel;
3284 Block startSelBlock = null, endSelBlock = null, b, next;
3286 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3288 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3289 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3291 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3292 for(b = startSelBlock.next; b; b = next)
3294 bool isEnd = b == endSelBlock;
3295 next = GetNextBlock(b);
3296 b.parent.subBlocks.Remove(b);
3301 textBlock = startSelBlock;
3302 selBlock = startSelBlock;
3303 curPosition = startSel;
3304 selPosition = startSel;
3308 PositionCaret(true);
3313 String GetSelectionString()
3315 String selection = null;
3316 if(textBlock == selBlock)
3318 // Within same block
3319 int start = Min(curPosition, selPosition);
3320 int end = Max(curPosition, selPosition);
3321 int len = end - start;
3322 selection = new char[len + 1];
3323 memcpy(selection, textBlock.text + start, len);
3328 int startSel, endSel;
3329 Block startSelBlock = null, endSelBlock = null, b;
3332 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3335 for(b = startSelBlock; b; b = GetNextBlock(b))
3337 int start = (b == startSelBlock) ? startSel : 0;
3338 int end = (b == endSelBlock) ? endSel : b.textLen;
3339 int len = end - start;
3341 if(b == endSelBlock)
3343 else if(b.type == TEXT)
3347 selection = new char[totalLen + 1];
3349 for(b = startSelBlock; b; b = GetNextBlock(b))
3351 int start = (b == startSelBlock) ? startSel : 0;
3352 int end = (b == endSelBlock) ? endSel : b.textLen;
3353 int len = end - start;
3354 memcpy(selection + totalLen, b.text + start, len);
3356 if(b == endSelBlock)
3358 else if(b.type == TEXT)
3359 selection[totalLen++] = '\n';
3361 selection[totalLen] = 0;
3366 void CopySelection()
3368 String s = GetSelectionString();
3371 int len = strlen(s);
3373 if(cb.Allocate(len + 1))
3375 memcpy(cb.text, s, len + 1);
3383 bool OnKeyDown(Key key, unichar ch)
3390 OnLeftButtonDown(0,0,0);
3392 case Key { end, shift = true }:
3394 curPosition = textBlock.textLen;
3397 selPosition = curPosition;
3398 selBlock = textBlock;
3400 PositionCaret(true);
3403 case Key { home, shift = true }:
3408 selPosition = curPosition;
3409 selBlock = textBlock;
3411 PositionCaret(true);
3414 case Key { home, ctrl = true, shift = true }:
3417 while(textBlock.prev)
3418 textBlock = textBlock.prev.prev;
3421 selPosition = curPosition;
3422 selBlock = textBlock;
3424 PositionCaret(true);
3427 case Key { end, ctrl = true, shift = true }:
3429 while(textBlock.next && textBlock.next.next)
3430 textBlock = textBlock.next.next;
3431 curPosition = textBlock.textLen;
3434 selPosition = curPosition;
3435 selBlock = textBlock;
3437 PositionCaret(true);
3443 return HTMLView::OnKeyDown(key, ch);
3447 bool OnKeyHit(Key key, unichar ch)
3453 case Key { up, shift = true }:
3456 if(caretY == textBlock.startY)
3460 textBlock = textBlock.prev.prev;
3461 curPosition = Min(curPosition, textBlock.textLen);
3464 selPosition = curPosition;
3465 selBlock = textBlock;
3468 PositionCaret(false);
3478 int sx = textBlock.startX, sy = textBlock.startY;
3479 char * text = textBlock.text;
3481 Block block = textBlock;
3482 while(block && block.type != TD) block = block.parent;
3485 Block table = block;
3486 while(table && table.type != TABLE) table = table.parent;
3488 maxW = block.w - 2* table.cellPadding;
3490 maxW = clientSize.w - 10 - sx;
3493 maxW = clientSize.w - 10 - sx;
3494 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3498 int startPos = textPos;
3501 bool lineComplete = false;
3502 for(; textPos<textBlock.textLen && !lineComplete;)
3506 char * nextSpace = strchr(text + textPos, ' ');
3509 len = (nextSpace - (text + textPos)) + 1;
3511 len = textBlock.textLen - textPos;
3513 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3515 if(x + width + w > maxW && x > 0)
3517 lineComplete = true;
3527 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3530 curPosition = textPos;
3531 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3534 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3535 len = curPosition - startPos;
3536 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3540 selPosition = curPosition;
3541 selBlock = textBlock;
3545 PositionCaret(false);
3549 if(sy == caretY - th || textPos == textBlock.textLen)
3551 if(textPos != textBlock.textLen)
3553 int c = textPos - 1;
3554 while(c > 0 && text[c] == ' ') c--;
3555 curPosition = c + 1;
3558 selPosition = curPosition;
3559 selBlock = textBlock;
3565 curPosition = textBlock.textLen;
3568 selPosition = curPosition;
3569 selBlock = textBlock;
3573 PositionCaret(false);
3577 sx = textBlock.startX;
3578 } while(textPos < textBlock.textLen);
3583 case Key { down, shift = true }:
3588 int sx = textBlock.startX, sy = textBlock.startY;
3589 char * text = textBlock.text;
3591 Block block = textBlock;
3592 while(block && block.type != TD) block = block.parent;
3595 Block table = block;
3596 while(table && table.type != TABLE) table = table.parent;
3598 maxW = block.w - 2* table.cellPadding;
3600 maxW = clientSize.w - 10 - sx;
3603 maxW = clientSize.w - 10 - sx;
3604 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3606 while(!textPos || textPos < textBlock.textLen)
3608 int startPos = textPos;
3611 bool lineComplete = false;
3612 for(; (textPos < textBlock.textLen) && !lineComplete;)
3616 char * nextSpace = strchr(text + textPos, ' ');
3619 len = (nextSpace - (text + textPos)) + 1;
3621 len = textBlock.textLen - textPos;
3623 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3625 if(x + width + w > maxW && x > 0)
3627 lineComplete = true;
3637 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3639 curPosition = textPos;
3641 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3644 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3645 len = curPosition - startPos;
3646 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3650 selPosition = curPosition;
3651 selBlock = textBlock;
3654 PositionCaret(false);
3660 curPosition = textBlock.textLen;
3663 selPosition = curPosition;
3664 selBlock = textBlock;
3667 PositionCaret(false);
3670 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3674 textBlock = textBlock.next.next;
3675 sy = textBlock.startY;
3676 sx = textBlock.startX;
3677 text = textBlock.text;
3682 sx = textBlock.startX;
3686 /*if(textBlock.next && textBlock.next.next)
3688 textBlock = textBlock.next.next;
3689 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3690 selBlock = textBlock;
3691 PositionCaret(false);
3695 case Key { right, shift = true, ctrl = true }:
3698 bool foundAlpha = false;
3700 Block line, lastLine;
3703 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3705 int start = (line == textBlock) ? curPosition : 0;
3707 for(c = start; c < line.textLen; c++)
3709 char ch = line.text[c];
3710 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3711 if(key.shift ? isAlUnder : !isAlUnder)
3725 selPosition = curPosition;
3726 selBlock = textBlock;
3730 PositionCaret(true);
3735 // No next word found,
3736 if(!found && (c != curPosition || line != textBlock))
3740 lastC = line.textLen-1;
3745 curPosition = line.textLen;
3748 selPosition = curPosition;
3749 selBlock = textBlock;
3754 PositionCaret(true);
3760 if(key.shift && found)
3762 curPosition = lastC+1;
3763 textBlock = lastLine;
3764 PositionCaret(true);
3769 case Key { left, ctrl = true, shift = true }:
3772 bool foundAlpha = false;
3774 Block line, lastLine;
3777 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3780 if(curPosition == 0 && line != textBlock)
3783 lastC = line.textLen;
3787 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3788 for(c = start; c>=0; c--)
3790 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3805 // No next word found,
3806 if(!found && curPosition > 0)
3816 textBlock = lastLine;
3817 curPosition = lastC;
3820 selPosition = curPosition;
3821 selBlock = textBlock;
3823 PositionCaret(true);
3828 case Key { right, shift = true }:
3830 if(curPosition < textBlock.textLen)
3832 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3835 selPosition = curPosition;
3836 selBlock = textBlock;
3838 PositionCaret(true);
3841 else if(textBlock.next && textBlock.next.next)
3843 textBlock = textBlock.next.next;
3847 selPosition = curPosition;
3848 selBlock = textBlock;
3850 PositionCaret(true);
3854 case Key { left, shift = true }:
3858 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3861 selPosition = curPosition;
3862 selBlock = textBlock;
3864 PositionCaret(true);
3867 else if(textBlock.prev)
3869 textBlock = textBlock.prev.prev;
3870 curPosition = textBlock.textLen;
3873 selPosition = curPosition;
3874 selBlock = textBlock;
3876 PositionCaret(true);
3882 if(textBlock == selBlock && curPosition == selPosition)
3886 int c = curPosition;
3888 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3889 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3890 textBlock.textLen -= nb;
3891 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3893 selPosition = curPosition;
3894 selBlock = textBlock;
3898 PositionCaret(true);
3901 else if(textBlock.prev)
3903 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3904 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3905 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3907 selPosition = curPosition = prevBlock.textLen;
3908 selBlock = textBlock;
3909 prevBlock.textLen += textBlock.textLen;
3910 textBlock.parent.subBlocks.Remove(prev);
3911 if(prev == selBlock)
3913 selBlock = textBlock;
3914 selPosition = curPosition;
3917 textBlock.parent.subBlocks.Remove(textBlock);
3918 if(textBlock == selBlock)
3920 selBlock = prevBlock;
3921 selPosition = curPosition;
3924 textBlock = prevBlock;
3928 PositionCaret(true);
3937 if(textBlock != selBlock || curPosition != selPosition)
3939 else if(textBlock.textLen > curPosition)
3941 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3942 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3943 textBlock.textLen -= nb;
3944 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3949 PositionCaret(true);
3952 else if(textBlock.next && textBlock.next.next)
3954 Block next = textBlock.next, nextBlock = textBlock.next.next;
3955 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3956 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3958 textBlock.textLen += nextBlock.textLen;
3959 textBlock.parent.subBlocks.Remove(next);
3960 if(next == selBlock)
3962 selBlock = textBlock;
3963 selPosition = curPosition;
3966 textBlock.parent.subBlocks.Remove(nextBlock);
3967 if(nextBlock == selBlock)
3969 selBlock = textBlock;
3970 selPosition = curPosition;
3976 PositionCaret(true);
3990 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3991 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3992 startY = textBlock.startY;
3993 startX = textBlock.startX;
3995 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3996 textBlock.parent.subBlocks.Insert(textBlock, block);
3997 textBlock.parent.subBlocks.Insert(block, newBlock);
4001 newBlock.textLen = textBlock.textLen - curPosition;
4002 newBlock.text = new char[newBlock.textLen+1];
4003 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4004 textBlock.textLen = curPosition;
4005 textBlock.text[curPosition] = 0;
4007 newBlock.startY = startY;
4008 newBlock.startX = startX;
4009 selPosition = curPosition = 0;
4014 textBlock = newBlock;
4015 selBlock = textBlock;
4016 PositionCaret(true);
4021 case Key { del, shift = true }:
4036 ClipBoard clipBoard { };
4037 if(clipBoard.Load())
4040 char * text = clipBoard.memory;
4048 parent = textBlock.parent;
4049 font = textBlock.font;
4054 if(ch == '\n' || ch == '\r' || !ch)
4056 int len = c - start;
4057 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4058 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4059 memcpy(textBlock.text + curPosition, text + start, len);
4060 textBlock.textLen += len;
4062 selPosition = curPosition;
4063 selBlock = textBlock;
4066 Block block { type = BR, parent = parent, font = font };
4067 Block newBlock { type = TEXT, parent = parent, font = font };
4068 int startY = textBlock.startY, startX = textBlock.startX;
4071 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4072 textBlock.parent.subBlocks.Insert(textBlock, block);
4073 textBlock.parent.subBlocks.Insert(block, newBlock);
4077 newBlock.textLen = textBlock.textLen - curPosition;
4078 newBlock.text = new char[newBlock.textLen+1];
4079 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4080 textBlock.textLen = curPosition;
4081 textBlock.text[curPosition] = 0;
4083 newBlock.startY = startY;
4084 newBlock.startX = startX;
4085 selPosition = curPosition = 0;
4086 selBlock = textBlock;
4087 textBlock = newBlock;
4089 if(ch == '\r' && text[c+1] == '\n') c++;
4095 PositionCaret(true);
4103 // eC BUG HERE: (Should be fixed)
4104 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4107 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4112 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4113 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4115 for(c = 0; c<len; c++)
4117 textBlock.text[curPosition] = string[c];
4118 textBlock.textLen++;
4121 selPosition = curPosition;
4122 selBlock = textBlock;
4125 //Clear(html.block);
4126 //CreateForms(html.block);
4131 PositionCaret(true);
4140 void OnResize(int width, int height)
4142 HTMLView::OnResize(width, height);
4143 PositionCaret(true);
4147 void PositionCaret(bool setCaretX)
4153 int sx = textBlock.startX, sy = textBlock.startY;
4154 char * text = textBlock.text;
4156 Block block = textBlock;
4157 while(block && block.type != TD) block = block.parent;
4160 Block table = block;
4161 while(table && table.type != TABLE) table = table.parent;
4163 maxW = block.w - 2* table.cellPadding;
4165 maxW = clientSize.w - 10 - sx;
4168 maxW = clientSize.w - 10 - sx;
4170 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4172 while(textPos < textBlock.textLen)
4174 int startPos = textPos;
4177 bool lineComplete = false;
4179 for(; textPos<textBlock.textLen && !lineComplete;)
4183 char * nextSpace = strchr(text + textPos, ' ');
4186 len = (nextSpace - (text + textPos)) + 1;
4188 len = textBlock.textLen - textPos;
4190 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4192 if(x + width + w > maxW && x > 0)
4194 lineComplete = true;
4207 if(curPosition < textPos || textPos == textBlock.textLen)
4209 int len = curPosition - startPos;
4210 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4215 sx = textBlock.startX;
4220 SetCaret(sx, sy, th);
4222 Point scrollPos = scroll;
4223 bool doScroll = false;
4224 if(sy - scroll.y + th > clientSize.h)
4226 scrollPos.y = sy + th - clientSize.h;
4229 else if(sy - scroll.y < 0)
4234 if(sx - scroll.x + 10 > clientSize.w)
4236 scrollPos.x = sx + 10 - clientSize.w;
4239 else if(sx - scroll.x < 10)
4241 scrollPos.x = sx - 10;
4252 // Returns a character offset into the TextBlock from a window coordinate
4253 int TextPosFromPoint(int px, int py, Block * block, bool half)
4255 Block parentBlock = this.textBlock.parent;
4258 *block = this.textBlock;
4263 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4265 int sx = textBlock.startX, sy = textBlock.startY;
4268 char * text = textBlock.text;
4270 Block b = textBlock;
4273 if(textBlock.type != TEXT) continue;
4275 while(b && b.type != TD) b = b.parent;
4279 while(table && table.type != TABLE) table = table.parent;
4281 maxW = b.w - 2* table.cellPadding;
4283 maxW = clientSize.w - 10 - sx;
4286 maxW = clientSize.w - 10 - sx;
4288 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4289 //space = space/2+2;
4292 while(textPos < textBlock.textLen)
4296 bool lineComplete = false;
4298 for(; textPos<textBlock.textLen && !lineComplete;)
4302 char * nextSpace = strchr(text + textPos, ' ');
4305 len = (nextSpace - (text + textPos)) + 1;
4307 len = textBlock.textLen - textPos;
4309 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4311 sx = x + textBlock.startX;
4312 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4317 for(c = textPos; (ch = text[c]); c += numBytes)
4319 numBytes = UTF8_NUM_BYTES(ch);
4320 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4321 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4328 if(x + width + w > maxW && x > 0)
4330 lineComplete = true;
4343 if(/*py >= sy && */py < sy + th)
4346 return textBlock.textLen;
4351 result = textBlock.textLen;
4357 Application componentsApp;
4359 class Documentor : GuiApplication
4363 Platform os = __runtimePlatform;
4364 SetGlobalContext(globalContext);
4365 SetExcludedSymbols(&excludedSymbols);
4366 SetDefines(&::defines);
4367 SetImports(&imports);
4368 SetInDocumentor(true);
4370 SetGlobalData(globalData);
4372 settingsContainer.dataOwner = &ideSettings;
4373 settingsContainer.Load();
4374 if(!ideSettings.docDir || !ideSettings.docDir[0] )
4376 if(os == win32) // if Windows OS then
4378 char programFilesDir[MAX_LOCATION];
4379 char appData[MAX_LOCATION];
4380 char homeDrive[MAX_LOCATION];
4381 char winDir[MAX_LOCATION];
4382 GetEnvironment("APPDATA", appData, sizeof(appData));
4383 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4384 GetEnvironment("windir", winDir, sizeof(winDir));
4385 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4387 PathCat(programFilesDir, "ECERE SDK\\doc");
4388 ideSettings.docDir = programFilesDir;
4390 else if(homeDrive[0])
4392 PathCat(homeDrive, "ECERE SDK\\doc");
4393 ideSettings.docDir = homeDrive;
4397 PathCat(winDir, "..\\ECERE SDK\\doc");
4398 ideSettings.docDir = winDir;
4401 ideSettings.docDir = "C:\\ECERE SDK\\doc";
4403 else // if Os is Linux, or Mac OSX or something else
4404 ideSettings.docDir = "/usr/share/ecere/doc/";
4405 settingsContainer.Save();
4411 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4413 AddComponents(module, true);
4414 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4415 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4416 while((row = row.parent))
4417 row.collapsed = false;
4421 commandThread.Create();
4425 bool Cycle(bool idle)
4428 mainForm.Destroy(0);
4437 if(commandThread.created)
4439 console.CloseInput();
4440 console.CloseOutput();
4442 commandThread.Wait();
4446 FreeContext(globalContext);
4447 FreeExcludedSymbols(excludedSymbols);
4448 ::defines.Free(FreeModuleDefine);
4449 imports.Free(FreeModuleImport);
4451 FreeGlobalData(globalData);
4452 FreeTypeData(componentsApp);
4454 delete componentsApp;
4458 ConsoleFile console { };
4459 MainForm mainForm { };
4462 Thread commandThread
4469 console.GetLine(command, sizeof(command));
4470 if(!quit && command[0])
4473 if(!strcmpi(command, "Activate"))
4474 mainForm.Activate();
4475 else if(!strcmpi(command, "Quit"))
4483 #endif // !defined(EAR_TO_ECON_ECDOC)
4488 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4489 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4493 property bool isEmpty
4499 (description && *description));
4509 class MoreDoc : ItemDoc
4512 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4513 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4514 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4515 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4521 property bool isEmpty
4526 (usage && *usage) ||
4527 (example && *example) ||
4528 (remarks && *remarks) ||
4542 class NamespaceDoc : ItemDoc
4545 Map<String, DefineDoc> defines;
4546 Map<String, FunctionDoc> functions;
4548 property bool isEmpty
4553 (defines && defines.count) ||
4554 (functions && functions.count) ||
4565 class DefineDoc : ItemDoc { }
4567 class FunctionDoc : MoreDoc
4570 Map<String, ParameterDoc> parameters;
4571 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4574 property bool isEmpty
4579 (parameters && parameters.count) ||
4580 (returnValue && *returnValue) ||
4591 class ParameterDoc : ItemDoc
4597 class ClassDoc : MoreDoc
4600 Map<String, ValueDoc> values;
4601 Map<String, FieldDoc> fields;
4602 Map<String, PropertyDoc> properties;
4603 Map<String, ConversionDoc> conversions;
4604 Map<String, MethodDoc> methods;
4606 property bool isEmpty
4611 (values && values.count) ||
4612 (fields && fields.count) ||
4613 (properties && properties.count) ||
4614 (conversions && conversions.count) ||
4615 (methods && methods.count) ||
4629 class ValueDoc : ItemDoc { }
4631 class FieldDoc : ItemDoc { }
4633 class PropertyDoc : ItemDoc { }
4635 class ConversionDoc : ItemDoc { }
4637 class MethodDoc : FunctionDoc { }
4639 char * getDocFileNameFromTypeName(const char * typeName)
4641 char * docFileName = new char[MAX_FILENAME];
4642 const char * swap = "pointer";
4643 const char * s = typeName;
4644 char * d = docFileName;
4645 const char * end = s + strlen(typeName);
4646 int swapLen = strlen(swap);
4664 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4667 Time timeStamp; // Should this be last accessed, or last retrieved?
4676 Map<String, DocCacheEntry> docCache { };