2 #if !defined(EAR_TO_ECON_ECDOC)
6 import "SettingsDialog"
8 static Context globalContext { };
9 static OldList defines { };
10 static OldList imports { };
11 static NameSpace globalData;
12 static OldList excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left };
15 define app = (GuiApplication)__thisModule.application;
17 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
20 /*extern */int __ecereVMethodID_class_OnGetString;
24 static __attribute__((unused)) void Dummy()
27 a.OnGetString(null, null, null);
30 static bool editing = true;
32 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
34 static const char * iconNames[CodeObjectType] =
36 "<:ecere>constructs/class.png",
37 "<:ecere>constructs/data.png",
38 "<:ecere>constructs/method.png",
39 "<:ecere>constructs/event.png",
40 "<:ecere>constructs/property.png",
41 "<:ecere>constructs/namespace.png",
42 "<:ecere>constructs/dataType.png",
43 "<:ecere>constructs/enumValue.png",
44 "<:ecere>constructs/dataPrivate.png",
45 "<:ecere>constructs/methodPrivate.png",
46 "<:ecere>constructs/propertyPrivate.png"
49 void GetTemplateString(Class c, char * templateString)
51 Module m = c.module.application;
52 const char * n = c.name;
53 char * lt = strchr(n, '<');
59 memcpy(templateString, n, lt-n);
60 templateString[lt-n] = 0;
61 strcat(templateString, "</a>");
63 for(s = lt; (ch = *s); s++)
65 if(ch == '<' || ch == '>' || ch == ',')
70 char * d = templateString + strlen(templateString);
72 TrimLSpaces(curName, curName);
73 TrimRSpaces(curName, curName);
74 pc = eSystem_FindClass(m, curName);
76 sprintf(d, "%s<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name);
81 strcat(templateString, "<");
83 strcat(templateString, ">");
85 strcat(templateString, ", ");
94 strcat(templateString, curName);
102 // WARNING : This function expects a null terminated string since it recursively concatenate...
103 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
107 if(type.constant && (type.kind != pointerType && type.kind != arrayType))
108 strcat(string, "const ");
112 if(type._class && type._class.string)
115 strcat(string, type._class.string);
118 if(type._class.registered)
121 const char * s = type._class.registered.name;
122 sprintf(hex, "%p", type._class.registered.templateClass ? type._class.registered.templateClass : type._class.registered);
123 strcat(string, "<a href=\"api://");
125 strcat(string, "\" style=\"text-decoration: none;\">");
129 GetTemplateString(type._class.registered, n);
133 strcat(string, type._class.registered.name);
134 strcat(string, "</a>");
137 strcat(string, type._class.string);
144 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
145 if(funcType && funcType.kind == functionType)
148 DocPrintType(funcType.returnType, string, false, fullName);
149 strcat(string, "(*");
150 if(printName || funcType.thisClass)
153 if(funcType.thisClass)
155 strcat(string, funcType.thisClass.string);
156 strcat(string, "::");
159 strcat(string, type.name);
161 strcat(string, ")(");
162 for(param = funcType.params.first; param; param = param.next)
164 DocPrintType(param, string, false, fullName);
165 if(param.next) strcat(string, ", ");
171 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
172 if(string[strlen(string)-1] == '(')
175 strcat(string, " *");
179 case voidType: strcat(string, "void"); break;
180 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
181 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
182 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
183 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
184 case floatType: strcat(string, "float"); break;
185 case doubleType: strcat(string, "double"); break;
189 strcat(string, "struct ");
190 strcat(string, type.enumName);
192 else if(type.typeName)
194 strcat(string, type.typeName);
199 strcat(string, "struct ");
200 strcat(string,"(unnamed)");
203 strcat(string, "struct {");
204 for(member = type.members.first; member; member = member.next)
206 DocPrintType(member, string, true, fullName);
215 strcat(string, "union ");
216 strcat(string, type.enumName);
218 else if(type.typeName)
220 strcat(string, type.typeName);
224 strcat(string, "union ");
225 strcat(string,"(unnamed)");
231 strcat(string, "enum ");
232 strcat(string, type.enumName);
234 else if(type.typeName)
236 strcat(string, type.typeName);
239 strcat(string, "enum");
246 strcat(string, "dllexport ");
247 DocPrintType(type.returnType, string, false, fullName);
251 // DANGER: Testing This
257 strcat(string, type.name);
260 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
261 if(name) name += 2; else name = type.name;
262 strcat(string, "<b>");
263 strcat(string, name);
264 strcat(string, "</b>");
273 for(param = type.params.first; param; param = param.next)
275 DocPrintType(param, string, true, fullName);
276 if(param.next) strcat(string, ", ");
285 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
286 if(funcType && funcType.kind == functionType)
289 DocPrintType(funcType.returnType, string, false, fullName);
290 strcat(string, "(*");
291 if(printName || funcType.thisClass)
294 if(funcType.thisClass)
296 strcat(string, funcType.thisClass.string);
297 strcat(string, "::");
300 strcat(string, type.name);
302 strcat(string, ")(");
303 for(param = funcType.params.first; param; param = param.next)
305 DocPrintType(param, string, false, fullName);
306 if(param.next) strcat(string, ", ");
312 char baseType[1024], size[256];
313 Type arrayType = type;
317 while(arrayType.kind == TypeKind::arrayType)
320 if(arrayType.enumClass)
321 strcat(size, arrayType.enumClass.string);
322 else if(arrayType.arraySizeExp)
323 PrintExpression(arrayType.arraySizeExp, size);
324 //sprintf(string, "%s[%s]", baseType, size);
327 arrayType = arrayType.arrayType;
329 _PrintType(arrayType, baseType, printName, printFunction, fullName);
330 strcat(string, baseType);
331 strcat(string, size);
335 DocPrintType(type.arrayType, baseType, printName, fullName);
337 strcpy(size, type.enumClass.string);
338 else if(type.arraySizeExp)
339 PrintExpression(type.arraySizeExp, size);
340 //sprintf(string, "%s[%s]", baseType, size);
341 strcat(string, baseType);
343 strcat(string, size);
351 strcat(string, "...");
354 _PrintType(type.method.dataType, string, false, printFunction, fullName);
357 strcat(string, "subclass(");
358 strcat(string, type._class ? type._class.string : "int");
364 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
367 strcat(string, type.name);
372 void DocPrintType(Type type, char * string, bool printName, bool fullName)
375 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
376 if(funcType && funcType.kind == functionType && type != funcType)
380 DocPrintType(funcType.returnType, string, false, fullName);
382 _PrintType(type, string, printName, false, fullName);
386 strcat(string, type.name);
393 for(param = funcType.params.first; param; param = param.next)
395 DocPrintType(param, string, true, fullName);
396 if(param.next) strcat(string, ", ");
401 _PrintType(type, string, printName, true, fullName);
404 Map<String, bool> modulesAdded { };
405 void AddComponents(Module module, bool isDll)
410 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")) && !modulesAdded["ecereCOM"])
412 row = mainForm.browser.AddRow();
413 modulesAdded["ecereCOM"] = true;
414 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
415 row.tag = (int64)null;
416 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
419 for(m = module.modules.first; m; m = m.next)
421 if(m.importMode == publicAccess || !isDll)
422 AddComponents(m.module, true);
425 // PUT MODULE DESCRIPTION HERE
426 if(module.name && !modulesAdded[module.name] && strcmp(module.name, "ecereCOM"))
428 row = mainForm.browser.AddRow();
429 modulesAdded[module.name] = true;
430 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
431 row.tag = (int64)module;
432 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
434 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
446 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
451 virtual void Generate(File f)
456 virtual Module GetModule()
458 return page ? page.GetModule() : null;
461 virtual NameSpace * GetNameSpace()
463 return page ? page.GetNameSpace() : null;
467 enum DocumentationType
476 enum DocumentationItem
493 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
497 sprintf(hex, "%p", module);
498 strcat(fileName, hex);
499 strcat(fileName, "/");
500 sprintf(hex, "%p", object);
501 strcat(fileName, hex);
502 strcat(fileName, "/");
503 sprintf(hex, "%p", data);
504 strcat(fileName, hex);
505 strcat(fileName, "/");
506 if(type == nameSpaceDoc)
507 strcat(fileName, "namespace");
508 else if(type == functionDoc)
509 strcat(fileName, "function");
510 else if(type == classDoc)
511 strcat(fileName, "class");
512 else if(type == methodDoc)
513 strcat(fileName, "method");
514 strcat(fileName, "/");
515 if(item == description)
516 strcat(fileName, "description");
517 else if(item == usage)
518 strcat(fileName, "usage");
519 else if(item == remarks)
520 strcat(fileName, "remarks");
521 else if(item == example)
522 strcat(fileName, "example");
523 else if(item == seeAlso)
524 strcat(fileName, "seeAlso");
525 else if(item == enumerationValue)
526 strcat(fileName, "enumerationValue");
527 else if(item == definition)
528 strcat(fileName, "definition");
529 else if(item == conversion)
530 strcat(fileName, "conversion");
531 else if(item == memberDescription)
532 strcat(fileName, "memberDescription");
533 else if(item == propertyDescription)
534 strcat(fileName, "propertyDescription");
535 else if(item == parameter)
536 strcat(fileName, "parameter");
537 else if(item == returnValue)
538 strcat(fileName, "returnValue");
541 static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
543 char docPath[MAX_LOCATION];
544 NameSpace * nameSpace, * ns;
546 Method method = null;
547 GlobalFunction function = null;
548 char nsName[1024], temp[1024];
551 case nameSpaceDoc: nameSpace = object; break;
552 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
553 case functionDoc: function = object; nameSpace = function.nameSpace; break;
554 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
560 while(ns && ns->name)
562 strcpy(temp, ns->name);
564 strcat(temp, nsName);
565 strcpy(nsName, temp);
570 PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
571 //ChangeExtension(docPath, "eCdoc", docPath);
572 PathCatSlash(docPath, nsName);
575 char * name = getDocFileNameFromTypeName(cl.name);
576 PathCatSlash(docPath, name);
580 PathCatSlash(docPath, "_global-defs");
581 ChangeExtension(docPath, "econ", docPath);
584 strcpy(path, ideSettings.docDir);
585 PathCatSlash(path, docPath);
588 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
590 String contents = null;
591 NamespaceDoc nsDoc = null;
592 ClassDoc clDoc = null;
593 FunctionDoc fnDoc = null;
594 MethodDoc mdDoc = null;
596 char filePath[MAX_LOCATION];
597 Method method = null;
598 GlobalFunction function = null;
600 ItemDoc doc = getDoc(filePath, module, type, object, item, data, false);
604 case functionDoc: function = object; break;
605 case methodDoc: method = object; break;
610 if(eClass_IsDerived(doc._class, class(ClassDoc)))
612 clDoc = (ClassDoc)doc;
614 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
616 nsDoc = (NamespaceDoc)doc;
622 ItemDoc itDoc = null;
623 if(type == functionDoc)
625 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
626 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
627 if(name) name += 2; else name = function.name;
628 if(it.Index(name, false))
631 else if(type == methodDoc)
633 MapIterator<String, MethodDoc> it { map = clDoc.methods };
634 if(it.Index(method.name, false))
640 case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break;
641 case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break;
642 case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break;
643 case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break;
644 case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break;
645 case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break;
646 case enumerationValue:
647 if(clDoc && clDoc.values)
649 itDoc = clDoc.values[((NamedLink)data).name];
650 if(itDoc) s = itDoc.description;
654 if(nsDoc && nsDoc.defines)
656 itDoc = nsDoc.defines[((Definition)data).name];
657 if(itDoc) s = itDoc.description;
661 if(clDoc && clDoc.conversions)
663 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
664 if(name) name += 2; else name = ((Property)data).name;
665 itDoc = clDoc.conversions[name];
666 if(itDoc) s = itDoc.description;
669 case memberDescription:
670 if(clDoc && clDoc.fields)
672 itDoc = clDoc.fields[((DataMember)data).name];
673 if(itDoc) s = itDoc.description;
676 case propertyDescription:
677 if(clDoc && clDoc.properties)
679 itDoc = clDoc.properties[((Property)data).name];
680 if(itDoc) s = itDoc.description;
684 if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters))
686 char * name = ((Type)data).name;
687 itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ;
688 if(itDoc) s = itDoc.description;
693 contents = CopyString(s);
695 if(editing && !contents && !readOnly)
696 contents = CopyString($"[Add Text]");
700 // The filePath is returned!
701 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
705 Method method = null;
711 case classDoc: cl = (Class)object; break;
712 case methodDoc: method = object; cl = method._class; break;
715 FigureFilePath(filePath, module, type, object, item, data);
717 entry = docCache[filePath];
723 File f = FileOpen(filePath, read);
726 ECONParser parser { f = f };
727 JSONResult jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
731 if(jsonResult != success)
733 PrintLn("error: problem parsing file: ", filePath);
738 doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
741 incref doc; // Reference to return
746 entry.timeStamp = now;
749 docCache[filePath] = { now, doc };
750 incref doc; // Reference for the cache
753 //void pruneDocCache()
754 // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
756 MapIterator<String, DocCacheEntry> it { map = docCache };
757 Array<const String> toRemove { };
758 for(entry : docCache; now - entry.timeStamp > 30)
759 toRemove.Add(&entry);
760 while(toRemove.count)
762 if(it.Index(toRemove.lastIterator.data, false))
767 toRemove.Remove(toRemove.lastIterator.pointer);
774 class APIPageNameSpace : APIPage
776 NameSpace * nameSpace;
784 NameSpace * GetNameSpace()
789 void Generate(File f)
791 char nsName[1024], temp[1024];
797 while(ns && ns->name)
799 strcpy(temp, ns->name);
800 if(nsName[0]) strcat(temp, "::");
801 strcat(temp, nsName);
802 strcpy(nsName, temp);
805 // Generate Class Page
806 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
809 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
810 f.Printf($"Module: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", (module && module.name) ? module : null, (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
813 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
816 ns = nameSpace->parent;
817 while(ns && ns->name)
819 strcpy(temp, ns->name);
820 if(nsName[0]) strcat(temp, "::");
821 strcat(temp, nsName);
822 strcpy(nsName, temp);
826 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
830 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
833 f.Printf($"<H3>Description</H3><BR>\n");
836 char fileName[MAX_LOCATION];
837 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
838 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
843 f.Printf("%s", desc);
844 f.Printf("<br><br><br>");
849 if(nameSpace->nameSpaces.first)
852 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
854 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
857 f.Printf($"<H3>Sub Namespaces</H3><BR>\n");
858 f.Printf("<TABLE>\n");
862 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", iconNames[typeNameSpace], ns, ns->name);
867 char fileName[MAX_LOCATION];
868 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
869 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
871 f.Printf("</a></TD>");
874 f.Printf("<TD valign=top height=22> %s</TD>", desc);
877 f.Printf("</TR><br>\n");
880 f.Printf("</TABLE><br><br>\n");
883 if(nameSpace->classes.first)
886 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
888 Class cl = link.data;
889 Module module = cl.module ? cl.module : this.module;
890 if(!cl.templateClass && !cl.internalDecl)
892 char * desc = ReadDoc(module, classDoc, cl, description, null);
896 f.Printf($"<a name=Classes></a><H3>Classes</H3><BR>\n");
897 f.Printf("<TABLE>\n");
903 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? iconNames[typeDataType] : iconNames[typeClass], cl, cl.name);
908 char fileName[MAX_LOCATION];
909 FigureFileName(fileName, module, classDoc, cl, description, null);
910 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
912 f.Printf("</a></TD>");
915 f.Printf("<TD valign=top height=22>%s</TD>", desc);
922 f.Printf("</TABLE><br><br>\n");
925 if(nameSpace->functions.first)
928 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
930 GlobalFunction function = link.data;
931 Module module = function.module ? function.module : this.module;
932 char * desc = ReadDoc(module, functionDoc, function, description, null);
933 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
934 if(name) name += 2; else name = function.name;
937 f.Printf($"<a name=Functions></a><H3>Functions</H3><BR>\n");
938 f.Printf("<TABLE>\n");
942 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", iconNames[typeMethod], function, name);
947 char fileName[MAX_LOCATION];
948 FigureFileName(fileName, module, functionDoc, function, description, null);
949 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
951 f.Printf("</a></TD>");
954 f.Printf("<TD valign=top height=22> %s</TD>", desc);
957 f.Printf("</TR><br>\n");
960 f.Printf("</TABLE><br><br>\n");
963 if(nameSpace->defines.first)
966 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
968 DefinedExpression def = link.data;
969 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
972 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><BR>\n");
973 f.Printf("<TABLE>\n");
977 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", def, iconNames[typeData], def.name);
978 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
983 char fileName[MAX_LOCATION];
984 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
985 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
987 f.Printf("</a></TD>");
990 f.Printf("<TD valign=top height=22> %s</TD>", desc);
993 f.Printf("</TR><br>\n");
996 f.Printf("</TABLE><br><br>\n");
999 f.Printf("</FONT></BODY></HTML>\n");
1003 class APIPageClass : APIPage
1012 NameSpace * GetNameSpace()
1014 return cl.nameSpace;
1017 void Generate(File f)
1022 char nsName[1024], temp[1024];
1023 NameSpace * ns = cl.nameSpace;
1024 Module module = cl.module;
1027 while(ns && ns->name)
1029 strcpy(temp, ns->name);
1030 if(nsName[0]) strcat(temp, "::");
1031 strcat(temp, nsName);
1032 strcpy(nsName, temp);
1035 // Generate Class Page
1036 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1037 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1039 f.Printf($"Module: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", (module && module.name) ? module : null, (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
1041 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1044 const char * classType = null;
1048 classType = $"Bit Collection";
1051 classType = $"Enumeration";
1054 classType = $"Structure";
1057 classType = $"Class";
1060 classType = $"Class (No header)";
1063 classType = $"Unit";
1066 classType = $"Basic Data Type";
1069 f.Printf($"Type: %s<br>\n", classType);
1072 if(cl.type != systemClass && cl.base)
1074 f.Printf($"Base Class: ");
1075 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1077 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1079 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1080 f.Printf("%s", cl.dataTypeString);
1082 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1087 char * desc = ReadDoc(module, classDoc, cl, description, null);
1090 f.Printf($"<br><H3>Description</H3><BR>\n");
1093 char fileName[MAX_LOCATION];
1094 FigureFileName(fileName, module, classDoc, cl, description, null);
1095 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1100 f.Printf("%s", desc);
1101 f.Printf("<br><br><br>");
1106 if(cl.type == enumClass)
1108 EnumClassData enumeration = (EnumClassData)cl.data;
1109 if(enumeration.values.first)
1113 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><BR>\n");
1114 f.Printf("<TABLE>\n");
1116 for(item = enumeration.values.first; item; item = item.next)
1118 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1119 bool needClass = true;
1122 char tempString[1024];
1124 while(base.type == enumClass) base = base.base;
1126 if(base.type == systemClass ||
1127 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1130 base.dataType = ProcessTypeString(base.dataTypeString, false);
1132 if(base.dataType.kind != classType)
1137 PrintType(base.dataType, string, false, true);
1138 classSym = FindClass(string);
1139 dataClass = classSym ? classSym.registered : null;
1142 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1148 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", item, iconNames[typeEnumValue], item.name);
1149 if(dataClass.type == systemClass)
1152 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1155 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1157 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1159 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1164 char fileName[MAX_LOCATION];
1165 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1166 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1168 f.Printf("</a></TD>");
1171 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1176 f.Printf("</TABLE><BR>\n");
1180 if(cl.conversions.first)
1182 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><BR>\n");
1183 f.Printf("<TABLE>\n");
1184 for(prop = cl.conversions.first; prop; prop = prop.next)
1186 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1188 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1190 Type type = ProcessTypeString(prop.name, false);
1191 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1192 if(name) name += 2; else name = prop.name;
1197 DocPrintType(type, string, true, false);
1199 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1204 char fileName[MAX_LOCATION];
1205 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1206 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1208 f.Printf("</a></TD>");
1211 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1215 f.Printf("</TR>\n");
1220 f.Printf("</TABLE><br><br>\n");
1223 if(cl.membersAndProperties.first)
1226 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1228 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1232 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><BR>\n");
1233 f.Printf("<TABLE>\n");
1239 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1241 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1245 DocPrintType(prop.dataType, string, true, false);
1247 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeProperty], prop.name);
1248 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1253 char fileName[MAX_LOCATION];
1254 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1255 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1257 f.Printf("</a></TD>");
1260 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1263 f.Printf("</TR>\n");
1267 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1272 f.Printf("</TABLE><br><br>\n");
1275 if(cl.methods.first)
1279 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1281 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1283 char * desc = ReadDoc(module, methodDoc, method, description, null);
1286 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><BR>\n");
1287 f.Printf("<TABLE>\n");
1290 if(!method.dataType)
1291 ProcessMethodType(method);
1294 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", method.dataType.thisClass ? iconNames[typeEvent] : iconNames[typeMethod], method, method.name);
1299 char fileName[MAX_LOCATION];
1300 FigureFileName(fileName, module, methodDoc, method, description, null);
1301 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1303 f.Printf("</a></TD>");
1306 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1309 f.Printf("</TR><br>\n");
1313 f.Printf("</TABLE><br><br>\n");
1315 // Non-Virtual Methods
1317 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1319 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1321 char * desc = ReadDoc(module, methodDoc, method, description, null);
1324 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><BR>\n");
1325 f.Printf("<TABLE>\n");
1329 if(!method.dataType)
1330 ProcessMethodType(method);
1333 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", iconNames[typeMethod], method, method.name);
1338 char fileName[MAX_LOCATION];
1339 FigureFileName(fileName, module, methodDoc, method, description, null);
1340 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1342 f.Printf("</a></TD>");
1345 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1349 f.Printf("</TR><br>\n");
1353 f.Printf("</TABLE><br><br>\n");
1356 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1359 f.Printf($"<H3>Usage</H3><BR>\n");
1362 char fileName[MAX_LOCATION];
1363 FigureFileName(fileName, module, classDoc, cl, usage, null);
1364 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1369 f.Printf("<br>%s\n", usageDoc);
1370 f.Printf("<br><br><br>\n");
1375 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1378 f.Printf($"<H3>Example</H3><BR>\n");
1379 f.Printf($"<FONT face=\"Courier New\">\n");
1380 f.Printf("<br><TABLE>\n");
1383 char fileName[MAX_LOCATION];
1384 FigureFileName(fileName, module, classDoc, cl, example, null);
1385 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1387 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1390 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1392 f.Printf("</TABLE></FONT>\n");
1393 f.Printf("<br><br>\n");
1398 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1402 f.Printf($"<H3>Remarks</H3><BR>\n");
1405 char fileName[MAX_LOCATION];
1406 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1407 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1412 f.Printf("<br>%s\n", remarksDoc);
1413 f.Printf("<br><br><br>\n");
1418 if(cl.type != systemClass)
1422 for(c = cl.derivatives.first; c; c = c.next)
1424 Class deriv = c.data;
1425 // TO VERIFY: Does this properly check public status?
1426 if(eSystem_FindClass(componentsApp, deriv.fullName))
1430 f.Printf($"<H3>Derived Classes</H3><BR>\n");
1435 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1439 f.Printf("<br><br>\n");
1442 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1445 f.Printf($"<H3>See Also</H3>\n");
1448 char fileName[MAX_LOCATION];
1449 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1450 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1455 f.Printf("<br>%s\n", seeAlsoDoc);
1456 f.Printf("<br><br>\n");
1460 f.Printf("</FONT></BODY></HTML>\n");
1464 class APIPageMethod : APIPage
1470 return method._class.module;
1473 NameSpace * GetNameSpace()
1475 return method._class.nameSpace;
1478 void Generate(File f)
1480 Class cl = method._class;
1482 Module module = cl.module;
1484 char nsName[1024], temp[1024];
1485 NameSpace * ns = cl.nameSpace;
1488 while(ns && ns->name)
1490 strcpy(temp, ns->name);
1491 if(nsName[0]) strcat(temp, "::");
1492 strcat(temp, nsName);
1493 strcpy(nsName, temp);
1497 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1498 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1500 f.Printf($"Module: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", (module && module.name) ? module : null, (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
1502 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1503 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1504 if(method.dataType.staticMethod)
1506 f.Printf($"this pointer class: None<br>\n");
1508 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1510 f.Printf($"this pointer class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", method.dataType.thisClass.registered, method.dataType.thisClass.registered.name);
1513 // Generate Method Page
1515 if(!method.dataType.name)
1516 method.dataType.name = CopyString(method.name);
1517 DocPrintType(method.dataType, string, true, false);
1518 f.Printf("<br>%s", string);
1521 char * desc = ReadDoc(module, methodDoc, method, description, null);
1524 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1527 char fileName[MAX_LOCATION];
1528 FigureFileName(fileName, module, methodDoc, method, description, null);
1529 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1534 f.Printf("%s", desc);
1535 f.Printf("<BR><BR>");
1540 f.Printf("<br><br>\n");
1541 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1543 f.Printf($"<H3>Parameters</H3><BR>\n");
1545 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1546 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1548 f.Printf("<TABLE valign=center>\n");
1551 for(param = method.dataType.params.first; param; param = param.next)
1553 // ADD DESCRIPTION HERE
1554 if(param.kind != voidType)
1556 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1559 DocPrintType(param, string, false, false);
1561 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1562 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1567 char fileName[MAX_LOCATION];
1568 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1569 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1571 f.Printf("</a></TD>\n");
1574 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1578 f.Printf("</TR>\n");
1581 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1583 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1584 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1586 f.Printf("<TR><TD> </TD></TR>");
1589 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1591 DocPrintType(method.dataType.returnType, string, false, false);
1592 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1597 char fileName[MAX_LOCATION];
1598 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1599 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1601 f.Printf("</a> </TD>\n");
1604 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1607 f.Printf("</TR>\n");
1608 f.Printf("</TABLE>\n");
1610 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1611 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1613 f.Printf("</TABLE><br>\n");
1616 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1619 f.Printf($"<H3>Usage</H3><BR>\n");
1622 char fileName[MAX_LOCATION];
1623 FigureFileName(fileName, module, methodDoc, method, usage, null);
1624 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1629 f.Printf("<br>%s\n", usageDoc);
1630 f.Printf("<br><br><br>\n");
1635 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1638 f.Printf($"<H3>Example</H3><BR>\n");
1639 f.Printf($"<FONT face=\"Courier New\">\n");
1640 f.Printf("<br><TABLE>\n");
1643 char fileName[MAX_LOCATION];
1644 FigureFileName(fileName, module, methodDoc, method, example, null);
1645 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1647 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1650 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1651 f.Printf("</TABLE></FONT>\n");
1652 f.Printf("<br><br>\n");
1657 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1660 f.Printf($"<H3>Remarks</H3><BR>\n");
1663 char fileName[MAX_LOCATION];
1664 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1665 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1670 f.Printf("<br>%s\n", method, remarksDoc);
1671 f.Printf("<br><br><br>\n");
1676 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1679 f.Printf($"<H3>See Also</H3><BR>\n");
1682 char fileName[MAX_LOCATION];
1683 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1684 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1689 f.Printf("<br>%s\n", method, seeAlsoDoc);
1691 f.Printf("<br><br><br>\n");
1695 f.Printf("</FONT></BODY></HTML>\n");
1699 class APIPageFunction : APIPage
1701 GlobalFunction function;
1705 return function.module;
1708 NameSpace * GetNameSpace()
1710 return function.nameSpace;
1713 void Generate(File f)
1716 Module module = function.module;
1718 char nsName[1024], temp[1024];
1719 NameSpace * ns = function.nameSpace;
1722 while(ns && ns->name)
1724 strcpy(temp, ns->name);
1725 if(nsName[0]) strcat(temp, "::");
1726 strcat(temp, nsName);
1727 strcpy(nsName, temp);
1731 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1732 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1734 f.Printf($"Module: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", (module && module.name) ? module : null, (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
1737 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1739 if(!function.dataType)
1740 function.dataType = ProcessTypeString(function.dataTypeString, false);
1742 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1744 f.Printf($"this pointer class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.dataType.thisClass.registered, function.dataType.thisClass.registered.name);
1747 // Generate Method Page
1749 if(!function.dataType.name)
1750 function.dataType.name = CopyString(function.name);
1751 DocPrintType(function.dataType, string, true, false);
1752 f.Printf("<br>%s", string);
1755 char * desc = ReadDoc(module, functionDoc, function, description, null);
1758 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1761 char fileName[MAX_LOCATION];
1762 FigureFileName(fileName, module, functionDoc, function, description, null);
1763 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1768 f.Printf("%s", desc);
1770 f.Printf("<BR><BR>");
1773 f.Printf("<br><br>\n");
1774 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1776 f.Printf($"<H3>Parameters</H3><BR>\n");
1778 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1779 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1781 f.Printf("<TABLE valign=center>\n");
1784 for(param = function.dataType.params.first; param; param = param.next)
1786 // ADD DESCRIPTION HERE
1787 if(param.kind != voidType)
1789 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1792 DocPrintType(param, string, false, false);
1794 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1795 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1800 char fileName[MAX_LOCATION];
1801 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1802 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1805 f.Printf("</a> </TD>\n");
1808 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1811 f.Printf("</TR>\n");
1814 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1816 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1817 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1819 f.Printf("<TR><TD> </TD></TR>");
1822 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1824 DocPrintType(function.dataType.returnType, string, false, false);
1825 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1830 char fileName[MAX_LOCATION];
1831 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1832 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1834 f.Printf("</a> </TD>\n");
1837 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1840 f.Printf("</TR>\n");
1841 f.Printf("</TABLE>\n");
1843 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1844 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1846 f.Printf("</TABLE><br>\n");
1849 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1852 f.Printf($"<H3>Usage</H3><BR>\n");
1855 char fileName[MAX_LOCATION];
1856 FigureFileName(fileName, module, functionDoc, function, usage, null);
1857 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1862 f.Printf("<br>%s\n", usageDoc);
1863 f.Printf("<br><br><br>\n");
1868 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1871 f.Printf($"<H3>Example</H3><BR>\n");
1872 f.Printf($"<FONT face=\"Courier New\">\n");
1873 f.Printf("<br><TABLE>\n");
1876 char fileName[MAX_LOCATION];
1877 FigureFileName(fileName, module, functionDoc, function, example, null);
1878 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1880 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1883 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1884 f.Printf("</TABLE></FONT>\n");
1885 f.Printf("<br><br>\n");
1890 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1893 f.Printf($"<H3>Remarks</H3><BR>\n");
1896 char fileName[MAX_LOCATION];
1897 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1898 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1903 f.Printf("<br>%s\n", remarksDoc);
1904 f.Printf("<br><br><br>\n");
1909 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1912 f.Printf($"<H3>See Also</H3><BR>\n");
1915 char fileName[MAX_LOCATION];
1916 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1917 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1922 f.Printf("<br>%s\n", seeAlsoDoc);
1923 f.Printf("<br><br><br>\n");
1927 f.Printf("</FONT></BODY></HTML>\n");
1931 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1935 NameSpace * nameSpace = mainNameSpace;
1937 DataRow classesRow = null;
1938 DataRow functionsRow = null, definesRow = null;
1941 strcpy(nsName, parentName ? parentName : "");
1945 strcat(nsName, "::");
1946 strcat(nsName, nameSpace->name);
1951 row = parentRow.AddRow();
1952 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1953 row.tag = (int64)nameSpace;
1954 row.icon = mainForm.icons[typeNameSpace];
1958 // "Global NameSpace"
1960 page = parentRow.GetData(null);
1963 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1965 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1966 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1968 if(comNameSpace != null)
1970 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1972 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1974 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1979 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1981 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1983 if(nameSpace->classes.first)
1987 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1990 if(!cl.templateClass && !cl.internalDecl && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1992 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1993 AddClass(classesRow, module, cl, nsName, showPrivate);
2000 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2002 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2004 if(nameSpace->functions.first)
2008 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2011 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2013 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2015 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2016 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2023 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2025 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2027 if(nameSpace->defines.first)
2031 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2034 //if(def.module == module)
2036 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2038 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2039 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2047 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2051 if(!member.dataType)
2052 member.dataType = ProcessTypeString(member.dataTypeString, false);
2056 DocPrintType(member.dataType, string, true, false);
2058 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2059 for(c = 0; c<indent; c++)
2060 f.Printf(" ");
2061 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2062 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2063 if(member.type == normalMember)
2065 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2070 char fileName[MAX_LOCATION];
2071 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2072 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2074 f.Printf("</a></TD>");
2077 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2082 f.Printf("<TD valign=top height=22></TD>");
2084 if(member.type != normalMember)
2086 DataMember subMember;
2087 for(subMember = member.members.first; subMember; subMember = subMember.next)
2089 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2091 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2095 f.Printf("</TR><br>\n");
2098 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2101 if(member.type == normalMember)
2103 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2104 row.tag = (int64)member;
2109 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2110 row.icon = mainForm.icons[typeData];
2111 row.tag = (int64)member;
2113 for(m = member.members.first; m; m = m.next)
2115 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2116 AddDataMember(row, page, m);
2121 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2126 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2127 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2130 row = parentRow.AddRow();
2131 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2132 row.tag = (int64)cl;
2133 row.collapsed = true;
2134 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2137 if(cl.methods.first)
2139 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2141 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2144 if(!method.dataType)
2145 ProcessMethodType(method);
2146 if(method.type == virtualMethod)
2148 if(method.dataType.thisClass)
2150 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2151 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2152 mRow.tag = (int64)method;
2156 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2157 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2158 mRow.tag = (int64)method;
2163 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2164 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2165 mRow.tag = (int64)method;
2171 if(cl.membersAndProperties.first)
2173 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2175 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2178 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2182 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2183 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2184 mRow.tag = (int64)prop;
2188 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2189 AddDataMember(membersRow, page, (DataMember)prop);
2195 if(cl.conversions.first)
2197 for(prop = cl.conversions.first; prop; prop = prop.next)
2201 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2202 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2203 if(name) name += 2; else name = prop.name;
2204 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2205 mRow.tag = (int64)prop;
2208 if(cl.type == enumClass)
2210 EnumClassData enumeration = (EnumClassData)cl.data;
2212 for(item = enumeration.values.first; item; item = item.next)
2215 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2216 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2217 mRow.tag = (int64)item;
2222 class AddressBar : Window
2224 background = activeBorder;
2228 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2230 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2232 MainForm mainForm = (MainForm)parent;
2233 FileDialog fileDialog = mainForm.fileDialog;
2234 if(fileDialog.Modal() == ok)
2235 mainForm.OpenModule(fileDialog.filePath);
2241 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2244 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2246 ((MainForm)parent).Back();
2252 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2255 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2257 ((MainForm)parent).Forward();
2263 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2265 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2267 ((MainForm)parent).Home();
2271 /* TODO: Search (#143/#441)
2272 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2273 Update this in the NotifyUpdate. Enter goes to the exact match.
2275 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2279 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2281 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2283 if(!disabled && (SmartKey)key == enter)
2284 ((MainForm)parent).Go(editBox.contents);
2288 void NotifyUpdate(EditBox editBox)
2290 String location = ((MainForm)parent).view.location;
2291 disabled = !strcmp(location ? location : "", editBox.contents);
2296 bool OnKeyHit(Key key, unichar ch)
2299 ((MainForm)parent).view.MakeActive();
2304 class MainForm : Window
2306 size = { 1000, 600 };
2308 borderStyle = sizable;
2311 icon = { ":documentorIcon.png" };
2312 text = $"API Documentation Browser";
2314 BitmapResource icons[CodeObjectType];
2319 for(c = 0; c < CodeObjectType::enumSize; c++)
2321 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2323 browser.AddField(DataField { dataType = class(APIPage) });
2328 Menu fileMenu { menu, $"File", f };
2329 Array<FileFilter> fileFilters
2331 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2332 { $"eC Symbol files (*.sym)", "sym" }
2335 FileDialog fileDialog
2337 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2339 MenuItem fileOpenItem
2341 fileMenu, $"Open...", o, ctrlO;
2343 bool NotifySelect(MenuItem selection, Modifiers mods)
2345 if(fileDialog.Modal() == ok)
2347 OpenModule(fileDialog.filePath);
2352 MenuItem fileSettingsItem
2354 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2356 bool NotifySelect(MenuItem selection, Modifiers mods)
2358 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2368 MenuDivider { fileMenu };
2369 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2371 void OpenModule(const char * filePath)
2373 char moduleName[MAX_LOCATION];
2374 char extension[MAX_EXTENSION];
2375 Module module = null;
2376 static char symbolsDir[MAX_LOCATION];
2379 modulesAdded.RemoveAll();
2381 FreeContext(globalContext);
2382 FreeExcludedSymbols(excludedSymbols);
2383 ::defines.Free(FreeModuleDefine);
2384 imports.Free(FreeModuleImport);
2386 FreeGlobalData(globalData);
2390 FreeTypeData(componentsApp);
2391 delete componentsApp;
2394 componentsApp = __ecere_COM_Initialize(false, 1, null);
2395 SetPrivateModule(componentsApp);
2397 StripLastDirectory(filePath, symbolsDir);
2398 SetSymbolsDir(symbolsDir);
2400 GetExtension(filePath, extension);
2402 mainForm.browser.Clear();
2404 ImportModule(filePath, normalImport, publicAccess, false);
2406 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2407 componentsApp.name = CopyString(filePath);
2409 for(module = componentsApp.allModules.first; module; module = module.next)
2411 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2415 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2416 AddComponents(componentsApp, false);
2418 GetLastDirectory(filePath, moduleName);
2419 // Extension, path and lib prefix get removed in Module::name
2422 StripExtension(moduleName);
2423 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2425 int len = strlen(moduleName) - 3;
2426 memmove(moduleName, moduleName + 3, len);
2427 moduleName[len] = 0;
2431 for(module = componentsApp.allModules.first; module; module = module.next)
2433 if(module.name && (!strcmp(module.name, moduleName)))
2436 if(!module) module = componentsApp;
2437 homeModule = module;
2438 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2440 SetSymbolsDir(null);
2443 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2446 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2447 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2450 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2452 APIPage page = row.GetData(null);
2453 if(view.edit) view.OnLeftButtonDown(0,0,0);
2454 if(page && page.page) page = page.page;
2456 view.PositionCaret(true);
2457 if(page != view.page)
2459 Window activeChild = this.activeChild;
2461 // Back / Forward Support
2462 if(row && !dontRecordHistory)
2464 if(history.count > historyPos+1)
2465 history.count = historyPos+1;
2466 historyPos = history.count-1;
2467 addressBar.back.disabled = (historyPos == 0);
2468 addressBar.forward.disabled = (historyPos >= history.count-1);
2470 history.Add((Instance)(uint64)row.tag);
2471 historyPos = history.count-1;
2473 addressBar.back.disabled = (historyPos == 0);
2474 addressBar.forward.disabled = (historyPos >= history.count-1);
2480 activeChild.Activate();
2482 else if(!view.created)
2486 page = row.GetData(null);
2487 if(page && page.page)
2491 case 1: view.GoToAnchor("Classes"); break;
2492 case 2: view.GoToAnchor("Functions"); break;
2493 case 3: view.GoToAnchor("Definitions"); break;
2494 case 4: view.GoToAnchor("VirtualMethods"); break;
2495 case 5: view.GoToAnchor("Methods"); break;
2496 case 6: view.GoToAnchor("Members"); break;
2497 case 7: view.GoToAnchor("Conversions"); break;
2498 case 8: view.GoToAnchor("EnumerationValues"); break;
2502 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2503 view.GoToAnchor(hex);
2509 view.SetScrollPosition(0, 0);
2517 this, anchor = { top = 26, bottom = 0, right = 0 };
2522 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2525 bool OnClose(bool parentClosing)
2528 view.OnLeftButtonDown(0,0,0);
2534 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2535 //mainForm.OpenModule("ec");
2536 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2537 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2539 int index = mainForm.browser.currentRow.index;
2540 int rowHeight = mainForm.browser.rowHeight;
2541 int height = mainForm.browser.clientSize.h;
2543 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2548 Array<Instance> history { };
2550 bool dontRecordHistory;
2555 if(historyPos < history.count-1)
2559 addressBar.back.disabled = (historyPos == 0);
2560 addressBar.forward.disabled = (historyPos >= history.count-1);
2561 sprintf(location, "api://%p", history[historyPos]);
2562 dontRecordHistory = true;
2563 view.OnOpen(location);
2564 dontRecordHistory = false;
2576 addressBar.back.disabled = (historyPos == 0);
2577 addressBar.forward.disabled = (historyPos >= history.count-1);
2578 sprintf(location, "api://%p", history[historyPos]);
2579 dontRecordHistory = true;
2580 view.OnOpen(location);
2581 dontRecordHistory = false;
2589 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2593 class EditDialog : Window
2595 borderStyle = sizable;
2596 size = { 600, 400 };
2601 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2605 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2609 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2613 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2614 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2616 class HelpView : HTMLView
2620 hasVertScroll = true;
2621 hasHorzScroll = true;
2623 char editString[MAX_LOCATION];
2629 page = mainForm.browser.currentRow.GetData(null);
2634 char docDir[MAX_LOCATION];
2636 strcpy(docDir, ideSettings.docDir);
2637 if(FileExists(docDir).isDirectory)
2639 PathCatSlash(docDir, "___docWriteTest");
2640 if(FileExists(docDir).isDirectory)
2643 if(!FileExists(docDir))
2649 if(FileExists(docDir).isDirectory)
2661 GoToAnchor(page.label);
2663 if(page.page) page = page.page;
2666 return HTMLView::OnCreate();
2677 String contents = null;
2680 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2682 if(block.type == TEXT && block.textLen)
2690 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2692 if(block.type == BR)
2694 else if(block.type == TEXT)
2695 f.Write(block.text, 1, block.textLen);
2699 if((len = f.GetSize()))
2701 contents = new char[len+1];
2702 f.Read(contents, 1, len);
2703 contents[len] = '\0';
2707 char docPath[MAX_LOCATION];
2708 char temp[MAX_LOCATION];
2709 char part[MAX_FILENAME];
2713 DocumentationType type;
2714 DocumentationItem item;
2716 NamespaceDoc nsDoc = null;
2717 ClassDoc clDoc = null;
2718 FunctionDoc fnDoc = null;
2719 MethodDoc mdDoc = null;
2721 Method method = null;
2722 GlobalFunction function = null;
2724 strcpy(temp, editString);
2725 SplitDirectory(temp, part, temp);
2726 module = (Module)strtoull(part, null, 16);
2727 SplitDirectory(temp, part, temp);
2728 object = (void *)strtoull(part, null, 16);
2729 SplitDirectory(temp, part, temp);
2730 data = (void *)strtoull(part, null, 16);
2731 SplitDirectory(temp, part, temp);
2732 if(!strcmp(part, "namespace"))
2733 type = nameSpaceDoc;
2734 else if(!strcmp(part, "function"))
2736 else if(!strcmp(part, "class"))
2738 else if(!strcmp(part, "method"))
2740 SplitDirectory(temp, part, temp);
2741 if(!strcmp(part, "description"))
2743 else if(!strcmp(part, "usage"))
2745 else if(!strcmp(part, "remarks"))
2747 else if(!strcmp(part, "example"))
2749 else if(!strcmp(part, "seeAlso"))
2751 else if(!strcmp(part, "enumerationValue"))
2752 item = enumerationValue;
2753 else if(!strcmp(part, "definition"))
2755 else if(!strcmp(part, "conversion"))
2757 else if(!strcmp(part, "memberDescription"))
2758 item = memberDescription;
2759 else if(!strcmp(part, "propertyDescription"))
2760 item = propertyDescription;
2761 else if(!strcmp(part, "parameter"))
2763 else if(!strcmp(part, "returnValue"))
2766 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2768 /* Why invalidate this entry here?
2770 MapIterator<const String, DocCacheEntry> it { map = docCache };
2771 if(it.Index(docPath, false))
2780 case classDoc: cl = (Class)object; break;
2781 case functionDoc: function = object; break;
2782 case methodDoc: method = object; cl = method._class; break;
2787 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2789 clDoc = (ClassDoc)doc;
2791 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2793 nsDoc = (NamespaceDoc)doc;
2799 if(type == functionDoc)
2801 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2802 if(name) name += 2; else name = function.name;
2803 fnDoc = nsDoc.functions ? nsDoc.functions[name] : null;
2804 if(!empty && !fnDoc)
2806 if(!nsDoc.functions) nsDoc.functions = { };
2807 nsDoc.functions[name] = fnDoc = { };
2810 else if(type == methodDoc)
2812 mdDoc = clDoc.methods ? clDoc.methods[method.name] : null;
2813 if(!empty && !mdDoc)
2815 if(!clDoc.methods && !empty) clDoc.methods = { };
2816 clDoc.methods[method.name] = mdDoc = { };
2820 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2825 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2826 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2827 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2828 else { nsDoc.description = contents; contents = null; }
2831 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2832 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2833 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2836 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2837 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2838 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2841 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2842 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2843 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2846 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2847 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2848 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2851 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2852 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2854 case enumerationValue:
2856 ValueDoc itDoc = clDoc.values ? clDoc.values[((NamedLink)data).name] : null;
2859 if(!empty && !itDoc)
2861 if(!clDoc.values) clDoc.values = { };
2862 clDoc.values[((NamedLink)data).name] = itDoc = { };
2864 itDoc.description = contents; contents = null;
2867 MapIterator<String, ValueDoc> it { map = clDoc.values };
2868 if(it.Index(((NamedLink)data).name, false))
2877 DefineDoc itDoc = nsDoc.defines ? nsDoc.defines[((Definition)data).name] : null;
2880 if(!empty && !itDoc)
2882 if(!nsDoc.defines) nsDoc.defines = { };
2883 nsDoc.defines[((Definition)data).name] = itDoc = { };
2885 itDoc.description = contents; contents = null;
2888 MapIterator<String, DefineDoc> it { map = nsDoc.defines };
2889 if(it.Index(((Definition)data).name, false))
2898 ConversionDoc itDoc;
2899 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2900 if(name) name += 2; else name = ((Property)data).name;
2901 itDoc = clDoc.conversions ? clDoc.conversions[name] : null;
2904 if(!empty && !itDoc)
2906 if(!clDoc.conversions) clDoc.conversions = { };
2907 clDoc.conversions[name] = itDoc = { };
2909 itDoc.description = contents; contents = null;
2912 MapIterator<String, ConversionDoc> it { map = clDoc.conversions };
2913 if(it.Index(name, false))
2920 case memberDescription:
2922 FieldDoc itDoc = clDoc.fields ? clDoc.fields[((DataMember)data).name] : null;
2925 if(!empty && !itDoc)
2927 if(!clDoc.fields) clDoc.fields = { };
2928 clDoc.fields[((DataMember)data).name] = itDoc = { };
2930 itDoc.description = contents; contents = null;
2933 MapIterator<String, FieldDoc> it { map = clDoc.fields };
2934 if(it.Index(((DataMember)data).name, false))
2941 case propertyDescription:
2943 PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null;
2946 if(!empty && !itDoc)
2948 if(!clDoc.properties) clDoc.properties = { };
2949 clDoc.properties[((Property)data).name] = itDoc = { };
2951 itDoc.description = contents, contents = null;
2954 MapIterator<String, PropertyDoc> it { map = clDoc.properties };
2955 if(it.Index(((Property)data).name, false))
2964 if(type == functionDoc || type == methodDoc)
2966 Map<String, ParameterDoc> * parameters = (type == functionDoc) ? &fnDoc.parameters : &mdDoc.parameters;
2967 char * name = ((Type)data).name;
2968 ParameterDoc itDoc = *parameters ? (*parameters)[name] : null;
2971 while(prev) position++, prev = prev.prev;
2975 if(!empty && !itDoc)
2977 if(!*parameters) *parameters = { };
2978 (*parameters)[name] = itDoc = { };
2980 itDoc.description = contents; contents = null;
2981 itDoc.position = position;
2984 MapIterator<String, ParameterDoc> it { map = *parameters };
2985 if(it.Index(((Type)data).name, false))
2997 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
2999 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
3000 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
3001 if(name) name += 2; else name = function.name;
3002 if(it.Index(name, false))
3006 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
3008 MapIterator<String, MethodDoc> it { map = clDoc.methods };
3009 if(it.Index(method.name, false))
3015 if(nsDoc.functions && !nsDoc.functions.count) delete nsDoc.functions;
3016 if(nsDoc.defines && !nsDoc.defines.count) delete nsDoc.defines;
3020 if(clDoc && clDoc.conversions && !clDoc.conversions.count) delete clDoc.conversions;
3021 if(clDoc && clDoc.properties && !clDoc.properties.count) delete clDoc.properties;
3022 if(clDoc && clDoc.fields && !clDoc.fields.count) delete clDoc.fields;
3023 if(clDoc && clDoc.methods && !clDoc.methods.count) delete clDoc.methods;
3024 if(clDoc && clDoc.values && !clDoc.values.count) delete clDoc.values;
3029 char dirPath[MAX_LOCATION];
3030 StripLastDirectory(docPath, dirPath);
3031 if(FileExists(docPath))
3032 DeleteFile(docPath);
3033 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
3036 if(!FileExists(dirPath))
3038 if((f = FileOpen(docPath, write)))
3040 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3044 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3053 Block parent = textBlock.parent;
3054 while((block = parent.subBlocks.first))
3056 parent.subBlocks.Remove(block);
3059 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3060 textBlock.text = CopyString($"[Add Text]");
3061 textBlock.textLen = strlen(textBlock.text);
3062 parent.subBlocks.Add(textBlock);
3070 PositionCaret(true);
3075 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3079 if(edit && (!textBlock || overLink != textBlock.parent))
3083 HTMLView::OnLeftButtonDown(x, y, mods);
3084 selPosition = curPosition = 0;
3085 selBlock = textBlock;
3089 result = HTMLView::OnLeftButtonDown(x, y, mods);
3091 if(!edit && clickedLink)
3094 if(clickedLink == overLink && clickedLink.href)
3096 if(OnOpen(clickedLink.href))
3104 if(textBlock && overLink == textBlock.parent)
3106 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3107 selBlock = textBlock;
3108 PositionCaret(true);
3116 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3118 if(!edit || !textBlock || clickedLink != textBlock.parent)
3120 HTMLView::OnLeftButtonUp(x, y, mods);
3123 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3124 selBlock = textBlock;
3125 PositionCaret(true);
3136 bool OnMouseMove(int x, int y, Modifiers mods)
3138 if(edit && selecting)
3140 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3141 PositionCaret(true);
3144 return HTMLView::OnMouseMove(x, y, mods);
3147 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3149 if(edit && textBlock)
3155 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3156 selBlock = textBlock;
3157 for(c = curPosition; c >= 0; c--)
3160 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3161 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3162 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3168 for(c = start; c < textBlock.textLen; c += numBytes)
3170 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3171 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3174 selPosition = start;
3177 PositionCaret(true);
3185 bool OnOpen(char * href)
3187 if(!strncmp(href, "api://", 6))
3189 int64 tag = (int64)strtoull(href + 6, null, 16);
3190 DataRow row = mainForm.browser.FindSubRow(tag);
3194 mainForm.browser.SelectRow(row);
3195 while((row = row.parent))
3196 row.collapsed = false;
3197 row = mainForm.browser.currentRow;
3198 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3201 else if(!strncmp(href, "edit://", 7))
3204 int startX = clickedLink.startX, startY = clickedLink.startY;
3205 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3207 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3208 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3210 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3212 display.FontExtent(block.font.font, " ", 1, null, &th);
3215 block.parent.subBlocks.Insert(null, newBlock);
3220 block.parent.subBlocks.Insert(block, newBlock);
3221 startY += block.prev.height;
3223 newBlock.startX = startX;
3224 newBlock.startY = startY;
3225 newBlock.text = new0 char[1];
3229 textBlock = (Block)clickedLink.subBlocks.first;
3230 if(!strcmp(textBlock.text, $"[Add Text]"))
3232 textBlock.text[0] = 0;
3233 textBlock.textLen = 0;
3236 strcpy(editString, href + 7);
3237 selPosition = curPosition = 0;
3238 selBlock = textBlock;
3241 // PositionCaret(true);
3248 void DeleteSelection()
3250 if(textBlock != selBlock || curPosition != selPosition)
3252 if(textBlock == selBlock)
3254 // Within same block
3255 int start = Min(curPosition, selPosition);
3256 int end = Max(curPosition, selPosition);
3257 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3258 textBlock.textLen -= end-start;
3259 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3260 curPosition = start;
3261 selPosition = start;
3265 int startSel, endSel;
3266 Block startSelBlock = null, endSelBlock = null, b, next;
3268 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3270 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3271 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3273 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3274 for(b = startSelBlock.next; b; b = next)
3276 bool isEnd = b == endSelBlock;
3277 next = GetNextBlock(b);
3278 b.parent.subBlocks.Remove(b);
3283 textBlock = startSelBlock;
3284 selBlock = startSelBlock;
3285 curPosition = startSel;
3286 selPosition = startSel;
3290 PositionCaret(true);
3295 String GetSelectionString()
3297 String selection = null;
3298 if(textBlock == selBlock)
3300 // Within same block
3301 int start = Min(curPosition, selPosition);
3302 int end = Max(curPosition, selPosition);
3303 int len = end - start;
3304 selection = new char[len + 1];
3305 memcpy(selection, textBlock.text + start, len);
3310 int startSel, endSel;
3311 Block startSelBlock = null, endSelBlock = null, b;
3314 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3317 for(b = startSelBlock; b; b = GetNextBlock(b))
3319 int start = (b == startSelBlock) ? startSel : 0;
3320 int end = (b == endSelBlock) ? endSel : b.textLen;
3321 int len = end - start;
3323 if(b == endSelBlock)
3325 else if(b.type == TEXT)
3329 selection = new char[totalLen + 1];
3331 for(b = startSelBlock; b; b = GetNextBlock(b))
3333 int start = (b == startSelBlock) ? startSel : 0;
3334 int end = (b == endSelBlock) ? endSel : b.textLen;
3335 int len = end - start;
3336 memcpy(selection + totalLen, b.text + start, len);
3338 if(b == endSelBlock)
3340 else if(b.type == TEXT)
3341 selection[totalLen++] = '\n';
3343 selection[totalLen] = 0;
3348 void CopySelection()
3350 String s = GetSelectionString();
3353 int len = strlen(s);
3355 if(cb.Allocate(len + 1))
3357 memcpy(cb.text, s, len + 1);
3365 bool OnKeyDown(Key key, unichar ch)
3372 OnLeftButtonDown(0,0,0);
3374 case Key { end, shift = true }:
3376 curPosition = textBlock.textLen;
3379 selPosition = curPosition;
3380 selBlock = textBlock;
3382 PositionCaret(true);
3385 case Key { home, shift = true }:
3390 selPosition = curPosition;
3391 selBlock = textBlock;
3393 PositionCaret(true);
3396 case Key { home, ctrl = true, shift = true }:
3399 while(textBlock.prev)
3400 textBlock = textBlock.prev.prev;
3403 selPosition = curPosition;
3404 selBlock = textBlock;
3406 PositionCaret(true);
3409 case Key { end, ctrl = true, shift = true }:
3411 while(textBlock.next && textBlock.next.next)
3412 textBlock = textBlock.next.next;
3413 curPosition = textBlock.textLen;
3416 selPosition = curPosition;
3417 selBlock = textBlock;
3419 PositionCaret(true);
3425 return HTMLView::OnKeyDown(key, ch);
3429 bool OnKeyHit(Key key, unichar ch)
3435 case Key { up, shift = true }:
3438 if(caretY == textBlock.startY)
3442 textBlock = textBlock.prev.prev;
3443 curPosition = Min(curPosition, textBlock.textLen);
3446 selPosition = curPosition;
3447 selBlock = textBlock;
3450 PositionCaret(false);
3460 int sx = textBlock.startX, sy = textBlock.startY;
3461 char * text = textBlock.text;
3463 Block block = textBlock;
3464 while(block && block.type != TD) block = block.parent;
3467 Block table = block;
3468 while(table && table.type != TABLE) table = table.parent;
3470 maxW = block.w - 2* table.cellPadding;
3472 maxW = clientSize.w - 10 - sx;
3475 maxW = clientSize.w - 10 - sx;
3476 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3480 int startPos = textPos;
3483 bool lineComplete = false;
3484 for(; textPos<textBlock.textLen && !lineComplete;)
3488 char * nextSpace = strchr(text + textPos, ' ');
3491 len = (nextSpace - (text + textPos)) + 1;
3493 len = textBlock.textLen - textPos;
3495 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3497 if(x + width + w > maxW && x > 0)
3499 lineComplete = true;
3509 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3512 curPosition = textPos;
3513 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3516 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3517 len = curPosition - startPos;
3518 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3522 selPosition = curPosition;
3523 selBlock = textBlock;
3527 PositionCaret(false);
3531 if(sy == caretY - th || textPos == textBlock.textLen)
3533 if(textPos != textBlock.textLen)
3535 int c = textPos - 1;
3536 while(c > 0 && text[c] == ' ') c--;
3537 curPosition = c + 1;
3540 selPosition = curPosition;
3541 selBlock = textBlock;
3547 curPosition = textBlock.textLen;
3550 selPosition = curPosition;
3551 selBlock = textBlock;
3555 PositionCaret(false);
3559 sx = textBlock.startX;
3560 } while(textPos < textBlock.textLen);
3565 case Key { down, shift = true }:
3570 int sx = textBlock.startX, sy = textBlock.startY;
3571 char * text = textBlock.text;
3573 Block block = textBlock;
3574 while(block && block.type != TD) block = block.parent;
3577 Block table = block;
3578 while(table && table.type != TABLE) table = table.parent;
3580 maxW = block.w - 2* table.cellPadding;
3582 maxW = clientSize.w - 10 - sx;
3585 maxW = clientSize.w - 10 - sx;
3586 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3588 while(!textPos || textPos < textBlock.textLen)
3590 int startPos = textPos;
3593 bool lineComplete = false;
3594 for(; (textPos < textBlock.textLen) && !lineComplete;)
3598 char * nextSpace = strchr(text + textPos, ' ');
3601 len = (nextSpace - (text + textPos)) + 1;
3603 len = textBlock.textLen - textPos;
3605 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3607 if(x + width + w > maxW && x > 0)
3609 lineComplete = true;
3619 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3621 curPosition = textPos;
3623 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3626 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3627 len = curPosition - startPos;
3628 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3632 selPosition = curPosition;
3633 selBlock = textBlock;
3636 PositionCaret(false);
3642 curPosition = textBlock.textLen;
3645 selPosition = curPosition;
3646 selBlock = textBlock;
3649 PositionCaret(false);
3652 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3656 textBlock = textBlock.next.next;
3657 sy = textBlock.startY;
3658 sx = textBlock.startX;
3659 text = textBlock.text;
3664 sx = textBlock.startX;
3668 /*if(textBlock.next && textBlock.next.next)
3670 textBlock = textBlock.next.next;
3671 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3672 selBlock = textBlock;
3673 PositionCaret(false);
3677 case Key { right, shift = true, ctrl = true }:
3680 bool foundAlpha = false;
3682 Block line, lastLine;
3685 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3687 int start = (line == textBlock) ? curPosition : 0;
3689 for(c = start; c < line.textLen; c++)
3691 char ch = line.text[c];
3692 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3693 if(key.shift ? isAlUnder : !isAlUnder)
3707 selPosition = curPosition;
3708 selBlock = textBlock;
3712 PositionCaret(true);
3717 // No next word found,
3718 if(!found && (c != curPosition || line != textBlock))
3722 lastC = line.textLen-1;
3727 curPosition = line.textLen;
3730 selPosition = curPosition;
3731 selBlock = textBlock;
3736 PositionCaret(true);
3742 if(key.shift && found)
3744 curPosition = lastC+1;
3745 textBlock = lastLine;
3746 PositionCaret(true);
3751 case Key { left, ctrl = true, shift = true }:
3754 bool foundAlpha = false;
3756 Block line, lastLine;
3759 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3762 if(curPosition == 0 && line != textBlock)
3765 lastC = line.textLen;
3769 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3770 for(c = start; c>=0; c--)
3772 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3787 // No next word found,
3788 if(!found && curPosition > 0)
3798 textBlock = lastLine;
3799 curPosition = lastC;
3802 selPosition = curPosition;
3803 selBlock = textBlock;
3805 PositionCaret(true);
3810 case Key { right, shift = true }:
3812 if(curPosition < textBlock.textLen)
3814 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3817 selPosition = curPosition;
3818 selBlock = textBlock;
3820 PositionCaret(true);
3823 else if(textBlock.next && textBlock.next.next)
3825 textBlock = textBlock.next.next;
3829 selPosition = curPosition;
3830 selBlock = textBlock;
3832 PositionCaret(true);
3836 case Key { left, shift = true }:
3840 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3843 selPosition = curPosition;
3844 selBlock = textBlock;
3846 PositionCaret(true);
3849 else if(textBlock.prev)
3851 textBlock = textBlock.prev.prev;
3852 curPosition = textBlock.textLen;
3855 selPosition = curPosition;
3856 selBlock = textBlock;
3858 PositionCaret(true);
3864 if(textBlock == selBlock && curPosition == selPosition)
3868 int c = curPosition;
3870 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3871 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3872 textBlock.textLen -= nb;
3873 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3875 selPosition = curPosition;
3876 selBlock = textBlock;
3880 PositionCaret(true);
3883 else if(textBlock.prev)
3885 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3886 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3887 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3889 selPosition = curPosition = prevBlock.textLen;
3890 selBlock = textBlock;
3891 prevBlock.textLen += textBlock.textLen;
3892 textBlock.parent.subBlocks.Remove(prev);
3893 if(prev == selBlock)
3895 selBlock = textBlock;
3896 selPosition = curPosition;
3899 textBlock.parent.subBlocks.Remove(textBlock);
3900 if(textBlock == selBlock)
3902 selBlock = prevBlock;
3903 selPosition = curPosition;
3906 textBlock = prevBlock;
3910 PositionCaret(true);
3919 if(textBlock != selBlock || curPosition != selPosition)
3921 else if(textBlock.textLen > curPosition)
3923 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3924 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3925 textBlock.textLen -= nb;
3926 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3931 PositionCaret(true);
3934 else if(textBlock.next && textBlock.next.next)
3936 Block next = textBlock.next, nextBlock = textBlock.next.next;
3937 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3938 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3940 textBlock.textLen += nextBlock.textLen;
3941 textBlock.parent.subBlocks.Remove(next);
3942 if(next == selBlock)
3944 selBlock = textBlock;
3945 selPosition = curPosition;
3948 textBlock.parent.subBlocks.Remove(nextBlock);
3949 if(nextBlock == selBlock)
3951 selBlock = textBlock;
3952 selPosition = curPosition;
3958 PositionCaret(true);
3972 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3973 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3974 startY = textBlock.startY;
3975 startX = textBlock.startX;
3977 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3978 textBlock.parent.subBlocks.Insert(textBlock, block);
3979 textBlock.parent.subBlocks.Insert(block, newBlock);
3983 newBlock.textLen = textBlock.textLen - curPosition;
3984 newBlock.text = new char[newBlock.textLen+1];
3985 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3986 textBlock.textLen = curPosition;
3987 textBlock.text[curPosition] = 0;
3989 newBlock.startY = startY;
3990 newBlock.startX = startX;
3991 selPosition = curPosition = 0;
3996 textBlock = newBlock;
3997 selBlock = textBlock;
3998 PositionCaret(true);
4003 case Key { del, shift = true }:
4018 ClipBoard clipBoard { };
4019 if(clipBoard.Load())
4022 char * text = clipBoard.memory;
4030 parent = textBlock.parent;
4031 font = textBlock.font;
4036 if(ch == '\n' || ch == '\r' || !ch)
4038 int len = c - start;
4039 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4040 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4041 memcpy(textBlock.text + curPosition, text + start, len);
4042 textBlock.textLen += len;
4044 selPosition = curPosition;
4045 selBlock = textBlock;
4048 Block block { type = BR, parent = parent, font = font };
4049 Block newBlock { type = TEXT, parent = parent, font = font };
4050 int startY = textBlock.startY, startX = textBlock.startX;
4053 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4054 textBlock.parent.subBlocks.Insert(textBlock, block);
4055 textBlock.parent.subBlocks.Insert(block, newBlock);
4059 newBlock.textLen = textBlock.textLen - curPosition;
4060 newBlock.text = new char[newBlock.textLen+1];
4061 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4062 textBlock.textLen = curPosition;
4063 textBlock.text[curPosition] = 0;
4065 newBlock.startY = startY;
4066 newBlock.startX = startX;
4067 selPosition = curPosition = 0;
4068 selBlock = textBlock;
4069 textBlock = newBlock;
4071 if(ch == '\r' && text[c+1] == '\n') c++;
4077 PositionCaret(true);
4085 // eC BUG HERE: (Should be fixed)
4086 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4089 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4094 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4095 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4097 for(c = 0; c<len; c++)
4099 textBlock.text[curPosition] = string[c];
4100 textBlock.textLen++;
4103 selPosition = curPosition;
4104 selBlock = textBlock;
4107 //Clear(html.block);
4108 //CreateForms(html.block);
4113 PositionCaret(true);
4122 void OnResize(int width, int height)
4124 HTMLView::OnResize(width, height);
4125 PositionCaret(true);
4129 void PositionCaret(bool setCaretX)
4135 int sx = textBlock.startX, sy = textBlock.startY;
4136 char * text = textBlock.text;
4138 Block block = textBlock;
4139 while(block && block.type != TD) block = block.parent;
4142 Block table = block;
4143 while(table && table.type != TABLE) table = table.parent;
4145 maxW = block.w - 2* table.cellPadding;
4147 maxW = clientSize.w - 10 - sx;
4150 maxW = clientSize.w - 10 - sx;
4152 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4154 while(textPos < textBlock.textLen)
4156 int startPos = textPos;
4159 bool lineComplete = false;
4161 for(; textPos<textBlock.textLen && !lineComplete;)
4165 char * nextSpace = strchr(text + textPos, ' ');
4168 len = (nextSpace - (text + textPos)) + 1;
4170 len = textBlock.textLen - textPos;
4172 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4174 if(x + width + w > maxW && x > 0)
4176 lineComplete = true;
4189 if(curPosition < textPos || textPos == textBlock.textLen)
4191 int len = curPosition - startPos;
4192 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4197 sx = textBlock.startX;
4202 SetCaret(sx, sy, th);
4204 Point scrollPos = scroll;
4205 bool doScroll = false;
4206 if(sy - scroll.y + th > clientSize.h)
4208 scrollPos.y = sy + th - clientSize.h;
4211 else if(sy - scroll.y < 0)
4216 if(sx - scroll.x + 10 > clientSize.w)
4218 scrollPos.x = sx + 10 - clientSize.w;
4221 else if(sx - scroll.x < 10)
4223 scrollPos.x = sx - 10;
4234 // Returns a character offset into the TextBlock from a window coordinate
4235 int TextPosFromPoint(int px, int py, Block * block, bool half)
4237 Block parentBlock = this.textBlock.parent;
4240 *block = this.textBlock;
4245 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4247 int sx = textBlock.startX, sy = textBlock.startY;
4250 char * text = textBlock.text;
4252 Block b = textBlock;
4255 if(textBlock.type != TEXT) continue;
4257 while(b && b.type != TD) b = b.parent;
4261 while(table && table.type != TABLE) table = table.parent;
4263 maxW = b.w - 2* table.cellPadding;
4265 maxW = clientSize.w - 10 - sx;
4268 maxW = clientSize.w - 10 - sx;
4270 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4271 //space = space/2+2;
4274 while(textPos < textBlock.textLen)
4278 bool lineComplete = false;
4280 for(; textPos<textBlock.textLen && !lineComplete;)
4284 char * nextSpace = strchr(text + textPos, ' ');
4287 len = (nextSpace - (text + textPos)) + 1;
4289 len = textBlock.textLen - textPos;
4291 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4293 sx = x + textBlock.startX;
4294 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4299 for(c = textPos; (ch = text[c]); c += numBytes)
4301 numBytes = UTF8_NUM_BYTES(ch);
4302 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4303 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4310 if(x + width + w > maxW && x > 0)
4312 lineComplete = true;
4325 if(/*py >= sy && */py < sy + th)
4328 return textBlock.textLen;
4333 result = textBlock.textLen;
4339 Application componentsApp;
4341 class Documentor : GuiApplication
4345 Platform os = __runtimePlatform;
4346 SetGlobalContext(globalContext);
4347 SetExcludedSymbols(&excludedSymbols);
4348 SetDefines(&::defines);
4349 SetImports(&imports);
4350 SetInDocumentor(true);
4352 SetGlobalData(globalData);
4354 settingsContainer.dataOwner = &ideSettings;
4355 settingsContainer.Load();
4356 if(!ideSettings.docDir || !ideSettings.docDir[0] )
4358 if(os == win32) // if Windows OS then
4360 char programFilesDir[MAX_LOCATION];
4361 char appData[MAX_LOCATION];
4362 char homeDrive[MAX_LOCATION];
4363 char winDir[MAX_LOCATION];
4364 GetEnvironment("APPDATA", appData, sizeof(appData));
4365 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4366 GetEnvironment("windir", winDir, sizeof(winDir));
4367 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4369 PathCat(programFilesDir, "ECERE SDK\\doc");
4370 ideSettings.docDir = programFilesDir;
4372 else if(homeDrive[0])
4374 PathCat(homeDrive, "ECERE SDK\\doc");
4375 ideSettings.docDir = homeDrive;
4379 PathCat(winDir, "..\\ECERE SDK\\doc");
4380 ideSettings.docDir = winDir;
4383 ideSettings.docDir = "C:\\ECERE SDK\\doc";
4385 else // if Os is Linux, or Mac OSX or something else
4386 ideSettings.docDir = "/usr/share/ecere/doc/";
4387 settingsContainer.Save();
4393 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4395 AddComponents(module, true);
4396 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4397 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4398 while((row = row.parent))
4399 row.collapsed = false;
4403 commandThread.Create();
4407 bool Cycle(bool idle)
4410 mainForm.Destroy(0);
4419 if(commandThread.created)
4421 console.CloseInput();
4422 console.CloseOutput();
4424 commandThread.Wait();
4428 FreeContext(globalContext);
4429 FreeExcludedSymbols(excludedSymbols);
4430 ::defines.Free(FreeModuleDefine);
4431 imports.Free(FreeModuleImport);
4433 FreeGlobalData(globalData);
4434 FreeTypeData(componentsApp);
4436 delete componentsApp;
4440 ConsoleFile console { };
4441 MainForm mainForm { };
4444 Thread commandThread
4451 console.GetLine(command, sizeof(command));
4452 if(!quit && command[0])
4455 if(!strcmpi(command, "Activate"))
4456 mainForm.Activate();
4457 else if(!strcmpi(command, "Quit"))
4465 #endif // !defined(EAR_TO_ECON_ECDOC)
4470 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4471 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4475 property bool isEmpty
4481 (description && *description));
4491 class MoreDoc : ItemDoc
4494 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4495 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4496 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4497 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4503 property bool isEmpty
4508 (usage && *usage) ||
4509 (example && *example) ||
4510 (remarks && *remarks) ||
4524 class NamespaceDoc : ItemDoc
4527 Map<String, DefineDoc> defines;
4528 Map<String, FunctionDoc> functions;
4530 property bool isEmpty
4535 (defines && defines.count) ||
4536 (functions && functions.count) ||
4547 class DefineDoc : ItemDoc { }
4549 class FunctionDoc : MoreDoc
4552 Map<String, ParameterDoc> parameters;
4553 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4556 property bool isEmpty
4561 (parameters && parameters.count) ||
4562 (returnValue && *returnValue) ||
4573 class ParameterDoc : ItemDoc
4579 class ClassDoc : MoreDoc
4582 Map<String, ValueDoc> values;
4583 Map<String, FieldDoc> fields;
4584 Map<String, PropertyDoc> properties;
4585 Map<String, ConversionDoc> conversions;
4586 Map<String, MethodDoc> methods;
4588 property bool isEmpty
4593 (values && values.count) ||
4594 (fields && fields.count) ||
4595 (properties && properties.count) ||
4596 (conversions && conversions.count) ||
4597 (methods && methods.count) ||
4611 class ValueDoc : ItemDoc { }
4613 class FieldDoc : ItemDoc { }
4615 class PropertyDoc : ItemDoc { }
4617 class ConversionDoc : ItemDoc { }
4619 class MethodDoc : FunctionDoc { }
4621 char * getDocFileNameFromTypeName(const char * typeName)
4623 char * docFileName = new char[MAX_FILENAME];
4624 const char * swap = "pointer";
4625 const char * s = typeName;
4626 char * d = docFileName;
4627 const char * end = s + strlen(typeName);
4628 int swapLen = strlen(swap);
4646 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4649 Time timeStamp; // Should this be last accessed, or last retrieved?
4658 Map<String, DocCacheEntry> docCache { };