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 pc = eSystem_FindClass(m, curName);
82 sprintf(d, "<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", pc, pc.name);
87 strcat(templateString, "<");
89 strcat(templateString, ">");
91 strcat(templateString, ", ");
100 strcat(templateString, curName);
108 // WARNING : This function expects a null terminated string since it recursively concatenate...
109 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
113 if(type.constant && (type.kind != pointerType && type.kind != arrayType))
114 strcat(string, "const ");
118 if(type._class && type._class.string)
121 strcat(string, type._class.string);
124 if(type._class.registered)
127 const char * s = type._class.registered.name;
128 sprintf(hex, "%p", type._class.registered.templateClass ? type._class.registered.templateClass : type._class.registered);
129 strcat(string, "<a href=\"api://");
131 strcat(string, "\" style=\"text-decoration: none;\">");
135 GetTemplateString(type._class.registered, n);
139 strcat(string, type._class.registered.name);
140 strcat(string, "</a>");
143 strcat(string, type._class.string);
150 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
151 if(funcType && funcType.kind == functionType)
154 DocPrintType(funcType.returnType, string, false, fullName);
155 strcat(string, "(*");
156 if(printName || funcType.thisClass)
159 if(funcType.thisClass)
161 strcat(string, funcType.thisClass.string);
162 strcat(string, "::");
165 strcat(string, type.name);
167 strcat(string, ")(");
168 for(param = funcType.params.first; param; param = param.next)
170 DocPrintType(param, string, false, fullName);
171 if(param.next) strcat(string, ", ");
177 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
178 if(string[strlen(string)-1] == '(')
181 strcat(string, " *");
185 case voidType: strcat(string, "void"); break;
186 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
187 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
188 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
189 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
190 case floatType: strcat(string, "float"); break;
191 case doubleType: strcat(string, "double"); break;
195 strcat(string, "struct ");
196 strcat(string, type.enumName);
198 else if(type.typeName)
200 strcat(string, type.typeName);
205 strcat(string, "struct ");
206 strcat(string,"(unnamed)");
209 strcat(string, "struct {");
210 for(member = type.members.first; member; member = member.next)
212 DocPrintType(member, string, true, fullName);
221 strcat(string, "union ");
222 strcat(string, type.enumName);
224 else if(type.typeName)
226 strcat(string, type.typeName);
230 strcat(string, "union ");
231 strcat(string,"(unnamed)");
237 strcat(string, "enum ");
238 strcat(string, type.enumName);
240 else if(type.typeName)
242 strcat(string, type.typeName);
245 strcat(string, "enum");
252 strcat(string, "dllexport ");
253 DocPrintType(type.returnType, string, false, fullName);
257 // DANGER: Testing This
263 strcat(string, type.name);
266 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
267 if(name) name += 2; else name = type.name;
268 strcat(string, "<b>");
269 strcat(string, name);
270 strcat(string, "</b>");
279 for(param = type.params.first; param; param = param.next)
281 DocPrintType(param, string, true, fullName);
282 if(param.next) strcat(string, ", ");
291 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
292 if(funcType && funcType.kind == functionType)
295 DocPrintType(funcType.returnType, string, false, fullName);
296 strcat(string, "(*");
297 if(printName || funcType.thisClass)
300 if(funcType.thisClass)
302 strcat(string, funcType.thisClass.string);
303 strcat(string, "::");
306 strcat(string, type.name);
308 strcat(string, ")(");
309 for(param = funcType.params.first; param; param = param.next)
311 DocPrintType(param, string, false, fullName);
312 if(param.next) strcat(string, ", ");
318 char baseType[1024], size[256];
319 Type arrayType = type;
323 while(arrayType.kind == TypeKind::arrayType)
326 if(arrayType.enumClass)
327 strcat(size, arrayType.enumClass.string);
328 else if(arrayType.arraySizeExp)
329 PrintExpression(arrayType.arraySizeExp, size);
330 //sprintf(string, "%s[%s]", baseType, size);
333 arrayType = arrayType.arrayType;
335 _PrintType(arrayType, baseType, printName, printFunction, fullName);
336 strcat(string, baseType);
337 strcat(string, size);
341 DocPrintType(type.arrayType, baseType, printName, fullName);
343 strcpy(size, type.enumClass.string);
344 else if(type.arraySizeExp)
345 PrintExpression(type.arraySizeExp, size);
346 //sprintf(string, "%s[%s]", baseType, size);
347 strcat(string, baseType);
349 strcat(string, size);
357 strcat(string, "...");
360 _PrintType(type.method.dataType, string, false, printFunction, fullName);
363 strcat(string, "subclass(");
364 strcat(string, type._class ? type._class.string : "int");
370 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
373 strcat(string, type.name);
378 void DocPrintType(Type type, char * string, bool printName, bool fullName)
381 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
382 if(funcType && funcType.kind == functionType && type != funcType)
386 DocPrintType(funcType.returnType, string, false, fullName);
388 _PrintType(type, string, printName, false, fullName);
392 strcat(string, type.name);
399 for(param = funcType.params.first; param; param = param.next)
401 DocPrintType(param, string, true, fullName);
402 if(param.next) strcat(string, ", ");
407 _PrintType(type, string, printName, true, fullName);
410 void AddComponents(Module module, bool isDll)
415 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
417 row = mainForm.browser.AddRow();
418 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
419 row.tag = (int64)null;
420 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
423 for(m = module.modules.first; m; m = m.next)
425 if(m.importMode == publicAccess || !isDll)
426 AddComponents(m.module, true);
429 // PUT MODULE DESCRIPTION HERE
430 if(module.name && strcmp(module.name, "ecereCOM"))
432 row = mainForm.browser.AddRow();
433 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
434 row.tag = (int64)module;
435 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
437 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
449 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
454 virtual void Generate(File f)
459 virtual Module GetModule()
461 return page ? page.GetModule() : null;
464 virtual NameSpace * GetNameSpace()
466 return page ? page.GetNameSpace() : null;
470 enum DocumentationType
478 enum DocumentationItem
494 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
496 NameSpace * nameSpace, * ns;
498 Method method = null;
499 GlobalFunction function = null;
500 char nsName[1024], temp[1024];
506 case nameSpaceDoc: nameSpace = object; break;
507 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
508 case functionDoc: function = object; nameSpace = function.nameSpace; break;
509 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
514 while(ns && ns->name)
516 strcpy(temp, "namespaces/");
517 strcat(temp, ns->name);
519 strcat(temp, nsName);
520 strcpy(nsName, temp);
523 sprintf(docFile, "%s.eCdoc", (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
524 if(strchr(docFile, DIR_SEP))
526 GetLastDirectory(docFile, temp);
527 strcpy(docFile, temp);
530 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.
531 strcat(fileName, nsName);
535 strcat(fileName, "classes/");
536 strcat(fileName, cl.name);
537 strcat(fileName, "/");
542 strcat(fileName, "methods/");
543 strcat(fileName, method.name);
544 strcat(fileName, "/");
548 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
549 if(name) name += 2; else name = function.name;
550 strcat(fileName, "functions/");
551 strcat(fileName, name);
552 strcat(fileName, "/");
557 case description: strcat(fileName, "description"); break;
558 case usage: strcat(fileName, "usage"); break;
559 case remarks: strcat(fileName, "remarks"); break;
560 case example: strcat(fileName, "example"); break;
561 case seeAlso: strcat(fileName, "seeAlso"); break;
562 case returnValue: strcat(fileName, "returnValue"); break;
563 case enumerationValue:
564 strcat(fileName, "enumeration values/");
565 strcat(fileName, ((NamedLink)data).name);
568 strcat(fileName, "definitions/");
569 strcat(fileName, ((Definition)data).name);
573 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
574 if(name) name += 2; else name = ((Property)data).name;
575 strcat(fileName, "conversions/");
576 strcat(fileName, name);
579 case memberDescription:
580 strcat(fileName, "data members/");
581 strcat(fileName, ((DataMember)data).name);
583 case propertyDescription:
584 strcat(fileName, "properties/");
585 strcat(fileName, ((Property)data).name);
592 strcat(fileName, "parameters/");
593 for(prev = data, count = 0; prev; prev = prev.prev, count++);
594 sprintf(name, "%s.%d", ((Type)data).name, count);
595 strcat(fileName, name);
601 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
603 char fileName[MAX_LOCATION];
604 String contents = null;
607 FigureFileName(fileName, module, type, object, item, data);
608 file = FileOpen(fileName, read);
612 if((len = file.GetSize()))
614 contents = new char[len+1];
615 file.Read(contents, 1, len);
616 contents[len] = '\0';
623 for(c = 0; contents[c]; c++)
624 if(!isspace(contents[c])) break;
628 if(editing && !contents && !readOnly)
629 contents = CopyString($"[Add Text]");
633 class APIPageNameSpace : APIPage
635 NameSpace * nameSpace;
643 NameSpace * GetNameSpace()
648 void Generate(File f)
650 char nsName[1024], temp[1024];
656 while(ns && ns->name)
658 strcpy(temp, ns->name);
659 if(nsName[0]) strcat(temp, "::");
660 strcat(temp, nsName);
661 strcpy(nsName, temp);
664 // Generate Class Page
665 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
668 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
669 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);
672 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
675 ns = nameSpace->parent;
676 while(ns && ns->name)
678 strcpy(temp, ns->name);
679 if(nsName[0]) strcat(temp, "::");
680 strcat(temp, nsName);
681 strcpy(nsName, temp);
685 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
689 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
692 f.Printf($"<H3>Description</H3><br><br>\n");
695 char fileName[MAX_LOCATION];
696 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
697 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
699 f.Printf("</a><br><br>");
702 f.Printf("%s<br><br>", desc);
707 if(nameSpace->nameSpaces.first)
710 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
712 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
715 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
716 f.Printf("<TABLE>\n");
720 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);
725 char fileName[MAX_LOCATION];
726 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
727 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
729 f.Printf("</a></TD>");
732 f.Printf("<TD valign=top height=22> %s</TD>", desc);
735 f.Printf("</TR><br>\n");
738 f.Printf("</TABLE><br>\n");
741 if(nameSpace->classes.first)
744 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
746 Class cl = link.data;
747 if(!cl.templateClass)
749 char * desc = ReadDoc(module, classDoc, cl, description, null);
753 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
754 f.Printf("<TABLE>\n");
760 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);
765 char fileName[MAX_LOCATION];
766 FigureFileName(fileName, module, classDoc, cl, description, null);
767 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
769 f.Printf("</a></TD>");
772 f.Printf("<TD valign=top height=22>%s</TD>", desc);
779 f.Printf("</TABLE><br>\n");
782 if(nameSpace->functions.first)
785 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
787 GlobalFunction function = link.data;
788 char * desc = ReadDoc(module, functionDoc, function, description, null);
789 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
790 if(name) name += 2; else name = function.name;
793 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
794 f.Printf("<TABLE>\n");
798 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);
803 char fileName[MAX_LOCATION];
804 FigureFileName(fileName, module, functionDoc, function, description, null);
805 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
807 f.Printf("</a></TD>");
810 f.Printf("<TD valign=top height=22> %s</TD>", desc);
813 f.Printf("</TR><br>\n");
816 f.Printf("</TABLE><br>\n");
819 if(nameSpace->defines.first)
822 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
824 DefinedExpression def = link.data;
825 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
828 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
829 f.Printf("<TABLE>\n");
833 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);
834 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
839 char fileName[MAX_LOCATION];
840 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
841 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
843 f.Printf("</a></TD>");
846 f.Printf("<TD valign=top height=22> %s</TD>", desc);
849 f.Printf("</TR><br>\n");
852 f.Printf("</TABLE><br>\n");
855 f.Printf("</FONT></BODY></HTML>\n");
859 class APIPageClass : APIPage
868 NameSpace * GetNameSpace()
873 void Generate(File f)
878 char nsName[1024], temp[1024];
879 NameSpace * ns = cl.nameSpace;
880 Module module = cl.module;
883 while(ns && ns->name)
885 strcpy(temp, ns->name);
886 if(nsName[0]) strcat(temp, "::");
887 strcat(temp, nsName);
888 strcpy(nsName, temp);
891 // Generate Class Page
892 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
893 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
895 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);
897 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
900 const char * classType = null;
904 classType = $"Bit Collection";
907 classType = $"Enumeration";
910 classType = $"Structure";
913 classType = $"Class";
916 classType = $"Class (No header)";
922 classType = $"Basic Data Type";
925 f.Printf($"Type: %s<br>\n", classType);
928 if(cl.type != systemClass && cl.base)
930 f.Printf($"Base Class: ");
931 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
933 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
935 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
936 f.Printf("%s", cl.dataTypeString);
938 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
943 char * desc = ReadDoc(module, classDoc, cl, description, null);
946 f.Printf($"<br><H3>Description</H3><br><br>\n");
949 char fileName[MAX_LOCATION];
950 FigureFileName(fileName, module, classDoc, cl, description, null);
951 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
953 f.Printf("</a><br><br>");
956 f.Printf("%s<br><br>", desc);
961 if(cl.type == enumClass)
963 EnumClassData enumeration = (EnumClassData)cl.data;
964 if(enumeration.values.first)
968 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
969 f.Printf("<TABLE>\n");
971 for(item = enumeration.values.first; item; item = item.next)
973 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
974 bool needClass = true;
977 char tempString[1024];
979 while(base.type == enumClass) base = base.base;
981 if(base.type == systemClass ||
982 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
985 base.dataType = ProcessTypeString(base.dataTypeString, false);
987 if(base.dataType.kind != classType)
992 PrintType(base.dataType, string, false, true);
993 classSym = FindClass(string);
994 dataClass = classSym ? classSym.registered : null;
997 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1003 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);
1004 if(dataClass.type == systemClass)
1007 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1010 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1012 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1014 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1019 char fileName[MAX_LOCATION];
1020 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1021 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1023 f.Printf("</a></TD>");
1026 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1031 f.Printf("</TABLE><BR>\n");
1035 if(cl.conversions.first)
1037 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
1038 f.Printf("<TABLE>\n");
1039 for(prop = cl.conversions.first; prop; prop = prop.next)
1041 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1043 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1045 Type type = ProcessTypeString(prop.name, false);
1046 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1047 if(name) name += 2; else name = prop.name;
1052 DocPrintType(type, string, true, false);
1054 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1059 char fileName[MAX_LOCATION];
1060 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1061 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1063 f.Printf("</a></TD>");
1066 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1070 f.Printf("</TR>\n");
1075 f.Printf("</TABLE><br>\n");
1078 if(cl.membersAndProperties.first)
1081 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1083 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1087 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1088 f.Printf("<TABLE>\n");
1094 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1096 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1100 DocPrintType(prop.dataType, string, true, false);
1102 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);
1103 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1108 char fileName[MAX_LOCATION];
1109 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1110 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1112 f.Printf("</a></TD>");
1115 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1118 f.Printf("</TR>\n");
1122 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1127 f.Printf("</TABLE><br>\n");
1130 if(cl.methods.first)
1134 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1136 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1138 char * desc = ReadDoc(module, methodDoc, method, description, null);
1141 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1142 f.Printf("<TABLE>\n");
1145 if(!method.dataType)
1146 ProcessMethodType(method);
1149 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);
1154 char fileName[MAX_LOCATION];
1155 FigureFileName(fileName, module, methodDoc, method, description, null);
1156 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1158 f.Printf("</a></TD>");
1161 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1164 f.Printf("</TR><br>\n");
1168 f.Printf("</TABLE><br>\n");
1170 // Non-Virtual Methods
1172 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1174 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1176 char * desc = ReadDoc(module, methodDoc, method, description, null);
1179 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1180 f.Printf("<TABLE>\n");
1184 if(!method.dataType)
1185 ProcessMethodType(method);
1188 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);
1193 char fileName[MAX_LOCATION];
1194 FigureFileName(fileName, module, methodDoc, method, description, null);
1195 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1197 f.Printf("</a></TD>");
1200 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1204 f.Printf("</TR><br>\n");
1208 f.Printf("</TABLE><br>\n");
1211 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1214 f.Printf($"<H3>Usage</H3><br>\n");
1217 char fileName[MAX_LOCATION];
1218 FigureFileName(fileName, module, classDoc, cl, usage, null);
1219 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1224 f.Printf("<br>%s\n", usageDoc);
1225 f.Printf("<br><br>\n");
1230 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1233 f.Printf($"<H3>Example</H3><br>\n");
1234 f.Printf($"<FONT face=\"Courier New\">\n");
1235 f.Printf("<br><TABLE>\n");
1238 char fileName[MAX_LOCATION];
1239 FigureFileName(fileName, module, classDoc, cl, example, null);
1240 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1242 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1245 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1247 f.Printf("</TABLE></FONT>\n");
1253 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1257 f.Printf($"<H3>Remarks</H3><br>\n");
1260 char fileName[MAX_LOCATION];
1261 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1262 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1267 f.Printf("<br>%s\n", remarksDoc);
1268 f.Printf("<br><br>\n");
1273 if(cl.type != systemClass)
1277 for(c = cl.derivatives.first; c; c = c.next)
1279 Class deriv = c.data;
1280 // TO VERIFY: Does this properly check public status?
1281 if(eSystem_FindClass(componentsApp, deriv.fullName))
1285 f.Printf($"<H3>Derived Classes</H3><br>\n");
1291 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1295 f.Printf("<br><br>\n");
1298 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1301 f.Printf($"<H3>See Also</H3><br>\n");
1304 char fileName[MAX_LOCATION];
1305 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1306 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1311 f.Printf("<br>%s\n", seeAlsoDoc);
1312 f.Printf("<br><br>\n");
1316 f.Printf("</FONT></BODY></HTML>\n");
1320 class APIPageMethod : APIPage
1326 return method._class.module;
1329 NameSpace * GetNameSpace()
1331 return method._class.nameSpace;
1334 void Generate(File f)
1336 Class cl = method._class;
1338 Module module = cl.module;
1340 char nsName[1024], temp[1024];
1341 NameSpace * ns = cl.nameSpace;
1344 while(ns && ns->name)
1346 strcpy(temp, ns->name);
1347 if(nsName[0]) strcat(temp, "::");
1348 strcat(temp, nsName);
1349 strcpy(nsName, temp);
1353 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1354 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1356 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);
1358 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1359 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1360 if(method.dataType.staticMethod)
1362 f.Printf($"this pointer class: None<br>\n");
1364 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1366 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);
1369 // Generate Method Page
1371 if(!method.dataType.name)
1372 method.dataType.name = CopyString(method.name);
1373 DocPrintType(method.dataType, string, true, false);
1374 f.Printf("<br>%s", string);
1377 char * desc = ReadDoc(module, methodDoc, method, description, null);
1380 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1383 char fileName[MAX_LOCATION];
1384 FigureFileName(fileName, module, methodDoc, method, description, null);
1385 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1390 f.Printf("%s", desc);
1395 f.Printf("<br><br>\n");
1396 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1398 f.Printf($"<H3>Parameters</H3><br><br>\n");
1400 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1401 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1403 f.Printf("<TABLE valign=center>\n");
1406 for(param = method.dataType.params.first; param; param = param.next)
1408 // ADD DESCRIPTION HERE
1409 if(param.kind != voidType)
1411 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1414 DocPrintType(param, string, false, false);
1416 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1417 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1422 char fileName[MAX_LOCATION];
1423 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1424 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1426 f.Printf("</a></TD>\n");
1429 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1433 f.Printf("</TR>\n");
1436 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1438 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1439 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1441 f.Printf("<TR><TD> </TD></TR>");
1444 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1446 DocPrintType(method.dataType.returnType, string, false, false);
1447 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1452 char fileName[MAX_LOCATION];
1453 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1454 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1456 f.Printf("</a> </TD>\n");
1459 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1462 f.Printf("</TR>\n");
1463 f.Printf("</TABLE>\n");
1465 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1466 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1468 f.Printf("</TABLE><br>\n");
1471 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1474 f.Printf($"<H3>Usage</H3><br>\n");
1477 char fileName[MAX_LOCATION];
1478 FigureFileName(fileName, module, methodDoc, method, usage, null);
1479 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1484 f.Printf("<br>%s\n", usageDoc);
1485 f.Printf("<br><br>\n");
1490 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1493 f.Printf($"<H3>Example</H3><br>\n");
1494 f.Printf($"<FONT face=\"Courier New\">\n");
1495 f.Printf("<br><TABLE>\n");
1498 char fileName[MAX_LOCATION];
1499 FigureFileName(fileName, module, methodDoc, method, example, null);
1500 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1502 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1505 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1506 f.Printf("</TABLE></FONT>\n");
1512 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1515 f.Printf($"<H3>Remarks</H3><br>\n");
1518 char fileName[MAX_LOCATION];
1519 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1520 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1525 f.Printf("<br>%s\n", method, remarksDoc);
1526 f.Printf("<br><br>\n");
1531 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1534 f.Printf($"<H3>See Also</H3><br>\n");
1537 char fileName[MAX_LOCATION];
1538 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1539 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1544 f.Printf("<br>%s\n", method, seeAlsoDoc);
1546 f.Printf("<br><br>\n");
1550 f.Printf("</FONT></BODY></HTML>\n");
1554 class APIPageFunction : APIPage
1556 GlobalFunction function;
1560 return function.module;
1563 NameSpace * GetNameSpace()
1565 return function.nameSpace;
1568 void Generate(File f)
1571 Module module = function.module;
1573 char nsName[1024], temp[1024];
1574 NameSpace * ns = function.nameSpace;
1577 while(ns && ns->name)
1579 strcpy(temp, ns->name);
1580 if(nsName[0]) strcat(temp, "::");
1581 strcat(temp, nsName);
1582 strcpy(nsName, temp);
1586 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1587 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1589 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);
1592 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1594 if(!function.dataType)
1595 function.dataType = ProcessTypeString(function.dataTypeString, false);
1597 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1599 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);
1602 // Generate Method Page
1604 if(!function.dataType.name)
1605 function.dataType.name = CopyString(function.name);
1606 DocPrintType(function.dataType, string, true, false);
1607 f.Printf("<br>%s", string);
1610 char * desc = ReadDoc(module, functionDoc, function, description, null);
1613 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1616 char fileName[MAX_LOCATION];
1617 FigureFileName(fileName, module, functionDoc, function, description, null);
1618 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1623 f.Printf("%s", desc);
1627 f.Printf("<br><br>\n");
1628 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1630 f.Printf($"<H3>Parameters</H3><br><br>\n");
1632 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1633 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1635 f.Printf("<TABLE valign=center>\n");
1638 for(param = function.dataType.params.first; param; param = param.next)
1640 // ADD DESCRIPTION HERE
1641 if(param.kind != voidType)
1643 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1646 DocPrintType(param, string, false, false);
1648 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1649 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1654 char fileName[MAX_LOCATION];
1655 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1656 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1659 f.Printf("</a> </TD>\n");
1662 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1665 f.Printf("</TR>\n");
1668 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1670 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1671 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1673 f.Printf("<TR><TD> </TD></TR>");
1676 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1678 DocPrintType(function.dataType.returnType, string, false, false);
1679 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1684 char fileName[MAX_LOCATION];
1685 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1686 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1688 f.Printf("</a> </TD>\n");
1691 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1694 f.Printf("</TR>\n");
1695 f.Printf("</TABLE>\n");
1697 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1698 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1700 f.Printf("</TABLE><br>\n");
1703 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1706 f.Printf($"<H3>Usage</H3><br>\n");
1709 char fileName[MAX_LOCATION];
1710 FigureFileName(fileName, module, functionDoc, function, usage, null);
1711 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1716 f.Printf("<br>%s\n", usageDoc);
1717 f.Printf("<br><br>\n");
1722 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1725 f.Printf($"<H3>Example</H3><br>\n");
1726 f.Printf($"<FONT face=\"Courier New\">\n");
1727 f.Printf("<br><TABLE>\n");
1730 char fileName[MAX_LOCATION];
1731 FigureFileName(fileName, module, functionDoc, function, example, null);
1732 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1734 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1737 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1738 f.Printf("</TABLE></FONT>\n");
1744 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1747 f.Printf($"<H3>Remarks</H3><br>\n");
1750 char fileName[MAX_LOCATION];
1751 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1752 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1757 f.Printf("<br>%s\n", remarksDoc);
1758 f.Printf("<br><br>\n");
1763 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1766 f.Printf($"<H3>See Also</H3><br>\n");
1769 char fileName[MAX_LOCATION];
1770 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1771 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1776 f.Printf("<br>%s\n", seeAlsoDoc);
1777 f.Printf("<br><br>\n");
1781 f.Printf("</FONT></BODY></HTML>\n");
1785 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1789 NameSpace * nameSpace = mainNameSpace;
1791 DataRow classesRow = null;
1792 DataRow functionsRow = null, definesRow = null;
1795 strcpy(nsName, parentName ? parentName : "");
1799 strcat(nsName, "::");
1800 strcat(nsName, nameSpace->name);
1805 row = parentRow.AddRow();
1806 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1807 row.tag = (int64)nameSpace;
1808 row.icon = mainForm.icons[typeNameSpace];
1812 // "Global NameSpace"
1814 page = parentRow.GetData(null);
1817 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1819 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1820 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1822 if(comNameSpace != null)
1824 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1826 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1828 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1833 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1835 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1837 if(nameSpace->classes.first)
1841 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1844 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1846 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1847 AddClass(classesRow, module, cl, nsName, showPrivate);
1854 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
1856 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1858 if(nameSpace->functions.first)
1862 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
1865 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
1867 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
1869 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
1870 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
1877 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
1879 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1881 if(nameSpace->defines.first)
1885 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
1888 //if(def.module == module)
1890 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
1892 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
1893 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
1901 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
1905 if(!member.dataType)
1906 member.dataType = ProcessTypeString(member.dataTypeString, false);
1910 DocPrintType(member.dataType, string, true, false);
1912 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
1913 for(c = 0; c<indent; c++)
1914 f.Printf(" ");
1915 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
1916 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
1917 if(member.type == normalMember)
1919 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
1924 char fileName[MAX_LOCATION];
1925 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
1926 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1928 f.Printf("</a></TD>");
1931 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1936 f.Printf("<TD valign=top height=22></TD>");
1938 if(member.type != normalMember)
1940 DataMember subMember;
1941 for(subMember = member.members.first; subMember; subMember = subMember.next)
1943 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
1945 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
1949 f.Printf("</TR><br>\n");
1952 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
1955 if(member.type == normalMember)
1957 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
1958 row.tag = (int64)member;
1963 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
1964 row.icon = mainForm.icons[typeData];
1965 row.tag = (int64)member;
1967 for(m = member.members.first; m; m = m.next)
1969 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
1970 AddDataMember(row, page, m);
1975 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
1980 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
1981 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
1984 row = parentRow.AddRow();
1985 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
1986 row.tag = (int64)cl;
1987 row.collapsed = true;
1988 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
1991 if(cl.methods.first)
1993 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1995 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
1998 if(!method.dataType)
1999 ProcessMethodType(method);
2000 if(method.type == virtualMethod)
2002 if(method.dataType.thisClass)
2004 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2005 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2006 mRow.tag = (int64)method;
2010 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2011 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2012 mRow.tag = (int64)method;
2017 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2018 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2019 mRow.tag = (int64)method;
2025 if(cl.membersAndProperties.first)
2027 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2029 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2032 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2036 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2037 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2038 mRow.tag = (int64)prop;
2042 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2043 AddDataMember(membersRow, page, (DataMember)prop);
2049 if(cl.conversions.first)
2051 for(prop = cl.conversions.first; prop; prop = prop.next)
2055 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2056 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2057 if(name) name += 2; else name = prop.name;
2058 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2059 mRow.tag = (int64)prop;
2062 if(cl.type == enumClass)
2064 EnumClassData enumeration = (EnumClassData)cl.data;
2066 for(item = enumeration.values.first; item; item = item.next)
2069 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2070 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2071 mRow.tag = (int64)item;
2076 class AddressBar : Window
2078 background = activeBorder;
2082 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2084 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2086 MainForm mainForm = (MainForm)parent;
2087 FileDialog fileDialog = mainForm.fileDialog;
2088 if(fileDialog.Modal() == ok)
2089 mainForm.OpenModule(fileDialog.filePath);
2095 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2098 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2100 ((MainForm)parent).Back();
2106 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2109 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2111 ((MainForm)parent).Forward();
2117 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2119 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2121 ((MainForm)parent).Home();
2125 /* TODO: Search (#143/#441)
2126 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2127 Update this in the NotifyUpdate. Enter goes to the exact match.
2129 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2133 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2135 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2137 if(!disabled && (SmartKey)key == enter)
2138 ((MainForm)parent).Go(editBox.contents);
2142 void NotifyUpdate(EditBox editBox)
2144 String location = ((MainForm)parent).view.location;
2145 disabled = !strcmp(location ? location : "", editBox.contents);
2150 bool OnKeyHit(Key key, unichar ch)
2153 ((MainForm)parent).view.MakeActive();
2158 class MainForm : Window
2160 size = { 1000, 600 };
2162 borderStyle = sizable;
2165 icon = { ":documentorIcon.png" };
2166 text = $"API Documentation Browser";
2168 BitmapResource icons[CodeObjectType];
2173 for(c = 0; c < CodeObjectType::enumSize; c++)
2175 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2177 browser.AddField(DataField { dataType = class(APIPage) });
2182 Menu fileMenu { menu, $"File", f };
2183 Array<FileFilter> fileFilters
2185 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2186 { $"eC Symbol files (*.sym)", "sym" }
2189 FileDialog fileDialog
2191 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2193 MenuItem fileOpenItem
2195 fileMenu, $"Open...", o, ctrlO;
2197 bool NotifySelect(MenuItem selection, Modifiers mods)
2199 if(fileDialog.Modal() == ok)
2201 OpenModule(fileDialog.filePath);
2206 MenuItem fileSettingsItem
2208 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2210 bool NotifySelect(MenuItem selection, Modifiers mods)
2212 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2222 MenuDivider { fileMenu };
2223 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2225 void OpenModule(const char * filePath)
2227 char moduleName[MAX_LOCATION];
2228 char extension[MAX_EXTENSION];
2229 Module module = null;
2230 static char symbolsDir[MAX_LOCATION];
2234 FreeContext(globalContext);
2235 FreeExcludedSymbols(excludedSymbols);
2236 ::defines.Free(FreeModuleDefine);
2237 imports.Free(FreeModuleImport);
2239 FreeGlobalData(globalData);
2243 FreeTypeData(componentsApp);
2244 delete componentsApp;
2247 componentsApp = __ecere_COM_Initialize(false, 1, null);
2248 SetPrivateModule(componentsApp);
2250 StripLastDirectory(filePath, symbolsDir);
2251 SetSymbolsDir(symbolsDir);
2253 GetExtension(filePath, extension);
2255 mainForm.browser.Clear();
2257 ImportModule(filePath, normalImport, publicAccess, false);
2259 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2260 componentsApp.name = CopyString(filePath);
2262 for(module = componentsApp.allModules.first; module; module = module.next)
2264 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2268 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2269 AddComponents(componentsApp, false);
2271 GetLastDirectory(filePath, moduleName);
2272 // Extension, path and lib prefix get removed in Module::name
2275 StripExtension(moduleName);
2276 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2278 int len = strlen(moduleName) - 3;
2279 memmove(moduleName, moduleName + 3, len);
2280 moduleName[len] = 0;
2284 for(module = componentsApp.allModules.first; module; module = module.next)
2286 if(module.name && (!strcmp(module.name, moduleName)))
2289 if(!module) module = componentsApp;
2290 homeModule = module;
2291 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2293 SetSymbolsDir(null);
2296 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2299 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2300 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2303 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2305 APIPage page = row.GetData(null);
2306 if(view.edit) view.OnLeftButtonDown(0,0,0);
2307 if(page && page.page) page = page.page;
2309 view.PositionCaret(true);
2310 if(page != view.page)
2312 Window activeChild = this.activeChild;
2314 // Back / Forward Support
2315 if(row && !dontRecordHistory)
2317 if(history.count > historyPos+1)
2318 history.count = historyPos+1;
2319 historyPos = history.count-1;
2320 addressBar.back.disabled = (historyPos == 0);
2321 addressBar.forward.disabled = (historyPos >= history.count-1);
2323 history.Add((Instance)(uint64)row.tag);
2324 historyPos = history.count-1;
2326 addressBar.back.disabled = (historyPos == 0);
2327 addressBar.forward.disabled = (historyPos >= history.count-1);
2333 activeChild.Activate();
2335 else if(!view.created)
2339 page = row.GetData(null);
2340 if(page && page.page)
2344 case 1: view.GoToAnchor("Classes"); break;
2345 case 2: view.GoToAnchor("Functions"); break;
2346 case 3: view.GoToAnchor("Definitions"); break;
2347 case 4: view.GoToAnchor("VirtualMethods"); break;
2348 case 5: view.GoToAnchor("Methods"); break;
2349 case 6: view.GoToAnchor("Members"); break;
2350 case 7: view.GoToAnchor("Conversions"); break;
2351 case 8: view.GoToAnchor("EnumerationValues"); break;
2355 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2356 view.GoToAnchor(hex);
2362 view.SetScrollPosition(0, 0);
2370 this, anchor = { top = 26, bottom = 0, right = 0 };
2375 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2378 bool OnClose(bool parentClosing)
2381 view.OnLeftButtonDown(0,0,0);
2387 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2388 //mainForm.OpenModule("ec");
2389 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2390 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2392 int index = mainForm.browser.currentRow.index;
2393 int rowHeight = mainForm.browser.rowHeight;
2394 int height = mainForm.browser.clientSize.h;
2396 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2401 Array<Instance> history { };
2403 bool dontRecordHistory;
2408 if(historyPos < history.count-1)
2412 addressBar.back.disabled = (historyPos == 0);
2413 addressBar.forward.disabled = (historyPos >= history.count-1);
2414 sprintf(location, "api://%p", history[historyPos]);
2415 dontRecordHistory = true;
2416 view.OnOpen(location);
2417 dontRecordHistory = false;
2429 addressBar.back.disabled = (historyPos == 0);
2430 addressBar.forward.disabled = (historyPos >= history.count-1);
2431 sprintf(location, "api://%p", history[historyPos]);
2432 dontRecordHistory = true;
2433 view.OnOpen(location);
2434 dontRecordHistory = false;
2442 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2446 class EditDialog : Window
2448 borderStyle = sizable;
2449 size = { 600, 400 };
2454 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2458 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2462 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2466 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2467 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2469 class HelpView : HTMLView
2473 hasVertScroll = true;
2474 hasHorzScroll = true;
2476 char editString[MAX_LOCATION];
2482 page = mainForm.browser.currentRow.GetData(null);
2487 char docFile[MAX_LOCATION];
2489 Module module = page ? page.GetModule() : null;
2490 NameSpace * ns = page ? page.GetNameSpace() : null;
2492 sprintf(docFile, "%s/%s.eCdoc", settings.docDir, (!module || !module.name || (ns && ns->name && !strcmp(ns->name, "namespaces/ecere/namespaces/com"))) ? "ecereCOM" : module.name);
2493 if(FileExists(docFile))
2495 archive = ArchiveOpen(docFile, { true } );
2496 readOnly = archive == null;
2502 archive = ArchiveOpen(docFile, { true } );
2505 // Must create root directory on archive creation
2506 ArchiveDir dir = archive.OpenDirectory("", null, replace);
2518 GoToAnchor(page.label);
2520 if(page.page) page = page.page;
2523 return HTMLView::OnCreate();
2532 char archiveFile[MAX_LOCATION];
2533 char fileName[MAX_FILENAME];
2534 char directory[MAX_LOCATION];
2535 const char * location;
2536 Archive archive = null;
2537 if(SplitArchivePath(editString, archiveFile, &location))
2539 GetLastDirectory(location, fileName);
2540 StripLastDirectory(location, directory);
2541 archive = ArchiveOpen(archiveFile, { true } );
2545 ArchiveDir dir = archive ? archive.OpenDirectory(directory, null, replace) : null;
2548 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2550 if(block.type == TEXT && block.textLen)
2558 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2560 if(block.type == BR)
2562 else if(block.type == TEXT)
2563 f.Write(block.text, 1, block.textLen);
2568 dir.AddFromFile(fileName, f, null, replace, 0, null, null);
2574 Block parent = textBlock.parent;
2575 while((block = parent.subBlocks.first))
2577 parent.subBlocks.Remove(block);
2580 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
2581 textBlock.text = CopyString($"[Add Text]");
2582 textBlock.textLen = strlen(textBlock.text);
2583 parent.subBlocks.Add(textBlock);
2591 PositionCaret(true);
2597 bool OnLeftButtonDown(int x, int y, Modifiers mods)
2601 if(edit && (!textBlock || overLink != textBlock.parent))
2605 HTMLView::OnLeftButtonDown(x, y, mods);
2606 selPosition = curPosition = 0;
2607 selBlock = textBlock;
2611 result = HTMLView::OnLeftButtonDown(x, y, mods);
2613 if(!edit && clickedLink)
2616 if(clickedLink == overLink && clickedLink.href)
2618 if(OnOpen(clickedLink.href))
2626 if(textBlock && overLink == textBlock.parent)
2628 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2629 selBlock = textBlock;
2630 PositionCaret(true);
2638 bool OnLeftButtonUp(int x, int y, Modifiers mods)
2640 if(!edit || !textBlock || clickedLink != textBlock.parent)
2642 HTMLView::OnLeftButtonUp(x, y, mods);
2645 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2646 selBlock = textBlock;
2647 PositionCaret(true);
2658 bool OnMouseMove(int x, int y, Modifiers mods)
2660 if(edit && selecting)
2662 curPosition = TextPosFromPoint(x, y, &textBlock, true);
2663 PositionCaret(true);
2666 return HTMLView::OnMouseMove(x, y, mods);
2669 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
2671 if(edit && textBlock)
2677 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
2678 selBlock = textBlock;
2679 for(c = curPosition; c >= 0; c--)
2682 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
2683 ch = UTF8GetChar(textBlock.text + c, &numBytes);
2684 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2690 for(c = start; c < textBlock.textLen; c += numBytes)
2692 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
2693 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2696 selPosition = start;
2699 PositionCaret(true);
2707 bool OnOpen(char * href)
2709 if(!strncmp(href, "api://", 6))
2711 int64 tag = (int64)strtoull(href + 6, null, 16);
2712 DataRow row = mainForm.browser.FindSubRow(tag);
2716 mainForm.browser.SelectRow(row);
2717 while((row = row.parent))
2718 row.collapsed = false;
2719 row = mainForm.browser.currentRow;
2720 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
2723 else if(!strncmp(href, "edit://", 7))
2726 int startX = clickedLink.startX, startY = clickedLink.startY;
2727 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
2729 if(block.type == TEXT) startX = block.startX, startY = block.startY;
2730 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
2732 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
2734 display.FontExtent(block.font.font, " ", 1, null, &th);
2737 block.parent.subBlocks.Insert(null, newBlock);
2742 block.parent.subBlocks.Insert(block, newBlock);
2743 startY += block.prev.height;
2745 newBlock.startX = startX;
2746 newBlock.startY = startY;
2747 newBlock.text = new0 char[1];
2751 textBlock = (Block)clickedLink.subBlocks.first;
2752 if(!strcmp(textBlock.text, $"[Add Text]"))
2754 textBlock.text[0] = 0;
2755 textBlock.textLen = 0;
2758 strcpy(editString, href + 7);
2759 selPosition = curPosition = 0;
2760 selBlock = textBlock;
2763 // PositionCaret(true);
2770 void DeleteSelection()
2772 if(textBlock != selBlock || curPosition != selPosition)
2774 if(textBlock == selBlock)
2776 // Within same block
2777 int start = Min(curPosition, selPosition);
2778 int end = Max(curPosition, selPosition);
2779 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
2780 textBlock.textLen -= end-start;
2781 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
2782 curPosition = start;
2783 selPosition = start;
2787 int startSel, endSel;
2788 Block startSelBlock = null, endSelBlock = null, b, next;
2790 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2792 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
2793 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
2795 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
2796 for(b = startSelBlock.next; b; b = next)
2798 bool isEnd = b == endSelBlock;
2799 next = GetNextBlock(b);
2800 b.parent.subBlocks.Remove(b);
2805 textBlock = startSelBlock;
2806 selBlock = startSelBlock;
2807 curPosition = startSel;
2808 selPosition = startSel;
2812 PositionCaret(true);
2817 String GetSelectionString()
2819 String selection = null;
2820 if(textBlock == selBlock)
2822 // Within same block
2823 int start = Min(curPosition, selPosition);
2824 int end = Max(curPosition, selPosition);
2825 int len = end - start;
2826 selection = new char[len + 1];
2827 memcpy(selection, textBlock.text + start, len);
2832 int startSel, endSel;
2833 Block startSelBlock = null, endSelBlock = null, b;
2836 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2839 for(b = startSelBlock; b; b = GetNextBlock(b))
2841 int start = (b == startSelBlock) ? startSel : 0;
2842 int end = (b == endSelBlock) ? endSel : b.textLen;
2843 int len = end - start;
2845 if(b == endSelBlock)
2847 else if(b.type == TEXT)
2851 selection = new char[totalLen + 1];
2853 for(b = startSelBlock; b; b = GetNextBlock(b))
2855 int start = (b == startSelBlock) ? startSel : 0;
2856 int end = (b == endSelBlock) ? endSel : b.textLen;
2857 int len = end - start;
2858 memcpy(selection + totalLen, b.text + start, len);
2860 if(b == endSelBlock)
2862 else if(b.type == TEXT)
2863 selection[totalLen++] = '\n';
2865 selection[totalLen] = 0;
2870 void CopySelection()
2872 String s = GetSelectionString();
2875 int len = strlen(s);
2877 if(cb.Allocate(len + 1))
2879 memcpy(cb.text, s, len + 1);
2887 bool OnKeyDown(Key key, unichar ch)
2894 OnLeftButtonDown(0,0,0);
2896 case Key { end, shift = true }:
2898 curPosition = textBlock.textLen;
2901 selPosition = curPosition;
2902 selBlock = textBlock;
2904 PositionCaret(true);
2907 case Key { home, shift = true }:
2912 selPosition = curPosition;
2913 selBlock = textBlock;
2915 PositionCaret(true);
2918 case Key { home, ctrl = true, shift = true }:
2921 while(textBlock.prev)
2922 textBlock = textBlock.prev.prev;
2925 selPosition = curPosition;
2926 selBlock = textBlock;
2928 PositionCaret(true);
2931 case Key { end, ctrl = true, shift = true }:
2933 while(textBlock.next && textBlock.next.next)
2934 textBlock = textBlock.next.next;
2935 curPosition = textBlock.textLen;
2938 selPosition = curPosition;
2939 selBlock = textBlock;
2941 PositionCaret(true);
2947 return HTMLView::OnKeyDown(key, ch);
2951 bool OnKeyHit(Key key, unichar ch)
2957 case Key { up, shift = true }:
2960 if(caretY == textBlock.startY)
2964 textBlock = textBlock.prev.prev;
2965 curPosition = Min(curPosition, textBlock.textLen);
2968 selPosition = curPosition;
2969 selBlock = textBlock;
2972 PositionCaret(false);
2982 int sx = textBlock.startX, sy = textBlock.startY;
2983 char * text = textBlock.text;
2985 Block block = textBlock;
2986 while(block && block.type != TD) block = block.parent;
2989 Block table = block;
2990 while(table && table.type != TABLE) table = table.parent;
2992 maxW = block.w - 2* table.cellPadding;
2994 maxW = clientSize.w - 10 - sx;
2997 maxW = clientSize.w - 10 - sx;
2998 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3002 int startPos = textPos;
3005 bool lineComplete = false;
3006 for(; textPos<textBlock.textLen && !lineComplete;)
3010 char * nextSpace = strchr(text + textPos, ' ');
3013 len = (nextSpace - (text + textPos)) + 1;
3015 len = textBlock.textLen - textPos;
3017 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3019 if(x + width + w > maxW && x > 0)
3021 lineComplete = true;
3031 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3034 curPosition = textPos;
3035 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3038 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3039 len = curPosition - startPos;
3040 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3044 selPosition = curPosition;
3045 selBlock = textBlock;
3049 PositionCaret(false);
3053 if(sy == caretY - th || textPos == textBlock.textLen)
3055 if(textPos != textBlock.textLen)
3057 int c = textPos - 1;
3058 while(c > 0 && text[c] == ' ') c--;
3059 curPosition = c + 1;
3062 selPosition = curPosition;
3063 selBlock = textBlock;
3069 curPosition = textBlock.textLen;
3072 selPosition = curPosition;
3073 selBlock = textBlock;
3077 PositionCaret(false);
3081 sx = textBlock.startX;
3082 } while(textPos < textBlock.textLen);
3087 case Key { down, shift = true }:
3092 int sx = textBlock.startX, sy = textBlock.startY;
3093 char * text = textBlock.text;
3095 Block block = textBlock;
3096 while(block && block.type != TD) block = block.parent;
3099 Block table = block;
3100 while(table && table.type != TABLE) table = table.parent;
3102 maxW = block.w - 2* table.cellPadding;
3104 maxW = clientSize.w - 10 - sx;
3107 maxW = clientSize.w - 10 - sx;
3108 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3110 while(!textPos || textPos < textBlock.textLen)
3112 int startPos = textPos;
3115 bool lineComplete = false;
3116 for(; (textPos < textBlock.textLen) && !lineComplete;)
3120 char * nextSpace = strchr(text + textPos, ' ');
3123 len = (nextSpace - (text + textPos)) + 1;
3125 len = textBlock.textLen - textPos;
3127 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3129 if(x + width + w > maxW && x > 0)
3131 lineComplete = true;
3141 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3143 curPosition = textPos;
3145 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3148 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3149 len = curPosition - startPos;
3150 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3154 selPosition = curPosition;
3155 selBlock = textBlock;
3158 PositionCaret(false);
3164 curPosition = textBlock.textLen;
3167 selPosition = curPosition;
3168 selBlock = textBlock;
3171 PositionCaret(false);
3174 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3178 textBlock = textBlock.next.next;
3179 sy = textBlock.startY;
3180 sx = textBlock.startX;
3181 text = textBlock.text;
3186 sx = textBlock.startX;
3190 /*if(textBlock.next && textBlock.next.next)
3192 textBlock = textBlock.next.next;
3193 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3194 selBlock = textBlock;
3195 PositionCaret(false);
3199 case Key { right, shift = true, ctrl = true }:
3202 bool foundAlpha = false;
3204 Block line, lastLine;
3207 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3209 int start = (line == textBlock) ? curPosition : 0;
3211 for(c = start; c < line.textLen; c++)
3213 char ch = line.text[c];
3214 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3215 if(key.shift ? isAlUnder : !isAlUnder)
3229 selPosition = curPosition;
3230 selBlock = textBlock;
3234 PositionCaret(true);
3239 // No next word found,
3240 if(!found && (c != curPosition || line != textBlock))
3244 lastC = line.textLen-1;
3249 curPosition = line.textLen;
3252 selPosition = curPosition;
3253 selBlock = textBlock;
3258 PositionCaret(true);
3264 if(key.shift && found)
3266 curPosition = lastC+1;
3267 textBlock = lastLine;
3268 PositionCaret(true);
3273 case Key { left, ctrl = true, shift = true }:
3276 bool foundAlpha = false;
3278 Block line, lastLine;
3281 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3284 if(curPosition == 0 && line != textBlock)
3287 lastC = line.textLen;
3291 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3292 for(c = start; c>=0; c--)
3294 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3309 // No next word found,
3310 if(!found && curPosition > 0)
3320 textBlock = lastLine;
3321 curPosition = lastC;
3324 selPosition = curPosition;
3325 selBlock = textBlock;
3327 PositionCaret(true);
3332 case Key { right, shift = true }:
3334 if(curPosition < textBlock.textLen)
3336 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3339 selPosition = curPosition;
3340 selBlock = textBlock;
3342 PositionCaret(true);
3345 else if(textBlock.next && textBlock.next.next)
3347 textBlock = textBlock.next.next;
3351 selPosition = curPosition;
3352 selBlock = textBlock;
3354 PositionCaret(true);
3358 case Key { left, shift = true }:
3362 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3365 selPosition = curPosition;
3366 selBlock = textBlock;
3368 PositionCaret(true);
3371 else if(textBlock.prev)
3373 textBlock = textBlock.prev.prev;
3374 curPosition = textBlock.textLen;
3377 selPosition = curPosition;
3378 selBlock = textBlock;
3380 PositionCaret(true);
3386 if(textBlock == selBlock && curPosition == selPosition)
3390 int c = curPosition;
3392 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3393 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3394 textBlock.textLen -= nb;
3395 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3397 selPosition = curPosition;
3398 selBlock = textBlock;
3402 PositionCaret(true);
3405 else if(textBlock.prev)
3407 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3408 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3409 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3411 selPosition = curPosition = prevBlock.textLen;
3412 selBlock = textBlock;
3413 prevBlock.textLen += textBlock.textLen;
3414 textBlock.parent.subBlocks.Remove(prev);
3415 if(prev == selBlock)
3417 selBlock = textBlock;
3418 selPosition = curPosition;
3421 textBlock.parent.subBlocks.Remove(textBlock);
3422 if(textBlock == selBlock)
3424 selBlock = prevBlock;
3425 selPosition = curPosition;
3428 textBlock = prevBlock;
3432 PositionCaret(true);
3441 if(textBlock != selBlock || curPosition != selPosition)
3443 else if(textBlock.textLen > curPosition)
3445 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3446 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3447 textBlock.textLen -= nb;
3448 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3453 PositionCaret(true);
3456 else if(textBlock.next && textBlock.next.next)
3458 Block next = textBlock.next, nextBlock = textBlock.next.next;
3459 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3460 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3462 textBlock.textLen += nextBlock.textLen;
3463 textBlock.parent.subBlocks.Remove(next);
3464 if(next == selBlock)
3466 selBlock = textBlock;
3467 selPosition = curPosition;
3470 textBlock.parent.subBlocks.Remove(nextBlock);
3471 if(nextBlock == selBlock)
3473 selBlock = textBlock;
3474 selPosition = curPosition;
3480 PositionCaret(true);
3494 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3495 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3496 startY = textBlock.startY;
3497 startX = textBlock.startX;
3499 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3500 textBlock.parent.subBlocks.Insert(textBlock, block);
3501 textBlock.parent.subBlocks.Insert(block, newBlock);
3505 newBlock.textLen = textBlock.textLen - curPosition;
3506 newBlock.text = new char[newBlock.textLen+1];
3507 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3508 textBlock.textLen = curPosition;
3509 textBlock.text[curPosition] = 0;
3511 newBlock.startY = startY;
3512 newBlock.startX = startX;
3513 selPosition = curPosition = 0;
3518 textBlock = newBlock;
3519 selBlock = textBlock;
3520 PositionCaret(true);
3525 case Key { del, shift = true }:
3540 ClipBoard clipBoard { };
3541 if(clipBoard.Load())
3544 char * text = clipBoard.memory;
3552 parent = textBlock.parent;
3553 font = textBlock.font;
3558 if(ch == '\n' || ch == '\r' || !ch)
3560 int len = c - start;
3561 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
3562 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3563 memcpy(textBlock.text + curPosition, text + start, len);
3564 textBlock.textLen += len;
3566 selPosition = curPosition;
3567 selBlock = textBlock;
3570 Block block { type = BR, parent = parent, font = font };
3571 Block newBlock { type = TEXT, parent = parent, font = font };
3572 int startY = textBlock.startY, startX = textBlock.startX;
3575 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3576 textBlock.parent.subBlocks.Insert(textBlock, block);
3577 textBlock.parent.subBlocks.Insert(block, newBlock);
3581 newBlock.textLen = textBlock.textLen - curPosition;
3582 newBlock.text = new char[newBlock.textLen+1];
3583 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3584 textBlock.textLen = curPosition;
3585 textBlock.text[curPosition] = 0;
3587 newBlock.startY = startY;
3588 newBlock.startX = startX;
3589 selPosition = curPosition = 0;
3590 selBlock = textBlock;
3591 textBlock = newBlock;
3593 if(ch == '\r' && text[c+1] == '\n') c++;
3599 PositionCaret(true);
3607 // eC BUG HERE: (Should be fixed)
3608 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
3611 int len = UTF32toUTF8Len(&ch, 1, string, 5);
3616 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
3617 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3619 for(c = 0; c<len; c++)
3621 textBlock.text[curPosition] = string[c];
3622 textBlock.textLen++;
3625 selPosition = curPosition;
3626 selBlock = textBlock;
3629 //Clear(html.block);
3630 //CreateForms(html.block);
3635 PositionCaret(true);
3644 void OnResize(int width, int height)
3646 HTMLView::OnResize(width, height);
3647 PositionCaret(true);
3651 void PositionCaret(bool setCaretX)
3657 int sx = textBlock.startX, sy = textBlock.startY;
3658 char * text = textBlock.text;
3660 Block block = textBlock;
3661 while(block && block.type != TD) block = block.parent;
3664 Block table = block;
3665 while(table && table.type != TABLE) table = table.parent;
3667 maxW = block.w - 2* table.cellPadding;
3669 maxW = clientSize.w - 10 - sx;
3672 maxW = clientSize.w - 10 - sx;
3674 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3676 while(textPos < textBlock.textLen)
3678 int startPos = textPos;
3681 bool lineComplete = false;
3683 for(; textPos<textBlock.textLen && !lineComplete;)
3687 char * nextSpace = strchr(text + textPos, ' ');
3690 len = (nextSpace - (text + textPos)) + 1;
3692 len = textBlock.textLen - textPos;
3694 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3696 if(x + width + w > maxW && x > 0)
3698 lineComplete = true;
3711 if(curPosition < textPos || textPos == textBlock.textLen)
3713 int len = curPosition - startPos;
3714 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
3719 sx = textBlock.startX;
3724 SetCaret(sx, sy, th);
3726 Point scrollPos = scroll;
3727 bool doScroll = false;
3728 if(sy - scroll.y + th > clientSize.h)
3730 scrollPos.y = sy + th - clientSize.h;
3733 else if(sy - scroll.y < 0)
3738 if(sx - scroll.x + 10 > clientSize.w)
3740 scrollPos.x = sx + 10 - clientSize.w;
3743 else if(sx - scroll.x < 10)
3745 scrollPos.x = sx - 10;
3756 // Returns a character offset into the TextBlock from a window coordinate
3757 int TextPosFromPoint(int px, int py, Block * block, bool half)
3759 Block parentBlock = this.textBlock.parent;
3762 *block = this.textBlock;
3767 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
3769 int sx = textBlock.startX, sy = textBlock.startY;
3772 char * text = textBlock.text;
3774 Block b = textBlock;
3777 if(textBlock.type != TEXT) continue;
3779 while(b && b.type != TD) b = b.parent;
3783 while(table && table.type != TABLE) table = table.parent;
3785 maxW = b.w - 2* table.cellPadding;
3787 maxW = clientSize.w - 10 - sx;
3790 maxW = clientSize.w - 10 - sx;
3792 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
3793 //space = space/2+2;
3796 while(textPos < textBlock.textLen)
3800 bool lineComplete = false;
3802 for(; textPos<textBlock.textLen && !lineComplete;)
3806 char * nextSpace = strchr(text + textPos, ' ');
3809 len = (nextSpace - (text + textPos)) + 1;
3811 len = textBlock.textLen - textPos;
3813 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3815 sx = x + textBlock.startX;
3816 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
3821 for(c = textPos; (ch = text[c]); c += numBytes)
3823 numBytes = UTF8_NUM_BYTES(ch);
3824 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
3825 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
3832 if(x + width + w > maxW && x > 0)
3834 lineComplete = true;
3847 if(/*py >= sy && */py < sy + th)
3850 return textBlock.textLen;
3855 result = textBlock.textLen;
3861 Application componentsApp;
3863 class Documentor : GuiApplication
3867 Platform os = __runtimePlatform;
3868 SetGlobalContext(globalContext);
3869 SetExcludedSymbols(&excludedSymbols);
3870 SetDefines(&::defines);
3871 SetImports(&imports);
3872 SetInDocumentor(true);
3874 SetGlobalData(globalData);
3876 settingsContainer.dataOwner = &settings;
3877 settingsContainer.Load();
3878 if(!settings.docDir || !settings.docDir[0] )
3880 if(os == win32) // if Windows OS then
3882 char programFilesDir[MAX_LOCATION];
3883 char appData[MAX_LOCATION];
3884 char homeDrive[MAX_LOCATION];
3885 char winDir[MAX_LOCATION];
3886 GetEnvironment("APPDATA", appData, sizeof(appData));
3887 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
3888 GetEnvironment("windir", winDir, sizeof(winDir));
3889 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
3891 PathCat(programFilesDir, "ECERE SDK\\doc");
3892 settings.docDir = programFilesDir;
3894 else if(homeDrive[0])
3896 PathCat(homeDrive, "ECERE SDK\\doc");
3897 settings.docDir = homeDrive;
3901 PathCat(winDir, "..\\ECERE SDK\\doc");
3902 settings.docDir = winDir;
3905 settings.docDir = "C:\\ECERE SDK\\doc";
3907 else // if Os is Linux, or Mac OSX or something else
3908 settings.docDir = "/usr/share/ecere/doc/";
3909 settingsContainer.Save();
3915 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
3917 AddComponents(module, true);
3918 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
3919 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
3920 while((row = row.parent))
3921 row.collapsed = false;
3925 commandThread.Create();
3929 bool Cycle(bool idle)
3932 mainForm.Destroy(0);
3941 if(commandThread.created)
3943 console.CloseInput();
3944 console.CloseOutput();
3946 commandThread.Wait();
3950 FreeContext(globalContext);
3951 FreeExcludedSymbols(excludedSymbols);
3952 ::defines.Free(FreeModuleDefine);
3953 imports.Free(FreeModuleImport);
3955 FreeGlobalData(globalData);
3956 FreeTypeData(componentsApp);
3958 delete componentsApp;
3962 ConsoleFile console { };
3963 MainForm mainForm { };
3966 Thread commandThread
3973 console.GetLine(command, sizeof(command));
3974 if(!quit && command[0])
3977 if(!strcmpi(command, "Activate"))
3978 mainForm.Activate();
3979 else if(!strcmpi(command, "Quit"))