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 if(!cl.templateClass && !cl.internalDecl)
891 char * desc = ReadDoc(module, classDoc, cl, description, null);
895 f.Printf($"<a name=Classes></a><H3>Classes</H3><BR>\n");
896 f.Printf("<TABLE>\n");
902 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);
907 char fileName[MAX_LOCATION];
908 FigureFileName(fileName, module, classDoc, cl, description, null);
909 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
911 f.Printf("</a></TD>");
914 f.Printf("<TD valign=top height=22>%s</TD>", desc);
921 f.Printf("</TABLE><br><br>\n");
924 if(nameSpace->functions.first)
927 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
929 GlobalFunction function = link.data;
930 char * desc = ReadDoc(module, functionDoc, function, description, null);
931 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
932 if(name) name += 2; else name = function.name;
935 f.Printf($"<a name=Functions></a><H3>Functions</H3><BR>\n");
936 f.Printf("<TABLE>\n");
940 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);
945 char fileName[MAX_LOCATION];
946 FigureFileName(fileName, module, functionDoc, function, description, null);
947 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
949 f.Printf("</a></TD>");
952 f.Printf("<TD valign=top height=22> %s</TD>", desc);
955 f.Printf("</TR><br>\n");
958 f.Printf("</TABLE><br><br>\n");
961 if(nameSpace->defines.first)
964 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
966 DefinedExpression def = link.data;
967 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
970 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><BR>\n");
971 f.Printf("<TABLE>\n");
975 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);
976 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
981 char fileName[MAX_LOCATION];
982 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
983 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
985 f.Printf("</a></TD>");
988 f.Printf("<TD valign=top height=22> %s</TD>", desc);
991 f.Printf("</TR><br>\n");
994 f.Printf("</TABLE><br><br>\n");
997 f.Printf("</FONT></BODY></HTML>\n");
1001 class APIPageClass : APIPage
1010 NameSpace * GetNameSpace()
1012 return cl.nameSpace;
1015 void Generate(File f)
1020 char nsName[1024], temp[1024];
1021 NameSpace * ns = cl.nameSpace;
1022 Module module = cl.module;
1025 while(ns && ns->name)
1027 strcpy(temp, ns->name);
1028 if(nsName[0]) strcat(temp, "::");
1029 strcat(temp, nsName);
1030 strcpy(nsName, temp);
1033 // Generate Class Page
1034 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1035 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1037 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);
1039 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1042 const char * classType = null;
1046 classType = $"Bit Collection";
1049 classType = $"Enumeration";
1052 classType = $"Structure";
1055 classType = $"Class";
1058 classType = $"Class (No header)";
1061 classType = $"Unit";
1064 classType = $"Basic Data Type";
1067 f.Printf($"Type: %s<br>\n", classType);
1070 if(cl.type != systemClass && cl.base)
1072 f.Printf($"Base Class: ");
1073 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1075 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1077 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1078 f.Printf("%s", cl.dataTypeString);
1080 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1085 char * desc = ReadDoc(module, classDoc, cl, description, null);
1088 f.Printf($"<br><H3>Description</H3><BR>\n");
1091 char fileName[MAX_LOCATION];
1092 FigureFileName(fileName, module, classDoc, cl, description, null);
1093 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1098 f.Printf("%s", desc);
1099 f.Printf("<br><br><br>");
1104 if(cl.type == enumClass)
1106 EnumClassData enumeration = (EnumClassData)cl.data;
1107 if(enumeration.values.first)
1111 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><BR>\n");
1112 f.Printf("<TABLE>\n");
1114 for(item = enumeration.values.first; item; item = item.next)
1116 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1117 bool needClass = true;
1120 char tempString[1024];
1122 while(base.type == enumClass) base = base.base;
1124 if(base.type == systemClass ||
1125 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1128 base.dataType = ProcessTypeString(base.dataTypeString, false);
1130 if(base.dataType.kind != classType)
1135 PrintType(base.dataType, string, false, true);
1136 classSym = FindClass(string);
1137 dataClass = classSym ? classSym.registered : null;
1140 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1146 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);
1147 if(dataClass.type == systemClass)
1150 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1153 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1155 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1157 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1162 char fileName[MAX_LOCATION];
1163 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1164 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1166 f.Printf("</a></TD>");
1169 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1174 f.Printf("</TABLE><BR>\n");
1178 if(cl.conversions.first)
1180 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><BR>\n");
1181 f.Printf("<TABLE>\n");
1182 for(prop = cl.conversions.first; prop; prop = prop.next)
1184 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1186 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1188 Type type = ProcessTypeString(prop.name, false);
1189 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1190 if(name) name += 2; else name = prop.name;
1195 DocPrintType(type, string, true, false);
1197 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1202 char fileName[MAX_LOCATION];
1203 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1204 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1206 f.Printf("</a></TD>");
1209 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1213 f.Printf("</TR>\n");
1218 f.Printf("</TABLE><br><br>\n");
1221 if(cl.membersAndProperties.first)
1224 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1226 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1230 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><BR>\n");
1231 f.Printf("<TABLE>\n");
1237 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1239 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1243 DocPrintType(prop.dataType, string, true, false);
1245 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);
1246 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1251 char fileName[MAX_LOCATION];
1252 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1253 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1255 f.Printf("</a></TD>");
1258 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1261 f.Printf("</TR>\n");
1265 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1270 f.Printf("</TABLE><br><br>\n");
1273 if(cl.methods.first)
1277 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1279 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1281 char * desc = ReadDoc(module, methodDoc, method, description, null);
1284 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><BR>\n");
1285 f.Printf("<TABLE>\n");
1288 if(!method.dataType)
1289 ProcessMethodType(method);
1292 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);
1297 char fileName[MAX_LOCATION];
1298 FigureFileName(fileName, module, methodDoc, method, description, null);
1299 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1301 f.Printf("</a></TD>");
1304 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1307 f.Printf("</TR><br>\n");
1311 f.Printf("</TABLE><br><br>\n");
1313 // Non-Virtual Methods
1315 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1317 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1319 char * desc = ReadDoc(module, methodDoc, method, description, null);
1322 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><BR>\n");
1323 f.Printf("<TABLE>\n");
1327 if(!method.dataType)
1328 ProcessMethodType(method);
1331 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);
1336 char fileName[MAX_LOCATION];
1337 FigureFileName(fileName, module, methodDoc, method, description, null);
1338 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1340 f.Printf("</a></TD>");
1343 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1347 f.Printf("</TR><br>\n");
1351 f.Printf("</TABLE><br><br>\n");
1354 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1357 f.Printf($"<H3>Usage</H3><BR>\n");
1360 char fileName[MAX_LOCATION];
1361 FigureFileName(fileName, module, classDoc, cl, usage, null);
1362 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1367 f.Printf("<br>%s\n", usageDoc);
1368 f.Printf("<br><br><br>\n");
1373 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1376 f.Printf($"<H3>Example</H3><BR>\n");
1377 f.Printf($"<FONT face=\"Courier New\">\n");
1378 f.Printf("<br><TABLE>\n");
1381 char fileName[MAX_LOCATION];
1382 FigureFileName(fileName, module, classDoc, cl, example, null);
1383 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1385 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1388 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1390 f.Printf("</TABLE></FONT>\n");
1391 f.Printf("<br><br>\n");
1396 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1400 f.Printf($"<H3>Remarks</H3><BR>\n");
1403 char fileName[MAX_LOCATION];
1404 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1405 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1410 f.Printf("<br>%s\n", remarksDoc);
1411 f.Printf("<br><br><br>\n");
1416 if(cl.type != systemClass)
1420 for(c = cl.derivatives.first; c; c = c.next)
1422 Class deriv = c.data;
1423 // TO VERIFY: Does this properly check public status?
1424 if(eSystem_FindClass(componentsApp, deriv.fullName))
1428 f.Printf($"<H3>Derived Classes</H3><BR>\n");
1433 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1437 f.Printf("<br><br>\n");
1440 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1443 f.Printf($"<H3>See Also</H3>\n");
1446 char fileName[MAX_LOCATION];
1447 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1448 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1453 f.Printf("<br>%s\n", seeAlsoDoc);
1454 f.Printf("<br><br>\n");
1458 f.Printf("</FONT></BODY></HTML>\n");
1462 class APIPageMethod : APIPage
1468 return method._class.module;
1471 NameSpace * GetNameSpace()
1473 return method._class.nameSpace;
1476 void Generate(File f)
1478 Class cl = method._class;
1480 Module module = cl.module;
1482 char nsName[1024], temp[1024];
1483 NameSpace * ns = cl.nameSpace;
1486 while(ns && ns->name)
1488 strcpy(temp, ns->name);
1489 if(nsName[0]) strcat(temp, "::");
1490 strcat(temp, nsName);
1491 strcpy(nsName, temp);
1495 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1496 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1498 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);
1500 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1501 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1502 if(method.dataType.staticMethod)
1504 f.Printf($"this pointer class: None<br>\n");
1506 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1508 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);
1511 // Generate Method Page
1513 if(!method.dataType.name)
1514 method.dataType.name = CopyString(method.name);
1515 DocPrintType(method.dataType, string, true, false);
1516 f.Printf("<br>%s", string);
1519 char * desc = ReadDoc(module, methodDoc, method, description, null);
1522 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1525 char fileName[MAX_LOCATION];
1526 FigureFileName(fileName, module, methodDoc, method, description, null);
1527 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1532 f.Printf("%s", desc);
1533 f.Printf("<BR><BR>");
1538 f.Printf("<br><br>\n");
1539 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1541 f.Printf($"<H3>Parameters</H3><BR>\n");
1543 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1544 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1546 f.Printf("<TABLE valign=center>\n");
1549 for(param = method.dataType.params.first; param; param = param.next)
1551 // ADD DESCRIPTION HERE
1552 if(param.kind != voidType)
1554 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1557 DocPrintType(param, string, false, false);
1559 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1560 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1565 char fileName[MAX_LOCATION];
1566 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1567 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1569 f.Printf("</a></TD>\n");
1572 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1576 f.Printf("</TR>\n");
1579 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1581 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1582 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1584 f.Printf("<TR><TD> </TD></TR>");
1587 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1589 DocPrintType(method.dataType.returnType, string, false, false);
1590 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1595 char fileName[MAX_LOCATION];
1596 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1597 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1599 f.Printf("</a> </TD>\n");
1602 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1605 f.Printf("</TR>\n");
1606 f.Printf("</TABLE>\n");
1608 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1609 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1611 f.Printf("</TABLE><br>\n");
1614 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1617 f.Printf($"<H3>Usage</H3><BR>\n");
1620 char fileName[MAX_LOCATION];
1621 FigureFileName(fileName, module, methodDoc, method, usage, null);
1622 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1627 f.Printf("<br>%s\n", usageDoc);
1628 f.Printf("<br><br><br>\n");
1633 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1636 f.Printf($"<H3>Example</H3><BR>\n");
1637 f.Printf($"<FONT face=\"Courier New\">\n");
1638 f.Printf("<br><TABLE>\n");
1641 char fileName[MAX_LOCATION];
1642 FigureFileName(fileName, module, methodDoc, method, example, null);
1643 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1645 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1648 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1649 f.Printf("</TABLE></FONT>\n");
1650 f.Printf("<br><br>\n");
1655 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1658 f.Printf($"<H3>Remarks</H3><BR>\n");
1661 char fileName[MAX_LOCATION];
1662 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1663 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1668 f.Printf("<br>%s\n", method, remarksDoc);
1669 f.Printf("<br><br><br>\n");
1674 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1677 f.Printf($"<H3>See Also</H3><BR>\n");
1680 char fileName[MAX_LOCATION];
1681 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1682 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1687 f.Printf("<br>%s\n", method, seeAlsoDoc);
1689 f.Printf("<br><br><br>\n");
1693 f.Printf("</FONT></BODY></HTML>\n");
1697 class APIPageFunction : APIPage
1699 GlobalFunction function;
1703 return function.module;
1706 NameSpace * GetNameSpace()
1708 return function.nameSpace;
1711 void Generate(File f)
1714 Module module = function.module;
1716 char nsName[1024], temp[1024];
1717 NameSpace * ns = function.nameSpace;
1720 while(ns && ns->name)
1722 strcpy(temp, ns->name);
1723 if(nsName[0]) strcat(temp, "::");
1724 strcat(temp, nsName);
1725 strcpy(nsName, temp);
1729 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1730 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1732 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);
1735 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1737 if(!function.dataType)
1738 function.dataType = ProcessTypeString(function.dataTypeString, false);
1740 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1742 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);
1745 // Generate Method Page
1747 if(!function.dataType.name)
1748 function.dataType.name = CopyString(function.name);
1749 DocPrintType(function.dataType, string, true, false);
1750 f.Printf("<br>%s", string);
1753 char * desc = ReadDoc(module, functionDoc, function, description, null);
1756 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1759 char fileName[MAX_LOCATION];
1760 FigureFileName(fileName, module, functionDoc, function, description, null);
1761 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1766 f.Printf("%s", desc);
1768 f.Printf("<BR><BR>");
1771 f.Printf("<br><br>\n");
1772 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1774 f.Printf($"<H3>Parameters</H3><BR>\n");
1776 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1777 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1779 f.Printf("<TABLE valign=center>\n");
1782 for(param = function.dataType.params.first; param; param = param.next)
1784 // ADD DESCRIPTION HERE
1785 if(param.kind != voidType)
1787 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1790 DocPrintType(param, string, false, false);
1792 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1793 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1798 char fileName[MAX_LOCATION];
1799 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1800 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1803 f.Printf("</a> </TD>\n");
1806 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1809 f.Printf("</TR>\n");
1812 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1814 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1815 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1817 f.Printf("<TR><TD> </TD></TR>");
1820 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1822 DocPrintType(function.dataType.returnType, string, false, false);
1823 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1828 char fileName[MAX_LOCATION];
1829 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1830 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1832 f.Printf("</a> </TD>\n");
1835 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1838 f.Printf("</TR>\n");
1839 f.Printf("</TABLE>\n");
1841 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1842 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1844 f.Printf("</TABLE><br>\n");
1847 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1850 f.Printf($"<H3>Usage</H3><BR>\n");
1853 char fileName[MAX_LOCATION];
1854 FigureFileName(fileName, module, functionDoc, function, usage, null);
1855 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1860 f.Printf("<br>%s\n", usageDoc);
1861 f.Printf("<br><br><br>\n");
1866 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1869 f.Printf($"<H3>Example</H3><BR>\n");
1870 f.Printf($"<FONT face=\"Courier New\">\n");
1871 f.Printf("<br><TABLE>\n");
1874 char fileName[MAX_LOCATION];
1875 FigureFileName(fileName, module, functionDoc, function, example, null);
1876 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1878 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1881 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1882 f.Printf("</TABLE></FONT>\n");
1883 f.Printf("<br><br>\n");
1888 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1891 f.Printf($"<H3>Remarks</H3><BR>\n");
1894 char fileName[MAX_LOCATION];
1895 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1896 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1901 f.Printf("<br>%s\n", remarksDoc);
1902 f.Printf("<br><br><br>\n");
1907 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1910 f.Printf($"<H3>See Also</H3><BR>\n");
1913 char fileName[MAX_LOCATION];
1914 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1915 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1920 f.Printf("<br>%s\n", seeAlsoDoc);
1921 f.Printf("<br><br><br>\n");
1925 f.Printf("</FONT></BODY></HTML>\n");
1929 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1933 NameSpace * nameSpace = mainNameSpace;
1935 DataRow classesRow = null;
1936 DataRow functionsRow = null, definesRow = null;
1939 strcpy(nsName, parentName ? parentName : "");
1943 strcat(nsName, "::");
1944 strcat(nsName, nameSpace->name);
1949 row = parentRow.AddRow();
1950 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1951 row.tag = (int64)nameSpace;
1952 row.icon = mainForm.icons[typeNameSpace];
1956 // "Global NameSpace"
1958 page = parentRow.GetData(null);
1961 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1963 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1964 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1966 if(comNameSpace != null)
1968 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1970 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1972 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1977 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1979 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1981 if(nameSpace->classes.first)
1985 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1988 if(!cl.templateClass && !cl.internalDecl && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1990 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1991 AddClass(classesRow, module, cl, nsName, showPrivate);
1998 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2000 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2002 if(nameSpace->functions.first)
2006 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2009 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2011 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2013 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2014 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2021 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2023 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2025 if(nameSpace->defines.first)
2029 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2032 //if(def.module == module)
2034 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2036 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2037 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2045 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2049 if(!member.dataType)
2050 member.dataType = ProcessTypeString(member.dataTypeString, false);
2054 DocPrintType(member.dataType, string, true, false);
2056 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2057 for(c = 0; c<indent; c++)
2058 f.Printf(" ");
2059 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2060 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2061 if(member.type == normalMember)
2063 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2068 char fileName[MAX_LOCATION];
2069 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2070 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2072 f.Printf("</a></TD>");
2075 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2080 f.Printf("<TD valign=top height=22></TD>");
2082 if(member.type != normalMember)
2084 DataMember subMember;
2085 for(subMember = member.members.first; subMember; subMember = subMember.next)
2087 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2089 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2093 f.Printf("</TR><br>\n");
2096 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2099 if(member.type == normalMember)
2101 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2102 row.tag = (int64)member;
2107 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2108 row.icon = mainForm.icons[typeData];
2109 row.tag = (int64)member;
2111 for(m = member.members.first; m; m = m.next)
2113 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2114 AddDataMember(row, page, m);
2119 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2124 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2125 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2128 row = parentRow.AddRow();
2129 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2130 row.tag = (int64)cl;
2131 row.collapsed = true;
2132 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2135 if(cl.methods.first)
2137 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2139 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2142 if(!method.dataType)
2143 ProcessMethodType(method);
2144 if(method.type == virtualMethod)
2146 if(method.dataType.thisClass)
2148 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2149 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2150 mRow.tag = (int64)method;
2154 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2155 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2156 mRow.tag = (int64)method;
2161 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2162 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2163 mRow.tag = (int64)method;
2169 if(cl.membersAndProperties.first)
2171 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2173 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2176 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2180 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2181 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2182 mRow.tag = (int64)prop;
2186 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2187 AddDataMember(membersRow, page, (DataMember)prop);
2193 if(cl.conversions.first)
2195 for(prop = cl.conversions.first; prop; prop = prop.next)
2199 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2200 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2201 if(name) name += 2; else name = prop.name;
2202 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2203 mRow.tag = (int64)prop;
2206 if(cl.type == enumClass)
2208 EnumClassData enumeration = (EnumClassData)cl.data;
2210 for(item = enumeration.values.first; item; item = item.next)
2213 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2214 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2215 mRow.tag = (int64)item;
2220 class AddressBar : Window
2222 background = activeBorder;
2226 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2228 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2230 MainForm mainForm = (MainForm)parent;
2231 FileDialog fileDialog = mainForm.fileDialog;
2232 if(fileDialog.Modal() == ok)
2233 mainForm.OpenModule(fileDialog.filePath);
2239 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2242 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2244 ((MainForm)parent).Back();
2250 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2253 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2255 ((MainForm)parent).Forward();
2261 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2263 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2265 ((MainForm)parent).Home();
2269 /* TODO: Search (#143/#441)
2270 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2271 Update this in the NotifyUpdate. Enter goes to the exact match.
2273 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2277 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2279 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2281 if(!disabled && (SmartKey)key == enter)
2282 ((MainForm)parent).Go(editBox.contents);
2286 void NotifyUpdate(EditBox editBox)
2288 String location = ((MainForm)parent).view.location;
2289 disabled = !strcmp(location ? location : "", editBox.contents);
2294 bool OnKeyHit(Key key, unichar ch)
2297 ((MainForm)parent).view.MakeActive();
2302 class MainForm : Window
2304 size = { 1000, 600 };
2306 borderStyle = sizable;
2309 icon = { ":documentorIcon.png" };
2310 text = $"API Documentation Browser";
2312 BitmapResource icons[CodeObjectType];
2317 for(c = 0; c < CodeObjectType::enumSize; c++)
2319 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2321 browser.AddField(DataField { dataType = class(APIPage) });
2326 Menu fileMenu { menu, $"File", f };
2327 Array<FileFilter> fileFilters
2329 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2330 { $"eC Symbol files (*.sym)", "sym" }
2333 FileDialog fileDialog
2335 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2337 MenuItem fileOpenItem
2339 fileMenu, $"Open...", o, ctrlO;
2341 bool NotifySelect(MenuItem selection, Modifiers mods)
2343 if(fileDialog.Modal() == ok)
2345 OpenModule(fileDialog.filePath);
2350 MenuItem fileSettingsItem
2352 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2354 bool NotifySelect(MenuItem selection, Modifiers mods)
2356 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2366 MenuDivider { fileMenu };
2367 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2369 void OpenModule(const char * filePath)
2371 char moduleName[MAX_LOCATION];
2372 char extension[MAX_EXTENSION];
2373 Module module = null;
2374 static char symbolsDir[MAX_LOCATION];
2377 modulesAdded.RemoveAll();
2379 FreeContext(globalContext);
2380 FreeExcludedSymbols(excludedSymbols);
2381 ::defines.Free(FreeModuleDefine);
2382 imports.Free(FreeModuleImport);
2384 FreeGlobalData(globalData);
2388 FreeTypeData(componentsApp);
2389 delete componentsApp;
2392 componentsApp = __ecere_COM_Initialize(false, 1, null);
2393 SetPrivateModule(componentsApp);
2395 StripLastDirectory(filePath, symbolsDir);
2396 SetSymbolsDir(symbolsDir);
2398 GetExtension(filePath, extension);
2400 mainForm.browser.Clear();
2402 ImportModule(filePath, normalImport, publicAccess, false);
2404 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2405 componentsApp.name = CopyString(filePath);
2407 for(module = componentsApp.allModules.first; module; module = module.next)
2409 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2413 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2414 AddComponents(componentsApp, false);
2416 GetLastDirectory(filePath, moduleName);
2417 // Extension, path and lib prefix get removed in Module::name
2420 StripExtension(moduleName);
2421 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2423 int len = strlen(moduleName) - 3;
2424 memmove(moduleName, moduleName + 3, len);
2425 moduleName[len] = 0;
2429 for(module = componentsApp.allModules.first; module; module = module.next)
2431 if(module.name && (!strcmp(module.name, moduleName)))
2434 if(!module) module = componentsApp;
2435 homeModule = module;
2436 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2438 SetSymbolsDir(null);
2441 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2444 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2445 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2448 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2450 APIPage page = row.GetData(null);
2451 if(view.edit) view.OnLeftButtonDown(0,0,0);
2452 if(page && page.page) page = page.page;
2454 view.PositionCaret(true);
2455 if(page != view.page)
2457 Window activeChild = this.activeChild;
2459 // Back / Forward Support
2460 if(row && !dontRecordHistory)
2462 if(history.count > historyPos+1)
2463 history.count = historyPos+1;
2464 historyPos = history.count-1;
2465 addressBar.back.disabled = (historyPos == 0);
2466 addressBar.forward.disabled = (historyPos >= history.count-1);
2468 history.Add((Instance)(uint64)row.tag);
2469 historyPos = history.count-1;
2471 addressBar.back.disabled = (historyPos == 0);
2472 addressBar.forward.disabled = (historyPos >= history.count-1);
2478 activeChild.Activate();
2480 else if(!view.created)
2484 page = row.GetData(null);
2485 if(page && page.page)
2489 case 1: view.GoToAnchor("Classes"); break;
2490 case 2: view.GoToAnchor("Functions"); break;
2491 case 3: view.GoToAnchor("Definitions"); break;
2492 case 4: view.GoToAnchor("VirtualMethods"); break;
2493 case 5: view.GoToAnchor("Methods"); break;
2494 case 6: view.GoToAnchor("Members"); break;
2495 case 7: view.GoToAnchor("Conversions"); break;
2496 case 8: view.GoToAnchor("EnumerationValues"); break;
2500 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2501 view.GoToAnchor(hex);
2507 view.SetScrollPosition(0, 0);
2515 this, anchor = { top = 26, bottom = 0, right = 0 };
2520 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2523 bool OnClose(bool parentClosing)
2526 view.OnLeftButtonDown(0,0,0);
2532 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2533 //mainForm.OpenModule("ec");
2534 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2535 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2537 int index = mainForm.browser.currentRow.index;
2538 int rowHeight = mainForm.browser.rowHeight;
2539 int height = mainForm.browser.clientSize.h;
2541 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2546 Array<Instance> history { };
2548 bool dontRecordHistory;
2553 if(historyPos < history.count-1)
2557 addressBar.back.disabled = (historyPos == 0);
2558 addressBar.forward.disabled = (historyPos >= history.count-1);
2559 sprintf(location, "api://%p", history[historyPos]);
2560 dontRecordHistory = true;
2561 view.OnOpen(location);
2562 dontRecordHistory = false;
2574 addressBar.back.disabled = (historyPos == 0);
2575 addressBar.forward.disabled = (historyPos >= history.count-1);
2576 sprintf(location, "api://%p", history[historyPos]);
2577 dontRecordHistory = true;
2578 view.OnOpen(location);
2579 dontRecordHistory = false;
2587 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2591 class EditDialog : Window
2593 borderStyle = sizable;
2594 size = { 600, 400 };
2599 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2603 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2607 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2611 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2612 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2614 class HelpView : HTMLView
2618 hasVertScroll = true;
2619 hasHorzScroll = true;
2621 char editString[MAX_LOCATION];
2627 page = mainForm.browser.currentRow.GetData(null);
2632 char docDir[MAX_LOCATION];
2634 strcpy(docDir, ideSettings.docDir);
2635 if(FileExists(docDir).isDirectory)
2637 PathCatSlash(docDir, "___docWriteTest");
2638 if(FileExists(docDir).isDirectory)
2641 if(!FileExists(docDir))
2647 if(FileExists(docDir).isDirectory)
2659 GoToAnchor(page.label);
2661 if(page.page) page = page.page;
2664 return HTMLView::OnCreate();
2675 String contents = null;
2678 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2680 if(block.type == TEXT && block.textLen)
2688 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2690 if(block.type == BR)
2692 else if(block.type == TEXT)
2693 f.Write(block.text, 1, block.textLen);
2697 if((len = f.GetSize()))
2699 contents = new char[len+1];
2700 f.Read(contents, 1, len);
2701 contents[len] = '\0';
2705 char docPath[MAX_LOCATION];
2706 char temp[MAX_LOCATION];
2707 char part[MAX_FILENAME];
2711 DocumentationType type;
2712 DocumentationItem item;
2714 NamespaceDoc nsDoc = null;
2715 ClassDoc clDoc = null;
2716 FunctionDoc fnDoc = null;
2717 MethodDoc mdDoc = null;
2719 Method method = null;
2720 GlobalFunction function = null;
2722 strcpy(temp, editString);
2723 SplitDirectory(temp, part, temp);
2724 module = (Module)strtoull(part, null, 16);
2725 SplitDirectory(temp, part, temp);
2726 object = (void *)strtoull(part, null, 16);
2727 SplitDirectory(temp, part, temp);
2728 data = (void *)strtoull(part, null, 16);
2729 SplitDirectory(temp, part, temp);
2730 if(!strcmp(part, "namespace"))
2731 type = nameSpaceDoc;
2732 else if(!strcmp(part, "function"))
2734 else if(!strcmp(part, "class"))
2736 else if(!strcmp(part, "method"))
2738 SplitDirectory(temp, part, temp);
2739 if(!strcmp(part, "description"))
2741 else if(!strcmp(part, "usage"))
2743 else if(!strcmp(part, "remarks"))
2745 else if(!strcmp(part, "example"))
2747 else if(!strcmp(part, "seeAlso"))
2749 else if(!strcmp(part, "enumerationValue"))
2750 item = enumerationValue;
2751 else if(!strcmp(part, "definition"))
2753 else if(!strcmp(part, "conversion"))
2755 else if(!strcmp(part, "memberDescription"))
2756 item = memberDescription;
2757 else if(!strcmp(part, "propertyDescription"))
2758 item = propertyDescription;
2759 else if(!strcmp(part, "parameter"))
2761 else if(!strcmp(part, "returnValue"))
2764 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2766 /* Why invalidate this entry here?
2768 MapIterator<const String, DocCacheEntry> it { map = docCache };
2769 if(it.Index(docPath, false))
2778 case classDoc: cl = (Class)object; break;
2779 case functionDoc: function = object; break;
2780 case methodDoc: method = object; cl = method._class; break;
2785 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2787 clDoc = (ClassDoc)doc;
2789 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2791 nsDoc = (NamespaceDoc)doc;
2797 if(type == functionDoc)
2799 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2800 if(name) name += 2; else name = function.name;
2801 fnDoc = nsDoc.functions ? nsDoc.functions[name] : null;
2802 if(!empty && !fnDoc)
2804 if(!nsDoc.functions) nsDoc.functions = { };
2805 nsDoc.functions[name] = fnDoc = { };
2808 else if(type == methodDoc)
2810 mdDoc = clDoc.methods ? clDoc.methods[method.name] : null;
2811 if(!empty && !mdDoc)
2813 if(!clDoc.methods && !empty) clDoc.methods = { };
2814 clDoc.methods[method.name] = mdDoc = { };
2818 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2823 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2824 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2825 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2826 else { nsDoc.description = contents; contents = null; }
2829 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2830 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2831 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2834 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2835 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2836 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2839 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2840 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2841 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2844 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2845 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2846 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2849 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2850 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2852 case enumerationValue:
2854 ValueDoc itDoc = clDoc.values ? clDoc.values[((NamedLink)data).name] : null;
2857 if(!empty && !itDoc)
2859 if(!clDoc.values) clDoc.values = { };
2860 clDoc.values[((NamedLink)data).name] = itDoc = { };
2862 itDoc.description = contents; contents = null;
2865 MapIterator<String, ValueDoc> it { map = clDoc.values };
2866 if(it.Index(((NamedLink)data).name, false))
2875 DefineDoc itDoc = nsDoc.defines ? nsDoc.defines[((Definition)data).name] : null;
2878 if(!empty && !itDoc)
2880 if(!nsDoc.defines) nsDoc.defines = { };
2881 nsDoc.defines[((Definition)data).name] = itDoc = { };
2883 itDoc.description = contents; contents = null;
2886 MapIterator<String, DefineDoc> it { map = nsDoc.defines };
2887 if(it.Index(((Definition)data).name, false))
2896 ConversionDoc itDoc;
2897 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2898 if(name) name += 2; else name = ((Property)data).name;
2899 itDoc = clDoc.conversions ? clDoc.conversions[name] : null;
2902 if(!empty && !itDoc)
2904 if(!clDoc.conversions) clDoc.conversions = { };
2905 clDoc.conversions[name] = itDoc = { };
2907 itDoc.description = contents; contents = null;
2910 MapIterator<String, ConversionDoc> it { map = clDoc.conversions };
2911 if(it.Index(name, false))
2918 case memberDescription:
2920 FieldDoc itDoc = clDoc.fields ? clDoc.fields[((DataMember)data).name] : null;
2923 if(!empty && !itDoc)
2925 if(!clDoc.fields) clDoc.fields = { };
2926 clDoc.fields[((DataMember)data).name] = itDoc = { };
2928 itDoc.description = contents; contents = null;
2931 MapIterator<String, FieldDoc> it { map = clDoc.fields };
2932 if(it.Index(((DataMember)data).name, false))
2939 case propertyDescription:
2941 PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null;
2944 if(!empty && !itDoc)
2946 if(!clDoc.properties) clDoc.properties = { };
2947 clDoc.properties[((Property)data).name] = itDoc = { };
2949 itDoc.description = contents, contents = null;
2952 MapIterator<String, PropertyDoc> it { map = clDoc.properties };
2953 if(it.Index(((Property)data).name, false))
2962 if(type == functionDoc || type == methodDoc)
2964 Map<String, ParameterDoc> * parameters = (type == functionDoc) ? &fnDoc.parameters : &mdDoc.parameters;
2965 char * name = ((Type)data).name;
2966 ParameterDoc itDoc = *parameters ? (*parameters)[name] : null;
2969 while(prev) position++, prev = prev.prev;
2973 if(!empty && !itDoc)
2975 if(!*parameters) *parameters = { };
2976 (*parameters)[name] = itDoc = { };
2978 itDoc.description = contents; contents = null;
2979 itDoc.position = position;
2982 MapIterator<String, ParameterDoc> it { map = *parameters };
2983 if(it.Index(((Type)data).name, false))
2995 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
2997 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
2998 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2999 if(name) name += 2; else name = function.name;
3000 if(it.Index(name, false))
3004 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
3006 MapIterator<String, MethodDoc> it { map = clDoc.methods };
3007 if(it.Index(method.name, false))
3013 if(nsDoc.functions && !nsDoc.functions.count) delete nsDoc.functions;
3014 if(nsDoc.defines && !nsDoc.defines.count) delete nsDoc.defines;
3018 if(clDoc && clDoc.conversions && !clDoc.conversions.count) delete clDoc.conversions;
3019 if(clDoc && clDoc.properties && !clDoc.properties.count) delete clDoc.properties;
3020 if(clDoc && clDoc.fields && !clDoc.fields.count) delete clDoc.fields;
3021 if(clDoc && clDoc.methods && !clDoc.methods.count) delete clDoc.methods;
3022 if(clDoc && clDoc.values && !clDoc.values.count) delete clDoc.values;
3027 char dirPath[MAX_LOCATION];
3028 StripLastDirectory(docPath, dirPath);
3029 if(FileExists(docPath))
3030 DeleteFile(docPath);
3031 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
3034 if(!FileExists(dirPath))
3036 if((f = FileOpen(docPath, write)))
3038 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3042 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3051 Block parent = textBlock.parent;
3052 while((block = parent.subBlocks.first))
3054 parent.subBlocks.Remove(block);
3057 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3058 textBlock.text = CopyString($"[Add Text]");
3059 textBlock.textLen = strlen(textBlock.text);
3060 parent.subBlocks.Add(textBlock);
3068 PositionCaret(true);
3073 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3077 if(edit && (!textBlock || overLink != textBlock.parent))
3081 HTMLView::OnLeftButtonDown(x, y, mods);
3082 selPosition = curPosition = 0;
3083 selBlock = textBlock;
3087 result = HTMLView::OnLeftButtonDown(x, y, mods);
3089 if(!edit && clickedLink)
3092 if(clickedLink == overLink && clickedLink.href)
3094 if(OnOpen(clickedLink.href))
3102 if(textBlock && overLink == textBlock.parent)
3104 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3105 selBlock = textBlock;
3106 PositionCaret(true);
3114 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3116 if(!edit || !textBlock || clickedLink != textBlock.parent)
3118 HTMLView::OnLeftButtonUp(x, y, mods);
3121 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3122 selBlock = textBlock;
3123 PositionCaret(true);
3134 bool OnMouseMove(int x, int y, Modifiers mods)
3136 if(edit && selecting)
3138 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3139 PositionCaret(true);
3142 return HTMLView::OnMouseMove(x, y, mods);
3145 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3147 if(edit && textBlock)
3153 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3154 selBlock = textBlock;
3155 for(c = curPosition; c >= 0; c--)
3158 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3159 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3160 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3166 for(c = start; c < textBlock.textLen; c += numBytes)
3168 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3169 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3172 selPosition = start;
3175 PositionCaret(true);
3183 bool OnOpen(char * href)
3185 if(!strncmp(href, "api://", 6))
3187 int64 tag = (int64)strtoull(href + 6, null, 16);
3188 DataRow row = mainForm.browser.FindSubRow(tag);
3192 mainForm.browser.SelectRow(row);
3193 while((row = row.parent))
3194 row.collapsed = false;
3195 row = mainForm.browser.currentRow;
3196 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3199 else if(!strncmp(href, "edit://", 7))
3202 int startX = clickedLink.startX, startY = clickedLink.startY;
3203 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3205 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3206 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3208 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3210 display.FontExtent(block.font.font, " ", 1, null, &th);
3213 block.parent.subBlocks.Insert(null, newBlock);
3218 block.parent.subBlocks.Insert(block, newBlock);
3219 startY += block.prev.height;
3221 newBlock.startX = startX;
3222 newBlock.startY = startY;
3223 newBlock.text = new0 char[1];
3227 textBlock = (Block)clickedLink.subBlocks.first;
3228 if(!strcmp(textBlock.text, $"[Add Text]"))
3230 textBlock.text[0] = 0;
3231 textBlock.textLen = 0;
3234 strcpy(editString, href + 7);
3235 selPosition = curPosition = 0;
3236 selBlock = textBlock;
3239 // PositionCaret(true);
3246 void DeleteSelection()
3248 if(textBlock != selBlock || curPosition != selPosition)
3250 if(textBlock == selBlock)
3252 // Within same block
3253 int start = Min(curPosition, selPosition);
3254 int end = Max(curPosition, selPosition);
3255 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3256 textBlock.textLen -= end-start;
3257 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3258 curPosition = start;
3259 selPosition = start;
3263 int startSel, endSel;
3264 Block startSelBlock = null, endSelBlock = null, b, next;
3266 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3268 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3269 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3271 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3272 for(b = startSelBlock.next; b; b = next)
3274 bool isEnd = b == endSelBlock;
3275 next = GetNextBlock(b);
3276 b.parent.subBlocks.Remove(b);
3281 textBlock = startSelBlock;
3282 selBlock = startSelBlock;
3283 curPosition = startSel;
3284 selPosition = startSel;
3288 PositionCaret(true);
3293 String GetSelectionString()
3295 String selection = null;
3296 if(textBlock == selBlock)
3298 // Within same block
3299 int start = Min(curPosition, selPosition);
3300 int end = Max(curPosition, selPosition);
3301 int len = end - start;
3302 selection = new char[len + 1];
3303 memcpy(selection, textBlock.text + start, len);
3308 int startSel, endSel;
3309 Block startSelBlock = null, endSelBlock = null, b;
3312 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3315 for(b = startSelBlock; b; b = GetNextBlock(b))
3317 int start = (b == startSelBlock) ? startSel : 0;
3318 int end = (b == endSelBlock) ? endSel : b.textLen;
3319 int len = end - start;
3321 if(b == endSelBlock)
3323 else if(b.type == TEXT)
3327 selection = new char[totalLen + 1];
3329 for(b = startSelBlock; b; b = GetNextBlock(b))
3331 int start = (b == startSelBlock) ? startSel : 0;
3332 int end = (b == endSelBlock) ? endSel : b.textLen;
3333 int len = end - start;
3334 memcpy(selection + totalLen, b.text + start, len);
3336 if(b == endSelBlock)
3338 else if(b.type == TEXT)
3339 selection[totalLen++] = '\n';
3341 selection[totalLen] = 0;
3346 void CopySelection()
3348 String s = GetSelectionString();
3351 int len = strlen(s);
3353 if(cb.Allocate(len + 1))
3355 memcpy(cb.text, s, len + 1);
3363 bool OnKeyDown(Key key, unichar ch)
3370 OnLeftButtonDown(0,0,0);
3372 case Key { end, shift = true }:
3374 curPosition = textBlock.textLen;
3377 selPosition = curPosition;
3378 selBlock = textBlock;
3380 PositionCaret(true);
3383 case Key { home, shift = true }:
3388 selPosition = curPosition;
3389 selBlock = textBlock;
3391 PositionCaret(true);
3394 case Key { home, ctrl = true, shift = true }:
3397 while(textBlock.prev)
3398 textBlock = textBlock.prev.prev;
3401 selPosition = curPosition;
3402 selBlock = textBlock;
3404 PositionCaret(true);
3407 case Key { end, ctrl = true, shift = true }:
3409 while(textBlock.next && textBlock.next.next)
3410 textBlock = textBlock.next.next;
3411 curPosition = textBlock.textLen;
3414 selPosition = curPosition;
3415 selBlock = textBlock;
3417 PositionCaret(true);
3423 return HTMLView::OnKeyDown(key, ch);
3427 bool OnKeyHit(Key key, unichar ch)
3433 case Key { up, shift = true }:
3436 if(caretY == textBlock.startY)
3440 textBlock = textBlock.prev.prev;
3441 curPosition = Min(curPosition, textBlock.textLen);
3444 selPosition = curPosition;
3445 selBlock = textBlock;
3448 PositionCaret(false);
3458 int sx = textBlock.startX, sy = textBlock.startY;
3459 char * text = textBlock.text;
3461 Block block = textBlock;
3462 while(block && block.type != TD) block = block.parent;
3465 Block table = block;
3466 while(table && table.type != TABLE) table = table.parent;
3468 maxW = block.w - 2* table.cellPadding;
3470 maxW = clientSize.w - 10 - sx;
3473 maxW = clientSize.w - 10 - sx;
3474 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3478 int startPos = textPos;
3481 bool lineComplete = false;
3482 for(; textPos<textBlock.textLen && !lineComplete;)
3486 char * nextSpace = strchr(text + textPos, ' ');
3489 len = (nextSpace - (text + textPos)) + 1;
3491 len = textBlock.textLen - textPos;
3493 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3495 if(x + width + w > maxW && x > 0)
3497 lineComplete = true;
3507 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3510 curPosition = textPos;
3511 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3514 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3515 len = curPosition - startPos;
3516 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3520 selPosition = curPosition;
3521 selBlock = textBlock;
3525 PositionCaret(false);
3529 if(sy == caretY - th || textPos == textBlock.textLen)
3531 if(textPos != textBlock.textLen)
3533 int c = textPos - 1;
3534 while(c > 0 && text[c] == ' ') c--;
3535 curPosition = c + 1;
3538 selPosition = curPosition;
3539 selBlock = textBlock;
3545 curPosition = textBlock.textLen;
3548 selPosition = curPosition;
3549 selBlock = textBlock;
3553 PositionCaret(false);
3557 sx = textBlock.startX;
3558 } while(textPos < textBlock.textLen);
3563 case Key { down, shift = true }:
3568 int sx = textBlock.startX, sy = textBlock.startY;
3569 char * text = textBlock.text;
3571 Block block = textBlock;
3572 while(block && block.type != TD) block = block.parent;
3575 Block table = block;
3576 while(table && table.type != TABLE) table = table.parent;
3578 maxW = block.w - 2* table.cellPadding;
3580 maxW = clientSize.w - 10 - sx;
3583 maxW = clientSize.w - 10 - sx;
3584 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3586 while(!textPos || textPos < textBlock.textLen)
3588 int startPos = textPos;
3591 bool lineComplete = false;
3592 for(; (textPos < textBlock.textLen) && !lineComplete;)
3596 char * nextSpace = strchr(text + textPos, ' ');
3599 len = (nextSpace - (text + textPos)) + 1;
3601 len = textBlock.textLen - textPos;
3603 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3605 if(x + width + w > maxW && x > 0)
3607 lineComplete = true;
3617 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3619 curPosition = textPos;
3621 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3624 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3625 len = curPosition - startPos;
3626 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3630 selPosition = curPosition;
3631 selBlock = textBlock;
3634 PositionCaret(false);
3640 curPosition = textBlock.textLen;
3643 selPosition = curPosition;
3644 selBlock = textBlock;
3647 PositionCaret(false);
3650 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3654 textBlock = textBlock.next.next;
3655 sy = textBlock.startY;
3656 sx = textBlock.startX;
3657 text = textBlock.text;
3662 sx = textBlock.startX;
3666 /*if(textBlock.next && textBlock.next.next)
3668 textBlock = textBlock.next.next;
3669 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3670 selBlock = textBlock;
3671 PositionCaret(false);
3675 case Key { right, shift = true, ctrl = true }:
3678 bool foundAlpha = false;
3680 Block line, lastLine;
3683 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3685 int start = (line == textBlock) ? curPosition : 0;
3687 for(c = start; c < line.textLen; c++)
3689 char ch = line.text[c];
3690 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3691 if(key.shift ? isAlUnder : !isAlUnder)
3705 selPosition = curPosition;
3706 selBlock = textBlock;
3710 PositionCaret(true);
3715 // No next word found,
3716 if(!found && (c != curPosition || line != textBlock))
3720 lastC = line.textLen-1;
3725 curPosition = line.textLen;
3728 selPosition = curPosition;
3729 selBlock = textBlock;
3734 PositionCaret(true);
3740 if(key.shift && found)
3742 curPosition = lastC+1;
3743 textBlock = lastLine;
3744 PositionCaret(true);
3749 case Key { left, ctrl = true, shift = true }:
3752 bool foundAlpha = false;
3754 Block line, lastLine;
3757 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3760 if(curPosition == 0 && line != textBlock)
3763 lastC = line.textLen;
3767 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3768 for(c = start; c>=0; c--)
3770 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3785 // No next word found,
3786 if(!found && curPosition > 0)
3796 textBlock = lastLine;
3797 curPosition = lastC;
3800 selPosition = curPosition;
3801 selBlock = textBlock;
3803 PositionCaret(true);
3808 case Key { right, shift = true }:
3810 if(curPosition < textBlock.textLen)
3812 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3815 selPosition = curPosition;
3816 selBlock = textBlock;
3818 PositionCaret(true);
3821 else if(textBlock.next && textBlock.next.next)
3823 textBlock = textBlock.next.next;
3827 selPosition = curPosition;
3828 selBlock = textBlock;
3830 PositionCaret(true);
3834 case Key { left, shift = true }:
3838 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3841 selPosition = curPosition;
3842 selBlock = textBlock;
3844 PositionCaret(true);
3847 else if(textBlock.prev)
3849 textBlock = textBlock.prev.prev;
3850 curPosition = textBlock.textLen;
3853 selPosition = curPosition;
3854 selBlock = textBlock;
3856 PositionCaret(true);
3862 if(textBlock == selBlock && curPosition == selPosition)
3866 int c = curPosition;
3868 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3869 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3870 textBlock.textLen -= nb;
3871 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3873 selPosition = curPosition;
3874 selBlock = textBlock;
3878 PositionCaret(true);
3881 else if(textBlock.prev)
3883 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3884 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3885 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3887 selPosition = curPosition = prevBlock.textLen;
3888 selBlock = textBlock;
3889 prevBlock.textLen += textBlock.textLen;
3890 textBlock.parent.subBlocks.Remove(prev);
3891 if(prev == selBlock)
3893 selBlock = textBlock;
3894 selPosition = curPosition;
3897 textBlock.parent.subBlocks.Remove(textBlock);
3898 if(textBlock == selBlock)
3900 selBlock = prevBlock;
3901 selPosition = curPosition;
3904 textBlock = prevBlock;
3908 PositionCaret(true);
3917 if(textBlock != selBlock || curPosition != selPosition)
3919 else if(textBlock.textLen > curPosition)
3921 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3922 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3923 textBlock.textLen -= nb;
3924 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3929 PositionCaret(true);
3932 else if(textBlock.next && textBlock.next.next)
3934 Block next = textBlock.next, nextBlock = textBlock.next.next;
3935 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3936 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3938 textBlock.textLen += nextBlock.textLen;
3939 textBlock.parent.subBlocks.Remove(next);
3940 if(next == selBlock)
3942 selBlock = textBlock;
3943 selPosition = curPosition;
3946 textBlock.parent.subBlocks.Remove(nextBlock);
3947 if(nextBlock == selBlock)
3949 selBlock = textBlock;
3950 selPosition = curPosition;
3956 PositionCaret(true);
3970 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3971 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3972 startY = textBlock.startY;
3973 startX = textBlock.startX;
3975 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3976 textBlock.parent.subBlocks.Insert(textBlock, block);
3977 textBlock.parent.subBlocks.Insert(block, newBlock);
3981 newBlock.textLen = textBlock.textLen - curPosition;
3982 newBlock.text = new char[newBlock.textLen+1];
3983 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3984 textBlock.textLen = curPosition;
3985 textBlock.text[curPosition] = 0;
3987 newBlock.startY = startY;
3988 newBlock.startX = startX;
3989 selPosition = curPosition = 0;
3994 textBlock = newBlock;
3995 selBlock = textBlock;
3996 PositionCaret(true);
4001 case Key { del, shift = true }:
4016 ClipBoard clipBoard { };
4017 if(clipBoard.Load())
4020 char * text = clipBoard.memory;
4028 parent = textBlock.parent;
4029 font = textBlock.font;
4034 if(ch == '\n' || ch == '\r' || !ch)
4036 int len = c - start;
4037 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4038 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4039 memcpy(textBlock.text + curPosition, text + start, len);
4040 textBlock.textLen += len;
4042 selPosition = curPosition;
4043 selBlock = textBlock;
4046 Block block { type = BR, parent = parent, font = font };
4047 Block newBlock { type = TEXT, parent = parent, font = font };
4048 int startY = textBlock.startY, startX = textBlock.startX;
4051 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4052 textBlock.parent.subBlocks.Insert(textBlock, block);
4053 textBlock.parent.subBlocks.Insert(block, newBlock);
4057 newBlock.textLen = textBlock.textLen - curPosition;
4058 newBlock.text = new char[newBlock.textLen+1];
4059 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4060 textBlock.textLen = curPosition;
4061 textBlock.text[curPosition] = 0;
4063 newBlock.startY = startY;
4064 newBlock.startX = startX;
4065 selPosition = curPosition = 0;
4066 selBlock = textBlock;
4067 textBlock = newBlock;
4069 if(ch == '\r' && text[c+1] == '\n') c++;
4075 PositionCaret(true);
4083 // eC BUG HERE: (Should be fixed)
4084 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4087 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4092 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4093 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4095 for(c = 0; c<len; c++)
4097 textBlock.text[curPosition] = string[c];
4098 textBlock.textLen++;
4101 selPosition = curPosition;
4102 selBlock = textBlock;
4105 //Clear(html.block);
4106 //CreateForms(html.block);
4111 PositionCaret(true);
4120 void OnResize(int width, int height)
4122 HTMLView::OnResize(width, height);
4123 PositionCaret(true);
4127 void PositionCaret(bool setCaretX)
4133 int sx = textBlock.startX, sy = textBlock.startY;
4134 char * text = textBlock.text;
4136 Block block = textBlock;
4137 while(block && block.type != TD) block = block.parent;
4140 Block table = block;
4141 while(table && table.type != TABLE) table = table.parent;
4143 maxW = block.w - 2* table.cellPadding;
4145 maxW = clientSize.w - 10 - sx;
4148 maxW = clientSize.w - 10 - sx;
4150 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4152 while(textPos < textBlock.textLen)
4154 int startPos = textPos;
4157 bool lineComplete = false;
4159 for(; textPos<textBlock.textLen && !lineComplete;)
4163 char * nextSpace = strchr(text + textPos, ' ');
4166 len = (nextSpace - (text + textPos)) + 1;
4168 len = textBlock.textLen - textPos;
4170 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4172 if(x + width + w > maxW && x > 0)
4174 lineComplete = true;
4187 if(curPosition < textPos || textPos == textBlock.textLen)
4189 int len = curPosition - startPos;
4190 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4195 sx = textBlock.startX;
4200 SetCaret(sx, sy, th);
4202 Point scrollPos = scroll;
4203 bool doScroll = false;
4204 if(sy - scroll.y + th > clientSize.h)
4206 scrollPos.y = sy + th - clientSize.h;
4209 else if(sy - scroll.y < 0)
4214 if(sx - scroll.x + 10 > clientSize.w)
4216 scrollPos.x = sx + 10 - clientSize.w;
4219 else if(sx - scroll.x < 10)
4221 scrollPos.x = sx - 10;
4232 // Returns a character offset into the TextBlock from a window coordinate
4233 int TextPosFromPoint(int px, int py, Block * block, bool half)
4235 Block parentBlock = this.textBlock.parent;
4238 *block = this.textBlock;
4243 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4245 int sx = textBlock.startX, sy = textBlock.startY;
4248 char * text = textBlock.text;
4250 Block b = textBlock;
4253 if(textBlock.type != TEXT) continue;
4255 while(b && b.type != TD) b = b.parent;
4259 while(table && table.type != TABLE) table = table.parent;
4261 maxW = b.w - 2* table.cellPadding;
4263 maxW = clientSize.w - 10 - sx;
4266 maxW = clientSize.w - 10 - sx;
4268 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4269 //space = space/2+2;
4272 while(textPos < textBlock.textLen)
4276 bool lineComplete = false;
4278 for(; textPos<textBlock.textLen && !lineComplete;)
4282 char * nextSpace = strchr(text + textPos, ' ');
4285 len = (nextSpace - (text + textPos)) + 1;
4287 len = textBlock.textLen - textPos;
4289 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4291 sx = x + textBlock.startX;
4292 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4297 for(c = textPos; (ch = text[c]); c += numBytes)
4299 numBytes = UTF8_NUM_BYTES(ch);
4300 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4301 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4308 if(x + width + w > maxW && x > 0)
4310 lineComplete = true;
4323 if(/*py >= sy && */py < sy + th)
4326 return textBlock.textLen;
4331 result = textBlock.textLen;
4337 Application componentsApp;
4339 class Documentor : GuiApplication
4343 Platform os = __runtimePlatform;
4344 SetGlobalContext(globalContext);
4345 SetExcludedSymbols(&excludedSymbols);
4346 SetDefines(&::defines);
4347 SetImports(&imports);
4348 SetInDocumentor(true);
4350 SetGlobalData(globalData);
4352 settingsContainer.dataOwner = &ideSettings;
4353 settingsContainer.Load();
4354 if(!ideSettings.docDir || !ideSettings.docDir[0] )
4356 if(os == win32) // if Windows OS then
4358 char programFilesDir[MAX_LOCATION];
4359 char appData[MAX_LOCATION];
4360 char homeDrive[MAX_LOCATION];
4361 char winDir[MAX_LOCATION];
4362 GetEnvironment("APPDATA", appData, sizeof(appData));
4363 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4364 GetEnvironment("windir", winDir, sizeof(winDir));
4365 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4367 PathCat(programFilesDir, "ECERE SDK\\doc");
4368 ideSettings.docDir = programFilesDir;
4370 else if(homeDrive[0])
4372 PathCat(homeDrive, "ECERE SDK\\doc");
4373 ideSettings.docDir = homeDrive;
4377 PathCat(winDir, "..\\ECERE SDK\\doc");
4378 ideSettings.docDir = winDir;
4381 ideSettings.docDir = "C:\\ECERE SDK\\doc";
4383 else // if Os is Linux, or Mac OSX or something else
4384 ideSettings.docDir = "/usr/share/ecere/doc/";
4385 settingsContainer.Save();
4391 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4393 AddComponents(module, true);
4394 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4395 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4396 while((row = row.parent))
4397 row.collapsed = false;
4401 commandThread.Create();
4405 bool Cycle(bool idle)
4408 mainForm.Destroy(0);
4417 if(commandThread.created)
4419 console.CloseInput();
4420 console.CloseOutput();
4422 commandThread.Wait();
4426 FreeContext(globalContext);
4427 FreeExcludedSymbols(excludedSymbols);
4428 ::defines.Free(FreeModuleDefine);
4429 imports.Free(FreeModuleImport);
4431 FreeGlobalData(globalData);
4432 FreeTypeData(componentsApp);
4434 delete componentsApp;
4438 ConsoleFile console { };
4439 MainForm mainForm { };
4442 Thread commandThread
4449 console.GetLine(command, sizeof(command));
4450 if(!quit && command[0])
4453 if(!strcmpi(command, "Activate"))
4454 mainForm.Activate();
4455 else if(!strcmpi(command, "Quit"))
4463 #endif // !defined(EAR_TO_ECON_ECDOC)
4468 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4469 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4473 property bool isEmpty
4479 (description && *description));
4489 class MoreDoc : ItemDoc
4492 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4493 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4494 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4495 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4501 property bool isEmpty
4506 (usage && *usage) ||
4507 (example && *example) ||
4508 (remarks && *remarks) ||
4522 class NamespaceDoc : ItemDoc
4525 Map<String, DefineDoc> defines;
4526 Map<String, FunctionDoc> functions;
4528 property bool isEmpty
4533 (defines && defines.count) ||
4534 (functions && functions.count) ||
4545 class DefineDoc : ItemDoc { }
4547 class FunctionDoc : MoreDoc
4550 Map<String, ParameterDoc> parameters;
4551 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4554 property bool isEmpty
4559 (parameters && parameters.count) ||
4560 (returnValue && *returnValue) ||
4571 class ParameterDoc : ItemDoc
4577 class ClassDoc : MoreDoc
4580 Map<String, ValueDoc> values;
4581 Map<String, FieldDoc> fields;
4582 Map<String, PropertyDoc> properties;
4583 Map<String, ConversionDoc> conversions;
4584 Map<String, MethodDoc> methods;
4586 property bool isEmpty
4591 (values && values.count) ||
4592 (fields && fields.count) ||
4593 (properties && properties.count) ||
4594 (conversions && conversions.count) ||
4595 (methods && methods.count) ||
4609 class ValueDoc : ItemDoc { }
4611 class FieldDoc : ItemDoc { }
4613 class PropertyDoc : ItemDoc { }
4615 class ConversionDoc : ItemDoc { }
4617 class MethodDoc : FunctionDoc { }
4619 char * getDocFileNameFromTypeName(const char * typeName)
4621 char * docFileName = new char[MAX_FILENAME];
4622 const char * swap = "pointer";
4623 const char * s = typeName;
4624 char * d = docFileName;
4625 const char * end = s + strlen(typeName);
4626 int swapLen = strlen(swap);
4644 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4647 Time timeStamp; // Should this be last accessed, or last retrieved?
4656 Map<String, DocCacheEntry> docCache { };