5 import "SettingsDialog"
7 static Context globalContext { };
8 static OldList defines { };
9 static OldList imports { };
10 static NameSpace globalData;
11 static OldList excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left };
14 define app = (GuiApplication)__thisModule.application;
16 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
19 /*extern */int __ecereVMethodID_class_OnGetString;
23 static __attribute__((unused)) void Dummy()
26 a.OnGetString(null, null, null);
29 static bool editing = true;
31 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
33 static const char * iconNames[CodeObjectType] =
35 "<:ecere>constructs/class.png",
36 "<:ecere>constructs/data.png",
37 "<:ecere>constructs/method.png",
38 "<:ecere>constructs/event.png",
39 "<:ecere>constructs/property.png",
40 "<:ecere>constructs/namespace.png",
41 "<:ecere>constructs/dataType.png",
42 "<:ecere>constructs/enumValue.png",
43 "<:ecere>constructs/dataPrivate.png",
44 "<:ecere>constructs/methodPrivate.png",
45 "<:ecere>constructs/propertyPrivate.png"
48 IDESettings settings { }; // instantiate the IDESettings class from the IDESettings.ec file. Do this at a global level so that all methods can access settings.
50 IDESettingsContainer settingsContainer
54 dataOwner = &settings;
57 void GetTemplateString(Class c, char * templateString)
59 Module m = c.module.application;
60 const char * n = c.name;
61 char * lt = strchr(n, '<');
67 memcpy(templateString, n, lt-n);
68 templateString[lt-n] = 0;
69 strcat(templateString, "</a>");
71 for(s = lt; (ch = *s); s++)
73 if(ch == '<' || ch == '>' || ch == ',')
78 char * d = templateString + strlen(templateString);
80 TrimLSpaces(curName, curName);
81 TrimRSpaces(curName, curName);
82 pc = eSystem_FindClass(m, curName);
84 sprintf(d, "%s<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name);
89 strcat(templateString, "<");
91 strcat(templateString, ">");
93 strcat(templateString, ", ");
100 curName[len++] = ' ';
102 strcat(templateString, curName);
110 // WARNING : This function expects a null terminated string since it recursively concatenate...
111 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
115 if(type.constant && (type.kind != pointerType && type.kind != arrayType))
116 strcat(string, "const ");
120 if(type._class && type._class.string)
123 strcat(string, type._class.string);
126 if(type._class.registered)
129 const char * s = type._class.registered.name;
130 sprintf(hex, "%p", type._class.registered.templateClass ? type._class.registered.templateClass : type._class.registered);
131 strcat(string, "<a href=\"api://");
133 strcat(string, "\" style=\"text-decoration: none;\">");
137 GetTemplateString(type._class.registered, n);
141 strcat(string, type._class.registered.name);
142 strcat(string, "</a>");
145 strcat(string, type._class.string);
152 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
153 if(funcType && funcType.kind == functionType)
156 DocPrintType(funcType.returnType, string, false, fullName);
157 strcat(string, "(*");
158 if(printName || funcType.thisClass)
161 if(funcType.thisClass)
163 strcat(string, funcType.thisClass.string);
164 strcat(string, "::");
167 strcat(string, type.name);
169 strcat(string, ")(");
170 for(param = funcType.params.first; param; param = param.next)
172 DocPrintType(param, string, false, fullName);
173 if(param.next) strcat(string, ", ");
179 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
180 if(string[strlen(string)-1] == '(')
183 strcat(string, " *");
187 case voidType: strcat(string, "void"); break;
188 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
189 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
190 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
191 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
192 case floatType: strcat(string, "float"); break;
193 case doubleType: strcat(string, "double"); break;
197 strcat(string, "struct ");
198 strcat(string, type.enumName);
200 else if(type.typeName)
202 strcat(string, type.typeName);
207 strcat(string, "struct ");
208 strcat(string,"(unnamed)");
211 strcat(string, "struct {");
212 for(member = type.members.first; member; member = member.next)
214 DocPrintType(member, string, true, fullName);
223 strcat(string, "union ");
224 strcat(string, type.enumName);
226 else if(type.typeName)
228 strcat(string, type.typeName);
232 strcat(string, "union ");
233 strcat(string,"(unnamed)");
239 strcat(string, "enum ");
240 strcat(string, type.enumName);
242 else if(type.typeName)
244 strcat(string, type.typeName);
247 strcat(string, "enum");
254 strcat(string, "dllexport ");
255 DocPrintType(type.returnType, string, false, fullName);
259 // DANGER: Testing This
265 strcat(string, type.name);
268 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
269 if(name) name += 2; else name = type.name;
270 strcat(string, "<b>");
271 strcat(string, name);
272 strcat(string, "</b>");
281 for(param = type.params.first; param; param = param.next)
283 DocPrintType(param, string, true, fullName);
284 if(param.next) strcat(string, ", ");
293 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
294 if(funcType && funcType.kind == functionType)
297 DocPrintType(funcType.returnType, string, false, fullName);
298 strcat(string, "(*");
299 if(printName || funcType.thisClass)
302 if(funcType.thisClass)
304 strcat(string, funcType.thisClass.string);
305 strcat(string, "::");
308 strcat(string, type.name);
310 strcat(string, ")(");
311 for(param = funcType.params.first; param; param = param.next)
313 DocPrintType(param, string, false, fullName);
314 if(param.next) strcat(string, ", ");
320 char baseType[1024], size[256];
321 Type arrayType = type;
325 while(arrayType.kind == TypeKind::arrayType)
328 if(arrayType.enumClass)
329 strcat(size, arrayType.enumClass.string);
330 else if(arrayType.arraySizeExp)
331 PrintExpression(arrayType.arraySizeExp, size);
332 //sprintf(string, "%s[%s]", baseType, size);
335 arrayType = arrayType.arrayType;
337 _PrintType(arrayType, baseType, printName, printFunction, fullName);
338 strcat(string, baseType);
339 strcat(string, size);
343 DocPrintType(type.arrayType, baseType, printName, fullName);
345 strcpy(size, type.enumClass.string);
346 else if(type.arraySizeExp)
347 PrintExpression(type.arraySizeExp, size);
348 //sprintf(string, "%s[%s]", baseType, size);
349 strcat(string, baseType);
351 strcat(string, size);
359 strcat(string, "...");
362 _PrintType(type.method.dataType, string, false, printFunction, fullName);
365 strcat(string, "subclass(");
366 strcat(string, type._class ? type._class.string : "int");
372 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
375 strcat(string, type.name);
380 void DocPrintType(Type type, char * string, bool printName, bool fullName)
383 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
384 if(funcType && funcType.kind == functionType && type != funcType)
388 DocPrintType(funcType.returnType, string, false, fullName);
390 _PrintType(type, string, printName, false, fullName);
394 strcat(string, type.name);
401 for(param = funcType.params.first; param; param = param.next)
403 DocPrintType(param, string, true, fullName);
404 if(param.next) strcat(string, ", ");
409 _PrintType(type, string, printName, true, fullName);
412 void AddComponents(Module module, bool isDll)
417 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
419 row = mainForm.browser.AddRow();
420 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
421 row.tag = (int64)null;
422 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
425 for(m = module.modules.first; m; m = m.next)
427 if(m.importMode == publicAccess || !isDll)
428 AddComponents(m.module, true);
431 // PUT MODULE DESCRIPTION HERE
432 if(module.name && strcmp(module.name, "ecereCOM"))
434 row = mainForm.browser.AddRow();
435 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
436 row.tag = (int64)module;
437 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
439 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
451 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
456 virtual void Generate(File f)
461 virtual Module GetModule()
463 return page ? page.GetModule() : null;
466 virtual NameSpace * GetNameSpace()
468 return page ? page.GetNameSpace() : null;
472 enum DocumentationType
480 enum DocumentationItem
496 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
498 NameSpace * nameSpace, * ns;
500 Method method = null;
501 GlobalFunction function = null;
502 char nsName[1024], temp[1024];
508 case nameSpaceDoc: nameSpace = object; break;
509 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
510 case functionDoc: function = object; nameSpace = function.nameSpace; break;
511 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
516 while(ns && ns->name)
518 strcpy(temp, "namespaces/");
519 strcat(temp, ns->name);
521 strcat(temp, nsName);
522 strcpy(nsName, temp);
525 sprintf(docFile, "%s.eCdoc", (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
526 if(strchr(docFile, DIR_SEP))
528 GetLastDirectory(docFile, temp);
529 strcpy(docFile, temp);
532 sprintf(fileName, "<%s/%s>", settings.docDir, docFile); // Note that in the ecereIDE.ini file, there can be no quotes around the path, and there needs to be the final backslash. Otherwise this does not work.
533 strcat(fileName, nsName);
537 strcat(fileName, "classes/");
538 strcat(fileName, cl.name);
539 strcat(fileName, "/");
544 strcat(fileName, "methods/");
545 strcat(fileName, method.name);
546 strcat(fileName, "/");
550 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
551 if(name) name += 2; else name = function.name;
552 strcat(fileName, "functions/");
553 strcat(fileName, name);
554 strcat(fileName, "/");
559 case description: strcat(fileName, "description"); break;
560 case usage: strcat(fileName, "usage"); break;
561 case remarks: strcat(fileName, "remarks"); break;
562 case example: strcat(fileName, "example"); break;
563 case seeAlso: strcat(fileName, "seeAlso"); break;
564 case returnValue: strcat(fileName, "returnValue"); break;
565 case enumerationValue:
566 strcat(fileName, "enumeration values/");
567 strcat(fileName, ((NamedLink)data).name);
570 strcat(fileName, "definitions/");
571 strcat(fileName, ((Definition)data).name);
575 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
576 if(name) name += 2; else name = ((Property)data).name;
577 strcat(fileName, "conversions/");
578 strcat(fileName, name);
581 case memberDescription:
582 strcat(fileName, "data members/");
583 strcat(fileName, ((DataMember)data).name);
585 case propertyDescription:
586 strcat(fileName, "properties/");
587 strcat(fileName, ((Property)data).name);
594 strcat(fileName, "parameters/");
595 for(prev = data, count = 0; prev; prev = prev.prev, count++);
596 sprintf(name, "%s.%d", ((Type)data).name, count);
597 strcat(fileName, name);
603 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
605 char fileName[MAX_LOCATION];
606 String contents = null;
609 FigureFileName(fileName, module, type, object, item, data);
610 file = FileOpen(fileName, read);
614 if((len = file.GetSize()))
616 contents = new char[len+1];
617 file.Read(contents, 1, len);
618 contents[len] = '\0';
625 for(c = 0; contents[c]; c++)
626 if(!isspace(contents[c])) break;
630 if(editing && !contents && !readOnly)
631 contents = CopyString($"[Add Text]");
635 class APIPageNameSpace : APIPage
637 NameSpace * nameSpace;
645 NameSpace * GetNameSpace()
650 void Generate(File f)
652 char nsName[1024], temp[1024];
658 while(ns && ns->name)
660 strcpy(temp, ns->name);
661 if(nsName[0]) strcat(temp, "::");
662 strcat(temp, nsName);
663 strcpy(nsName, temp);
666 // Generate Class Page
667 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
670 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
671 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);
674 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
677 ns = nameSpace->parent;
678 while(ns && ns->name)
680 strcpy(temp, ns->name);
681 if(nsName[0]) strcat(temp, "::");
682 strcat(temp, nsName);
683 strcpy(nsName, temp);
687 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
691 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
694 f.Printf($"<H3>Description</H3><br><br>\n");
697 char fileName[MAX_LOCATION];
698 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
699 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
701 f.Printf("</a><br><br>");
704 f.Printf("%s<br><br>", desc);
709 if(nameSpace->nameSpaces.first)
712 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
714 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
717 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
718 f.Printf("<TABLE>\n");
722 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);
727 char fileName[MAX_LOCATION];
728 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
729 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
731 f.Printf("</a></TD>");
734 f.Printf("<TD valign=top height=22> %s</TD>", desc);
737 f.Printf("</TR><br>\n");
740 f.Printf("</TABLE><br>\n");
743 if(nameSpace->classes.first)
746 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
748 Class cl = link.data;
749 if(!cl.templateClass)
751 char * desc = ReadDoc(module, classDoc, cl, description, null);
755 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
756 f.Printf("<TABLE>\n");
762 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);
767 char fileName[MAX_LOCATION];
768 FigureFileName(fileName, module, classDoc, cl, description, null);
769 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
771 f.Printf("</a></TD>");
774 f.Printf("<TD valign=top height=22>%s</TD>", desc);
781 f.Printf("</TABLE><br>\n");
784 if(nameSpace->functions.first)
787 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
789 GlobalFunction function = link.data;
790 char * desc = ReadDoc(module, functionDoc, function, description, null);
791 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
792 if(name) name += 2; else name = function.name;
795 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
796 f.Printf("<TABLE>\n");
800 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);
805 char fileName[MAX_LOCATION];
806 FigureFileName(fileName, module, functionDoc, function, description, null);
807 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
809 f.Printf("</a></TD>");
812 f.Printf("<TD valign=top height=22> %s</TD>", desc);
815 f.Printf("</TR><br>\n");
818 f.Printf("</TABLE><br>\n");
821 if(nameSpace->defines.first)
824 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
826 DefinedExpression def = link.data;
827 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
830 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
831 f.Printf("<TABLE>\n");
835 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);
836 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
841 char fileName[MAX_LOCATION];
842 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
843 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
845 f.Printf("</a></TD>");
848 f.Printf("<TD valign=top height=22> %s</TD>", desc);
851 f.Printf("</TR><br>\n");
854 f.Printf("</TABLE><br>\n");
857 f.Printf("</FONT></BODY></HTML>\n");
861 class APIPageClass : APIPage
870 NameSpace * GetNameSpace()
875 void Generate(File f)
880 char nsName[1024], temp[1024];
881 NameSpace * ns = cl.nameSpace;
882 Module module = cl.module;
885 while(ns && ns->name)
887 strcpy(temp, ns->name);
888 if(nsName[0]) strcat(temp, "::");
889 strcat(temp, nsName);
890 strcpy(nsName, temp);
893 // Generate Class Page
894 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
895 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
897 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);
899 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
902 const char * classType = null;
906 classType = $"Bit Collection";
909 classType = $"Enumeration";
912 classType = $"Structure";
915 classType = $"Class";
918 classType = $"Class (No header)";
924 classType = $"Basic Data Type";
927 f.Printf($"Type: %s<br>\n", classType);
930 if(cl.type != systemClass && cl.base)
932 f.Printf($"Base Class: ");
933 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
935 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
937 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
938 f.Printf("%s", cl.dataTypeString);
940 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
945 char * desc = ReadDoc(module, classDoc, cl, description, null);
948 f.Printf($"<br><H3>Description</H3><br><br>\n");
951 char fileName[MAX_LOCATION];
952 FigureFileName(fileName, module, classDoc, cl, description, null);
953 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
955 f.Printf("</a><br><br>");
958 f.Printf("%s<br><br>", desc);
963 if(cl.type == enumClass)
965 EnumClassData enumeration = (EnumClassData)cl.data;
966 if(enumeration.values.first)
970 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
971 f.Printf("<TABLE>\n");
973 for(item = enumeration.values.first; item; item = item.next)
975 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
976 bool needClass = true;
979 char tempString[1024];
981 while(base.type == enumClass) base = base.base;
983 if(base.type == systemClass ||
984 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
987 base.dataType = ProcessTypeString(base.dataTypeString, false);
989 if(base.dataType.kind != classType)
994 PrintType(base.dataType, string, false, true);
995 classSym = FindClass(string);
996 dataClass = classSym ? classSym.registered : null;
999 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1005 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);
1006 if(dataClass.type == systemClass)
1009 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1012 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1014 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1016 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1021 char fileName[MAX_LOCATION];
1022 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1023 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1025 f.Printf("</a></TD>");
1028 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1033 f.Printf("</TABLE><BR>\n");
1037 if(cl.conversions.first)
1039 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
1040 f.Printf("<TABLE>\n");
1041 for(prop = cl.conversions.first; prop; prop = prop.next)
1043 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1045 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1047 Type type = ProcessTypeString(prop.name, false);
1048 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1049 if(name) name += 2; else name = prop.name;
1054 DocPrintType(type, string, true, false);
1056 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1061 char fileName[MAX_LOCATION];
1062 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1063 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1065 f.Printf("</a></TD>");
1068 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1072 f.Printf("</TR>\n");
1077 f.Printf("</TABLE><br>\n");
1080 if(cl.membersAndProperties.first)
1083 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1085 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1089 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1090 f.Printf("<TABLE>\n");
1096 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1098 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1102 DocPrintType(prop.dataType, string, true, false);
1104 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);
1105 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1110 char fileName[MAX_LOCATION];
1111 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1112 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1114 f.Printf("</a></TD>");
1117 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1120 f.Printf("</TR>\n");
1124 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1129 f.Printf("</TABLE><br>\n");
1132 if(cl.methods.first)
1136 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1138 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1140 char * desc = ReadDoc(module, methodDoc, method, description, null);
1143 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1144 f.Printf("<TABLE>\n");
1147 if(!method.dataType)
1148 ProcessMethodType(method);
1151 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);
1156 char fileName[MAX_LOCATION];
1157 FigureFileName(fileName, module, methodDoc, method, description, null);
1158 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1160 f.Printf("</a></TD>");
1163 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1166 f.Printf("</TR><br>\n");
1170 f.Printf("</TABLE><br>\n");
1172 // Non-Virtual Methods
1174 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1176 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1178 char * desc = ReadDoc(module, methodDoc, method, description, null);
1181 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1182 f.Printf("<TABLE>\n");
1186 if(!method.dataType)
1187 ProcessMethodType(method);
1190 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);
1195 char fileName[MAX_LOCATION];
1196 FigureFileName(fileName, module, methodDoc, method, description, null);
1197 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1199 f.Printf("</a></TD>");
1202 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1206 f.Printf("</TR><br>\n");
1210 f.Printf("</TABLE><br>\n");
1213 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1216 f.Printf($"<H3>Usage</H3><br>\n");
1219 char fileName[MAX_LOCATION];
1220 FigureFileName(fileName, module, classDoc, cl, usage, null);
1221 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1226 f.Printf("<br>%s\n", usageDoc);
1227 f.Printf("<br><br>\n");
1232 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1235 f.Printf($"<H3>Example</H3><br>\n");
1236 f.Printf($"<FONT face=\"Courier New\">\n");
1237 f.Printf("<br><TABLE>\n");
1240 char fileName[MAX_LOCATION];
1241 FigureFileName(fileName, module, classDoc, cl, example, null);
1242 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1244 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1247 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1249 f.Printf("</TABLE></FONT>\n");
1255 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1259 f.Printf($"<H3>Remarks</H3><br>\n");
1262 char fileName[MAX_LOCATION];
1263 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1264 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1269 f.Printf("<br>%s\n", remarksDoc);
1270 f.Printf("<br><br>\n");
1275 if(cl.type != systemClass)
1279 for(c = cl.derivatives.first; c; c = c.next)
1281 Class deriv = c.data;
1282 // TO VERIFY: Does this properly check public status?
1283 if(eSystem_FindClass(componentsApp, deriv.fullName))
1287 f.Printf($"<H3>Derived Classes</H3><br>\n");
1293 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1297 f.Printf("<br><br>\n");
1300 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1303 f.Printf($"<H3>See Also</H3><br>\n");
1306 char fileName[MAX_LOCATION];
1307 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1308 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1313 f.Printf("<br>%s\n", seeAlsoDoc);
1314 f.Printf("<br><br>\n");
1318 f.Printf("</FONT></BODY></HTML>\n");
1322 class APIPageMethod : APIPage
1328 return method._class.module;
1331 NameSpace * GetNameSpace()
1333 return method._class.nameSpace;
1336 void Generate(File f)
1338 Class cl = method._class;
1340 Module module = cl.module;
1342 char nsName[1024], temp[1024];
1343 NameSpace * ns = cl.nameSpace;
1346 while(ns && ns->name)
1348 strcpy(temp, ns->name);
1349 if(nsName[0]) strcat(temp, "::");
1350 strcat(temp, nsName);
1351 strcpy(nsName, temp);
1355 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1356 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1358 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);
1360 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1361 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1362 if(method.dataType.staticMethod)
1364 f.Printf($"this pointer class: None<br>\n");
1366 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1368 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);
1371 // Generate Method Page
1373 if(!method.dataType.name)
1374 method.dataType.name = CopyString(method.name);
1375 DocPrintType(method.dataType, string, true, false);
1376 f.Printf("<br>%s", string);
1379 char * desc = ReadDoc(module, methodDoc, method, description, null);
1382 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1385 char fileName[MAX_LOCATION];
1386 FigureFileName(fileName, module, methodDoc, method, description, null);
1387 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1392 f.Printf("%s", desc);
1397 f.Printf("<br><br>\n");
1398 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1400 f.Printf($"<H3>Parameters</H3><br><br>\n");
1402 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1403 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1405 f.Printf("<TABLE valign=center>\n");
1408 for(param = method.dataType.params.first; param; param = param.next)
1410 // ADD DESCRIPTION HERE
1411 if(param.kind != voidType)
1413 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1416 DocPrintType(param, string, false, false);
1418 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1419 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1424 char fileName[MAX_LOCATION];
1425 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1426 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1428 f.Printf("</a></TD>\n");
1431 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1435 f.Printf("</TR>\n");
1438 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1440 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1441 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1443 f.Printf("<TR><TD> </TD></TR>");
1446 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1448 DocPrintType(method.dataType.returnType, string, false, false);
1449 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1454 char fileName[MAX_LOCATION];
1455 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1456 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1458 f.Printf("</a> </TD>\n");
1461 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1464 f.Printf("</TR>\n");
1465 f.Printf("</TABLE>\n");
1467 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1468 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1470 f.Printf("</TABLE><br>\n");
1473 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1476 f.Printf($"<H3>Usage</H3><br>\n");
1479 char fileName[MAX_LOCATION];
1480 FigureFileName(fileName, module, methodDoc, method, usage, null);
1481 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1486 f.Printf("<br>%s\n", usageDoc);
1487 f.Printf("<br><br>\n");
1492 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1495 f.Printf($"<H3>Example</H3><br>\n");
1496 f.Printf($"<FONT face=\"Courier New\">\n");
1497 f.Printf("<br><TABLE>\n");
1500 char fileName[MAX_LOCATION];
1501 FigureFileName(fileName, module, methodDoc, method, example, null);
1502 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1504 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1507 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1508 f.Printf("</TABLE></FONT>\n");
1514 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1517 f.Printf($"<H3>Remarks</H3><br>\n");
1520 char fileName[MAX_LOCATION];
1521 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1522 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1527 f.Printf("<br>%s\n", method, remarksDoc);
1528 f.Printf("<br><br>\n");
1533 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1536 f.Printf($"<H3>See Also</H3><br>\n");
1539 char fileName[MAX_LOCATION];
1540 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1541 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1546 f.Printf("<br>%s\n", method, seeAlsoDoc);
1548 f.Printf("<br><br>\n");
1552 f.Printf("</FONT></BODY></HTML>\n");
1556 class APIPageFunction : APIPage
1558 GlobalFunction function;
1562 return function.module;
1565 NameSpace * GetNameSpace()
1567 return function.nameSpace;
1570 void Generate(File f)
1573 Module module = function.module;
1575 char nsName[1024], temp[1024];
1576 NameSpace * ns = function.nameSpace;
1579 while(ns && ns->name)
1581 strcpy(temp, ns->name);
1582 if(nsName[0]) strcat(temp, "::");
1583 strcat(temp, nsName);
1584 strcpy(nsName, temp);
1588 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1589 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1591 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);
1594 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1596 if(!function.dataType)
1597 function.dataType = ProcessTypeString(function.dataTypeString, false);
1599 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1601 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);
1604 // Generate Method Page
1606 if(!function.dataType.name)
1607 function.dataType.name = CopyString(function.name);
1608 DocPrintType(function.dataType, string, true, false);
1609 f.Printf("<br>%s", string);
1612 char * desc = ReadDoc(module, functionDoc, function, description, null);
1615 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1618 char fileName[MAX_LOCATION];
1619 FigureFileName(fileName, module, functionDoc, function, description, null);
1620 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1625 f.Printf("%s", desc);
1629 f.Printf("<br><br>\n");
1630 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1632 f.Printf($"<H3>Parameters</H3><br><br>\n");
1634 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1635 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1637 f.Printf("<TABLE valign=center>\n");
1640 for(param = function.dataType.params.first; param; param = param.next)
1642 // ADD DESCRIPTION HERE
1643 if(param.kind != voidType)
1645 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1648 DocPrintType(param, string, false, false);
1650 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1651 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1656 char fileName[MAX_LOCATION];
1657 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1658 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1661 f.Printf("</a> </TD>\n");
1664 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1667 f.Printf("</TR>\n");
1670 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1672 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1673 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1675 f.Printf("<TR><TD> </TD></TR>");
1678 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1680 DocPrintType(function.dataType.returnType, string, false, false);
1681 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1686 char fileName[MAX_LOCATION];
1687 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1688 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1690 f.Printf("</a> </TD>\n");
1693 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1696 f.Printf("</TR>\n");
1697 f.Printf("</TABLE>\n");
1699 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1700 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1702 f.Printf("</TABLE><br>\n");
1705 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1708 f.Printf($"<H3>Usage</H3><br>\n");
1711 char fileName[MAX_LOCATION];
1712 FigureFileName(fileName, module, functionDoc, function, usage, null);
1713 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1718 f.Printf("<br>%s\n", usageDoc);
1719 f.Printf("<br><br>\n");
1724 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1727 f.Printf($"<H3>Example</H3><br>\n");
1728 f.Printf($"<FONT face=\"Courier New\">\n");
1729 f.Printf("<br><TABLE>\n");
1732 char fileName[MAX_LOCATION];
1733 FigureFileName(fileName, module, functionDoc, function, example, null);
1734 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1736 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1739 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1740 f.Printf("</TABLE></FONT>\n");
1746 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1749 f.Printf($"<H3>Remarks</H3><br>\n");
1752 char fileName[MAX_LOCATION];
1753 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1754 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1759 f.Printf("<br>%s\n", remarksDoc);
1760 f.Printf("<br><br>\n");
1765 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1768 f.Printf($"<H3>See Also</H3><br>\n");
1771 char fileName[MAX_LOCATION];
1772 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1773 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1778 f.Printf("<br>%s\n", seeAlsoDoc);
1779 f.Printf("<br><br>\n");
1783 f.Printf("</FONT></BODY></HTML>\n");
1787 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1791 NameSpace * nameSpace = mainNameSpace;
1793 DataRow classesRow = null;
1794 DataRow functionsRow = null, definesRow = null;
1797 strcpy(nsName, parentName ? parentName : "");
1801 strcat(nsName, "::");
1802 strcat(nsName, nameSpace->name);
1807 row = parentRow.AddRow();
1808 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1809 row.tag = (int64)nameSpace;
1810 row.icon = mainForm.icons[typeNameSpace];
1814 // "Global NameSpace"
1816 page = parentRow.GetData(null);
1819 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1821 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1822 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1824 if(comNameSpace != null)
1826 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1828 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1830 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1835 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1837 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1839 if(nameSpace->classes.first)
1843 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1846 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1848 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1849 AddClass(classesRow, module, cl, nsName, showPrivate);
1856 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
1858 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1860 if(nameSpace->functions.first)
1864 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
1867 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
1869 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
1871 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
1872 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
1879 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
1881 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1883 if(nameSpace->defines.first)
1887 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
1890 //if(def.module == module)
1892 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
1894 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
1895 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
1903 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
1907 if(!member.dataType)
1908 member.dataType = ProcessTypeString(member.dataTypeString, false);
1912 DocPrintType(member.dataType, string, true, false);
1914 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
1915 for(c = 0; c<indent; c++)
1916 f.Printf(" ");
1917 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
1918 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
1919 if(member.type == normalMember)
1921 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
1926 char fileName[MAX_LOCATION];
1927 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
1928 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1930 f.Printf("</a></TD>");
1933 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1938 f.Printf("<TD valign=top height=22></TD>");
1940 if(member.type != normalMember)
1942 DataMember subMember;
1943 for(subMember = member.members.first; subMember; subMember = subMember.next)
1945 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
1947 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
1951 f.Printf("</TR><br>\n");
1954 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
1957 if(member.type == normalMember)
1959 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
1960 row.tag = (int64)member;
1965 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
1966 row.icon = mainForm.icons[typeData];
1967 row.tag = (int64)member;
1969 for(m = member.members.first; m; m = m.next)
1971 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
1972 AddDataMember(row, page, m);
1977 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
1982 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
1983 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
1986 row = parentRow.AddRow();
1987 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
1988 row.tag = (int64)cl;
1989 row.collapsed = true;
1990 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
1993 if(cl.methods.first)
1995 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1997 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2000 if(!method.dataType)
2001 ProcessMethodType(method);
2002 if(method.type == virtualMethod)
2004 if(method.dataType.thisClass)
2006 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2007 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2008 mRow.tag = (int64)method;
2012 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2013 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2014 mRow.tag = (int64)method;
2019 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2020 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2021 mRow.tag = (int64)method;
2027 if(cl.membersAndProperties.first)
2029 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2031 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2034 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2038 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2039 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2040 mRow.tag = (int64)prop;
2044 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2045 AddDataMember(membersRow, page, (DataMember)prop);
2051 if(cl.conversions.first)
2053 for(prop = cl.conversions.first; prop; prop = prop.next)
2057 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2058 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2059 if(name) name += 2; else name = prop.name;
2060 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2061 mRow.tag = (int64)prop;
2064 if(cl.type == enumClass)
2066 EnumClassData enumeration = (EnumClassData)cl.data;
2068 for(item = enumeration.values.first; item; item = item.next)
2071 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2072 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2073 mRow.tag = (int64)item;
2078 class AddressBar : Window
2080 background = activeBorder;
2084 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2086 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2088 MainForm mainForm = (MainForm)parent;
2089 FileDialog fileDialog = mainForm.fileDialog;
2090 if(fileDialog.Modal() == ok)
2091 mainForm.OpenModule(fileDialog.filePath);
2097 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2100 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2102 ((MainForm)parent).Back();
2108 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2111 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2113 ((MainForm)parent).Forward();
2119 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2121 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2123 ((MainForm)parent).Home();
2127 /* TODO: Search (#143/#441)
2128 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2129 Update this in the NotifyUpdate. Enter goes to the exact match.
2131 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2135 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2137 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2139 if(!disabled && (SmartKey)key == enter)
2140 ((MainForm)parent).Go(editBox.contents);
2144 void NotifyUpdate(EditBox editBox)
2146 String location = ((MainForm)parent).view.location;
2147 disabled = !strcmp(location ? location : "", editBox.contents);
2152 bool OnKeyHit(Key key, unichar ch)
2155 ((MainForm)parent).view.MakeActive();
2160 class MainForm : Window
2162 size = { 1000, 600 };
2164 borderStyle = sizable;
2167 icon = { ":documentorIcon.png" };
2168 text = $"API Documentation Browser";
2170 BitmapResource icons[CodeObjectType];
2175 for(c = 0; c < CodeObjectType::enumSize; c++)
2177 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2179 browser.AddField(DataField { dataType = class(APIPage) });
2184 Menu fileMenu { menu, $"File", f };
2185 Array<FileFilter> fileFilters
2187 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2188 { $"eC Symbol files (*.sym)", "sym" }
2191 FileDialog fileDialog
2193 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2195 MenuItem fileOpenItem
2197 fileMenu, $"Open...", o, ctrlO;
2199 bool NotifySelect(MenuItem selection, Modifiers mods)
2201 if(fileDialog.Modal() == ok)
2203 OpenModule(fileDialog.filePath);
2208 MenuItem fileSettingsItem
2210 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2212 bool NotifySelect(MenuItem selection, Modifiers mods)
2214 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2224 MenuDivider { fileMenu };
2225 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2227 void OpenModule(const char * filePath)
2229 char moduleName[MAX_LOCATION];
2230 char extension[MAX_EXTENSION];
2231 Module module = null;
2232 static char symbolsDir[MAX_LOCATION];
2236 FreeContext(globalContext);
2237 FreeExcludedSymbols(excludedSymbols);
2238 ::defines.Free(FreeModuleDefine);
2239 imports.Free(FreeModuleImport);
2241 FreeGlobalData(globalData);
2245 FreeTypeData(componentsApp);
2246 delete componentsApp;
2249 componentsApp = __ecere_COM_Initialize(false, 1, null);
2250 SetPrivateModule(componentsApp);
2252 StripLastDirectory(filePath, symbolsDir);
2253 SetSymbolsDir(symbolsDir);
2255 GetExtension(filePath, extension);
2257 mainForm.browser.Clear();
2259 ImportModule(filePath, normalImport, publicAccess, false);
2261 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2262 componentsApp.name = CopyString(filePath);
2264 for(module = componentsApp.allModules.first; module; module = module.next)
2266 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2270 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2271 AddComponents(componentsApp, false);
2273 GetLastDirectory(filePath, moduleName);
2274 // Extension, path and lib prefix get removed in Module::name
2277 StripExtension(moduleName);
2278 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2280 int len = strlen(moduleName) - 3;
2281 memmove(moduleName, moduleName + 3, len);
2282 moduleName[len] = 0;
2286 for(module = componentsApp.allModules.first; module; module = module.next)
2288 if(module.name && (!strcmp(module.name, moduleName)))
2291 if(!module) module = componentsApp;
2292 homeModule = module;
2293 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2295 SetSymbolsDir(null);
2298 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2301 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2302 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2305 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2307 APIPage page = row.GetData(null);
2308 if(view.edit) view.OnLeftButtonDown(0,0,0);
2309 if(page && page.page) page = page.page;
2311 view.PositionCaret(true);
2312 if(page != view.page)
2314 Window activeChild = this.activeChild;
2316 // Back / Forward Support
2317 if(row && !dontRecordHistory)
2319 if(history.count > historyPos+1)
2320 history.count = historyPos+1;
2321 historyPos = history.count-1;
2322 addressBar.back.disabled = (historyPos == 0);
2323 addressBar.forward.disabled = (historyPos >= history.count-1);
2325 history.Add((Instance)(uint64)row.tag);
2326 historyPos = history.count-1;
2328 addressBar.back.disabled = (historyPos == 0);
2329 addressBar.forward.disabled = (historyPos >= history.count-1);
2335 activeChild.Activate();
2337 else if(!view.created)
2341 page = row.GetData(null);
2342 if(page && page.page)
2346 case 1: view.GoToAnchor("Classes"); break;
2347 case 2: view.GoToAnchor("Functions"); break;
2348 case 3: view.GoToAnchor("Definitions"); break;
2349 case 4: view.GoToAnchor("VirtualMethods"); break;
2350 case 5: view.GoToAnchor("Methods"); break;
2351 case 6: view.GoToAnchor("Members"); break;
2352 case 7: view.GoToAnchor("Conversions"); break;
2353 case 8: view.GoToAnchor("EnumerationValues"); break;
2357 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2358 view.GoToAnchor(hex);
2364 view.SetScrollPosition(0, 0);
2372 this, anchor = { top = 26, bottom = 0, right = 0 };
2377 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2380 bool OnClose(bool parentClosing)
2383 view.OnLeftButtonDown(0,0,0);
2389 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2390 //mainForm.OpenModule("ec");
2391 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2392 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2394 int index = mainForm.browser.currentRow.index;
2395 int rowHeight = mainForm.browser.rowHeight;
2396 int height = mainForm.browser.clientSize.h;
2398 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2403 Array<Instance> history { };
2405 bool dontRecordHistory;
2410 if(historyPos < history.count-1)
2414 addressBar.back.disabled = (historyPos == 0);
2415 addressBar.forward.disabled = (historyPos >= history.count-1);
2416 sprintf(location, "api://%p", history[historyPos]);
2417 dontRecordHistory = true;
2418 view.OnOpen(location);
2419 dontRecordHistory = false;
2431 addressBar.back.disabled = (historyPos == 0);
2432 addressBar.forward.disabled = (historyPos >= history.count-1);
2433 sprintf(location, "api://%p", history[historyPos]);
2434 dontRecordHistory = true;
2435 view.OnOpen(location);
2436 dontRecordHistory = false;
2444 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2448 class EditDialog : Window
2450 borderStyle = sizable;
2451 size = { 600, 400 };
2456 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2460 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2464 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2468 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2469 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2471 class HelpView : HTMLView
2475 hasVertScroll = true;
2476 hasHorzScroll = true;
2478 char editString[MAX_LOCATION];
2484 page = mainForm.browser.currentRow.GetData(null);
2489 char docFile[MAX_LOCATION];
2491 Module module = page ? page.GetModule() : null;
2492 NameSpace * ns = page ? page.GetNameSpace() : null;
2494 sprintf(docFile, "%s/%s.eCdoc", settings.docDir, (!module || !module.name || (ns && ns->name && !strcmp(ns->name, "namespaces/ecere/namespaces/com"))) ? "ecereCOM" : module.name);
2495 if(FileExists(docFile))
2497 archive = ArchiveOpen(docFile, { true } );
2498 readOnly = archive == null;
2504 archive = ArchiveOpen(docFile, { true } );
2507 // Must create root directory on archive creation
2508 ArchiveDir dir = archive.OpenDirectory("", null, replace);
2520 GoToAnchor(page.label);
2522 if(page.page) page = page.page;
2525 return HTMLView::OnCreate();
2534 char archiveFile[MAX_LOCATION];
2535 char fileName[MAX_FILENAME];
2536 char directory[MAX_LOCATION];
2537 const char * location;
2538 Archive archive = null;
2539 if(SplitArchivePath(editString, archiveFile, &location))
2541 GetLastDirectory(location, fileName);
2542 StripLastDirectory(location, directory);
2543 archive = ArchiveOpen(archiveFile, { true } );
2549 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2551 if(block.type == TEXT && block.textLen)
2559 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2561 if(block.type == BR)
2563 else if(block.type == TEXT)
2564 f.Write(block.text, 1, block.textLen);
2569 if(!empty || archive.FileExists(location))
2571 ArchiveDir dir = archive ? archive.OpenDirectory(directory, null, replace) : null;
2573 dir.AddFromFile(fileName, f, null, replace, 0, null, null);
2580 Block parent = textBlock.parent;
2581 while((block = parent.subBlocks.first))
2583 parent.subBlocks.Remove(block);
2586 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
2587 textBlock.text = CopyString($"[Add Text]");
2588 textBlock.textLen = strlen(textBlock.text);
2589 parent.subBlocks.Add(textBlock);
2597 PositionCaret(true);
2603 bool OnLeftButtonDown(int x, int y, Modifiers mods)
2607 if(edit && (!textBlock || overLink != textBlock.parent))
2611 HTMLView::OnLeftButtonDown(x, y, mods);
2612 selPosition = curPosition = 0;
2613 selBlock = textBlock;
2617 result = HTMLView::OnLeftButtonDown(x, y, mods);
2619 if(!edit && clickedLink)
2622 if(clickedLink == overLink && clickedLink.href)
2624 if(OnOpen(clickedLink.href))
2632 if(textBlock && overLink == textBlock.parent)
2634 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2635 selBlock = textBlock;
2636 PositionCaret(true);
2644 bool OnLeftButtonUp(int x, int y, Modifiers mods)
2646 if(!edit || !textBlock || clickedLink != textBlock.parent)
2648 HTMLView::OnLeftButtonUp(x, y, mods);
2651 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2652 selBlock = textBlock;
2653 PositionCaret(true);
2664 bool OnMouseMove(int x, int y, Modifiers mods)
2666 if(edit && selecting)
2668 curPosition = TextPosFromPoint(x, y, &textBlock, true);
2669 PositionCaret(true);
2672 return HTMLView::OnMouseMove(x, y, mods);
2675 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
2677 if(edit && textBlock)
2683 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
2684 selBlock = textBlock;
2685 for(c = curPosition; c >= 0; c--)
2688 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
2689 ch = UTF8GetChar(textBlock.text + c, &numBytes);
2690 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2696 for(c = start; c < textBlock.textLen; c += numBytes)
2698 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
2699 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2702 selPosition = start;
2705 PositionCaret(true);
2713 bool OnOpen(char * href)
2715 if(!strncmp(href, "api://", 6))
2717 int64 tag = (int64)strtoull(href + 6, null, 16);
2718 DataRow row = mainForm.browser.FindSubRow(tag);
2722 mainForm.browser.SelectRow(row);
2723 while((row = row.parent))
2724 row.collapsed = false;
2725 row = mainForm.browser.currentRow;
2726 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
2729 else if(!strncmp(href, "edit://", 7))
2732 int startX = clickedLink.startX, startY = clickedLink.startY;
2733 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
2735 if(block.type == TEXT) startX = block.startX, startY = block.startY;
2736 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
2738 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
2740 display.FontExtent(block.font.font, " ", 1, null, &th);
2743 block.parent.subBlocks.Insert(null, newBlock);
2748 block.parent.subBlocks.Insert(block, newBlock);
2749 startY += block.prev.height;
2751 newBlock.startX = startX;
2752 newBlock.startY = startY;
2753 newBlock.text = new0 char[1];
2757 textBlock = (Block)clickedLink.subBlocks.first;
2758 if(!strcmp(textBlock.text, $"[Add Text]"))
2760 textBlock.text[0] = 0;
2761 textBlock.textLen = 0;
2764 strcpy(editString, href + 7);
2765 selPosition = curPosition = 0;
2766 selBlock = textBlock;
2769 // PositionCaret(true);
2776 void DeleteSelection()
2778 if(textBlock != selBlock || curPosition != selPosition)
2780 if(textBlock == selBlock)
2782 // Within same block
2783 int start = Min(curPosition, selPosition);
2784 int end = Max(curPosition, selPosition);
2785 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
2786 textBlock.textLen -= end-start;
2787 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
2788 curPosition = start;
2789 selPosition = start;
2793 int startSel, endSel;
2794 Block startSelBlock = null, endSelBlock = null, b, next;
2796 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2798 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
2799 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
2801 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
2802 for(b = startSelBlock.next; b; b = next)
2804 bool isEnd = b == endSelBlock;
2805 next = GetNextBlock(b);
2806 b.parent.subBlocks.Remove(b);
2811 textBlock = startSelBlock;
2812 selBlock = startSelBlock;
2813 curPosition = startSel;
2814 selPosition = startSel;
2818 PositionCaret(true);
2823 String GetSelectionString()
2825 String selection = null;
2826 if(textBlock == selBlock)
2828 // Within same block
2829 int start = Min(curPosition, selPosition);
2830 int end = Max(curPosition, selPosition);
2831 int len = end - start;
2832 selection = new char[len + 1];
2833 memcpy(selection, textBlock.text + start, len);
2838 int startSel, endSel;
2839 Block startSelBlock = null, endSelBlock = null, b;
2842 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2845 for(b = startSelBlock; b; b = GetNextBlock(b))
2847 int start = (b == startSelBlock) ? startSel : 0;
2848 int end = (b == endSelBlock) ? endSel : b.textLen;
2849 int len = end - start;
2851 if(b == endSelBlock)
2853 else if(b.type == TEXT)
2857 selection = new char[totalLen + 1];
2859 for(b = startSelBlock; b; b = GetNextBlock(b))
2861 int start = (b == startSelBlock) ? startSel : 0;
2862 int end = (b == endSelBlock) ? endSel : b.textLen;
2863 int len = end - start;
2864 memcpy(selection + totalLen, b.text + start, len);
2866 if(b == endSelBlock)
2868 else if(b.type == TEXT)
2869 selection[totalLen++] = '\n';
2871 selection[totalLen] = 0;
2876 void CopySelection()
2878 String s = GetSelectionString();
2881 int len = strlen(s);
2883 if(cb.Allocate(len + 1))
2885 memcpy(cb.text, s, len + 1);
2893 bool OnKeyDown(Key key, unichar ch)
2900 OnLeftButtonDown(0,0,0);
2902 case Key { end, shift = true }:
2904 curPosition = textBlock.textLen;
2907 selPosition = curPosition;
2908 selBlock = textBlock;
2910 PositionCaret(true);
2913 case Key { home, shift = true }:
2918 selPosition = curPosition;
2919 selBlock = textBlock;
2921 PositionCaret(true);
2924 case Key { home, ctrl = true, shift = true }:
2927 while(textBlock.prev)
2928 textBlock = textBlock.prev.prev;
2931 selPosition = curPosition;
2932 selBlock = textBlock;
2934 PositionCaret(true);
2937 case Key { end, ctrl = true, shift = true }:
2939 while(textBlock.next && textBlock.next.next)
2940 textBlock = textBlock.next.next;
2941 curPosition = textBlock.textLen;
2944 selPosition = curPosition;
2945 selBlock = textBlock;
2947 PositionCaret(true);
2953 return HTMLView::OnKeyDown(key, ch);
2957 bool OnKeyHit(Key key, unichar ch)
2963 case Key { up, shift = true }:
2966 if(caretY == textBlock.startY)
2970 textBlock = textBlock.prev.prev;
2971 curPosition = Min(curPosition, textBlock.textLen);
2974 selPosition = curPosition;
2975 selBlock = textBlock;
2978 PositionCaret(false);
2988 int sx = textBlock.startX, sy = textBlock.startY;
2989 char * text = textBlock.text;
2991 Block block = textBlock;
2992 while(block && block.type != TD) block = block.parent;
2995 Block table = block;
2996 while(table && table.type != TABLE) table = table.parent;
2998 maxW = block.w - 2* table.cellPadding;
3000 maxW = clientSize.w - 10 - sx;
3003 maxW = clientSize.w - 10 - sx;
3004 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3008 int startPos = textPos;
3011 bool lineComplete = false;
3012 for(; textPos<textBlock.textLen && !lineComplete;)
3016 char * nextSpace = strchr(text + textPos, ' ');
3019 len = (nextSpace - (text + textPos)) + 1;
3021 len = textBlock.textLen - textPos;
3023 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3025 if(x + width + w > maxW && x > 0)
3027 lineComplete = true;
3037 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3040 curPosition = textPos;
3041 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3044 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3045 len = curPosition - startPos;
3046 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3050 selPosition = curPosition;
3051 selBlock = textBlock;
3055 PositionCaret(false);
3059 if(sy == caretY - th || textPos == textBlock.textLen)
3061 if(textPos != textBlock.textLen)
3063 int c = textPos - 1;
3064 while(c > 0 && text[c] == ' ') c--;
3065 curPosition = c + 1;
3068 selPosition = curPosition;
3069 selBlock = textBlock;
3075 curPosition = textBlock.textLen;
3078 selPosition = curPosition;
3079 selBlock = textBlock;
3083 PositionCaret(false);
3087 sx = textBlock.startX;
3088 } while(textPos < textBlock.textLen);
3093 case Key { down, shift = true }:
3098 int sx = textBlock.startX, sy = textBlock.startY;
3099 char * text = textBlock.text;
3101 Block block = textBlock;
3102 while(block && block.type != TD) block = block.parent;
3105 Block table = block;
3106 while(table && table.type != TABLE) table = table.parent;
3108 maxW = block.w - 2* table.cellPadding;
3110 maxW = clientSize.w - 10 - sx;
3113 maxW = clientSize.w - 10 - sx;
3114 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3116 while(!textPos || textPos < textBlock.textLen)
3118 int startPos = textPos;
3121 bool lineComplete = false;
3122 for(; (textPos < textBlock.textLen) && !lineComplete;)
3126 char * nextSpace = strchr(text + textPos, ' ');
3129 len = (nextSpace - (text + textPos)) + 1;
3131 len = textBlock.textLen - textPos;
3133 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3135 if(x + width + w > maxW && x > 0)
3137 lineComplete = true;
3147 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3149 curPosition = textPos;
3151 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3154 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3155 len = curPosition - startPos;
3156 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3160 selPosition = curPosition;
3161 selBlock = textBlock;
3164 PositionCaret(false);
3170 curPosition = textBlock.textLen;
3173 selPosition = curPosition;
3174 selBlock = textBlock;
3177 PositionCaret(false);
3180 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3184 textBlock = textBlock.next.next;
3185 sy = textBlock.startY;
3186 sx = textBlock.startX;
3187 text = textBlock.text;
3192 sx = textBlock.startX;
3196 /*if(textBlock.next && textBlock.next.next)
3198 textBlock = textBlock.next.next;
3199 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3200 selBlock = textBlock;
3201 PositionCaret(false);
3205 case Key { right, shift = true, ctrl = true }:
3208 bool foundAlpha = false;
3210 Block line, lastLine;
3213 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3215 int start = (line == textBlock) ? curPosition : 0;
3217 for(c = start; c < line.textLen; c++)
3219 char ch = line.text[c];
3220 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3221 if(key.shift ? isAlUnder : !isAlUnder)
3235 selPosition = curPosition;
3236 selBlock = textBlock;
3240 PositionCaret(true);
3245 // No next word found,
3246 if(!found && (c != curPosition || line != textBlock))
3250 lastC = line.textLen-1;
3255 curPosition = line.textLen;
3258 selPosition = curPosition;
3259 selBlock = textBlock;
3264 PositionCaret(true);
3270 if(key.shift && found)
3272 curPosition = lastC+1;
3273 textBlock = lastLine;
3274 PositionCaret(true);
3279 case Key { left, ctrl = true, shift = true }:
3282 bool foundAlpha = false;
3284 Block line, lastLine;
3287 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3290 if(curPosition == 0 && line != textBlock)
3293 lastC = line.textLen;
3297 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3298 for(c = start; c>=0; c--)
3300 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3315 // No next word found,
3316 if(!found && curPosition > 0)
3326 textBlock = lastLine;
3327 curPosition = lastC;
3330 selPosition = curPosition;
3331 selBlock = textBlock;
3333 PositionCaret(true);
3338 case Key { right, shift = true }:
3340 if(curPosition < textBlock.textLen)
3342 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3345 selPosition = curPosition;
3346 selBlock = textBlock;
3348 PositionCaret(true);
3351 else if(textBlock.next && textBlock.next.next)
3353 textBlock = textBlock.next.next;
3357 selPosition = curPosition;
3358 selBlock = textBlock;
3360 PositionCaret(true);
3364 case Key { left, shift = true }:
3368 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3371 selPosition = curPosition;
3372 selBlock = textBlock;
3374 PositionCaret(true);
3377 else if(textBlock.prev)
3379 textBlock = textBlock.prev.prev;
3380 curPosition = textBlock.textLen;
3383 selPosition = curPosition;
3384 selBlock = textBlock;
3386 PositionCaret(true);
3392 if(textBlock == selBlock && curPosition == selPosition)
3396 int c = curPosition;
3398 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3399 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3400 textBlock.textLen -= nb;
3401 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3403 selPosition = curPosition;
3404 selBlock = textBlock;
3408 PositionCaret(true);
3411 else if(textBlock.prev)
3413 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3414 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3415 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3417 selPosition = curPosition = prevBlock.textLen;
3418 selBlock = textBlock;
3419 prevBlock.textLen += textBlock.textLen;
3420 textBlock.parent.subBlocks.Remove(prev);
3421 if(prev == selBlock)
3423 selBlock = textBlock;
3424 selPosition = curPosition;
3427 textBlock.parent.subBlocks.Remove(textBlock);
3428 if(textBlock == selBlock)
3430 selBlock = prevBlock;
3431 selPosition = curPosition;
3434 textBlock = prevBlock;
3438 PositionCaret(true);
3447 if(textBlock != selBlock || curPosition != selPosition)
3449 else if(textBlock.textLen > curPosition)
3451 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3452 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3453 textBlock.textLen -= nb;
3454 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3459 PositionCaret(true);
3462 else if(textBlock.next && textBlock.next.next)
3464 Block next = textBlock.next, nextBlock = textBlock.next.next;
3465 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3466 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3468 textBlock.textLen += nextBlock.textLen;
3469 textBlock.parent.subBlocks.Remove(next);
3470 if(next == selBlock)
3472 selBlock = textBlock;
3473 selPosition = curPosition;
3476 textBlock.parent.subBlocks.Remove(nextBlock);
3477 if(nextBlock == selBlock)
3479 selBlock = textBlock;
3480 selPosition = curPosition;
3486 PositionCaret(true);
3500 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3501 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3502 startY = textBlock.startY;
3503 startX = textBlock.startX;
3505 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3506 textBlock.parent.subBlocks.Insert(textBlock, block);
3507 textBlock.parent.subBlocks.Insert(block, newBlock);
3511 newBlock.textLen = textBlock.textLen - curPosition;
3512 newBlock.text = new char[newBlock.textLen+1];
3513 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3514 textBlock.textLen = curPosition;
3515 textBlock.text[curPosition] = 0;
3517 newBlock.startY = startY;
3518 newBlock.startX = startX;
3519 selPosition = curPosition = 0;
3524 textBlock = newBlock;
3525 selBlock = textBlock;
3526 PositionCaret(true);
3531 case Key { del, shift = true }:
3546 ClipBoard clipBoard { };
3547 if(clipBoard.Load())
3550 char * text = clipBoard.memory;
3558 parent = textBlock.parent;
3559 font = textBlock.font;
3564 if(ch == '\n' || ch == '\r' || !ch)
3566 int len = c - start;
3567 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
3568 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3569 memcpy(textBlock.text + curPosition, text + start, len);
3570 textBlock.textLen += len;
3572 selPosition = curPosition;
3573 selBlock = textBlock;
3576 Block block { type = BR, parent = parent, font = font };
3577 Block newBlock { type = TEXT, parent = parent, font = font };
3578 int startY = textBlock.startY, startX = textBlock.startX;
3581 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3582 textBlock.parent.subBlocks.Insert(textBlock, block);
3583 textBlock.parent.subBlocks.Insert(block, newBlock);
3587 newBlock.textLen = textBlock.textLen - curPosition;
3588 newBlock.text = new char[newBlock.textLen+1];
3589 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3590 textBlock.textLen = curPosition;
3591 textBlock.text[curPosition] = 0;
3593 newBlock.startY = startY;
3594 newBlock.startX = startX;
3595 selPosition = curPosition = 0;
3596 selBlock = textBlock;
3597 textBlock = newBlock;
3599 if(ch == '\r' && text[c+1] == '\n') c++;
3605 PositionCaret(true);
3613 // eC BUG HERE: (Should be fixed)
3614 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
3617 int len = UTF32toUTF8Len(&ch, 1, string, 5);
3622 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
3623 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3625 for(c = 0; c<len; c++)
3627 textBlock.text[curPosition] = string[c];
3628 textBlock.textLen++;
3631 selPosition = curPosition;
3632 selBlock = textBlock;
3635 //Clear(html.block);
3636 //CreateForms(html.block);
3641 PositionCaret(true);
3650 void OnResize(int width, int height)
3652 HTMLView::OnResize(width, height);
3653 PositionCaret(true);
3657 void PositionCaret(bool setCaretX)
3663 int sx = textBlock.startX, sy = textBlock.startY;
3664 char * text = textBlock.text;
3666 Block block = textBlock;
3667 while(block && block.type != TD) block = block.parent;
3670 Block table = block;
3671 while(table && table.type != TABLE) table = table.parent;
3673 maxW = block.w - 2* table.cellPadding;
3675 maxW = clientSize.w - 10 - sx;
3678 maxW = clientSize.w - 10 - sx;
3680 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3682 while(textPos < textBlock.textLen)
3684 int startPos = textPos;
3687 bool lineComplete = false;
3689 for(; textPos<textBlock.textLen && !lineComplete;)
3693 char * nextSpace = strchr(text + textPos, ' ');
3696 len = (nextSpace - (text + textPos)) + 1;
3698 len = textBlock.textLen - textPos;
3700 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3702 if(x + width + w > maxW && x > 0)
3704 lineComplete = true;
3717 if(curPosition < textPos || textPos == textBlock.textLen)
3719 int len = curPosition - startPos;
3720 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
3725 sx = textBlock.startX;
3730 SetCaret(sx, sy, th);
3732 Point scrollPos = scroll;
3733 bool doScroll = false;
3734 if(sy - scroll.y + th > clientSize.h)
3736 scrollPos.y = sy + th - clientSize.h;
3739 else if(sy - scroll.y < 0)
3744 if(sx - scroll.x + 10 > clientSize.w)
3746 scrollPos.x = sx + 10 - clientSize.w;
3749 else if(sx - scroll.x < 10)
3751 scrollPos.x = sx - 10;
3762 // Returns a character offset into the TextBlock from a window coordinate
3763 int TextPosFromPoint(int px, int py, Block * block, bool half)
3765 Block parentBlock = this.textBlock.parent;
3768 *block = this.textBlock;
3773 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
3775 int sx = textBlock.startX, sy = textBlock.startY;
3778 char * text = textBlock.text;
3780 Block b = textBlock;
3783 if(textBlock.type != TEXT) continue;
3785 while(b && b.type != TD) b = b.parent;
3789 while(table && table.type != TABLE) table = table.parent;
3791 maxW = b.w - 2* table.cellPadding;
3793 maxW = clientSize.w - 10 - sx;
3796 maxW = clientSize.w - 10 - sx;
3798 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
3799 //space = space/2+2;
3802 while(textPos < textBlock.textLen)
3806 bool lineComplete = false;
3808 for(; textPos<textBlock.textLen && !lineComplete;)
3812 char * nextSpace = strchr(text + textPos, ' ');
3815 len = (nextSpace - (text + textPos)) + 1;
3817 len = textBlock.textLen - textPos;
3819 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3821 sx = x + textBlock.startX;
3822 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
3827 for(c = textPos; (ch = text[c]); c += numBytes)
3829 numBytes = UTF8_NUM_BYTES(ch);
3830 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
3831 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
3838 if(x + width + w > maxW && x > 0)
3840 lineComplete = true;
3853 if(/*py >= sy && */py < sy + th)
3856 return textBlock.textLen;
3861 result = textBlock.textLen;
3867 Application componentsApp;
3869 class Documentor : GuiApplication
3873 Platform os = __runtimePlatform;
3874 SetGlobalContext(globalContext);
3875 SetExcludedSymbols(&excludedSymbols);
3876 SetDefines(&::defines);
3877 SetImports(&imports);
3878 SetInDocumentor(true);
3880 SetGlobalData(globalData);
3882 settingsContainer.dataOwner = &settings;
3883 settingsContainer.Load();
3884 if(!settings.docDir || !settings.docDir[0] )
3886 if(os == win32) // if Windows OS then
3888 char programFilesDir[MAX_LOCATION];
3889 char appData[MAX_LOCATION];
3890 char homeDrive[MAX_LOCATION];
3891 char winDir[MAX_LOCATION];
3892 GetEnvironment("APPDATA", appData, sizeof(appData));
3893 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
3894 GetEnvironment("windir", winDir, sizeof(winDir));
3895 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
3897 PathCat(programFilesDir, "ECERE SDK\\doc");
3898 settings.docDir = programFilesDir;
3900 else if(homeDrive[0])
3902 PathCat(homeDrive, "ECERE SDK\\doc");
3903 settings.docDir = homeDrive;
3907 PathCat(winDir, "..\\ECERE SDK\\doc");
3908 settings.docDir = winDir;
3911 settings.docDir = "C:\\ECERE SDK\\doc";
3913 else // if Os is Linux, or Mac OSX or something else
3914 settings.docDir = "/usr/share/ecere/doc/";
3915 settingsContainer.Save();
3921 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
3923 AddComponents(module, true);
3924 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
3925 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
3926 while((row = row.parent))
3927 row.collapsed = false;
3931 commandThread.Create();
3935 bool Cycle(bool idle)
3938 mainForm.Destroy(0);
3947 if(commandThread.created)
3949 console.CloseInput();
3950 console.CloseOutput();
3952 commandThread.Wait();
3956 FreeContext(globalContext);
3957 FreeExcludedSymbols(excludedSymbols);
3958 ::defines.Free(FreeModuleDefine);
3959 imports.Free(FreeModuleImport);
3961 FreeGlobalData(globalData);
3962 FreeTypeData(componentsApp);
3964 delete componentsApp;
3968 ConsoleFile console { };
3969 MainForm mainForm { };
3972 Thread commandThread
3979 console.GetLine(command, sizeof(command));
3980 if(!quit && command[0])
3983 if(!strcmpi(command, "Activate"))
3984 mainForm.Activate();
3985 else if(!strcmpi(command, "Quit"))