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 void AddComponents(Module module, bool isDll)
418 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
420 row = mainForm.browser.AddRow();
421 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
422 row.tag = (int64)null;
423 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
426 for(m = module.modules.first; m; m = m.next)
428 if(m.importMode == publicAccess || !isDll)
429 AddComponents(m.module, true);
432 // PUT MODULE DESCRIPTION HERE
433 if(module.name && strcmp(module.name, "ecereCOM"))
435 row = mainForm.browser.AddRow();
436 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
437 row.tag = (int64)module;
438 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
440 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
452 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
457 virtual void Generate(File f)
462 virtual Module GetModule()
464 return page ? page.GetModule() : null;
467 virtual NameSpace * GetNameSpace()
469 return page ? page.GetNameSpace() : null;
473 enum DocumentationType
482 enum DocumentationItem
499 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
503 sprintf(hex, "%p", module);
504 strcat(fileName, hex);
505 strcat(fileName, "/");
506 sprintf(hex, "%p", object);
507 strcat(fileName, hex);
508 strcat(fileName, "/");
509 sprintf(hex, "%p", data);
510 strcat(fileName, hex);
511 strcat(fileName, "/");
512 if(type == nameSpaceDoc)
513 strcat(fileName, "namespace");
514 else if(type == functionDoc)
515 strcat(fileName, "function");
516 else if(type == classDoc)
517 strcat(fileName, "class");
518 else if(type == methodDoc)
519 strcat(fileName, "method");
520 strcat(fileName, "/");
521 if(item == description)
522 strcat(fileName, "description");
523 else if(item == usage)
524 strcat(fileName, "usage");
525 else if(item == remarks)
526 strcat(fileName, "remarks");
527 else if(item == example)
528 strcat(fileName, "example");
529 else if(item == seeAlso)
530 strcat(fileName, "seeAlso");
531 else if(item == enumerationValue)
532 strcat(fileName, "enumerationValue");
533 else if(item == definition)
534 strcat(fileName, "definition");
535 else if(item == conversion)
536 strcat(fileName, "conversion");
537 else if(item == memberDescription)
538 strcat(fileName, "memberDescription");
539 else if(item == propertyDescription)
540 strcat(fileName, "propertyDescription");
541 else if(item == parameter)
542 strcat(fileName, "parameter");
543 else if(item == returnValue)
544 strcat(fileName, "returnValue");
547 static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
549 char docPath[MAX_LOCATION];
550 NameSpace * nameSpace, * ns;
552 Method method = null;
553 GlobalFunction function = null;
554 char nsName[1024], temp[1024];
557 case nameSpaceDoc: nameSpace = object; break;
558 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
559 case functionDoc: function = object; nameSpace = function.nameSpace; break;
560 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
566 while(ns && ns->name)
568 strcpy(temp, ns->name);
570 strcat(temp, nsName);
571 strcpy(nsName, temp);
576 PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
577 //ChangeExtension(docPath, "eCdoc", docPath);
578 PathCatSlash(docPath, nsName);
581 char * name = getDocFileNameFromTypeName(cl.name);
582 PathCatSlash(docPath, name);
586 PathCatSlash(docPath, "_global-defs");
587 ChangeExtension(docPath, "econ", docPath);
590 strcpy(path, settings.docDir);
591 PathCatSlash(path, docPath);
594 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
596 String contents = null;
597 bool docRetrieved = false;
598 NamespaceDoc nsDoc = null;
599 ClassDoc clDoc = null;
600 FunctionDoc fnDoc = null;
601 MethodDoc mdDoc = null;
603 char filePath[MAX_LOCATION];
604 Method method = null;
605 GlobalFunction function = null;
607 ItemDoc doc = getDoc(filePath, module, type, object, item, data, false);
611 case functionDoc: function = object; break;
612 case methodDoc: method = object; break;
617 if(eClass_IsDerived(doc._class, class(ClassDoc)))
619 clDoc = (ClassDoc)doc;
622 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
624 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))
697 for(prev = data; prev; prev = prev.prev);
698 name = ((Type)data).name;
699 if(type == functionDoc)
701 itDoc = fnDoc.parameters[name];
702 if(itDoc) s = itDoc.description;
704 else if(type == methodDoc)
706 itDoc = mdDoc.parameters[name];
707 if(itDoc) s = itDoc.description;
713 contents = CopyString(s);
715 if(editing && !contents && !readOnly)
716 contents = CopyString($"[Add Text]");
720 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
723 bool docRetrieved = false;
725 NamespaceDoc nsDoc = null;
726 ClassDoc clDoc = null;
728 char docPath[MAX_LOCATION];
730 Method method = null;
734 case classDoc: cl = (Class)object; break;
735 case methodDoc: method = object; cl = method._class; break;
738 FigureFilePath(filePath, module, type, object, item, data);
740 if(docCache[filePath])
742 DocCacheEntry entry = docCache[docPath];
743 if(cl && eClass_IsDerived(entry.doc._class, class(ClassDoc)))
745 clDoc = (ClassDoc)entry.doc;
748 else if(!cl && eClass_IsDerived(entry.doc._class, class(NamespaceDoc)))
750 nsDoc = (NamespaceDoc)entry.doc;
757 f = FileOpen(filePath, read);
760 JSONParser parser { f = f, eCON = true };
761 JSONResult jsonResult;
762 jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), cl ? &clDoc : &nsDoc);
766 if(jsonResult == success)
769 docCache[docPath] = { added = GetTime(), doc = cl ? clDoc : nsDoc };
773 PrintLn("error: problem parsing file: ", filePath);
786 doc = cl ? clDoc : nsDoc;
787 docCache[docPath] = { added = GetTime(), doc = cl ? clDoc : nsDoc };
792 doc = cl ? clDoc : nsDoc;
795 //void pruneDocCache()
797 MapIterator<const String, DocCacheEntry> it { map = docCache };
798 Array<const String> toRemove { };
799 Time now = GetTime();
800 for(entry : docCache)
802 Time diff = now - entry.added;
804 toRemove.Add(&entry);
806 while(toRemove.count)
808 if(it.Index(toRemove.lastIterator.data, false))
813 toRemove.Remove(toRemove.lastIterator.pointer);
820 class APIPageNameSpace : APIPage
822 NameSpace * nameSpace;
830 NameSpace * GetNameSpace()
835 void Generate(File f)
837 char nsName[1024], temp[1024];
843 while(ns && ns->name)
845 strcpy(temp, ns->name);
846 if(nsName[0]) strcat(temp, "::");
847 strcat(temp, nsName);
848 strcpy(nsName, temp);
851 // Generate Class Page
852 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
855 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
856 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);
859 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
862 ns = nameSpace->parent;
863 while(ns && ns->name)
865 strcpy(temp, ns->name);
866 if(nsName[0]) strcat(temp, "::");
867 strcat(temp, nsName);
868 strcpy(nsName, temp);
872 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
876 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
879 f.Printf($"<H3>Description</H3><br><br>\n");
882 char fileName[MAX_LOCATION];
883 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
884 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
886 f.Printf("</a><br><br>");
889 f.Printf("%s<br><br>", desc);
894 if(nameSpace->nameSpaces.first)
897 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
899 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
902 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
903 f.Printf("<TABLE>\n");
907 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);
912 char fileName[MAX_LOCATION];
913 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
914 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
916 f.Printf("</a></TD>");
919 f.Printf("<TD valign=top height=22> %s</TD>", desc);
922 f.Printf("</TR><br>\n");
925 f.Printf("</TABLE><br>\n");
928 if(nameSpace->classes.first)
931 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
933 Class cl = link.data;
934 if(!cl.templateClass)
936 char * desc = ReadDoc(module, classDoc, cl, description, null);
940 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
941 f.Printf("<TABLE>\n");
947 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);
952 char fileName[MAX_LOCATION];
953 FigureFileName(fileName, module, classDoc, cl, description, null);
954 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
956 f.Printf("</a></TD>");
959 f.Printf("<TD valign=top height=22>%s</TD>", desc);
966 f.Printf("</TABLE><br>\n");
969 if(nameSpace->functions.first)
972 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
974 GlobalFunction function = link.data;
975 char * desc = ReadDoc(module, functionDoc, function, description, null);
976 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
977 if(name) name += 2; else name = function.name;
980 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
981 f.Printf("<TABLE>\n");
985 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);
990 char fileName[MAX_LOCATION];
991 FigureFileName(fileName, module, functionDoc, function, description, null);
992 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
994 f.Printf("</a></TD>");
997 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1000 f.Printf("</TR><br>\n");
1003 f.Printf("</TABLE><br>\n");
1006 if(nameSpace->defines.first)
1009 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
1011 DefinedExpression def = link.data;
1012 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
1015 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
1016 f.Printf("<TABLE>\n");
1020 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);
1021 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
1026 char fileName[MAX_LOCATION];
1027 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
1028 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1030 f.Printf("</a></TD>");
1033 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1036 f.Printf("</TR><br>\n");
1039 f.Printf("</TABLE><br>\n");
1042 f.Printf("</FONT></BODY></HTML>\n");
1046 class APIPageClass : APIPage
1055 NameSpace * GetNameSpace()
1057 return cl.nameSpace;
1060 void Generate(File f)
1065 char nsName[1024], temp[1024];
1066 NameSpace * ns = cl.nameSpace;
1067 Module module = cl.module;
1070 while(ns && ns->name)
1072 strcpy(temp, ns->name);
1073 if(nsName[0]) strcat(temp, "::");
1074 strcat(temp, nsName);
1075 strcpy(nsName, temp);
1078 // Generate Class Page
1079 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1080 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1082 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);
1084 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1087 const char * classType = null;
1091 classType = $"Bit Collection";
1094 classType = $"Enumeration";
1097 classType = $"Structure";
1100 classType = $"Class";
1103 classType = $"Class (No header)";
1106 classType = $"Unit";
1109 classType = $"Basic Data Type";
1112 f.Printf($"Type: %s<br>\n", classType);
1115 if(cl.type != systemClass && cl.base)
1117 f.Printf($"Base Class: ");
1118 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1120 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1122 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1123 f.Printf("%s", cl.dataTypeString);
1125 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1130 char * desc = ReadDoc(module, classDoc, cl, description, null);
1133 f.Printf($"<br><H3>Description</H3><br><br>\n");
1136 char fileName[MAX_LOCATION];
1137 FigureFileName(fileName, module, classDoc, cl, description, null);
1138 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1140 f.Printf("</a><br><br>");
1143 f.Printf("%s<br><br>", desc);
1148 if(cl.type == enumClass)
1150 EnumClassData enumeration = (EnumClassData)cl.data;
1151 if(enumeration.values.first)
1155 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
1156 f.Printf("<TABLE>\n");
1158 for(item = enumeration.values.first; item; item = item.next)
1160 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1161 bool needClass = true;
1164 char tempString[1024];
1166 while(base.type == enumClass) base = base.base;
1168 if(base.type == systemClass ||
1169 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1172 base.dataType = ProcessTypeString(base.dataTypeString, false);
1174 if(base.dataType.kind != classType)
1179 PrintType(base.dataType, string, false, true);
1180 classSym = FindClass(string);
1181 dataClass = classSym ? classSym.registered : null;
1184 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1190 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);
1191 if(dataClass.type == systemClass)
1194 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1197 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1199 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1201 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1206 char fileName[MAX_LOCATION];
1207 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1208 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1210 f.Printf("</a></TD>");
1213 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1218 f.Printf("</TABLE><BR>\n");
1222 if(cl.conversions.first)
1224 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
1225 f.Printf("<TABLE>\n");
1226 for(prop = cl.conversions.first; prop; prop = prop.next)
1228 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1230 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1232 Type type = ProcessTypeString(prop.name, false);
1233 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1234 if(name) name += 2; else name = prop.name;
1239 DocPrintType(type, string, true, false);
1241 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1246 char fileName[MAX_LOCATION];
1247 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1248 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1250 f.Printf("</a></TD>");
1253 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1257 f.Printf("</TR>\n");
1262 f.Printf("</TABLE><br>\n");
1265 if(cl.membersAndProperties.first)
1268 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1270 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1274 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1275 f.Printf("<TABLE>\n");
1281 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1283 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1287 DocPrintType(prop.dataType, string, true, false);
1289 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);
1290 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1295 char fileName[MAX_LOCATION];
1296 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1297 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1299 f.Printf("</a></TD>");
1302 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1305 f.Printf("</TR>\n");
1309 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1314 f.Printf("</TABLE><br>\n");
1317 if(cl.methods.first)
1321 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1323 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1325 char * desc = ReadDoc(module, methodDoc, method, description, null);
1328 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1329 f.Printf("<TABLE>\n");
1332 if(!method.dataType)
1333 ProcessMethodType(method);
1336 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);
1341 char fileName[MAX_LOCATION];
1342 FigureFileName(fileName, module, methodDoc, method, description, null);
1343 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1345 f.Printf("</a></TD>");
1348 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1351 f.Printf("</TR><br>\n");
1355 f.Printf("</TABLE><br>\n");
1357 // Non-Virtual Methods
1359 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1361 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1363 char * desc = ReadDoc(module, methodDoc, method, description, null);
1366 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1367 f.Printf("<TABLE>\n");
1371 if(!method.dataType)
1372 ProcessMethodType(method);
1375 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);
1380 char fileName[MAX_LOCATION];
1381 FigureFileName(fileName, module, methodDoc, method, description, null);
1382 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1384 f.Printf("</a></TD>");
1387 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1391 f.Printf("</TR><br>\n");
1395 f.Printf("</TABLE><br>\n");
1398 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1401 f.Printf($"<H3>Usage</H3><br>\n");
1404 char fileName[MAX_LOCATION];
1405 FigureFileName(fileName, module, classDoc, cl, usage, null);
1406 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1411 f.Printf("<br>%s\n", usageDoc);
1412 f.Printf("<br><br>\n");
1417 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1420 f.Printf($"<H3>Example</H3><br>\n");
1421 f.Printf($"<FONT face=\"Courier New\">\n");
1422 f.Printf("<br><TABLE>\n");
1425 char fileName[MAX_LOCATION];
1426 FigureFileName(fileName, module, classDoc, cl, example, null);
1427 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1429 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1432 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1434 f.Printf("</TABLE></FONT>\n");
1440 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1444 f.Printf($"<H3>Remarks</H3><br>\n");
1447 char fileName[MAX_LOCATION];
1448 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1449 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1454 f.Printf("<br>%s\n", remarksDoc);
1455 f.Printf("<br><br>\n");
1460 if(cl.type != systemClass)
1464 for(c = cl.derivatives.first; c; c = c.next)
1466 Class deriv = c.data;
1467 // TO VERIFY: Does this properly check public status?
1468 if(eSystem_FindClass(componentsApp, deriv.fullName))
1472 f.Printf($"<H3>Derived Classes</H3><br>\n");
1478 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1482 f.Printf("<br><br>\n");
1485 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1488 f.Printf($"<H3>See Also</H3><br>\n");
1491 char fileName[MAX_LOCATION];
1492 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1493 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1498 f.Printf("<br>%s\n", seeAlsoDoc);
1499 f.Printf("<br><br>\n");
1503 f.Printf("</FONT></BODY></HTML>\n");
1507 class APIPageMethod : APIPage
1513 return method._class.module;
1516 NameSpace * GetNameSpace()
1518 return method._class.nameSpace;
1521 void Generate(File f)
1523 Class cl = method._class;
1525 Module module = cl.module;
1527 char nsName[1024], temp[1024];
1528 NameSpace * ns = cl.nameSpace;
1531 while(ns && ns->name)
1533 strcpy(temp, ns->name);
1534 if(nsName[0]) strcat(temp, "::");
1535 strcat(temp, nsName);
1536 strcpy(nsName, temp);
1540 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1541 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1543 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);
1545 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1546 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1547 if(method.dataType.staticMethod)
1549 f.Printf($"this pointer class: None<br>\n");
1551 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1553 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);
1556 // Generate Method Page
1558 if(!method.dataType.name)
1559 method.dataType.name = CopyString(method.name);
1560 DocPrintType(method.dataType, string, true, false);
1561 f.Printf("<br>%s", string);
1564 char * desc = ReadDoc(module, methodDoc, method, description, null);
1567 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1570 char fileName[MAX_LOCATION];
1571 FigureFileName(fileName, module, methodDoc, method, description, null);
1572 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1577 f.Printf("%s", desc);
1582 f.Printf("<br><br>\n");
1583 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1585 f.Printf($"<H3>Parameters</H3><br><br>\n");
1587 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1588 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1590 f.Printf("<TABLE valign=center>\n");
1593 for(param = method.dataType.params.first; param; param = param.next)
1595 // ADD DESCRIPTION HERE
1596 if(param.kind != voidType)
1598 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1601 DocPrintType(param, string, false, false);
1603 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1604 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1609 char fileName[MAX_LOCATION];
1610 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1611 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1613 f.Printf("</a></TD>\n");
1616 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1620 f.Printf("</TR>\n");
1623 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1625 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1626 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1628 f.Printf("<TR><TD> </TD></TR>");
1631 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1633 DocPrintType(method.dataType.returnType, string, false, false);
1634 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1639 char fileName[MAX_LOCATION];
1640 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1641 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1643 f.Printf("</a> </TD>\n");
1646 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1649 f.Printf("</TR>\n");
1650 f.Printf("</TABLE>\n");
1652 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1653 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1655 f.Printf("</TABLE><br>\n");
1658 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1661 f.Printf($"<H3>Usage</H3><br>\n");
1664 char fileName[MAX_LOCATION];
1665 FigureFileName(fileName, module, methodDoc, method, usage, null);
1666 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1671 f.Printf("<br>%s\n", usageDoc);
1672 f.Printf("<br><br>\n");
1677 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1680 f.Printf($"<H3>Example</H3><br>\n");
1681 f.Printf($"<FONT face=\"Courier New\">\n");
1682 f.Printf("<br><TABLE>\n");
1685 char fileName[MAX_LOCATION];
1686 FigureFileName(fileName, module, methodDoc, method, example, null);
1687 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1689 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1692 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1693 f.Printf("</TABLE></FONT>\n");
1699 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1702 f.Printf($"<H3>Remarks</H3><br>\n");
1705 char fileName[MAX_LOCATION];
1706 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1707 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1712 f.Printf("<br>%s\n", method, remarksDoc);
1713 f.Printf("<br><br>\n");
1718 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1721 f.Printf($"<H3>See Also</H3><br>\n");
1724 char fileName[MAX_LOCATION];
1725 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1726 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1731 f.Printf("<br>%s\n", method, seeAlsoDoc);
1733 f.Printf("<br><br>\n");
1737 f.Printf("</FONT></BODY></HTML>\n");
1741 class APIPageFunction : APIPage
1743 GlobalFunction function;
1747 return function.module;
1750 NameSpace * GetNameSpace()
1752 return function.nameSpace;
1755 void Generate(File f)
1758 Module module = function.module;
1760 char nsName[1024], temp[1024];
1761 NameSpace * ns = function.nameSpace;
1764 while(ns && ns->name)
1766 strcpy(temp, ns->name);
1767 if(nsName[0]) strcat(temp, "::");
1768 strcat(temp, nsName);
1769 strcpy(nsName, temp);
1773 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1774 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1776 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);
1779 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1781 if(!function.dataType)
1782 function.dataType = ProcessTypeString(function.dataTypeString, false);
1784 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1786 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);
1789 // Generate Method Page
1791 if(!function.dataType.name)
1792 function.dataType.name = CopyString(function.name);
1793 DocPrintType(function.dataType, string, true, false);
1794 f.Printf("<br>%s", string);
1797 char * desc = ReadDoc(module, functionDoc, function, description, null);
1800 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1803 char fileName[MAX_LOCATION];
1804 FigureFileName(fileName, module, functionDoc, function, description, null);
1805 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1810 f.Printf("%s", desc);
1814 f.Printf("<br><br>\n");
1815 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1817 f.Printf($"<H3>Parameters</H3><br><br>\n");
1819 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1820 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1822 f.Printf("<TABLE valign=center>\n");
1825 for(param = function.dataType.params.first; param; param = param.next)
1827 // ADD DESCRIPTION HERE
1828 if(param.kind != voidType)
1830 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1833 DocPrintType(param, string, false, false);
1835 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1836 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1841 char fileName[MAX_LOCATION];
1842 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1843 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1846 f.Printf("</a> </TD>\n");
1849 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1852 f.Printf("</TR>\n");
1855 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1857 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1858 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1860 f.Printf("<TR><TD> </TD></TR>");
1863 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1865 DocPrintType(function.dataType.returnType, string, false, false);
1866 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1871 char fileName[MAX_LOCATION];
1872 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1873 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1875 f.Printf("</a> </TD>\n");
1878 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1881 f.Printf("</TR>\n");
1882 f.Printf("</TABLE>\n");
1884 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1885 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1887 f.Printf("</TABLE><br>\n");
1890 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1893 f.Printf($"<H3>Usage</H3><br>\n");
1896 char fileName[MAX_LOCATION];
1897 FigureFileName(fileName, module, functionDoc, function, usage, null);
1898 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1903 f.Printf("<br>%s\n", usageDoc);
1904 f.Printf("<br><br>\n");
1909 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1912 f.Printf($"<H3>Example</H3><br>\n");
1913 f.Printf($"<FONT face=\"Courier New\">\n");
1914 f.Printf("<br><TABLE>\n");
1917 char fileName[MAX_LOCATION];
1918 FigureFileName(fileName, module, functionDoc, function, example, null);
1919 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1921 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1924 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1925 f.Printf("</TABLE></FONT>\n");
1931 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1934 f.Printf($"<H3>Remarks</H3><br>\n");
1937 char fileName[MAX_LOCATION];
1938 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1939 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1944 f.Printf("<br>%s\n", remarksDoc);
1945 f.Printf("<br><br>\n");
1950 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1953 f.Printf($"<H3>See Also</H3><br>\n");
1956 char fileName[MAX_LOCATION];
1957 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1958 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1963 f.Printf("<br>%s\n", seeAlsoDoc);
1964 f.Printf("<br><br>\n");
1968 f.Printf("</FONT></BODY></HTML>\n");
1972 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1976 NameSpace * nameSpace = mainNameSpace;
1978 DataRow classesRow = null;
1979 DataRow functionsRow = null, definesRow = null;
1982 strcpy(nsName, parentName ? parentName : "");
1986 strcat(nsName, "::");
1987 strcat(nsName, nameSpace->name);
1992 row = parentRow.AddRow();
1993 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1994 row.tag = (int64)nameSpace;
1995 row.icon = mainForm.icons[typeNameSpace];
1999 // "Global NameSpace"
2001 page = parentRow.GetData(null);
2004 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
2006 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
2007 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
2009 if(comNameSpace != null)
2011 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
2013 if(!mainNameSpace.nameSpaces.FindString(ns->name))
2015 AddNameSpace(row, module, ns, null, nsName, showPrivate);
2020 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
2022 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2024 if(nameSpace->classes.first)
2028 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
2031 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
2033 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
2034 AddClass(classesRow, module, cl, nsName, showPrivate);
2041 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2043 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2045 if(nameSpace->functions.first)
2049 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2052 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2054 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2056 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2057 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2064 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2066 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2068 if(nameSpace->defines.first)
2072 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2075 //if(def.module == module)
2077 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2079 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2080 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2088 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2092 if(!member.dataType)
2093 member.dataType = ProcessTypeString(member.dataTypeString, false);
2097 DocPrintType(member.dataType, string, true, false);
2099 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2100 for(c = 0; c<indent; c++)
2101 f.Printf(" ");
2102 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2103 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2104 if(member.type == normalMember)
2106 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2111 char fileName[MAX_LOCATION];
2112 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2113 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2115 f.Printf("</a></TD>");
2118 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2123 f.Printf("<TD valign=top height=22></TD>");
2125 if(member.type != normalMember)
2127 DataMember subMember;
2128 for(subMember = member.members.first; subMember; subMember = subMember.next)
2130 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2132 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2136 f.Printf("</TR><br>\n");
2139 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2142 if(member.type == normalMember)
2144 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2145 row.tag = (int64)member;
2150 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2151 row.icon = mainForm.icons[typeData];
2152 row.tag = (int64)member;
2154 for(m = member.members.first; m; m = m.next)
2156 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2157 AddDataMember(row, page, m);
2162 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2167 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2168 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2171 row = parentRow.AddRow();
2172 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2173 row.tag = (int64)cl;
2174 row.collapsed = true;
2175 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2178 if(cl.methods.first)
2180 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2182 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2185 if(!method.dataType)
2186 ProcessMethodType(method);
2187 if(method.type == virtualMethod)
2189 if(method.dataType.thisClass)
2191 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2192 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2193 mRow.tag = (int64)method;
2197 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2198 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2199 mRow.tag = (int64)method;
2204 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2205 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2206 mRow.tag = (int64)method;
2212 if(cl.membersAndProperties.first)
2214 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2216 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2219 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2223 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2224 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2225 mRow.tag = (int64)prop;
2229 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2230 AddDataMember(membersRow, page, (DataMember)prop);
2236 if(cl.conversions.first)
2238 for(prop = cl.conversions.first; prop; prop = prop.next)
2242 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2243 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2244 if(name) name += 2; else name = prop.name;
2245 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2246 mRow.tag = (int64)prop;
2249 if(cl.type == enumClass)
2251 EnumClassData enumeration = (EnumClassData)cl.data;
2253 for(item = enumeration.values.first; item; item = item.next)
2256 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2257 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2258 mRow.tag = (int64)item;
2263 class AddressBar : Window
2265 background = activeBorder;
2269 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2271 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2273 MainForm mainForm = (MainForm)parent;
2274 FileDialog fileDialog = mainForm.fileDialog;
2275 if(fileDialog.Modal() == ok)
2276 mainForm.OpenModule(fileDialog.filePath);
2282 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2285 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2287 ((MainForm)parent).Back();
2293 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2296 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2298 ((MainForm)parent).Forward();
2304 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2306 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2308 ((MainForm)parent).Home();
2312 /* TODO: Search (#143/#441)
2313 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2314 Update this in the NotifyUpdate. Enter goes to the exact match.
2316 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2320 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2322 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2324 if(!disabled && (SmartKey)key == enter)
2325 ((MainForm)parent).Go(editBox.contents);
2329 void NotifyUpdate(EditBox editBox)
2331 String location = ((MainForm)parent).view.location;
2332 disabled = !strcmp(location ? location : "", editBox.contents);
2337 bool OnKeyHit(Key key, unichar ch)
2340 ((MainForm)parent).view.MakeActive();
2345 class MainForm : Window
2347 size = { 1000, 600 };
2349 borderStyle = sizable;
2352 icon = { ":documentorIcon.png" };
2353 text = $"API Documentation Browser";
2355 BitmapResource icons[CodeObjectType];
2360 for(c = 0; c < CodeObjectType::enumSize; c++)
2362 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2364 browser.AddField(DataField { dataType = class(APIPage) });
2369 Menu fileMenu { menu, $"File", f };
2370 Array<FileFilter> fileFilters
2372 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2373 { $"eC Symbol files (*.sym)", "sym" }
2376 FileDialog fileDialog
2378 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2380 MenuItem fileOpenItem
2382 fileMenu, $"Open...", o, ctrlO;
2384 bool NotifySelect(MenuItem selection, Modifiers mods)
2386 if(fileDialog.Modal() == ok)
2388 OpenModule(fileDialog.filePath);
2393 MenuItem fileSettingsItem
2395 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2397 bool NotifySelect(MenuItem selection, Modifiers mods)
2399 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2409 MenuDivider { fileMenu };
2410 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2412 void OpenModule(const char * filePath)
2414 char moduleName[MAX_LOCATION];
2415 char extension[MAX_EXTENSION];
2416 Module module = null;
2417 static char symbolsDir[MAX_LOCATION];
2421 FreeContext(globalContext);
2422 FreeExcludedSymbols(excludedSymbols);
2423 ::defines.Free(FreeModuleDefine);
2424 imports.Free(FreeModuleImport);
2426 FreeGlobalData(globalData);
2430 FreeTypeData(componentsApp);
2431 delete componentsApp;
2434 componentsApp = __ecere_COM_Initialize(false, 1, null);
2435 SetPrivateModule(componentsApp);
2437 StripLastDirectory(filePath, symbolsDir);
2438 SetSymbolsDir(symbolsDir);
2440 GetExtension(filePath, extension);
2442 mainForm.browser.Clear();
2444 ImportModule(filePath, normalImport, publicAccess, false);
2446 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2447 componentsApp.name = CopyString(filePath);
2449 for(module = componentsApp.allModules.first; module; module = module.next)
2451 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2455 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2456 AddComponents(componentsApp, false);
2458 GetLastDirectory(filePath, moduleName);
2459 // Extension, path and lib prefix get removed in Module::name
2462 StripExtension(moduleName);
2463 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2465 int len = strlen(moduleName) - 3;
2466 memmove(moduleName, moduleName + 3, len);
2467 moduleName[len] = 0;
2471 for(module = componentsApp.allModules.first; module; module = module.next)
2473 if(module.name && (!strcmp(module.name, moduleName)))
2476 if(!module) module = componentsApp;
2477 homeModule = module;
2478 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2480 SetSymbolsDir(null);
2483 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2486 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2487 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2490 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2492 APIPage page = row.GetData(null);
2493 if(view.edit) view.OnLeftButtonDown(0,0,0);
2494 if(page && page.page) page = page.page;
2496 view.PositionCaret(true);
2497 if(page != view.page)
2499 Window activeChild = this.activeChild;
2501 // Back / Forward Support
2502 if(row && !dontRecordHistory)
2504 if(history.count > historyPos+1)
2505 history.count = historyPos+1;
2506 historyPos = history.count-1;
2507 addressBar.back.disabled = (historyPos == 0);
2508 addressBar.forward.disabled = (historyPos >= history.count-1);
2510 history.Add((Instance)(uint64)row.tag);
2511 historyPos = history.count-1;
2513 addressBar.back.disabled = (historyPos == 0);
2514 addressBar.forward.disabled = (historyPos >= history.count-1);
2520 activeChild.Activate();
2522 else if(!view.created)
2526 page = row.GetData(null);
2527 if(page && page.page)
2531 case 1: view.GoToAnchor("Classes"); break;
2532 case 2: view.GoToAnchor("Functions"); break;
2533 case 3: view.GoToAnchor("Definitions"); break;
2534 case 4: view.GoToAnchor("VirtualMethods"); break;
2535 case 5: view.GoToAnchor("Methods"); break;
2536 case 6: view.GoToAnchor("Members"); break;
2537 case 7: view.GoToAnchor("Conversions"); break;
2538 case 8: view.GoToAnchor("EnumerationValues"); break;
2542 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2543 view.GoToAnchor(hex);
2549 view.SetScrollPosition(0, 0);
2557 this, anchor = { top = 26, bottom = 0, right = 0 };
2562 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2565 bool OnClose(bool parentClosing)
2568 view.OnLeftButtonDown(0,0,0);
2574 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2575 //mainForm.OpenModule("ec");
2576 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2577 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2579 int index = mainForm.browser.currentRow.index;
2580 int rowHeight = mainForm.browser.rowHeight;
2581 int height = mainForm.browser.clientSize.h;
2583 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2588 Array<Instance> history { };
2590 bool dontRecordHistory;
2595 if(historyPos < history.count-1)
2599 addressBar.back.disabled = (historyPos == 0);
2600 addressBar.forward.disabled = (historyPos >= history.count-1);
2601 sprintf(location, "api://%p", history[historyPos]);
2602 dontRecordHistory = true;
2603 view.OnOpen(location);
2604 dontRecordHistory = false;
2616 addressBar.back.disabled = (historyPos == 0);
2617 addressBar.forward.disabled = (historyPos >= history.count-1);
2618 sprintf(location, "api://%p", history[historyPos]);
2619 dontRecordHistory = true;
2620 view.OnOpen(location);
2621 dontRecordHistory = false;
2629 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2633 class EditDialog : Window
2635 borderStyle = sizable;
2636 size = { 600, 400 };
2641 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2645 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2649 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2653 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2654 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2656 class HelpView : HTMLView
2660 hasVertScroll = true;
2661 hasHorzScroll = true;
2663 char editString[MAX_LOCATION];
2669 page = mainForm.browser.currentRow.GetData(null);
2674 char docDir[MAX_LOCATION];
2676 strcpy(docDir, settings.docDir);
2677 if(FileExists(docDir).isDirectory)
2679 PathCatSlash(docDir, "___docWriteTest");
2680 if(FileExists(docDir).isDirectory)
2683 if(!FileExists(docDir))
2689 if(FileExists(docDir).isDirectory)
2701 GoToAnchor(page.label);
2703 if(page.page) page = page.page;
2706 return HTMLView::OnCreate();
2717 String contents = null;
2720 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2722 if(block.type == TEXT && block.textLen)
2730 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2732 if(block.type == BR)
2734 else if(block.type == TEXT)
2735 f.Write(block.text, 1, block.textLen);
2739 if((len = f.GetSize()))
2741 contents = new char[len+1];
2742 f.Read(contents, 1, len);
2743 contents[len] = '\0';
2745 if(!empty && contents)
2747 char temp[MAX_LOCATION];
2748 char part[MAX_FILENAME];
2752 DocumentationType type;
2753 DocumentationItem item;
2755 bool docRetrieved = false;
2756 NamespaceDoc nsDoc = null;
2757 ClassDoc clDoc = null;
2758 FunctionDoc fnDoc = null;
2759 MethodDoc mdDoc = null;
2760 //char filePath[MAX_LOCATION];
2762 Method method = null;
2763 GlobalFunction function = null;
2765 strcpy(temp, editString);
2766 SplitDirectory(temp, part, temp);
2767 module = (Module)strtoull(part, null, 16);
2768 SplitDirectory(temp, part, temp);
2769 object = (void *)strtoull(part, null, 16);
2770 SplitDirectory(temp, part, temp);
2771 data = (void *)strtoull(part, null, 16);
2772 SplitDirectory(temp, part, temp);
2773 if(!strcmp(part, "namespace"))
2774 type = nameSpaceDoc;
2775 else if(!strcmp(part, "function"))
2777 else if(!strcmp(part, "class"))
2779 else if(!strcmp(part, "method"))
2781 SplitDirectory(temp, part, temp);
2782 if(!strcmp(part, "description"))
2784 else if(!strcmp(part, "usage"))
2786 else if(!strcmp(part, "remarks"))
2788 else if(!strcmp(part, "example"))
2790 else if(!strcmp(part, "seeAlso"))
2792 else if(!strcmp(part, "enumerationValue"))
2793 item = enumerationValue;
2794 else if(!strcmp(part, "definition"))
2796 else if(!strcmp(part, "conversion"))
2798 else if(!strcmp(part, "memberDescription"))
2799 item = memberDescription;
2800 else if(!strcmp(part, "propertyDescription"))
2801 item = propertyDescription;
2802 else if(!strcmp(part, "parameter"))
2804 else if(!strcmp(part, "returnValue"))
2807 doc = getDoc(temp, module, type, object, item, data, true);
2810 MapIterator<const String, DocCacheEntry> it { map = docCache };
2811 if(it.Index(temp, false))
2821 case classDoc: cl = (Class)object; break;
2822 case functionDoc: function = object; break;
2823 case methodDoc: method = object; cl = method._class; break;
2826 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2828 clDoc = (ClassDoc)doc;
2829 docRetrieved = true;
2831 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2833 nsDoc = (NamespaceDoc)doc;
2834 docRetrieved = true;
2839 if(type == functionDoc)
2841 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2842 if(name) name += 2; else name = function.name;
2843 if(!nsDoc.functions) nsDoc.functions = { };
2844 fnDoc = nsDoc.functions[name];
2848 nsDoc.functions[name] = fnDoc;
2851 else if(type == methodDoc)
2853 if(!clDoc.methods) clDoc.methods = { };
2854 mdDoc = clDoc.methods[method.name];
2858 clDoc.methods[method.name] = mdDoc;
2865 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2866 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2867 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2868 else { nsDoc.description = contents; contents = null; }
2871 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2872 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2873 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2876 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2877 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2878 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2881 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2882 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2883 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2886 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2887 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2888 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2891 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2892 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2894 case enumerationValue:
2897 if(!clDoc.values) clDoc.values = { };
2898 itDoc = clDoc.values[((NamedLink)data).name];
2902 clDoc.values[((NamedLink)data).name] = itDoc;
2904 itDoc.description = contents; contents = null;
2910 if(!nsDoc.defines) nsDoc.defines = { };
2911 itDoc = nsDoc.defines[((Definition)data).name];
2915 nsDoc.defines[((Definition)data).name] = itDoc;
2917 itDoc.description = contents; contents = null;
2922 ConversionDoc itDoc;
2923 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2924 if(name) name += 2; else name = ((Property)data).name;
2925 if(!clDoc.conversions) clDoc.conversions = { };
2926 itDoc = clDoc.conversions[name];
2930 clDoc.conversions[name] = itDoc;
2932 itDoc.description = contents; contents = null;
2935 case memberDescription:
2938 if(!clDoc.fields) clDoc.fields = { };
2939 itDoc = clDoc.fields[((DataMember)data).name];
2943 clDoc.fields[((DataMember)data).name] = itDoc;
2945 itDoc.description = contents; contents = null;
2948 case propertyDescription:
2951 if(!clDoc.properties) clDoc.properties = { };
2952 itDoc = clDoc.properties[((Property)data).name];
2956 clDoc.properties[((Property)data).name] = itDoc;
2958 itDoc.description = contents; contents = null;
2966 for(prev = data; prev; prev = prev.prev);
2967 name = ((Type)data).name;
2968 if(type == functionDoc)
2970 if(!fnDoc.parameters) fnDoc.parameters = { };
2971 itDoc = fnDoc.parameters[name];
2975 fnDoc.parameters[name] = itDoc;
2977 itDoc.description = contents; contents = null;
2979 else if(type == methodDoc)
2981 if(!mdDoc.parameters) mdDoc.parameters = { };
2982 itDoc = mdDoc.parameters[name];
2986 mdDoc.parameters[name] = itDoc;
2988 itDoc.description = contents; contents = null;
2997 char filePath[MAX_LOCATION];
2998 char dirPath[MAX_LOCATION];
2999 strcpy(filePath, temp);
3000 StripLastDirectory(filePath, dirPath);
3001 if(FileExists(filePath))
3002 DeleteFile(filePath);
3003 if(cl ? !clDoc.isEmpty : !nsDoc.isEmpty)
3005 if(!FileExists(dirPath))
3007 f = FileOpen(filePath, write);
3011 WriteJSONObject(f, class(ClassDoc), clDoc, 0, true);
3013 WriteJSONObject(f, class(NamespaceDoc), nsDoc, 0, true);
3018 PrintLn("error: writeClassDocFile -- problem opening file: ", filePath);
3028 Block parent = textBlock.parent;
3029 while((block = parent.subBlocks.first))
3031 parent.subBlocks.Remove(block);
3034 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3035 textBlock.text = CopyString($"[Add Text]");
3036 textBlock.textLen = strlen(textBlock.text);
3037 parent.subBlocks.Add(textBlock);
3045 PositionCaret(true);
3050 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3054 if(edit && (!textBlock || overLink != textBlock.parent))
3058 HTMLView::OnLeftButtonDown(x, y, mods);
3059 selPosition = curPosition = 0;
3060 selBlock = textBlock;
3064 result = HTMLView::OnLeftButtonDown(x, y, mods);
3066 if(!edit && clickedLink)
3069 if(clickedLink == overLink && clickedLink.href)
3071 if(OnOpen(clickedLink.href))
3079 if(textBlock && overLink == textBlock.parent)
3081 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3082 selBlock = textBlock;
3083 PositionCaret(true);
3091 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3093 if(!edit || !textBlock || clickedLink != textBlock.parent)
3095 HTMLView::OnLeftButtonUp(x, y, mods);
3098 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3099 selBlock = textBlock;
3100 PositionCaret(true);
3111 bool OnMouseMove(int x, int y, Modifiers mods)
3113 if(edit && selecting)
3115 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3116 PositionCaret(true);
3119 return HTMLView::OnMouseMove(x, y, mods);
3122 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3124 if(edit && textBlock)
3130 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3131 selBlock = textBlock;
3132 for(c = curPosition; c >= 0; c--)
3135 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3136 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3137 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3143 for(c = start; c < textBlock.textLen; c += numBytes)
3145 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3146 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3149 selPosition = start;
3152 PositionCaret(true);
3160 bool OnOpen(char * href)
3162 if(!strncmp(href, "api://", 6))
3164 int64 tag = (int64)strtoull(href + 6, null, 16);
3165 DataRow row = mainForm.browser.FindSubRow(tag);
3169 mainForm.browser.SelectRow(row);
3170 while((row = row.parent))
3171 row.collapsed = false;
3172 row = mainForm.browser.currentRow;
3173 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3176 else if(!strncmp(href, "edit://", 7))
3179 int startX = clickedLink.startX, startY = clickedLink.startY;
3180 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3182 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3183 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3185 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3187 display.FontExtent(block.font.font, " ", 1, null, &th);
3190 block.parent.subBlocks.Insert(null, newBlock);
3195 block.parent.subBlocks.Insert(block, newBlock);
3196 startY += block.prev.height;
3198 newBlock.startX = startX;
3199 newBlock.startY = startY;
3200 newBlock.text = new0 char[1];
3204 textBlock = (Block)clickedLink.subBlocks.first;
3205 if(!strcmp(textBlock.text, $"[Add Text]"))
3207 textBlock.text[0] = 0;
3208 textBlock.textLen = 0;
3211 strcpy(editString, href + 7);
3212 selPosition = curPosition = 0;
3213 selBlock = textBlock;
3216 // PositionCaret(true);
3223 void DeleteSelection()
3225 if(textBlock != selBlock || curPosition != selPosition)
3227 if(textBlock == selBlock)
3229 // Within same block
3230 int start = Min(curPosition, selPosition);
3231 int end = Max(curPosition, selPosition);
3232 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3233 textBlock.textLen -= end-start;
3234 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3235 curPosition = start;
3236 selPosition = start;
3240 int startSel, endSel;
3241 Block startSelBlock = null, endSelBlock = null, b, next;
3243 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3245 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3246 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3248 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3249 for(b = startSelBlock.next; b; b = next)
3251 bool isEnd = b == endSelBlock;
3252 next = GetNextBlock(b);
3253 b.parent.subBlocks.Remove(b);
3258 textBlock = startSelBlock;
3259 selBlock = startSelBlock;
3260 curPosition = startSel;
3261 selPosition = startSel;
3265 PositionCaret(true);
3270 String GetSelectionString()
3272 String selection = null;
3273 if(textBlock == selBlock)
3275 // Within same block
3276 int start = Min(curPosition, selPosition);
3277 int end = Max(curPosition, selPosition);
3278 int len = end - start;
3279 selection = new char[len + 1];
3280 memcpy(selection, textBlock.text + start, len);
3285 int startSel, endSel;
3286 Block startSelBlock = null, endSelBlock = null, b;
3289 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3292 for(b = startSelBlock; b; b = GetNextBlock(b))
3294 int start = (b == startSelBlock) ? startSel : 0;
3295 int end = (b == endSelBlock) ? endSel : b.textLen;
3296 int len = end - start;
3298 if(b == endSelBlock)
3300 else if(b.type == TEXT)
3304 selection = new char[totalLen + 1];
3306 for(b = startSelBlock; b; b = GetNextBlock(b))
3308 int start = (b == startSelBlock) ? startSel : 0;
3309 int end = (b == endSelBlock) ? endSel : b.textLen;
3310 int len = end - start;
3311 memcpy(selection + totalLen, b.text + start, len);
3313 if(b == endSelBlock)
3315 else if(b.type == TEXT)
3316 selection[totalLen++] = '\n';
3318 selection[totalLen] = 0;
3323 void CopySelection()
3325 String s = GetSelectionString();
3328 int len = strlen(s);
3330 if(cb.Allocate(len + 1))
3332 memcpy(cb.text, s, len + 1);
3340 bool OnKeyDown(Key key, unichar ch)
3347 OnLeftButtonDown(0,0,0);
3349 case Key { end, shift = true }:
3351 curPosition = textBlock.textLen;
3354 selPosition = curPosition;
3355 selBlock = textBlock;
3357 PositionCaret(true);
3360 case Key { home, shift = true }:
3365 selPosition = curPosition;
3366 selBlock = textBlock;
3368 PositionCaret(true);
3371 case Key { home, ctrl = true, shift = true }:
3374 while(textBlock.prev)
3375 textBlock = textBlock.prev.prev;
3378 selPosition = curPosition;
3379 selBlock = textBlock;
3381 PositionCaret(true);
3384 case Key { end, ctrl = true, shift = true }:
3386 while(textBlock.next && textBlock.next.next)
3387 textBlock = textBlock.next.next;
3388 curPosition = textBlock.textLen;
3391 selPosition = curPosition;
3392 selBlock = textBlock;
3394 PositionCaret(true);
3400 return HTMLView::OnKeyDown(key, ch);
3404 bool OnKeyHit(Key key, unichar ch)
3410 case Key { up, shift = true }:
3413 if(caretY == textBlock.startY)
3417 textBlock = textBlock.prev.prev;
3418 curPosition = Min(curPosition, textBlock.textLen);
3421 selPosition = curPosition;
3422 selBlock = textBlock;
3425 PositionCaret(false);
3435 int sx = textBlock.startX, sy = textBlock.startY;
3436 char * text = textBlock.text;
3438 Block block = textBlock;
3439 while(block && block.type != TD) block = block.parent;
3442 Block table = block;
3443 while(table && table.type != TABLE) table = table.parent;
3445 maxW = block.w - 2* table.cellPadding;
3447 maxW = clientSize.w - 10 - sx;
3450 maxW = clientSize.w - 10 - sx;
3451 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3455 int startPos = textPos;
3458 bool lineComplete = false;
3459 for(; textPos<textBlock.textLen && !lineComplete;)
3463 char * nextSpace = strchr(text + textPos, ' ');
3466 len = (nextSpace - (text + textPos)) + 1;
3468 len = textBlock.textLen - textPos;
3470 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3472 if(x + width + w > maxW && x > 0)
3474 lineComplete = true;
3484 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3487 curPosition = textPos;
3488 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3491 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3492 len = curPosition - startPos;
3493 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3497 selPosition = curPosition;
3498 selBlock = textBlock;
3502 PositionCaret(false);
3506 if(sy == caretY - th || textPos == textBlock.textLen)
3508 if(textPos != textBlock.textLen)
3510 int c = textPos - 1;
3511 while(c > 0 && text[c] == ' ') c--;
3512 curPosition = c + 1;
3515 selPosition = curPosition;
3516 selBlock = textBlock;
3522 curPosition = textBlock.textLen;
3525 selPosition = curPosition;
3526 selBlock = textBlock;
3530 PositionCaret(false);
3534 sx = textBlock.startX;
3535 } while(textPos < textBlock.textLen);
3540 case Key { down, shift = true }:
3545 int sx = textBlock.startX, sy = textBlock.startY;
3546 char * text = textBlock.text;
3548 Block block = textBlock;
3549 while(block && block.type != TD) block = block.parent;
3552 Block table = block;
3553 while(table && table.type != TABLE) table = table.parent;
3555 maxW = block.w - 2* table.cellPadding;
3557 maxW = clientSize.w - 10 - sx;
3560 maxW = clientSize.w - 10 - sx;
3561 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3563 while(!textPos || textPos < textBlock.textLen)
3565 int startPos = textPos;
3568 bool lineComplete = false;
3569 for(; (textPos < textBlock.textLen) && !lineComplete;)
3573 char * nextSpace = strchr(text + textPos, ' ');
3576 len = (nextSpace - (text + textPos)) + 1;
3578 len = textBlock.textLen - textPos;
3580 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3582 if(x + width + w > maxW && x > 0)
3584 lineComplete = true;
3594 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3596 curPosition = textPos;
3598 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3601 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3602 len = curPosition - startPos;
3603 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3607 selPosition = curPosition;
3608 selBlock = textBlock;
3611 PositionCaret(false);
3617 curPosition = textBlock.textLen;
3620 selPosition = curPosition;
3621 selBlock = textBlock;
3624 PositionCaret(false);
3627 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3631 textBlock = textBlock.next.next;
3632 sy = textBlock.startY;
3633 sx = textBlock.startX;
3634 text = textBlock.text;
3639 sx = textBlock.startX;
3643 /*if(textBlock.next && textBlock.next.next)
3645 textBlock = textBlock.next.next;
3646 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3647 selBlock = textBlock;
3648 PositionCaret(false);
3652 case Key { right, shift = true, ctrl = true }:
3655 bool foundAlpha = false;
3657 Block line, lastLine;
3660 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3662 int start = (line == textBlock) ? curPosition : 0;
3664 for(c = start; c < line.textLen; c++)
3666 char ch = line.text[c];
3667 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3668 if(key.shift ? isAlUnder : !isAlUnder)
3682 selPosition = curPosition;
3683 selBlock = textBlock;
3687 PositionCaret(true);
3692 // No next word found,
3693 if(!found && (c != curPosition || line != textBlock))
3697 lastC = line.textLen-1;
3702 curPosition = line.textLen;
3705 selPosition = curPosition;
3706 selBlock = textBlock;
3711 PositionCaret(true);
3717 if(key.shift && found)
3719 curPosition = lastC+1;
3720 textBlock = lastLine;
3721 PositionCaret(true);
3726 case Key { left, ctrl = true, shift = true }:
3729 bool foundAlpha = false;
3731 Block line, lastLine;
3734 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3737 if(curPosition == 0 && line != textBlock)
3740 lastC = line.textLen;
3744 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3745 for(c = start; c>=0; c--)
3747 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3762 // No next word found,
3763 if(!found && curPosition > 0)
3773 textBlock = lastLine;
3774 curPosition = lastC;
3777 selPosition = curPosition;
3778 selBlock = textBlock;
3780 PositionCaret(true);
3785 case Key { right, shift = true }:
3787 if(curPosition < textBlock.textLen)
3789 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3792 selPosition = curPosition;
3793 selBlock = textBlock;
3795 PositionCaret(true);
3798 else if(textBlock.next && textBlock.next.next)
3800 textBlock = textBlock.next.next;
3804 selPosition = curPosition;
3805 selBlock = textBlock;
3807 PositionCaret(true);
3811 case Key { left, shift = true }:
3815 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3818 selPosition = curPosition;
3819 selBlock = textBlock;
3821 PositionCaret(true);
3824 else if(textBlock.prev)
3826 textBlock = textBlock.prev.prev;
3827 curPosition = textBlock.textLen;
3830 selPosition = curPosition;
3831 selBlock = textBlock;
3833 PositionCaret(true);
3839 if(textBlock == selBlock && curPosition == selPosition)
3843 int c = curPosition;
3845 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3846 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3847 textBlock.textLen -= nb;
3848 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3850 selPosition = curPosition;
3851 selBlock = textBlock;
3855 PositionCaret(true);
3858 else if(textBlock.prev)
3860 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3861 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3862 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3864 selPosition = curPosition = prevBlock.textLen;
3865 selBlock = textBlock;
3866 prevBlock.textLen += textBlock.textLen;
3867 textBlock.parent.subBlocks.Remove(prev);
3868 if(prev == selBlock)
3870 selBlock = textBlock;
3871 selPosition = curPosition;
3874 textBlock.parent.subBlocks.Remove(textBlock);
3875 if(textBlock == selBlock)
3877 selBlock = prevBlock;
3878 selPosition = curPosition;
3881 textBlock = prevBlock;
3885 PositionCaret(true);
3894 if(textBlock != selBlock || curPosition != selPosition)
3896 else if(textBlock.textLen > curPosition)
3898 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3899 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3900 textBlock.textLen -= nb;
3901 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3906 PositionCaret(true);
3909 else if(textBlock.next && textBlock.next.next)
3911 Block next = textBlock.next, nextBlock = textBlock.next.next;
3912 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3913 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3915 textBlock.textLen += nextBlock.textLen;
3916 textBlock.parent.subBlocks.Remove(next);
3917 if(next == selBlock)
3919 selBlock = textBlock;
3920 selPosition = curPosition;
3923 textBlock.parent.subBlocks.Remove(nextBlock);
3924 if(nextBlock == selBlock)
3926 selBlock = textBlock;
3927 selPosition = curPosition;
3933 PositionCaret(true);
3947 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3948 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3949 startY = textBlock.startY;
3950 startX = textBlock.startX;
3952 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3953 textBlock.parent.subBlocks.Insert(textBlock, block);
3954 textBlock.parent.subBlocks.Insert(block, newBlock);
3958 newBlock.textLen = textBlock.textLen - curPosition;
3959 newBlock.text = new char[newBlock.textLen+1];
3960 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3961 textBlock.textLen = curPosition;
3962 textBlock.text[curPosition] = 0;
3964 newBlock.startY = startY;
3965 newBlock.startX = startX;
3966 selPosition = curPosition = 0;
3971 textBlock = newBlock;
3972 selBlock = textBlock;
3973 PositionCaret(true);
3978 case Key { del, shift = true }:
3993 ClipBoard clipBoard { };
3994 if(clipBoard.Load())
3997 char * text = clipBoard.memory;
4005 parent = textBlock.parent;
4006 font = textBlock.font;
4011 if(ch == '\n' || ch == '\r' || !ch)
4013 int len = c - start;
4014 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4015 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4016 memcpy(textBlock.text + curPosition, text + start, len);
4017 textBlock.textLen += len;
4019 selPosition = curPosition;
4020 selBlock = textBlock;
4023 Block block { type = BR, parent = parent, font = font };
4024 Block newBlock { type = TEXT, parent = parent, font = font };
4025 int startY = textBlock.startY, startX = textBlock.startX;
4028 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4029 textBlock.parent.subBlocks.Insert(textBlock, block);
4030 textBlock.parent.subBlocks.Insert(block, newBlock);
4034 newBlock.textLen = textBlock.textLen - curPosition;
4035 newBlock.text = new char[newBlock.textLen+1];
4036 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4037 textBlock.textLen = curPosition;
4038 textBlock.text[curPosition] = 0;
4040 newBlock.startY = startY;
4041 newBlock.startX = startX;
4042 selPosition = curPosition = 0;
4043 selBlock = textBlock;
4044 textBlock = newBlock;
4046 if(ch == '\r' && text[c+1] == '\n') c++;
4052 PositionCaret(true);
4060 // eC BUG HERE: (Should be fixed)
4061 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4064 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4069 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4070 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4072 for(c = 0; c<len; c++)
4074 textBlock.text[curPosition] = string[c];
4075 textBlock.textLen++;
4078 selPosition = curPosition;
4079 selBlock = textBlock;
4082 //Clear(html.block);
4083 //CreateForms(html.block);
4088 PositionCaret(true);
4097 void OnResize(int width, int height)
4099 HTMLView::OnResize(width, height);
4100 PositionCaret(true);
4104 void PositionCaret(bool setCaretX)
4110 int sx = textBlock.startX, sy = textBlock.startY;
4111 char * text = textBlock.text;
4113 Block block = textBlock;
4114 while(block && block.type != TD) block = block.parent;
4117 Block table = block;
4118 while(table && table.type != TABLE) table = table.parent;
4120 maxW = block.w - 2* table.cellPadding;
4122 maxW = clientSize.w - 10 - sx;
4125 maxW = clientSize.w - 10 - sx;
4127 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4129 while(textPos < textBlock.textLen)
4131 int startPos = textPos;
4134 bool lineComplete = false;
4136 for(; textPos<textBlock.textLen && !lineComplete;)
4140 char * nextSpace = strchr(text + textPos, ' ');
4143 len = (nextSpace - (text + textPos)) + 1;
4145 len = textBlock.textLen - textPos;
4147 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4149 if(x + width + w > maxW && x > 0)
4151 lineComplete = true;
4164 if(curPosition < textPos || textPos == textBlock.textLen)
4166 int len = curPosition - startPos;
4167 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4172 sx = textBlock.startX;
4177 SetCaret(sx, sy, th);
4179 Point scrollPos = scroll;
4180 bool doScroll = false;
4181 if(sy - scroll.y + th > clientSize.h)
4183 scrollPos.y = sy + th - clientSize.h;
4186 else if(sy - scroll.y < 0)
4191 if(sx - scroll.x + 10 > clientSize.w)
4193 scrollPos.x = sx + 10 - clientSize.w;
4196 else if(sx - scroll.x < 10)
4198 scrollPos.x = sx - 10;
4209 // Returns a character offset into the TextBlock from a window coordinate
4210 int TextPosFromPoint(int px, int py, Block * block, bool half)
4212 Block parentBlock = this.textBlock.parent;
4215 *block = this.textBlock;
4220 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4222 int sx = textBlock.startX, sy = textBlock.startY;
4225 char * text = textBlock.text;
4227 Block b = textBlock;
4230 if(textBlock.type != TEXT) continue;
4232 while(b && b.type != TD) b = b.parent;
4236 while(table && table.type != TABLE) table = table.parent;
4238 maxW = b.w - 2* table.cellPadding;
4240 maxW = clientSize.w - 10 - sx;
4243 maxW = clientSize.w - 10 - sx;
4245 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4246 //space = space/2+2;
4249 while(textPos < textBlock.textLen)
4253 bool lineComplete = false;
4255 for(; textPos<textBlock.textLen && !lineComplete;)
4259 char * nextSpace = strchr(text + textPos, ' ');
4262 len = (nextSpace - (text + textPos)) + 1;
4264 len = textBlock.textLen - textPos;
4266 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4268 sx = x + textBlock.startX;
4269 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4274 for(c = textPos; (ch = text[c]); c += numBytes)
4276 numBytes = UTF8_NUM_BYTES(ch);
4277 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4278 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4285 if(x + width + w > maxW && x > 0)
4287 lineComplete = true;
4300 if(/*py >= sy && */py < sy + th)
4303 return textBlock.textLen;
4308 result = textBlock.textLen;
4314 Application componentsApp;
4316 class Documentor : GuiApplication
4320 Platform os = __runtimePlatform;
4321 SetGlobalContext(globalContext);
4322 SetExcludedSymbols(&excludedSymbols);
4323 SetDefines(&::defines);
4324 SetImports(&imports);
4325 SetInDocumentor(true);
4327 SetGlobalData(globalData);
4329 settingsContainer.dataOwner = &settings;
4330 settingsContainer.Load();
4331 if(!settings.docDir || !settings.docDir[0] )
4333 if(os == win32) // if Windows OS then
4335 char programFilesDir[MAX_LOCATION];
4336 char appData[MAX_LOCATION];
4337 char homeDrive[MAX_LOCATION];
4338 char winDir[MAX_LOCATION];
4339 GetEnvironment("APPDATA", appData, sizeof(appData));
4340 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4341 GetEnvironment("windir", winDir, sizeof(winDir));
4342 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4344 PathCat(programFilesDir, "ECERE SDK\\doc");
4345 settings.docDir = programFilesDir;
4347 else if(homeDrive[0])
4349 PathCat(homeDrive, "ECERE SDK\\doc");
4350 settings.docDir = homeDrive;
4354 PathCat(winDir, "..\\ECERE SDK\\doc");
4355 settings.docDir = winDir;
4358 settings.docDir = "C:\\ECERE SDK\\doc";
4360 else // if Os is Linux, or Mac OSX or something else
4361 settings.docDir = "/usr/share/ecere/doc/";
4362 settingsContainer.Save();
4368 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4370 AddComponents(module, true);
4371 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4372 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4373 while((row = row.parent))
4374 row.collapsed = false;
4378 commandThread.Create();
4382 bool Cycle(bool idle)
4385 mainForm.Destroy(0);
4394 if(commandThread.created)
4396 console.CloseInput();
4397 console.CloseOutput();
4399 commandThread.Wait();
4403 FreeContext(globalContext);
4404 FreeExcludedSymbols(excludedSymbols);
4405 ::defines.Free(FreeModuleDefine);
4406 imports.Free(FreeModuleImport);
4408 FreeGlobalData(globalData);
4409 FreeTypeData(componentsApp);
4411 delete componentsApp;
4415 ConsoleFile console { };
4416 MainForm mainForm { };
4419 Thread commandThread
4426 console.GetLine(command, sizeof(command));
4427 if(!quit && command[0])
4430 if(!strcmpi(command, "Activate"))
4431 mainForm.Activate();
4432 else if(!strcmpi(command, "Quit"))
4440 #endif // !defined(EAR_TO_ECON_ECDOC)
4445 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4446 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4450 property bool isEmpty
4456 (description && *description));
4466 class MoreDoc : ItemDoc
4469 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4470 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4471 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4472 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4478 property bool isEmpty
4483 (usage && *usage) ||
4484 (example && *example) ||
4485 (remarks && *remarks) ||
4499 class NamespaceDoc : ItemDoc
4502 Map<String, DefineDoc> defines;
4503 Map<String, FunctionDoc> functions;
4505 property bool isEmpty
4510 (defines && defines.count) ||
4511 (functions && functions.count) ||
4522 class DefineDoc : ItemDoc { }
4524 class FunctionDoc : MoreDoc
4527 Map<String, ParameterDoc> parameters;
4528 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4531 property bool isEmpty
4536 (parameters && parameters.count) ||
4537 (returnValue && *returnValue) ||
4548 class ParameterDoc : ItemDoc
4554 class ClassDoc : MoreDoc
4557 Map<String, ValueDoc> values;
4558 Map<String, FieldDoc> fields;
4559 Map<String, PropertyDoc> properties;
4560 Map<String, ConversionDoc> conversions;
4561 Map<String, MethodDoc> methods;
4563 property bool isEmpty
4568 (values && values.count) ||
4569 (fields && fields.count) ||
4570 (properties && properties.count) ||
4571 (conversions && conversions.count) ||
4572 (methods && methods.count) ||
4586 class ValueDoc : ItemDoc { }
4588 class FieldDoc : ItemDoc { }
4590 class PropertyDoc : ItemDoc { }
4592 class ConversionDoc : ItemDoc { }
4594 class MethodDoc : FunctionDoc { }
4596 char * getDocFileNameFromTypeName(const char * typeName)
4598 char * docFileName = new char[MAX_FILENAME];
4599 const char * swap = "pointer";
4600 const char * s = typeName;
4601 char * d = docFileName;
4602 const char * end = s + strlen(typeName);
4603 int swapLen = strlen(swap);
4632 Map<const String, DocCacheEntry> docCache { };