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><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);
840 f.Printf("</a><br><br>");
843 f.Printf("%s<br><br>", desc);
848 if(nameSpace->nameSpaces.first)
851 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
853 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
856 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
857 f.Printf("<TABLE>\n");
861 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);
866 char fileName[MAX_LOCATION];
867 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
868 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
870 f.Printf("</a></TD>");
873 f.Printf("<TD valign=top height=22> %s</TD>", desc);
876 f.Printf("</TR><br>\n");
879 f.Printf("</TABLE><br>\n");
882 if(nameSpace->classes.first)
885 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
887 Class cl = link.data;
888 if(!cl.templateClass)
890 char * desc = ReadDoc(module, classDoc, cl, description, null);
894 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
895 f.Printf("<TABLE>\n");
901 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);
906 char fileName[MAX_LOCATION];
907 FigureFileName(fileName, module, classDoc, cl, description, null);
908 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
910 f.Printf("</a></TD>");
913 f.Printf("<TD valign=top height=22>%s</TD>", desc);
920 f.Printf("</TABLE><br>\n");
923 if(nameSpace->functions.first)
926 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
928 GlobalFunction function = link.data;
929 char * desc = ReadDoc(module, functionDoc, function, description, null);
930 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
931 if(name) name += 2; else name = function.name;
934 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
935 f.Printf("<TABLE>\n");
939 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);
944 char fileName[MAX_LOCATION];
945 FigureFileName(fileName, module, functionDoc, function, description, null);
946 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
948 f.Printf("</a></TD>");
951 f.Printf("<TD valign=top height=22> %s</TD>", desc);
954 f.Printf("</TR><br>\n");
957 f.Printf("</TABLE><br>\n");
960 if(nameSpace->defines.first)
963 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
965 DefinedExpression def = link.data;
966 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
969 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
970 f.Printf("<TABLE>\n");
974 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);
975 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
980 char fileName[MAX_LOCATION];
981 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
982 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
984 f.Printf("</a></TD>");
987 f.Printf("<TD valign=top height=22> %s</TD>", desc);
990 f.Printf("</TR><br>\n");
993 f.Printf("</TABLE><br>\n");
996 f.Printf("</FONT></BODY></HTML>\n");
1000 class APIPageClass : APIPage
1009 NameSpace * GetNameSpace()
1011 return cl.nameSpace;
1014 void Generate(File f)
1019 char nsName[1024], temp[1024];
1020 NameSpace * ns = cl.nameSpace;
1021 Module module = cl.module;
1024 while(ns && ns->name)
1026 strcpy(temp, ns->name);
1027 if(nsName[0]) strcat(temp, "::");
1028 strcat(temp, nsName);
1029 strcpy(nsName, temp);
1032 // Generate Class Page
1033 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1034 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1036 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);
1038 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1041 const char * classType = null;
1045 classType = $"Bit Collection";
1048 classType = $"Enumeration";
1051 classType = $"Structure";
1054 classType = $"Class";
1057 classType = $"Class (No header)";
1060 classType = $"Unit";
1063 classType = $"Basic Data Type";
1066 f.Printf($"Type: %s<br>\n", classType);
1069 if(cl.type != systemClass && cl.base)
1071 f.Printf($"Base Class: ");
1072 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1074 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1076 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1077 f.Printf("%s", cl.dataTypeString);
1079 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1084 char * desc = ReadDoc(module, classDoc, cl, description, null);
1087 f.Printf($"<br><H3>Description</H3><br><br>\n");
1090 char fileName[MAX_LOCATION];
1091 FigureFileName(fileName, module, classDoc, cl, description, null);
1092 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1094 f.Printf("</a><br><br>");
1097 f.Printf("%s<br><br>", desc);
1102 if(cl.type == enumClass)
1104 EnumClassData enumeration = (EnumClassData)cl.data;
1105 if(enumeration.values.first)
1109 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
1110 f.Printf("<TABLE>\n");
1112 for(item = enumeration.values.first; item; item = item.next)
1114 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1115 bool needClass = true;
1118 char tempString[1024];
1120 while(base.type == enumClass) base = base.base;
1122 if(base.type == systemClass ||
1123 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1126 base.dataType = ProcessTypeString(base.dataTypeString, false);
1128 if(base.dataType.kind != classType)
1133 PrintType(base.dataType, string, false, true);
1134 classSym = FindClass(string);
1135 dataClass = classSym ? classSym.registered : null;
1138 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1144 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);
1145 if(dataClass.type == systemClass)
1148 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1151 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1153 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1155 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1160 char fileName[MAX_LOCATION];
1161 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1162 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1164 f.Printf("</a></TD>");
1167 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1172 f.Printf("</TABLE><BR>\n");
1176 if(cl.conversions.first)
1178 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
1179 f.Printf("<TABLE>\n");
1180 for(prop = cl.conversions.first; prop; prop = prop.next)
1182 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1184 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1186 Type type = ProcessTypeString(prop.name, false);
1187 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1188 if(name) name += 2; else name = prop.name;
1193 DocPrintType(type, string, true, false);
1195 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1200 char fileName[MAX_LOCATION];
1201 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1202 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1204 f.Printf("</a></TD>");
1207 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1211 f.Printf("</TR>\n");
1216 f.Printf("</TABLE><br>\n");
1219 if(cl.membersAndProperties.first)
1222 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1224 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1228 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1229 f.Printf("<TABLE>\n");
1235 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1237 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1241 DocPrintType(prop.dataType, string, true, false);
1243 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);
1244 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1249 char fileName[MAX_LOCATION];
1250 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1251 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1253 f.Printf("</a></TD>");
1256 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1259 f.Printf("</TR>\n");
1263 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1268 f.Printf("</TABLE><br>\n");
1271 if(cl.methods.first)
1275 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1277 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1279 char * desc = ReadDoc(module, methodDoc, method, description, null);
1282 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1283 f.Printf("<TABLE>\n");
1286 if(!method.dataType)
1287 ProcessMethodType(method);
1290 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);
1295 char fileName[MAX_LOCATION];
1296 FigureFileName(fileName, module, methodDoc, method, description, null);
1297 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1299 f.Printf("</a></TD>");
1302 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1305 f.Printf("</TR><br>\n");
1309 f.Printf("</TABLE><br>\n");
1311 // Non-Virtual Methods
1313 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1315 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1317 char * desc = ReadDoc(module, methodDoc, method, description, null);
1320 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1321 f.Printf("<TABLE>\n");
1325 if(!method.dataType)
1326 ProcessMethodType(method);
1329 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);
1334 char fileName[MAX_LOCATION];
1335 FigureFileName(fileName, module, methodDoc, method, description, null);
1336 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1338 f.Printf("</a></TD>");
1341 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1345 f.Printf("</TR><br>\n");
1349 f.Printf("</TABLE><br>\n");
1352 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1355 f.Printf($"<H3>Usage</H3><br>\n");
1358 char fileName[MAX_LOCATION];
1359 FigureFileName(fileName, module, classDoc, cl, usage, null);
1360 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1365 f.Printf("<br>%s\n", usageDoc);
1366 f.Printf("<br><br>\n");
1371 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1374 f.Printf($"<H3>Example</H3><br>\n");
1375 f.Printf($"<FONT face=\"Courier New\">\n");
1376 f.Printf("<br><TABLE>\n");
1379 char fileName[MAX_LOCATION];
1380 FigureFileName(fileName, module, classDoc, cl, example, null);
1381 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1383 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1386 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1388 f.Printf("</TABLE></FONT>\n");
1394 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1398 f.Printf($"<H3>Remarks</H3><br>\n");
1401 char fileName[MAX_LOCATION];
1402 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1403 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1408 f.Printf("<br>%s\n", remarksDoc);
1409 f.Printf("<br><br>\n");
1414 if(cl.type != systemClass)
1418 for(c = cl.derivatives.first; c; c = c.next)
1420 Class deriv = c.data;
1421 // TO VERIFY: Does this properly check public status?
1422 if(eSystem_FindClass(componentsApp, deriv.fullName))
1426 f.Printf($"<H3>Derived Classes</H3><br>\n");
1432 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1436 f.Printf("<br><br>\n");
1439 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1442 f.Printf($"<H3>See Also</H3><br>\n");
1445 char fileName[MAX_LOCATION];
1446 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1447 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1452 f.Printf("<br>%s\n", seeAlsoDoc);
1453 f.Printf("<br><br>\n");
1457 f.Printf("</FONT></BODY></HTML>\n");
1461 class APIPageMethod : APIPage
1467 return method._class.module;
1470 NameSpace * GetNameSpace()
1472 return method._class.nameSpace;
1475 void Generate(File f)
1477 Class cl = method._class;
1479 Module module = cl.module;
1481 char nsName[1024], temp[1024];
1482 NameSpace * ns = cl.nameSpace;
1485 while(ns && ns->name)
1487 strcpy(temp, ns->name);
1488 if(nsName[0]) strcat(temp, "::");
1489 strcat(temp, nsName);
1490 strcpy(nsName, temp);
1494 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1495 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1497 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);
1499 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1500 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1501 if(method.dataType.staticMethod)
1503 f.Printf($"this pointer class: None<br>\n");
1505 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1507 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);
1510 // Generate Method Page
1512 if(!method.dataType.name)
1513 method.dataType.name = CopyString(method.name);
1514 DocPrintType(method.dataType, string, true, false);
1515 f.Printf("<br>%s", string);
1518 char * desc = ReadDoc(module, methodDoc, method, description, null);
1521 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1524 char fileName[MAX_LOCATION];
1525 FigureFileName(fileName, module, methodDoc, method, description, null);
1526 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1531 f.Printf("%s", desc);
1536 f.Printf("<br><br>\n");
1537 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1539 f.Printf($"<H3>Parameters</H3><br><br>\n");
1541 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1542 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1544 f.Printf("<TABLE valign=center>\n");
1547 for(param = method.dataType.params.first; param; param = param.next)
1549 // ADD DESCRIPTION HERE
1550 if(param.kind != voidType)
1552 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1555 DocPrintType(param, string, false, false);
1557 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1558 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1563 char fileName[MAX_LOCATION];
1564 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1565 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1567 f.Printf("</a></TD>\n");
1570 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1574 f.Printf("</TR>\n");
1577 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1579 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1580 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1582 f.Printf("<TR><TD> </TD></TR>");
1585 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1587 DocPrintType(method.dataType.returnType, string, false, false);
1588 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1593 char fileName[MAX_LOCATION];
1594 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1595 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1597 f.Printf("</a> </TD>\n");
1600 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1603 f.Printf("</TR>\n");
1604 f.Printf("</TABLE>\n");
1606 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1607 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1609 f.Printf("</TABLE><br>\n");
1612 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1615 f.Printf($"<H3>Usage</H3><br>\n");
1618 char fileName[MAX_LOCATION];
1619 FigureFileName(fileName, module, methodDoc, method, usage, null);
1620 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1625 f.Printf("<br>%s\n", usageDoc);
1626 f.Printf("<br><br>\n");
1631 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1634 f.Printf($"<H3>Example</H3><br>\n");
1635 f.Printf($"<FONT face=\"Courier New\">\n");
1636 f.Printf("<br><TABLE>\n");
1639 char fileName[MAX_LOCATION];
1640 FigureFileName(fileName, module, methodDoc, method, example, null);
1641 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1643 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1646 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1647 f.Printf("</TABLE></FONT>\n");
1653 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1656 f.Printf($"<H3>Remarks</H3><br>\n");
1659 char fileName[MAX_LOCATION];
1660 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1661 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1666 f.Printf("<br>%s\n", method, remarksDoc);
1667 f.Printf("<br><br>\n");
1672 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1675 f.Printf($"<H3>See Also</H3><br>\n");
1678 char fileName[MAX_LOCATION];
1679 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1680 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1685 f.Printf("<br>%s\n", method, seeAlsoDoc);
1687 f.Printf("<br><br>\n");
1691 f.Printf("</FONT></BODY></HTML>\n");
1695 class APIPageFunction : APIPage
1697 GlobalFunction function;
1701 return function.module;
1704 NameSpace * GetNameSpace()
1706 return function.nameSpace;
1709 void Generate(File f)
1712 Module module = function.module;
1714 char nsName[1024], temp[1024];
1715 NameSpace * ns = function.nameSpace;
1718 while(ns && ns->name)
1720 strcpy(temp, ns->name);
1721 if(nsName[0]) strcat(temp, "::");
1722 strcat(temp, nsName);
1723 strcpy(nsName, temp);
1727 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1728 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1730 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);
1733 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1735 if(!function.dataType)
1736 function.dataType = ProcessTypeString(function.dataTypeString, false);
1738 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1740 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);
1743 // Generate Method Page
1745 if(!function.dataType.name)
1746 function.dataType.name = CopyString(function.name);
1747 DocPrintType(function.dataType, string, true, false);
1748 f.Printf("<br>%s", string);
1751 char * desc = ReadDoc(module, functionDoc, function, description, null);
1754 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1757 char fileName[MAX_LOCATION];
1758 FigureFileName(fileName, module, functionDoc, function, description, null);
1759 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1764 f.Printf("%s", desc);
1768 f.Printf("<br><br>\n");
1769 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1771 f.Printf($"<H3>Parameters</H3><br><br>\n");
1773 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1774 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1776 f.Printf("<TABLE valign=center>\n");
1779 for(param = function.dataType.params.first; param; param = param.next)
1781 // ADD DESCRIPTION HERE
1782 if(param.kind != voidType)
1784 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1787 DocPrintType(param, string, false, false);
1789 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1790 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1795 char fileName[MAX_LOCATION];
1796 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1797 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1800 f.Printf("</a> </TD>\n");
1803 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1806 f.Printf("</TR>\n");
1809 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1811 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1812 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1814 f.Printf("<TR><TD> </TD></TR>");
1817 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1819 DocPrintType(function.dataType.returnType, string, false, false);
1820 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1825 char fileName[MAX_LOCATION];
1826 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1827 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1829 f.Printf("</a> </TD>\n");
1832 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1835 f.Printf("</TR>\n");
1836 f.Printf("</TABLE>\n");
1838 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1839 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1841 f.Printf("</TABLE><br>\n");
1844 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1847 f.Printf($"<H3>Usage</H3><br>\n");
1850 char fileName[MAX_LOCATION];
1851 FigureFileName(fileName, module, functionDoc, function, usage, null);
1852 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1857 f.Printf("<br>%s\n", usageDoc);
1858 f.Printf("<br><br>\n");
1863 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1866 f.Printf($"<H3>Example</H3><br>\n");
1867 f.Printf($"<FONT face=\"Courier New\">\n");
1868 f.Printf("<br><TABLE>\n");
1871 char fileName[MAX_LOCATION];
1872 FigureFileName(fileName, module, functionDoc, function, example, null);
1873 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1875 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1878 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1879 f.Printf("</TABLE></FONT>\n");
1885 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1888 f.Printf($"<H3>Remarks</H3><br>\n");
1891 char fileName[MAX_LOCATION];
1892 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1893 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1898 f.Printf("<br>%s\n", remarksDoc);
1899 f.Printf("<br><br>\n");
1904 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1907 f.Printf($"<H3>See Also</H3><br>\n");
1910 char fileName[MAX_LOCATION];
1911 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1912 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1917 f.Printf("<br>%s\n", seeAlsoDoc);
1918 f.Printf("<br><br>\n");
1922 f.Printf("</FONT></BODY></HTML>\n");
1926 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1930 NameSpace * nameSpace = mainNameSpace;
1932 DataRow classesRow = null;
1933 DataRow functionsRow = null, definesRow = null;
1936 strcpy(nsName, parentName ? parentName : "");
1940 strcat(nsName, "::");
1941 strcat(nsName, nameSpace->name);
1946 row = parentRow.AddRow();
1947 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1948 row.tag = (int64)nameSpace;
1949 row.icon = mainForm.icons[typeNameSpace];
1953 // "Global NameSpace"
1955 page = parentRow.GetData(null);
1958 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1960 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1961 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1963 if(comNameSpace != null)
1965 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1967 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1969 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1974 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1976 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1978 if(nameSpace->classes.first)
1982 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1985 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1987 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1988 AddClass(classesRow, module, cl, nsName, showPrivate);
1995 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
1997 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1999 if(nameSpace->functions.first)
2003 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2006 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2008 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2010 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2011 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2018 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2020 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2022 if(nameSpace->defines.first)
2026 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2029 //if(def.module == module)
2031 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2033 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2034 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2042 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2046 if(!member.dataType)
2047 member.dataType = ProcessTypeString(member.dataTypeString, false);
2051 DocPrintType(member.dataType, string, true, false);
2053 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2054 for(c = 0; c<indent; c++)
2055 f.Printf(" ");
2056 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2057 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2058 if(member.type == normalMember)
2060 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2065 char fileName[MAX_LOCATION];
2066 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2067 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2069 f.Printf("</a></TD>");
2072 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2077 f.Printf("<TD valign=top height=22></TD>");
2079 if(member.type != normalMember)
2081 DataMember subMember;
2082 for(subMember = member.members.first; subMember; subMember = subMember.next)
2084 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2086 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2090 f.Printf("</TR><br>\n");
2093 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2096 if(member.type == normalMember)
2098 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2099 row.tag = (int64)member;
2104 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2105 row.icon = mainForm.icons[typeData];
2106 row.tag = (int64)member;
2108 for(m = member.members.first; m; m = m.next)
2110 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2111 AddDataMember(row, page, m);
2116 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2121 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2122 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2125 row = parentRow.AddRow();
2126 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2127 row.tag = (int64)cl;
2128 row.collapsed = true;
2129 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2132 if(cl.methods.first)
2134 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2136 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2139 if(!method.dataType)
2140 ProcessMethodType(method);
2141 if(method.type == virtualMethod)
2143 if(method.dataType.thisClass)
2145 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2146 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2147 mRow.tag = (int64)method;
2151 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2152 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2153 mRow.tag = (int64)method;
2158 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2159 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2160 mRow.tag = (int64)method;
2166 if(cl.membersAndProperties.first)
2168 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2170 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2173 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2177 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2178 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2179 mRow.tag = (int64)prop;
2183 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2184 AddDataMember(membersRow, page, (DataMember)prop);
2190 if(cl.conversions.first)
2192 for(prop = cl.conversions.first; prop; prop = prop.next)
2196 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2197 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2198 if(name) name += 2; else name = prop.name;
2199 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2200 mRow.tag = (int64)prop;
2203 if(cl.type == enumClass)
2205 EnumClassData enumeration = (EnumClassData)cl.data;
2207 for(item = enumeration.values.first; item; item = item.next)
2210 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2211 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2212 mRow.tag = (int64)item;
2217 class AddressBar : Window
2219 background = activeBorder;
2223 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2225 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2227 MainForm mainForm = (MainForm)parent;
2228 FileDialog fileDialog = mainForm.fileDialog;
2229 if(fileDialog.Modal() == ok)
2230 mainForm.OpenModule(fileDialog.filePath);
2236 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2239 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2241 ((MainForm)parent).Back();
2247 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2250 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2252 ((MainForm)parent).Forward();
2258 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2260 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2262 ((MainForm)parent).Home();
2266 /* TODO: Search (#143/#441)
2267 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2268 Update this in the NotifyUpdate. Enter goes to the exact match.
2270 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2274 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2276 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2278 if(!disabled && (SmartKey)key == enter)
2279 ((MainForm)parent).Go(editBox.contents);
2283 void NotifyUpdate(EditBox editBox)
2285 String location = ((MainForm)parent).view.location;
2286 disabled = !strcmp(location ? location : "", editBox.contents);
2291 bool OnKeyHit(Key key, unichar ch)
2294 ((MainForm)parent).view.MakeActive();
2299 class MainForm : Window
2301 size = { 1000, 600 };
2303 borderStyle = sizable;
2306 icon = { ":documentorIcon.png" };
2307 text = $"API Documentation Browser";
2309 BitmapResource icons[CodeObjectType];
2314 for(c = 0; c < CodeObjectType::enumSize; c++)
2316 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2318 browser.AddField(DataField { dataType = class(APIPage) });
2323 Menu fileMenu { menu, $"File", f };
2324 Array<FileFilter> fileFilters
2326 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2327 { $"eC Symbol files (*.sym)", "sym" }
2330 FileDialog fileDialog
2332 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2334 MenuItem fileOpenItem
2336 fileMenu, $"Open...", o, ctrlO;
2338 bool NotifySelect(MenuItem selection, Modifiers mods)
2340 if(fileDialog.Modal() == ok)
2342 OpenModule(fileDialog.filePath);
2347 MenuItem fileSettingsItem
2349 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2351 bool NotifySelect(MenuItem selection, Modifiers mods)
2353 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2363 MenuDivider { fileMenu };
2364 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2366 void OpenModule(const char * filePath)
2368 char moduleName[MAX_LOCATION];
2369 char extension[MAX_EXTENSION];
2370 Module module = null;
2371 static char symbolsDir[MAX_LOCATION];
2374 modulesAdded.RemoveAll();
2376 FreeContext(globalContext);
2377 FreeExcludedSymbols(excludedSymbols);
2378 ::defines.Free(FreeModuleDefine);
2379 imports.Free(FreeModuleImport);
2381 FreeGlobalData(globalData);
2385 FreeTypeData(componentsApp);
2386 delete componentsApp;
2389 componentsApp = __ecere_COM_Initialize(false, 1, null);
2390 SetPrivateModule(componentsApp);
2392 StripLastDirectory(filePath, symbolsDir);
2393 SetSymbolsDir(symbolsDir);
2395 GetExtension(filePath, extension);
2397 mainForm.browser.Clear();
2399 ImportModule(filePath, normalImport, publicAccess, false);
2401 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2402 componentsApp.name = CopyString(filePath);
2404 for(module = componentsApp.allModules.first; module; module = module.next)
2406 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2410 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2411 AddComponents(componentsApp, false);
2413 GetLastDirectory(filePath, moduleName);
2414 // Extension, path and lib prefix get removed in Module::name
2417 StripExtension(moduleName);
2418 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2420 int len = strlen(moduleName) - 3;
2421 memmove(moduleName, moduleName + 3, len);
2422 moduleName[len] = 0;
2426 for(module = componentsApp.allModules.first; module; module = module.next)
2428 if(module.name && (!strcmp(module.name, moduleName)))
2431 if(!module) module = componentsApp;
2432 homeModule = module;
2433 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2435 SetSymbolsDir(null);
2438 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2441 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2442 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2445 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2447 APIPage page = row.GetData(null);
2448 if(view.edit) view.OnLeftButtonDown(0,0,0);
2449 if(page && page.page) page = page.page;
2451 view.PositionCaret(true);
2452 if(page != view.page)
2454 Window activeChild = this.activeChild;
2456 // Back / Forward Support
2457 if(row && !dontRecordHistory)
2459 if(history.count > historyPos+1)
2460 history.count = historyPos+1;
2461 historyPos = history.count-1;
2462 addressBar.back.disabled = (historyPos == 0);
2463 addressBar.forward.disabled = (historyPos >= history.count-1);
2465 history.Add((Instance)(uint64)row.tag);
2466 historyPos = history.count-1;
2468 addressBar.back.disabled = (historyPos == 0);
2469 addressBar.forward.disabled = (historyPos >= history.count-1);
2475 activeChild.Activate();
2477 else if(!view.created)
2481 page = row.GetData(null);
2482 if(page && page.page)
2486 case 1: view.GoToAnchor("Classes"); break;
2487 case 2: view.GoToAnchor("Functions"); break;
2488 case 3: view.GoToAnchor("Definitions"); break;
2489 case 4: view.GoToAnchor("VirtualMethods"); break;
2490 case 5: view.GoToAnchor("Methods"); break;
2491 case 6: view.GoToAnchor("Members"); break;
2492 case 7: view.GoToAnchor("Conversions"); break;
2493 case 8: view.GoToAnchor("EnumerationValues"); break;
2497 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2498 view.GoToAnchor(hex);
2504 view.SetScrollPosition(0, 0);
2512 this, anchor = { top = 26, bottom = 0, right = 0 };
2517 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2520 bool OnClose(bool parentClosing)
2523 view.OnLeftButtonDown(0,0,0);
2529 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2530 //mainForm.OpenModule("ec");
2531 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2532 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2534 int index = mainForm.browser.currentRow.index;
2535 int rowHeight = mainForm.browser.rowHeight;
2536 int height = mainForm.browser.clientSize.h;
2538 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2543 Array<Instance> history { };
2545 bool dontRecordHistory;
2550 if(historyPos < history.count-1)
2554 addressBar.back.disabled = (historyPos == 0);
2555 addressBar.forward.disabled = (historyPos >= history.count-1);
2556 sprintf(location, "api://%p", history[historyPos]);
2557 dontRecordHistory = true;
2558 view.OnOpen(location);
2559 dontRecordHistory = false;
2571 addressBar.back.disabled = (historyPos == 0);
2572 addressBar.forward.disabled = (historyPos >= history.count-1);
2573 sprintf(location, "api://%p", history[historyPos]);
2574 dontRecordHistory = true;
2575 view.OnOpen(location);
2576 dontRecordHistory = false;
2584 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2588 class EditDialog : Window
2590 borderStyle = sizable;
2591 size = { 600, 400 };
2596 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2600 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2604 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2608 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2609 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2611 class HelpView : HTMLView
2615 hasVertScroll = true;
2616 hasHorzScroll = true;
2618 char editString[MAX_LOCATION];
2624 page = mainForm.browser.currentRow.GetData(null);
2629 char docDir[MAX_LOCATION];
2631 strcpy(docDir, ideSettings.docDir);
2632 if(FileExists(docDir).isDirectory)
2634 PathCatSlash(docDir, "___docWriteTest");
2635 if(FileExists(docDir).isDirectory)
2638 if(!FileExists(docDir))
2644 if(FileExists(docDir).isDirectory)
2656 GoToAnchor(page.label);
2658 if(page.page) page = page.page;
2661 return HTMLView::OnCreate();
2672 String contents = null;
2675 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2677 if(block.type == TEXT && block.textLen)
2685 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2687 if(block.type == BR)
2689 else if(block.type == TEXT)
2690 f.Write(block.text, 1, block.textLen);
2694 if((len = f.GetSize()))
2696 contents = new char[len+1];
2697 f.Read(contents, 1, len);
2698 contents[len] = '\0';
2702 char docPath[MAX_LOCATION];
2703 char temp[MAX_LOCATION];
2704 char part[MAX_FILENAME];
2708 DocumentationType type;
2709 DocumentationItem item;
2711 NamespaceDoc nsDoc = null;
2712 ClassDoc clDoc = null;
2713 FunctionDoc fnDoc = null;
2714 MethodDoc mdDoc = null;
2716 Method method = null;
2717 GlobalFunction function = null;
2719 strcpy(temp, editString);
2720 SplitDirectory(temp, part, temp);
2721 module = (Module)strtoull(part, null, 16);
2722 SplitDirectory(temp, part, temp);
2723 object = (void *)strtoull(part, null, 16);
2724 SplitDirectory(temp, part, temp);
2725 data = (void *)strtoull(part, null, 16);
2726 SplitDirectory(temp, part, temp);
2727 if(!strcmp(part, "namespace"))
2728 type = nameSpaceDoc;
2729 else if(!strcmp(part, "function"))
2731 else if(!strcmp(part, "class"))
2733 else if(!strcmp(part, "method"))
2735 SplitDirectory(temp, part, temp);
2736 if(!strcmp(part, "description"))
2738 else if(!strcmp(part, "usage"))
2740 else if(!strcmp(part, "remarks"))
2742 else if(!strcmp(part, "example"))
2744 else if(!strcmp(part, "seeAlso"))
2746 else if(!strcmp(part, "enumerationValue"))
2747 item = enumerationValue;
2748 else if(!strcmp(part, "definition"))
2750 else if(!strcmp(part, "conversion"))
2752 else if(!strcmp(part, "memberDescription"))
2753 item = memberDescription;
2754 else if(!strcmp(part, "propertyDescription"))
2755 item = propertyDescription;
2756 else if(!strcmp(part, "parameter"))
2758 else if(!strcmp(part, "returnValue"))
2761 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2763 /* Why invalidate this entry here?
2765 MapIterator<const String, DocCacheEntry> it { map = docCache };
2766 if(it.Index(docPath, false))
2775 case classDoc: cl = (Class)object; break;
2776 case functionDoc: function = object; break;
2777 case methodDoc: method = object; cl = method._class; break;
2782 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2784 clDoc = (ClassDoc)doc;
2786 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2788 nsDoc = (NamespaceDoc)doc;
2794 if(type == functionDoc)
2796 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2797 if(name) name += 2; else name = function.name;
2798 fnDoc = nsDoc.functions ? nsDoc.functions[name] : null;
2799 if(!empty && !fnDoc)
2801 if(!nsDoc.functions) nsDoc.functions = { };
2802 nsDoc.functions[name] = fnDoc = { };
2805 else if(type == methodDoc)
2807 mdDoc = clDoc.methods ? clDoc.methods[method.name] : null;
2808 if(!empty && !mdDoc)
2810 if(!clDoc.methods && !empty) clDoc.methods = { };
2811 clDoc.methods[method.name] = mdDoc = { };
2815 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2820 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2821 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2822 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2823 else { nsDoc.description = contents; contents = null; }
2826 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2827 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2828 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2831 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2832 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2833 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2836 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2837 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2838 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2841 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2842 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2843 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2846 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2847 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2849 case enumerationValue:
2851 ValueDoc itDoc = clDoc.values ? clDoc.values[((NamedLink)data).name] : null;
2854 if(!empty && !itDoc)
2856 if(!clDoc.values) clDoc.values = { };
2857 clDoc.values[((NamedLink)data).name] = itDoc = { };
2859 itDoc.description = contents; contents = null;
2862 MapIterator<String, ValueDoc> it { map = clDoc.values };
2863 if(it.Index(((NamedLink)data).name, false))
2872 DefineDoc itDoc = nsDoc.defines ? nsDoc.defines[((Definition)data).name] : null;
2875 if(!empty && !itDoc)
2877 if(!nsDoc.defines) nsDoc.defines = { };
2878 nsDoc.defines[((Definition)data).name] = itDoc = { };
2880 itDoc.description = contents; contents = null;
2883 MapIterator<String, DefineDoc> it { map = nsDoc.defines };
2884 if(it.Index(((Definition)data).name, false))
2893 ConversionDoc itDoc;
2894 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2895 if(name) name += 2; else name = ((Property)data).name;
2896 itDoc = clDoc.conversions ? clDoc.conversions[name] : null;
2899 if(!empty && !itDoc)
2901 if(!clDoc.conversions) clDoc.conversions = { };
2902 clDoc.conversions[name] = itDoc = { };
2904 itDoc.description = contents; contents = null;
2907 MapIterator<String, ConversionDoc> it { map = clDoc.conversions };
2908 if(it.Index(name, false))
2915 case memberDescription:
2917 FieldDoc itDoc = clDoc.fields ? clDoc.fields[((DataMember)data).name] : null;
2920 if(!empty && !itDoc)
2922 if(!clDoc.fields) clDoc.fields = { };
2923 clDoc.fields[((DataMember)data).name] = itDoc = { };
2925 itDoc.description = contents; contents = null;
2928 MapIterator<String, FieldDoc> it { map = clDoc.fields };
2929 if(it.Index(((DataMember)data).name, false))
2936 case propertyDescription:
2938 PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null;
2941 if(!empty && !itDoc)
2943 if(!clDoc.properties) clDoc.properties = { };
2944 clDoc.properties[((Property)data).name] = itDoc = { };
2946 itDoc.description = contents, contents = null;
2949 MapIterator<String, PropertyDoc> it { map = clDoc.properties };
2950 if(it.Index(((Property)data).name, false))
2959 if(type == functionDoc || type == methodDoc)
2961 Map<String, ParameterDoc> * parameters = (type == functionDoc) ? &fnDoc.parameters : &mdDoc.parameters;
2962 char * name = ((Type)data).name;
2963 ParameterDoc itDoc = *parameters ? (*parameters)[name] : null;
2966 while(prev) position++, prev = prev.prev;
2970 if(!empty && !itDoc)
2972 if(!*parameters) *parameters = { };
2973 (*parameters)[name] = itDoc = { };
2975 itDoc.description = contents; contents = null;
2976 itDoc.position = position;
2979 MapIterator<String, ParameterDoc> it { map = *parameters };
2980 if(it.Index(((Type)data).name, false))
2992 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
2994 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
2995 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2996 if(name) name += 2; else name = function.name;
2997 if(it.Index(name, false))
3001 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
3003 MapIterator<String, MethodDoc> it { map = clDoc.methods };
3004 if(it.Index(method.name, false))
3010 if(nsDoc.functions && !nsDoc.functions.count) delete nsDoc.functions;
3011 if(nsDoc.defines && !nsDoc.defines.count) delete nsDoc.defines;
3015 if(clDoc && clDoc.conversions && !clDoc.conversions.count) delete clDoc.conversions;
3016 if(clDoc && clDoc.properties && !clDoc.properties.count) delete clDoc.properties;
3017 if(clDoc && clDoc.fields && !clDoc.fields.count) delete clDoc.fields;
3018 if(clDoc && clDoc.methods && !clDoc.methods.count) delete clDoc.methods;
3019 if(clDoc && clDoc.values && !clDoc.values.count) delete clDoc.values;
3024 char dirPath[MAX_LOCATION];
3025 StripLastDirectory(docPath, dirPath);
3026 if(FileExists(docPath))
3027 DeleteFile(docPath);
3028 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
3031 if(!FileExists(dirPath))
3033 if((f = FileOpen(docPath, write)))
3035 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3039 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3048 Block parent = textBlock.parent;
3049 while((block = parent.subBlocks.first))
3051 parent.subBlocks.Remove(block);
3054 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3055 textBlock.text = CopyString($"[Add Text]");
3056 textBlock.textLen = strlen(textBlock.text);
3057 parent.subBlocks.Add(textBlock);
3065 PositionCaret(true);
3070 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3074 if(edit && (!textBlock || overLink != textBlock.parent))
3078 HTMLView::OnLeftButtonDown(x, y, mods);
3079 selPosition = curPosition = 0;
3080 selBlock = textBlock;
3084 result = HTMLView::OnLeftButtonDown(x, y, mods);
3086 if(!edit && clickedLink)
3089 if(clickedLink == overLink && clickedLink.href)
3091 if(OnOpen(clickedLink.href))
3099 if(textBlock && overLink == textBlock.parent)
3101 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3102 selBlock = textBlock;
3103 PositionCaret(true);
3111 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3113 if(!edit || !textBlock || clickedLink != textBlock.parent)
3115 HTMLView::OnLeftButtonUp(x, y, mods);
3118 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3119 selBlock = textBlock;
3120 PositionCaret(true);
3131 bool OnMouseMove(int x, int y, Modifiers mods)
3133 if(edit && selecting)
3135 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3136 PositionCaret(true);
3139 return HTMLView::OnMouseMove(x, y, mods);
3142 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3144 if(edit && textBlock)
3150 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3151 selBlock = textBlock;
3152 for(c = curPosition; c >= 0; c--)
3155 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3156 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3157 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3163 for(c = start; c < textBlock.textLen; c += numBytes)
3165 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3166 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3169 selPosition = start;
3172 PositionCaret(true);
3180 bool OnOpen(char * href)
3182 if(!strncmp(href, "api://", 6))
3184 int64 tag = (int64)strtoull(href + 6, null, 16);
3185 DataRow row = mainForm.browser.FindSubRow(tag);
3189 mainForm.browser.SelectRow(row);
3190 while((row = row.parent))
3191 row.collapsed = false;
3192 row = mainForm.browser.currentRow;
3193 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3196 else if(!strncmp(href, "edit://", 7))
3199 int startX = clickedLink.startX, startY = clickedLink.startY;
3200 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3202 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3203 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3205 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3207 display.FontExtent(block.font.font, " ", 1, null, &th);
3210 block.parent.subBlocks.Insert(null, newBlock);
3215 block.parent.subBlocks.Insert(block, newBlock);
3216 startY += block.prev.height;
3218 newBlock.startX = startX;
3219 newBlock.startY = startY;
3220 newBlock.text = new0 char[1];
3224 textBlock = (Block)clickedLink.subBlocks.first;
3225 if(!strcmp(textBlock.text, $"[Add Text]"))
3227 textBlock.text[0] = 0;
3228 textBlock.textLen = 0;
3231 strcpy(editString, href + 7);
3232 selPosition = curPosition = 0;
3233 selBlock = textBlock;
3236 // PositionCaret(true);
3243 void DeleteSelection()
3245 if(textBlock != selBlock || curPosition != selPosition)
3247 if(textBlock == selBlock)
3249 // Within same block
3250 int start = Min(curPosition, selPosition);
3251 int end = Max(curPosition, selPosition);
3252 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3253 textBlock.textLen -= end-start;
3254 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3255 curPosition = start;
3256 selPosition = start;
3260 int startSel, endSel;
3261 Block startSelBlock = null, endSelBlock = null, b, next;
3263 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3265 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3266 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3268 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3269 for(b = startSelBlock.next; b; b = next)
3271 bool isEnd = b == endSelBlock;
3272 next = GetNextBlock(b);
3273 b.parent.subBlocks.Remove(b);
3278 textBlock = startSelBlock;
3279 selBlock = startSelBlock;
3280 curPosition = startSel;
3281 selPosition = startSel;
3285 PositionCaret(true);
3290 String GetSelectionString()
3292 String selection = null;
3293 if(textBlock == selBlock)
3295 // Within same block
3296 int start = Min(curPosition, selPosition);
3297 int end = Max(curPosition, selPosition);
3298 int len = end - start;
3299 selection = new char[len + 1];
3300 memcpy(selection, textBlock.text + start, len);
3305 int startSel, endSel;
3306 Block startSelBlock = null, endSelBlock = null, b;
3309 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3312 for(b = startSelBlock; b; b = GetNextBlock(b))
3314 int start = (b == startSelBlock) ? startSel : 0;
3315 int end = (b == endSelBlock) ? endSel : b.textLen;
3316 int len = end - start;
3318 if(b == endSelBlock)
3320 else if(b.type == TEXT)
3324 selection = new char[totalLen + 1];
3326 for(b = startSelBlock; b; b = GetNextBlock(b))
3328 int start = (b == startSelBlock) ? startSel : 0;
3329 int end = (b == endSelBlock) ? endSel : b.textLen;
3330 int len = end - start;
3331 memcpy(selection + totalLen, b.text + start, len);
3333 if(b == endSelBlock)
3335 else if(b.type == TEXT)
3336 selection[totalLen++] = '\n';
3338 selection[totalLen] = 0;
3343 void CopySelection()
3345 String s = GetSelectionString();
3348 int len = strlen(s);
3350 if(cb.Allocate(len + 1))
3352 memcpy(cb.text, s, len + 1);
3360 bool OnKeyDown(Key key, unichar ch)
3367 OnLeftButtonDown(0,0,0);
3369 case Key { end, shift = true }:
3371 curPosition = textBlock.textLen;
3374 selPosition = curPosition;
3375 selBlock = textBlock;
3377 PositionCaret(true);
3380 case Key { home, shift = true }:
3385 selPosition = curPosition;
3386 selBlock = textBlock;
3388 PositionCaret(true);
3391 case Key { home, ctrl = true, shift = true }:
3394 while(textBlock.prev)
3395 textBlock = textBlock.prev.prev;
3398 selPosition = curPosition;
3399 selBlock = textBlock;
3401 PositionCaret(true);
3404 case Key { end, ctrl = true, shift = true }:
3406 while(textBlock.next && textBlock.next.next)
3407 textBlock = textBlock.next.next;
3408 curPosition = textBlock.textLen;
3411 selPosition = curPosition;
3412 selBlock = textBlock;
3414 PositionCaret(true);
3420 return HTMLView::OnKeyDown(key, ch);
3424 bool OnKeyHit(Key key, unichar ch)
3430 case Key { up, shift = true }:
3433 if(caretY == textBlock.startY)
3437 textBlock = textBlock.prev.prev;
3438 curPosition = Min(curPosition, textBlock.textLen);
3441 selPosition = curPosition;
3442 selBlock = textBlock;
3445 PositionCaret(false);
3455 int sx = textBlock.startX, sy = textBlock.startY;
3456 char * text = textBlock.text;
3458 Block block = textBlock;
3459 while(block && block.type != TD) block = block.parent;
3462 Block table = block;
3463 while(table && table.type != TABLE) table = table.parent;
3465 maxW = block.w - 2* table.cellPadding;
3467 maxW = clientSize.w - 10 - sx;
3470 maxW = clientSize.w - 10 - sx;
3471 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3475 int startPos = textPos;
3478 bool lineComplete = false;
3479 for(; textPos<textBlock.textLen && !lineComplete;)
3483 char * nextSpace = strchr(text + textPos, ' ');
3486 len = (nextSpace - (text + textPos)) + 1;
3488 len = textBlock.textLen - textPos;
3490 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3492 if(x + width + w > maxW && x > 0)
3494 lineComplete = true;
3504 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3507 curPosition = textPos;
3508 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3511 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3512 len = curPosition - startPos;
3513 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3517 selPosition = curPosition;
3518 selBlock = textBlock;
3522 PositionCaret(false);
3526 if(sy == caretY - th || textPos == textBlock.textLen)
3528 if(textPos != textBlock.textLen)
3530 int c = textPos - 1;
3531 while(c > 0 && text[c] == ' ') c--;
3532 curPosition = c + 1;
3535 selPosition = curPosition;
3536 selBlock = textBlock;
3542 curPosition = textBlock.textLen;
3545 selPosition = curPosition;
3546 selBlock = textBlock;
3550 PositionCaret(false);
3554 sx = textBlock.startX;
3555 } while(textPos < textBlock.textLen);
3560 case Key { down, shift = true }:
3565 int sx = textBlock.startX, sy = textBlock.startY;
3566 char * text = textBlock.text;
3568 Block block = textBlock;
3569 while(block && block.type != TD) block = block.parent;
3572 Block table = block;
3573 while(table && table.type != TABLE) table = table.parent;
3575 maxW = block.w - 2* table.cellPadding;
3577 maxW = clientSize.w - 10 - sx;
3580 maxW = clientSize.w - 10 - sx;
3581 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3583 while(!textPos || textPos < textBlock.textLen)
3585 int startPos = textPos;
3588 bool lineComplete = false;
3589 for(; (textPos < textBlock.textLen) && !lineComplete;)
3593 char * nextSpace = strchr(text + textPos, ' ');
3596 len = (nextSpace - (text + textPos)) + 1;
3598 len = textBlock.textLen - textPos;
3600 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3602 if(x + width + w > maxW && x > 0)
3604 lineComplete = true;
3614 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3616 curPosition = textPos;
3618 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3621 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3622 len = curPosition - startPos;
3623 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3627 selPosition = curPosition;
3628 selBlock = textBlock;
3631 PositionCaret(false);
3637 curPosition = textBlock.textLen;
3640 selPosition = curPosition;
3641 selBlock = textBlock;
3644 PositionCaret(false);
3647 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3651 textBlock = textBlock.next.next;
3652 sy = textBlock.startY;
3653 sx = textBlock.startX;
3654 text = textBlock.text;
3659 sx = textBlock.startX;
3663 /*if(textBlock.next && textBlock.next.next)
3665 textBlock = textBlock.next.next;
3666 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3667 selBlock = textBlock;
3668 PositionCaret(false);
3672 case Key { right, shift = true, ctrl = true }:
3675 bool foundAlpha = false;
3677 Block line, lastLine;
3680 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3682 int start = (line == textBlock) ? curPosition : 0;
3684 for(c = start; c < line.textLen; c++)
3686 char ch = line.text[c];
3687 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3688 if(key.shift ? isAlUnder : !isAlUnder)
3702 selPosition = curPosition;
3703 selBlock = textBlock;
3707 PositionCaret(true);
3712 // No next word found,
3713 if(!found && (c != curPosition || line != textBlock))
3717 lastC = line.textLen-1;
3722 curPosition = line.textLen;
3725 selPosition = curPosition;
3726 selBlock = textBlock;
3731 PositionCaret(true);
3737 if(key.shift && found)
3739 curPosition = lastC+1;
3740 textBlock = lastLine;
3741 PositionCaret(true);
3746 case Key { left, ctrl = true, shift = true }:
3749 bool foundAlpha = false;
3751 Block line, lastLine;
3754 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3757 if(curPosition == 0 && line != textBlock)
3760 lastC = line.textLen;
3764 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3765 for(c = start; c>=0; c--)
3767 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3782 // No next word found,
3783 if(!found && curPosition > 0)
3793 textBlock = lastLine;
3794 curPosition = lastC;
3797 selPosition = curPosition;
3798 selBlock = textBlock;
3800 PositionCaret(true);
3805 case Key { right, shift = true }:
3807 if(curPosition < textBlock.textLen)
3809 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3812 selPosition = curPosition;
3813 selBlock = textBlock;
3815 PositionCaret(true);
3818 else if(textBlock.next && textBlock.next.next)
3820 textBlock = textBlock.next.next;
3824 selPosition = curPosition;
3825 selBlock = textBlock;
3827 PositionCaret(true);
3831 case Key { left, shift = true }:
3835 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3838 selPosition = curPosition;
3839 selBlock = textBlock;
3841 PositionCaret(true);
3844 else if(textBlock.prev)
3846 textBlock = textBlock.prev.prev;
3847 curPosition = textBlock.textLen;
3850 selPosition = curPosition;
3851 selBlock = textBlock;
3853 PositionCaret(true);
3859 if(textBlock == selBlock && curPosition == selPosition)
3863 int c = curPosition;
3865 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3866 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3867 textBlock.textLen -= nb;
3868 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3870 selPosition = curPosition;
3871 selBlock = textBlock;
3875 PositionCaret(true);
3878 else if(textBlock.prev)
3880 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3881 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3882 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3884 selPosition = curPosition = prevBlock.textLen;
3885 selBlock = textBlock;
3886 prevBlock.textLen += textBlock.textLen;
3887 textBlock.parent.subBlocks.Remove(prev);
3888 if(prev == selBlock)
3890 selBlock = textBlock;
3891 selPosition = curPosition;
3894 textBlock.parent.subBlocks.Remove(textBlock);
3895 if(textBlock == selBlock)
3897 selBlock = prevBlock;
3898 selPosition = curPosition;
3901 textBlock = prevBlock;
3905 PositionCaret(true);
3914 if(textBlock != selBlock || curPosition != selPosition)
3916 else if(textBlock.textLen > curPosition)
3918 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3919 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3920 textBlock.textLen -= nb;
3921 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3926 PositionCaret(true);
3929 else if(textBlock.next && textBlock.next.next)
3931 Block next = textBlock.next, nextBlock = textBlock.next.next;
3932 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3933 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3935 textBlock.textLen += nextBlock.textLen;
3936 textBlock.parent.subBlocks.Remove(next);
3937 if(next == selBlock)
3939 selBlock = textBlock;
3940 selPosition = curPosition;
3943 textBlock.parent.subBlocks.Remove(nextBlock);
3944 if(nextBlock == selBlock)
3946 selBlock = textBlock;
3947 selPosition = curPosition;
3953 PositionCaret(true);
3967 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3968 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3969 startY = textBlock.startY;
3970 startX = textBlock.startX;
3972 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3973 textBlock.parent.subBlocks.Insert(textBlock, block);
3974 textBlock.parent.subBlocks.Insert(block, newBlock);
3978 newBlock.textLen = textBlock.textLen - curPosition;
3979 newBlock.text = new char[newBlock.textLen+1];
3980 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3981 textBlock.textLen = curPosition;
3982 textBlock.text[curPosition] = 0;
3984 newBlock.startY = startY;
3985 newBlock.startX = startX;
3986 selPosition = curPosition = 0;
3991 textBlock = newBlock;
3992 selBlock = textBlock;
3993 PositionCaret(true);
3998 case Key { del, shift = true }:
4013 ClipBoard clipBoard { };
4014 if(clipBoard.Load())
4017 char * text = clipBoard.memory;
4025 parent = textBlock.parent;
4026 font = textBlock.font;
4031 if(ch == '\n' || ch == '\r' || !ch)
4033 int len = c - start;
4034 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4035 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4036 memcpy(textBlock.text + curPosition, text + start, len);
4037 textBlock.textLen += len;
4039 selPosition = curPosition;
4040 selBlock = textBlock;
4043 Block block { type = BR, parent = parent, font = font };
4044 Block newBlock { type = TEXT, parent = parent, font = font };
4045 int startY = textBlock.startY, startX = textBlock.startX;
4048 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4049 textBlock.parent.subBlocks.Insert(textBlock, block);
4050 textBlock.parent.subBlocks.Insert(block, newBlock);
4054 newBlock.textLen = textBlock.textLen - curPosition;
4055 newBlock.text = new char[newBlock.textLen+1];
4056 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4057 textBlock.textLen = curPosition;
4058 textBlock.text[curPosition] = 0;
4060 newBlock.startY = startY;
4061 newBlock.startX = startX;
4062 selPosition = curPosition = 0;
4063 selBlock = textBlock;
4064 textBlock = newBlock;
4066 if(ch == '\r' && text[c+1] == '\n') c++;
4072 PositionCaret(true);
4080 // eC BUG HERE: (Should be fixed)
4081 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4084 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4089 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4090 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4092 for(c = 0; c<len; c++)
4094 textBlock.text[curPosition] = string[c];
4095 textBlock.textLen++;
4098 selPosition = curPosition;
4099 selBlock = textBlock;
4102 //Clear(html.block);
4103 //CreateForms(html.block);
4108 PositionCaret(true);
4117 void OnResize(int width, int height)
4119 HTMLView::OnResize(width, height);
4120 PositionCaret(true);
4124 void PositionCaret(bool setCaretX)
4130 int sx = textBlock.startX, sy = textBlock.startY;
4131 char * text = textBlock.text;
4133 Block block = textBlock;
4134 while(block && block.type != TD) block = block.parent;
4137 Block table = block;
4138 while(table && table.type != TABLE) table = table.parent;
4140 maxW = block.w - 2* table.cellPadding;
4142 maxW = clientSize.w - 10 - sx;
4145 maxW = clientSize.w - 10 - sx;
4147 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4149 while(textPos < textBlock.textLen)
4151 int startPos = textPos;
4154 bool lineComplete = false;
4156 for(; textPos<textBlock.textLen && !lineComplete;)
4160 char * nextSpace = strchr(text + textPos, ' ');
4163 len = (nextSpace - (text + textPos)) + 1;
4165 len = textBlock.textLen - textPos;
4167 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4169 if(x + width + w > maxW && x > 0)
4171 lineComplete = true;
4184 if(curPosition < textPos || textPos == textBlock.textLen)
4186 int len = curPosition - startPos;
4187 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4192 sx = textBlock.startX;
4197 SetCaret(sx, sy, th);
4199 Point scrollPos = scroll;
4200 bool doScroll = false;
4201 if(sy - scroll.y + th > clientSize.h)
4203 scrollPos.y = sy + th - clientSize.h;
4206 else if(sy - scroll.y < 0)
4211 if(sx - scroll.x + 10 > clientSize.w)
4213 scrollPos.x = sx + 10 - clientSize.w;
4216 else if(sx - scroll.x < 10)
4218 scrollPos.x = sx - 10;
4229 // Returns a character offset into the TextBlock from a window coordinate
4230 int TextPosFromPoint(int px, int py, Block * block, bool half)
4232 Block parentBlock = this.textBlock.parent;
4235 *block = this.textBlock;
4240 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4242 int sx = textBlock.startX, sy = textBlock.startY;
4245 char * text = textBlock.text;
4247 Block b = textBlock;
4250 if(textBlock.type != TEXT) continue;
4252 while(b && b.type != TD) b = b.parent;
4256 while(table && table.type != TABLE) table = table.parent;
4258 maxW = b.w - 2* table.cellPadding;
4260 maxW = clientSize.w - 10 - sx;
4263 maxW = clientSize.w - 10 - sx;
4265 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4266 //space = space/2+2;
4269 while(textPos < textBlock.textLen)
4273 bool lineComplete = false;
4275 for(; textPos<textBlock.textLen && !lineComplete;)
4279 char * nextSpace = strchr(text + textPos, ' ');
4282 len = (nextSpace - (text + textPos)) + 1;
4284 len = textBlock.textLen - textPos;
4286 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4288 sx = x + textBlock.startX;
4289 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4294 for(c = textPos; (ch = text[c]); c += numBytes)
4296 numBytes = UTF8_NUM_BYTES(ch);
4297 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4298 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4305 if(x + width + w > maxW && x > 0)
4307 lineComplete = true;
4320 if(/*py >= sy && */py < sy + th)
4323 return textBlock.textLen;
4328 result = textBlock.textLen;
4334 Application componentsApp;
4336 class Documentor : GuiApplication
4340 Platform os = __runtimePlatform;
4341 SetGlobalContext(globalContext);
4342 SetExcludedSymbols(&excludedSymbols);
4343 SetDefines(&::defines);
4344 SetImports(&imports);
4345 SetInDocumentor(true);
4347 SetGlobalData(globalData);
4349 settingsContainer.dataOwner = &ideSettings;
4350 settingsContainer.Load();
4351 if(!ideSettings.docDir || !ideSettings.docDir[0] )
4353 if(os == win32) // if Windows OS then
4355 char programFilesDir[MAX_LOCATION];
4356 char appData[MAX_LOCATION];
4357 char homeDrive[MAX_LOCATION];
4358 char winDir[MAX_LOCATION];
4359 GetEnvironment("APPDATA", appData, sizeof(appData));
4360 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4361 GetEnvironment("windir", winDir, sizeof(winDir));
4362 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4364 PathCat(programFilesDir, "ECERE SDK\\doc");
4365 ideSettings.docDir = programFilesDir;
4367 else if(homeDrive[0])
4369 PathCat(homeDrive, "ECERE SDK\\doc");
4370 ideSettings.docDir = homeDrive;
4374 PathCat(winDir, "..\\ECERE SDK\\doc");
4375 ideSettings.docDir = winDir;
4378 ideSettings.docDir = "C:\\ECERE SDK\\doc";
4380 else // if Os is Linux, or Mac OSX or something else
4381 ideSettings.docDir = "/usr/share/ecere/doc/";
4382 settingsContainer.Save();
4388 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4390 AddComponents(module, true);
4391 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4392 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4393 while((row = row.parent))
4394 row.collapsed = false;
4398 commandThread.Create();
4402 bool Cycle(bool idle)
4405 mainForm.Destroy(0);
4414 if(commandThread.created)
4416 console.CloseInput();
4417 console.CloseOutput();
4419 commandThread.Wait();
4423 FreeContext(globalContext);
4424 FreeExcludedSymbols(excludedSymbols);
4425 ::defines.Free(FreeModuleDefine);
4426 imports.Free(FreeModuleImport);
4428 FreeGlobalData(globalData);
4429 FreeTypeData(componentsApp);
4431 delete componentsApp;
4435 ConsoleFile console { };
4436 MainForm mainForm { };
4439 Thread commandThread
4446 console.GetLine(command, sizeof(command));
4447 if(!quit && command[0])
4450 if(!strcmpi(command, "Activate"))
4451 mainForm.Activate();
4452 else if(!strcmpi(command, "Quit"))
4460 #endif // !defined(EAR_TO_ECON_ECDOC)
4465 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4466 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4470 property bool isEmpty
4476 (description && *description));
4486 class MoreDoc : ItemDoc
4489 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4490 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4491 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4492 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4498 property bool isEmpty
4503 (usage && *usage) ||
4504 (example && *example) ||
4505 (remarks && *remarks) ||
4519 class NamespaceDoc : ItemDoc
4522 Map<String, DefineDoc> defines;
4523 Map<String, FunctionDoc> functions;
4525 property bool isEmpty
4530 (defines && defines.count) ||
4531 (functions && functions.count) ||
4542 class DefineDoc : ItemDoc { }
4544 class FunctionDoc : MoreDoc
4547 Map<String, ParameterDoc> parameters;
4548 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4551 property bool isEmpty
4556 (parameters && parameters.count) ||
4557 (returnValue && *returnValue) ||
4568 class ParameterDoc : ItemDoc
4574 class ClassDoc : MoreDoc
4577 Map<String, ValueDoc> values;
4578 Map<String, FieldDoc> fields;
4579 Map<String, PropertyDoc> properties;
4580 Map<String, ConversionDoc> conversions;
4581 Map<String, MethodDoc> methods;
4583 property bool isEmpty
4588 (values && values.count) ||
4589 (fields && fields.count) ||
4590 (properties && properties.count) ||
4591 (conversions && conversions.count) ||
4592 (methods && methods.count) ||
4606 class ValueDoc : ItemDoc { }
4608 class FieldDoc : ItemDoc { }
4610 class PropertyDoc : ItemDoc { }
4612 class ConversionDoc : ItemDoc { }
4614 class MethodDoc : FunctionDoc { }
4616 char * getDocFileNameFromTypeName(const char * typeName)
4618 char * docFileName = new char[MAX_FILENAME];
4619 const char * swap = "pointer";
4620 const char * s = typeName;
4621 char * d = docFileName;
4622 const char * end = s + strlen(typeName);
4623 int swapLen = strlen(swap);
4641 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4644 Time timeStamp; // Should this be last accessed, or last retrieved?
4653 Map<String, DocCacheEntry> docCache { };