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 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;
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 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 // WARNING : This function expects a null terminated string since it recursively concatenate...
58 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
65 if(type._class && type._class.string)
68 strcat(string, type._class.string);
71 if(type._class.registered)
74 sprintf(hex, "%p", type._class.registered);
75 strcat(string, "<a href=\"api://");
77 strcat(string, "\" style=\"text-decoration: none;\">");
78 strcat(string, type._class.registered.name);
79 strcat(string, "</a>");
82 strcat(string, type._class.string);
89 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
90 if(funcType && funcType.kind == functionType)
93 DocPrintType(funcType.returnType, string, false, fullName);
95 if(printName || funcType.thisClass)
98 if(funcType.thisClass)
100 strcat(string, funcType.thisClass.string);
101 strcat(string, "::");
104 strcat(string, type.name);
106 strcat(string, ")(");
107 for(param = funcType.params.first; param; param = param.next)
109 DocPrintType(param, string, false, fullName);
110 if(param.next) strcat(string, ", ");
116 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
117 if(string[strlen(string)-1] == '(')
120 strcat(string, " *");
124 case voidType: strcat(string, "void"); break;
125 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
126 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
127 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
128 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
129 case floatType: strcat(string, "float"); break;
130 case doubleType: strcat(string, "double"); break;
134 strcat(string, "struct ");
135 strcat(string, type.enumName);
137 else if(type.typeName)
139 strcat(string, type.typeName);
144 strcat(string, "struct ");
145 strcat(string,"(unnamed)");
148 strcat(string, "struct {");
149 for(member = type.members.first; member; member = member.next)
151 DocPrintType(member, string, true, fullName);
160 strcat(string, "union ");
161 strcat(string, type.enumName);
163 else if(type.typeName)
165 strcat(string, type.typeName);
169 strcat(string, "union ");
170 strcat(string,"(unnamed)");
176 strcat(string, "enum ");
177 strcat(string, type.enumName);
179 else if(type.typeName)
181 strcat(string, type.typeName);
184 strcat(string, "enum");
191 strcat(string, "dllexport ");
192 DocPrintType(type.returnType, string, false, fullName);
196 // DANGER: Testing This
202 strcat(string, type.name);
205 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
206 if(name) name += 2; else name = type.name;
207 strcat(string, "<b>");
208 strcat(string, name);
209 strcat(string, "</b>");
222 for(param = type.params.first; param; param = param.next)
224 DocPrintType(param, string, true, fullName);
225 if(param.next) strcat(string, ", ");
234 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
235 if(funcType && funcType.kind == functionType)
238 DocPrintType(funcType.returnType, string, false, fullName);
239 strcat(string, "(*");
240 if(printName || funcType.thisClass)
243 if(funcType.thisClass)
245 strcat(string, funcType.thisClass.string);
246 strcat(string, "::");
249 strcat(string, type.name);
251 strcat(string, ")(");
252 for(param = funcType.params.first; param; param = param.next)
254 DocPrintType(param, string, false, fullName);
255 if(param.next) strcat(string, ", ");
261 char baseType[1024], size[256];
262 Type arrayType = type;
266 while(arrayType.kind == TypeKind::arrayType)
269 if(arrayType.enumClass)
270 strcat(size, arrayType.enumClass.string);
271 else if(arrayType.arraySizeExp)
272 PrintExpression(arrayType.arraySizeExp, size);
273 //sprintf(string, "%s[%s]", baseType, size);
276 arrayType = arrayType.arrayType;
278 _PrintType(arrayType, baseType, printName, printFunction, fullName);
279 strcat(string, baseType);
280 strcat(string, size);
284 DocPrintType(type.arrayType, baseType, printName, fullName);
286 strcpy(size, type.enumClass.string);
287 else if(type.arraySizeExp)
288 PrintExpression(type.arraySizeExp, size);
289 //sprintf(string, "%s[%s]", baseType, size);
290 strcat(string, baseType);
292 strcat(string, size);
300 strcat(string, "...");
303 _PrintType(type.method.dataType, string, false, printFunction, fullName);
306 strcat(string, "subclass(");
307 strcat(string, type._class ? type._class.string : "int");
313 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
316 strcat(string, type.name);
321 void DocPrintType(Type type, char * string, bool printName, bool fullName)
324 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
325 if(funcType && funcType.kind == functionType && type != funcType)
327 char typeString[1024];
330 DocPrintType(funcType.returnType, string, false, fullName);
332 _PrintType(type, string, printName, false, fullName);
336 strcat(string, type.name);
343 for(param = funcType.params.first; param; param = param.next)
345 DocPrintType(param, string, true, fullName);
346 if(param.next) strcat(string, ", ");
351 _PrintType(type, string, printName, true, fullName);
354 void AddComponents(Module module, bool isDll)
359 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
361 row = mainForm.browser.AddRow();
362 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
364 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
367 for(m = module.modules.first; m; m = m.next)
369 if(m.importMode == publicAccess || !isDll)
370 AddComponents(m.module, true);
373 // PUT MODULE DESCRIPTION HERE
374 if(module.name && strcmp(module.name, "ecereCOM"))
376 row = mainForm.browser.AddRow();
377 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
378 row.tag = (int)module;
379 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
381 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
393 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
398 virtual void Generate(File f)
403 virtual Module GetModule()
405 return page ? page.GetModule() : null;
408 virtual NameSpace * GetNameSpace()
410 return page ? page.GetNameSpace() : null;
414 enum DocumentationType
422 enum DocumentationItem
438 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
440 NameSpace * nameSpace, * ns;
442 Method method = null;
443 GlobalFunction function = null;
444 char nsName[1024], temp[1024];
450 case nameSpaceDoc: nameSpace = object; break;
451 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
452 case functionDoc: function = object; nameSpace = function.nameSpace; break;
453 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
458 while(ns && ns->name)
460 strcpy(temp, "namespaces/");
461 strcat(temp, ns->name);
463 strcat(temp, nsName);
464 strcpy(nsName, temp);
467 sprintf(docFile, "%s.eCdoc", (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
469 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.
470 strcat(fileName, nsName);
474 strcat(fileName, "classes/");
475 strcat(fileName, cl.name);
476 strcat(fileName, "/");
481 strcat(fileName, "methods/");
482 strcat(fileName, method.name);
483 strcat(fileName, "/");
487 char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
488 if(name) name += 2; else name = function.name;
489 strcat(fileName, "functions/");
490 strcat(fileName, name);
491 strcat(fileName, "/");
496 case description: strcat(fileName, "description"); break;
497 case usage: strcat(fileName, "usage"); break;
498 case remarks: strcat(fileName, "remarks"); break;
499 case example: strcat(fileName, "example"); break;
500 case seeAlso: strcat(fileName, "seeAlso"); break;
501 case returnValue: strcat(fileName, "returnValue"); break;
502 case enumerationValue:
503 strcat(fileName, "enumeration values/");
504 strcat(fileName, ((NamedLink)data).name);
507 strcat(fileName, "definitions/");
508 strcat(fileName, ((Definition)data).name);
512 char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
513 if(name) name += 2; else name = ((Property)data).name;
514 strcat(fileName, "conversions/");
515 strcat(fileName, name);
518 case memberDescription:
519 strcat(fileName, "data members/");
520 strcat(fileName, ((DataMember)data).name);
522 case propertyDescription:
523 strcat(fileName, "properties/");
524 strcat(fileName, ((Property)data).name);
531 strcat(fileName, "parameters/");
532 for(prev = data, count = 0; prev; prev = prev.prev, count++);
533 sprintf(name, "%s.%d", ((Type)data).name, count);
534 strcat(fileName, name);
540 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
542 char fileName[MAX_LOCATION];
543 String contents = null;
546 FigureFileName(fileName, module, type, object, item, data);
547 file = FileOpen(fileName, read);
551 if((len = file.GetSize()))
553 contents = new char[len+1];
554 file.Read(contents, 1, len);
555 contents[len] = '\0';
562 for(c = 0; contents[c]; c++)
563 if(!isspace(contents[c])) break;
567 if(editing && !contents && !readOnly)
568 contents = CopyString($"[Add Text]");
572 class APIPageNameSpace : APIPage
574 NameSpace * nameSpace;
582 NameSpace * GetNameSpace()
587 void Generate(File f)
590 char nsName[1024], temp[1024];
597 while(ns && ns->name)
599 strcpy(temp, ns->name);
600 if(nsName[0]) strcat(temp, "::");
601 strcat(temp, nsName);
602 strcpy(nsName, temp);
605 // Generate Class Page
606 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
609 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
610 tag = (uint)nameSpace;
611 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);
615 tag = (uint)((!module || !module.name || !strcmp(nsName, "ecere::com") ? null : module));
616 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
620 ns = nameSpace->parent;
621 while(ns && ns->name)
623 strcpy(temp, ns->name);
624 if(nsName[0]) strcat(temp, "::");
625 strcat(temp, nsName);
626 strcpy(nsName, temp);
630 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
634 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
637 f.Printf($"<H3>Description</H3><br><br>\n");
640 char fileName[MAX_LOCATION];
641 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
642 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
644 f.Printf("</a><br><br>");
647 f.Printf("%s<br><br>", desc);
652 if(nameSpace->nameSpaces.first)
655 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
657 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
660 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
661 f.Printf("<TABLE>\n");
665 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);
670 char fileName[MAX_LOCATION];
671 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
672 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
674 f.Printf("</a></TD>");
677 f.Printf("<TD valign=top height=22> %s</TD>", desc);
680 f.Printf("</TR><br>\n");
683 f.Printf("</TABLE><br>\n");
686 if(nameSpace->classes.first)
689 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
691 Class cl = link.data;
692 if(!cl.templateClass)
694 char * desc = ReadDoc(module, classDoc, cl, description, null);
698 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
699 f.Printf("<TABLE>\n");
705 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);
710 char fileName[MAX_LOCATION];
711 FigureFileName(fileName, module, classDoc, cl, description, null);
712 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
714 f.Printf("</a></TD>");
717 f.Printf("<TD valign=top height=22>%s</TD>", desc);
724 f.Printf("</TABLE><br>\n");
727 if(nameSpace->functions.first)
730 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
732 GlobalFunction function = link.data;
733 char * desc = ReadDoc(module, functionDoc, function, description, null);
734 char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
735 if(name) name += 2; else name = function.name;
738 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
739 f.Printf("<TABLE>\n");
743 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);
748 char fileName[MAX_LOCATION];
749 FigureFileName(fileName, module, functionDoc, function, description, null);
750 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
752 f.Printf("</a></TD>");
755 f.Printf("<TD valign=top height=22> %s</TD>", desc);
758 f.Printf("</TR><br>\n");
761 f.Printf("</TABLE><br>\n");
764 if(nameSpace->defines.first)
767 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
769 DefinedExpression def = link.data;
770 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
773 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
774 f.Printf("<TABLE>\n");
778 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);
779 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
784 char fileName[MAX_LOCATION];
785 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
786 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
788 f.Printf("</a></TD>");
791 f.Printf("<TD valign=top height=22> %s</TD>", desc);
794 f.Printf("</TR><br>\n");
797 f.Printf("</TABLE><br>\n");
800 f.Printf("</FONT></BODY></HTML>\n");
804 class APIPageClass : APIPage
813 NameSpace * GetNameSpace()
818 void Generate(File f)
824 char nsName[1024], temp[1024];
825 NameSpace * ns = cl.nameSpace;
826 Module module = cl.module;
829 while(ns && ns->name)
831 strcpy(temp, ns->name);
832 if(nsName[0]) strcat(temp, "::");
833 strcat(temp, nsName);
834 strcpy(nsName, temp);
837 // Generate Class Page
838 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
839 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
841 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);
843 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
846 char * classType = null;
850 classType = $"Bit Collection";
853 classType = $"Enumeration";
856 classType = $"Structure";
859 classType = $"Class";
862 classType = $"Class (No header)";
868 classType = $"Basic Data Type";
871 f.Printf($"Type: %s<br>\n", classType);
874 if(cl.type != systemClass && cl.base)
876 f.Printf($"Base Class: ");
877 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
879 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
881 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
882 f.Printf("%s", cl.dataTypeString);
884 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
889 char * desc = ReadDoc(module, classDoc, cl, description, null);
892 f.Printf($"<br><H3>Description</H3><br><br>\n");
895 char fileName[MAX_LOCATION];
896 FigureFileName(fileName, module, classDoc, cl, description, null);
897 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
899 f.Printf("</a><br><br>");
902 f.Printf("%s<br><br>", desc);
907 if(cl.type == enumClass)
909 EnumClassData enumeration = (EnumClassData)cl.data;
910 if(enumeration.values.first)
914 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
915 f.Printf("<TABLE>\n");
917 for(item = enumeration.values.first; item; item = item.next)
919 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
920 bool needClass = true;
923 char tempString[1024];
925 while(base.type == enumClass) base = base.base;
927 if(base.type == systemClass ||
928 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
931 base.dataType = ProcessTypeString(base.dataTypeString, false);
933 if(base.dataType.kind != classType)
938 PrintType(base.dataType, string, false, true);
939 classSym = FindClass(string);
940 dataClass = classSym ? classSym.registered : null;
943 dataClass = base.dataType._class ? base.dataType._class.registered : null;
949 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);
950 if(dataClass.type == systemClass)
953 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
956 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
958 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
960 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
965 char fileName[MAX_LOCATION];
966 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
967 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
969 f.Printf("</a></TD>");
972 f.Printf("<TD valign=top height=22>%s</TD>", desc);
977 f.Printf("</TABLE><BR>\n");
981 if(cl.conversions.first)
983 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
984 f.Printf("<TABLE>\n");
985 for(prop = cl.conversions.first; prop; prop = prop.next)
987 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
989 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
992 Type type = ProcessTypeString(prop.name, false);
993 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
994 if(name) name += 2; else name = prop.name;
999 DocPrintType(type, string, true, false);
1001 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1006 char fileName[MAX_LOCATION];
1007 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1008 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1010 f.Printf("</a></TD>");
1013 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1017 f.Printf("</TR>\n");
1022 f.Printf("</TABLE><br>\n");
1025 if(cl.membersAndProperties.first)
1028 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1030 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1034 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1035 f.Printf("<TABLE>\n");
1041 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1043 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1047 DocPrintType(prop.dataType, string, true, false);
1049 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);
1050 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1055 char fileName[MAX_LOCATION];
1056 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1057 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1059 f.Printf("</a></TD>");
1062 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1065 f.Printf("</TR>\n");
1069 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1074 f.Printf("</TABLE><br>\n");
1077 if(cl.methods.first)
1081 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1083 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1085 char * desc = ReadDoc(module, methodDoc, method, description, null);
1088 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1089 f.Printf("<TABLE>\n");
1092 if(!method.dataType)
1093 ProcessMethodType(method);
1096 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);
1101 char fileName[MAX_LOCATION];
1102 FigureFileName(fileName, module, methodDoc, method, description, null);
1103 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1105 f.Printf("</a></TD>");
1108 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1111 f.Printf("</TR><br>\n");
1115 f.Printf("</TABLE><br>\n");
1117 // Non-Virtual Methods
1119 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1121 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1123 char * desc = ReadDoc(module, methodDoc, method, description, null);
1126 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1127 f.Printf("<TABLE>\n");
1131 if(!method.dataType)
1132 ProcessMethodType(method);
1135 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);
1140 char fileName[MAX_LOCATION];
1141 FigureFileName(fileName, module, methodDoc, method, description, null);
1142 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1144 f.Printf("</a></TD>");
1147 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1151 f.Printf("</TR><br>\n");
1155 f.Printf("</TABLE><br>\n");
1158 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1161 f.Printf($"<H3>Usage</H3><br>\n");
1164 char fileName[MAX_LOCATION];
1165 FigureFileName(fileName, module, classDoc, cl, usage, null);
1166 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1171 f.Printf("<br>%s\n", usageDoc);
1172 f.Printf("<br><br>\n");
1177 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1180 f.Printf($"<H3>Example</H3><br>\n");
1181 f.Printf($"<FONT face=\"Courier New\">\n");
1182 f.Printf("<br><TABLE>\n");
1185 char fileName[MAX_LOCATION];
1186 FigureFileName(fileName, module, classDoc, cl, example, null);
1187 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1189 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1192 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1194 f.Printf("</TABLE></FONT>\n");
1200 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1204 f.Printf($"<H3>Remarks</H3><br>\n");
1207 char fileName[MAX_LOCATION];
1208 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1209 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1214 f.Printf("<br>%s\n", remarksDoc);
1215 f.Printf("<br><br>\n");
1220 if(cl.type != systemClass)
1224 for(c = cl.derivatives.first; c; c = c.next)
1226 Class deriv = c.data;
1227 // TO VERIFY: Does this properly check public status?
1228 if(eSystem_FindClass(componentsApp, deriv.fullName))
1232 f.Printf($"<H3>Derived Classes</H3><br>\n");
1238 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1242 f.Printf("<br><br>\n");
1245 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1248 f.Printf($"<H3>See Also</H3><br>\n");
1251 char fileName[MAX_LOCATION];
1252 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1253 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1258 f.Printf("<br>%s\n", seeAlsoDoc);
1259 f.Printf("<br><br>\n");
1263 f.Printf("</FONT></BODY></HTML>\n");
1267 class APIPageMethod : APIPage
1273 return method._class.module;
1276 NameSpace * GetNameSpace()
1278 return method._class.nameSpace;
1281 void Generate(File f)
1283 Class cl = method._class;
1285 Module module = cl.module;
1287 char nsName[1024], temp[1024];
1288 NameSpace * ns = cl.nameSpace;
1291 while(ns && ns->name)
1293 strcpy(temp, ns->name);
1294 if(nsName[0]) strcat(temp, "::");
1295 strcat(temp, nsName);
1296 strcpy(nsName, temp);
1300 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1301 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1303 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);
1305 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1306 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1307 if(method.dataType.staticMethod)
1309 f.Printf($"this pointer class: None<br>\n");
1311 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1313 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);
1316 // Generate Method Page
1318 if(!method.dataType.name)
1319 method.dataType.name = CopyString(method.name);
1320 DocPrintType(method.dataType, string, true, false);
1321 f.Printf("<br>%s", string);
1324 char * desc = ReadDoc(module, methodDoc, method, description, null);
1327 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1330 char fileName[MAX_LOCATION];
1331 FigureFileName(fileName, module, methodDoc, method, description, null);
1332 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1337 f.Printf("%s", desc);
1342 f.Printf("<br><br>\n");
1343 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1345 f.Printf($"<H3>Parameters</H3><br><br>\n");
1347 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1348 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1350 f.Printf("<TABLE valign=center>\n");
1353 for(param = method.dataType.params.first; param; param = param.next)
1355 // ADD DESCRIPTION HERE
1356 if(param.kind != voidType)
1358 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1361 DocPrintType(param, string, false, false);
1363 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1364 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1369 char fileName[MAX_LOCATION];
1370 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1371 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1373 f.Printf("</a></TD>\n");
1376 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1380 f.Printf("</TR>\n");
1383 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1385 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1386 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1388 f.Printf("<TR><TD> </TD></TR>");
1391 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1393 DocPrintType(method.dataType.returnType, string, false, false);
1394 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1399 char fileName[MAX_LOCATION];
1400 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1401 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1403 f.Printf("</a> </TD>\n");
1406 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1409 f.Printf("</TR>\n");
1410 f.Printf("</TABLE>\n");
1412 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1413 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1415 f.Printf("</TABLE><br>\n");
1418 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1421 f.Printf($"<H3>Usage</H3><br>\n");
1424 char fileName[MAX_LOCATION];
1425 FigureFileName(fileName, module, methodDoc, method, usage, null);
1426 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1431 f.Printf("<br>%s\n", usageDoc);
1432 f.Printf("<br><br>\n");
1437 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1440 f.Printf($"<H3>Example</H3><br>\n");
1441 f.Printf($"<FONT face=\"Courier New\">\n");
1442 f.Printf("<br><TABLE>\n");
1445 char fileName[MAX_LOCATION];
1446 FigureFileName(fileName, module, methodDoc, method, example, null);
1447 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1449 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1452 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1453 f.Printf("</TABLE></FONT>\n");
1459 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1462 f.Printf($"<H3>Remarks</H3><br>\n");
1465 char fileName[MAX_LOCATION];
1466 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1467 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1472 f.Printf("<br>%s\n", method, remarksDoc);
1473 f.Printf("<br><br>\n");
1478 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1481 f.Printf($"<H3>See Also</H3><br>\n");
1484 char fileName[MAX_LOCATION];
1485 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1486 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1491 f.Printf("<br>%s\n", method, seeAlsoDoc);
1493 f.Printf("<br><br>\n");
1497 f.Printf("</FONT></BODY></HTML>\n");
1501 class APIPageFunction : APIPage
1503 GlobalFunction function;
1507 return function.module;
1510 NameSpace * GetNameSpace()
1512 return function.nameSpace;
1515 void Generate(File f)
1518 Module module = function.module;
1520 char nsName[1024], temp[1024];
1521 NameSpace * ns = function.nameSpace;
1524 while(ns && ns->name)
1526 strcpy(temp, ns->name);
1527 if(nsName[0]) strcat(temp, "::");
1528 strcat(temp, nsName);
1529 strcpy(nsName, temp);
1533 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1534 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1536 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);
1539 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1541 if(!function.dataType)
1542 function.dataType = ProcessTypeString(function.dataTypeString, false);
1544 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1546 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);
1549 // Generate Method Page
1551 if(!function.dataType.name)
1552 function.dataType.name = CopyString(function.name);
1553 DocPrintType(function.dataType, string, true, false);
1554 f.Printf("<br>%s", string);
1557 char * desc = ReadDoc(module, functionDoc, function, description, null);
1560 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1563 char fileName[MAX_LOCATION];
1564 FigureFileName(fileName, module, functionDoc, function, description, null);
1565 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1570 f.Printf("%s", desc);
1574 f.Printf("<br><br>\n");
1575 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1577 f.Printf($"<H3>Parameters</H3><br><br>\n");
1579 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1580 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1582 f.Printf("<TABLE valign=center>\n");
1585 for(param = function.dataType.params.first; param; param = param.next)
1587 // ADD DESCRIPTION HERE
1588 if(param.kind != voidType)
1590 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1593 DocPrintType(param, string, false, false);
1595 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1596 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1601 char fileName[MAX_LOCATION];
1602 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1603 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1606 f.Printf("</a> </TD>\n");
1609 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1612 f.Printf("</TR>\n");
1615 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1617 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1618 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1620 f.Printf("<TR><TD> </TD></TR>");
1623 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1625 DocPrintType(function.dataType.returnType, string, false, false);
1626 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1631 char fileName[MAX_LOCATION];
1632 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1633 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1635 f.Printf("</a> </TD>\n");
1638 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1641 f.Printf("</TR>\n");
1642 f.Printf("</TABLE>\n");
1644 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1645 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1647 f.Printf("</TABLE><br>\n");
1650 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1653 f.Printf($"<H3>Usage</H3><br>\n");
1656 char fileName[MAX_LOCATION];
1657 FigureFileName(fileName, module, functionDoc, function, usage, null);
1658 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1663 f.Printf("<br>%s\n", usageDoc);
1664 f.Printf("<br><br>\n");
1669 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1672 f.Printf($"<H3>Example</H3><br>\n");
1673 f.Printf($"<FONT face=\"Courier New\">\n");
1674 f.Printf("<br><TABLE>\n");
1677 char fileName[MAX_LOCATION];
1678 FigureFileName(fileName, module, functionDoc, function, example, null);
1679 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1681 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1684 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1685 f.Printf("</TABLE></FONT>\n");
1691 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1694 f.Printf($"<H3>Remarks</H3><br>\n");
1697 char fileName[MAX_LOCATION];
1698 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1699 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1704 f.Printf("<br>%s\n", remarksDoc);
1705 f.Printf("<br><br>\n");
1710 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1713 f.Printf($"<H3>See Also</H3><br>\n");
1716 char fileName[MAX_LOCATION];
1717 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1718 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1723 f.Printf("<br>%s\n", seeAlsoDoc);
1724 f.Printf("<br><br>\n");
1728 f.Printf("</FONT></BODY></HTML>\n");
1732 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, char * parentName, bool showPrivate)
1736 NameSpace * nameSpace = mainNameSpace;
1738 DataRow classesRow = null;
1739 DataRow functionsRow = null, definesRow = null;
1742 char fileName[MAX_LOCATION];
1744 strcpy(nsName, parentName ? parentName : "");
1748 strcat(nsName, "::");
1749 strcat(nsName, nameSpace->name);
1754 row = parentRow.AddRow();
1755 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1756 row.tag = (int)nameSpace;
1757 row.icon = mainForm.icons[typeNameSpace];
1761 // "Global NameSpace"
1763 page = parentRow.GetData(null);
1769 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1771 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1772 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1774 if(comNameSpace != null)
1776 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1778 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1780 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1785 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1787 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1789 if(nameSpace->classes.first)
1793 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1796 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1798 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1799 AddClass(classesRow, module, cl, nsName, showPrivate);
1806 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
1808 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1810 if(nameSpace->functions.first)
1814 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
1817 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
1819 char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
1821 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
1822 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int)fn;
1829 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
1831 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1833 if(nameSpace->defines.first)
1837 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
1840 //if(def.module == module)
1842 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
1844 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
1845 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int)def;
1853 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
1857 if(!member.dataType)
1858 member.dataType = ProcessTypeString(member.dataTypeString, false);
1862 DocPrintType(member.dataType, string, true, false);
1864 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
1865 for(c = 0; c<indent; c++)
1866 f.Printf(" ");
1867 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
1868 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
1869 if(member.type == normalMember)
1871 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
1876 char fileName[MAX_LOCATION];
1877 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
1878 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1880 f.Printf("</a></TD>");
1883 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1888 f.Printf("<TD valign=top height=22></TD>");
1890 if(member.type != normalMember)
1892 DataMember subMember;
1893 for(subMember = member.members.first; subMember; subMember = subMember.next)
1895 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
1897 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
1901 f.Printf("</TR><br>\n");
1904 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
1907 if(member.type == normalMember)
1909 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
1910 row.tag = (int)member;
1915 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
1916 row.icon = mainForm.icons[typeData];
1917 row.tag = (int)member;
1919 for(m = member.members.first; m; m = m.next)
1921 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
1922 AddDataMember(row, page, m);
1927 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
1929 char fileName[MAX_LOCATION];
1936 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
1937 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
1940 row = parentRow.AddRow();
1941 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
1943 row.collapsed = true;
1944 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
1947 if(cl.methods.first)
1949 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1951 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
1954 if(!method.dataType)
1955 ProcessMethodType(method);
1956 if(method.type == virtualMethod)
1958 if(method.dataType.thisClass)
1960 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
1961 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
1962 mRow.tag = (int)method;
1966 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
1967 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
1968 mRow.tag = (int)method;
1973 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
1974 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
1975 mRow.tag = (int)method;
1981 if(cl.membersAndProperties.first)
1983 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1985 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1988 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1992 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
1993 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
1994 mRow.tag = (int)prop;
1998 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
1999 AddDataMember(membersRow, page, (DataMember)prop);
2005 if(cl.conversions.first)
2007 for(prop = cl.conversions.first; prop; prop = prop.next)
2011 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2012 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2013 if(name) name += 2; else name = prop.name;
2014 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2015 mRow.tag = (int)prop;
2018 if(cl.type == enumClass)
2020 EnumClassData enumeration = (EnumClassData)cl.data;
2022 for(item = enumeration.values.first; item; item = item.next)
2025 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2026 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2027 mRow.tag = (int)item;
2032 class MainForm : Window
2034 size = { 1000, 600 };
2036 borderStyle = sizable;
2039 nativeDecorations = true;
2040 icon = { ":documentorIcon.png" };
2041 text = $"API Documentation Browser";
2043 BitmapResource icons[CodeObjectType];
2048 for(c = 0; c < CodeObjectType::enumSize; c++)
2050 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2052 browser.AddField(DataField { dataType = class(APIPage) });
2057 Menu fileMenu { menu, $"File", f };
2058 Array<FileFilter> fileFilters
2060 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2061 { $"eC Symbol files (*.sym)", "sym" }
2064 FileDialog fileDialog
2066 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2068 MenuItem fileOpenItem
2070 fileMenu, $"Open...", o, ctrlO;
2072 bool NotifySelect(MenuItem selection, Modifiers mods)
2074 if(fileDialog.Modal() == ok)
2076 OpenModule(fileDialog.filePath);
2081 MenuItem fileSettingsItem
2083 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2085 bool NotifySelect(MenuItem selection, Modifiers mods)
2087 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2097 MenuDivider { fileMenu };
2098 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2100 void OpenModule(char * filePath)
2102 char extension[MAX_EXTENSION];
2103 Module module = null;
2104 static char symbolsDir[MAX_LOCATION];
2106 FreeContext(globalContext);
2107 FreeExcludedSymbols(excludedSymbols);
2108 ::defines.Free(FreeModuleDefine);
2109 imports.Free(FreeModuleImport);
2111 FreeGlobalData(globalData);
2112 FreeTypeData(componentsApp);
2114 delete componentsApp;
2116 SetGlobalContext(globalContext);
2117 componentsApp = __ecere_COM_Initialize(false, 1, null);
2118 SetPrivateModule(componentsApp);
2120 StripLastDirectory(filePath, symbolsDir);
2121 SetSymbolsDir(symbolsDir);
2123 GetExtension(filePath, extension);
2125 mainForm.browser.Clear();
2127 ImportModule(filePath, normalImport, publicAccess, false);
2129 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll"))
2130 componentsApp.name = CopyString(filePath);
2132 for(module = componentsApp.allModules.first; module; module = module.next)
2134 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2138 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2139 AddComponents(componentsApp, false);
2141 for(module = componentsApp.allModules.first; module; module = module.next)
2143 if(module.name && (!strcmp(module.name, filePath)))
2146 if(!module) module = componentsApp;
2147 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int)module));
2149 SetSymbolsDir(null);
2154 this, anchor = { left = 0, top = 0, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2155 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2158 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2160 APIPage page = row.GetData(null);
2161 if(view.edit) view.OnLeftButtonDown(0,0,0);
2162 if(page && page.page) page = page.page;
2164 view.PositionCaret(true);
2165 if(page != view.page)
2167 Window activeChild = this.activeChild;
2172 activeChild.Activate();
2174 else if(!view.created)
2178 page = row.GetData(null);
2179 if(page && page.page)
2183 case 1: view.GoToAnchor("Classes"); break;
2184 case 2: view.GoToAnchor("Functions"); break;
2185 case 3: view.GoToAnchor("Definitions"); break;
2186 case 4: view.GoToAnchor("VirtualMethods"); break;
2187 case 5: view.GoToAnchor("Methods"); break;
2188 case 6: view.GoToAnchor("Members"); break;
2189 case 7: view.GoToAnchor("Conversions"); break;
2190 case 8: view.GoToAnchor("EnumerationValues"); break;
2194 sprintf(hex, "%p", row.tag);
2195 view.GoToAnchor(hex);
2201 view.SetScrollPosition(0, 0);
2209 this, anchor = { top = 0, bottom = 0, right = 0 };
2214 this, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2217 bool OnClose(bool parentClosing)
2220 view.OnLeftButtonDown(0,0,0);
2226 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2227 //mainForm.OpenModule("ec");
2228 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2229 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2231 int index = mainForm.browser.currentRow.index;
2232 int rowHeight = mainForm.browser.rowHeight;
2233 int height = mainForm.browser.clientSize.h;
2235 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2241 class EditDialog : Window
2243 borderStyle = sizable;
2244 size = { 600, 400 };
2249 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2253 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2257 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2261 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2262 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2264 class HelpView : HTMLView
2268 hasVertScroll = true;
2269 hasHorzScroll = true;
2271 char editString[MAX_LOCATION];
2277 page = mainForm.browser.currentRow.GetData(null);
2282 char docFile[MAX_LOCATION];
2284 Module module = page ? page.GetModule() : null;
2285 NameSpace * ns = page ? page.GetNameSpace() : null;
2287 sprintf(docFile, "%s/%s.eCdoc", settings.docDir, (!module || !module.name || (ns && ns->name && !strcmp(ns->name, "namespaces/ecere/namespaces/com"))) ? "ecereCOM" : module.name);
2289 if(FileExists(docFile))
2291 archive = ArchiveOpen(docFile, { true } );
2292 readOnly = archive == null;
2298 archive = ArchiveOpen(docFile, { true } );
2301 // Must create root directory on archive creation
2302 ArchiveDir dir = archive.OpenDirectory("", null, replace);
2314 GoToAnchor(page.label);
2316 if(page.page) page = page.page;
2319 return HTMLView::OnCreate();
2328 char archiveFile[MAX_LOCATION];
2329 char fileName[MAX_FILENAME];
2330 char directory[MAX_LOCATION];
2332 Archive archive = null;
2333 if(SplitArchivePath(editString, archiveFile, &location))
2335 GetLastDirectory(location, fileName);
2336 StripLastDirectory(location, directory);
2337 archive = ArchiveOpen(archiveFile, { true } );
2341 ArchiveDir dir = archive ? archive.OpenDirectory(directory, null, replace) : null;
2344 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2346 if(block.type == TEXT && block.textLen)
2354 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2356 if(block.type == BR)
2358 else if(block.type == TEXT)
2359 f.Write(block.text, 1, block.textLen);
2364 dir.AddFromFile(fileName, f, null, replace, 0, null, null);
2370 Block parent = textBlock.parent;
2371 while((block = parent.subBlocks.first))
2373 parent.subBlocks.Remove(block);
2376 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
2377 textBlock.text = CopyString($"[Add Text]");
2378 textBlock.textLen = strlen(textBlock.text);
2379 parent.subBlocks.Add(textBlock);
2387 PositionCaret(true);
2393 bool OnLeftButtonDown(int x, int y, Modifiers mods)
2397 if(edit && (!textBlock || overLink != textBlock.parent))
2401 HTMLView::OnLeftButtonDown(x, y, mods);
2402 selPosition = curPosition = 0;
2403 selBlock = textBlock;
2407 result = HTMLView::OnLeftButtonDown(x, y, mods);
2409 if(!edit && clickedLink)
2412 if(clickedLink == overLink && clickedLink.href)
2414 if(OnOpen(clickedLink.href))
2422 if(textBlock && overLink == textBlock.parent)
2424 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2425 selBlock = textBlock;
2426 PositionCaret(true);
2434 bool OnLeftButtonUp(int x, int y, Modifiers mods)
2436 if(!edit || !textBlock || clickedLink != textBlock.parent)
2438 HTMLView::OnLeftButtonUp(x, y, mods);
2441 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
2442 selBlock = textBlock;
2443 PositionCaret(true);
2454 bool OnMouseMove(int x, int y, Modifiers mods)
2456 if(edit && selecting)
2458 curPosition = TextPosFromPoint(x, y, &textBlock, true);
2459 PositionCaret(true);
2462 return HTMLView::OnMouseMove(x, y, mods);
2465 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
2467 if(edit && textBlock)
2473 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
2474 selBlock = textBlock;
2475 for(c = curPosition; c >= 0; c--)
2478 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
2479 ch = UTF8GetChar(textBlock.text + c, &numBytes);
2480 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2486 for(c = start; c < textBlock.textLen; c += numBytes)
2488 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
2489 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2492 selPosition = start;
2495 PositionCaret(true);
2503 bool OnOpen(char * href)
2505 if(!strncmp(href, "api://", 6))
2507 int tag = (uint)strtoul(href + 6, null, 16);
2508 DataRow row = mainForm.browser.FindSubRow(tag);
2512 mainForm.browser.SelectRow(row);
2513 while((row = row.parent))
2514 row.collapsed = false;
2515 row = mainForm.browser.currentRow;
2516 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
2519 else if(!strncmp(href, "edit://", 7))
2522 int startX = clickedLink.startX, startY = clickedLink.startY;
2523 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
2525 if(block.type == TEXT) startX = block.startX, startY = block.startY;
2526 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
2528 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
2530 display.FontExtent(block.font.font, " ", 1, null, &th);
2533 block.parent.subBlocks.Insert(null, newBlock);
2538 block.parent.subBlocks.Insert(block, newBlock);
2539 startY += block.prev.height;
2541 newBlock.startX = startX;
2542 newBlock.startY = startY;
2543 newBlock.text = new0 char[1];
2547 textBlock = (Block)clickedLink.subBlocks.first;
2548 if(!strcmp(textBlock.text, $"[Add Text]"))
2550 textBlock.text[0] = 0;
2551 textBlock.textLen = 0;
2554 strcpy(editString, href + 7);
2555 selPosition = curPosition = 0;
2556 selBlock = textBlock;
2559 // PositionCaret(true);
2566 void DeleteSelection()
2568 if(textBlock != selBlock || curPosition != selPosition)
2570 if(textBlock == selBlock)
2572 // Within same block
2573 int start = Min(curPosition, selPosition);
2574 int end = Max(curPosition, selPosition);
2575 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
2576 textBlock.textLen -= end-start;
2577 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
2578 curPosition = start;
2579 selPosition = start;
2583 int startSel, endSel;
2584 Block startSelBlock = null, endSelBlock = null, b, next;
2586 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2588 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
2589 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
2591 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
2592 for(b = startSelBlock.next; b; b = next)
2594 bool isEnd = b == endSelBlock;
2595 next = GetNextBlock(b);
2596 b.parent.subBlocks.Remove(b);
2601 textBlock = startSelBlock;
2602 selBlock = startSelBlock;
2603 curPosition = startSel;
2604 selPosition = startSel;
2608 PositionCaret(true);
2613 String GetSelectionString()
2615 String selection = null;
2616 if(textBlock == selBlock)
2618 // Within same block
2619 int start = Min(curPosition, selPosition);
2620 int end = Max(curPosition, selPosition);
2621 int len = end - start;
2622 selection = new char[len + 1];
2623 memcpy(selection, textBlock.text + start, len);
2628 int startSel, endSel;
2629 Block startSelBlock = null, endSelBlock = null, b;
2632 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2635 for(b = startSelBlock; b; b = GetNextBlock(b))
2637 int start = (b == startSelBlock) ? startSel : 0;
2638 int end = (b == endSelBlock) ? endSel : b.textLen;
2639 int len = end - start;
2641 if(b == endSelBlock)
2643 else if(b.type == TEXT)
2647 selection = new char[totalLen + 1];
2649 for(b = startSelBlock; b; b = GetNextBlock(b))
2651 int start = (b == startSelBlock) ? startSel : 0;
2652 int end = (b == endSelBlock) ? endSel : b.textLen;
2653 int len = end - start;
2654 memcpy(selection + totalLen, b.text + start, len);
2656 if(b == endSelBlock)
2658 else if(b.type == TEXT)
2659 selection[totalLen++] = '\n';
2661 selection[totalLen] = 0;
2666 void CopySelection()
2668 String s = GetSelectionString();
2671 int len = strlen(s);
2673 if(cb.Allocate(len + 1))
2675 memcpy(cb.text, s, len + 1);
2683 bool OnKeyDown(Key key, unichar ch)
2690 OnLeftButtonDown(0,0,0);
2692 case Key { end, shift = true }:
2694 curPosition = textBlock.textLen;
2697 selPosition = curPosition;
2698 selBlock = textBlock;
2700 PositionCaret(true);
2703 case Key { home, shift = true }:
2708 selPosition = curPosition;
2709 selBlock = textBlock;
2711 PositionCaret(true);
2714 case Key { home, ctrl = true, shift = true }:
2717 while(textBlock.prev)
2718 textBlock = textBlock.prev.prev;
2721 selPosition = curPosition;
2722 selBlock = textBlock;
2724 PositionCaret(true);
2727 case Key { end, ctrl = true, shift = true }:
2729 while(textBlock.next && textBlock.next.next)
2730 textBlock = textBlock.next.next;
2731 curPosition = textBlock.textLen;
2734 selPosition = curPosition;
2735 selBlock = textBlock;
2737 PositionCaret(true);
2743 return HTMLView::OnKeyDown(key, ch);
2747 bool OnKeyHit(Key key, unichar ch)
2753 case Key { up, shift = true }:
2756 if(caretY == textBlock.startY)
2760 textBlock = textBlock.prev.prev;
2761 curPosition = Min(curPosition, textBlock.textLen);
2764 selPosition = curPosition;
2765 selBlock = textBlock;
2768 PositionCaret(false);
2778 int sx = textBlock.startX, sy = textBlock.startY;
2779 char * text = textBlock.text;
2781 Block block = textBlock;
2782 while(block && block.type != TD) block = block.parent;
2785 Block table = block;
2786 while(table && table.type != TABLE) table = table.parent;
2788 maxW = block.w - 2* table.cellPadding;
2790 maxW = clientSize.w - 10 - sx;
2793 maxW = clientSize.w - 10 - sx;
2794 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
2798 int startPos = textPos;
2801 bool lineComplete = false;
2802 for(; textPos<textBlock.textLen && !lineComplete;)
2806 char * nextSpace = strchr(text + textPos, ' ');
2809 len = (nextSpace - (text + textPos)) + 1;
2811 len = textBlock.textLen - textPos;
2813 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
2815 if(x + width + w > maxW && x > 0)
2817 lineComplete = true;
2827 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
2830 curPosition = textPos;
2831 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
2834 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
2835 len = curPosition - startPos;
2836 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
2840 selPosition = curPosition;
2841 selBlock = textBlock;
2845 PositionCaret(false);
2849 if(sy == caretY - th || textPos == textBlock.textLen)
2851 if(textPos != textBlock.textLen)
2853 int c = textPos - 1;
2854 while(c > 0 && text[c] == ' ') c--;
2855 curPosition = c + 1;
2858 selPosition = curPosition;
2859 selBlock = textBlock;
2865 curPosition = textBlock.textLen;
2868 selPosition = curPosition;
2869 selBlock = textBlock;
2873 PositionCaret(false);
2877 sx = textBlock.startX;
2878 } while(textPos < textBlock.textLen);
2883 case Key { down, shift = true }:
2888 int sx = textBlock.startX, sy = textBlock.startY;
2889 char * text = textBlock.text;
2891 Block block = textBlock;
2892 while(block && block.type != TD) block = block.parent;
2895 Block table = block;
2896 while(table && table.type != TABLE) table = table.parent;
2898 maxW = block.w - 2* table.cellPadding;
2900 maxW = clientSize.w - 10 - sx;
2903 maxW = clientSize.w - 10 - sx;
2904 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
2906 while(!textPos || textPos < textBlock.textLen)
2908 int startPos = textPos;
2911 bool lineComplete = false;
2912 for(; (textPos < textBlock.textLen) && !lineComplete;)
2916 char * nextSpace = strchr(text + textPos, ' ');
2919 len = (nextSpace - (text + textPos)) + 1;
2921 len = textBlock.textLen - textPos;
2923 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
2925 if(x + width + w > maxW && x > 0)
2927 lineComplete = true;
2937 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
2939 curPosition = textPos;
2941 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
2944 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
2945 len = curPosition - startPos;
2946 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
2950 selPosition = curPosition;
2951 selBlock = textBlock;
2954 PositionCaret(false);
2960 curPosition = textBlock.textLen;
2963 selPosition = curPosition;
2964 selBlock = textBlock;
2967 PositionCaret(false);
2970 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
2974 textBlock = textBlock.next.next;
2975 sy = textBlock.startY;
2976 sx = textBlock.startX;
2977 text = textBlock.text;
2982 sx = textBlock.startX;
2986 /*if(textBlock.next && textBlock.next.next)
2988 textBlock = textBlock.next.next;
2989 selPosition = curPosition = Min(curPosition, textBlock.textLen);
2990 selBlock = textBlock;
2991 PositionCaret(false);
2995 case Key { right, shift = true, ctrl = true }:
2998 bool foundAlpha = false;
3000 Block line, lastLine;
3003 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3005 int start = (line == textBlock) ? curPosition : 0;
3007 for(c = start; c < line.textLen; c++)
3009 char ch = line.text[c];
3010 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3011 if(key.shift ? isAlUnder : !isAlUnder)
3025 selPosition = curPosition;
3026 selBlock = textBlock;
3030 PositionCaret(true);
3035 // No next word found,
3036 if(!found && (c != curPosition || line != textBlock))
3040 lastC = line.textLen-1;
3045 curPosition = line.textLen;
3048 selPosition = curPosition;
3049 selBlock = textBlock;
3054 PositionCaret(true);
3060 if(key.shift && found)
3062 curPosition = lastC+1;
3063 textBlock = lastLine;
3064 PositionCaret(true);
3069 case Key { left, ctrl = true, shift = true }:
3072 bool foundAlpha = false;
3074 Block line, lastLine;
3077 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3080 if(curPosition == 0 && line != textBlock)
3083 lastC = line.textLen;
3087 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3088 for(c = start; c>=0; c--)
3090 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3105 // No next word found,
3106 if(!found && curPosition > 0)
3116 textBlock = lastLine;
3117 curPosition = lastC;
3120 selPosition = curPosition;
3121 selBlock = textBlock;
3123 PositionCaret(true);
3128 case Key { right, shift = true }:
3130 if(curPosition < textBlock.textLen)
3132 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3135 selPosition = curPosition;
3136 selBlock = textBlock;
3138 PositionCaret(true);
3141 else if(textBlock.next && textBlock.next.next)
3143 textBlock = textBlock.next.next;
3147 selPosition = curPosition;
3148 selBlock = textBlock;
3150 PositionCaret(true);
3154 case Key { left, shift = true }:
3158 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3161 selPosition = curPosition;
3162 selBlock = textBlock;
3164 PositionCaret(true);
3167 else if(textBlock.prev)
3169 textBlock = textBlock.prev.prev;
3170 curPosition = textBlock.textLen;
3173 selPosition = curPosition;
3174 selBlock = textBlock;
3176 PositionCaret(true);
3182 if(textBlock == selBlock && curPosition == selPosition)
3186 int c = curPosition;
3188 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3189 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3190 textBlock.textLen -= nb;
3191 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3193 selPosition = curPosition;
3194 selBlock = textBlock;
3198 PositionCaret(true);
3201 else if(textBlock.prev)
3203 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3204 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3205 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3207 selPosition = curPosition = prevBlock.textLen;
3208 selBlock = textBlock;
3209 prevBlock.textLen += textBlock.textLen;
3210 textBlock.parent.subBlocks.Remove(prev);
3211 if(prev == selBlock)
3213 selBlock = textBlock;
3214 selPosition = curPosition;
3217 textBlock.parent.subBlocks.Remove(textBlock);
3218 if(textBlock == selBlock)
3220 selBlock = prevBlock;
3221 selPosition = curPosition;
3224 textBlock = prevBlock;
3228 PositionCaret(true);
3237 if(textBlock != selBlock || curPosition != selPosition)
3239 else if(textBlock.textLen > curPosition)
3241 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3242 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3243 textBlock.textLen -= nb;
3244 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3249 PositionCaret(true);
3252 else if(textBlock.next && textBlock.next.next)
3254 Block next = textBlock.next, nextBlock = textBlock.next.next;
3255 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3256 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3258 textBlock.textLen += nextBlock.textLen;
3259 textBlock.parent.subBlocks.Remove(next);
3260 if(next == selBlock)
3262 selBlock = textBlock;
3263 selPosition = curPosition;
3266 textBlock.parent.subBlocks.Remove(nextBlock);
3267 if(nextBlock == selBlock)
3269 selBlock = textBlock;
3270 selPosition = curPosition;
3276 PositionCaret(true);
3290 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3291 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3292 startY = textBlock.startY;
3293 startX = textBlock.startX;
3295 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3296 textBlock.parent.subBlocks.Insert(textBlock, block);
3297 textBlock.parent.subBlocks.Insert(block, newBlock);
3301 newBlock.textLen = textBlock.textLen - curPosition;
3302 newBlock.text = new char[newBlock.textLen+1];
3303 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3304 textBlock.textLen = curPosition;
3305 textBlock.text[curPosition] = 0;
3307 newBlock.startY = startY;
3308 newBlock.startX = startX;
3309 selPosition = curPosition = 0;
3314 textBlock = newBlock;
3315 selBlock = textBlock;
3316 PositionCaret(true);
3321 case Key { del, shift = true }:
3336 ClipBoard clipBoard { };
3337 if(clipBoard.Load())
3340 char * text = clipBoard.memory;
3348 parent = textBlock.parent;
3349 font = textBlock.font;
3354 if(ch == '\n' || ch == '\r' || !ch)
3356 int len = c - start;
3357 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
3358 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3359 memcpy(textBlock.text + curPosition, text + start, len);
3360 textBlock.textLen += len;
3362 selPosition = curPosition;
3363 selBlock = textBlock;
3366 Block block { type = BR, parent = parent, font = font };
3367 Block newBlock { type = TEXT, parent = parent, font = font };
3368 int startY = textBlock.startY, startX = textBlock.startX;
3371 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3372 textBlock.parent.subBlocks.Insert(textBlock, block);
3373 textBlock.parent.subBlocks.Insert(block, newBlock);
3377 newBlock.textLen = textBlock.textLen - curPosition;
3378 newBlock.text = new char[newBlock.textLen+1];
3379 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3380 textBlock.textLen = curPosition;
3381 textBlock.text[curPosition] = 0;
3383 newBlock.startY = startY;
3384 newBlock.startX = startX;
3385 selPosition = curPosition = 0;
3386 selBlock = textBlock;
3387 textBlock = newBlock;
3389 if(ch == '\r' && text[c+1] == '\n') c++;
3395 PositionCaret(true);
3403 // eC BUG HERE: (Should be fixed)
3404 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
3407 int len = UTF32toUTF8Len(&ch, 1, string, 5);
3412 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
3413 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3415 for(c = 0; c<len; c++)
3417 textBlock.text[curPosition] = string[c];
3418 textBlock.textLen++;
3421 selPosition = curPosition;
3422 selBlock = textBlock;
3425 //Clear(html.block);
3426 //CreateForms(html.block);
3431 PositionCaret(true);
3440 void OnResize(int width, int height)
3442 HTMLView::OnResize(width, height);
3443 PositionCaret(true);
3447 void PositionCaret(bool setCaretX)
3453 int sx = textBlock.startX, sy = textBlock.startY;
3454 char * text = textBlock.text;
3456 Block block = textBlock;
3457 while(block && block.type != TD) block = block.parent;
3460 Block table = block;
3461 while(table && table.type != TABLE) table = table.parent;
3463 maxW = block.w - 2* table.cellPadding;
3465 maxW = clientSize.w - 10 - sx;
3468 maxW = clientSize.w - 10 - sx;
3470 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3472 while(textPos < textBlock.textLen)
3474 int startPos = textPos;
3477 bool lineComplete = false;
3479 for(; textPos<textBlock.textLen && !lineComplete;)
3483 char * nextSpace = strchr(text + textPos, ' ');
3486 len = (nextSpace - (text + textPos)) + 1;
3488 len = textBlock.textLen - textPos;
3490 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3492 if(x + width + w > maxW && x > 0)
3494 lineComplete = true;
3507 if(curPosition < textPos || textPos == textBlock.textLen)
3509 int len = curPosition - startPos;
3510 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
3515 sx = textBlock.startX;
3520 SetCaret(sx, sy, th);
3522 Point scrollPos = scroll;
3523 bool doScroll = false;
3524 if(sy - scroll.y + th > clientSize.h)
3526 scrollPos.y = sy + th - clientSize.h;
3529 else if(sy - scroll.y < 0)
3534 if(sx - scroll.x + 10 > clientSize.w)
3536 scrollPos.x = sx + 10 - clientSize.w;
3539 else if(sx - scroll.x < 10)
3541 scrollPos.x = sx - 10;
3552 // Returns a character offset into the TextBlock from a window coordinate
3553 int TextPosFromPoint(int px, int py, Block * block, bool half)
3555 Block parentBlock = this.textBlock.parent;
3558 *block = this.textBlock;
3563 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
3565 int sx = textBlock.startX, sy = textBlock.startY;
3568 char * text = textBlock.text;
3570 Block b = textBlock;
3573 if(textBlock.type != TEXT) continue;
3575 while(b && b.type != TD) b = b.parent;
3579 while(table && table.type != TABLE) table = table.parent;
3581 maxW = b.w - 2* table.cellPadding;
3583 maxW = clientSize.w - 10 - sx;
3586 maxW = clientSize.w - 10 - sx;
3588 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
3589 //space = space/2+2;
3592 while(textPos < textBlock.textLen)
3594 int startPos = textPos;
3597 bool lineComplete = false;
3599 for(; textPos<textBlock.textLen && !lineComplete;)
3603 char * nextSpace = strchr(text + textPos, ' ');
3606 len = (nextSpace - (text + textPos)) + 1;
3608 len = textBlock.textLen - textPos;
3610 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3612 sx = x + textBlock.startX;
3613 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
3618 for(c = textPos; (ch = text[c]); c += numBytes)
3620 numBytes = UTF8_NUM_BYTES(ch);
3621 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
3622 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
3629 if(x + width + w > maxW && x > 0)
3631 lineComplete = true;
3644 if(/*py >= sy && */py < sy + th)
3647 return textBlock.textLen;
3652 result = textBlock.textLen;
3658 Application componentsApp;
3660 class Documentor : GuiApplication
3664 Platform os = GetRuntimePlatform();
3665 componentsApp = __ecere_COM_Initialize(false, 1, null);
3666 SetPrivateModule(componentsApp);
3667 SetGlobalContext(globalContext);
3668 SetExcludedSymbols(&excludedSymbols);
3669 SetDefines(&::defines);
3670 SetImports(&imports);
3672 SetGlobalData(globalData);
3674 settingsContainer.dataOwner = &settings;
3675 settingsContainer.Load();
3676 if(!settings.docDir || !settings.docDir[0] )
3678 if(os == win32) // if Windows OS then
3680 char programFilesDir[MAX_LOCATION];
3681 char appData[MAX_LOCATION];
3682 char homeDrive[MAX_LOCATION];
3683 char winDir[MAX_LOCATION];
3684 GetEnvironment("APPDATA", appData, sizeof(appData));
3685 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
3686 GetEnvironment("windir", winDir, sizeof(winDir));
3687 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
3689 PathCat(programFilesDir, "ECERE SDK\\doc");
3690 settings.docDir = programFilesDir;
3692 else if(homeDrive && homeDrive[0])
3694 PathCat(homeDrive, "ECERE SDK\\doc");
3695 settings.docDir = homeDrive;
3697 else if(winDir && winDir[0])
3699 PathCat(winDir, "..\\ECERE SDK\\doc");
3700 settings.docDir = winDir;
3703 settings.docDir = "C:\\ECERE SDK\\doc";
3705 else // if Os is Linux, or Mac OSX or something else
3706 settings.docDir = "/usr/share/ecere/doc/";
3707 settingsContainer.Save();
3713 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
3715 AddComponents(module, true);
3716 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int)module);
3717 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int)eSystem_FindClass(componentsApp, "Window"));
3718 while((row = row.parent))
3719 row.collapsed = false;
3723 commandThread.Create();
3727 bool Cycle(bool idle)
3730 mainForm.Destroy(0);
3739 console.CloseInput();
3740 console.CloseOutput();
3742 commandThread.Wait();
3745 FreeContext(globalContext);
3746 FreeExcludedSymbols(excludedSymbols);
3747 ::defines.Free(FreeModuleDefine);
3748 imports.Free(FreeModuleImport);
3750 FreeGlobalData(globalData);
3751 FreeTypeData(componentsApp);
3753 delete componentsApp;
3757 ConsoleFile console { };
3758 MainForm mainForm { };
3761 Thread commandThread
3768 console.GetLine(command, sizeof(command));
3769 if(!quit && command[0])
3772 if(!strcmpi(command, "Activate"))
3773 mainForm.Activate();
3774 else if(!strcmpi(command, "Quit"))