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 // The filePath is returned!
721 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
725 Method method = null;
731 case classDoc: cl = (Class)object; break;
732 case methodDoc: method = object; cl = method._class; break;
735 FigureFilePath(filePath, module, type, object, item, data);
737 entry = docCache[filePath];
743 File f = FileOpen(filePath, read);
746 JSONParser parser { f = f, eCON = true };
747 JSONResult jsonResult;
748 jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
752 if(jsonResult != success)
754 PrintLn("error: problem parsing file: ", filePath);
759 doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
762 incref doc; // Reference to return
767 entry.timeStamp = now;
770 docCache[filePath] = { now, doc };
771 incref doc; // Reference for the cache
774 //void pruneDocCache()
775 // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
777 MapIterator<String, DocCacheEntry> it { map = docCache };
778 Array<const String> toRemove { };
779 for(entry : docCache; now - entry.timeStamp > 30)
780 toRemove.Add(&entry);
781 while(toRemove.count)
783 if(it.Index(toRemove.lastIterator.data, false))
788 toRemove.Remove(toRemove.lastIterator.pointer);
795 class APIPageNameSpace : APIPage
797 NameSpace * nameSpace;
805 NameSpace * GetNameSpace()
810 void Generate(File f)
812 char nsName[1024], temp[1024];
818 while(ns && ns->name)
820 strcpy(temp, ns->name);
821 if(nsName[0]) strcat(temp, "::");
822 strcat(temp, nsName);
823 strcpy(nsName, temp);
826 // Generate Class Page
827 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
830 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
831 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);
834 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
837 ns = nameSpace->parent;
838 while(ns && ns->name)
840 strcpy(temp, ns->name);
841 if(nsName[0]) strcat(temp, "::");
842 strcat(temp, nsName);
843 strcpy(nsName, temp);
847 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
851 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
854 f.Printf($"<H3>Description</H3><br><br>\n");
857 char fileName[MAX_LOCATION];
858 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
859 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
861 f.Printf("</a><br><br>");
864 f.Printf("%s<br><br>", desc);
869 if(nameSpace->nameSpaces.first)
872 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
874 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
877 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
878 f.Printf("<TABLE>\n");
882 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);
887 char fileName[MAX_LOCATION];
888 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
889 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
891 f.Printf("</a></TD>");
894 f.Printf("<TD valign=top height=22> %s</TD>", desc);
897 f.Printf("</TR><br>\n");
900 f.Printf("</TABLE><br>\n");
903 if(nameSpace->classes.first)
906 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
908 Class cl = link.data;
909 if(!cl.templateClass)
911 char * desc = ReadDoc(module, classDoc, cl, description, null);
915 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
916 f.Printf("<TABLE>\n");
922 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);
927 char fileName[MAX_LOCATION];
928 FigureFileName(fileName, module, classDoc, cl, description, null);
929 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
931 f.Printf("</a></TD>");
934 f.Printf("<TD valign=top height=22>%s</TD>", desc);
941 f.Printf("</TABLE><br>\n");
944 if(nameSpace->functions.first)
947 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
949 GlobalFunction function = link.data;
950 char * desc = ReadDoc(module, functionDoc, function, description, null);
951 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
952 if(name) name += 2; else name = function.name;
955 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
956 f.Printf("<TABLE>\n");
960 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);
965 char fileName[MAX_LOCATION];
966 FigureFileName(fileName, module, functionDoc, function, description, null);
967 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
969 f.Printf("</a></TD>");
972 f.Printf("<TD valign=top height=22> %s</TD>", desc);
975 f.Printf("</TR><br>\n");
978 f.Printf("</TABLE><br>\n");
981 if(nameSpace->defines.first)
984 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
986 DefinedExpression def = link.data;
987 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
990 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
991 f.Printf("<TABLE>\n");
995 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);
996 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
1001 char fileName[MAX_LOCATION];
1002 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
1003 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1005 f.Printf("</a></TD>");
1008 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1011 f.Printf("</TR><br>\n");
1014 f.Printf("</TABLE><br>\n");
1017 f.Printf("</FONT></BODY></HTML>\n");
1021 class APIPageClass : APIPage
1030 NameSpace * GetNameSpace()
1032 return cl.nameSpace;
1035 void Generate(File f)
1040 char nsName[1024], temp[1024];
1041 NameSpace * ns = cl.nameSpace;
1042 Module module = cl.module;
1045 while(ns && ns->name)
1047 strcpy(temp, ns->name);
1048 if(nsName[0]) strcat(temp, "::");
1049 strcat(temp, nsName);
1050 strcpy(nsName, temp);
1053 // Generate Class Page
1054 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1055 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1057 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);
1059 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1062 const char * classType = null;
1066 classType = $"Bit Collection";
1069 classType = $"Enumeration";
1072 classType = $"Structure";
1075 classType = $"Class";
1078 classType = $"Class (No header)";
1081 classType = $"Unit";
1084 classType = $"Basic Data Type";
1087 f.Printf($"Type: %s<br>\n", classType);
1090 if(cl.type != systemClass && cl.base)
1092 f.Printf($"Base Class: ");
1093 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1095 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1097 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1098 f.Printf("%s", cl.dataTypeString);
1100 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1105 char * desc = ReadDoc(module, classDoc, cl, description, null);
1108 f.Printf($"<br><H3>Description</H3><br><br>\n");
1111 char fileName[MAX_LOCATION];
1112 FigureFileName(fileName, module, classDoc, cl, description, null);
1113 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1115 f.Printf("</a><br><br>");
1118 f.Printf("%s<br><br>", desc);
1123 if(cl.type == enumClass)
1125 EnumClassData enumeration = (EnumClassData)cl.data;
1126 if(enumeration.values.first)
1130 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
1131 f.Printf("<TABLE>\n");
1133 for(item = enumeration.values.first; item; item = item.next)
1135 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1136 bool needClass = true;
1139 char tempString[1024];
1141 while(base.type == enumClass) base = base.base;
1143 if(base.type == systemClass ||
1144 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1147 base.dataType = ProcessTypeString(base.dataTypeString, false);
1149 if(base.dataType.kind != classType)
1154 PrintType(base.dataType, string, false, true);
1155 classSym = FindClass(string);
1156 dataClass = classSym ? classSym.registered : null;
1159 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1165 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);
1166 if(dataClass.type == systemClass)
1169 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1172 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1174 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1176 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1181 char fileName[MAX_LOCATION];
1182 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1183 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1185 f.Printf("</a></TD>");
1188 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1193 f.Printf("</TABLE><BR>\n");
1197 if(cl.conversions.first)
1199 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
1200 f.Printf("<TABLE>\n");
1201 for(prop = cl.conversions.first; prop; prop = prop.next)
1203 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1205 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1207 Type type = ProcessTypeString(prop.name, false);
1208 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1209 if(name) name += 2; else name = prop.name;
1214 DocPrintType(type, string, true, false);
1216 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1221 char fileName[MAX_LOCATION];
1222 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1223 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1225 f.Printf("</a></TD>");
1228 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1232 f.Printf("</TR>\n");
1237 f.Printf("</TABLE><br>\n");
1240 if(cl.membersAndProperties.first)
1243 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1245 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1249 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1250 f.Printf("<TABLE>\n");
1256 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1258 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1262 DocPrintType(prop.dataType, string, true, false);
1264 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);
1265 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1270 char fileName[MAX_LOCATION];
1271 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1272 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1274 f.Printf("</a></TD>");
1277 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1280 f.Printf("</TR>\n");
1284 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1289 f.Printf("</TABLE><br>\n");
1292 if(cl.methods.first)
1296 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1298 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1300 char * desc = ReadDoc(module, methodDoc, method, description, null);
1303 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1304 f.Printf("<TABLE>\n");
1307 if(!method.dataType)
1308 ProcessMethodType(method);
1311 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);
1316 char fileName[MAX_LOCATION];
1317 FigureFileName(fileName, module, methodDoc, method, description, null);
1318 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1320 f.Printf("</a></TD>");
1323 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1326 f.Printf("</TR><br>\n");
1330 f.Printf("</TABLE><br>\n");
1332 // Non-Virtual Methods
1334 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1336 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1338 char * desc = ReadDoc(module, methodDoc, method, description, null);
1341 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1342 f.Printf("<TABLE>\n");
1346 if(!method.dataType)
1347 ProcessMethodType(method);
1350 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);
1355 char fileName[MAX_LOCATION];
1356 FigureFileName(fileName, module, methodDoc, method, description, null);
1357 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1359 f.Printf("</a></TD>");
1362 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1366 f.Printf("</TR><br>\n");
1370 f.Printf("</TABLE><br>\n");
1373 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1376 f.Printf($"<H3>Usage</H3><br>\n");
1379 char fileName[MAX_LOCATION];
1380 FigureFileName(fileName, module, classDoc, cl, usage, null);
1381 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1386 f.Printf("<br>%s\n", usageDoc);
1387 f.Printf("<br><br>\n");
1392 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1395 f.Printf($"<H3>Example</H3><br>\n");
1396 f.Printf($"<FONT face=\"Courier New\">\n");
1397 f.Printf("<br><TABLE>\n");
1400 char fileName[MAX_LOCATION];
1401 FigureFileName(fileName, module, classDoc, cl, example, null);
1402 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1404 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1407 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1409 f.Printf("</TABLE></FONT>\n");
1415 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1419 f.Printf($"<H3>Remarks</H3><br>\n");
1422 char fileName[MAX_LOCATION];
1423 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1424 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1429 f.Printf("<br>%s\n", remarksDoc);
1430 f.Printf("<br><br>\n");
1435 if(cl.type != systemClass)
1439 for(c = cl.derivatives.first; c; c = c.next)
1441 Class deriv = c.data;
1442 // TO VERIFY: Does this properly check public status?
1443 if(eSystem_FindClass(componentsApp, deriv.fullName))
1447 f.Printf($"<H3>Derived Classes</H3><br>\n");
1453 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1457 f.Printf("<br><br>\n");
1460 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1463 f.Printf($"<H3>See Also</H3><br>\n");
1466 char fileName[MAX_LOCATION];
1467 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1468 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1473 f.Printf("<br>%s\n", seeAlsoDoc);
1474 f.Printf("<br><br>\n");
1478 f.Printf("</FONT></BODY></HTML>\n");
1482 class APIPageMethod : APIPage
1488 return method._class.module;
1491 NameSpace * GetNameSpace()
1493 return method._class.nameSpace;
1496 void Generate(File f)
1498 Class cl = method._class;
1500 Module module = cl.module;
1502 char nsName[1024], temp[1024];
1503 NameSpace * ns = cl.nameSpace;
1506 while(ns && ns->name)
1508 strcpy(temp, ns->name);
1509 if(nsName[0]) strcat(temp, "::");
1510 strcat(temp, nsName);
1511 strcpy(nsName, temp);
1515 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1516 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1518 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);
1520 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1521 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1522 if(method.dataType.staticMethod)
1524 f.Printf($"this pointer class: None<br>\n");
1526 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1528 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);
1531 // Generate Method Page
1533 if(!method.dataType.name)
1534 method.dataType.name = CopyString(method.name);
1535 DocPrintType(method.dataType, string, true, false);
1536 f.Printf("<br>%s", string);
1539 char * desc = ReadDoc(module, methodDoc, method, description, null);
1542 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1545 char fileName[MAX_LOCATION];
1546 FigureFileName(fileName, module, methodDoc, method, description, null);
1547 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1552 f.Printf("%s", desc);
1557 f.Printf("<br><br>\n");
1558 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1560 f.Printf($"<H3>Parameters</H3><br><br>\n");
1562 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1563 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1565 f.Printf("<TABLE valign=center>\n");
1568 for(param = method.dataType.params.first; param; param = param.next)
1570 // ADD DESCRIPTION HERE
1571 if(param.kind != voidType)
1573 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1576 DocPrintType(param, string, false, false);
1578 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1579 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1584 char fileName[MAX_LOCATION];
1585 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1586 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1588 f.Printf("</a></TD>\n");
1591 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1595 f.Printf("</TR>\n");
1598 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1600 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1601 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1603 f.Printf("<TR><TD> </TD></TR>");
1606 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1608 DocPrintType(method.dataType.returnType, string, false, false);
1609 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1614 char fileName[MAX_LOCATION];
1615 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1616 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1618 f.Printf("</a> </TD>\n");
1621 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1624 f.Printf("</TR>\n");
1625 f.Printf("</TABLE>\n");
1627 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1628 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1630 f.Printf("</TABLE><br>\n");
1633 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1636 f.Printf($"<H3>Usage</H3><br>\n");
1639 char fileName[MAX_LOCATION];
1640 FigureFileName(fileName, module, methodDoc, method, usage, null);
1641 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1646 f.Printf("<br>%s\n", usageDoc);
1647 f.Printf("<br><br>\n");
1652 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1655 f.Printf($"<H3>Example</H3><br>\n");
1656 f.Printf($"<FONT face=\"Courier New\">\n");
1657 f.Printf("<br><TABLE>\n");
1660 char fileName[MAX_LOCATION];
1661 FigureFileName(fileName, module, methodDoc, method, example, null);
1662 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1664 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1667 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1668 f.Printf("</TABLE></FONT>\n");
1674 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1677 f.Printf($"<H3>Remarks</H3><br>\n");
1680 char fileName[MAX_LOCATION];
1681 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1682 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1687 f.Printf("<br>%s\n", method, remarksDoc);
1688 f.Printf("<br><br>\n");
1693 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1696 f.Printf($"<H3>See Also</H3><br>\n");
1699 char fileName[MAX_LOCATION];
1700 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1701 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1706 f.Printf("<br>%s\n", method, seeAlsoDoc);
1708 f.Printf("<br><br>\n");
1712 f.Printf("</FONT></BODY></HTML>\n");
1716 class APIPageFunction : APIPage
1718 GlobalFunction function;
1722 return function.module;
1725 NameSpace * GetNameSpace()
1727 return function.nameSpace;
1730 void Generate(File f)
1733 Module module = function.module;
1735 char nsName[1024], temp[1024];
1736 NameSpace * ns = function.nameSpace;
1739 while(ns && ns->name)
1741 strcpy(temp, ns->name);
1742 if(nsName[0]) strcat(temp, "::");
1743 strcat(temp, nsName);
1744 strcpy(nsName, temp);
1748 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1749 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1751 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);
1754 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1756 if(!function.dataType)
1757 function.dataType = ProcessTypeString(function.dataTypeString, false);
1759 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1761 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);
1764 // Generate Method Page
1766 if(!function.dataType.name)
1767 function.dataType.name = CopyString(function.name);
1768 DocPrintType(function.dataType, string, true, false);
1769 f.Printf("<br>%s", string);
1772 char * desc = ReadDoc(module, functionDoc, function, description, null);
1775 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1778 char fileName[MAX_LOCATION];
1779 FigureFileName(fileName, module, functionDoc, function, description, null);
1780 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1785 f.Printf("%s", desc);
1789 f.Printf("<br><br>\n");
1790 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1792 f.Printf($"<H3>Parameters</H3><br><br>\n");
1794 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1795 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1797 f.Printf("<TABLE valign=center>\n");
1800 for(param = function.dataType.params.first; param; param = param.next)
1802 // ADD DESCRIPTION HERE
1803 if(param.kind != voidType)
1805 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1808 DocPrintType(param, string, false, false);
1810 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1811 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1816 char fileName[MAX_LOCATION];
1817 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1818 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1821 f.Printf("</a> </TD>\n");
1824 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1827 f.Printf("</TR>\n");
1830 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1832 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1833 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1835 f.Printf("<TR><TD> </TD></TR>");
1838 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1840 DocPrintType(function.dataType.returnType, string, false, false);
1841 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1846 char fileName[MAX_LOCATION];
1847 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1848 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1850 f.Printf("</a> </TD>\n");
1853 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1856 f.Printf("</TR>\n");
1857 f.Printf("</TABLE>\n");
1859 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1860 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1862 f.Printf("</TABLE><br>\n");
1865 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1868 f.Printf($"<H3>Usage</H3><br>\n");
1871 char fileName[MAX_LOCATION];
1872 FigureFileName(fileName, module, functionDoc, function, usage, null);
1873 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1878 f.Printf("<br>%s\n", usageDoc);
1879 f.Printf("<br><br>\n");
1884 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1887 f.Printf($"<H3>Example</H3><br>\n");
1888 f.Printf($"<FONT face=\"Courier New\">\n");
1889 f.Printf("<br><TABLE>\n");
1892 char fileName[MAX_LOCATION];
1893 FigureFileName(fileName, module, functionDoc, function, example, null);
1894 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1896 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1899 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1900 f.Printf("</TABLE></FONT>\n");
1906 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1909 f.Printf($"<H3>Remarks</H3><br>\n");
1912 char fileName[MAX_LOCATION];
1913 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1914 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1919 f.Printf("<br>%s\n", remarksDoc);
1920 f.Printf("<br><br>\n");
1925 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1928 f.Printf($"<H3>See Also</H3><br>\n");
1931 char fileName[MAX_LOCATION];
1932 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1933 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1938 f.Printf("<br>%s\n", seeAlsoDoc);
1939 f.Printf("<br><br>\n");
1943 f.Printf("</FONT></BODY></HTML>\n");
1947 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1951 NameSpace * nameSpace = mainNameSpace;
1953 DataRow classesRow = null;
1954 DataRow functionsRow = null, definesRow = null;
1957 strcpy(nsName, parentName ? parentName : "");
1961 strcat(nsName, "::");
1962 strcat(nsName, nameSpace->name);
1967 row = parentRow.AddRow();
1968 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1969 row.tag = (int64)nameSpace;
1970 row.icon = mainForm.icons[typeNameSpace];
1974 // "Global NameSpace"
1976 page = parentRow.GetData(null);
1979 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1981 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1982 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1984 if(comNameSpace != null)
1986 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1988 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1990 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1995 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1997 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1999 if(nameSpace->classes.first)
2003 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
2006 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
2008 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
2009 AddClass(classesRow, module, cl, nsName, showPrivate);
2016 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2018 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2020 if(nameSpace->functions.first)
2024 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2027 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2029 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2031 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2032 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2039 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2041 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2043 if(nameSpace->defines.first)
2047 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2050 //if(def.module == module)
2052 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2054 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2055 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2063 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2067 if(!member.dataType)
2068 member.dataType = ProcessTypeString(member.dataTypeString, false);
2072 DocPrintType(member.dataType, string, true, false);
2074 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2075 for(c = 0; c<indent; c++)
2076 f.Printf(" ");
2077 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2078 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2079 if(member.type == normalMember)
2081 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2086 char fileName[MAX_LOCATION];
2087 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2088 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2090 f.Printf("</a></TD>");
2093 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2098 f.Printf("<TD valign=top height=22></TD>");
2100 if(member.type != normalMember)
2102 DataMember subMember;
2103 for(subMember = member.members.first; subMember; subMember = subMember.next)
2105 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2107 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2111 f.Printf("</TR><br>\n");
2114 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2117 if(member.type == normalMember)
2119 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2120 row.tag = (int64)member;
2125 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2126 row.icon = mainForm.icons[typeData];
2127 row.tag = (int64)member;
2129 for(m = member.members.first; m; m = m.next)
2131 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2132 AddDataMember(row, page, m);
2137 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2142 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2143 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2146 row = parentRow.AddRow();
2147 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2148 row.tag = (int64)cl;
2149 row.collapsed = true;
2150 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2153 if(cl.methods.first)
2155 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2157 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2160 if(!method.dataType)
2161 ProcessMethodType(method);
2162 if(method.type == virtualMethod)
2164 if(method.dataType.thisClass)
2166 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2167 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2168 mRow.tag = (int64)method;
2172 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2173 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2174 mRow.tag = (int64)method;
2179 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2180 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2181 mRow.tag = (int64)method;
2187 if(cl.membersAndProperties.first)
2189 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2191 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2194 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2198 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2199 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2200 mRow.tag = (int64)prop;
2204 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2205 AddDataMember(membersRow, page, (DataMember)prop);
2211 if(cl.conversions.first)
2213 for(prop = cl.conversions.first; prop; prop = prop.next)
2217 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2218 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2219 if(name) name += 2; else name = prop.name;
2220 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2221 mRow.tag = (int64)prop;
2224 if(cl.type == enumClass)
2226 EnumClassData enumeration = (EnumClassData)cl.data;
2228 for(item = enumeration.values.first; item; item = item.next)
2231 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2232 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2233 mRow.tag = (int64)item;
2238 class AddressBar : Window
2240 background = activeBorder;
2244 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2246 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2248 MainForm mainForm = (MainForm)parent;
2249 FileDialog fileDialog = mainForm.fileDialog;
2250 if(fileDialog.Modal() == ok)
2251 mainForm.OpenModule(fileDialog.filePath);
2257 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2260 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2262 ((MainForm)parent).Back();
2268 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2271 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2273 ((MainForm)parent).Forward();
2279 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2281 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2283 ((MainForm)parent).Home();
2287 /* TODO: Search (#143/#441)
2288 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2289 Update this in the NotifyUpdate. Enter goes to the exact match.
2291 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2295 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2297 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2299 if(!disabled && (SmartKey)key == enter)
2300 ((MainForm)parent).Go(editBox.contents);
2304 void NotifyUpdate(EditBox editBox)
2306 String location = ((MainForm)parent).view.location;
2307 disabled = !strcmp(location ? location : "", editBox.contents);
2312 bool OnKeyHit(Key key, unichar ch)
2315 ((MainForm)parent).view.MakeActive();
2320 class MainForm : Window
2322 size = { 1000, 600 };
2324 borderStyle = sizable;
2327 icon = { ":documentorIcon.png" };
2328 text = $"API Documentation Browser";
2330 BitmapResource icons[CodeObjectType];
2335 for(c = 0; c < CodeObjectType::enumSize; c++)
2337 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2339 browser.AddField(DataField { dataType = class(APIPage) });
2344 Menu fileMenu { menu, $"File", f };
2345 Array<FileFilter> fileFilters
2347 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2348 { $"eC Symbol files (*.sym)", "sym" }
2351 FileDialog fileDialog
2353 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2355 MenuItem fileOpenItem
2357 fileMenu, $"Open...", o, ctrlO;
2359 bool NotifySelect(MenuItem selection, Modifiers mods)
2361 if(fileDialog.Modal() == ok)
2363 OpenModule(fileDialog.filePath);
2368 MenuItem fileSettingsItem
2370 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2372 bool NotifySelect(MenuItem selection, Modifiers mods)
2374 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2384 MenuDivider { fileMenu };
2385 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2387 void OpenModule(const char * filePath)
2389 char moduleName[MAX_LOCATION];
2390 char extension[MAX_EXTENSION];
2391 Module module = null;
2392 static char symbolsDir[MAX_LOCATION];
2396 FreeContext(globalContext);
2397 FreeExcludedSymbols(excludedSymbols);
2398 ::defines.Free(FreeModuleDefine);
2399 imports.Free(FreeModuleImport);
2401 FreeGlobalData(globalData);
2405 FreeTypeData(componentsApp);
2406 delete componentsApp;
2409 componentsApp = __ecere_COM_Initialize(false, 1, null);
2410 SetPrivateModule(componentsApp);
2412 StripLastDirectory(filePath, symbolsDir);
2413 SetSymbolsDir(symbolsDir);
2415 GetExtension(filePath, extension);
2417 mainForm.browser.Clear();
2419 ImportModule(filePath, normalImport, publicAccess, false);
2421 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2422 componentsApp.name = CopyString(filePath);
2424 for(module = componentsApp.allModules.first; module; module = module.next)
2426 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2430 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2431 AddComponents(componentsApp, false);
2433 GetLastDirectory(filePath, moduleName);
2434 // Extension, path and lib prefix get removed in Module::name
2437 StripExtension(moduleName);
2438 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2440 int len = strlen(moduleName) - 3;
2441 memmove(moduleName, moduleName + 3, len);
2442 moduleName[len] = 0;
2446 for(module = componentsApp.allModules.first; module; module = module.next)
2448 if(module.name && (!strcmp(module.name, moduleName)))
2451 if(!module) module = componentsApp;
2452 homeModule = module;
2453 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2455 SetSymbolsDir(null);
2458 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2461 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2462 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2465 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2467 APIPage page = row.GetData(null);
2468 if(view.edit) view.OnLeftButtonDown(0,0,0);
2469 if(page && page.page) page = page.page;
2471 view.PositionCaret(true);
2472 if(page != view.page)
2474 Window activeChild = this.activeChild;
2476 // Back / Forward Support
2477 if(row && !dontRecordHistory)
2479 if(history.count > historyPos+1)
2480 history.count = historyPos+1;
2481 historyPos = history.count-1;
2482 addressBar.back.disabled = (historyPos == 0);
2483 addressBar.forward.disabled = (historyPos >= history.count-1);
2485 history.Add((Instance)(uint64)row.tag);
2486 historyPos = history.count-1;
2488 addressBar.back.disabled = (historyPos == 0);
2489 addressBar.forward.disabled = (historyPos >= history.count-1);
2495 activeChild.Activate();
2497 else if(!view.created)
2501 page = row.GetData(null);
2502 if(page && page.page)
2506 case 1: view.GoToAnchor("Classes"); break;
2507 case 2: view.GoToAnchor("Functions"); break;
2508 case 3: view.GoToAnchor("Definitions"); break;
2509 case 4: view.GoToAnchor("VirtualMethods"); break;
2510 case 5: view.GoToAnchor("Methods"); break;
2511 case 6: view.GoToAnchor("Members"); break;
2512 case 7: view.GoToAnchor("Conversions"); break;
2513 case 8: view.GoToAnchor("EnumerationValues"); break;
2517 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2518 view.GoToAnchor(hex);
2524 view.SetScrollPosition(0, 0);
2532 this, anchor = { top = 26, bottom = 0, right = 0 };
2537 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2540 bool OnClose(bool parentClosing)
2543 view.OnLeftButtonDown(0,0,0);
2549 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2550 //mainForm.OpenModule("ec");
2551 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2552 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2554 int index = mainForm.browser.currentRow.index;
2555 int rowHeight = mainForm.browser.rowHeight;
2556 int height = mainForm.browser.clientSize.h;
2558 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2563 Array<Instance> history { };
2565 bool dontRecordHistory;
2570 if(historyPos < history.count-1)
2574 addressBar.back.disabled = (historyPos == 0);
2575 addressBar.forward.disabled = (historyPos >= history.count-1);
2576 sprintf(location, "api://%p", history[historyPos]);
2577 dontRecordHistory = true;
2578 view.OnOpen(location);
2579 dontRecordHistory = false;
2591 addressBar.back.disabled = (historyPos == 0);
2592 addressBar.forward.disabled = (historyPos >= history.count-1);
2593 sprintf(location, "api://%p", history[historyPos]);
2594 dontRecordHistory = true;
2595 view.OnOpen(location);
2596 dontRecordHistory = false;
2604 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2608 class EditDialog : Window
2610 borderStyle = sizable;
2611 size = { 600, 400 };
2616 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2620 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2624 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2628 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2629 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2631 class HelpView : HTMLView
2635 hasVertScroll = true;
2636 hasHorzScroll = true;
2638 char editString[MAX_LOCATION];
2644 page = mainForm.browser.currentRow.GetData(null);
2649 char docDir[MAX_LOCATION];
2651 strcpy(docDir, settings.docDir);
2652 if(FileExists(docDir).isDirectory)
2654 PathCatSlash(docDir, "___docWriteTest");
2655 if(FileExists(docDir).isDirectory)
2658 if(!FileExists(docDir))
2664 if(FileExists(docDir).isDirectory)
2676 GoToAnchor(page.label);
2678 if(page.page) page = page.page;
2681 return HTMLView::OnCreate();
2692 String contents = null;
2695 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2697 if(block.type == TEXT && block.textLen)
2705 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2707 if(block.type == BR)
2709 else if(block.type == TEXT)
2710 f.Write(block.text, 1, block.textLen);
2714 if((len = f.GetSize()))
2716 contents = new char[len+1];
2717 f.Read(contents, 1, len);
2718 contents[len] = '\0';
2722 char docPath[MAX_LOCATION];
2723 char temp[MAX_LOCATION];
2724 char part[MAX_FILENAME];
2728 DocumentationType type;
2729 DocumentationItem item;
2731 bool docRetrieved = false;
2732 NamespaceDoc nsDoc = null;
2733 ClassDoc clDoc = null;
2734 FunctionDoc fnDoc = null;
2735 MethodDoc mdDoc = null;
2737 Method method = null;
2738 GlobalFunction function = null;
2740 strcpy(temp, editString);
2741 SplitDirectory(temp, part, temp);
2742 module = (Module)strtoull(part, null, 16);
2743 SplitDirectory(temp, part, temp);
2744 object = (void *)strtoull(part, null, 16);
2745 SplitDirectory(temp, part, temp);
2746 data = (void *)strtoull(part, null, 16);
2747 SplitDirectory(temp, part, temp);
2748 if(!strcmp(part, "namespace"))
2749 type = nameSpaceDoc;
2750 else if(!strcmp(part, "function"))
2752 else if(!strcmp(part, "class"))
2754 else if(!strcmp(part, "method"))
2756 SplitDirectory(temp, part, temp);
2757 if(!strcmp(part, "description"))
2759 else if(!strcmp(part, "usage"))
2761 else if(!strcmp(part, "remarks"))
2763 else if(!strcmp(part, "example"))
2765 else if(!strcmp(part, "seeAlso"))
2767 else if(!strcmp(part, "enumerationValue"))
2768 item = enumerationValue;
2769 else if(!strcmp(part, "definition"))
2771 else if(!strcmp(part, "conversion"))
2773 else if(!strcmp(part, "memberDescription"))
2774 item = memberDescription;
2775 else if(!strcmp(part, "propertyDescription"))
2776 item = propertyDescription;
2777 else if(!strcmp(part, "parameter"))
2779 else if(!strcmp(part, "returnValue"))
2782 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2784 /* Why invalidate this entry here?
2786 MapIterator<const String, DocCacheEntry> it { map = docCache };
2787 if(it.Index(docPath, false))
2796 case classDoc: cl = (Class)object; break;
2797 case functionDoc: function = object; break;
2798 case methodDoc: method = object; cl = method._class; break;
2803 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2805 clDoc = (ClassDoc)doc;
2806 docRetrieved = true;
2808 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2810 nsDoc = (NamespaceDoc)doc;
2811 docRetrieved = true;
2817 if(type == functionDoc)
2819 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2820 if(name) name += 2; else name = function.name;
2821 if(!nsDoc.functions && !empty) nsDoc.functions = { };
2822 fnDoc = nsDoc.functions[name];
2823 if(!fnDoc && !empty)
2826 nsDoc.functions[name] = fnDoc;
2829 else if(type == methodDoc)
2831 if(!clDoc.methods && !empty) clDoc.methods = { };
2832 mdDoc = clDoc.methods[method.name];
2833 if(!mdDoc && !empty)
2836 clDoc.methods[method.name] = mdDoc;
2840 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2845 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2846 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2847 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2848 else { nsDoc.description = contents; contents = null; }
2851 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2852 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2853 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2856 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2857 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2858 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2861 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2862 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2863 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2866 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2867 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2868 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2871 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2872 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2874 case enumerationValue:
2877 if(!clDoc.values) clDoc.values = { };
2878 itDoc = clDoc.values[((NamedLink)data).name];
2882 clDoc.values[((NamedLink)data).name] = itDoc;
2884 itDoc.description = contents; contents = null;
2890 if(!nsDoc.defines) nsDoc.defines = { };
2891 itDoc = nsDoc.defines[((Definition)data).name];
2895 nsDoc.defines[((Definition)data).name] = itDoc;
2897 itDoc.description = contents; contents = null;
2902 ConversionDoc itDoc;
2903 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2904 if(name) name += 2; else name = ((Property)data).name;
2905 if(!clDoc.conversions) clDoc.conversions = { };
2906 itDoc = clDoc.conversions[name];
2910 clDoc.conversions[name] = itDoc;
2912 itDoc.description = contents; contents = null;
2915 case memberDescription:
2918 if(!clDoc.fields) clDoc.fields = { };
2919 itDoc = clDoc.fields[((DataMember)data).name];
2923 clDoc.fields[((DataMember)data).name] = itDoc;
2925 itDoc.description = contents; contents = null;
2928 case propertyDescription:
2931 if(!clDoc.properties) clDoc.properties = { };
2932 itDoc = clDoc.properties[((Property)data).name];
2936 clDoc.properties[((Property)data).name] = itDoc;
2938 itDoc.description = contents; contents = null;
2946 for(prev = data; prev; prev = prev.prev);
2947 name = ((Type)data).name;
2948 if(type == functionDoc)
2950 if(!fnDoc.parameters) fnDoc.parameters = { };
2951 itDoc = fnDoc.parameters[name];
2955 fnDoc.parameters[name] = itDoc;
2957 itDoc.description = contents; contents = null;
2959 else if(type == methodDoc)
2961 if(!mdDoc.parameters) mdDoc.parameters = { };
2962 itDoc = mdDoc.parameters[name];
2966 mdDoc.parameters[name] = itDoc;
2968 itDoc.description = contents; contents = null;
2976 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
2978 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
2979 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2980 if(name) name += 2; else name = function.name;
2981 if(it.Index(name, false))
2987 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
2989 MapIterator<String, MethodDoc> it { map = clDoc.methods };
2990 if(it.Index(method.name, false))
2999 char dirPath[MAX_LOCATION];
3000 StripLastDirectory(docPath, dirPath);
3001 if(FileExists(docPath))
3002 DeleteFile(docPath);
3003 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
3006 if(!FileExists(dirPath))
3008 if((f = FileOpen(docPath, write)))
3010 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3014 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3023 Block parent = textBlock.parent;
3024 while((block = parent.subBlocks.first))
3026 parent.subBlocks.Remove(block);
3029 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3030 textBlock.text = CopyString($"[Add Text]");
3031 textBlock.textLen = strlen(textBlock.text);
3032 parent.subBlocks.Add(textBlock);
3040 PositionCaret(true);
3045 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3049 if(edit && (!textBlock || overLink != textBlock.parent))
3053 HTMLView::OnLeftButtonDown(x, y, mods);
3054 selPosition = curPosition = 0;
3055 selBlock = textBlock;
3059 result = HTMLView::OnLeftButtonDown(x, y, mods);
3061 if(!edit && clickedLink)
3064 if(clickedLink == overLink && clickedLink.href)
3066 if(OnOpen(clickedLink.href))
3074 if(textBlock && overLink == textBlock.parent)
3076 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3077 selBlock = textBlock;
3078 PositionCaret(true);
3086 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3088 if(!edit || !textBlock || clickedLink != textBlock.parent)
3090 HTMLView::OnLeftButtonUp(x, y, mods);
3093 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3094 selBlock = textBlock;
3095 PositionCaret(true);
3106 bool OnMouseMove(int x, int y, Modifiers mods)
3108 if(edit && selecting)
3110 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3111 PositionCaret(true);
3114 return HTMLView::OnMouseMove(x, y, mods);
3117 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3119 if(edit && textBlock)
3125 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3126 selBlock = textBlock;
3127 for(c = curPosition; c >= 0; c--)
3130 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3131 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3132 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3138 for(c = start; c < textBlock.textLen; c += numBytes)
3140 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3141 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3144 selPosition = start;
3147 PositionCaret(true);
3155 bool OnOpen(char * href)
3157 if(!strncmp(href, "api://", 6))
3159 int64 tag = (int64)strtoull(href + 6, null, 16);
3160 DataRow row = mainForm.browser.FindSubRow(tag);
3164 mainForm.browser.SelectRow(row);
3165 while((row = row.parent))
3166 row.collapsed = false;
3167 row = mainForm.browser.currentRow;
3168 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3171 else if(!strncmp(href, "edit://", 7))
3174 int startX = clickedLink.startX, startY = clickedLink.startY;
3175 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3177 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3178 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3180 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3182 display.FontExtent(block.font.font, " ", 1, null, &th);
3185 block.parent.subBlocks.Insert(null, newBlock);
3190 block.parent.subBlocks.Insert(block, newBlock);
3191 startY += block.prev.height;
3193 newBlock.startX = startX;
3194 newBlock.startY = startY;
3195 newBlock.text = new0 char[1];
3199 textBlock = (Block)clickedLink.subBlocks.first;
3200 if(!strcmp(textBlock.text, $"[Add Text]"))
3202 textBlock.text[0] = 0;
3203 textBlock.textLen = 0;
3206 strcpy(editString, href + 7);
3207 selPosition = curPosition = 0;
3208 selBlock = textBlock;
3211 // PositionCaret(true);
3218 void DeleteSelection()
3220 if(textBlock != selBlock || curPosition != selPosition)
3222 if(textBlock == selBlock)
3224 // Within same block
3225 int start = Min(curPosition, selPosition);
3226 int end = Max(curPosition, selPosition);
3227 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3228 textBlock.textLen -= end-start;
3229 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3230 curPosition = start;
3231 selPosition = start;
3235 int startSel, endSel;
3236 Block startSelBlock = null, endSelBlock = null, b, next;
3238 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3240 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3241 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3243 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3244 for(b = startSelBlock.next; b; b = next)
3246 bool isEnd = b == endSelBlock;
3247 next = GetNextBlock(b);
3248 b.parent.subBlocks.Remove(b);
3253 textBlock = startSelBlock;
3254 selBlock = startSelBlock;
3255 curPosition = startSel;
3256 selPosition = startSel;
3260 PositionCaret(true);
3265 String GetSelectionString()
3267 String selection = null;
3268 if(textBlock == selBlock)
3270 // Within same block
3271 int start = Min(curPosition, selPosition);
3272 int end = Max(curPosition, selPosition);
3273 int len = end - start;
3274 selection = new char[len + 1];
3275 memcpy(selection, textBlock.text + start, len);
3280 int startSel, endSel;
3281 Block startSelBlock = null, endSelBlock = null, b;
3284 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3287 for(b = startSelBlock; b; b = GetNextBlock(b))
3289 int start = (b == startSelBlock) ? startSel : 0;
3290 int end = (b == endSelBlock) ? endSel : b.textLen;
3291 int len = end - start;
3293 if(b == endSelBlock)
3295 else if(b.type == TEXT)
3299 selection = new char[totalLen + 1];
3301 for(b = startSelBlock; b; b = GetNextBlock(b))
3303 int start = (b == startSelBlock) ? startSel : 0;
3304 int end = (b == endSelBlock) ? endSel : b.textLen;
3305 int len = end - start;
3306 memcpy(selection + totalLen, b.text + start, len);
3308 if(b == endSelBlock)
3310 else if(b.type == TEXT)
3311 selection[totalLen++] = '\n';
3313 selection[totalLen] = 0;
3318 void CopySelection()
3320 String s = GetSelectionString();
3323 int len = strlen(s);
3325 if(cb.Allocate(len + 1))
3327 memcpy(cb.text, s, len + 1);
3335 bool OnKeyDown(Key key, unichar ch)
3342 OnLeftButtonDown(0,0,0);
3344 case Key { end, shift = true }:
3346 curPosition = textBlock.textLen;
3349 selPosition = curPosition;
3350 selBlock = textBlock;
3352 PositionCaret(true);
3355 case Key { home, shift = true }:
3360 selPosition = curPosition;
3361 selBlock = textBlock;
3363 PositionCaret(true);
3366 case Key { home, ctrl = true, shift = true }:
3369 while(textBlock.prev)
3370 textBlock = textBlock.prev.prev;
3373 selPosition = curPosition;
3374 selBlock = textBlock;
3376 PositionCaret(true);
3379 case Key { end, ctrl = true, shift = true }:
3381 while(textBlock.next && textBlock.next.next)
3382 textBlock = textBlock.next.next;
3383 curPosition = textBlock.textLen;
3386 selPosition = curPosition;
3387 selBlock = textBlock;
3389 PositionCaret(true);
3395 return HTMLView::OnKeyDown(key, ch);
3399 bool OnKeyHit(Key key, unichar ch)
3405 case Key { up, shift = true }:
3408 if(caretY == textBlock.startY)
3412 textBlock = textBlock.prev.prev;
3413 curPosition = Min(curPosition, textBlock.textLen);
3416 selPosition = curPosition;
3417 selBlock = textBlock;
3420 PositionCaret(false);
3430 int sx = textBlock.startX, sy = textBlock.startY;
3431 char * text = textBlock.text;
3433 Block block = textBlock;
3434 while(block && block.type != TD) block = block.parent;
3437 Block table = block;
3438 while(table && table.type != TABLE) table = table.parent;
3440 maxW = block.w - 2* table.cellPadding;
3442 maxW = clientSize.w - 10 - sx;
3445 maxW = clientSize.w - 10 - sx;
3446 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3450 int startPos = textPos;
3453 bool lineComplete = false;
3454 for(; textPos<textBlock.textLen && !lineComplete;)
3458 char * nextSpace = strchr(text + textPos, ' ');
3461 len = (nextSpace - (text + textPos)) + 1;
3463 len = textBlock.textLen - textPos;
3465 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3467 if(x + width + w > maxW && x > 0)
3469 lineComplete = true;
3479 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3482 curPosition = textPos;
3483 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3486 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3487 len = curPosition - startPos;
3488 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3492 selPosition = curPosition;
3493 selBlock = textBlock;
3497 PositionCaret(false);
3501 if(sy == caretY - th || textPos == textBlock.textLen)
3503 if(textPos != textBlock.textLen)
3505 int c = textPos - 1;
3506 while(c > 0 && text[c] == ' ') c--;
3507 curPosition = c + 1;
3510 selPosition = curPosition;
3511 selBlock = textBlock;
3517 curPosition = textBlock.textLen;
3520 selPosition = curPosition;
3521 selBlock = textBlock;
3525 PositionCaret(false);
3529 sx = textBlock.startX;
3530 } while(textPos < textBlock.textLen);
3535 case Key { down, shift = true }:
3540 int sx = textBlock.startX, sy = textBlock.startY;
3541 char * text = textBlock.text;
3543 Block block = textBlock;
3544 while(block && block.type != TD) block = block.parent;
3547 Block table = block;
3548 while(table && table.type != TABLE) table = table.parent;
3550 maxW = block.w - 2* table.cellPadding;
3552 maxW = clientSize.w - 10 - sx;
3555 maxW = clientSize.w - 10 - sx;
3556 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3558 while(!textPos || textPos < textBlock.textLen)
3560 int startPos = textPos;
3563 bool lineComplete = false;
3564 for(; (textPos < textBlock.textLen) && !lineComplete;)
3568 char * nextSpace = strchr(text + textPos, ' ');
3571 len = (nextSpace - (text + textPos)) + 1;
3573 len = textBlock.textLen - textPos;
3575 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3577 if(x + width + w > maxW && x > 0)
3579 lineComplete = true;
3589 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3591 curPosition = textPos;
3593 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3596 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3597 len = curPosition - startPos;
3598 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3602 selPosition = curPosition;
3603 selBlock = textBlock;
3606 PositionCaret(false);
3612 curPosition = textBlock.textLen;
3615 selPosition = curPosition;
3616 selBlock = textBlock;
3619 PositionCaret(false);
3622 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3626 textBlock = textBlock.next.next;
3627 sy = textBlock.startY;
3628 sx = textBlock.startX;
3629 text = textBlock.text;
3634 sx = textBlock.startX;
3638 /*if(textBlock.next && textBlock.next.next)
3640 textBlock = textBlock.next.next;
3641 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3642 selBlock = textBlock;
3643 PositionCaret(false);
3647 case Key { right, shift = true, ctrl = true }:
3650 bool foundAlpha = false;
3652 Block line, lastLine;
3655 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3657 int start = (line == textBlock) ? curPosition : 0;
3659 for(c = start; c < line.textLen; c++)
3661 char ch = line.text[c];
3662 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3663 if(key.shift ? isAlUnder : !isAlUnder)
3677 selPosition = curPosition;
3678 selBlock = textBlock;
3682 PositionCaret(true);
3687 // No next word found,
3688 if(!found && (c != curPosition || line != textBlock))
3692 lastC = line.textLen-1;
3697 curPosition = line.textLen;
3700 selPosition = curPosition;
3701 selBlock = textBlock;
3706 PositionCaret(true);
3712 if(key.shift && found)
3714 curPosition = lastC+1;
3715 textBlock = lastLine;
3716 PositionCaret(true);
3721 case Key { left, ctrl = true, shift = true }:
3724 bool foundAlpha = false;
3726 Block line, lastLine;
3729 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3732 if(curPosition == 0 && line != textBlock)
3735 lastC = line.textLen;
3739 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3740 for(c = start; c>=0; c--)
3742 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3757 // No next word found,
3758 if(!found && curPosition > 0)
3768 textBlock = lastLine;
3769 curPosition = lastC;
3772 selPosition = curPosition;
3773 selBlock = textBlock;
3775 PositionCaret(true);
3780 case Key { right, shift = true }:
3782 if(curPosition < textBlock.textLen)
3784 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3787 selPosition = curPosition;
3788 selBlock = textBlock;
3790 PositionCaret(true);
3793 else if(textBlock.next && textBlock.next.next)
3795 textBlock = textBlock.next.next;
3799 selPosition = curPosition;
3800 selBlock = textBlock;
3802 PositionCaret(true);
3806 case Key { left, shift = true }:
3810 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3813 selPosition = curPosition;
3814 selBlock = textBlock;
3816 PositionCaret(true);
3819 else if(textBlock.prev)
3821 textBlock = textBlock.prev.prev;
3822 curPosition = textBlock.textLen;
3825 selPosition = curPosition;
3826 selBlock = textBlock;
3828 PositionCaret(true);
3834 if(textBlock == selBlock && curPosition == selPosition)
3838 int c = curPosition;
3840 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3841 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3842 textBlock.textLen -= nb;
3843 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3845 selPosition = curPosition;
3846 selBlock = textBlock;
3850 PositionCaret(true);
3853 else if(textBlock.prev)
3855 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3856 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3857 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3859 selPosition = curPosition = prevBlock.textLen;
3860 selBlock = textBlock;
3861 prevBlock.textLen += textBlock.textLen;
3862 textBlock.parent.subBlocks.Remove(prev);
3863 if(prev == selBlock)
3865 selBlock = textBlock;
3866 selPosition = curPosition;
3869 textBlock.parent.subBlocks.Remove(textBlock);
3870 if(textBlock == selBlock)
3872 selBlock = prevBlock;
3873 selPosition = curPosition;
3876 textBlock = prevBlock;
3880 PositionCaret(true);
3889 if(textBlock != selBlock || curPosition != selPosition)
3891 else if(textBlock.textLen > curPosition)
3893 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3894 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3895 textBlock.textLen -= nb;
3896 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3901 PositionCaret(true);
3904 else if(textBlock.next && textBlock.next.next)
3906 Block next = textBlock.next, nextBlock = textBlock.next.next;
3907 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3908 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3910 textBlock.textLen += nextBlock.textLen;
3911 textBlock.parent.subBlocks.Remove(next);
3912 if(next == selBlock)
3914 selBlock = textBlock;
3915 selPosition = curPosition;
3918 textBlock.parent.subBlocks.Remove(nextBlock);
3919 if(nextBlock == selBlock)
3921 selBlock = textBlock;
3922 selPosition = curPosition;
3928 PositionCaret(true);
3942 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3943 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3944 startY = textBlock.startY;
3945 startX = textBlock.startX;
3947 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3948 textBlock.parent.subBlocks.Insert(textBlock, block);
3949 textBlock.parent.subBlocks.Insert(block, newBlock);
3953 newBlock.textLen = textBlock.textLen - curPosition;
3954 newBlock.text = new char[newBlock.textLen+1];
3955 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3956 textBlock.textLen = curPosition;
3957 textBlock.text[curPosition] = 0;
3959 newBlock.startY = startY;
3960 newBlock.startX = startX;
3961 selPosition = curPosition = 0;
3966 textBlock = newBlock;
3967 selBlock = textBlock;
3968 PositionCaret(true);
3973 case Key { del, shift = true }:
3988 ClipBoard clipBoard { };
3989 if(clipBoard.Load())
3992 char * text = clipBoard.memory;
4000 parent = textBlock.parent;
4001 font = textBlock.font;
4006 if(ch == '\n' || ch == '\r' || !ch)
4008 int len = c - start;
4009 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4010 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4011 memcpy(textBlock.text + curPosition, text + start, len);
4012 textBlock.textLen += len;
4014 selPosition = curPosition;
4015 selBlock = textBlock;
4018 Block block { type = BR, parent = parent, font = font };
4019 Block newBlock { type = TEXT, parent = parent, font = font };
4020 int startY = textBlock.startY, startX = textBlock.startX;
4023 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4024 textBlock.parent.subBlocks.Insert(textBlock, block);
4025 textBlock.parent.subBlocks.Insert(block, newBlock);
4029 newBlock.textLen = textBlock.textLen - curPosition;
4030 newBlock.text = new char[newBlock.textLen+1];
4031 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4032 textBlock.textLen = curPosition;
4033 textBlock.text[curPosition] = 0;
4035 newBlock.startY = startY;
4036 newBlock.startX = startX;
4037 selPosition = curPosition = 0;
4038 selBlock = textBlock;
4039 textBlock = newBlock;
4041 if(ch == '\r' && text[c+1] == '\n') c++;
4047 PositionCaret(true);
4055 // eC BUG HERE: (Should be fixed)
4056 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4059 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4064 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4065 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4067 for(c = 0; c<len; c++)
4069 textBlock.text[curPosition] = string[c];
4070 textBlock.textLen++;
4073 selPosition = curPosition;
4074 selBlock = textBlock;
4077 //Clear(html.block);
4078 //CreateForms(html.block);
4083 PositionCaret(true);
4092 void OnResize(int width, int height)
4094 HTMLView::OnResize(width, height);
4095 PositionCaret(true);
4099 void PositionCaret(bool setCaretX)
4105 int sx = textBlock.startX, sy = textBlock.startY;
4106 char * text = textBlock.text;
4108 Block block = textBlock;
4109 while(block && block.type != TD) block = block.parent;
4112 Block table = block;
4113 while(table && table.type != TABLE) table = table.parent;
4115 maxW = block.w - 2* table.cellPadding;
4117 maxW = clientSize.w - 10 - sx;
4120 maxW = clientSize.w - 10 - sx;
4122 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4124 while(textPos < textBlock.textLen)
4126 int startPos = textPos;
4129 bool lineComplete = false;
4131 for(; textPos<textBlock.textLen && !lineComplete;)
4135 char * nextSpace = strchr(text + textPos, ' ');
4138 len = (nextSpace - (text + textPos)) + 1;
4140 len = textBlock.textLen - textPos;
4142 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4144 if(x + width + w > maxW && x > 0)
4146 lineComplete = true;
4159 if(curPosition < textPos || textPos == textBlock.textLen)
4161 int len = curPosition - startPos;
4162 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4167 sx = textBlock.startX;
4172 SetCaret(sx, sy, th);
4174 Point scrollPos = scroll;
4175 bool doScroll = false;
4176 if(sy - scroll.y + th > clientSize.h)
4178 scrollPos.y = sy + th - clientSize.h;
4181 else if(sy - scroll.y < 0)
4186 if(sx - scroll.x + 10 > clientSize.w)
4188 scrollPos.x = sx + 10 - clientSize.w;
4191 else if(sx - scroll.x < 10)
4193 scrollPos.x = sx - 10;
4204 // Returns a character offset into the TextBlock from a window coordinate
4205 int TextPosFromPoint(int px, int py, Block * block, bool half)
4207 Block parentBlock = this.textBlock.parent;
4210 *block = this.textBlock;
4215 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4217 int sx = textBlock.startX, sy = textBlock.startY;
4220 char * text = textBlock.text;
4222 Block b = textBlock;
4225 if(textBlock.type != TEXT) continue;
4227 while(b && b.type != TD) b = b.parent;
4231 while(table && table.type != TABLE) table = table.parent;
4233 maxW = b.w - 2* table.cellPadding;
4235 maxW = clientSize.w - 10 - sx;
4238 maxW = clientSize.w - 10 - sx;
4240 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4241 //space = space/2+2;
4244 while(textPos < textBlock.textLen)
4248 bool lineComplete = false;
4250 for(; textPos<textBlock.textLen && !lineComplete;)
4254 char * nextSpace = strchr(text + textPos, ' ');
4257 len = (nextSpace - (text + textPos)) + 1;
4259 len = textBlock.textLen - textPos;
4261 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4263 sx = x + textBlock.startX;
4264 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4269 for(c = textPos; (ch = text[c]); c += numBytes)
4271 numBytes = UTF8_NUM_BYTES(ch);
4272 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4273 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4280 if(x + width + w > maxW && x > 0)
4282 lineComplete = true;
4295 if(/*py >= sy && */py < sy + th)
4298 return textBlock.textLen;
4303 result = textBlock.textLen;
4309 Application componentsApp;
4311 class Documentor : GuiApplication
4315 Platform os = __runtimePlatform;
4316 SetGlobalContext(globalContext);
4317 SetExcludedSymbols(&excludedSymbols);
4318 SetDefines(&::defines);
4319 SetImports(&imports);
4320 SetInDocumentor(true);
4322 SetGlobalData(globalData);
4324 settingsContainer.dataOwner = &settings;
4325 settingsContainer.Load();
4326 if(!settings.docDir || !settings.docDir[0] )
4328 if(os == win32) // if Windows OS then
4330 char programFilesDir[MAX_LOCATION];
4331 char appData[MAX_LOCATION];
4332 char homeDrive[MAX_LOCATION];
4333 char winDir[MAX_LOCATION];
4334 GetEnvironment("APPDATA", appData, sizeof(appData));
4335 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4336 GetEnvironment("windir", winDir, sizeof(winDir));
4337 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4339 PathCat(programFilesDir, "ECERE SDK\\doc");
4340 settings.docDir = programFilesDir;
4342 else if(homeDrive[0])
4344 PathCat(homeDrive, "ECERE SDK\\doc");
4345 settings.docDir = homeDrive;
4349 PathCat(winDir, "..\\ECERE SDK\\doc");
4350 settings.docDir = winDir;
4353 settings.docDir = "C:\\ECERE SDK\\doc";
4355 else // if Os is Linux, or Mac OSX or something else
4356 settings.docDir = "/usr/share/ecere/doc/";
4357 settingsContainer.Save();
4363 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4365 AddComponents(module, true);
4366 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4367 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4368 while((row = row.parent))
4369 row.collapsed = false;
4373 commandThread.Create();
4377 bool Cycle(bool idle)
4380 mainForm.Destroy(0);
4389 if(commandThread.created)
4391 console.CloseInput();
4392 console.CloseOutput();
4394 commandThread.Wait();
4398 FreeContext(globalContext);
4399 FreeExcludedSymbols(excludedSymbols);
4400 ::defines.Free(FreeModuleDefine);
4401 imports.Free(FreeModuleImport);
4403 FreeGlobalData(globalData);
4404 FreeTypeData(componentsApp);
4406 delete componentsApp;
4410 ConsoleFile console { };
4411 MainForm mainForm { };
4414 Thread commandThread
4421 console.GetLine(command, sizeof(command));
4422 if(!quit && command[0])
4425 if(!strcmpi(command, "Activate"))
4426 mainForm.Activate();
4427 else if(!strcmpi(command, "Quit"))
4435 #endif // !defined(EAR_TO_ECON_ECDOC)
4440 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4441 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4445 property bool isEmpty
4451 (description && *description));
4461 class MoreDoc : ItemDoc
4464 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4465 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4466 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4467 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4473 property bool isEmpty
4478 (usage && *usage) ||
4479 (example && *example) ||
4480 (remarks && *remarks) ||
4494 class NamespaceDoc : ItemDoc
4497 Map<String, DefineDoc> defines;
4498 Map<String, FunctionDoc> functions;
4500 property bool isEmpty
4505 (defines && defines.count) ||
4506 (functions && functions.count) ||
4517 class DefineDoc : ItemDoc { }
4519 class FunctionDoc : MoreDoc
4522 Map<String, ParameterDoc> parameters;
4523 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4526 property bool isEmpty
4531 (parameters && parameters.count) ||
4532 (returnValue && *returnValue) ||
4543 class ParameterDoc : ItemDoc
4549 class ClassDoc : MoreDoc
4552 Map<String, ValueDoc> values;
4553 Map<String, FieldDoc> fields;
4554 Map<String, PropertyDoc> properties;
4555 Map<String, ConversionDoc> conversions;
4556 Map<String, MethodDoc> methods;
4558 property bool isEmpty
4563 (values && values.count) ||
4564 (fields && fields.count) ||
4565 (properties && properties.count) ||
4566 (conversions && conversions.count) ||
4567 (methods && methods.count) ||
4581 class ValueDoc : ItemDoc { }
4583 class FieldDoc : ItemDoc { }
4585 class PropertyDoc : ItemDoc { }
4587 class ConversionDoc : ItemDoc { }
4589 class MethodDoc : FunctionDoc { }
4591 char * getDocFileNameFromTypeName(const char * typeName)
4593 char * docFileName = new char[MAX_FILENAME];
4594 const char * swap = "pointer";
4595 const char * s = typeName;
4596 char * d = docFileName;
4597 const char * end = s + strlen(typeName);
4598 int swapLen = strlen(swap);
4616 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4619 Time timeStamp; // Should this be last accessed, or last retrieved?
4628 Map<String, DocCacheEntry> docCache { };