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 IDESettings settings { }; // instantiate the IDESettings class from the IDESettings.ec file. Do this at a global level so that all methods can access settings.
51 IDESettingsContainer settingsContainer
55 dataOwner = &settings;
58 void GetTemplateString(Class c, char * templateString)
60 Module m = c.module.application;
61 const char * n = c.name;
62 char * lt = strchr(n, '<');
68 memcpy(templateString, n, lt-n);
69 templateString[lt-n] = 0;
70 strcat(templateString, "</a>");
72 for(s = lt; (ch = *s); s++)
74 if(ch == '<' || ch == '>' || ch == ',')
79 char * d = templateString + strlen(templateString);
81 TrimLSpaces(curName, curName);
82 TrimRSpaces(curName, curName);
83 pc = eSystem_FindClass(m, curName);
85 sprintf(d, "%s<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name);
90 strcat(templateString, "<");
92 strcat(templateString, ">");
94 strcat(templateString, ", ");
101 curName[len++] = ' ';
103 strcat(templateString, curName);
111 // WARNING : This function expects a null terminated string since it recursively concatenate...
112 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
116 if(type.constant && (type.kind != pointerType && type.kind != arrayType))
117 strcat(string, "const ");
121 if(type._class && type._class.string)
124 strcat(string, type._class.string);
127 if(type._class.registered)
130 const char * s = type._class.registered.name;
131 sprintf(hex, "%p", type._class.registered.templateClass ? type._class.registered.templateClass : type._class.registered);
132 strcat(string, "<a href=\"api://");
134 strcat(string, "\" style=\"text-decoration: none;\">");
138 GetTemplateString(type._class.registered, n);
142 strcat(string, type._class.registered.name);
143 strcat(string, "</a>");
146 strcat(string, type._class.string);
153 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
154 if(funcType && funcType.kind == functionType)
157 DocPrintType(funcType.returnType, string, false, fullName);
158 strcat(string, "(*");
159 if(printName || funcType.thisClass)
162 if(funcType.thisClass)
164 strcat(string, funcType.thisClass.string);
165 strcat(string, "::");
168 strcat(string, type.name);
170 strcat(string, ")(");
171 for(param = funcType.params.first; param; param = param.next)
173 DocPrintType(param, string, false, fullName);
174 if(param.next) strcat(string, ", ");
180 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
181 if(string[strlen(string)-1] == '(')
184 strcat(string, " *");
188 case voidType: strcat(string, "void"); break;
189 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
190 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
191 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
192 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
193 case floatType: strcat(string, "float"); break;
194 case doubleType: strcat(string, "double"); break;
198 strcat(string, "struct ");
199 strcat(string, type.enumName);
201 else if(type.typeName)
203 strcat(string, type.typeName);
208 strcat(string, "struct ");
209 strcat(string,"(unnamed)");
212 strcat(string, "struct {");
213 for(member = type.members.first; member; member = member.next)
215 DocPrintType(member, string, true, fullName);
224 strcat(string, "union ");
225 strcat(string, type.enumName);
227 else if(type.typeName)
229 strcat(string, type.typeName);
233 strcat(string, "union ");
234 strcat(string,"(unnamed)");
240 strcat(string, "enum ");
241 strcat(string, type.enumName);
243 else if(type.typeName)
245 strcat(string, type.typeName);
248 strcat(string, "enum");
255 strcat(string, "dllexport ");
256 DocPrintType(type.returnType, string, false, fullName);
260 // DANGER: Testing This
266 strcat(string, type.name);
269 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
270 if(name) name += 2; else name = type.name;
271 strcat(string, "<b>");
272 strcat(string, name);
273 strcat(string, "</b>");
282 for(param = type.params.first; param; param = param.next)
284 DocPrintType(param, string, true, fullName);
285 if(param.next) strcat(string, ", ");
294 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
295 if(funcType && funcType.kind == functionType)
298 DocPrintType(funcType.returnType, string, false, fullName);
299 strcat(string, "(*");
300 if(printName || funcType.thisClass)
303 if(funcType.thisClass)
305 strcat(string, funcType.thisClass.string);
306 strcat(string, "::");
309 strcat(string, type.name);
311 strcat(string, ")(");
312 for(param = funcType.params.first; param; param = param.next)
314 DocPrintType(param, string, false, fullName);
315 if(param.next) strcat(string, ", ");
321 char baseType[1024], size[256];
322 Type arrayType = type;
326 while(arrayType.kind == TypeKind::arrayType)
329 if(arrayType.enumClass)
330 strcat(size, arrayType.enumClass.string);
331 else if(arrayType.arraySizeExp)
332 PrintExpression(arrayType.arraySizeExp, size);
333 //sprintf(string, "%s[%s]", baseType, size);
336 arrayType = arrayType.arrayType;
338 _PrintType(arrayType, baseType, printName, printFunction, fullName);
339 strcat(string, baseType);
340 strcat(string, size);
344 DocPrintType(type.arrayType, baseType, printName, fullName);
346 strcpy(size, type.enumClass.string);
347 else if(type.arraySizeExp)
348 PrintExpression(type.arraySizeExp, size);
349 //sprintf(string, "%s[%s]", baseType, size);
350 strcat(string, baseType);
352 strcat(string, size);
360 strcat(string, "...");
363 _PrintType(type.method.dataType, string, false, printFunction, fullName);
366 strcat(string, "subclass(");
367 strcat(string, type._class ? type._class.string : "int");
373 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
376 strcat(string, type.name);
381 void DocPrintType(Type type, char * string, bool printName, bool fullName)
384 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
385 if(funcType && funcType.kind == functionType && type != funcType)
389 DocPrintType(funcType.returnType, string, false, fullName);
391 _PrintType(type, string, printName, false, fullName);
395 strcat(string, type.name);
402 for(param = funcType.params.first; param; param = param.next)
404 DocPrintType(param, string, true, fullName);
405 if(param.next) strcat(string, ", ");
410 _PrintType(type, string, printName, true, fullName);
413 Map<String, bool> modulesAdded { };
414 void AddComponents(Module module, bool isDll)
419 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")) && !modulesAdded["ecereCOM"])
421 row = mainForm.browser.AddRow();
422 modulesAdded["ecereCOM"] = true;
423 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
424 row.tag = (int64)null;
425 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
428 for(m = module.modules.first; m; m = m.next)
430 if(m.importMode == publicAccess || !isDll)
431 AddComponents(m.module, true);
434 // PUT MODULE DESCRIPTION HERE
435 if(module.name && !modulesAdded[module.name] && strcmp(module.name, "ecereCOM"))
437 row = mainForm.browser.AddRow();
438 modulesAdded[module.name] = true;
439 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
440 row.tag = (int64)module;
441 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
443 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
455 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
460 virtual void Generate(File f)
465 virtual Module GetModule()
467 return page ? page.GetModule() : null;
470 virtual NameSpace * GetNameSpace()
472 return page ? page.GetNameSpace() : null;
476 enum DocumentationType
485 enum DocumentationItem
502 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
506 sprintf(hex, "%p", module);
507 strcat(fileName, hex);
508 strcat(fileName, "/");
509 sprintf(hex, "%p", object);
510 strcat(fileName, hex);
511 strcat(fileName, "/");
512 sprintf(hex, "%p", data);
513 strcat(fileName, hex);
514 strcat(fileName, "/");
515 if(type == nameSpaceDoc)
516 strcat(fileName, "namespace");
517 else if(type == functionDoc)
518 strcat(fileName, "function");
519 else if(type == classDoc)
520 strcat(fileName, "class");
521 else if(type == methodDoc)
522 strcat(fileName, "method");
523 strcat(fileName, "/");
524 if(item == description)
525 strcat(fileName, "description");
526 else if(item == usage)
527 strcat(fileName, "usage");
528 else if(item == remarks)
529 strcat(fileName, "remarks");
530 else if(item == example)
531 strcat(fileName, "example");
532 else if(item == seeAlso)
533 strcat(fileName, "seeAlso");
534 else if(item == enumerationValue)
535 strcat(fileName, "enumerationValue");
536 else if(item == definition)
537 strcat(fileName, "definition");
538 else if(item == conversion)
539 strcat(fileName, "conversion");
540 else if(item == memberDescription)
541 strcat(fileName, "memberDescription");
542 else if(item == propertyDescription)
543 strcat(fileName, "propertyDescription");
544 else if(item == parameter)
545 strcat(fileName, "parameter");
546 else if(item == returnValue)
547 strcat(fileName, "returnValue");
550 static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
552 char docPath[MAX_LOCATION];
553 NameSpace * nameSpace, * ns;
555 Method method = null;
556 GlobalFunction function = null;
557 char nsName[1024], temp[1024];
560 case nameSpaceDoc: nameSpace = object; break;
561 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
562 case functionDoc: function = object; nameSpace = function.nameSpace; break;
563 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
569 while(ns && ns->name)
571 strcpy(temp, ns->name);
573 strcat(temp, nsName);
574 strcpy(nsName, temp);
579 PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
580 //ChangeExtension(docPath, "eCdoc", docPath);
581 PathCatSlash(docPath, nsName);
584 char * name = getDocFileNameFromTypeName(cl.name);
585 PathCatSlash(docPath, name);
589 PathCatSlash(docPath, "_global-defs");
590 ChangeExtension(docPath, "econ", docPath);
593 strcpy(path, settings.docDir);
594 PathCatSlash(path, docPath);
597 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
599 String contents = null;
600 NamespaceDoc nsDoc = null;
601 ClassDoc clDoc = null;
602 FunctionDoc fnDoc = null;
603 MethodDoc mdDoc = null;
605 char filePath[MAX_LOCATION];
606 Method method = null;
607 GlobalFunction function = null;
609 ItemDoc doc = getDoc(filePath, module, type, object, item, data, false);
613 case functionDoc: function = object; break;
614 case methodDoc: method = object; break;
619 if(eClass_IsDerived(doc._class, class(ClassDoc)))
621 clDoc = (ClassDoc)doc;
623 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
625 nsDoc = (NamespaceDoc)doc;
631 ItemDoc itDoc = null;
632 if(type == functionDoc)
634 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
635 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
636 if(name) name += 2; else name = function.name;
637 if(it.Index(name, false))
640 else if(type == methodDoc)
642 MapIterator<String, MethodDoc> it { map = clDoc.methods };
643 if(it.Index(method.name, false))
649 case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break;
650 case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break;
651 case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break;
652 case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break;
653 case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break;
654 case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break;
655 case enumerationValue:
656 if(clDoc && clDoc.values)
658 itDoc = clDoc.values[((NamedLink)data).name];
659 if(itDoc) s = itDoc.description;
663 if(nsDoc && nsDoc.defines)
665 itDoc = nsDoc.defines[((Definition)data).name];
666 if(itDoc) s = itDoc.description;
670 if(clDoc && clDoc.conversions)
672 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
673 if(name) name += 2; else name = ((Property)data).name;
674 itDoc = clDoc.conversions[name];
675 if(itDoc) s = itDoc.description;
678 case memberDescription:
679 if(clDoc && clDoc.fields)
681 itDoc = clDoc.fields[((DataMember)data).name];
682 if(itDoc) s = itDoc.description;
685 case propertyDescription:
686 if(clDoc && clDoc.properties)
688 itDoc = clDoc.properties[((Property)data).name];
689 if(itDoc) s = itDoc.description;
693 if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters))
695 char * name = ((Type)data).name;
696 itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ;
697 if(itDoc) s = itDoc.description;
702 contents = CopyString(s);
704 if(editing && !contents && !readOnly)
705 contents = CopyString($"[Add Text]");
709 // The filePath is returned!
710 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
714 Method method = null;
720 case classDoc: cl = (Class)object; break;
721 case methodDoc: method = object; cl = method._class; break;
724 FigureFilePath(filePath, module, type, object, item, data);
726 entry = docCache[filePath];
732 File f = FileOpen(filePath, read);
735 ECONParser parser { f = f };
736 JSONResult jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
740 if(jsonResult != success)
742 PrintLn("error: problem parsing file: ", filePath);
747 doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
750 incref doc; // Reference to return
755 entry.timeStamp = now;
758 docCache[filePath] = { now, doc };
759 incref doc; // Reference for the cache
762 //void pruneDocCache()
763 // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
765 MapIterator<String, DocCacheEntry> it { map = docCache };
766 Array<const String> toRemove { };
767 for(entry : docCache; now - entry.timeStamp > 30)
768 toRemove.Add(&entry);
769 while(toRemove.count)
771 if(it.Index(toRemove.lastIterator.data, false))
776 toRemove.Remove(toRemove.lastIterator.pointer);
783 class APIPageNameSpace : APIPage
785 NameSpace * nameSpace;
793 NameSpace * GetNameSpace()
798 void Generate(File f)
800 char nsName[1024], temp[1024];
806 while(ns && ns->name)
808 strcpy(temp, ns->name);
809 if(nsName[0]) strcat(temp, "::");
810 strcat(temp, nsName);
811 strcpy(nsName, temp);
814 // Generate Class Page
815 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
818 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
819 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);
822 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
825 ns = nameSpace->parent;
826 while(ns && ns->name)
828 strcpy(temp, ns->name);
829 if(nsName[0]) strcat(temp, "::");
830 strcat(temp, nsName);
831 strcpy(nsName, temp);
835 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
839 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
842 f.Printf($"<H3>Description</H3><br><br>\n");
845 char fileName[MAX_LOCATION];
846 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
847 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
849 f.Printf("</a><br><br>");
852 f.Printf("%s<br><br>", desc);
857 if(nameSpace->nameSpaces.first)
860 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
862 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
865 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
866 f.Printf("<TABLE>\n");
870 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", iconNames[typeNameSpace], ns, ns->name);
875 char fileName[MAX_LOCATION];
876 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
877 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
879 f.Printf("</a></TD>");
882 f.Printf("<TD valign=top height=22> %s</TD>", desc);
885 f.Printf("</TR><br>\n");
888 f.Printf("</TABLE><br>\n");
891 if(nameSpace->classes.first)
894 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
896 Class cl = link.data;
897 if(!cl.templateClass)
899 char * desc = ReadDoc(module, classDoc, cl, description, null);
903 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
904 f.Printf("<TABLE>\n");
910 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);
915 char fileName[MAX_LOCATION];
916 FigureFileName(fileName, module, classDoc, cl, description, null);
917 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
919 f.Printf("</a></TD>");
922 f.Printf("<TD valign=top height=22>%s</TD>", desc);
929 f.Printf("</TABLE><br>\n");
932 if(nameSpace->functions.first)
935 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
937 GlobalFunction function = link.data;
938 char * desc = ReadDoc(module, functionDoc, function, description, null);
939 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
940 if(name) name += 2; else name = function.name;
943 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
944 f.Printf("<TABLE>\n");
948 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);
953 char fileName[MAX_LOCATION];
954 FigureFileName(fileName, module, functionDoc, function, description, null);
955 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
957 f.Printf("</a></TD>");
960 f.Printf("<TD valign=top height=22> %s</TD>", desc);
963 f.Printf("</TR><br>\n");
966 f.Printf("</TABLE><br>\n");
969 if(nameSpace->defines.first)
972 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
974 DefinedExpression def = link.data;
975 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
978 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
979 f.Printf("<TABLE>\n");
983 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);
984 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
989 char fileName[MAX_LOCATION];
990 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
991 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
993 f.Printf("</a></TD>");
996 f.Printf("<TD valign=top height=22> %s</TD>", desc);
999 f.Printf("</TR><br>\n");
1002 f.Printf("</TABLE><br>\n");
1005 f.Printf("</FONT></BODY></HTML>\n");
1009 class APIPageClass : APIPage
1018 NameSpace * GetNameSpace()
1020 return cl.nameSpace;
1023 void Generate(File f)
1028 char nsName[1024], temp[1024];
1029 NameSpace * ns = cl.nameSpace;
1030 Module module = cl.module;
1033 while(ns && ns->name)
1035 strcpy(temp, ns->name);
1036 if(nsName[0]) strcat(temp, "::");
1037 strcat(temp, nsName);
1038 strcpy(nsName, temp);
1041 // Generate Class Page
1042 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1043 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1045 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);
1047 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1050 const char * classType = null;
1054 classType = $"Bit Collection";
1057 classType = $"Enumeration";
1060 classType = $"Structure";
1063 classType = $"Class";
1066 classType = $"Class (No header)";
1069 classType = $"Unit";
1072 classType = $"Basic Data Type";
1075 f.Printf($"Type: %s<br>\n", classType);
1078 if(cl.type != systemClass && cl.base)
1080 f.Printf($"Base Class: ");
1081 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1083 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1085 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1086 f.Printf("%s", cl.dataTypeString);
1088 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1093 char * desc = ReadDoc(module, classDoc, cl, description, null);
1096 f.Printf($"<br><H3>Description</H3><br><br>\n");
1099 char fileName[MAX_LOCATION];
1100 FigureFileName(fileName, module, classDoc, cl, description, null);
1101 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1103 f.Printf("</a><br><br>");
1106 f.Printf("%s<br><br>", desc);
1111 if(cl.type == enumClass)
1113 EnumClassData enumeration = (EnumClassData)cl.data;
1114 if(enumeration.values.first)
1118 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
1119 f.Printf("<TABLE>\n");
1121 for(item = enumeration.values.first; item; item = item.next)
1123 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1124 bool needClass = true;
1127 char tempString[1024];
1129 while(base.type == enumClass) base = base.base;
1131 if(base.type == systemClass ||
1132 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1135 base.dataType = ProcessTypeString(base.dataTypeString, false);
1137 if(base.dataType.kind != classType)
1142 PrintType(base.dataType, string, false, true);
1143 classSym = FindClass(string);
1144 dataClass = classSym ? classSym.registered : null;
1147 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1153 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);
1154 if(dataClass.type == systemClass)
1157 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1160 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1162 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1164 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1169 char fileName[MAX_LOCATION];
1170 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1171 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1173 f.Printf("</a></TD>");
1176 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1181 f.Printf("</TABLE><BR>\n");
1185 if(cl.conversions.first)
1187 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
1188 f.Printf("<TABLE>\n");
1189 for(prop = cl.conversions.first; prop; prop = prop.next)
1191 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1193 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1195 Type type = ProcessTypeString(prop.name, false);
1196 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1197 if(name) name += 2; else name = prop.name;
1202 DocPrintType(type, string, true, false);
1204 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1209 char fileName[MAX_LOCATION];
1210 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1211 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1213 f.Printf("</a></TD>");
1216 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1220 f.Printf("</TR>\n");
1225 f.Printf("</TABLE><br>\n");
1228 if(cl.membersAndProperties.first)
1231 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1233 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1237 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1238 f.Printf("<TABLE>\n");
1244 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1246 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1250 DocPrintType(prop.dataType, string, true, false);
1252 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);
1253 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1258 char fileName[MAX_LOCATION];
1259 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1260 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1262 f.Printf("</a></TD>");
1265 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1268 f.Printf("</TR>\n");
1272 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1277 f.Printf("</TABLE><br>\n");
1280 if(cl.methods.first)
1284 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1286 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1288 char * desc = ReadDoc(module, methodDoc, method, description, null);
1291 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1292 f.Printf("<TABLE>\n");
1295 if(!method.dataType)
1296 ProcessMethodType(method);
1299 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);
1304 char fileName[MAX_LOCATION];
1305 FigureFileName(fileName, module, methodDoc, method, description, null);
1306 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1308 f.Printf("</a></TD>");
1311 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1314 f.Printf("</TR><br>\n");
1318 f.Printf("</TABLE><br>\n");
1320 // Non-Virtual Methods
1322 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1324 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1326 char * desc = ReadDoc(module, methodDoc, method, description, null);
1329 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1330 f.Printf("<TABLE>\n");
1334 if(!method.dataType)
1335 ProcessMethodType(method);
1338 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);
1343 char fileName[MAX_LOCATION];
1344 FigureFileName(fileName, module, methodDoc, method, description, null);
1345 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1347 f.Printf("</a></TD>");
1350 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1354 f.Printf("</TR><br>\n");
1358 f.Printf("</TABLE><br>\n");
1361 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1364 f.Printf($"<H3>Usage</H3><br>\n");
1367 char fileName[MAX_LOCATION];
1368 FigureFileName(fileName, module, classDoc, cl, usage, null);
1369 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1374 f.Printf("<br>%s\n", usageDoc);
1375 f.Printf("<br><br>\n");
1380 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1383 f.Printf($"<H3>Example</H3><br>\n");
1384 f.Printf($"<FONT face=\"Courier New\">\n");
1385 f.Printf("<br><TABLE>\n");
1388 char fileName[MAX_LOCATION];
1389 FigureFileName(fileName, module, classDoc, cl, example, null);
1390 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1392 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1395 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1397 f.Printf("</TABLE></FONT>\n");
1403 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1407 f.Printf($"<H3>Remarks</H3><br>\n");
1410 char fileName[MAX_LOCATION];
1411 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1412 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1417 f.Printf("<br>%s\n", remarksDoc);
1418 f.Printf("<br><br>\n");
1423 if(cl.type != systemClass)
1427 for(c = cl.derivatives.first; c; c = c.next)
1429 Class deriv = c.data;
1430 // TO VERIFY: Does this properly check public status?
1431 if(eSystem_FindClass(componentsApp, deriv.fullName))
1435 f.Printf($"<H3>Derived Classes</H3><br>\n");
1441 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1445 f.Printf("<br><br>\n");
1448 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1451 f.Printf($"<H3>See Also</H3><br>\n");
1454 char fileName[MAX_LOCATION];
1455 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1456 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1461 f.Printf("<br>%s\n", seeAlsoDoc);
1462 f.Printf("<br><br>\n");
1466 f.Printf("</FONT></BODY></HTML>\n");
1470 class APIPageMethod : APIPage
1476 return method._class.module;
1479 NameSpace * GetNameSpace()
1481 return method._class.nameSpace;
1484 void Generate(File f)
1486 Class cl = method._class;
1488 Module module = cl.module;
1490 char nsName[1024], temp[1024];
1491 NameSpace * ns = cl.nameSpace;
1494 while(ns && ns->name)
1496 strcpy(temp, ns->name);
1497 if(nsName[0]) strcat(temp, "::");
1498 strcat(temp, nsName);
1499 strcpy(nsName, temp);
1503 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1504 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1506 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);
1508 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1509 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1510 if(method.dataType.staticMethod)
1512 f.Printf($"this pointer class: None<br>\n");
1514 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1516 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);
1519 // Generate Method Page
1521 if(!method.dataType.name)
1522 method.dataType.name = CopyString(method.name);
1523 DocPrintType(method.dataType, string, true, false);
1524 f.Printf("<br>%s", string);
1527 char * desc = ReadDoc(module, methodDoc, method, description, null);
1530 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1533 char fileName[MAX_LOCATION];
1534 FigureFileName(fileName, module, methodDoc, method, description, null);
1535 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1540 f.Printf("%s", desc);
1545 f.Printf("<br><br>\n");
1546 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1548 f.Printf($"<H3>Parameters</H3><br><br>\n");
1550 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1551 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1553 f.Printf("<TABLE valign=center>\n");
1556 for(param = method.dataType.params.first; param; param = param.next)
1558 // ADD DESCRIPTION HERE
1559 if(param.kind != voidType)
1561 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1564 DocPrintType(param, string, false, false);
1566 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1567 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1572 char fileName[MAX_LOCATION];
1573 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1574 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1576 f.Printf("</a></TD>\n");
1579 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1583 f.Printf("</TR>\n");
1586 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1588 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1589 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1591 f.Printf("<TR><TD> </TD></TR>");
1594 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1596 DocPrintType(method.dataType.returnType, string, false, false);
1597 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1602 char fileName[MAX_LOCATION];
1603 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1604 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1606 f.Printf("</a> </TD>\n");
1609 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1612 f.Printf("</TR>\n");
1613 f.Printf("</TABLE>\n");
1615 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1616 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1618 f.Printf("</TABLE><br>\n");
1621 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1624 f.Printf($"<H3>Usage</H3><br>\n");
1627 char fileName[MAX_LOCATION];
1628 FigureFileName(fileName, module, methodDoc, method, usage, null);
1629 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1634 f.Printf("<br>%s\n", usageDoc);
1635 f.Printf("<br><br>\n");
1640 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1643 f.Printf($"<H3>Example</H3><br>\n");
1644 f.Printf($"<FONT face=\"Courier New\">\n");
1645 f.Printf("<br><TABLE>\n");
1648 char fileName[MAX_LOCATION];
1649 FigureFileName(fileName, module, methodDoc, method, example, null);
1650 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1652 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1655 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1656 f.Printf("</TABLE></FONT>\n");
1662 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1665 f.Printf($"<H3>Remarks</H3><br>\n");
1668 char fileName[MAX_LOCATION];
1669 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1670 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1675 f.Printf("<br>%s\n", method, remarksDoc);
1676 f.Printf("<br><br>\n");
1681 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1684 f.Printf($"<H3>See Also</H3><br>\n");
1687 char fileName[MAX_LOCATION];
1688 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1689 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1694 f.Printf("<br>%s\n", method, seeAlsoDoc);
1696 f.Printf("<br><br>\n");
1700 f.Printf("</FONT></BODY></HTML>\n");
1704 class APIPageFunction : APIPage
1706 GlobalFunction function;
1710 return function.module;
1713 NameSpace * GetNameSpace()
1715 return function.nameSpace;
1718 void Generate(File f)
1721 Module module = function.module;
1723 char nsName[1024], temp[1024];
1724 NameSpace * ns = function.nameSpace;
1727 while(ns && ns->name)
1729 strcpy(temp, ns->name);
1730 if(nsName[0]) strcat(temp, "::");
1731 strcat(temp, nsName);
1732 strcpy(nsName, temp);
1736 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1737 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1739 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);
1742 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1744 if(!function.dataType)
1745 function.dataType = ProcessTypeString(function.dataTypeString, false);
1747 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1749 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);
1752 // Generate Method Page
1754 if(!function.dataType.name)
1755 function.dataType.name = CopyString(function.name);
1756 DocPrintType(function.dataType, string, true, false);
1757 f.Printf("<br>%s", string);
1760 char * desc = ReadDoc(module, functionDoc, function, description, null);
1763 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1766 char fileName[MAX_LOCATION];
1767 FigureFileName(fileName, module, functionDoc, function, description, null);
1768 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1773 f.Printf("%s", desc);
1777 f.Printf("<br><br>\n");
1778 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1780 f.Printf($"<H3>Parameters</H3><br><br>\n");
1782 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1783 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1785 f.Printf("<TABLE valign=center>\n");
1788 for(param = function.dataType.params.first; param; param = param.next)
1790 // ADD DESCRIPTION HERE
1791 if(param.kind != voidType)
1793 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1796 DocPrintType(param, string, false, false);
1798 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1799 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1804 char fileName[MAX_LOCATION];
1805 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1806 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1809 f.Printf("</a> </TD>\n");
1812 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1815 f.Printf("</TR>\n");
1818 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1820 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1821 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1823 f.Printf("<TR><TD> </TD></TR>");
1826 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1828 DocPrintType(function.dataType.returnType, string, false, false);
1829 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1834 char fileName[MAX_LOCATION];
1835 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1836 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1838 f.Printf("</a> </TD>\n");
1841 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1844 f.Printf("</TR>\n");
1845 f.Printf("</TABLE>\n");
1847 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1848 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1850 f.Printf("</TABLE><br>\n");
1853 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1856 f.Printf($"<H3>Usage</H3><br>\n");
1859 char fileName[MAX_LOCATION];
1860 FigureFileName(fileName, module, functionDoc, function, usage, null);
1861 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1866 f.Printf("<br>%s\n", usageDoc);
1867 f.Printf("<br><br>\n");
1872 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1875 f.Printf($"<H3>Example</H3><br>\n");
1876 f.Printf($"<FONT face=\"Courier New\">\n");
1877 f.Printf("<br><TABLE>\n");
1880 char fileName[MAX_LOCATION];
1881 FigureFileName(fileName, module, functionDoc, function, example, null);
1882 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1884 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1887 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1888 f.Printf("</TABLE></FONT>\n");
1894 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1897 f.Printf($"<H3>Remarks</H3><br>\n");
1900 char fileName[MAX_LOCATION];
1901 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1902 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1907 f.Printf("<br>%s\n", remarksDoc);
1908 f.Printf("<br><br>\n");
1913 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1916 f.Printf($"<H3>See Also</H3><br>\n");
1919 char fileName[MAX_LOCATION];
1920 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1921 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1926 f.Printf("<br>%s\n", seeAlsoDoc);
1927 f.Printf("<br><br>\n");
1931 f.Printf("</FONT></BODY></HTML>\n");
1935 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1939 NameSpace * nameSpace = mainNameSpace;
1941 DataRow classesRow = null;
1942 DataRow functionsRow = null, definesRow = null;
1945 strcpy(nsName, parentName ? parentName : "");
1949 strcat(nsName, "::");
1950 strcat(nsName, nameSpace->name);
1955 row = parentRow.AddRow();
1956 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1957 row.tag = (int64)nameSpace;
1958 row.icon = mainForm.icons[typeNameSpace];
1962 // "Global NameSpace"
1964 page = parentRow.GetData(null);
1967 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1969 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1970 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1972 if(comNameSpace != null)
1974 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1976 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1978 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1983 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1985 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1987 if(nameSpace->classes.first)
1991 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1994 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1996 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1997 AddClass(classesRow, module, cl, nsName, showPrivate);
2004 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2006 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2008 if(nameSpace->functions.first)
2012 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2015 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2017 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2019 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2020 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2027 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2029 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2031 if(nameSpace->defines.first)
2035 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2038 //if(def.module == module)
2040 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2042 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2043 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2051 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2055 if(!member.dataType)
2056 member.dataType = ProcessTypeString(member.dataTypeString, false);
2060 DocPrintType(member.dataType, string, true, false);
2062 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2063 for(c = 0; c<indent; c++)
2064 f.Printf(" ");
2065 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2066 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2067 if(member.type == normalMember)
2069 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2074 char fileName[MAX_LOCATION];
2075 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2076 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2078 f.Printf("</a></TD>");
2081 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2086 f.Printf("<TD valign=top height=22></TD>");
2088 if(member.type != normalMember)
2090 DataMember subMember;
2091 for(subMember = member.members.first; subMember; subMember = subMember.next)
2093 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2095 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2099 f.Printf("</TR><br>\n");
2102 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2105 if(member.type == normalMember)
2107 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2108 row.tag = (int64)member;
2113 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2114 row.icon = mainForm.icons[typeData];
2115 row.tag = (int64)member;
2117 for(m = member.members.first; m; m = m.next)
2119 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2120 AddDataMember(row, page, m);
2125 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2130 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2131 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2134 row = parentRow.AddRow();
2135 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2136 row.tag = (int64)cl;
2137 row.collapsed = true;
2138 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2141 if(cl.methods.first)
2143 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2145 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2148 if(!method.dataType)
2149 ProcessMethodType(method);
2150 if(method.type == virtualMethod)
2152 if(method.dataType.thisClass)
2154 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2155 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2156 mRow.tag = (int64)method;
2160 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2161 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2162 mRow.tag = (int64)method;
2167 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2168 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2169 mRow.tag = (int64)method;
2175 if(cl.membersAndProperties.first)
2177 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2179 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2182 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2186 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2187 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2188 mRow.tag = (int64)prop;
2192 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2193 AddDataMember(membersRow, page, (DataMember)prop);
2199 if(cl.conversions.first)
2201 for(prop = cl.conversions.first; prop; prop = prop.next)
2205 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2206 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2207 if(name) name += 2; else name = prop.name;
2208 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2209 mRow.tag = (int64)prop;
2212 if(cl.type == enumClass)
2214 EnumClassData enumeration = (EnumClassData)cl.data;
2216 for(item = enumeration.values.first; item; item = item.next)
2219 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2220 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2221 mRow.tag = (int64)item;
2226 class AddressBar : Window
2228 background = activeBorder;
2232 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2234 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2236 MainForm mainForm = (MainForm)parent;
2237 FileDialog fileDialog = mainForm.fileDialog;
2238 if(fileDialog.Modal() == ok)
2239 mainForm.OpenModule(fileDialog.filePath);
2245 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2248 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2250 ((MainForm)parent).Back();
2256 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2259 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2261 ((MainForm)parent).Forward();
2267 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2269 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2271 ((MainForm)parent).Home();
2275 /* TODO: Search (#143/#441)
2276 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2277 Update this in the NotifyUpdate. Enter goes to the exact match.
2279 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2283 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2285 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2287 if(!disabled && (SmartKey)key == enter)
2288 ((MainForm)parent).Go(editBox.contents);
2292 void NotifyUpdate(EditBox editBox)
2294 String location = ((MainForm)parent).view.location;
2295 disabled = !strcmp(location ? location : "", editBox.contents);
2300 bool OnKeyHit(Key key, unichar ch)
2303 ((MainForm)parent).view.MakeActive();
2308 class MainForm : Window
2310 size = { 1000, 600 };
2312 borderStyle = sizable;
2315 icon = { ":documentorIcon.png" };
2316 text = $"API Documentation Browser";
2318 BitmapResource icons[CodeObjectType];
2323 for(c = 0; c < CodeObjectType::enumSize; c++)
2325 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2327 browser.AddField(DataField { dataType = class(APIPage) });
2332 Menu fileMenu { menu, $"File", f };
2333 Array<FileFilter> fileFilters
2335 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2336 { $"eC Symbol files (*.sym)", "sym" }
2339 FileDialog fileDialog
2341 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2343 MenuItem fileOpenItem
2345 fileMenu, $"Open...", o, ctrlO;
2347 bool NotifySelect(MenuItem selection, Modifiers mods)
2349 if(fileDialog.Modal() == ok)
2351 OpenModule(fileDialog.filePath);
2356 MenuItem fileSettingsItem
2358 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2360 bool NotifySelect(MenuItem selection, Modifiers mods)
2362 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2372 MenuDivider { fileMenu };
2373 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2375 void OpenModule(const char * filePath)
2377 char moduleName[MAX_LOCATION];
2378 char extension[MAX_EXTENSION];
2379 Module module = null;
2380 static char symbolsDir[MAX_LOCATION];
2383 modulesAdded.RemoveAll();
2385 FreeContext(globalContext);
2386 FreeExcludedSymbols(excludedSymbols);
2387 ::defines.Free(FreeModuleDefine);
2388 imports.Free(FreeModuleImport);
2390 FreeGlobalData(globalData);
2394 FreeTypeData(componentsApp);
2395 delete componentsApp;
2398 componentsApp = __ecere_COM_Initialize(false, 1, null);
2399 SetPrivateModule(componentsApp);
2401 StripLastDirectory(filePath, symbolsDir);
2402 SetSymbolsDir(symbolsDir);
2404 GetExtension(filePath, extension);
2406 mainForm.browser.Clear();
2408 ImportModule(filePath, normalImport, publicAccess, false);
2410 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2411 componentsApp.name = CopyString(filePath);
2413 for(module = componentsApp.allModules.first; module; module = module.next)
2415 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2419 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2420 AddComponents(componentsApp, false);
2422 GetLastDirectory(filePath, moduleName);
2423 // Extension, path and lib prefix get removed in Module::name
2426 StripExtension(moduleName);
2427 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2429 int len = strlen(moduleName) - 3;
2430 memmove(moduleName, moduleName + 3, len);
2431 moduleName[len] = 0;
2435 for(module = componentsApp.allModules.first; module; module = module.next)
2437 if(module.name && (!strcmp(module.name, moduleName)))
2440 if(!module) module = componentsApp;
2441 homeModule = module;
2442 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2444 SetSymbolsDir(null);
2447 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2450 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2451 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2454 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2456 APIPage page = row.GetData(null);
2457 if(view.edit) view.OnLeftButtonDown(0,0,0);
2458 if(page && page.page) page = page.page;
2460 view.PositionCaret(true);
2461 if(page != view.page)
2463 Window activeChild = this.activeChild;
2465 // Back / Forward Support
2466 if(row && !dontRecordHistory)
2468 if(history.count > historyPos+1)
2469 history.count = historyPos+1;
2470 historyPos = history.count-1;
2471 addressBar.back.disabled = (historyPos == 0);
2472 addressBar.forward.disabled = (historyPos >= history.count-1);
2474 history.Add((Instance)(uint64)row.tag);
2475 historyPos = history.count-1;
2477 addressBar.back.disabled = (historyPos == 0);
2478 addressBar.forward.disabled = (historyPos >= history.count-1);
2484 activeChild.Activate();
2486 else if(!view.created)
2490 page = row.GetData(null);
2491 if(page && page.page)
2495 case 1: view.GoToAnchor("Classes"); break;
2496 case 2: view.GoToAnchor("Functions"); break;
2497 case 3: view.GoToAnchor("Definitions"); break;
2498 case 4: view.GoToAnchor("VirtualMethods"); break;
2499 case 5: view.GoToAnchor("Methods"); break;
2500 case 6: view.GoToAnchor("Members"); break;
2501 case 7: view.GoToAnchor("Conversions"); break;
2502 case 8: view.GoToAnchor("EnumerationValues"); break;
2506 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2507 view.GoToAnchor(hex);
2513 view.SetScrollPosition(0, 0);
2521 this, anchor = { top = 26, bottom = 0, right = 0 };
2526 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2529 bool OnClose(bool parentClosing)
2532 view.OnLeftButtonDown(0,0,0);
2538 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2539 //mainForm.OpenModule("ec");
2540 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2541 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2543 int index = mainForm.browser.currentRow.index;
2544 int rowHeight = mainForm.browser.rowHeight;
2545 int height = mainForm.browser.clientSize.h;
2547 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2552 Array<Instance> history { };
2554 bool dontRecordHistory;
2559 if(historyPos < history.count-1)
2563 addressBar.back.disabled = (historyPos == 0);
2564 addressBar.forward.disabled = (historyPos >= history.count-1);
2565 sprintf(location, "api://%p", history[historyPos]);
2566 dontRecordHistory = true;
2567 view.OnOpen(location);
2568 dontRecordHistory = false;
2580 addressBar.back.disabled = (historyPos == 0);
2581 addressBar.forward.disabled = (historyPos >= history.count-1);
2582 sprintf(location, "api://%p", history[historyPos]);
2583 dontRecordHistory = true;
2584 view.OnOpen(location);
2585 dontRecordHistory = false;
2593 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2597 class EditDialog : Window
2599 borderStyle = sizable;
2600 size = { 600, 400 };
2605 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2609 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2613 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2617 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2618 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2620 class HelpView : HTMLView
2624 hasVertScroll = true;
2625 hasHorzScroll = true;
2627 char editString[MAX_LOCATION];
2633 page = mainForm.browser.currentRow.GetData(null);
2638 char docDir[MAX_LOCATION];
2640 strcpy(docDir, settings.docDir);
2641 if(FileExists(docDir).isDirectory)
2643 PathCatSlash(docDir, "___docWriteTest");
2644 if(FileExists(docDir).isDirectory)
2647 if(!FileExists(docDir))
2653 if(FileExists(docDir).isDirectory)
2665 GoToAnchor(page.label);
2667 if(page.page) page = page.page;
2670 return HTMLView::OnCreate();
2681 String contents = null;
2684 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2686 if(block.type == TEXT && block.textLen)
2694 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2696 if(block.type == BR)
2698 else if(block.type == TEXT)
2699 f.Write(block.text, 1, block.textLen);
2703 if((len = f.GetSize()))
2705 contents = new char[len+1];
2706 f.Read(contents, 1, len);
2707 contents[len] = '\0';
2711 char docPath[MAX_LOCATION];
2712 char temp[MAX_LOCATION];
2713 char part[MAX_FILENAME];
2717 DocumentationType type;
2718 DocumentationItem item;
2720 NamespaceDoc nsDoc = null;
2721 ClassDoc clDoc = null;
2722 FunctionDoc fnDoc = null;
2723 MethodDoc mdDoc = null;
2725 Method method = null;
2726 GlobalFunction function = null;
2728 strcpy(temp, editString);
2729 SplitDirectory(temp, part, temp);
2730 module = (Module)strtoull(part, null, 16);
2731 SplitDirectory(temp, part, temp);
2732 object = (void *)strtoull(part, null, 16);
2733 SplitDirectory(temp, part, temp);
2734 data = (void *)strtoull(part, null, 16);
2735 SplitDirectory(temp, part, temp);
2736 if(!strcmp(part, "namespace"))
2737 type = nameSpaceDoc;
2738 else if(!strcmp(part, "function"))
2740 else if(!strcmp(part, "class"))
2742 else if(!strcmp(part, "method"))
2744 SplitDirectory(temp, part, temp);
2745 if(!strcmp(part, "description"))
2747 else if(!strcmp(part, "usage"))
2749 else if(!strcmp(part, "remarks"))
2751 else if(!strcmp(part, "example"))
2753 else if(!strcmp(part, "seeAlso"))
2755 else if(!strcmp(part, "enumerationValue"))
2756 item = enumerationValue;
2757 else if(!strcmp(part, "definition"))
2759 else if(!strcmp(part, "conversion"))
2761 else if(!strcmp(part, "memberDescription"))
2762 item = memberDescription;
2763 else if(!strcmp(part, "propertyDescription"))
2764 item = propertyDescription;
2765 else if(!strcmp(part, "parameter"))
2767 else if(!strcmp(part, "returnValue"))
2770 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2772 /* Why invalidate this entry here?
2774 MapIterator<const String, DocCacheEntry> it { map = docCache };
2775 if(it.Index(docPath, false))
2784 case classDoc: cl = (Class)object; break;
2785 case functionDoc: function = object; break;
2786 case methodDoc: method = object; cl = method._class; break;
2791 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2793 clDoc = (ClassDoc)doc;
2795 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2797 nsDoc = (NamespaceDoc)doc;
2803 if(type == functionDoc)
2805 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2806 if(name) name += 2; else name = function.name;
2807 fnDoc = nsDoc.functions ? nsDoc.functions[name] : null;
2808 if(!empty && !fnDoc)
2810 if(!nsDoc.functions) nsDoc.functions = { };
2811 nsDoc.functions[name] = fnDoc = { };
2814 else if(type == methodDoc)
2816 mdDoc = clDoc.methods ? clDoc.methods[method.name] : null;
2817 if(!empty && !mdDoc)
2819 if(!clDoc.methods && !empty) clDoc.methods = { };
2820 clDoc.methods[method.name] = mdDoc = { };
2824 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2829 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2830 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2831 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2832 else { nsDoc.description = contents; contents = null; }
2835 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2836 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2837 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2840 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2841 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2842 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2845 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2846 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2847 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2850 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2851 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2852 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2855 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2856 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2858 case enumerationValue:
2860 ValueDoc itDoc = clDoc.values ? clDoc.values[((NamedLink)data).name] : null;
2863 if(!empty && !itDoc)
2865 if(!clDoc.values) clDoc.values = { };
2866 clDoc.values[((NamedLink)data).name] = itDoc = { };
2868 itDoc.description = contents; contents = null;
2871 MapIterator<String, ValueDoc> it { map = clDoc.values };
2872 if(it.Index(((NamedLink)data).name, false))
2881 DefineDoc itDoc = nsDoc.defines ? nsDoc.defines[((Definition)data).name] : null;
2884 if(!empty && !itDoc)
2886 if(!nsDoc.defines) nsDoc.defines = { };
2887 nsDoc.defines[((Definition)data).name] = itDoc = { };
2889 itDoc.description = contents; contents = null;
2892 MapIterator<String, DefineDoc> it { map = nsDoc.defines };
2893 if(it.Index(((Definition)data).name, false))
2902 ConversionDoc itDoc;
2903 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2904 if(name) name += 2; else name = ((Property)data).name;
2905 itDoc = clDoc.conversions ? clDoc.conversions[name] : null;
2908 if(!empty && !itDoc)
2910 if(!clDoc.conversions) clDoc.conversions = { };
2911 clDoc.conversions[name] = itDoc = { };
2913 itDoc.description = contents; contents = null;
2916 MapIterator<String, ConversionDoc> it { map = clDoc.conversions };
2917 if(it.Index(name, false))
2924 case memberDescription:
2926 FieldDoc itDoc = clDoc.fields ? clDoc.fields[((DataMember)data).name] : null;
2929 if(!empty && !itDoc)
2931 if(!clDoc.fields) clDoc.fields = { };
2932 clDoc.fields[((DataMember)data).name] = itDoc = { };
2934 itDoc.description = contents; contents = null;
2937 MapIterator<String, FieldDoc> it { map = clDoc.fields };
2938 if(it.Index(((DataMember)data).name, false))
2945 case propertyDescription:
2947 PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null;
2950 if(!empty && !itDoc)
2952 if(!clDoc.properties) clDoc.properties = { };
2953 clDoc.properties[((Property)data).name] = itDoc = { };
2955 itDoc.description = contents, contents = null;
2958 MapIterator<String, PropertyDoc> it { map = clDoc.properties };
2959 if(it.Index(((Property)data).name, false))
2968 if(type == functionDoc || type == methodDoc)
2970 Map<String, ParameterDoc> * parameters = (type == functionDoc) ? &fnDoc.parameters : &mdDoc.parameters;
2971 char * name = ((Type)data).name;
2972 ParameterDoc itDoc = *parameters ? (*parameters)[name] : null;
2975 while(prev) position++, prev = prev.prev;
2979 if(!empty && !itDoc)
2981 if(!*parameters) *parameters = { };
2982 (*parameters)[name] = itDoc = { };
2984 itDoc.description = contents; contents = null;
2985 itDoc.position = position;
2988 MapIterator<String, ParameterDoc> it { map = *parameters };
2989 if(it.Index(((Type)data).name, false))
3001 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
3003 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
3004 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
3005 if(name) name += 2; else name = function.name;
3006 if(it.Index(name, false))
3010 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
3012 MapIterator<String, MethodDoc> it { map = clDoc.methods };
3013 if(it.Index(method.name, false))
3019 if(nsDoc.functions && !nsDoc.functions.count) delete nsDoc.functions;
3020 if(nsDoc.defines && !nsDoc.defines.count) delete nsDoc.defines;
3024 if(clDoc && clDoc.conversions && !clDoc.conversions.count) delete clDoc.conversions;
3025 if(clDoc && clDoc.properties && !clDoc.properties.count) delete clDoc.properties;
3026 if(clDoc && clDoc.fields && !clDoc.fields.count) delete clDoc.fields;
3027 if(clDoc && clDoc.methods && !clDoc.methods.count) delete clDoc.methods;
3028 if(clDoc && clDoc.values && !clDoc.values.count) delete clDoc.values;
3033 char dirPath[MAX_LOCATION];
3034 StripLastDirectory(docPath, dirPath);
3035 if(FileExists(docPath))
3036 DeleteFile(docPath);
3037 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
3040 if(!FileExists(dirPath))
3042 if((f = FileOpen(docPath, write)))
3044 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3048 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3057 Block parent = textBlock.parent;
3058 while((block = parent.subBlocks.first))
3060 parent.subBlocks.Remove(block);
3063 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3064 textBlock.text = CopyString($"[Add Text]");
3065 textBlock.textLen = strlen(textBlock.text);
3066 parent.subBlocks.Add(textBlock);
3074 PositionCaret(true);
3079 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3083 if(edit && (!textBlock || overLink != textBlock.parent))
3087 HTMLView::OnLeftButtonDown(x, y, mods);
3088 selPosition = curPosition = 0;
3089 selBlock = textBlock;
3093 result = HTMLView::OnLeftButtonDown(x, y, mods);
3095 if(!edit && clickedLink)
3098 if(clickedLink == overLink && clickedLink.href)
3100 if(OnOpen(clickedLink.href))
3108 if(textBlock && overLink == textBlock.parent)
3110 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3111 selBlock = textBlock;
3112 PositionCaret(true);
3120 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3122 if(!edit || !textBlock || clickedLink != textBlock.parent)
3124 HTMLView::OnLeftButtonUp(x, y, mods);
3127 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3128 selBlock = textBlock;
3129 PositionCaret(true);
3140 bool OnMouseMove(int x, int y, Modifiers mods)
3142 if(edit && selecting)
3144 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3145 PositionCaret(true);
3148 return HTMLView::OnMouseMove(x, y, mods);
3151 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3153 if(edit && textBlock)
3159 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3160 selBlock = textBlock;
3161 for(c = curPosition; c >= 0; c--)
3164 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3165 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3166 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3172 for(c = start; c < textBlock.textLen; c += numBytes)
3174 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3175 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3178 selPosition = start;
3181 PositionCaret(true);
3189 bool OnOpen(char * href)
3191 if(!strncmp(href, "api://", 6))
3193 int64 tag = (int64)strtoull(href + 6, null, 16);
3194 DataRow row = mainForm.browser.FindSubRow(tag);
3198 mainForm.browser.SelectRow(row);
3199 while((row = row.parent))
3200 row.collapsed = false;
3201 row = mainForm.browser.currentRow;
3202 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3205 else if(!strncmp(href, "edit://", 7))
3208 int startX = clickedLink.startX, startY = clickedLink.startY;
3209 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3211 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3212 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3214 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3216 display.FontExtent(block.font.font, " ", 1, null, &th);
3219 block.parent.subBlocks.Insert(null, newBlock);
3224 block.parent.subBlocks.Insert(block, newBlock);
3225 startY += block.prev.height;
3227 newBlock.startX = startX;
3228 newBlock.startY = startY;
3229 newBlock.text = new0 char[1];
3233 textBlock = (Block)clickedLink.subBlocks.first;
3234 if(!strcmp(textBlock.text, $"[Add Text]"))
3236 textBlock.text[0] = 0;
3237 textBlock.textLen = 0;
3240 strcpy(editString, href + 7);
3241 selPosition = curPosition = 0;
3242 selBlock = textBlock;
3245 // PositionCaret(true);
3252 void DeleteSelection()
3254 if(textBlock != selBlock || curPosition != selPosition)
3256 if(textBlock == selBlock)
3258 // Within same block
3259 int start = Min(curPosition, selPosition);
3260 int end = Max(curPosition, selPosition);
3261 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3262 textBlock.textLen -= end-start;
3263 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3264 curPosition = start;
3265 selPosition = start;
3269 int startSel, endSel;
3270 Block startSelBlock = null, endSelBlock = null, b, next;
3272 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3274 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3275 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3277 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3278 for(b = startSelBlock.next; b; b = next)
3280 bool isEnd = b == endSelBlock;
3281 next = GetNextBlock(b);
3282 b.parent.subBlocks.Remove(b);
3287 textBlock = startSelBlock;
3288 selBlock = startSelBlock;
3289 curPosition = startSel;
3290 selPosition = startSel;
3294 PositionCaret(true);
3299 String GetSelectionString()
3301 String selection = null;
3302 if(textBlock == selBlock)
3304 // Within same block
3305 int start = Min(curPosition, selPosition);
3306 int end = Max(curPosition, selPosition);
3307 int len = end - start;
3308 selection = new char[len + 1];
3309 memcpy(selection, textBlock.text + start, len);
3314 int startSel, endSel;
3315 Block startSelBlock = null, endSelBlock = null, b;
3318 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3321 for(b = startSelBlock; b; b = GetNextBlock(b))
3323 int start = (b == startSelBlock) ? startSel : 0;
3324 int end = (b == endSelBlock) ? endSel : b.textLen;
3325 int len = end - start;
3327 if(b == endSelBlock)
3329 else if(b.type == TEXT)
3333 selection = new char[totalLen + 1];
3335 for(b = startSelBlock; b; b = GetNextBlock(b))
3337 int start = (b == startSelBlock) ? startSel : 0;
3338 int end = (b == endSelBlock) ? endSel : b.textLen;
3339 int len = end - start;
3340 memcpy(selection + totalLen, b.text + start, len);
3342 if(b == endSelBlock)
3344 else if(b.type == TEXT)
3345 selection[totalLen++] = '\n';
3347 selection[totalLen] = 0;
3352 void CopySelection()
3354 String s = GetSelectionString();
3357 int len = strlen(s);
3359 if(cb.Allocate(len + 1))
3361 memcpy(cb.text, s, len + 1);
3369 bool OnKeyDown(Key key, unichar ch)
3376 OnLeftButtonDown(0,0,0);
3378 case Key { end, shift = true }:
3380 curPosition = textBlock.textLen;
3383 selPosition = curPosition;
3384 selBlock = textBlock;
3386 PositionCaret(true);
3389 case Key { home, shift = true }:
3394 selPosition = curPosition;
3395 selBlock = textBlock;
3397 PositionCaret(true);
3400 case Key { home, ctrl = true, shift = true }:
3403 while(textBlock.prev)
3404 textBlock = textBlock.prev.prev;
3407 selPosition = curPosition;
3408 selBlock = textBlock;
3410 PositionCaret(true);
3413 case Key { end, ctrl = true, shift = true }:
3415 while(textBlock.next && textBlock.next.next)
3416 textBlock = textBlock.next.next;
3417 curPosition = textBlock.textLen;
3420 selPosition = curPosition;
3421 selBlock = textBlock;
3423 PositionCaret(true);
3429 return HTMLView::OnKeyDown(key, ch);
3433 bool OnKeyHit(Key key, unichar ch)
3439 case Key { up, shift = true }:
3442 if(caretY == textBlock.startY)
3446 textBlock = textBlock.prev.prev;
3447 curPosition = Min(curPosition, textBlock.textLen);
3450 selPosition = curPosition;
3451 selBlock = textBlock;
3454 PositionCaret(false);
3464 int sx = textBlock.startX, sy = textBlock.startY;
3465 char * text = textBlock.text;
3467 Block block = textBlock;
3468 while(block && block.type != TD) block = block.parent;
3471 Block table = block;
3472 while(table && table.type != TABLE) table = table.parent;
3474 maxW = block.w - 2* table.cellPadding;
3476 maxW = clientSize.w - 10 - sx;
3479 maxW = clientSize.w - 10 - sx;
3480 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3484 int startPos = textPos;
3487 bool lineComplete = false;
3488 for(; textPos<textBlock.textLen && !lineComplete;)
3492 char * nextSpace = strchr(text + textPos, ' ');
3495 len = (nextSpace - (text + textPos)) + 1;
3497 len = textBlock.textLen - textPos;
3499 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3501 if(x + width + w > maxW && x > 0)
3503 lineComplete = true;
3513 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3516 curPosition = textPos;
3517 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3520 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3521 len = curPosition - startPos;
3522 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3526 selPosition = curPosition;
3527 selBlock = textBlock;
3531 PositionCaret(false);
3535 if(sy == caretY - th || textPos == textBlock.textLen)
3537 if(textPos != textBlock.textLen)
3539 int c = textPos - 1;
3540 while(c > 0 && text[c] == ' ') c--;
3541 curPosition = c + 1;
3544 selPosition = curPosition;
3545 selBlock = textBlock;
3551 curPosition = textBlock.textLen;
3554 selPosition = curPosition;
3555 selBlock = textBlock;
3559 PositionCaret(false);
3563 sx = textBlock.startX;
3564 } while(textPos < textBlock.textLen);
3569 case Key { down, shift = true }:
3574 int sx = textBlock.startX, sy = textBlock.startY;
3575 char * text = textBlock.text;
3577 Block block = textBlock;
3578 while(block && block.type != TD) block = block.parent;
3581 Block table = block;
3582 while(table && table.type != TABLE) table = table.parent;
3584 maxW = block.w - 2* table.cellPadding;
3586 maxW = clientSize.w - 10 - sx;
3589 maxW = clientSize.w - 10 - sx;
3590 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3592 while(!textPos || textPos < textBlock.textLen)
3594 int startPos = textPos;
3597 bool lineComplete = false;
3598 for(; (textPos < textBlock.textLen) && !lineComplete;)
3602 char * nextSpace = strchr(text + textPos, ' ');
3605 len = (nextSpace - (text + textPos)) + 1;
3607 len = textBlock.textLen - textPos;
3609 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3611 if(x + width + w > maxW && x > 0)
3613 lineComplete = true;
3623 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3625 curPosition = textPos;
3627 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3630 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3631 len = curPosition - startPos;
3632 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3636 selPosition = curPosition;
3637 selBlock = textBlock;
3640 PositionCaret(false);
3646 curPosition = textBlock.textLen;
3649 selPosition = curPosition;
3650 selBlock = textBlock;
3653 PositionCaret(false);
3656 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3660 textBlock = textBlock.next.next;
3661 sy = textBlock.startY;
3662 sx = textBlock.startX;
3663 text = textBlock.text;
3668 sx = textBlock.startX;
3672 /*if(textBlock.next && textBlock.next.next)
3674 textBlock = textBlock.next.next;
3675 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3676 selBlock = textBlock;
3677 PositionCaret(false);
3681 case Key { right, shift = true, ctrl = true }:
3684 bool foundAlpha = false;
3686 Block line, lastLine;
3689 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3691 int start = (line == textBlock) ? curPosition : 0;
3693 for(c = start; c < line.textLen; c++)
3695 char ch = line.text[c];
3696 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3697 if(key.shift ? isAlUnder : !isAlUnder)
3711 selPosition = curPosition;
3712 selBlock = textBlock;
3716 PositionCaret(true);
3721 // No next word found,
3722 if(!found && (c != curPosition || line != textBlock))
3726 lastC = line.textLen-1;
3731 curPosition = line.textLen;
3734 selPosition = curPosition;
3735 selBlock = textBlock;
3740 PositionCaret(true);
3746 if(key.shift && found)
3748 curPosition = lastC+1;
3749 textBlock = lastLine;
3750 PositionCaret(true);
3755 case Key { left, ctrl = true, shift = true }:
3758 bool foundAlpha = false;
3760 Block line, lastLine;
3763 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3766 if(curPosition == 0 && line != textBlock)
3769 lastC = line.textLen;
3773 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3774 for(c = start; c>=0; c--)
3776 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3791 // No next word found,
3792 if(!found && curPosition > 0)
3802 textBlock = lastLine;
3803 curPosition = lastC;
3806 selPosition = curPosition;
3807 selBlock = textBlock;
3809 PositionCaret(true);
3814 case Key { right, shift = true }:
3816 if(curPosition < textBlock.textLen)
3818 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3821 selPosition = curPosition;
3822 selBlock = textBlock;
3824 PositionCaret(true);
3827 else if(textBlock.next && textBlock.next.next)
3829 textBlock = textBlock.next.next;
3833 selPosition = curPosition;
3834 selBlock = textBlock;
3836 PositionCaret(true);
3840 case Key { left, shift = true }:
3844 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3847 selPosition = curPosition;
3848 selBlock = textBlock;
3850 PositionCaret(true);
3853 else if(textBlock.prev)
3855 textBlock = textBlock.prev.prev;
3856 curPosition = textBlock.textLen;
3859 selPosition = curPosition;
3860 selBlock = textBlock;
3862 PositionCaret(true);
3868 if(textBlock == selBlock && curPosition == selPosition)
3872 int c = curPosition;
3874 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3875 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3876 textBlock.textLen -= nb;
3877 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3879 selPosition = curPosition;
3880 selBlock = textBlock;
3884 PositionCaret(true);
3887 else if(textBlock.prev)
3889 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3890 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3891 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3893 selPosition = curPosition = prevBlock.textLen;
3894 selBlock = textBlock;
3895 prevBlock.textLen += textBlock.textLen;
3896 textBlock.parent.subBlocks.Remove(prev);
3897 if(prev == selBlock)
3899 selBlock = textBlock;
3900 selPosition = curPosition;
3903 textBlock.parent.subBlocks.Remove(textBlock);
3904 if(textBlock == selBlock)
3906 selBlock = prevBlock;
3907 selPosition = curPosition;
3910 textBlock = prevBlock;
3914 PositionCaret(true);
3923 if(textBlock != selBlock || curPosition != selPosition)
3925 else if(textBlock.textLen > curPosition)
3927 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3928 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3929 textBlock.textLen -= nb;
3930 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3935 PositionCaret(true);
3938 else if(textBlock.next && textBlock.next.next)
3940 Block next = textBlock.next, nextBlock = textBlock.next.next;
3941 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3942 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3944 textBlock.textLen += nextBlock.textLen;
3945 textBlock.parent.subBlocks.Remove(next);
3946 if(next == selBlock)
3948 selBlock = textBlock;
3949 selPosition = curPosition;
3952 textBlock.parent.subBlocks.Remove(nextBlock);
3953 if(nextBlock == selBlock)
3955 selBlock = textBlock;
3956 selPosition = curPosition;
3962 PositionCaret(true);
3976 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3977 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3978 startY = textBlock.startY;
3979 startX = textBlock.startX;
3981 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3982 textBlock.parent.subBlocks.Insert(textBlock, block);
3983 textBlock.parent.subBlocks.Insert(block, newBlock);
3987 newBlock.textLen = textBlock.textLen - curPosition;
3988 newBlock.text = new char[newBlock.textLen+1];
3989 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3990 textBlock.textLen = curPosition;
3991 textBlock.text[curPosition] = 0;
3993 newBlock.startY = startY;
3994 newBlock.startX = startX;
3995 selPosition = curPosition = 0;
4000 textBlock = newBlock;
4001 selBlock = textBlock;
4002 PositionCaret(true);
4007 case Key { del, shift = true }:
4022 ClipBoard clipBoard { };
4023 if(clipBoard.Load())
4026 char * text = clipBoard.memory;
4034 parent = textBlock.parent;
4035 font = textBlock.font;
4040 if(ch == '\n' || ch == '\r' || !ch)
4042 int len = c - start;
4043 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4044 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4045 memcpy(textBlock.text + curPosition, text + start, len);
4046 textBlock.textLen += len;
4048 selPosition = curPosition;
4049 selBlock = textBlock;
4052 Block block { type = BR, parent = parent, font = font };
4053 Block newBlock { type = TEXT, parent = parent, font = font };
4054 int startY = textBlock.startY, startX = textBlock.startX;
4057 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4058 textBlock.parent.subBlocks.Insert(textBlock, block);
4059 textBlock.parent.subBlocks.Insert(block, newBlock);
4063 newBlock.textLen = textBlock.textLen - curPosition;
4064 newBlock.text = new char[newBlock.textLen+1];
4065 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4066 textBlock.textLen = curPosition;
4067 textBlock.text[curPosition] = 0;
4069 newBlock.startY = startY;
4070 newBlock.startX = startX;
4071 selPosition = curPosition = 0;
4072 selBlock = textBlock;
4073 textBlock = newBlock;
4075 if(ch == '\r' && text[c+1] == '\n') c++;
4081 PositionCaret(true);
4089 // eC BUG HERE: (Should be fixed)
4090 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4093 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4098 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4099 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4101 for(c = 0; c<len; c++)
4103 textBlock.text[curPosition] = string[c];
4104 textBlock.textLen++;
4107 selPosition = curPosition;
4108 selBlock = textBlock;
4111 //Clear(html.block);
4112 //CreateForms(html.block);
4117 PositionCaret(true);
4126 void OnResize(int width, int height)
4128 HTMLView::OnResize(width, height);
4129 PositionCaret(true);
4133 void PositionCaret(bool setCaretX)
4139 int sx = textBlock.startX, sy = textBlock.startY;
4140 char * text = textBlock.text;
4142 Block block = textBlock;
4143 while(block && block.type != TD) block = block.parent;
4146 Block table = block;
4147 while(table && table.type != TABLE) table = table.parent;
4149 maxW = block.w - 2* table.cellPadding;
4151 maxW = clientSize.w - 10 - sx;
4154 maxW = clientSize.w - 10 - sx;
4156 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4158 while(textPos < textBlock.textLen)
4160 int startPos = textPos;
4163 bool lineComplete = false;
4165 for(; textPos<textBlock.textLen && !lineComplete;)
4169 char * nextSpace = strchr(text + textPos, ' ');
4172 len = (nextSpace - (text + textPos)) + 1;
4174 len = textBlock.textLen - textPos;
4176 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4178 if(x + width + w > maxW && x > 0)
4180 lineComplete = true;
4193 if(curPosition < textPos || textPos == textBlock.textLen)
4195 int len = curPosition - startPos;
4196 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4201 sx = textBlock.startX;
4206 SetCaret(sx, sy, th);
4208 Point scrollPos = scroll;
4209 bool doScroll = false;
4210 if(sy - scroll.y + th > clientSize.h)
4212 scrollPos.y = sy + th - clientSize.h;
4215 else if(sy - scroll.y < 0)
4220 if(sx - scroll.x + 10 > clientSize.w)
4222 scrollPos.x = sx + 10 - clientSize.w;
4225 else if(sx - scroll.x < 10)
4227 scrollPos.x = sx - 10;
4238 // Returns a character offset into the TextBlock from a window coordinate
4239 int TextPosFromPoint(int px, int py, Block * block, bool half)
4241 Block parentBlock = this.textBlock.parent;
4244 *block = this.textBlock;
4249 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4251 int sx = textBlock.startX, sy = textBlock.startY;
4254 char * text = textBlock.text;
4256 Block b = textBlock;
4259 if(textBlock.type != TEXT) continue;
4261 while(b && b.type != TD) b = b.parent;
4265 while(table && table.type != TABLE) table = table.parent;
4267 maxW = b.w - 2* table.cellPadding;
4269 maxW = clientSize.w - 10 - sx;
4272 maxW = clientSize.w - 10 - sx;
4274 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4275 //space = space/2+2;
4278 while(textPos < textBlock.textLen)
4282 bool lineComplete = false;
4284 for(; textPos<textBlock.textLen && !lineComplete;)
4288 char * nextSpace = strchr(text + textPos, ' ');
4291 len = (nextSpace - (text + textPos)) + 1;
4293 len = textBlock.textLen - textPos;
4295 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4297 sx = x + textBlock.startX;
4298 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4303 for(c = textPos; (ch = text[c]); c += numBytes)
4305 numBytes = UTF8_NUM_BYTES(ch);
4306 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4307 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4314 if(x + width + w > maxW && x > 0)
4316 lineComplete = true;
4329 if(/*py >= sy && */py < sy + th)
4332 return textBlock.textLen;
4337 result = textBlock.textLen;
4343 Application componentsApp;
4345 class Documentor : GuiApplication
4349 Platform os = __runtimePlatform;
4350 SetGlobalContext(globalContext);
4351 SetExcludedSymbols(&excludedSymbols);
4352 SetDefines(&::defines);
4353 SetImports(&imports);
4354 SetInDocumentor(true);
4356 SetGlobalData(globalData);
4358 settingsContainer.dataOwner = &settings;
4359 settingsContainer.Load();
4360 if(!settings.docDir || !settings.docDir[0] )
4362 if(os == win32) // if Windows OS then
4364 char programFilesDir[MAX_LOCATION];
4365 char appData[MAX_LOCATION];
4366 char homeDrive[MAX_LOCATION];
4367 char winDir[MAX_LOCATION];
4368 GetEnvironment("APPDATA", appData, sizeof(appData));
4369 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4370 GetEnvironment("windir", winDir, sizeof(winDir));
4371 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4373 PathCat(programFilesDir, "ECERE SDK\\doc");
4374 settings.docDir = programFilesDir;
4376 else if(homeDrive[0])
4378 PathCat(homeDrive, "ECERE SDK\\doc");
4379 settings.docDir = homeDrive;
4383 PathCat(winDir, "..\\ECERE SDK\\doc");
4384 settings.docDir = winDir;
4387 settings.docDir = "C:\\ECERE SDK\\doc";
4389 else // if Os is Linux, or Mac OSX or something else
4390 settings.docDir = "/usr/share/ecere/doc/";
4391 settingsContainer.Save();
4397 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4399 AddComponents(module, true);
4400 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4401 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4402 while((row = row.parent))
4403 row.collapsed = false;
4407 commandThread.Create();
4411 bool Cycle(bool idle)
4414 mainForm.Destroy(0);
4423 if(commandThread.created)
4425 console.CloseInput();
4426 console.CloseOutput();
4428 commandThread.Wait();
4432 FreeContext(globalContext);
4433 FreeExcludedSymbols(excludedSymbols);
4434 ::defines.Free(FreeModuleDefine);
4435 imports.Free(FreeModuleImport);
4437 FreeGlobalData(globalData);
4438 FreeTypeData(componentsApp);
4440 delete componentsApp;
4444 ConsoleFile console { };
4445 MainForm mainForm { };
4448 Thread commandThread
4455 console.GetLine(command, sizeof(command));
4456 if(!quit && command[0])
4459 if(!strcmpi(command, "Activate"))
4460 mainForm.Activate();
4461 else if(!strcmpi(command, "Quit"))
4469 #endif // !defined(EAR_TO_ECON_ECDOC)
4474 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4475 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4479 property bool isEmpty
4485 (description && *description));
4495 class MoreDoc : ItemDoc
4498 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4499 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4500 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4501 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4507 property bool isEmpty
4512 (usage && *usage) ||
4513 (example && *example) ||
4514 (remarks && *remarks) ||
4528 class NamespaceDoc : ItemDoc
4531 Map<String, DefineDoc> defines;
4532 Map<String, FunctionDoc> functions;
4534 property bool isEmpty
4539 (defines && defines.count) ||
4540 (functions && functions.count) ||
4551 class DefineDoc : ItemDoc { }
4553 class FunctionDoc : MoreDoc
4556 Map<String, ParameterDoc> parameters;
4557 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4560 property bool isEmpty
4565 (parameters && parameters.count) ||
4566 (returnValue && *returnValue) ||
4577 class ParameterDoc : ItemDoc
4583 class ClassDoc : MoreDoc
4586 Map<String, ValueDoc> values;
4587 Map<String, FieldDoc> fields;
4588 Map<String, PropertyDoc> properties;
4589 Map<String, ConversionDoc> conversions;
4590 Map<String, MethodDoc> methods;
4592 property bool isEmpty
4597 (values && values.count) ||
4598 (fields && fields.count) ||
4599 (properties && properties.count) ||
4600 (conversions && conversions.count) ||
4601 (methods && methods.count) ||
4615 class ValueDoc : ItemDoc { }
4617 class FieldDoc : ItemDoc { }
4619 class PropertyDoc : ItemDoc { }
4621 class ConversionDoc : ItemDoc { }
4623 class MethodDoc : FunctionDoc { }
4625 char * getDocFileNameFromTypeName(const char * typeName)
4627 char * docFileName = new char[MAX_FILENAME];
4628 const char * swap = "pointer";
4629 const char * s = typeName;
4630 char * d = docFileName;
4631 const char * end = s + strlen(typeName);
4632 int swapLen = strlen(swap);
4650 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4653 Time timeStamp; // Should this be last accessed, or last retrieved?
4662 Map<String, DocCacheEntry> docCache { };