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 } );
2547 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2549 if(block.type == TEXT && block.textLen)
2557 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2559 if(block.type == BR)
2561 else if(block.type == TEXT)
2562 f.Write(block.text, 1, block.textLen);
2567 if(!empty || archive.FileExists(location))
2569 ArchiveDir dir = archive ? archive.OpenDirectory(directory, null, replace) : null;
2571 dir.AddFromFile(fileName, f, null, replace, 0, null, null);
2578 Block parent = textBlock.parent;
2579 while((block = parent.subBlocks.first))
2581 parent.subBlocks.Remove(block);
2584 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
2585 textBlock.text = CopyString($"[Add Text]");
2586 textBlock.textLen = strlen(textBlock.text);
2587 parent.subBlocks.Add(textBlock);
2595 PositionCaret(true);
2601 bool OnLeftButtonDown(int x, int y, Modifiers mods)
2605 if(edit && (!textBlock || overLink != textBlock.parent))
2609 HTMLView::OnLeftButtonDown(x, y, mods);
2610 selPosition = curPosition = 0;
2611 selBlock = textBlock;
2615 result = HTMLView::OnLeftButtonDown(x, y, mods);
2617 if(!edit && clickedLink)
2620 if(clickedLink == overLink && clickedLink.href)
2622 if(OnOpen(clickedLink.href))
2630 if(textBlock && overLink == textBlock.parent)
2632 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2633 selBlock = textBlock;
2634 PositionCaret(true);
2642 bool OnLeftButtonUp(int x, int y, Modifiers mods)
2644 if(!edit || !textBlock || clickedLink != textBlock.parent)
2646 HTMLView::OnLeftButtonUp(x, y, mods);
2649 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2650 selBlock = textBlock;
2651 PositionCaret(true);
2662 bool OnMouseMove(int x, int y, Modifiers mods)
2664 if(edit && selecting)
2666 curPosition = TextPosFromPoint(x, y, &textBlock, true);
2667 PositionCaret(true);
2670 return HTMLView::OnMouseMove(x, y, mods);
2673 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
2675 if(edit && textBlock)
2681 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
2682 selBlock = textBlock;
2683 for(c = curPosition; c >= 0; c--)
2686 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
2687 ch = UTF8GetChar(textBlock.text + c, &numBytes);
2688 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2694 for(c = start; c < textBlock.textLen; c += numBytes)
2696 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
2697 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2700 selPosition = start;
2703 PositionCaret(true);
2711 bool OnOpen(char * href)
2713 if(!strncmp(href, "api://", 6))
2715 int64 tag = (int64)strtoull(href + 6, null, 16);
2716 DataRow row = mainForm.browser.FindSubRow(tag);
2720 mainForm.browser.SelectRow(row);
2721 while((row = row.parent))
2722 row.collapsed = false;
2723 row = mainForm.browser.currentRow;
2724 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
2727 else if(!strncmp(href, "edit://", 7))
2730 int startX = clickedLink.startX, startY = clickedLink.startY;
2731 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
2733 if(block.type == TEXT) startX = block.startX, startY = block.startY;
2734 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
2736 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
2738 display.FontExtent(block.font.font, " ", 1, null, &th);
2741 block.parent.subBlocks.Insert(null, newBlock);
2746 block.parent.subBlocks.Insert(block, newBlock);
2747 startY += block.prev.height;
2749 newBlock.startX = startX;
2750 newBlock.startY = startY;
2751 newBlock.text = new0 char[1];
2755 textBlock = (Block)clickedLink.subBlocks.first;
2756 if(!strcmp(textBlock.text, $"[Add Text]"))
2758 textBlock.text[0] = 0;
2759 textBlock.textLen = 0;
2762 strcpy(editString, href + 7);
2763 selPosition = curPosition = 0;
2764 selBlock = textBlock;
2767 // PositionCaret(true);
2774 void DeleteSelection()
2776 if(textBlock != selBlock || curPosition != selPosition)
2778 if(textBlock == selBlock)
2780 // Within same block
2781 int start = Min(curPosition, selPosition);
2782 int end = Max(curPosition, selPosition);
2783 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
2784 textBlock.textLen -= end-start;
2785 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
2786 curPosition = start;
2787 selPosition = start;
2791 int startSel, endSel;
2792 Block startSelBlock = null, endSelBlock = null, b, next;
2794 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2796 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
2797 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
2799 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
2800 for(b = startSelBlock.next; b; b = next)
2802 bool isEnd = b == endSelBlock;
2803 next = GetNextBlock(b);
2804 b.parent.subBlocks.Remove(b);
2809 textBlock = startSelBlock;
2810 selBlock = startSelBlock;
2811 curPosition = startSel;
2812 selPosition = startSel;
2816 PositionCaret(true);
2821 String GetSelectionString()
2823 String selection = null;
2824 if(textBlock == selBlock)
2826 // Within same block
2827 int start = Min(curPosition, selPosition);
2828 int end = Max(curPosition, selPosition);
2829 int len = end - start;
2830 selection = new char[len + 1];
2831 memcpy(selection, textBlock.text + start, len);
2836 int startSel, endSel;
2837 Block startSelBlock = null, endSelBlock = null, b;
2840 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2843 for(b = startSelBlock; b; b = GetNextBlock(b))
2845 int start = (b == startSelBlock) ? startSel : 0;
2846 int end = (b == endSelBlock) ? endSel : b.textLen;
2847 int len = end - start;
2849 if(b == endSelBlock)
2851 else if(b.type == TEXT)
2855 selection = new char[totalLen + 1];
2857 for(b = startSelBlock; b; b = GetNextBlock(b))
2859 int start = (b == startSelBlock) ? startSel : 0;
2860 int end = (b == endSelBlock) ? endSel : b.textLen;
2861 int len = end - start;
2862 memcpy(selection + totalLen, b.text + start, len);
2864 if(b == endSelBlock)
2866 else if(b.type == TEXT)
2867 selection[totalLen++] = '\n';
2869 selection[totalLen] = 0;
2874 void CopySelection()
2876 String s = GetSelectionString();
2879 int len = strlen(s);
2881 if(cb.Allocate(len + 1))
2883 memcpy(cb.text, s, len + 1);
2891 bool OnKeyDown(Key key, unichar ch)
2898 OnLeftButtonDown(0,0,0);
2900 case Key { end, shift = true }:
2902 curPosition = textBlock.textLen;
2905 selPosition = curPosition;
2906 selBlock = textBlock;
2908 PositionCaret(true);
2911 case Key { home, shift = true }:
2916 selPosition = curPosition;
2917 selBlock = textBlock;
2919 PositionCaret(true);
2922 case Key { home, ctrl = true, shift = true }:
2925 while(textBlock.prev)
2926 textBlock = textBlock.prev.prev;
2929 selPosition = curPosition;
2930 selBlock = textBlock;
2932 PositionCaret(true);
2935 case Key { end, ctrl = true, shift = true }:
2937 while(textBlock.next && textBlock.next.next)
2938 textBlock = textBlock.next.next;
2939 curPosition = textBlock.textLen;
2942 selPosition = curPosition;
2943 selBlock = textBlock;
2945 PositionCaret(true);
2951 return HTMLView::OnKeyDown(key, ch);
2955 bool OnKeyHit(Key key, unichar ch)
2961 case Key { up, shift = true }:
2964 if(caretY == textBlock.startY)
2968 textBlock = textBlock.prev.prev;
2969 curPosition = Min(curPosition, textBlock.textLen);
2972 selPosition = curPosition;
2973 selBlock = textBlock;
2976 PositionCaret(false);
2986 int sx = textBlock.startX, sy = textBlock.startY;
2987 char * text = textBlock.text;
2989 Block block = textBlock;
2990 while(block && block.type != TD) block = block.parent;
2993 Block table = block;
2994 while(table && table.type != TABLE) table = table.parent;
2996 maxW = block.w - 2* table.cellPadding;
2998 maxW = clientSize.w - 10 - sx;
3001 maxW = clientSize.w - 10 - sx;
3002 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3006 int startPos = textPos;
3009 bool lineComplete = false;
3010 for(; textPos<textBlock.textLen && !lineComplete;)
3014 char * nextSpace = strchr(text + textPos, ' ');
3017 len = (nextSpace - (text + textPos)) + 1;
3019 len = textBlock.textLen - textPos;
3021 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3023 if(x + width + w > maxW && x > 0)
3025 lineComplete = true;
3035 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3038 curPosition = textPos;
3039 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3042 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3043 len = curPosition - startPos;
3044 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3048 selPosition = curPosition;
3049 selBlock = textBlock;
3053 PositionCaret(false);
3057 if(sy == caretY - th || textPos == textBlock.textLen)
3059 if(textPos != textBlock.textLen)
3061 int c = textPos - 1;
3062 while(c > 0 && text[c] == ' ') c--;
3063 curPosition = c + 1;
3066 selPosition = curPosition;
3067 selBlock = textBlock;
3073 curPosition = textBlock.textLen;
3076 selPosition = curPosition;
3077 selBlock = textBlock;
3081 PositionCaret(false);
3085 sx = textBlock.startX;
3086 } while(textPos < textBlock.textLen);
3091 case Key { down, shift = true }:
3096 int sx = textBlock.startX, sy = textBlock.startY;
3097 char * text = textBlock.text;
3099 Block block = textBlock;
3100 while(block && block.type != TD) block = block.parent;
3103 Block table = block;
3104 while(table && table.type != TABLE) table = table.parent;
3106 maxW = block.w - 2* table.cellPadding;
3108 maxW = clientSize.w - 10 - sx;
3111 maxW = clientSize.w - 10 - sx;
3112 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3114 while(!textPos || textPos < textBlock.textLen)
3116 int startPos = textPos;
3119 bool lineComplete = false;
3120 for(; (textPos < textBlock.textLen) && !lineComplete;)
3124 char * nextSpace = strchr(text + textPos, ' ');
3127 len = (nextSpace - (text + textPos)) + 1;
3129 len = textBlock.textLen - textPos;
3131 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3133 if(x + width + w > maxW && x > 0)
3135 lineComplete = true;
3145 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3147 curPosition = textPos;
3149 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3152 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3153 len = curPosition - startPos;
3154 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3158 selPosition = curPosition;
3159 selBlock = textBlock;
3162 PositionCaret(false);
3168 curPosition = textBlock.textLen;
3171 selPosition = curPosition;
3172 selBlock = textBlock;
3175 PositionCaret(false);
3178 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3182 textBlock = textBlock.next.next;
3183 sy = textBlock.startY;
3184 sx = textBlock.startX;
3185 text = textBlock.text;
3190 sx = textBlock.startX;
3194 /*if(textBlock.next && textBlock.next.next)
3196 textBlock = textBlock.next.next;
3197 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3198 selBlock = textBlock;
3199 PositionCaret(false);
3203 case Key { right, shift = true, ctrl = true }:
3206 bool foundAlpha = false;
3208 Block line, lastLine;
3211 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3213 int start = (line == textBlock) ? curPosition : 0;
3215 for(c = start; c < line.textLen; c++)
3217 char ch = line.text[c];
3218 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3219 if(key.shift ? isAlUnder : !isAlUnder)
3233 selPosition = curPosition;
3234 selBlock = textBlock;
3238 PositionCaret(true);
3243 // No next word found,
3244 if(!found && (c != curPosition || line != textBlock))
3248 lastC = line.textLen-1;
3253 curPosition = line.textLen;
3256 selPosition = curPosition;
3257 selBlock = textBlock;
3262 PositionCaret(true);
3268 if(key.shift && found)
3270 curPosition = lastC+1;
3271 textBlock = lastLine;
3272 PositionCaret(true);
3277 case Key { left, ctrl = true, shift = true }:
3280 bool foundAlpha = false;
3282 Block line, lastLine;
3285 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3288 if(curPosition == 0 && line != textBlock)
3291 lastC = line.textLen;
3295 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3296 for(c = start; c>=0; c--)
3298 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3313 // No next word found,
3314 if(!found && curPosition > 0)
3324 textBlock = lastLine;
3325 curPosition = lastC;
3328 selPosition = curPosition;
3329 selBlock = textBlock;
3331 PositionCaret(true);
3336 case Key { right, shift = true }:
3338 if(curPosition < textBlock.textLen)
3340 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3343 selPosition = curPosition;
3344 selBlock = textBlock;
3346 PositionCaret(true);
3349 else if(textBlock.next && textBlock.next.next)
3351 textBlock = textBlock.next.next;
3355 selPosition = curPosition;
3356 selBlock = textBlock;
3358 PositionCaret(true);
3362 case Key { left, shift = true }:
3366 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3369 selPosition = curPosition;
3370 selBlock = textBlock;
3372 PositionCaret(true);
3375 else if(textBlock.prev)
3377 textBlock = textBlock.prev.prev;
3378 curPosition = textBlock.textLen;
3381 selPosition = curPosition;
3382 selBlock = textBlock;
3384 PositionCaret(true);
3390 if(textBlock == selBlock && curPosition == selPosition)
3394 int c = curPosition;
3396 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3397 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3398 textBlock.textLen -= nb;
3399 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3401 selPosition = curPosition;
3402 selBlock = textBlock;
3406 PositionCaret(true);
3409 else if(textBlock.prev)
3411 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3412 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3413 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3415 selPosition = curPosition = prevBlock.textLen;
3416 selBlock = textBlock;
3417 prevBlock.textLen += textBlock.textLen;
3418 textBlock.parent.subBlocks.Remove(prev);
3419 if(prev == selBlock)
3421 selBlock = textBlock;
3422 selPosition = curPosition;
3425 textBlock.parent.subBlocks.Remove(textBlock);
3426 if(textBlock == selBlock)
3428 selBlock = prevBlock;
3429 selPosition = curPosition;
3432 textBlock = prevBlock;
3436 PositionCaret(true);
3445 if(textBlock != selBlock || curPosition != selPosition)
3447 else if(textBlock.textLen > curPosition)
3449 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3450 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3451 textBlock.textLen -= nb;
3452 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3457 PositionCaret(true);
3460 else if(textBlock.next && textBlock.next.next)
3462 Block next = textBlock.next, nextBlock = textBlock.next.next;
3463 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3464 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3466 textBlock.textLen += nextBlock.textLen;
3467 textBlock.parent.subBlocks.Remove(next);
3468 if(next == selBlock)
3470 selBlock = textBlock;
3471 selPosition = curPosition;
3474 textBlock.parent.subBlocks.Remove(nextBlock);
3475 if(nextBlock == selBlock)
3477 selBlock = textBlock;
3478 selPosition = curPosition;
3484 PositionCaret(true);
3498 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3499 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3500 startY = textBlock.startY;
3501 startX = textBlock.startX;
3503 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3504 textBlock.parent.subBlocks.Insert(textBlock, block);
3505 textBlock.parent.subBlocks.Insert(block, newBlock);
3509 newBlock.textLen = textBlock.textLen - curPosition;
3510 newBlock.text = new char[newBlock.textLen+1];
3511 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3512 textBlock.textLen = curPosition;
3513 textBlock.text[curPosition] = 0;
3515 newBlock.startY = startY;
3516 newBlock.startX = startX;
3517 selPosition = curPosition = 0;
3522 textBlock = newBlock;
3523 selBlock = textBlock;
3524 PositionCaret(true);
3529 case Key { del, shift = true }:
3544 ClipBoard clipBoard { };
3545 if(clipBoard.Load())
3548 char * text = clipBoard.memory;
3556 parent = textBlock.parent;
3557 font = textBlock.font;
3562 if(ch == '\n' || ch == '\r' || !ch)
3564 int len = c - start;
3565 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
3566 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3567 memcpy(textBlock.text + curPosition, text + start, len);
3568 textBlock.textLen += len;
3570 selPosition = curPosition;
3571 selBlock = textBlock;
3574 Block block { type = BR, parent = parent, font = font };
3575 Block newBlock { type = TEXT, parent = parent, font = font };
3576 int startY = textBlock.startY, startX = textBlock.startX;
3579 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3580 textBlock.parent.subBlocks.Insert(textBlock, block);
3581 textBlock.parent.subBlocks.Insert(block, newBlock);
3585 newBlock.textLen = textBlock.textLen - curPosition;
3586 newBlock.text = new char[newBlock.textLen+1];
3587 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3588 textBlock.textLen = curPosition;
3589 textBlock.text[curPosition] = 0;
3591 newBlock.startY = startY;
3592 newBlock.startX = startX;
3593 selPosition = curPosition = 0;
3594 selBlock = textBlock;
3595 textBlock = newBlock;
3597 if(ch == '\r' && text[c+1] == '\n') c++;
3603 PositionCaret(true);
3611 // eC BUG HERE: (Should be fixed)
3612 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
3615 int len = UTF32toUTF8Len(&ch, 1, string, 5);
3620 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
3621 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3623 for(c = 0; c<len; c++)
3625 textBlock.text[curPosition] = string[c];
3626 textBlock.textLen++;
3629 selPosition = curPosition;
3630 selBlock = textBlock;
3633 //Clear(html.block);
3634 //CreateForms(html.block);
3639 PositionCaret(true);
3648 void OnResize(int width, int height)
3650 HTMLView::OnResize(width, height);
3651 PositionCaret(true);
3655 void PositionCaret(bool setCaretX)
3661 int sx = textBlock.startX, sy = textBlock.startY;
3662 char * text = textBlock.text;
3664 Block block = textBlock;
3665 while(block && block.type != TD) block = block.parent;
3668 Block table = block;
3669 while(table && table.type != TABLE) table = table.parent;
3671 maxW = block.w - 2* table.cellPadding;
3673 maxW = clientSize.w - 10 - sx;
3676 maxW = clientSize.w - 10 - sx;
3678 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3680 while(textPos < textBlock.textLen)
3682 int startPos = textPos;
3685 bool lineComplete = false;
3687 for(; textPos<textBlock.textLen && !lineComplete;)
3691 char * nextSpace = strchr(text + textPos, ' ');
3694 len = (nextSpace - (text + textPos)) + 1;
3696 len = textBlock.textLen - textPos;
3698 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3700 if(x + width + w > maxW && x > 0)
3702 lineComplete = true;
3715 if(curPosition < textPos || textPos == textBlock.textLen)
3717 int len = curPosition - startPos;
3718 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
3723 sx = textBlock.startX;
3728 SetCaret(sx, sy, th);
3730 Point scrollPos = scroll;
3731 bool doScroll = false;
3732 if(sy - scroll.y + th > clientSize.h)
3734 scrollPos.y = sy + th - clientSize.h;
3737 else if(sy - scroll.y < 0)
3742 if(sx - scroll.x + 10 > clientSize.w)
3744 scrollPos.x = sx + 10 - clientSize.w;
3747 else if(sx - scroll.x < 10)
3749 scrollPos.x = sx - 10;
3760 // Returns a character offset into the TextBlock from a window coordinate
3761 int TextPosFromPoint(int px, int py, Block * block, bool half)
3763 Block parentBlock = this.textBlock.parent;
3766 *block = this.textBlock;
3771 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
3773 int sx = textBlock.startX, sy = textBlock.startY;
3776 char * text = textBlock.text;
3778 Block b = textBlock;
3781 if(textBlock.type != TEXT) continue;
3783 while(b && b.type != TD) b = b.parent;
3787 while(table && table.type != TABLE) table = table.parent;
3789 maxW = b.w - 2* table.cellPadding;
3791 maxW = clientSize.w - 10 - sx;
3794 maxW = clientSize.w - 10 - sx;
3796 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
3797 //space = space/2+2;
3800 while(textPos < textBlock.textLen)
3804 bool lineComplete = false;
3806 for(; textPos<textBlock.textLen && !lineComplete;)
3810 char * nextSpace = strchr(text + textPos, ' ');
3813 len = (nextSpace - (text + textPos)) + 1;
3815 len = textBlock.textLen - textPos;
3817 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3819 sx = x + textBlock.startX;
3820 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
3825 for(c = textPos; (ch = text[c]); c += numBytes)
3827 numBytes = UTF8_NUM_BYTES(ch);
3828 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
3829 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
3836 if(x + width + w > maxW && x > 0)
3838 lineComplete = true;
3851 if(/*py >= sy && */py < sy + th)
3854 return textBlock.textLen;
3859 result = textBlock.textLen;
3865 Application componentsApp;
3867 class Documentor : GuiApplication
3871 Platform os = __runtimePlatform;
3872 SetGlobalContext(globalContext);
3873 SetExcludedSymbols(&excludedSymbols);
3874 SetDefines(&::defines);
3875 SetImports(&imports);
3876 SetInDocumentor(true);
3878 SetGlobalData(globalData);
3880 settingsContainer.dataOwner = &settings;
3881 settingsContainer.Load();
3882 if(!settings.docDir || !settings.docDir[0] )
3884 if(os == win32) // if Windows OS then
3886 char programFilesDir[MAX_LOCATION];
3887 char appData[MAX_LOCATION];
3888 char homeDrive[MAX_LOCATION];
3889 char winDir[MAX_LOCATION];
3890 GetEnvironment("APPDATA", appData, sizeof(appData));
3891 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
3892 GetEnvironment("windir", winDir, sizeof(winDir));
3893 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
3895 PathCat(programFilesDir, "ECERE SDK\\doc");
3896 settings.docDir = programFilesDir;
3898 else if(homeDrive[0])
3900 PathCat(homeDrive, "ECERE SDK\\doc");
3901 settings.docDir = homeDrive;
3905 PathCat(winDir, "..\\ECERE SDK\\doc");
3906 settings.docDir = winDir;
3909 settings.docDir = "C:\\ECERE SDK\\doc";
3911 else // if Os is Linux, or Mac OSX or something else
3912 settings.docDir = "/usr/share/ecere/doc/";
3913 settingsContainer.Save();
3919 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
3921 AddComponents(module, true);
3922 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
3923 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
3924 while((row = row.parent))
3925 row.collapsed = false;
3929 commandThread.Create();
3933 bool Cycle(bool idle)
3936 mainForm.Destroy(0);
3945 if(commandThread.created)
3947 console.CloseInput();
3948 console.CloseOutput();
3950 commandThread.Wait();
3954 FreeContext(globalContext);
3955 FreeExcludedSymbols(excludedSymbols);
3956 ::defines.Free(FreeModuleDefine);
3957 imports.Free(FreeModuleImport);
3959 FreeGlobalData(globalData);
3960 FreeTypeData(componentsApp);
3962 delete componentsApp;
3966 ConsoleFile console { };
3967 MainForm mainForm { };
3970 Thread commandThread
3977 console.GetLine(command, sizeof(command));
3978 if(!quit && command[0])
3981 if(!strcmpi(command, "Activate"))
3982 mainForm.Activate();
3983 else if(!strcmpi(command, "Quit"))