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)&((Symbol)0).left };
14 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
17 /*extern */int __ecereVMethodID_class_OnGetString;
24 a.OnGetString(null, null, null);
27 static bool editing = true;
29 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
31 static char * iconNames[CodeObjectType] =
33 "<:ecere>constructs/class.png",
34 "<:ecere>constructs/data.png",
35 "<:ecere>constructs/method.png",
36 "<:ecere>constructs/event.png",
37 "<:ecere>constructs/property.png",
38 "<:ecere>constructs/namespace.png",
39 "<:ecere>constructs/dataType.png",
40 "<:ecere>constructs/enumValue.png",
41 "<:ecere>constructs/dataPrivate.png",
42 "<:ecere>constructs/methodPrivate.png",
43 "<:ecere>constructs/propertyPrivate.png"
46 IDESettings settings { }; // instantiate the IDESettings class from the IDESettings.ec file. Do this at a global level so that all methods can access settings.
48 IDESettingsContainer settingsContainer
52 dataOwner = &settings;
55 // WARNING : This function expects a null terminated string since it recursively concatenate...
56 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
63 if(type._class && type._class.string)
66 strcat(string, type._class.string);
69 if(type._class.registered)
72 sprintf(hex, "%p", type._class.registered);
73 strcat(string, "<a href=\"api://");
75 strcat(string, "\" style=\"text-decoration: none;\">");
76 strcat(string, type._class.registered.name);
77 strcat(string, "</a>");
80 strcat(string, type._class.string);
87 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
88 if(funcType && funcType.kind == functionType)
91 DocPrintType(funcType.returnType, string, false, fullName);
93 if(printName || funcType.thisClass)
96 if(funcType.thisClass)
98 strcat(string, funcType.thisClass.string);
102 strcat(string, type.name);
104 strcat(string, ")(");
105 for(param = funcType.params.first; param; param = param.next)
107 DocPrintType(param, string, false, fullName);
108 if(param.next) strcat(string, ", ");
114 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
115 if(string[strlen(string)-1] == '(')
118 strcat(string, " *");
122 case voidType: strcat(string, "void"); break;
123 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
124 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
125 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
126 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
127 case floatType: strcat(string, "float"); break;
128 case doubleType: strcat(string, "double"); break;
132 strcat(string, "struct ");
133 strcat(string, type.enumName);
135 else if(type.typeName)
137 strcat(string, type.typeName);
142 strcat(string, "struct ");
143 strcat(string,"(unnamed)");
146 strcat(string, "struct {");
147 for(member = type.members.first; member; member = member.next)
149 DocPrintType(member, string, true, fullName);
158 strcat(string, "union ");
159 strcat(string, type.enumName);
161 else if(type.typeName)
163 strcat(string, type.typeName);
167 strcat(string, "union ");
168 strcat(string,"(unnamed)");
174 strcat(string, "enum ");
175 strcat(string, type.enumName);
177 else if(type.typeName)
179 strcat(string, type.typeName);
182 strcat(string, "enum");
189 strcat(string, "dllexport ");
190 DocPrintType(type.returnType, string, false, fullName);
194 // DANGER: Testing This
200 strcat(string, type.name);
203 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
204 if(name) name += 2; else name = type.name;
205 strcat(string, "<b>");
206 strcat(string, name);
207 strcat(string, "</b>");
220 for(param = type.params.first; param; param = param.next)
222 DocPrintType(param, string, true, fullName);
223 if(param.next) strcat(string, ", ");
232 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
233 if(funcType && funcType.kind == functionType)
236 DocPrintType(funcType.returnType, string, false, fullName);
237 strcat(string, "(*");
238 if(printName || funcType.thisClass)
241 if(funcType.thisClass)
243 strcat(string, funcType.thisClass.string);
244 strcat(string, "::");
247 strcat(string, type.name);
249 strcat(string, ")(");
250 for(param = funcType.params.first; param; param = param.next)
252 DocPrintType(param, string, false, fullName);
253 if(param.next) strcat(string, ", ");
259 char baseType[1024], size[256];
260 Type arrayType = type;
264 while(arrayType.kind == TypeKind::arrayType)
267 if(arrayType.enumClass)
268 strcat(size, arrayType.enumClass.string);
269 else if(arrayType.arraySizeExp)
270 PrintExpression(arrayType.arraySizeExp, size);
271 //sprintf(string, "%s[%s]", baseType, size);
274 arrayType = arrayType.arrayType;
276 _PrintType(arrayType, baseType, printName, printFunction, fullName);
277 strcat(string, baseType);
278 strcat(string, size);
282 DocPrintType(type.arrayType, baseType, printName, fullName);
284 strcpy(size, type.enumClass.string);
285 else if(type.arraySizeExp)
286 PrintExpression(type.arraySizeExp, size);
287 //sprintf(string, "%s[%s]", baseType, size);
288 strcat(string, baseType);
290 strcat(string, size);
298 strcat(string, "...");
301 _PrintType(type.method.dataType, string, false, printFunction, fullName);
304 strcat(string, "subclass(");
305 strcat(string, type._class ? type._class.string : "int");
311 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
314 strcat(string, type.name);
319 void DocPrintType(Type type, char * string, bool printName, bool fullName)
322 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
323 if(funcType && funcType.kind == functionType && type != funcType)
325 char typeString[1024];
328 DocPrintType(funcType.returnType, string, false, fullName);
330 _PrintType(type, string, printName, false, fullName);
334 strcat(string, type.name);
341 for(param = funcType.params.first; param; param = param.next)
343 DocPrintType(param, string, true, fullName);
344 if(param.next) strcat(string, ", ");
349 _PrintType(type, string, printName, true, fullName);
352 void AddComponents(Module module, bool isDll)
357 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
359 row = mainForm.browser.AddRow();
360 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
362 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
365 for(m = module.modules.first; m; m = m.next)
367 if(m.importMode == publicAccess || !isDll)
368 AddComponents(m.module, true);
371 // PUT MODULE DESCRIPTION HERE
372 if(module.name && strcmp(module.name, "ecereCOM"))
374 row = mainForm.browser.AddRow();
375 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
376 row.tag = (int)module;
377 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
379 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
391 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
396 virtual void Generate(File f)
401 virtual Module GetModule()
403 return page ? page.GetModule() : null;
406 virtual NameSpace * GetNameSpace()
408 return page ? page.GetNameSpace() : null;
412 enum DocumentationType
420 enum DocumentationItem
436 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
438 NameSpace * nameSpace, * ns;
440 Method method = null;
441 GlobalFunction function = null;
442 char nsName[1024], temp[1024];
448 case nameSpaceDoc: nameSpace = object; break;
449 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
450 case functionDoc: function = object; nameSpace = function.nameSpace; break;
451 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
456 while(ns && ns->name)
458 strcpy(temp, "namespaces/");
459 strcat(temp, ns->name);
461 strcat(temp, nsName);
462 strcpy(nsName, temp);
465 sprintf(docFile, "%s.eCdoc", (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
467 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.
468 strcat(fileName, nsName);
472 strcat(fileName, "classes/");
473 strcat(fileName, cl.name);
474 strcat(fileName, "/");
479 strcat(fileName, "methods/");
480 strcat(fileName, method.name);
481 strcat(fileName, "/");
485 char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
486 if(name) name += 2; else name = function.name;
487 strcat(fileName, "functions/");
488 strcat(fileName, name);
489 strcat(fileName, "/");
494 case description: strcat(fileName, "description"); break;
495 case usage: strcat(fileName, "usage"); break;
496 case remarks: strcat(fileName, "remarks"); break;
497 case example: strcat(fileName, "example"); break;
498 case seeAlso: strcat(fileName, "seeAlso"); break;
499 case returnValue: strcat(fileName, "returnValue"); break;
500 case enumerationValue:
501 strcat(fileName, "enumeration values/");
502 strcat(fileName, ((NamedLink)data).name);
505 strcat(fileName, "definitions/");
506 strcat(fileName, ((Definition)data).name);
510 char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
511 if(name) name += 2; else name = ((Property)data).name;
512 strcat(fileName, "conversions/");
513 strcat(fileName, name);
516 case memberDescription:
517 strcat(fileName, "data members/");
518 strcat(fileName, ((DataMember)data).name);
520 case propertyDescription:
521 strcat(fileName, "properties/");
522 strcat(fileName, ((Property)data).name);
529 strcat(fileName, "parameters/");
530 for(prev = data, count = 0; prev; prev = prev.prev, count++);
531 sprintf(name, "%s.%d", ((Type)data).name, count);
532 strcat(fileName, name);
538 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
540 char fileName[MAX_LOCATION];
541 String contents = null;
544 FigureFileName(fileName, module, type, object, item, data);
545 file = FileOpen(fileName, read);
549 if((len = file.GetSize()))
551 contents = new char[len+1];
552 file.Read(contents, 1, len);
553 contents[len] = '\0';
560 for(c = 0; contents[c]; c++)
561 if(!isspace(contents[c])) break;
565 if(editing && !contents && !readOnly)
566 contents = CopyString($"[Add Text]");
570 class APIPageNameSpace : APIPage
572 NameSpace * nameSpace;
580 NameSpace * GetNameSpace()
585 void Generate(File f)
588 char nsName[1024], temp[1024];
595 while(ns && ns->name)
597 strcpy(temp, ns->name);
598 if(nsName[0]) strcat(temp, "::");
599 strcat(temp, nsName);
600 strcpy(nsName, temp);
603 // Generate Class Page
604 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
607 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
608 tag = (uint)nameSpace;
609 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);
613 tag = (uint)((!module || !module.name || !strcmp(nsName, "ecere::com") ? null : module));
614 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
618 ns = nameSpace->parent;
619 while(ns && ns->name)
621 strcpy(temp, ns->name);
622 if(nsName[0]) strcat(temp, "::");
623 strcat(temp, nsName);
624 strcpy(nsName, temp);
628 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
632 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
635 f.Printf($"<H3>Description</H3><br><br>\n");
638 char fileName[MAX_LOCATION];
639 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
640 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
642 f.Printf("</a><br><br>");
645 f.Printf("%s<br><br>", desc);
650 if(nameSpace->nameSpaces.first)
653 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
655 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
658 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
659 f.Printf("<TABLE>\n");
663 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);
668 char fileName[MAX_LOCATION];
669 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
670 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
672 f.Printf("</a></TD>");
675 f.Printf("<TD valign=top height=22> %s</TD>", desc);
678 f.Printf("</TR><br>\n");
681 f.Printf("</TABLE><br>\n");
684 if(nameSpace->classes.first)
687 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
689 Class cl = link.data;
690 if(!cl.templateClass)
692 char * desc = ReadDoc(module, classDoc, cl, description, null);
696 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
697 f.Printf("<TABLE>\n");
703 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);
708 char fileName[MAX_LOCATION];
709 FigureFileName(fileName, module, classDoc, cl, description, null);
710 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
712 f.Printf("</a></TD>");
715 f.Printf("<TD valign=top height=22>%s</TD>", desc);
722 f.Printf("</TABLE><br>\n");
725 if(nameSpace->functions.first)
728 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
730 GlobalFunction function = link.data;
731 char * desc = ReadDoc(module, functionDoc, function, description, null);
732 char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
733 if(name) name += 2; else name = function.name;
736 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
737 f.Printf("<TABLE>\n");
741 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);
746 char fileName[MAX_LOCATION];
747 FigureFileName(fileName, module, functionDoc, function, description, null);
748 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
750 f.Printf("</a></TD>");
753 f.Printf("<TD valign=top height=22> %s</TD>", desc);
756 f.Printf("</TR><br>\n");
759 f.Printf("</TABLE><br>\n");
762 if(nameSpace->defines.first)
765 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
767 DefinedExpression def = link.data;
768 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
771 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
772 f.Printf("<TABLE>\n");
776 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);
777 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
782 char fileName[MAX_LOCATION];
783 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
784 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
786 f.Printf("</a></TD>");
789 f.Printf("<TD valign=top height=22> %s</TD>", desc);
792 f.Printf("</TR><br>\n");
795 f.Printf("</TABLE><br>\n");
798 f.Printf("</FONT></BODY></HTML>\n");
802 class APIPageClass : APIPage
811 NameSpace * GetNameSpace()
816 void Generate(File f)
822 char nsName[1024], temp[1024];
823 NameSpace * ns = cl.nameSpace;
824 Module module = cl.module;
827 while(ns && ns->name)
829 strcpy(temp, ns->name);
830 if(nsName[0]) strcat(temp, "::");
831 strcat(temp, nsName);
832 strcpy(nsName, temp);
835 // Generate Class Page
836 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
837 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
839 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);
841 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
844 char * classType = null;
848 classType = $"Bit Collection";
851 classType = $"Enumeration";
854 classType = $"Structure";
857 classType = $"Class";
860 classType = $"Class (No header)";
866 classType = $"Basic Data Type";
869 f.Printf($"Type: %s<br>\n", classType);
872 if(cl.type != systemClass && cl.base)
874 f.Printf($"Base Class: ");
875 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
877 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
879 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
880 f.Printf("%s", cl.dataTypeString);
882 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
887 char * desc = ReadDoc(module, classDoc, cl, description, null);
890 f.Printf($"<br><H3>Description</H3><br><br>\n");
893 char fileName[MAX_LOCATION];
894 FigureFileName(fileName, module, classDoc, cl, description, null);
895 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
897 f.Printf("</a><br><br>");
900 f.Printf("%s<br><br>", desc);
905 if(cl.type == enumClass)
907 EnumClassData enumeration = (EnumClassData)cl.data;
908 if(enumeration.values.first)
912 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
913 f.Printf("<TABLE>\n");
915 for(item = enumeration.values.first; item; item = item.next)
917 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
918 bool needClass = true;
921 char tempString[1024];
923 while(base.type == enumClass) base = base.base;
925 if(base.type == systemClass ||
926 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
929 base.dataType = ProcessTypeString(base.dataTypeString, false);
931 if(base.dataType.kind != classType)
936 PrintType(base.dataType, string, false, true);
937 classSym = FindClass(string);
938 dataClass = classSym ? classSym.registered : null;
941 dataClass = base.dataType._class ? base.dataType._class.registered : null;
947 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);
948 if(dataClass.type == systemClass)
951 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
954 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
956 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
958 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
963 char fileName[MAX_LOCATION];
964 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
965 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
967 f.Printf("</a></TD>");
970 f.Printf("<TD valign=top height=22>%s</TD>", desc);
975 f.Printf("</TABLE><BR>\n");
979 if(cl.conversions.first)
981 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
982 f.Printf("<TABLE>\n");
983 for(prop = cl.conversions.first; prop; prop = prop.next)
985 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
987 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
990 Type type = ProcessTypeString(prop.name, false);
991 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
992 if(name) name += 2; else name = prop.name;
997 DocPrintType(type, string, true, false);
999 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1004 char fileName[MAX_LOCATION];
1005 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1006 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1008 f.Printf("</a></TD>");
1011 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1015 f.Printf("</TR>\n");
1020 f.Printf("</TABLE><br>\n");
1023 if(cl.membersAndProperties.first)
1026 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1028 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1032 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1033 f.Printf("<TABLE>\n");
1039 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1041 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1045 DocPrintType(prop.dataType, string, true, false);
1047 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);
1048 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1053 char fileName[MAX_LOCATION];
1054 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1055 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1057 f.Printf("</a></TD>");
1060 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1063 f.Printf("</TR>\n");
1067 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1072 f.Printf("</TABLE><br>\n");
1075 if(cl.methods.first)
1079 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1081 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1083 char * desc = ReadDoc(module, methodDoc, method, description, null);
1086 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1087 f.Printf("<TABLE>\n");
1090 if(!method.dataType)
1091 ProcessMethodType(method);
1094 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);
1099 char fileName[MAX_LOCATION];
1100 FigureFileName(fileName, module, methodDoc, method, description, null);
1101 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1103 f.Printf("</a></TD>");
1106 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1109 f.Printf("</TR><br>\n");
1113 f.Printf("</TABLE><br>\n");
1115 // Non-Virtual Methods
1117 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1119 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1121 char * desc = ReadDoc(module, methodDoc, method, description, null);
1124 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1125 f.Printf("<TABLE>\n");
1129 if(!method.dataType)
1130 ProcessMethodType(method);
1133 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);
1138 char fileName[MAX_LOCATION];
1139 FigureFileName(fileName, module, methodDoc, method, description, null);
1140 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1142 f.Printf("</a></TD>");
1145 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1149 f.Printf("</TR><br>\n");
1153 f.Printf("</TABLE><br>\n");
1156 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1159 f.Printf($"<H3>Usage</H3><br>\n");
1162 char fileName[MAX_LOCATION];
1163 FigureFileName(fileName, module, classDoc, cl, usage, null);
1164 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1169 f.Printf("<br>%s\n", usageDoc);
1170 f.Printf("<br><br>\n");
1175 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1178 f.Printf($"<H3>Example</H3><br>\n");
1179 f.Printf($"<FONT face=\"Courier New\">\n");
1180 f.Printf("<br><TABLE>\n");
1183 char fileName[MAX_LOCATION];
1184 FigureFileName(fileName, module, classDoc, cl, example, null);
1185 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1187 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1190 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1192 f.Printf("</TABLE></FONT>\n");
1198 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1202 f.Printf($"<H3>Remarks</H3><br>\n");
1205 char fileName[MAX_LOCATION];
1206 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1207 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1212 f.Printf("<br>%s\n", remarksDoc);
1213 f.Printf("<br><br>\n");
1218 if(cl.type != systemClass)
1222 for(c = cl.derivatives.first; c; c = c.next)
1224 Class deriv = c.data;
1225 // TO VERIFY: Does this properly check public status?
1226 if(eSystem_FindClass(componentsApp, deriv.fullName))
1230 f.Printf($"<H3>Derived Classes</H3><br>\n");
1236 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1240 f.Printf("<br><br>\n");
1243 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1246 f.Printf($"<H3>See Also</H3><br>\n");
1249 char fileName[MAX_LOCATION];
1250 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1251 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1256 f.Printf("<br>%s\n", seeAlsoDoc);
1257 f.Printf("<br><br>\n");
1261 f.Printf("</FONT></BODY></HTML>\n");
1265 class APIPageMethod : APIPage
1271 return method._class.module;
1274 NameSpace * GetNameSpace()
1276 return method._class.nameSpace;
1279 void Generate(File f)
1281 Class cl = method._class;
1283 Module module = cl.module;
1285 char nsName[1024], temp[1024];
1286 NameSpace * ns = cl.nameSpace;
1289 while(ns && ns->name)
1291 strcpy(temp, ns->name);
1292 if(nsName[0]) strcat(temp, "::");
1293 strcat(temp, nsName);
1294 strcpy(nsName, temp);
1298 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1299 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1301 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);
1303 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1304 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1305 if(method.dataType.staticMethod)
1307 f.Printf($"this pointer class: None<br>\n");
1309 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1311 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);
1314 // Generate Method Page
1316 if(!method.dataType.name)
1317 method.dataType.name = CopyString(method.name);
1318 DocPrintType(method.dataType, string, true, false);
1319 f.Printf("<br>%s", string);
1322 char * desc = ReadDoc(module, methodDoc, method, description, null);
1325 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1328 char fileName[MAX_LOCATION];
1329 FigureFileName(fileName, module, methodDoc, method, description, null);
1330 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1335 f.Printf("%s", desc);
1340 f.Printf("<br><br>\n");
1341 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1343 f.Printf($"<H3>Parameters</H3><br><br>\n");
1345 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1346 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1348 f.Printf("<TABLE valign=center>\n");
1351 for(param = method.dataType.params.first; param; param = param.next)
1353 // ADD DESCRIPTION HERE
1354 if(param.kind != voidType)
1356 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1359 DocPrintType(param, string, false, false);
1361 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1362 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1367 char fileName[MAX_LOCATION];
1368 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1369 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1371 f.Printf("</a></TD>\n");
1374 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1378 f.Printf("</TR>\n");
1381 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1383 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1384 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1386 f.Printf("<TR><TD> </TD></TR>");
1389 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1391 DocPrintType(method.dataType.returnType, string, false, false);
1392 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1397 char fileName[MAX_LOCATION];
1398 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1399 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1401 f.Printf("</a> </TD>\n");
1404 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1407 f.Printf("</TR>\n");
1408 f.Printf("</TABLE>\n");
1410 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1411 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1413 f.Printf("</TABLE><br>\n");
1416 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1419 f.Printf($"<H3>Usage</H3><br>\n");
1422 char fileName[MAX_LOCATION];
1423 FigureFileName(fileName, module, methodDoc, method, usage, null);
1424 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1429 f.Printf("<br>%s\n", usageDoc);
1430 f.Printf("<br><br>\n");
1435 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1438 f.Printf($"<H3>Example</H3><br>\n");
1439 f.Printf($"<FONT face=\"Courier New\">\n");
1440 f.Printf("<br><TABLE>\n");
1443 char fileName[MAX_LOCATION];
1444 FigureFileName(fileName, module, methodDoc, method, example, null);
1445 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1447 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1450 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1451 f.Printf("</TABLE></FONT>\n");
1457 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1460 f.Printf($"<H3>Remarks</H3><br>\n");
1463 char fileName[MAX_LOCATION];
1464 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1465 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1470 f.Printf("<br>%s\n", method, remarksDoc);
1471 f.Printf("<br><br>\n");
1476 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1479 f.Printf($"<H3>See Also</H3><br>\n");
1482 char fileName[MAX_LOCATION];
1483 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1484 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1489 f.Printf("<br>%s\n", method, seeAlsoDoc);
1491 f.Printf("<br><br>\n");
1495 f.Printf("</FONT></BODY></HTML>\n");
1499 class APIPageFunction : APIPage
1501 GlobalFunction function;
1505 return function.module;
1508 NameSpace * GetNameSpace()
1510 return function.nameSpace;
1513 void Generate(File f)
1516 Module module = function.module;
1518 char nsName[1024], temp[1024];
1519 NameSpace * ns = function.nameSpace;
1522 while(ns && ns->name)
1524 strcpy(temp, ns->name);
1525 if(nsName[0]) strcat(temp, "::");
1526 strcat(temp, nsName);
1527 strcpy(nsName, temp);
1531 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1532 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1534 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);
1537 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1539 if(!function.dataType)
1540 function.dataType = ProcessTypeString(function.dataTypeString, false);
1542 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1544 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);
1547 // Generate Method Page
1549 if(!function.dataType.name)
1550 function.dataType.name = CopyString(function.name);
1551 DocPrintType(function.dataType, string, true, false);
1552 f.Printf("<br>%s", string);
1555 char * desc = ReadDoc(module, functionDoc, function, description, null);
1558 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1561 char fileName[MAX_LOCATION];
1562 FigureFileName(fileName, module, functionDoc, function, description, null);
1563 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1568 f.Printf("%s", desc);
1572 f.Printf("<br><br>\n");
1573 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1575 f.Printf($"<H3>Parameters</H3><br><br>\n");
1577 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1578 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1580 f.Printf("<TABLE valign=center>\n");
1583 for(param = function.dataType.params.first; param; param = param.next)
1585 // ADD DESCRIPTION HERE
1586 if(param.kind != voidType)
1588 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1591 DocPrintType(param, string, false, false);
1593 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1594 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1599 char fileName[MAX_LOCATION];
1600 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1601 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1604 f.Printf("</a> </TD>\n");
1607 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1610 f.Printf("</TR>\n");
1613 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1615 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1616 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1618 f.Printf("<TR><TD> </TD></TR>");
1621 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1623 DocPrintType(function.dataType.returnType, string, false, false);
1624 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1629 char fileName[MAX_LOCATION];
1630 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1631 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1633 f.Printf("</a> </TD>\n");
1636 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1639 f.Printf("</TR>\n");
1640 f.Printf("</TABLE>\n");
1642 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1643 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1645 f.Printf("</TABLE><br>\n");
1648 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1651 f.Printf($"<H3>Usage</H3><br>\n");
1654 char fileName[MAX_LOCATION];
1655 FigureFileName(fileName, module, functionDoc, function, usage, null);
1656 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1661 f.Printf("<br>%s\n", usageDoc);
1662 f.Printf("<br><br>\n");
1667 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1670 f.Printf($"<H3>Example</H3><br>\n");
1671 f.Printf($"<FONT face=\"Courier New\">\n");
1672 f.Printf("<br><TABLE>\n");
1675 char fileName[MAX_LOCATION];
1676 FigureFileName(fileName, module, functionDoc, function, example, null);
1677 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1679 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1682 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1683 f.Printf("</TABLE></FONT>\n");
1689 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1692 f.Printf($"<H3>Remarks</H3><br>\n");
1695 char fileName[MAX_LOCATION];
1696 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1697 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1702 f.Printf("<br>%s\n", remarksDoc);
1703 f.Printf("<br><br>\n");
1708 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1711 f.Printf($"<H3>See Also</H3><br>\n");
1714 char fileName[MAX_LOCATION];
1715 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1716 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1721 f.Printf("<br>%s\n", seeAlsoDoc);
1722 f.Printf("<br><br>\n");
1726 f.Printf("</FONT></BODY></HTML>\n");
1730 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, char * parentName, bool showPrivate)
1734 NameSpace * nameSpace = mainNameSpace;
1736 DataRow classesRow = null;
1737 DataRow functionsRow = null, definesRow = null;
1740 char fileName[MAX_LOCATION];
1742 strcpy(nsName, parentName ? parentName : "");
1746 strcat(nsName, "::");
1747 strcat(nsName, nameSpace->name);
1752 row = parentRow.AddRow();
1753 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1754 row.tag = (int)nameSpace;
1755 row.icon = mainForm.icons[typeNameSpace];
1759 // "Global NameSpace"
1761 page = parentRow.GetData(null);
1767 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1769 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1770 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1772 if(comNameSpace != null)
1774 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1776 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1778 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1783 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1785 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1787 if(nameSpace->classes.first)
1791 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1794 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1796 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1797 AddClass(classesRow, module, cl, nsName, showPrivate);
1804 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
1806 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1808 if(nameSpace->functions.first)
1812 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
1815 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
1817 char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
1819 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
1820 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int)fn;
1827 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
1829 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1831 if(nameSpace->defines.first)
1835 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
1838 //if(def.module == module)
1840 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
1842 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
1843 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int)def;
1851 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
1855 if(!member.dataType)
1856 member.dataType = ProcessTypeString(member.dataTypeString, false);
1860 DocPrintType(member.dataType, string, true, false);
1862 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
1863 for(c = 0; c<indent; c++)
1864 f.Printf(" ");
1865 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
1866 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
1867 if(member.type == normalMember)
1869 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
1874 char fileName[MAX_LOCATION];
1875 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
1876 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1878 f.Printf("</a></TD>");
1881 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1886 f.Printf("<TD valign=top height=22></TD>");
1888 if(member.type != normalMember)
1890 DataMember subMember;
1891 for(subMember = member.members.first; subMember; subMember = subMember.next)
1893 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
1895 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
1899 f.Printf("</TR><br>\n");
1902 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
1905 if(member.type == normalMember)
1907 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
1908 row.tag = (int)member;
1913 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
1914 row.icon = mainForm.icons[typeData];
1915 row.tag = (int)member;
1917 for(m = member.members.first; m; m = m.next)
1919 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
1920 AddDataMember(row, page, m);
1925 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
1927 char fileName[MAX_LOCATION];
1934 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
1935 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
1938 row = parentRow.AddRow();
1939 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
1941 row.collapsed = true;
1942 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
1945 if(cl.methods.first)
1947 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1949 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
1952 if(!method.dataType)
1953 ProcessMethodType(method);
1954 if(method.type == virtualMethod)
1956 if(method.dataType.thisClass)
1958 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
1959 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
1960 mRow.tag = (int)method;
1964 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
1965 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
1966 mRow.tag = (int)method;
1971 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
1972 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
1973 mRow.tag = (int)method;
1979 if(cl.membersAndProperties.first)
1981 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1983 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1986 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1990 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
1991 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
1992 mRow.tag = (int)prop;
1996 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
1997 AddDataMember(membersRow, page, (DataMember)prop);
2003 if(cl.conversions.first)
2005 for(prop = cl.conversions.first; prop; prop = prop.next)
2009 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2010 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2011 if(name) name += 2; else name = prop.name;
2012 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2013 mRow.tag = (int)prop;
2016 if(cl.type == enumClass)
2018 EnumClassData enumeration = (EnumClassData)cl.data;
2020 for(item = enumeration.values.first; item; item = item.next)
2023 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2024 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2025 mRow.tag = (int)item;
2030 class MainForm : Window
2032 size = { 1000, 600 };
2034 borderStyle = sizable;
2037 nativeDecorations = true;
2038 icon = { ":documentorIcon.png" };
2039 text = $"API Documentation Browser";
2041 BitmapResource icons[CodeObjectType];
2046 for(c = 0; c < CodeObjectType::enumSize; c++)
2048 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2050 browser.AddField(DataField { dataType = class(APIPage) });
2055 Menu fileMenu { menu, $"File", f };
2056 Array<FileFilter> fileFilters
2058 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2059 { $"eC Symbol files (*.sym)", "sym" }
2062 FileDialog fileDialog
2064 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2066 MenuItem fileOpenItem
2068 fileMenu, $"Open...", o, ctrlO;
2070 bool NotifySelect(MenuItem selection, Modifiers mods)
2072 if(fileDialog.Modal() == ok)
2074 OpenModule(fileDialog.filePath);
2079 MenuItem fileSettingsItem
2081 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2083 bool NotifySelect(MenuItem selection, Modifiers mods)
2085 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2094 MenuDivider { fileMenu };
2095 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2097 void OpenModule(char * filePath)
2099 char extension[MAX_EXTENSION];
2100 Module module = null;
2101 static char symbolsDir[MAX_LOCATION];
2103 FreeContext(globalContext);
2104 FreeExcludedSymbols(excludedSymbols);
2105 ::defines.Free(FreeModuleDefine);
2106 imports.Free(FreeModuleImport);
2108 FreeGlobalData(globalData);
2109 FreeTypeData(componentsApp);
2111 delete componentsApp;
2113 SetGlobalContext(globalContext);
2114 componentsApp = __ecere_COM_Initialize(false, 1, null);
2115 SetPrivateModule(componentsApp);
2117 StripLastDirectory(filePath, symbolsDir);
2118 SetSymbolsDir(symbolsDir);
2120 GetExtension(filePath, extension);
2122 mainForm.browser.Clear();
2124 ImportModule(filePath, normalImport, publicAccess, false);
2126 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll"))
2127 componentsApp.name = CopyString(filePath);
2129 for(module = componentsApp.allModules.first; module; module = module.next)
2131 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2135 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2136 AddComponents(componentsApp, false);
2138 for(module = componentsApp.allModules.first; module; module = module.next)
2140 if(module.name && (!strcmp(module.name, filePath)))
2143 if(!module) module = componentsApp;
2144 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int)module));
2146 SetSymbolsDir(null);
2151 this, anchor = { left = 0, top = 0, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2152 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2155 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2157 APIPage page = row.GetData(null);
2158 if(view.edit) view.OnLeftButtonDown(0,0,0);
2159 if(page && page.page) page = page.page;
2161 view.PositionCaret(true);
2162 if(page != view.page)
2164 Window activeChild = this.activeChild;
2169 activeChild.Activate();
2171 else if(!view.created)
2175 page = row.GetData(null);
2176 if(page && page.page)
2180 case 1: view.GoToAnchor("Classes"); break;
2181 case 2: view.GoToAnchor("Functions"); break;
2182 case 3: view.GoToAnchor("Definitions"); break;
2183 case 4: view.GoToAnchor("VirtualMethods"); break;
2184 case 5: view.GoToAnchor("Methods"); break;
2185 case 6: view.GoToAnchor("Members"); break;
2186 case 7: view.GoToAnchor("Conversions"); break;
2187 case 8: view.GoToAnchor("EnumerationValues"); break;
2191 sprintf(hex, "%p", row.tag);
2192 view.GoToAnchor(hex);
2198 view.SetScrollPosition(0, 0);
2206 this, anchor = { top = 0, bottom = 0, right = 0 };
2211 this, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2214 bool OnClose(bool parentClosing)
2217 view.OnLeftButtonDown(0,0,0);
2223 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2224 //mainForm.OpenModule("ec");
2225 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2226 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2228 int index = mainForm.browser.currentRow.index;
2229 int rowHeight = mainForm.browser.rowHeight;
2230 int height = mainForm.browser.clientSize.h;
2232 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2238 class EditDialog : Window
2240 borderStyle = sizable;
2241 size = { 600, 400 };
2246 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2250 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2254 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2258 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2259 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2261 class HelpView : HTMLView
2265 hasVertScroll = true;
2266 hasHorzScroll = true;
2268 char editString[MAX_LOCATION];
2274 page = mainForm.browser.currentRow.GetData(null);
2279 char docFile[MAX_LOCATION];
2281 Module module = page ? page.GetModule() : null;
2282 NameSpace * ns = page ? page.GetNameSpace() : null;
2284 sprintf(docFile, "%s/%s.eCdoc", settings.docDir, (!module || !module.name || (ns && ns->name && !strcmp(ns->name, "namespaces/ecere/namespaces/com"))) ? "ecereCOM" : module.name);
2286 archive = ArchiveOpen(docFile, { true } );
2287 readOnly = archive == null;
2294 GoToAnchor(page.label);
2296 if(page.page) page = page.page;
2299 return HTMLView::OnCreate();
2308 char archiveFile[MAX_LOCATION];
2309 char fileName[MAX_FILENAME];
2310 char directory[MAX_LOCATION];
2312 Archive archive = null;
2313 if(SplitArchivePath(editString, archiveFile, &location))
2315 GetLastDirectory(location, fileName);
2316 StripLastDirectory(location, directory);
2317 archive = ArchiveOpen(archiveFile, { true } );
2321 ArchiveDir dir = archive ? archive.OpenDirectory(directory, null, replace) : null;
2324 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2326 if(block.type == TEXT && block.textLen)
2334 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2336 if(block.type == BR)
2338 else if(block.type == TEXT)
2339 f.Write(block.text, 1, block.textLen);
2344 dir.AddFromFile(fileName, f, null, replace, 0, null, null);
2350 Block parent = textBlock.parent;
2351 while((block = parent.subBlocks.first))
2353 parent.subBlocks.Remove(block);
2356 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
2357 textBlock.text = CopyString($"[Add Text]");
2358 textBlock.textLen = strlen(textBlock.text);
2359 parent.subBlocks.Add(textBlock);
2367 PositionCaret(true);
2373 bool OnLeftButtonDown(int x, int y, Modifiers mods)
2377 if(edit && (!textBlock || overLink != textBlock.parent))
2381 HTMLView::OnLeftButtonDown(x, y, mods);
2382 selPosition = curPosition = 0;
2383 selBlock = textBlock;
2387 result = HTMLView::OnLeftButtonDown(x, y, mods);
2389 if(!edit && clickedLink)
2392 if(clickedLink == overLink && clickedLink.href)
2394 if(OnOpen(clickedLink.href))
2402 if(textBlock && overLink == textBlock.parent)
2404 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2405 selBlock = textBlock;
2406 PositionCaret(true);
2414 bool OnLeftButtonUp(int x, int y, Modifiers mods)
2416 if(!edit || !textBlock || clickedLink != textBlock.parent)
2418 HTMLView::OnLeftButtonUp(x, y, mods);
2421 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2422 selBlock = textBlock;
2423 PositionCaret(true);
2434 bool OnMouseMove(int x, int y, Modifiers mods)
2436 if(edit && selecting)
2438 curPosition = TextPosFromPoint(x, y, &textBlock, true);
2439 PositionCaret(true);
2442 return HTMLView::OnMouseMove(x, y, mods);
2445 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
2447 if(edit && textBlock)
2453 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
2454 selBlock = textBlock;
2455 for(c = curPosition; c >= 0; c--)
2458 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
2459 ch = UTF8GetChar(textBlock.text + c, &numBytes);
2460 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2466 for(c = start; c < textBlock.textLen; c += numBytes)
2468 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
2469 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2472 selPosition = start;
2475 PositionCaret(true);
2483 bool OnOpen(char * href)
2485 if(!strncmp(href, "api://", 6))
2487 int tag = (uint)strtoul(href + 6, null, 16);
2488 DataRow row = mainForm.browser.FindSubRow(tag);
2492 mainForm.browser.SelectRow(row);
2493 while((row = row.parent))
2494 row.collapsed = false;
2495 row = mainForm.browser.currentRow;
2496 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
2499 else if(!strncmp(href, "edit://", 7))
2502 int startX = clickedLink.startX, startY = clickedLink.startY;
2503 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
2505 if(block.type == TEXT) startX = block.startX, startY = block.startY;
2506 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
2508 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
2510 display.FontExtent(block.font.font, " ", 1, null, &th);
2513 block.parent.subBlocks.Insert(null, newBlock);
2518 block.parent.subBlocks.Insert(block, newBlock);
2519 startY += block.prev.height;
2521 newBlock.startX = startX;
2522 newBlock.startY = startY;
2523 newBlock.text = new0 char[1];
2527 textBlock = (Block)clickedLink.subBlocks.first;
2528 if(!strcmp(textBlock.text, $"[Add Text]"))
2530 textBlock.text[0] = 0;
2531 textBlock.textLen = 0;
2534 strcpy(editString, href + 7);
2535 selPosition = curPosition = 0;
2536 selBlock = textBlock;
2539 // PositionCaret(true);
2546 void DeleteSelection()
2548 if(textBlock != selBlock || curPosition != selPosition)
2550 if(textBlock == selBlock)
2552 // Within same block
2553 int start = Min(curPosition, selPosition);
2554 int end = Max(curPosition, selPosition);
2555 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
2556 textBlock.textLen -= end-start;
2557 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
2558 curPosition = start;
2559 selPosition = start;
2563 int startSel, endSel;
2564 Block startSelBlock = null, endSelBlock = null, b, next;
2566 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2568 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
2569 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
2571 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
2572 for(b = startSelBlock.next; b; b = next)
2574 bool isEnd = b == endSelBlock;
2575 next = GetNextBlock(b);
2576 b.parent.subBlocks.Remove(b);
2581 textBlock = startSelBlock;
2582 selBlock = startSelBlock;
2583 curPosition = startSel;
2584 selPosition = startSel;
2588 PositionCaret(true);
2593 String GetSelectionString()
2595 String selection = null;
2596 if(textBlock == selBlock)
2598 // Within same block
2599 int start = Min(curPosition, selPosition);
2600 int end = Max(curPosition, selPosition);
2601 int len = end - start;
2602 selection = new char[len + 1];
2603 memcpy(selection, textBlock.text + start, len);
2608 int startSel, endSel;
2609 Block startSelBlock = null, endSelBlock = null, b;
2612 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2615 for(b = startSelBlock; b; b = GetNextBlock(b))
2617 int start = (b == startSelBlock) ? startSel : 0;
2618 int end = (b == endSelBlock) ? endSel : b.textLen;
2619 int len = end - start;
2621 if(b == endSelBlock)
2623 else if(b.type == TEXT)
2627 selection = new char[totalLen + 1];
2629 for(b = startSelBlock; b; b = GetNextBlock(b))
2631 int start = (b == startSelBlock) ? startSel : 0;
2632 int end = (b == endSelBlock) ? endSel : b.textLen;
2633 int len = end - start;
2634 memcpy(selection + totalLen, b.text + start, len);
2636 if(b == endSelBlock)
2638 else if(b.type == TEXT)
2639 selection[totalLen++] = '\n';
2641 selection[totalLen] = 0;
2646 void CopySelection()
2648 String s = GetSelectionString();
2651 int len = strlen(s);
2653 if(cb.Allocate(len + 1))
2655 memcpy(cb.text, s, len + 1);
2663 bool OnKeyDown(Key key, unichar ch)
2670 OnLeftButtonDown(0,0,0);
2672 case Key { end, shift = true }:
2674 curPosition = textBlock.textLen;
2677 selPosition = curPosition;
2678 selBlock = textBlock;
2680 PositionCaret(true);
2683 case Key { home, shift = true }:
2688 selPosition = curPosition;
2689 selBlock = textBlock;
2691 PositionCaret(true);
2694 case Key { home, ctrl = true, shift = true }:
2697 while(textBlock.prev)
2698 textBlock = textBlock.prev.prev;
2701 selPosition = curPosition;
2702 selBlock = textBlock;
2704 PositionCaret(true);
2707 case Key { end, ctrl = true, shift = true }:
2709 while(textBlock.next && textBlock.next.next)
2710 textBlock = textBlock.next.next;
2711 curPosition = textBlock.textLen;
2714 selPosition = curPosition;
2715 selBlock = textBlock;
2717 PositionCaret(true);
2723 return HTMLView::OnKeyDown(key, ch);
2727 bool OnKeyHit(Key key, unichar ch)
2733 case Key { up, shift = true }:
2736 if(caretY == textBlock.startY)
2740 textBlock = textBlock.prev.prev;
2741 curPosition = Min(curPosition, textBlock.textLen);
2744 selPosition = curPosition;
2745 selBlock = textBlock;
2748 PositionCaret(false);
2758 int sx = textBlock.startX, sy = textBlock.startY;
2759 char * text = textBlock.text;
2761 Block block = textBlock;
2762 while(block && block.type != TD) block = block.parent;
2765 Block table = block;
2766 while(table && table.type != TABLE) table = table.parent;
2768 maxW = block.w - 2* table.cellPadding;
2770 maxW = clientSize.w - 10 - sx;
2773 maxW = clientSize.w - 10 - sx;
2774 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
2778 int startPos = textPos;
2781 bool lineComplete = false;
2782 for(; textPos<textBlock.textLen && !lineComplete;)
2786 char * nextSpace = strchr(text + textPos, ' ');
2789 len = (nextSpace - (text + textPos)) + 1;
2791 len = textBlock.textLen - textPos;
2793 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
2795 if(x + width + w > maxW && x > 0)
2797 lineComplete = true;
2807 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
2810 curPosition = textPos;
2811 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
2814 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
2815 len = curPosition - startPos;
2816 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
2820 selPosition = curPosition;
2821 selBlock = textBlock;
2825 PositionCaret(false);
2829 if(sy == caretY - th || textPos == textBlock.textLen)
2831 if(textPos != textBlock.textLen)
2833 int c = textPos - 1;
2834 while(c > 0 && text[c] == ' ') c--;
2835 curPosition = c + 1;
2838 selPosition = curPosition;
2839 selBlock = textBlock;
2845 curPosition = textBlock.textLen;
2848 selPosition = curPosition;
2849 selBlock = textBlock;
2853 PositionCaret(false);
2857 sx = textBlock.startX;
2858 } while(textPos < textBlock.textLen);
2863 case Key { down, shift = true }:
2868 int sx = textBlock.startX, sy = textBlock.startY;
2869 char * text = textBlock.text;
2871 Block block = textBlock;
2872 while(block && block.type != TD) block = block.parent;
2875 Block table = block;
2876 while(table && table.type != TABLE) table = table.parent;
2878 maxW = block.w - 2* table.cellPadding;
2880 maxW = clientSize.w - 10 - sx;
2883 maxW = clientSize.w - 10 - sx;
2884 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
2886 while(!textPos || textPos < textBlock.textLen)
2888 int startPos = textPos;
2891 bool lineComplete = false;
2892 for(; (textPos < textBlock.textLen) && !lineComplete;)
2896 char * nextSpace = strchr(text + textPos, ' ');
2899 len = (nextSpace - (text + textPos)) + 1;
2901 len = textBlock.textLen - textPos;
2903 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
2905 if(x + width + w > maxW && x > 0)
2907 lineComplete = true;
2917 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
2919 curPosition = textPos;
2921 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
2924 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
2925 len = curPosition - startPos;
2926 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
2930 selPosition = curPosition;
2931 selBlock = textBlock;
2934 PositionCaret(false);
2940 curPosition = textBlock.textLen;
2943 selPosition = curPosition;
2944 selBlock = textBlock;
2947 PositionCaret(false);
2950 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
2954 textBlock = textBlock.next.next;
2955 sy = textBlock.startY;
2956 sx = textBlock.startX;
2957 text = textBlock.text;
2962 sx = textBlock.startX;
2966 /*if(textBlock.next && textBlock.next.next)
2968 textBlock = textBlock.next.next;
2969 selPosition = curPosition = Min(curPosition, textBlock.textLen);
2970 selBlock = textBlock;
2971 PositionCaret(false);
2975 case Key { right, shift = true, ctrl = true }:
2978 bool foundAlpha = false;
2980 Block line, lastLine;
2983 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
2985 int start = (line == textBlock) ? curPosition : 0;
2987 for(c = start; c < line.textLen; c++)
2989 char ch = line.text[c];
2990 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
2991 if(key.shift ? isAlUnder : !isAlUnder)
3005 selPosition = curPosition;
3006 selBlock = textBlock;
3010 PositionCaret(true);
3015 // No next word found,
3016 if(!found && (c != curPosition || line != textBlock))
3020 lastC = line.textLen-1;
3025 curPosition = line.textLen;
3028 selPosition = curPosition;
3029 selBlock = textBlock;
3034 PositionCaret(true);
3040 if(key.shift && found)
3042 curPosition = lastC+1;
3043 textBlock = lastLine;
3044 PositionCaret(true);
3049 case Key { left, ctrl = true, shift = true }:
3052 bool foundAlpha = false;
3054 Block line, lastLine;
3057 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3060 if(curPosition == 0 && line != textBlock)
3063 lastC = line.textLen;
3067 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3068 for(c = start; c>=0; c--)
3070 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3085 // No next word found,
3086 if(!found && curPosition > 0)
3096 textBlock = lastLine;
3097 curPosition = lastC;
3100 selPosition = curPosition;
3101 selBlock = textBlock;
3103 PositionCaret(true);
3108 case Key { right, shift = true }:
3110 if(curPosition < textBlock.textLen)
3112 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3115 selPosition = curPosition;
3116 selBlock = textBlock;
3118 PositionCaret(true);
3121 else if(textBlock.next && textBlock.next.next)
3123 textBlock = textBlock.next.next;
3127 selPosition = curPosition;
3128 selBlock = textBlock;
3130 PositionCaret(true);
3134 case Key { left, shift = true }:
3138 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3141 selPosition = curPosition;
3142 selBlock = textBlock;
3144 PositionCaret(true);
3147 else if(textBlock.prev)
3149 textBlock = textBlock.prev.prev;
3150 curPosition = textBlock.textLen;
3153 selPosition = curPosition;
3154 selBlock = textBlock;
3156 PositionCaret(true);
3162 if(textBlock == selBlock && curPosition == selPosition)
3166 int c = curPosition;
3168 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3169 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3170 textBlock.textLen -= nb;
3171 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3173 selPosition = curPosition;
3174 selBlock = textBlock;
3178 PositionCaret(true);
3181 else if(textBlock.prev)
3183 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3184 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3185 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3187 selPosition = curPosition = prevBlock.textLen;
3188 selBlock = textBlock;
3189 prevBlock.textLen += textBlock.textLen;
3190 textBlock.parent.subBlocks.Remove(prev);
3191 if(prev == selBlock)
3193 selBlock = textBlock;
3194 selPosition = curPosition;
3197 textBlock.parent.subBlocks.Remove(textBlock);
3198 if(textBlock == selBlock)
3200 selBlock = prevBlock;
3201 selPosition = curPosition;
3204 textBlock = prevBlock;
3208 PositionCaret(true);
3217 if(textBlock != selBlock || curPosition != selPosition)
3219 else if(textBlock.textLen > curPosition)
3221 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3222 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3223 textBlock.textLen -= nb;
3224 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3229 PositionCaret(true);
3232 else if(textBlock.next && textBlock.next.next)
3234 Block next = textBlock.next, nextBlock = textBlock.next.next;
3235 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3236 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3238 textBlock.textLen += nextBlock.textLen;
3239 textBlock.parent.subBlocks.Remove(next);
3240 if(next == selBlock)
3242 selBlock = textBlock;
3243 selPosition = curPosition;
3246 textBlock.parent.subBlocks.Remove(nextBlock);
3247 if(nextBlock == selBlock)
3249 selBlock = textBlock;
3250 selPosition = curPosition;
3256 PositionCaret(true);
3270 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3271 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3272 startY = textBlock.startY;
3273 startX = textBlock.startX;
3275 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3276 textBlock.parent.subBlocks.Insert(textBlock, block);
3277 textBlock.parent.subBlocks.Insert(block, newBlock);
3281 newBlock.textLen = textBlock.textLen - curPosition;
3282 newBlock.text = new char[newBlock.textLen+1];
3283 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3284 textBlock.textLen = curPosition;
3285 textBlock.text[curPosition] = 0;
3287 newBlock.startY = startY;
3288 newBlock.startX = startX;
3289 selPosition = curPosition = 0;
3294 textBlock = newBlock;
3295 selBlock = textBlock;
3296 PositionCaret(true);
3301 case Key { del, shift = true }:
3316 ClipBoard clipBoard { };
3317 if(clipBoard.Load())
3320 char * text = clipBoard.memory;
3328 parent = textBlock.parent;
3329 font = textBlock.font;
3334 if(ch == '\n' || ch == '\r' || !ch)
3336 int len = c - start;
3337 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
3338 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3339 memcpy(textBlock.text + curPosition, text + start, len);
3340 textBlock.textLen += len;
3342 selPosition = curPosition;
3343 selBlock = textBlock;
3346 Block block { type = BR, parent = parent, font = font };
3347 Block newBlock { type = TEXT, parent = parent, font = font };
3348 int startY = textBlock.startY, startX = textBlock.startX;
3351 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3352 textBlock.parent.subBlocks.Insert(textBlock, block);
3353 textBlock.parent.subBlocks.Insert(block, newBlock);
3357 newBlock.textLen = textBlock.textLen - curPosition;
3358 newBlock.text = new char[newBlock.textLen+1];
3359 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3360 textBlock.textLen = curPosition;
3361 textBlock.text[curPosition] = 0;
3363 newBlock.startY = startY;
3364 newBlock.startX = startX;
3365 selPosition = curPosition = 0;
3366 selBlock = textBlock;
3367 textBlock = newBlock;
3369 if(ch == '\r' && text[c+1] == '\n') c++;
3375 PositionCaret(true);
3383 // eC BUG HERE: (Should be fixed)
3384 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
3387 int len = UTF32toUTF8Len(&ch, 1, string, 5);
3392 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
3393 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3395 for(c = 0; c<len; c++)
3397 textBlock.text[curPosition] = string[c];
3398 textBlock.textLen++;
3401 selPosition = curPosition;
3402 selBlock = textBlock;
3405 //Clear(html.block);
3406 //CreateForms(html.block);
3411 PositionCaret(true);
3420 void OnResize(int width, int height)
3422 HTMLView::OnResize(width, height);
3423 PositionCaret(true);
3427 void PositionCaret(bool setCaretX)
3433 int sx = textBlock.startX, sy = textBlock.startY;
3434 char * text = textBlock.text;
3436 Block block = textBlock;
3437 while(block && block.type != TD) block = block.parent;
3440 Block table = block;
3441 while(table && table.type != TABLE) table = table.parent;
3443 maxW = block.w - 2* table.cellPadding;
3445 maxW = clientSize.w - 10 - sx;
3448 maxW = clientSize.w - 10 - sx;
3450 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3452 while(textPos < textBlock.textLen)
3454 int startPos = textPos;
3457 bool lineComplete = false;
3459 for(; textPos<textBlock.textLen && !lineComplete;)
3463 char * nextSpace = strchr(text + textPos, ' ');
3466 len = (nextSpace - (text + textPos)) + 1;
3468 len = textBlock.textLen - textPos;
3470 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3472 if(x + width + w > maxW && x > 0)
3474 lineComplete = true;
3487 if(curPosition < textPos || textPos == textBlock.textLen)
3489 int len = curPosition - startPos;
3490 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
3495 sx = textBlock.startX;
3500 SetCaret(sx, sy, th);
3502 Point scrollPos = scroll;
3503 bool doScroll = false;
3504 if(sy - scroll.y + th > clientSize.h)
3506 scrollPos.y = sy + th - clientSize.h;
3509 else if(sy - scroll.y < 0)
3514 if(sx - scroll.x + 10 > clientSize.w)
3516 scrollPos.x = sx + 10 - clientSize.w;
3519 else if(sx - scroll.x < 10)
3521 scrollPos.x = sx - 10;
3532 // Returns a character offset into the TextBlock from a window coordinate
3533 int TextPosFromPoint(int px, int py, Block * block, bool half)
3535 Block parentBlock = this.textBlock.parent;
3538 *block = this.textBlock;
3543 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
3545 int sx = textBlock.startX, sy = textBlock.startY;
3548 char * text = textBlock.text;
3550 Block b = textBlock;
3553 if(textBlock.type != TEXT) continue;
3555 while(b && b.type != TD) b = b.parent;
3559 while(table && table.type != TABLE) table = table.parent;
3561 maxW = b.w - 2* table.cellPadding;
3563 maxW = clientSize.w - 10 - sx;
3566 maxW = clientSize.w - 10 - sx;
3568 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
3569 //space = space/2+2;
3572 while(textPos < textBlock.textLen)
3574 int startPos = textPos;
3577 bool lineComplete = false;
3579 for(; textPos<textBlock.textLen && !lineComplete;)
3583 char * nextSpace = strchr(text + textPos, ' ');
3586 len = (nextSpace - (text + textPos)) + 1;
3588 len = textBlock.textLen - textPos;
3590 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3592 sx = x + textBlock.startX;
3593 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
3598 for(c = textPos; (ch = text[c]); c += numBytes)
3600 numBytes = UTF8_NUM_BYTES(ch);
3601 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
3602 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
3609 if(x + width + w > maxW && x > 0)
3611 lineComplete = true;
3624 if(/*py >= sy && */py < sy + th)
3627 return textBlock.textLen;
3632 result = textBlock.textLen;
3638 Application componentsApp;
3640 class Documentor : GuiApplication
3644 Platform os = GetRuntimePlatform();
3645 componentsApp = __ecere_COM_Initialize(false, 1, null);
3646 SetPrivateModule(componentsApp);
3647 SetGlobalContext(globalContext);
3648 SetExcludedSymbols(&excludedSymbols);
3649 SetDefines(&::defines);
3650 SetImports(&imports);
3652 SetGlobalData(globalData);
3654 settingsContainer.dataOwner = &settings;
3655 settingsContainer.Load();
3656 if(!settings.docDir || !settings.docDir[0] )
3658 if(os == win32) // if Windows OS then
3660 char programFilesDir[MAX_LOCATION];
3661 char appData[MAX_LOCATION];
3662 char homeDrive[MAX_LOCATION];
3663 char winDir[MAX_LOCATION];
3664 GetEnvironment("APPDATA", appData, sizeof(appData));
3665 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
3666 GetEnvironment("windir", winDir, sizeof(winDir));
3667 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
3669 PathCat(programFilesDir, "ECERE SDK\\doc");
3670 settings.docDir = programFilesDir;
3672 else if(homeDrive && homeDrive[0])
3674 PathCat(homeDrive, "ECERE SDK\\doc");
3675 settings.docDir = homeDrive;
3677 else if(winDir && winDir[0])
3679 PathCat(winDir, "..\\ECERE SDK\\doc");
3680 settings.docDir = winDir;
3683 settings.docDir = "C:\\ECERE SDK\\doc";
3685 else // if Os is Linux, or Mac OSX or something else
3686 settings.docDir = "/usr/share/ecere/doc/";
3687 settingsContainer.Save();
3693 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
3695 AddComponents(module, true);
3696 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int)module);
3697 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int)eSystem_FindClass(componentsApp, "Window"));
3698 while((row = row.parent))
3699 row.collapsed = false;
3707 FreeContext(globalContext);
3708 FreeExcludedSymbols(excludedSymbols);
3709 ::defines.Free(FreeModuleDefine);
3710 imports.Free(FreeModuleImport);
3712 FreeGlobalData(globalData);
3713 FreeTypeData(componentsApp);
3715 delete componentsApp;
3719 MainForm mainForm { };