2 #if !defined(EAR_TO_ECON_ECDOC)
6 import "SettingsDialog"
8 static Context globalContext { };
9 static OldList defines { };
10 static OldList imports { };
11 static NameSpace globalData;
12 static OldList excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left };
15 define app = (GuiApplication)__thisModule.application;
17 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
20 /*extern */int __ecereVMethodID_class_OnGetString;
24 static __attribute__((unused)) void Dummy()
27 a.OnGetString(null, null, null);
30 static bool editing = true;
32 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
34 static const char * iconNames[CodeObjectType] =
36 "<:ecere>constructs/class.png",
37 "<:ecere>constructs/data.png",
38 "<:ecere>constructs/method.png",
39 "<:ecere>constructs/event.png",
40 "<:ecere>constructs/property.png",
41 "<:ecere>constructs/namespace.png",
42 "<:ecere>constructs/dataType.png",
43 "<:ecere>constructs/enumValue.png",
44 "<:ecere>constructs/dataPrivate.png",
45 "<:ecere>constructs/methodPrivate.png",
46 "<:ecere>constructs/propertyPrivate.png"
49 void GetTemplateString(Class c, char * templateString)
51 Module m = c.module.application;
52 const char * n = c.name;
53 char * lt = strchr(n, '<');
59 memcpy(templateString, n, lt-n);
60 templateString[lt-n] = 0;
61 strcat(templateString, "</a>");
63 for(s = lt; (ch = *s); s++)
65 if(ch == '<' || ch == '>' || ch == ',')
70 char * d = templateString + strlen(templateString);
72 TrimLSpaces(curName, curName);
73 TrimRSpaces(curName, curName);
74 pc = eSystem_FindClass(m, curName);
76 sprintf(d, "%s<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name);
81 strcat(templateString, "<");
83 strcat(templateString, ">");
85 strcat(templateString, ", ");
94 strcat(templateString, curName);
102 // WARNING : This function expects a null terminated string since it recursively concatenate...
103 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
107 if(type.constant && (type.kind != pointerType && type.kind != arrayType))
108 strcat(string, "const ");
112 if(type._class && type._class.string)
115 strcat(string, type._class.string);
118 if(type._class.registered)
121 const char * s = type._class.registered.name;
122 sprintf(hex, "%p", type._class.registered.templateClass ? type._class.registered.templateClass : type._class.registered);
123 strcat(string, "<a href=\"api://");
125 strcat(string, "\" style=\"text-decoration: none;\">");
129 GetTemplateString(type._class.registered, n);
133 strcat(string, type._class.registered.name);
134 strcat(string, "</a>");
137 strcat(string, type._class.string);
144 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
145 if(funcType && funcType.kind == functionType)
148 DocPrintType(funcType.returnType, string, false, fullName);
149 strcat(string, "(*");
150 if(printName || funcType.thisClass)
153 if(funcType.thisClass)
155 strcat(string, funcType.thisClass.string);
156 strcat(string, "::");
159 strcat(string, type.name);
161 strcat(string, ")(");
162 for(param = funcType.params.first; param; param = param.next)
164 DocPrintType(param, string, false, fullName);
165 if(param.next) strcat(string, ", ");
171 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
172 if(string[strlen(string)-1] == '(')
175 strcat(string, " *");
179 case voidType: strcat(string, "void"); break;
180 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
181 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
182 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
183 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
184 case floatType: strcat(string, "float"); break;
185 case doubleType: strcat(string, "double"); break;
189 strcat(string, "struct ");
190 strcat(string, type.enumName);
192 else if(type.typeName)
194 strcat(string, type.typeName);
199 strcat(string, "struct ");
200 strcat(string,"(unnamed)");
203 strcat(string, "struct {");
204 for(member = type.members.first; member; member = member.next)
206 DocPrintType(member, string, true, fullName);
215 strcat(string, "union ");
216 strcat(string, type.enumName);
218 else if(type.typeName)
220 strcat(string, type.typeName);
224 strcat(string, "union ");
225 strcat(string,"(unnamed)");
231 strcat(string, "enum ");
232 strcat(string, type.enumName);
234 else if(type.typeName)
236 strcat(string, type.typeName);
239 strcat(string, "enum");
246 strcat(string, "dllexport ");
247 DocPrintType(type.returnType, string, false, fullName);
251 // DANGER: Testing This
257 strcat(string, type.name);
260 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
261 if(name) name += 2; else name = type.name;
262 strcat(string, "<b>");
263 strcat(string, name);
264 strcat(string, "</b>");
273 for(param = type.params.first; param; param = param.next)
275 DocPrintType(param, string, true, fullName);
276 if(param.next) strcat(string, ", ");
285 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
286 if(funcType && funcType.kind == functionType)
289 DocPrintType(funcType.returnType, string, false, fullName);
290 strcat(string, "(*");
291 if(printName || funcType.thisClass)
294 if(funcType.thisClass)
296 strcat(string, funcType.thisClass.string);
297 strcat(string, "::");
300 strcat(string, type.name);
302 strcat(string, ")(");
303 for(param = funcType.params.first; param; param = param.next)
305 DocPrintType(param, string, false, fullName);
306 if(param.next) strcat(string, ", ");
312 char baseType[1024], size[256];
313 Type arrayType = type;
317 while(arrayType.kind == TypeKind::arrayType)
320 if(arrayType.enumClass)
321 strcat(size, arrayType.enumClass.string);
322 else if(arrayType.arraySizeExp)
323 PrintExpression(arrayType.arraySizeExp, size);
324 //sprintf(string, "%s[%s]", baseType, size);
327 arrayType = arrayType.arrayType;
329 _PrintType(arrayType, baseType, printName, printFunction, fullName);
330 strcat(string, baseType);
331 strcat(string, size);
335 DocPrintType(type.arrayType, baseType, printName, fullName);
337 strcpy(size, type.enumClass.string);
338 else if(type.arraySizeExp)
339 PrintExpression(type.arraySizeExp, size);
340 //sprintf(string, "%s[%s]", baseType, size);
341 strcat(string, baseType);
343 strcat(string, size);
351 strcat(string, "...");
354 _PrintType(type.method.dataType, string, false, printFunction, fullName);
357 strcat(string, "subclass(");
358 strcat(string, type._class ? type._class.string : "int");
364 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
367 strcat(string, type.name);
372 void DocPrintType(Type type, char * string, bool printName, bool fullName)
375 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
376 if(funcType && funcType.kind == functionType && type != funcType)
380 DocPrintType(funcType.returnType, string, false, fullName);
382 _PrintType(type, string, printName, false, fullName);
386 strcat(string, type.name);
393 for(param = funcType.params.first; param; param = param.next)
395 DocPrintType(param, string, true, fullName);
396 if(param.next) strcat(string, ", ");
401 _PrintType(type, string, printName, true, fullName);
404 Map<String, bool> modulesAdded { };
405 void AddComponents(Module module, bool isDll)
410 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")) && !modulesAdded["ecereCOM"])
412 row = mainForm.browser.AddRow();
413 modulesAdded["ecereCOM"] = true;
414 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
415 row.tag = (int64)null;
416 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
419 for(m = module.modules.first; m; m = m.next)
421 if(m.importMode == publicAccess || !isDll)
422 AddComponents(m.module, true);
425 // PUT MODULE DESCRIPTION HERE
426 if(module.name && !modulesAdded[module.name] && strcmp(module.name, "ecereCOM"))
428 row = mainForm.browser.AddRow();
429 modulesAdded[module.name] = true;
430 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
431 row.tag = (int64)module;
432 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
434 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
446 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
451 virtual void Generate(File f)
456 virtual Module GetModule()
458 return page ? page.GetModule() : null;
461 virtual NameSpace * GetNameSpace()
463 return page ? page.GetNameSpace() : null;
467 enum DocumentationType
476 enum DocumentationItem
493 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
497 sprintf(hex, "%p", module);
498 strcat(fileName, hex);
499 strcat(fileName, "/");
500 sprintf(hex, "%p", object);
501 strcat(fileName, hex);
502 strcat(fileName, "/");
503 sprintf(hex, "%p", data);
504 strcat(fileName, hex);
505 strcat(fileName, "/");
506 if(type == nameSpaceDoc)
507 strcat(fileName, "namespace");
508 else if(type == functionDoc)
509 strcat(fileName, "function");
510 else if(type == classDoc)
511 strcat(fileName, "class");
512 else if(type == methodDoc)
513 strcat(fileName, "method");
514 strcat(fileName, "/");
515 if(item == description)
516 strcat(fileName, "description");
517 else if(item == usage)
518 strcat(fileName, "usage");
519 else if(item == remarks)
520 strcat(fileName, "remarks");
521 else if(item == example)
522 strcat(fileName, "example");
523 else if(item == seeAlso)
524 strcat(fileName, "seeAlso");
525 else if(item == enumerationValue)
526 strcat(fileName, "enumerationValue");
527 else if(item == definition)
528 strcat(fileName, "definition");
529 else if(item == conversion)
530 strcat(fileName, "conversion");
531 else if(item == memberDescription)
532 strcat(fileName, "memberDescription");
533 else if(item == propertyDescription)
534 strcat(fileName, "propertyDescription");
535 else if(item == parameter)
536 strcat(fileName, "parameter");
537 else if(item == returnValue)
538 strcat(fileName, "returnValue");
541 static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
543 char docPath[MAX_LOCATION];
544 NameSpace * nameSpace, * ns;
546 Method method = null;
547 GlobalFunction function = null;
548 char nsName[1024], temp[1024];
551 case nameSpaceDoc: nameSpace = object; break;
552 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
553 case functionDoc: function = object; nameSpace = function.nameSpace; break;
554 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
560 while(ns && ns->name)
562 strcpy(temp, ns->name);
564 strcat(temp, nsName);
565 strcpy(nsName, temp);
570 PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
571 //ChangeExtension(docPath, "eCdoc", docPath);
572 PathCatSlash(docPath, nsName);
575 char * name = getDocFileNameFromTypeName(cl.name);
576 PathCatSlash(docPath, name);
580 PathCatSlash(docPath, "_global-defs");
581 ChangeExtension(docPath, "econ", docPath);
584 strcpy(path, ideSettings.docDir);
585 PathCatSlash(path, docPath);
588 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
590 String contents = null;
591 NamespaceDoc nsDoc = null;
592 ClassDoc clDoc = null;
593 FunctionDoc fnDoc = null;
594 MethodDoc mdDoc = null;
596 char filePath[MAX_LOCATION];
597 Method method = null;
598 GlobalFunction function = null;
600 ItemDoc doc = getDoc(filePath, module, type, object, item, data, false);
604 case functionDoc: function = object; break;
605 case methodDoc: method = object; break;
610 if(eClass_IsDerived(doc._class, class(ClassDoc)))
612 clDoc = (ClassDoc)doc;
614 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
616 nsDoc = (NamespaceDoc)doc;
622 ItemDoc itDoc = null;
623 if(type == functionDoc)
625 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
626 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
627 if(name) name += 2; else name = function.name;
628 if(it.Index(name, false))
631 else if(type == methodDoc)
633 MapIterator<String, MethodDoc> it { map = clDoc.methods };
634 if(it.Index(method.name, false))
640 case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break;
641 case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break;
642 case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break;
643 case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break;
644 case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break;
645 case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break;
646 case enumerationValue:
647 if(clDoc && clDoc.values)
649 itDoc = clDoc.values[((NamedLink)data).name];
650 if(itDoc) s = itDoc.description;
654 if(nsDoc && nsDoc.defines)
656 itDoc = nsDoc.defines[((Definition)data).name];
657 if(itDoc) s = itDoc.description;
661 if(clDoc && clDoc.conversions)
663 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
664 if(name) name += 2; else name = ((Property)data).name;
665 itDoc = clDoc.conversions[name];
666 if(itDoc) s = itDoc.description;
669 case memberDescription:
670 if(clDoc && clDoc.fields)
672 itDoc = clDoc.fields[((DataMember)data).name];
673 if(itDoc) s = itDoc.description;
676 case propertyDescription:
677 if(clDoc && clDoc.properties)
679 itDoc = clDoc.properties[((Property)data).name];
680 if(itDoc) s = itDoc.description;
684 if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters))
686 char * name = ((Type)data).name;
687 itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ;
688 if(itDoc) s = itDoc.description;
693 contents = CopyString(s);
695 if(editing && !contents && !readOnly)
696 contents = CopyString($"[Add Text]");
700 // The filePath is returned!
701 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
705 Method method = null;
711 case classDoc: cl = (Class)object; break;
712 case methodDoc: method = object; cl = method._class; break;
715 FigureFilePath(filePath, module, type, object, item, data);
717 entry = docCache[filePath];
723 File f = FileOpen(filePath, read);
726 ECONParser parser { f = f };
727 JSONResult jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
731 if(jsonResult != success)
733 PrintLn("error: problem parsing file: ", filePath);
738 doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
741 incref doc; // Reference to return
746 entry.timeStamp = now;
749 docCache[filePath] = { now, doc };
750 incref doc; // Reference for the cache
753 //void pruneDocCache()
754 // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
756 MapIterator<String, DocCacheEntry> it { map = docCache };
757 Array<const String> toRemove { };
758 for(entry : docCache; now - entry.timeStamp > 30)
759 toRemove.Add(&entry);
760 while(toRemove.count)
762 if(it.Index(toRemove.lastIterator.data, false))
767 toRemove.Remove(toRemove.lastIterator.pointer);
774 class APIPageNameSpace : APIPage
776 NameSpace * nameSpace;
784 NameSpace * GetNameSpace()
789 void Generate(File f)
791 char nsName[1024], temp[1024];
797 while(ns && ns->name)
799 strcpy(temp, ns->name);
800 if(nsName[0]) strcat(temp, "::");
801 strcat(temp, nsName);
802 strcpy(nsName, temp);
805 // Generate Class Page
806 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
809 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
810 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);
813 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
816 ns = nameSpace->parent;
817 while(ns && ns->name)
819 strcpy(temp, ns->name);
820 if(nsName[0]) strcat(temp, "::");
821 strcat(temp, nsName);
822 strcpy(nsName, temp);
826 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
830 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
833 f.Printf($"<H3>Description</H3><BR>\n");
836 char fileName[MAX_LOCATION];
837 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
838 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
843 f.Printf("%s", desc);
844 f.Printf("<br><br><br>");
849 if(nameSpace->nameSpaces.first)
852 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
854 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
857 f.Printf($"<H3>Sub Namespaces</H3><BR>\n");
858 f.Printf("<TABLE>\n");
862 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);
867 char fileName[MAX_LOCATION];
868 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
869 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
871 f.Printf("</a></TD>");
874 f.Printf("<TD valign=top height=22> %s</TD>", desc);
877 f.Printf("</TR><br>\n");
880 f.Printf("</TABLE><br><br>\n");
883 if(nameSpace->classes.first)
886 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
888 Class cl = link.data;
889 Module module = cl.module ? cl.module : this.module;
890 if(!cl.templateClass) // && !cl.internalDecl)
892 char * desc = ReadDoc(module, classDoc, cl, description, null);
896 f.Printf($"<a name=Classes></a><H3>Classes</H3><BR>\n");
897 f.Printf("<TABLE>\n");
903 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);
908 char fileName[MAX_LOCATION];
909 FigureFileName(fileName, module, classDoc, cl, description, null);
910 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
912 f.Printf("</a></TD>");
915 f.Printf("<TD valign=top height=22>%s</TD>", desc);
922 f.Printf("</TABLE><br><br>\n");
925 if(nameSpace->functions.first)
928 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
930 GlobalFunction function = link.data;
931 Module module = function.module ? function.module : this.module;
932 char * desc = ReadDoc(module, functionDoc, function, description, null);
933 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
934 if(name) name += 2; else name = function.name;
937 f.Printf($"<a name=Functions></a><H3>Functions</H3><BR>\n");
938 f.Printf("<TABLE>\n");
942 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);
947 char fileName[MAX_LOCATION];
948 FigureFileName(fileName, module, functionDoc, function, description, null);
949 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
951 f.Printf("</a></TD>");
954 f.Printf("<TD valign=top height=22> %s</TD>", desc);
957 f.Printf("</TR><br>\n");
960 f.Printf("</TABLE><br><br>\n");
963 if(nameSpace->defines.first)
966 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
968 DefinedExpression def = link.data;
969 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
972 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><BR>\n");
973 f.Printf("<TABLE>\n");
977 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);
978 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
983 char fileName[MAX_LOCATION];
984 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
985 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
987 f.Printf("</a></TD>");
990 f.Printf("<TD valign=top height=22> %s</TD>", desc);
993 f.Printf("</TR><br>\n");
996 f.Printf("</TABLE><br><br>\n");
999 f.Printf("</FONT></BODY></HTML>\n");
1003 class APIPageClass : APIPage
1012 NameSpace * GetNameSpace()
1014 return cl.nameSpace;
1017 void Generate(File f)
1022 char nsName[1024], temp[1024];
1023 NameSpace * ns = cl.nameSpace;
1024 Module module = cl.module;
1027 while(ns && ns->name)
1029 strcpy(temp, ns->name);
1030 if(nsName[0]) strcat(temp, "::");
1031 strcat(temp, nsName);
1032 strcpy(nsName, temp);
1035 // Generate Class Page
1036 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1037 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1039 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);
1041 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1044 const char * classType = null;
1048 classType = $"Bit Collection";
1051 classType = $"Enumeration";
1054 classType = $"Structure";
1057 classType = $"Class";
1060 classType = $"Class (No header)";
1063 classType = $"Unit";
1066 classType = $"Basic Data Type";
1069 f.Printf($"Type: %s<br>\n", classType);
1072 if(cl.type != systemClass && cl.base)
1074 f.Printf($"Base Class: ");
1075 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1077 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1079 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1080 f.Printf("%s", cl.dataTypeString);
1082 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1087 char * desc = ReadDoc(module, classDoc, cl, description, null);
1090 f.Printf($"<br><H3>Description</H3><BR>\n");
1093 char fileName[MAX_LOCATION];
1094 FigureFileName(fileName, module, classDoc, cl, description, null);
1095 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1100 f.Printf("%s", desc);
1101 f.Printf("<br><br><br>");
1106 if(cl.type == enumClass)
1108 EnumClassData enumeration = (EnumClassData)cl.data;
1109 if(enumeration.values.first)
1113 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><BR>\n");
1114 f.Printf("<TABLE>\n");
1116 for(item = enumeration.values.first; item; item = item.next)
1118 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1119 bool needClass = true;
1122 char tempString[1024];
1124 while(base.type == enumClass) base = base.base;
1126 if(base.type == systemClass ||
1127 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1130 base.dataType = ProcessTypeString(base.dataTypeString, false);
1132 if(base.dataType.kind != classType)
1137 PrintType(base.dataType, string, false, true);
1138 classSym = FindClass(string);
1139 dataClass = classSym ? classSym.registered : null;
1142 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1148 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);
1149 if(dataClass.type == systemClass)
1152 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1155 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1157 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1159 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1164 char fileName[MAX_LOCATION];
1165 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1166 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1168 f.Printf("</a></TD>");
1171 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1176 f.Printf("</TABLE><BR>\n");
1180 if(cl.conversions.first)
1182 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><BR>\n");
1183 f.Printf("<TABLE>\n");
1184 for(prop = cl.conversions.first; prop; prop = prop.next)
1186 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1188 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1190 Type type = ProcessTypeString(prop.name, false);
1191 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1192 if(name) name += 2; else name = prop.name;
1197 DocPrintType(type, string, true, false);
1199 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1204 char fileName[MAX_LOCATION];
1205 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1206 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1208 f.Printf("</a></TD>");
1211 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1215 f.Printf("</TR>\n");
1220 f.Printf("</TABLE><br><br>\n");
1223 if(cl.membersAndProperties.first)
1226 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1228 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1232 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><BR>\n");
1233 f.Printf("<TABLE>\n");
1239 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1241 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1245 DocPrintType(prop.dataType, string, true, false);
1247 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);
1248 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1253 char fileName[MAX_LOCATION];
1254 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1255 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1257 f.Printf("</a></TD>");
1260 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1263 f.Printf("</TR>\n");
1267 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1272 f.Printf("</TABLE><br><br>\n");
1275 if(cl.methods.first)
1279 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1281 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1283 char * desc = ReadDoc(module, methodDoc, method, description, null);
1286 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><BR>\n");
1287 f.Printf("<TABLE>\n");
1290 if(!method.dataType)
1291 ProcessMethodType(method);
1294 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);
1299 char fileName[MAX_LOCATION];
1300 FigureFileName(fileName, module, methodDoc, method, description, null);
1301 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1303 f.Printf("</a></TD>");
1306 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1309 f.Printf("</TR><br>\n");
1313 f.Printf("</TABLE><br><br>\n");
1315 // Non-Virtual Methods
1317 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1319 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1321 char * desc = ReadDoc(module, methodDoc, method, description, null);
1324 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><BR>\n");
1325 f.Printf("<TABLE>\n");
1329 if(!method.dataType)
1330 ProcessMethodType(method);
1333 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);
1338 char fileName[MAX_LOCATION];
1339 FigureFileName(fileName, module, methodDoc, method, description, null);
1340 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1342 f.Printf("</a></TD>");
1345 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1349 f.Printf("</TR><br>\n");
1353 f.Printf("</TABLE><br><br>\n");
1356 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1359 f.Printf($"<H3>Usage</H3><BR>\n");
1362 char fileName[MAX_LOCATION];
1363 FigureFileName(fileName, module, classDoc, cl, usage, null);
1364 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1369 f.Printf("<br>%s\n", usageDoc);
1370 f.Printf("<br><br><br>\n");
1375 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1378 f.Printf($"<H3>Example</H3><BR>\n");
1379 f.Printf($"<FONT face=\"Courier New\">\n");
1380 f.Printf("<br><TABLE>\n");
1383 char fileName[MAX_LOCATION];
1384 FigureFileName(fileName, module, classDoc, cl, example, null);
1385 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1387 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1390 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1392 f.Printf("</TABLE></FONT>\n");
1393 f.Printf("<br><br>\n");
1398 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1402 f.Printf($"<H3>Remarks</H3><BR>\n");
1405 char fileName[MAX_LOCATION];
1406 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1407 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1412 f.Printf("<br>%s\n", remarksDoc);
1413 f.Printf("<br><br><br>\n");
1418 if(cl.type != systemClass)
1422 for(c = cl.derivatives.first; c; c = c.next)
1424 Class deriv = c.data;
1425 // TO VERIFY: Does this properly check public status?
1426 if(eSystem_FindClass(componentsApp, deriv.fullName))
1430 f.Printf($"<H3>Derived Classes</H3><BR>\n");
1435 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1439 f.Printf("<br><br>\n");
1442 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1445 f.Printf($"<H3>See Also</H3>\n");
1448 char fileName[MAX_LOCATION];
1449 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1450 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1455 f.Printf("<br>%s\n", seeAlsoDoc);
1456 f.Printf("<br><br>\n");
1460 f.Printf("</FONT></BODY></HTML>\n");
1464 class APIPageMethod : APIPage
1470 return method._class.module;
1473 NameSpace * GetNameSpace()
1475 return method._class.nameSpace;
1478 void Generate(File f)
1480 Class cl = method._class;
1482 Module module = cl.module;
1484 char nsName[1024], temp[1024];
1485 NameSpace * ns = cl.nameSpace;
1488 while(ns && ns->name)
1490 strcpy(temp, ns->name);
1491 if(nsName[0]) strcat(temp, "::");
1492 strcat(temp, nsName);
1493 strcpy(nsName, temp);
1497 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1498 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1500 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);
1502 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1503 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1504 if(method.dataType.staticMethod)
1506 f.Printf($"this pointer class: None<br>\n");
1508 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1510 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);
1513 // Generate Method Page
1515 if(!method.dataType.name)
1516 method.dataType.name = CopyString(method.name);
1517 DocPrintType(method.dataType, string, true, false);
1518 f.Printf("<br>%s", string);
1521 char * desc = ReadDoc(module, methodDoc, method, description, null);
1524 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1527 char fileName[MAX_LOCATION];
1528 FigureFileName(fileName, module, methodDoc, method, description, null);
1529 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1534 f.Printf("%s", desc);
1535 f.Printf("<BR><BR>");
1540 f.Printf("<br><br>\n");
1541 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1543 f.Printf($"<H3>Parameters</H3><BR>\n");
1545 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1546 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1548 f.Printf("<TABLE valign=center>\n");
1551 for(param = method.dataType.params.first; param; param = param.next)
1553 // ADD DESCRIPTION HERE
1554 if(param.kind != voidType)
1556 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1559 DocPrintType(param, string, false, false);
1561 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1562 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1567 char fileName[MAX_LOCATION];
1568 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1569 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1571 f.Printf("</a></TD>\n");
1574 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1578 f.Printf("</TR>\n");
1581 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1583 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1584 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1586 f.Printf("<TR><TD> </TD></TR>");
1589 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1591 DocPrintType(method.dataType.returnType, string, false, false);
1592 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1597 char fileName[MAX_LOCATION];
1598 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1599 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1601 f.Printf("</a> </TD>\n");
1604 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1607 f.Printf("</TR>\n");
1608 f.Printf("</TABLE>\n");
1610 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1611 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1613 f.Printf("</TABLE><br>\n");
1616 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1619 f.Printf($"<H3>Usage</H3><BR>\n");
1622 char fileName[MAX_LOCATION];
1623 FigureFileName(fileName, module, methodDoc, method, usage, null);
1624 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1629 f.Printf("<br>%s\n", usageDoc);
1630 f.Printf("<br><br><br>\n");
1635 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1638 f.Printf($"<H3>Example</H3><BR>\n");
1639 f.Printf($"<FONT face=\"Courier New\">\n");
1640 f.Printf("<br><TABLE>\n");
1643 char fileName[MAX_LOCATION];
1644 FigureFileName(fileName, module, methodDoc, method, example, null);
1645 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1647 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1650 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1651 f.Printf("</TABLE></FONT>\n");
1652 f.Printf("<br><br>\n");
1657 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1660 f.Printf($"<H3>Remarks</H3><BR>\n");
1663 char fileName[MAX_LOCATION];
1664 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1665 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1670 f.Printf("<br>%s\n", method, remarksDoc);
1671 f.Printf("<br><br><br>\n");
1676 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1679 f.Printf($"<H3>See Also</H3><BR>\n");
1682 char fileName[MAX_LOCATION];
1683 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1684 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1689 f.Printf("<br>%s\n", method, seeAlsoDoc);
1691 f.Printf("<br><br><br>\n");
1695 f.Printf("</FONT></BODY></HTML>\n");
1699 class APIPageFunction : APIPage
1701 GlobalFunction function;
1705 return function.module;
1708 NameSpace * GetNameSpace()
1710 return function.nameSpace;
1713 void Generate(File f)
1716 Module module = function.module;
1718 char nsName[1024], temp[1024];
1719 NameSpace * ns = function.nameSpace;
1722 while(ns && ns->name)
1724 strcpy(temp, ns->name);
1725 if(nsName[0]) strcat(temp, "::");
1726 strcat(temp, nsName);
1727 strcpy(nsName, temp);
1731 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1732 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1734 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);
1737 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1739 if(!function.dataType)
1740 function.dataType = ProcessTypeString(function.dataTypeString, false);
1742 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1744 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);
1747 // Generate Method Page
1749 if(!function.dataType.name)
1750 function.dataType.name = CopyString(function.name);
1751 DocPrintType(function.dataType, string, true, false);
1752 f.Printf("<br>%s", string);
1755 char * desc = ReadDoc(module, functionDoc, function, description, null);
1758 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1761 char fileName[MAX_LOCATION];
1762 FigureFileName(fileName, module, functionDoc, function, description, null);
1763 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1768 f.Printf("%s", desc);
1770 f.Printf("<BR><BR>");
1773 f.Printf("<br><br>\n");
1774 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1776 f.Printf($"<H3>Parameters</H3><BR>\n");
1778 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1779 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1781 f.Printf("<TABLE valign=center>\n");
1784 for(param = function.dataType.params.first; param; param = param.next)
1786 // ADD DESCRIPTION HERE
1787 if(param.kind != voidType)
1789 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1792 DocPrintType(param, string, false, false);
1794 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1795 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1800 char fileName[MAX_LOCATION];
1801 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1802 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1805 f.Printf("</a> </TD>\n");
1808 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1811 f.Printf("</TR>\n");
1814 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1816 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1817 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1819 f.Printf("<TR><TD> </TD></TR>");
1822 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1824 DocPrintType(function.dataType.returnType, string, false, false);
1825 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1830 char fileName[MAX_LOCATION];
1831 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1832 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1834 f.Printf("</a> </TD>\n");
1837 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1840 f.Printf("</TR>\n");
1841 f.Printf("</TABLE>\n");
1843 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1844 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1846 f.Printf("</TABLE><br>\n");
1849 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1852 f.Printf($"<H3>Usage</H3><BR>\n");
1855 char fileName[MAX_LOCATION];
1856 FigureFileName(fileName, module, functionDoc, function, usage, null);
1857 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1862 f.Printf("<br>%s\n", usageDoc);
1863 f.Printf("<br><br><br>\n");
1868 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1871 f.Printf($"<H3>Example</H3><BR>\n");
1872 f.Printf($"<FONT face=\"Courier New\">\n");
1873 f.Printf("<br><TABLE>\n");
1876 char fileName[MAX_LOCATION];
1877 FigureFileName(fileName, module, functionDoc, function, example, null);
1878 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1880 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1883 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1884 f.Printf("</TABLE></FONT>\n");
1885 f.Printf("<br><br>\n");
1890 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1893 f.Printf($"<H3>Remarks</H3><BR>\n");
1896 char fileName[MAX_LOCATION];
1897 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1898 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1903 f.Printf("<br>%s\n", remarksDoc);
1904 f.Printf("<br><br><br>\n");
1909 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1912 f.Printf($"<H3>See Also</H3><BR>\n");
1915 char fileName[MAX_LOCATION];
1916 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1917 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1922 f.Printf("<br>%s\n", seeAlsoDoc);
1923 f.Printf("<br><br><br>\n");
1927 f.Printf("</FONT></BODY></HTML>\n");
1931 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1935 NameSpace * nameSpace = mainNameSpace;
1937 DataRow classesRow = null;
1938 DataRow functionsRow = null, definesRow = null;
1941 strcpy(nsName, parentName ? parentName : "");
1945 strcat(nsName, "::");
1946 strcat(nsName, nameSpace->name);
1951 row = parentRow.AddRow();
1952 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1953 row.tag = (int64)nameSpace;
1954 row.icon = mainForm.icons[typeNameSpace];
1958 // "Global NameSpace"
1960 page = parentRow.GetData(null);
1963 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1965 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1966 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1968 if(comNameSpace != null)
1970 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1972 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1974 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1979 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1981 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1983 if(nameSpace->classes.first)
1987 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1990 if(!cl.templateClass /*&& !cl.internalDecl*/ && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1992 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1993 AddClass(classesRow, module, cl, nsName, showPrivate);
2000 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2002 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2004 if(nameSpace->functions.first)
2008 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2011 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2013 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2015 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2016 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2023 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2025 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2027 if(nameSpace->defines.first)
2031 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2034 //if(def.module == module)
2036 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2038 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2039 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2047 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2051 if(!member.dataType)
2052 member.dataType = ProcessTypeString(member.dataTypeString, false);
2056 DocPrintType(member.dataType, string, true, false);
2058 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2059 for(c = 0; c<indent; c++)
2060 f.Printf(" ");
2061 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2062 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2063 if(member.type == normalMember)
2065 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2070 char fileName[MAX_LOCATION];
2071 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2072 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2074 f.Printf("</a></TD>");
2077 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2082 f.Printf("<TD valign=top height=22></TD>");
2084 if(member.type != normalMember)
2086 DataMember subMember;
2087 for(subMember = member.members.first; subMember; subMember = subMember.next)
2089 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2091 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2095 f.Printf("</TR><br>\n");
2098 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2101 if(member.type == normalMember)
2103 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2104 row.tag = (int64)member;
2109 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2110 row.icon = mainForm.icons[typeData];
2111 row.tag = (int64)member;
2113 for(m = member.members.first; m; m = m.next)
2115 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2116 AddDataMember(row, page, m);
2121 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2126 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2127 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2130 row = parentRow.AddRow();
2131 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2132 row.tag = (int64)cl;
2133 row.collapsed = true;
2134 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2137 if(cl.methods.first)
2139 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2141 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2144 if(!method.dataType)
2145 ProcessMethodType(method);
2146 if(method.type == virtualMethod)
2148 if(method.dataType.thisClass)
2150 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2151 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2152 mRow.tag = (int64)method;
2156 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2157 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2158 mRow.tag = (int64)method;
2163 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2164 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2165 mRow.tag = (int64)method;
2171 if(cl.membersAndProperties.first)
2173 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2175 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2178 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2182 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2183 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2184 mRow.tag = (int64)prop;
2188 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2189 AddDataMember(membersRow, page, (DataMember)prop);
2195 if(cl.conversions.first)
2197 for(prop = cl.conversions.first; prop; prop = prop.next)
2201 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2202 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2203 if(name) name += 2; else name = prop.name;
2204 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2205 mRow.tag = (int64)prop;
2208 if(cl.type == enumClass)
2210 EnumClassData enumeration = (EnumClassData)cl.data;
2212 for(item = enumeration.values.first; item; item = item.next)
2215 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2216 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2217 mRow.tag = (int64)item;
2222 class AddressBar : Window
2224 background = activeBorder;
2228 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2230 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2232 MainForm mainForm = (MainForm)parent;
2233 FileDialog fileDialog = mainForm.fileDialog;
2234 if(fileDialog.Modal() == ok)
2235 mainForm.OpenModule(fileDialog.filePath);
2241 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2244 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2246 ((MainForm)parent).Back();
2252 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2255 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2257 ((MainForm)parent).Forward();
2263 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2265 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2267 ((MainForm)parent).Home();
2271 /* TODO: Search (#143/#441)
2272 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2273 Update this in the NotifyUpdate. Enter goes to the exact match.
2275 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2279 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2281 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2283 if(!disabled && (SmartKey)key == enter)
2284 ((MainForm)parent).Go(editBox.contents);
2288 void NotifyUpdate(EditBox editBox)
2290 String location = ((MainForm)parent).view.location;
2291 disabled = !strcmp(location ? location : "", editBox.contents);
2296 bool OnKeyHit(Key key, unichar ch)
2299 ((MainForm)parent).view.MakeActive();
2304 class MainForm : Window
2306 size = { 1000, 600 };
2308 borderStyle = sizable;
2311 icon = { ":documentorIcon.png" };
2312 text = $"API Documentation Browser";
2314 BitmapResource icons[CodeObjectType];
2319 for(c = 0; c < CodeObjectType::enumSize; c++)
2321 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2323 browser.AddField(DataField { dataType = class(APIPage) });
2328 Menu fileMenu { menu, $"File", f };
2329 Array<FileFilter> fileFilters
2331 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2332 { $"eC Symbol files (*.sym)", "sym" }
2335 FileDialog fileDialog
2337 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2339 MenuItem fileOpenItem
2341 fileMenu, $"Open...", o, ctrlO;
2343 bool NotifySelect(MenuItem selection, Modifiers mods)
2345 if(fileDialog.Modal() == ok)
2347 OpenModule(fileDialog.filePath);
2352 MenuItem fileSettingsItem
2354 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2356 bool NotifySelect(MenuItem selection, Modifiers mods)
2358 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2368 MenuDivider { fileMenu };
2369 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2371 void OpenModule(const char * filePath)
2373 char moduleName[MAX_LOCATION];
2374 char extension[MAX_EXTENSION];
2375 Module module = null;
2376 static char symbolsDir[MAX_LOCATION];
2379 modulesAdded.RemoveAll();
2381 FreeContext(globalContext);
2382 FreeExcludedSymbols(excludedSymbols);
2383 ::defines.Free(FreeModuleDefine);
2384 imports.Free(FreeModuleImport);
2386 FreeGlobalData(globalData);
2390 FreeTypeData(componentsApp);
2391 delete componentsApp;
2394 componentsApp = __ecere_COM_Initialize(false, 1, null);
2395 SetPrivateModule(componentsApp);
2397 StripLastDirectory(filePath, symbolsDir);
2398 SetSymbolsDir(symbolsDir);
2400 GetExtension(filePath, extension);
2402 mainForm.browser.Clear();
2404 ImportModule(filePath, normalImport, publicAccess, false);
2406 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2407 componentsApp.name = CopyString(filePath);
2409 for(module = componentsApp.allModules.first; module; module = module.next)
2411 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2415 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2416 AddComponents(componentsApp, false);
2418 GetLastDirectory(filePath, moduleName);
2419 // Extension, path and lib prefix get removed in Module::name
2422 StripExtension(moduleName);
2423 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2425 int len = strlen(moduleName) - 3;
2426 memmove(moduleName, moduleName + 3, len);
2427 moduleName[len] = 0;
2431 for(module = componentsApp.allModules.first; module; module = module.next)
2433 if(module.name && (!strcmp(module.name, moduleName)))
2436 if(!module) module = componentsApp;
2437 homeModule = module;
2438 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2440 SetSymbolsDir(null);
2443 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2446 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2447 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2450 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2452 APIPage page = row.GetData(null);
2453 if(view.edit) view.OnLeftButtonDown(0,0,0);
2454 if(page && page.page) page = page.page;
2456 view.PositionCaret(true);
2457 if(page != view.page)
2459 Window activeChild = this.activeChild;
2461 // Back / Forward Support
2462 if(row && !dontRecordHistory)
2464 if(history.count > historyPos+1)
2465 history.count = historyPos+1;
2466 historyPos = history.count-1;
2467 addressBar.back.disabled = (historyPos == 0);
2468 addressBar.forward.disabled = (historyPos >= history.count-1);
2470 history.Add((Instance)(uint64)row.tag);
2471 historyPos = history.count-1;
2473 addressBar.back.disabled = (historyPos == 0);
2474 addressBar.forward.disabled = (historyPos >= history.count-1);
2480 activeChild.Activate();
2482 else if(!view.created)
2486 page = row.GetData(null);
2487 if(page && page.page)
2491 case 1: view.GoToAnchor("Classes"); break;
2492 case 2: view.GoToAnchor("Functions"); break;
2493 case 3: view.GoToAnchor("Definitions"); break;
2494 case 4: view.GoToAnchor("VirtualMethods"); break;
2495 case 5: view.GoToAnchor("Methods"); break;
2496 case 6: view.GoToAnchor("Members"); break;
2497 case 7: view.GoToAnchor("Conversions"); break;
2498 case 8: view.GoToAnchor("EnumerationValues"); break;
2502 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2503 view.GoToAnchor(hex);
2509 view.SetScrollPosition(0, 0);
2517 this, anchor = { top = 26, bottom = 0, right = 0 };
2522 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2525 bool OnClose(bool parentClosing)
2528 view.OnLeftButtonDown(0,0,0);
2534 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2535 //mainForm.OpenModule("ec");
2536 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2537 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2539 int index = mainForm.browser.currentRow.index;
2540 int rowHeight = mainForm.browser.rowHeight;
2541 int height = mainForm.browser.clientSize.h;
2543 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2548 Array<Instance> history { };
2550 bool dontRecordHistory;
2553 bool OnKeyHit(Key key, unichar ch)
2557 case altLeft: Back(); return false;
2558 case altRight: Forward(); return false;
2565 if(historyPos < history.count-1)
2569 addressBar.back.disabled = (historyPos == 0);
2570 addressBar.forward.disabled = (historyPos >= history.count-1);
2571 sprintf(location, "api://%p", history[historyPos]);
2572 dontRecordHistory = true;
2573 view.OnOpen(location);
2574 dontRecordHistory = false;
2586 addressBar.back.disabled = (historyPos == 0);
2587 addressBar.forward.disabled = (historyPos >= history.count-1);
2588 sprintf(location, "api://%p", history[historyPos]);
2589 dontRecordHistory = true;
2590 view.OnOpen(location);
2591 dontRecordHistory = false;
2599 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2603 class EditDialog : Window
2605 borderStyle = sizable;
2606 size = { 600, 400 };
2611 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2615 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2619 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2623 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2624 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2626 class HelpView : HTMLView
2630 hasVertScroll = true;
2631 hasHorzScroll = true;
2633 char editString[MAX_LOCATION];
2639 page = mainForm.browser.currentRow.GetData(null);
2644 char docDir[MAX_LOCATION];
2646 strcpy(docDir, ideSettings.docDir);
2647 if(FileExists(docDir).isDirectory)
2649 PathCatSlash(docDir, "___docWriteTest");
2650 if(FileExists(docDir).isDirectory)
2653 if(!FileExists(docDir))
2659 if(FileExists(docDir).isDirectory)
2671 GoToAnchor(page.label);
2673 if(page.page) page = page.page;
2676 return HTMLView::OnCreate();
2687 String contents = null;
2690 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2692 if(block.type == TEXT && block.textLen)
2700 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2702 if(block.type == BR)
2704 else if(block.type == TEXT)
2705 f.Write(block.text, 1, block.textLen);
2709 if((len = f.GetSize()))
2711 contents = new char[len+1];
2712 f.Read(contents, 1, len);
2713 contents[len] = '\0';
2717 char docPath[MAX_LOCATION];
2718 char temp[MAX_LOCATION];
2719 char part[MAX_FILENAME];
2723 DocumentationType type;
2724 DocumentationItem item;
2726 NamespaceDoc nsDoc = null;
2727 ClassDoc clDoc = null;
2728 FunctionDoc fnDoc = null;
2729 MethodDoc mdDoc = null;
2731 Method method = null;
2732 GlobalFunction function = null;
2734 strcpy(temp, editString);
2735 SplitDirectory(temp, part, temp);
2736 module = (Module)strtoull(part, null, 16);
2737 SplitDirectory(temp, part, temp);
2738 object = (void *)strtoull(part, null, 16);
2739 SplitDirectory(temp, part, temp);
2740 data = (void *)strtoull(part, null, 16);
2741 SplitDirectory(temp, part, temp);
2742 if(!strcmp(part, "namespace"))
2743 type = nameSpaceDoc;
2744 else if(!strcmp(part, "function"))
2746 else if(!strcmp(part, "class"))
2748 else if(!strcmp(part, "method"))
2750 SplitDirectory(temp, part, temp);
2751 if(!strcmp(part, "description"))
2753 else if(!strcmp(part, "usage"))
2755 else if(!strcmp(part, "remarks"))
2757 else if(!strcmp(part, "example"))
2759 else if(!strcmp(part, "seeAlso"))
2761 else if(!strcmp(part, "enumerationValue"))
2762 item = enumerationValue;
2763 else if(!strcmp(part, "definition"))
2765 else if(!strcmp(part, "conversion"))
2767 else if(!strcmp(part, "memberDescription"))
2768 item = memberDescription;
2769 else if(!strcmp(part, "propertyDescription"))
2770 item = propertyDescription;
2771 else if(!strcmp(part, "parameter"))
2773 else if(!strcmp(part, "returnValue"))
2776 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2778 /* Why invalidate this entry here?
2780 MapIterator<const String, DocCacheEntry> it { map = docCache };
2781 if(it.Index(docPath, false))
2790 case classDoc: cl = (Class)object; break;
2791 case functionDoc: function = object; break;
2792 case methodDoc: method = object; cl = method._class; break;
2797 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2799 clDoc = (ClassDoc)doc;
2801 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2803 nsDoc = (NamespaceDoc)doc;
2809 if(type == functionDoc)
2811 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2812 if(name) name += 2; else name = function.name;
2813 fnDoc = nsDoc.functions ? nsDoc.functions[name] : null;
2814 if(!empty && !fnDoc)
2816 if(!nsDoc.functions) nsDoc.functions = { };
2817 nsDoc.functions[name] = fnDoc = { };
2820 else if(type == methodDoc)
2822 mdDoc = clDoc.methods ? clDoc.methods[method.name] : null;
2823 if(!empty && !mdDoc)
2825 if(!clDoc.methods && !empty) clDoc.methods = { };
2826 clDoc.methods[method.name] = mdDoc = { };
2830 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2835 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2836 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2837 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2838 else { nsDoc.description = contents; contents = null; }
2841 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2842 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2843 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2846 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2847 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2848 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2851 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2852 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2853 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2856 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2857 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2858 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2861 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2862 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2864 case enumerationValue:
2866 ValueDoc itDoc = clDoc.values ? clDoc.values[((NamedLink)data).name] : null;
2869 if(!empty && !itDoc)
2871 if(!clDoc.values) clDoc.values = { };
2872 clDoc.values[((NamedLink)data).name] = itDoc = { };
2874 itDoc.description = contents; contents = null;
2877 MapIterator<String, ValueDoc> it { map = clDoc.values };
2878 if(it.Index(((NamedLink)data).name, false))
2887 DefineDoc itDoc = nsDoc.defines ? nsDoc.defines[((Definition)data).name] : null;
2890 if(!empty && !itDoc)
2892 if(!nsDoc.defines) nsDoc.defines = { };
2893 nsDoc.defines[((Definition)data).name] = itDoc = { };
2895 itDoc.description = contents; contents = null;
2898 MapIterator<String, DefineDoc> it { map = nsDoc.defines };
2899 if(it.Index(((Definition)data).name, false))
2908 ConversionDoc itDoc;
2909 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2910 if(name) name += 2; else name = ((Property)data).name;
2911 itDoc = clDoc.conversions ? clDoc.conversions[name] : null;
2914 if(!empty && !itDoc)
2916 if(!clDoc.conversions) clDoc.conversions = { };
2917 clDoc.conversions[name] = itDoc = { };
2919 itDoc.description = contents; contents = null;
2922 MapIterator<String, ConversionDoc> it { map = clDoc.conversions };
2923 if(it.Index(name, false))
2930 case memberDescription:
2932 FieldDoc itDoc = clDoc.fields ? clDoc.fields[((DataMember)data).name] : null;
2935 if(!empty && !itDoc)
2937 if(!clDoc.fields) clDoc.fields = { };
2938 clDoc.fields[((DataMember)data).name] = itDoc = { };
2940 itDoc.description = contents; contents = null;
2943 MapIterator<String, FieldDoc> it { map = clDoc.fields };
2944 if(it.Index(((DataMember)data).name, false))
2951 case propertyDescription:
2953 PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null;
2956 if(!empty && !itDoc)
2958 if(!clDoc.properties) clDoc.properties = { };
2959 clDoc.properties[((Property)data).name] = itDoc = { };
2961 itDoc.description = contents, contents = null;
2964 MapIterator<String, PropertyDoc> it { map = clDoc.properties };
2965 if(it.Index(((Property)data).name, false))
2974 if(type == functionDoc || type == methodDoc)
2976 Map<String, ParameterDoc> * parameters = (type == functionDoc) ? &fnDoc.parameters : &mdDoc.parameters;
2977 char * name = ((Type)data).name;
2978 ParameterDoc itDoc = *parameters ? (*parameters)[name] : null;
2981 while(prev) position++, prev = prev.prev;
2985 if(!empty && !itDoc)
2987 if(!*parameters) *parameters = { };
2988 (*parameters)[name] = itDoc = { };
2990 itDoc.description = contents; contents = null;
2991 itDoc.position = position;
2994 MapIterator<String, ParameterDoc> it { map = *parameters };
2995 if(it.Index(((Type)data).name, false))
3007 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
3009 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
3010 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
3011 if(name) name += 2; else name = function.name;
3012 if(it.Index(name, false))
3016 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
3018 MapIterator<String, MethodDoc> it { map = clDoc.methods };
3019 if(it.Index(method.name, false))
3025 if(nsDoc.functions && !nsDoc.functions.count) delete nsDoc.functions;
3026 if(nsDoc.defines && !nsDoc.defines.count) delete nsDoc.defines;
3030 if(clDoc && clDoc.conversions && !clDoc.conversions.count) delete clDoc.conversions;
3031 if(clDoc && clDoc.properties && !clDoc.properties.count) delete clDoc.properties;
3032 if(clDoc && clDoc.fields && !clDoc.fields.count) delete clDoc.fields;
3033 if(clDoc && clDoc.methods && !clDoc.methods.count) delete clDoc.methods;
3034 if(clDoc && clDoc.values && !clDoc.values.count) delete clDoc.values;
3039 char dirPath[MAX_LOCATION];
3040 StripLastDirectory(docPath, dirPath);
3041 if(FileExists(docPath))
3042 DeleteFile(docPath);
3043 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
3046 if(!FileExists(dirPath))
3048 if((f = FileOpen(docPath, write)))
3050 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3054 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3063 Block parent = textBlock.parent;
3064 while((block = parent.subBlocks.first))
3066 parent.subBlocks.Remove(block);
3069 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3070 textBlock.text = CopyString($"[Add Text]");
3071 textBlock.textLen = strlen(textBlock.text);
3072 parent.subBlocks.Add(textBlock);
3080 PositionCaret(true);
3085 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3089 if(edit && (!textBlock || overLink != textBlock.parent))
3093 HTMLView::OnLeftButtonDown(x, y, mods);
3094 selPosition = curPosition = 0;
3095 selBlock = textBlock;
3099 result = HTMLView::OnLeftButtonDown(x, y, mods);
3101 if(!edit && clickedLink)
3104 if(clickedLink == overLink && clickedLink.href)
3106 if(OnOpen(clickedLink.href))
3114 if(textBlock && overLink == textBlock.parent)
3116 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3117 selBlock = textBlock;
3118 PositionCaret(true);
3126 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3128 if(!edit || !textBlock || clickedLink != textBlock.parent)
3130 HTMLView::OnLeftButtonUp(x, y, mods);
3133 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3134 selBlock = textBlock;
3135 PositionCaret(true);
3146 bool OnMouseMove(int x, int y, Modifiers mods)
3148 if(edit && selecting)
3150 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3151 PositionCaret(true);
3154 return HTMLView::OnMouseMove(x, y, mods);
3157 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3159 if(edit && textBlock)
3165 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3166 selBlock = textBlock;
3167 for(c = curPosition; c >= 0; c--)
3170 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3171 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3172 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3178 for(c = start; c < textBlock.textLen; c += numBytes)
3180 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3181 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3184 selPosition = start;
3187 PositionCaret(true);
3195 bool OnOpen(char * href)
3197 if(!strncmp(href, "api://", 6))
3199 int64 tag = (int64)strtoull(href + 6, null, 16);
3200 DataRow row = mainForm.browser.FindSubRow(tag);
3204 mainForm.browser.SelectRow(row);
3205 while((row = row.parent))
3206 row.collapsed = false;
3207 row = mainForm.browser.currentRow;
3208 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3211 else if(!strncmp(href, "edit://", 7))
3214 int startX = clickedLink.startX, startY = clickedLink.startY;
3215 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3217 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3218 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3220 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3222 display.FontExtent(block.font.font, " ", 1, null, &th);
3225 block.parent.subBlocks.Insert(null, newBlock);
3230 block.parent.subBlocks.Insert(block, newBlock);
3231 startY += block.prev.height;
3233 newBlock.startX = startX;
3234 newBlock.startY = startY;
3235 newBlock.text = new0 char[1];
3239 textBlock = (Block)clickedLink.subBlocks.first;
3240 if(!strcmp(textBlock.text, $"[Add Text]"))
3242 textBlock.text[0] = 0;
3243 textBlock.textLen = 0;
3246 strcpy(editString, href + 7);
3247 selPosition = curPosition = 0;
3248 selBlock = textBlock;
3251 // PositionCaret(true);
3258 void DeleteSelection()
3260 if(textBlock != selBlock || curPosition != selPosition)
3262 if(textBlock == selBlock)
3264 // Within same block
3265 int start = Min(curPosition, selPosition);
3266 int end = Max(curPosition, selPosition);
3267 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3268 textBlock.textLen -= end-start;
3269 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3270 curPosition = start;
3271 selPosition = start;
3275 int startSel, endSel;
3276 Block startSelBlock = null, endSelBlock = null, b, next;
3278 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3280 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3281 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3283 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3284 for(b = startSelBlock.next; b; b = next)
3286 bool isEnd = b == endSelBlock;
3287 next = GetNextBlock(b);
3288 b.parent.subBlocks.Remove(b);
3293 textBlock = startSelBlock;
3294 selBlock = startSelBlock;
3295 curPosition = startSel;
3296 selPosition = startSel;
3300 PositionCaret(true);
3305 String GetSelectionString()
3307 String selection = null;
3308 if(textBlock == selBlock)
3310 // Within same block
3311 int start = Min(curPosition, selPosition);
3312 int end = Max(curPosition, selPosition);
3313 int len = end - start;
3314 selection = new char[len + 1];
3315 memcpy(selection, textBlock.text + start, len);
3320 int startSel, endSel;
3321 Block startSelBlock = null, endSelBlock = null, b;
3324 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3327 for(b = startSelBlock; b; b = GetNextBlock(b))
3329 int start = (b == startSelBlock) ? startSel : 0;
3330 int end = (b == endSelBlock) ? endSel : b.textLen;
3331 int len = end - start;
3333 if(b == endSelBlock)
3335 else if(b.type == TEXT)
3339 selection = new char[totalLen + 1];
3341 for(b = startSelBlock; b; b = GetNextBlock(b))
3343 int start = (b == startSelBlock) ? startSel : 0;
3344 int end = (b == endSelBlock) ? endSel : b.textLen;
3345 int len = end - start;
3346 memcpy(selection + totalLen, b.text + start, len);
3348 if(b == endSelBlock)
3350 else if(b.type == TEXT)
3351 selection[totalLen++] = '\n';
3353 selection[totalLen] = 0;
3358 void CopySelection()
3360 String s = GetSelectionString();
3363 int len = strlen(s);
3365 if(cb.Allocate(len + 1))
3367 memcpy(cb.text, s, len + 1);
3375 bool OnKeyDown(Key key, unichar ch)
3382 OnLeftButtonDown(0,0,0);
3384 case Key { end, shift = true }:
3386 curPosition = textBlock.textLen;
3389 selPosition = curPosition;
3390 selBlock = textBlock;
3392 PositionCaret(true);
3395 case Key { home, shift = true }:
3400 selPosition = curPosition;
3401 selBlock = textBlock;
3403 PositionCaret(true);
3406 case Key { home, ctrl = true, shift = true }:
3409 while(textBlock.prev)
3410 textBlock = textBlock.prev.prev;
3413 selPosition = curPosition;
3414 selBlock = textBlock;
3416 PositionCaret(true);
3419 case Key { end, ctrl = true, shift = true }:
3421 while(textBlock.next && textBlock.next.next)
3422 textBlock = textBlock.next.next;
3423 curPosition = textBlock.textLen;
3426 selPosition = curPosition;
3427 selBlock = textBlock;
3429 PositionCaret(true);
3435 return HTMLView::OnKeyDown(key, ch);
3439 bool OnKeyHit(Key key, unichar ch)
3445 case Key { up, shift = true }:
3448 if(caretY == textBlock.startY)
3452 textBlock = textBlock.prev.prev;
3453 curPosition = Min(curPosition, textBlock.textLen);
3456 selPosition = curPosition;
3457 selBlock = textBlock;
3460 PositionCaret(false);
3470 int sx = textBlock.startX, sy = textBlock.startY;
3471 char * text = textBlock.text;
3473 Block block = textBlock;
3474 while(block && block.type != TD) block = block.parent;
3477 Block table = block;
3478 while(table && table.type != TABLE) table = table.parent;
3480 maxW = block.w - 2* table.cellPadding;
3482 maxW = clientSize.w - 10 - sx;
3485 maxW = clientSize.w - 10 - sx;
3486 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3490 int startPos = textPos;
3493 bool lineComplete = false;
3494 for(; textPos<textBlock.textLen && !lineComplete;)
3498 char * nextSpace = strchr(text + textPos, ' ');
3501 len = (nextSpace - (text + textPos)) + 1;
3503 len = textBlock.textLen - textPos;
3505 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3507 if(x + width + w > maxW && x > 0)
3509 lineComplete = true;
3519 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3522 curPosition = textPos;
3523 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3526 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3527 len = curPosition - startPos;
3528 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3532 selPosition = curPosition;
3533 selBlock = textBlock;
3537 PositionCaret(false);
3541 if(sy == caretY - th || textPos == textBlock.textLen)
3543 if(textPos != textBlock.textLen)
3545 int c = textPos - 1;
3546 while(c > 0 && text[c] == ' ') c--;
3547 curPosition = c + 1;
3550 selPosition = curPosition;
3551 selBlock = textBlock;
3557 curPosition = textBlock.textLen;
3560 selPosition = curPosition;
3561 selBlock = textBlock;
3565 PositionCaret(false);
3569 sx = textBlock.startX;
3570 } while(textPos < textBlock.textLen);
3575 case Key { down, shift = true }:
3580 int sx = textBlock.startX, sy = textBlock.startY;
3581 char * text = textBlock.text;
3583 Block block = textBlock;
3584 while(block && block.type != TD) block = block.parent;
3587 Block table = block;
3588 while(table && table.type != TABLE) table = table.parent;
3590 maxW = block.w - 2* table.cellPadding;
3592 maxW = clientSize.w - 10 - sx;
3595 maxW = clientSize.w - 10 - sx;
3596 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3598 while(!textPos || textPos < textBlock.textLen)
3600 int startPos = textPos;
3603 bool lineComplete = false;
3604 for(; (textPos < textBlock.textLen) && !lineComplete;)
3608 char * nextSpace = strchr(text + textPos, ' ');
3611 len = (nextSpace - (text + textPos)) + 1;
3613 len = textBlock.textLen - textPos;
3615 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3617 if(x + width + w > maxW && x > 0)
3619 lineComplete = true;
3629 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3631 curPosition = textPos;
3633 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3636 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3637 len = curPosition - startPos;
3638 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3642 selPosition = curPosition;
3643 selBlock = textBlock;
3646 PositionCaret(false);
3652 curPosition = textBlock.textLen;
3655 selPosition = curPosition;
3656 selBlock = textBlock;
3659 PositionCaret(false);
3662 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3666 textBlock = textBlock.next.next;
3667 sy = textBlock.startY;
3668 sx = textBlock.startX;
3669 text = textBlock.text;
3674 sx = textBlock.startX;
3678 /*if(textBlock.next && textBlock.next.next)
3680 textBlock = textBlock.next.next;
3681 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3682 selBlock = textBlock;
3683 PositionCaret(false);
3687 case Key { right, shift = true, ctrl = true }:
3690 bool foundAlpha = false;
3692 Block line, lastLine;
3695 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3697 int start = (line == textBlock) ? curPosition : 0;
3699 for(c = start; c < line.textLen; c++)
3701 char ch = line.text[c];
3702 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3703 if(key.shift ? isAlUnder : !isAlUnder)
3717 selPosition = curPosition;
3718 selBlock = textBlock;
3722 PositionCaret(true);
3727 // No next word found,
3728 if(!found && (c != curPosition || line != textBlock))
3732 lastC = line.textLen-1;
3737 curPosition = line.textLen;
3740 selPosition = curPosition;
3741 selBlock = textBlock;
3746 PositionCaret(true);
3752 if(key.shift && found)
3754 curPosition = lastC+1;
3755 textBlock = lastLine;
3756 PositionCaret(true);
3761 case Key { left, ctrl = true, shift = true }:
3764 bool foundAlpha = false;
3766 Block line, lastLine;
3769 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3772 if(curPosition == 0 && line != textBlock)
3775 lastC = line.textLen;
3779 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3780 for(c = start; c>=0; c--)
3782 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3797 // No next word found,
3798 if(!found && curPosition > 0)
3808 textBlock = lastLine;
3809 curPosition = lastC;
3812 selPosition = curPosition;
3813 selBlock = textBlock;
3815 PositionCaret(true);
3820 case Key { right, shift = true }:
3822 if(curPosition < textBlock.textLen)
3824 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3827 selPosition = curPosition;
3828 selBlock = textBlock;
3830 PositionCaret(true);
3833 else if(textBlock.next && textBlock.next.next)
3835 textBlock = textBlock.next.next;
3839 selPosition = curPosition;
3840 selBlock = textBlock;
3842 PositionCaret(true);
3846 case Key { left, shift = true }:
3850 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3853 selPosition = curPosition;
3854 selBlock = textBlock;
3856 PositionCaret(true);
3859 else if(textBlock.prev)
3861 textBlock = textBlock.prev.prev;
3862 curPosition = textBlock.textLen;
3865 selPosition = curPosition;
3866 selBlock = textBlock;
3868 PositionCaret(true);
3874 if(textBlock == selBlock && curPosition == selPosition)
3878 int c = curPosition;
3880 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3881 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3882 textBlock.textLen -= nb;
3883 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3885 selPosition = curPosition;
3886 selBlock = textBlock;
3890 PositionCaret(true);
3893 else if(textBlock.prev)
3895 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3896 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3897 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3899 selPosition = curPosition = prevBlock.textLen;
3900 selBlock = textBlock;
3901 prevBlock.textLen += textBlock.textLen;
3902 textBlock.parent.subBlocks.Remove(prev);
3903 if(prev == selBlock)
3905 selBlock = textBlock;
3906 selPosition = curPosition;
3909 textBlock.parent.subBlocks.Remove(textBlock);
3910 if(textBlock == selBlock)
3912 selBlock = prevBlock;
3913 selPosition = curPosition;
3916 textBlock = prevBlock;
3920 PositionCaret(true);
3929 if(textBlock != selBlock || curPosition != selPosition)
3931 else if(textBlock.textLen > curPosition)
3933 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3934 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3935 textBlock.textLen -= nb;
3936 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3941 PositionCaret(true);
3944 else if(textBlock.next && textBlock.next.next)
3946 Block next = textBlock.next, nextBlock = textBlock.next.next;
3947 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3948 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3950 textBlock.textLen += nextBlock.textLen;
3951 textBlock.parent.subBlocks.Remove(next);
3952 if(next == selBlock)
3954 selBlock = textBlock;
3955 selPosition = curPosition;
3958 textBlock.parent.subBlocks.Remove(nextBlock);
3959 if(nextBlock == selBlock)
3961 selBlock = textBlock;
3962 selPosition = curPosition;
3968 PositionCaret(true);
3982 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3983 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3984 startY = textBlock.startY;
3985 startX = textBlock.startX;
3987 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3988 textBlock.parent.subBlocks.Insert(textBlock, block);
3989 textBlock.parent.subBlocks.Insert(block, newBlock);
3993 newBlock.textLen = textBlock.textLen - curPosition;
3994 newBlock.text = new char[newBlock.textLen+1];
3995 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3996 textBlock.textLen = curPosition;
3997 textBlock.text[curPosition] = 0;
3999 newBlock.startY = startY;
4000 newBlock.startX = startX;
4001 selPosition = curPosition = 0;
4006 textBlock = newBlock;
4007 selBlock = textBlock;
4008 PositionCaret(true);
4013 case Key { del, shift = true }:
4028 ClipBoard clipBoard { };
4029 if(clipBoard.Load())
4032 char * text = clipBoard.memory;
4040 parent = textBlock.parent;
4041 font = textBlock.font;
4046 if(ch == '\n' || ch == '\r' || !ch)
4048 int len = c - start;
4049 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4050 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4051 memcpy(textBlock.text + curPosition, text + start, len);
4052 textBlock.textLen += len;
4054 selPosition = curPosition;
4055 selBlock = textBlock;
4058 Block block { type = BR, parent = parent, font = font };
4059 Block newBlock { type = TEXT, parent = parent, font = font };
4060 int startY = textBlock.startY, startX = textBlock.startX;
4063 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4064 textBlock.parent.subBlocks.Insert(textBlock, block);
4065 textBlock.parent.subBlocks.Insert(block, newBlock);
4069 newBlock.textLen = textBlock.textLen - curPosition;
4070 newBlock.text = new char[newBlock.textLen+1];
4071 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4072 textBlock.textLen = curPosition;
4073 textBlock.text[curPosition] = 0;
4075 newBlock.startY = startY;
4076 newBlock.startX = startX;
4077 selPosition = curPosition = 0;
4078 selBlock = textBlock;
4079 textBlock = newBlock;
4081 if(ch == '\r' && text[c+1] == '\n') c++;
4087 PositionCaret(true);
4095 // eC BUG HERE: (Should be fixed)
4096 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4099 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4104 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4105 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4107 for(c = 0; c<len; c++)
4109 textBlock.text[curPosition] = string[c];
4110 textBlock.textLen++;
4113 selPosition = curPosition;
4114 selBlock = textBlock;
4117 //Clear(html.block);
4118 //CreateForms(html.block);
4123 PositionCaret(true);
4132 void OnResize(int width, int height)
4134 HTMLView::OnResize(width, height);
4135 PositionCaret(true);
4139 void PositionCaret(bool setCaretX)
4145 int sx = textBlock.startX, sy = textBlock.startY;
4146 char * text = textBlock.text;
4148 Block block = textBlock;
4149 while(block && block.type != TD) block = block.parent;
4152 Block table = block;
4153 while(table && table.type != TABLE) table = table.parent;
4155 maxW = block.w - 2* table.cellPadding;
4157 maxW = clientSize.w - 10 - sx;
4160 maxW = clientSize.w - 10 - sx;
4162 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4164 while(textPos < textBlock.textLen)
4166 int startPos = textPos;
4169 bool lineComplete = false;
4171 for(; textPos<textBlock.textLen && !lineComplete;)
4175 char * nextSpace = strchr(text + textPos, ' ');
4178 len = (nextSpace - (text + textPos)) + 1;
4180 len = textBlock.textLen - textPos;
4182 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4184 if(x + width + w > maxW && x > 0)
4186 lineComplete = true;
4199 if(curPosition < textPos || textPos == textBlock.textLen)
4201 int len = curPosition - startPos;
4202 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4207 sx = textBlock.startX;
4212 SetCaret(sx, sy, th);
4214 Point scrollPos = scroll;
4215 bool doScroll = false;
4216 if(sy - scroll.y + th > clientSize.h)
4218 scrollPos.y = sy + th - clientSize.h;
4221 else if(sy - scroll.y < 0)
4226 if(sx - scroll.x + 10 > clientSize.w)
4228 scrollPos.x = sx + 10 - clientSize.w;
4231 else if(sx - scroll.x < 10)
4233 scrollPos.x = sx - 10;
4244 // Returns a character offset into the TextBlock from a window coordinate
4245 int TextPosFromPoint(int px, int py, Block * block, bool half)
4247 Block parentBlock = this.textBlock.parent;
4250 *block = this.textBlock;
4255 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4257 int sx = textBlock.startX, sy = textBlock.startY;
4260 char * text = textBlock.text;
4262 Block b = textBlock;
4265 if(textBlock.type != TEXT) continue;
4267 while(b && b.type != TD) b = b.parent;
4271 while(table && table.type != TABLE) table = table.parent;
4273 maxW = b.w - 2* table.cellPadding;
4275 maxW = clientSize.w - 10 - sx;
4278 maxW = clientSize.w - 10 - sx;
4280 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4281 //space = space/2+2;
4284 while(textPos < textBlock.textLen)
4288 bool lineComplete = false;
4290 for(; textPos<textBlock.textLen && !lineComplete;)
4294 char * nextSpace = strchr(text + textPos, ' ');
4297 len = (nextSpace - (text + textPos)) + 1;
4299 len = textBlock.textLen - textPos;
4301 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4303 sx = x + textBlock.startX;
4304 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4309 for(c = textPos; (ch = text[c]); c += numBytes)
4311 numBytes = UTF8_NUM_BYTES(ch);
4312 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4313 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4320 if(x + width + w > maxW && x > 0)
4322 lineComplete = true;
4335 if(/*py >= sy && */py < sy + th)
4338 return textBlock.textLen;
4343 result = textBlock.textLen;
4349 Application componentsApp;
4351 class Documentor : GuiApplication
4355 Platform os = __runtimePlatform;
4356 SetGlobalContext(globalContext);
4357 SetExcludedSymbols(&excludedSymbols);
4358 SetDefines(&::defines);
4359 SetImports(&imports);
4360 SetInDocumentor(true);
4362 SetGlobalData(globalData);
4364 settingsContainer.dataOwner = &ideSettings;
4365 settingsContainer.Load();
4366 if(!ideSettings.docDir || !ideSettings.docDir[0] )
4368 if(os == win32) // if Windows OS then
4370 char programFilesDir[MAX_LOCATION];
4371 char appData[MAX_LOCATION];
4372 char homeDrive[MAX_LOCATION];
4373 char winDir[MAX_LOCATION];
4374 GetEnvironment("APPDATA", appData, sizeof(appData));
4375 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4376 GetEnvironment("windir", winDir, sizeof(winDir));
4377 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4379 PathCat(programFilesDir, "ECERE SDK\\doc");
4380 ideSettings.docDir = programFilesDir;
4382 else if(homeDrive[0])
4384 PathCat(homeDrive, "ECERE SDK\\doc");
4385 ideSettings.docDir = homeDrive;
4389 PathCat(winDir, "..\\ECERE SDK\\doc");
4390 ideSettings.docDir = winDir;
4393 ideSettings.docDir = "C:\\ECERE SDK\\doc";
4395 else // if Os is Linux, or Mac OSX or something else
4396 ideSettings.docDir = "/usr/share/ecere/doc/";
4397 settingsContainer.Save();
4403 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4405 AddComponents(module, true);
4406 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4407 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4408 while((row = row.parent))
4409 row.collapsed = false;
4413 commandThread.Create();
4417 bool Cycle(bool idle)
4420 mainForm.Destroy(0);
4429 if(commandThread.created)
4431 console.CloseInput();
4432 console.CloseOutput();
4434 commandThread.Wait();
4438 FreeContext(globalContext);
4439 FreeExcludedSymbols(excludedSymbols);
4440 ::defines.Free(FreeModuleDefine);
4441 imports.Free(FreeModuleImport);
4443 FreeGlobalData(globalData);
4444 FreeTypeData(componentsApp);
4446 delete componentsApp;
4450 ConsoleFile console { };
4451 MainForm mainForm { };
4454 Thread commandThread
4461 console.GetLine(command, sizeof(command));
4462 if(!quit && command[0])
4465 if(!strcmpi(command, "Activate"))
4466 mainForm.Activate();
4467 else if(!strcmpi(command, "Quit"))
4475 #endif // !defined(EAR_TO_ECON_ECDOC)
4480 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4481 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4485 property bool isEmpty
4491 (description && *description));
4501 class MoreDoc : ItemDoc
4504 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4505 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4506 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4507 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4513 property bool isEmpty
4518 (usage && *usage) ||
4519 (example && *example) ||
4520 (remarks && *remarks) ||
4534 class NamespaceDoc : ItemDoc
4537 Map<String, DefineDoc> defines;
4538 Map<String, FunctionDoc> functions;
4540 property bool isEmpty
4545 (defines && defines.count) ||
4546 (functions && functions.count) ||
4557 class DefineDoc : ItemDoc { }
4559 class FunctionDoc : MoreDoc
4562 Map<String, ParameterDoc> parameters;
4563 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4566 property bool isEmpty
4571 (parameters && parameters.count) ||
4572 (returnValue && *returnValue) ||
4583 class ParameterDoc : ItemDoc
4589 class ClassDoc : MoreDoc
4592 Map<String, ValueDoc> values;
4593 Map<String, FieldDoc> fields;
4594 Map<String, PropertyDoc> properties;
4595 Map<String, ConversionDoc> conversions;
4596 Map<String, MethodDoc> methods;
4598 property bool isEmpty
4603 (values && values.count) ||
4604 (fields && fields.count) ||
4605 (properties && properties.count) ||
4606 (conversions && conversions.count) ||
4607 (methods && methods.count) ||
4621 class ValueDoc : ItemDoc { }
4623 class FieldDoc : ItemDoc { }
4625 class PropertyDoc : ItemDoc { }
4627 class ConversionDoc : ItemDoc { }
4629 class MethodDoc : FunctionDoc { }
4631 char * getDocFileNameFromTypeName(const char * typeName)
4633 char * docFileName = new char[MAX_FILENAME];
4634 const char * swap = "pointer";
4635 const char * s = typeName;
4636 char * d = docFileName;
4637 const char * end = s + strlen(typeName);
4638 int swapLen = strlen(swap);
4656 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4659 Time timeStamp; // Should this be last accessed, or last retrieved?
4668 Map<String, DocCacheEntry> docCache { };