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 };
13 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
16 /*extern */int __ecereVMethodID_class_OnGetString;
23 a.OnGetString(null, null, null);
26 static bool editing = true;
28 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
30 static char * iconNames[CodeObjectType] =
32 "<:ecere>constructs/class.png",
33 "<:ecere>constructs/data.png",
34 "<:ecere>constructs/method.png",
35 "<:ecere>constructs/event.png",
36 "<:ecere>constructs/property.png",
37 "<:ecere>constructs/namespace.png",
38 "<:ecere>constructs/dataType.png",
39 "<:ecere>constructs/enumValue.png",
40 "<:ecere>constructs/dataPrivate.png",
41 "<:ecere>constructs/methodPrivate.png",
42 "<:ecere>constructs/propertyPrivate.png"
45 IDESettings settings { }; // instantiate the IDESettings class from the IDESettings.ec file. Do this at a global level so that all methods can access settings.
47 IDESettingsContainer settingsContainer
51 dataOwner = &settings;
54 // WARNING : This function expects a null terminated string since it recursively concatenate...
55 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
62 if(type._class && type._class.string)
65 strcat(string, type._class.string);
68 if(type._class.registered)
71 sprintf(hex, "%p", type._class.registered);
72 strcat(string, "<a href=\"api://");
74 strcat(string, "\" style=\"text-decoration: none;\">");
75 strcat(string, type._class.registered.name);
76 strcat(string, "</a>");
79 strcat(string, type._class.string);
86 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
87 if(funcType && funcType.kind == functionType)
90 DocPrintType(funcType.returnType, string, false, fullName);
92 if(printName || funcType.thisClass)
95 if(funcType.thisClass)
97 strcat(string, funcType.thisClass.string);
101 strcat(string, type.name);
103 strcat(string, ")(");
104 for(param = funcType.params.first; param; param = param.next)
106 DocPrintType(param, string, false, fullName);
107 if(param.next) strcat(string, ", ");
113 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
114 if(string[strlen(string)-1] == '(')
117 strcat(string, " *");
121 case voidType: strcat(string, "void"); break;
122 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
123 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
124 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
125 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
126 case floatType: strcat(string, "float"); break;
127 case doubleType: strcat(string, "double"); break;
131 strcat(string, "struct ");
132 strcat(string, type.enumName);
134 else if(type.typeName)
136 strcat(string, type.typeName);
141 strcat(string, "struct ");
142 strcat(string,"(unnamed)");
145 strcat(string, "struct {");
146 for(member = type.members.first; member; member = member.next)
148 DocPrintType(member, string, true, fullName);
157 strcat(string, "union ");
158 strcat(string, type.enumName);
160 else if(type.typeName)
162 strcat(string, type.typeName);
166 strcat(string, "union ");
167 strcat(string,"(unnamed)");
173 strcat(string, "enum ");
174 strcat(string, type.enumName);
176 else if(type.typeName)
178 strcat(string, type.typeName);
181 strcat(string, "enum");
188 strcat(string, "dllexport ");
189 DocPrintType(type.returnType, string, false, fullName);
193 // DANGER: Testing This
199 strcat(string, type.name);
202 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
203 if(name) name += 2; else name = type.name;
204 strcat(string, "<b>");
205 strcat(string, name);
206 strcat(string, "</b>");
219 for(param = type.params.first; param; param = param.next)
221 DocPrintType(param, string, true, fullName);
222 if(param.next) strcat(string, ", ");
231 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
232 if(funcType && funcType.kind == functionType)
235 DocPrintType(funcType.returnType, string, false, fullName);
236 strcat(string, "(*");
237 if(printName || funcType.thisClass)
240 if(funcType.thisClass)
242 strcat(string, funcType.thisClass.string);
243 strcat(string, "::");
246 strcat(string, type.name);
248 strcat(string, ")(");
249 for(param = funcType.params.first; param; param = param.next)
251 DocPrintType(param, string, false, fullName);
252 if(param.next) strcat(string, ", ");
258 char baseType[1024], size[256];
259 Type arrayType = type;
263 while(arrayType.kind == TypeKind::arrayType)
266 if(arrayType.enumClass)
267 strcat(size, arrayType.enumClass.string);
268 else if(arrayType.arraySizeExp)
269 PrintExpression(arrayType.arraySizeExp, size);
270 //sprintf(string, "%s[%s]", baseType, size);
273 arrayType = arrayType.arrayType;
275 _PrintType(arrayType, baseType, printName, printFunction, fullName);
276 strcat(string, baseType);
277 strcat(string, size);
281 DocPrintType(type.arrayType, baseType, printName, fullName);
283 strcpy(size, type.enumClass.string);
284 else if(type.arraySizeExp)
285 PrintExpression(type.arraySizeExp, size);
286 //sprintf(string, "%s[%s]", baseType, size);
287 strcat(string, baseType);
289 strcat(string, size);
297 strcat(string, "...");
300 _PrintType(type.method.dataType, string, false, printFunction, fullName);
303 strcat(string, "subclass(");
304 strcat(string, type._class ? type._class.string : "int");
310 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
313 strcat(string, type.name);
318 void DocPrintType(Type type, char * string, bool printName, bool fullName)
321 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
322 if(funcType && funcType.kind == functionType && type != funcType)
324 char typeString[1024];
327 DocPrintType(funcType.returnType, string, false, fullName);
329 _PrintType(type, string, printName, false, fullName);
333 strcat(string, type.name);
340 for(param = funcType.params.first; param; param = param.next)
342 DocPrintType(param, string, true, fullName);
343 if(param.next) strcat(string, ", ");
348 _PrintType(type, string, printName, true, fullName);
351 void AddComponents(Module module, bool isDll)
356 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
358 row = mainForm.browser.AddRow();
359 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
361 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
364 for(m = module.modules.first; m; m = m.next)
366 if(m.importMode == publicAccess || !isDll)
367 AddComponents(m.module, true);
370 // PUT MODULE DESCRIPTION HERE
371 if(module.name && strcmp(module.name, "ecereCOM"))
373 row = mainForm.browser.AddRow();
374 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
375 row.tag = (int)module;
376 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
378 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
390 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
395 virtual void Generate(File f)
401 enum DocumentationType
409 enum DocumentationItem
425 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
427 NameSpace * nameSpace, * ns;
429 Method method = null;
430 GlobalFunction function = null;
431 char nsName[1024], temp[1024];
437 case nameSpaceDoc: nameSpace = object; break;
438 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
439 case functionDoc: function = object; nameSpace = function.nameSpace; break;
440 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
445 while(ns && ns->name)
447 strcpy(temp, "namespaces/");
448 strcat(temp, ns->name);
450 strcat(temp, nsName);
451 strcpy(nsName, temp);
454 sprintf(docFile, "%s.eCdoc", (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
456 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.
457 strcat(fileName, nsName);
461 strcat(fileName, "classes/");
462 strcat(fileName, cl.name);
463 strcat(fileName, "/");
468 strcat(fileName, "methods/");
469 strcat(fileName, method.name);
470 strcat(fileName, "/");
474 char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
475 if(name) name += 2; else name = function.name;
476 strcat(fileName, "functions/");
477 strcat(fileName, name);
478 strcat(fileName, "/");
483 case description: strcat(fileName, "description"); break;
484 case usage: strcat(fileName, "usage"); break;
485 case remarks: strcat(fileName, "remarks"); break;
486 case example: strcat(fileName, "example"); break;
487 case seeAlso: strcat(fileName, "seeAlso"); break;
488 case returnValue: strcat(fileName, "returnValue"); break;
489 case enumerationValue:
490 strcat(fileName, "enumeration values/");
491 strcat(fileName, ((NamedLink)data).name);
494 strcat(fileName, "definitions/");
495 strcat(fileName, ((Definition)data).name);
499 char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
500 if(name) name += 2; else name = ((Property)data).name;
501 strcat(fileName, "conversions/");
502 strcat(fileName, name);
505 case memberDescription:
506 strcat(fileName, "data members/");
507 strcat(fileName, ((DataMember)data).name);
509 case propertyDescription:
510 strcat(fileName, "properties/");
511 strcat(fileName, ((Property)data).name);
518 strcat(fileName, "parameters/");
519 for(prev = data, count = 0; prev; prev = prev.prev, count++);
520 sprintf(name, "%s.%d", ((Type)data).name, count);
521 strcat(fileName, name);
527 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
529 char fileName[MAX_LOCATION];
530 String contents = null;
533 FigureFileName(fileName, module, type, object, item, data);
534 file = FileOpen(fileName, read);
538 if((len = file.GetSize()))
540 contents = new char[len+1];
541 file.Read(contents, 1, len);
542 contents[len] = '\0';
549 for(c = 0; contents[c]; c++)
550 if(!isspace(contents[c])) break;
554 if(editing && !contents)
555 contents = CopyString($"[Add Text]");
559 class APIPageNameSpace : APIPage
561 NameSpace * nameSpace;
564 void Generate(File f)
567 char nsName[1024], temp[1024];
574 while(ns && ns->name)
576 strcpy(temp, ns->name);
577 if(nsName[0]) strcat(temp, "::");
578 strcat(temp, nsName);
579 strcpy(nsName, temp);
582 // Generate Class Page
583 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
586 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
587 tag = (uint)nameSpace;
588 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);
592 tag = (uint)((!module || !module.name || !strcmp(nsName, "ecere::com") ? null : module));
593 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
597 ns = nameSpace->parent;
598 while(ns && ns->name)
600 strcpy(temp, ns->name);
601 if(nsName[0]) strcat(temp, "::");
602 strcat(temp, nsName);
603 strcpy(nsName, temp);
607 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
611 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
614 f.Printf($"<H3>Description</H3><br><br>\n");
617 char fileName[MAX_LOCATION];
618 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
619 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
621 f.Printf("</a><br><br>");
624 f.Printf("%s<br><br>", desc);
629 if(nameSpace->nameSpaces.first)
632 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
634 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
637 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
638 f.Printf("<TABLE >\n");
642 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);
647 char fileName[MAX_LOCATION];
648 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
649 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
651 f.Printf("</a></TD>");
654 f.Printf("<TD valign=top height=22> %s</TD>", desc);
657 f.Printf("</TR><br>\n");
660 f.Printf("</TABLE><br>\n");
663 if(nameSpace->classes.first)
666 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
668 Class cl = link.data;
669 if(!cl.templateClass)
671 char * desc = ReadDoc(module, classDoc, cl, description, null);
675 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
676 f.Printf("<TABLE >\n");
682 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);
687 char fileName[MAX_LOCATION];
688 FigureFileName(fileName, module, classDoc, cl, description, null);
689 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
691 f.Printf("</a></TD>");
694 f.Printf("<TD valign=top height=22>%s</TD>", desc);
701 f.Printf("</TABLE><br>\n");
704 if(nameSpace->functions.first)
707 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
709 GlobalFunction function = link.data;
710 char * desc = ReadDoc(module, functionDoc, function, description, null);
711 char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
712 if(name) name += 2; else name = function.name;
715 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
716 f.Printf("<TABLE >\n");
720 f.Printf("<TD valign=top height=22 nowrap=1><img valign=center src=\"%s\"> <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a></TD>", iconNames[typeMethod], function, name);
725 char fileName[MAX_LOCATION];
726 FigureFileName(fileName, module, functionDoc, function, description, null);
727 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
729 f.Printf("</a></TD>");
732 f.Printf("<TD valign=top height=22> %s</TD>", desc);
735 f.Printf("</TR><br>\n");
738 f.Printf("</TABLE><br>\n");
741 if(nameSpace->defines.first)
744 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
746 DefinedExpression def = link.data;
747 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
750 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
751 f.Printf("<TABLE >\n");
755 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);
756 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
761 char fileName[MAX_LOCATION];
762 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
763 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
765 f.Printf("</a></TD>");
768 f.Printf("<TD valign=top height=22> %s</TD>", desc);
771 f.Printf("</TR><br>\n");
774 f.Printf("</TABLE><br>\n");
777 f.Printf("</FONT></BODY></HTML>\n");
781 class APIPageClass : APIPage
785 void Generate(File f)
791 char nsName[1024], temp[1024];
792 NameSpace * ns = cl.nameSpace;
793 Module module = cl.module;
796 while(ns && ns->name)
798 strcpy(temp, ns->name);
799 if(nsName[0]) strcat(temp, "::");
800 strcat(temp, nsName);
801 strcpy(nsName, temp);
804 // Generate Class Page
805 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
806 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
808 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);
810 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
813 char * classType = null;
817 classType = $"Bit Collection";
820 classType = $"Enumeration";
823 classType = $"Structure";
826 classType = $"Class";
829 classType = $"Class (No header)";
835 classType = $"Basic Data Type";
838 f.Printf($"Type: %s<br>\n", classType);
841 if(cl.type != systemClass && cl.base)
843 f.Printf($"Base Class: ");
844 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
846 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
848 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
849 f.Printf("%s", cl.dataTypeString);
851 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
856 char * desc = ReadDoc(module, classDoc, cl, description, null);
859 f.Printf($"<br><H3>Description</H3><br><br>\n");
862 char fileName[MAX_LOCATION];
863 FigureFileName(fileName, module, classDoc, cl, description, null);
864 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
866 f.Printf("</a><br><br>");
869 f.Printf("%s<br><br>", desc);
874 if(cl.type == enumClass)
876 EnumClassData enumeration = (EnumClassData)cl.data;
877 if(enumeration.values.first)
881 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
882 f.Printf("<TABLE >\n");
884 for(item = enumeration.values.first; item; item = item.next)
886 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
887 bool needClass = true;
890 char tempString[1024];
892 while(base.type == enumClass) base = base.base;
894 if(base.type == systemClass ||
895 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
898 base.dataType = ProcessTypeString(base.dataTypeString, false);
900 if(base.dataType.kind != classType)
905 PrintType(base.dataType, string, false, true);
906 classSym = FindClass(string);
907 dataClass = classSym ? classSym.registered : null;
910 dataClass = base.dataType._class ? base.dataType._class.registered : null;
916 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);
917 if(dataClass.type == systemClass)
920 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
923 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
925 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
927 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
932 char fileName[MAX_LOCATION];
933 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
934 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
936 f.Printf("</a></TD>");
939 f.Printf("<TD valign=top height=22>%s</TD>", desc);
944 f.Printf("</TABLE><BR>\n");
948 if(cl.conversions.first)
950 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
951 f.Printf("<TABLE >\n");
952 for(prop = cl.conversions.first; prop; prop = prop.next)
954 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
956 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
959 Type type = ProcessTypeString(prop.name, false);
960 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
961 if(name) name += 2; else name = prop.name;
966 DocPrintType(type, string, true, false);
968 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
973 char fileName[MAX_LOCATION];
974 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
975 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
977 f.Printf("</a></TD>");
980 f.Printf("<TD valign=top height=22>%s</TD>", desc);
989 f.Printf("</TABLE><br>\n");
992 if(cl.membersAndProperties.first)
995 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
997 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1001 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1002 f.Printf("<TABLE >\n");
1008 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1010 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1014 DocPrintType(prop.dataType, string, true, false);
1016 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);
1017 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1022 char fileName[MAX_LOCATION];
1023 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1024 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1026 f.Printf("</a></TD>");
1029 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1032 f.Printf("</TR>\n");
1036 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1041 f.Printf("</TABLE><br>\n");
1044 if(cl.methods.first)
1048 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1050 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1052 char * desc = ReadDoc(module, methodDoc, method, description, null);
1055 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1056 f.Printf("<TABLE >\n");
1059 if(!method.dataType)
1060 ProcessMethodType(method);
1063 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);
1068 char fileName[MAX_LOCATION];
1069 FigureFileName(fileName, module, methodDoc, method, description, null);
1070 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1072 f.Printf("</a></TD>");
1075 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1078 f.Printf("</TR><br>\n");
1082 f.Printf("</TABLE><br>\n");
1084 // Non-Virtual Methods
1086 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1088 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1090 char * desc = ReadDoc(module, methodDoc, method, description, null);
1093 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1094 f.Printf("<TABLE >\n");
1098 if(!method.dataType)
1099 ProcessMethodType(method);
1102 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);
1107 char fileName[MAX_LOCATION];
1108 FigureFileName(fileName, module, methodDoc, method, description, null);
1109 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1111 f.Printf("</a></TD>");
1114 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1118 f.Printf("</TR><br>\n");
1122 f.Printf("</TABLE><br>\n");
1125 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1128 f.Printf($"<H3>Usage</H3><br>\n");
1131 char fileName[MAX_LOCATION];
1132 FigureFileName(fileName, module, classDoc, cl, usage, null);
1133 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1138 f.Printf("<br>%s\n", usageDoc);
1139 f.Printf("<br><br>\n");
1144 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1147 f.Printf($"<H3>Example</H3><br>\n");
1148 f.Printf($"<FONT face=\"Courier New\">\n");
1149 f.Printf("<br><TABLE >\n");
1152 char fileName[MAX_LOCATION];
1153 FigureFileName(fileName, module, classDoc, cl, example, null);
1154 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1156 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1159 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1161 f.Printf("</TABLE></FONT>\n");
1167 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1171 f.Printf($"<H3>Remarks</H3><br>\n");
1174 char fileName[MAX_LOCATION];
1175 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1176 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1181 f.Printf("<br>%s\n", remarksDoc);
1182 f.Printf("<br><br>\n");
1187 if(cl.type != systemClass)
1191 for(c = cl.derivatives.first; c; c = c.next)
1193 Class deriv = c.data;
1194 // TO VERIFY: Does this properly check public status?
1195 if(eSystem_FindClass(componentsApp, deriv.fullName))
1199 f.Printf($"<H3>Derived Classes</H3><br>\n");
1205 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1209 f.Printf("<br><br>\n");
1212 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1215 f.Printf($"<H3>See Also</H3><br>\n");
1218 char fileName[MAX_LOCATION];
1219 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1220 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1225 f.Printf("<br>%s\n", seeAlsoDoc);
1226 f.Printf("<br><br>\n");
1230 f.Printf("</FONT></BODY></HTML>\n");
1234 class APIPageMethod : APIPage
1237 void Generate(File f)
1239 Class cl = method._class;
1241 Module module = cl.module;
1243 char nsName[1024], temp[1024];
1244 NameSpace * ns = cl.nameSpace;
1247 while(ns && ns->name)
1249 strcpy(temp, ns->name);
1250 if(nsName[0]) strcat(temp, "::");
1251 strcat(temp, nsName);
1252 strcpy(nsName, temp);
1256 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1257 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1259 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);
1261 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1262 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1263 if(method.dataType.staticMethod)
1265 f.Printf($"this pointer class: None<br>\n");
1267 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1269 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);
1272 // Generate Method Page
1274 if(!method.dataType.name)
1275 method.dataType.name = CopyString(method.name);
1276 DocPrintType(method.dataType, string, true, false);
1277 f.Printf("<br>%s", string);
1280 char * desc = ReadDoc(module, methodDoc, method, description, null);
1283 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1286 char fileName[MAX_LOCATION];
1287 FigureFileName(fileName, module, methodDoc, method, description, null);
1288 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1293 f.Printf("%s", desc);
1298 f.Printf("<br><br>\n");
1299 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1301 f.Printf($"<H3>Parameters</H3><br><br>\n");
1303 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1304 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1306 f.Printf("<TABLE valign=center>\n");
1309 for(param = method.dataType.params.first; param; param = param.next)
1311 // ADD DESCRIPTION HERE
1312 if(param.kind != voidType)
1314 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1317 DocPrintType(param, string, false, false);
1319 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1320 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1325 char fileName[MAX_LOCATION];
1326 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1327 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1329 f.Printf("s</a> </TD>\n");
1332 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1336 f.Printf("</TR>\n");
1339 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1341 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1342 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1344 f.Printf("<TR><TD> </TD></TR>");
1347 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1349 DocPrintType(method.dataType.returnType, string, false, false);
1350 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1355 char fileName[MAX_LOCATION];
1356 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1357 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1359 f.Printf("</a> </TD>\n");
1362 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1365 f.Printf("</TR>\n");
1366 f.Printf("</TABLE>\n");
1368 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1369 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1371 f.Printf("</TABLE><br>\n");
1374 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1377 f.Printf($"<H3>Usage</H3><br>\n");
1380 char fileName[MAX_LOCATION];
1381 FigureFileName(fileName, module, methodDoc, method, usage, null);
1382 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1387 f.Printf("<br>%s\n", usageDoc);
1388 f.Printf("<br><br>\n");
1393 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1396 f.Printf($"<H3>Example</H3><br>\n");
1397 f.Printf($"<FONT face=\"Courier New\">\n");
1398 f.Printf("<br><TABLE >\n");
1401 char fileName[MAX_LOCATION];
1402 FigureFileName(fileName, module, methodDoc, method, example, null);
1403 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1405 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1408 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1409 f.Printf("</TABLE></FONT>\n");
1415 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1418 f.Printf($"<H3>Remarks</H3><br>\n");
1421 char fileName[MAX_LOCATION];
1422 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1423 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1428 f.Printf("<br>%s\n", method, remarksDoc);
1429 f.Printf("<br><br>\n");
1434 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1437 f.Printf($"<H3>See Also</H3><br>\n");
1440 char fileName[MAX_LOCATION];
1441 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1442 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1447 f.Printf("<br>%s\n", method, seeAlsoDoc);
1449 f.Printf("<br><br>\n");
1453 f.Printf("</FONT></BODY></HTML>\n");
1457 class APIPageFunction : APIPage
1459 GlobalFunction function;
1460 void Generate(File f)
1463 Module module = function.module;
1465 char nsName[1024], temp[1024];
1466 NameSpace * ns = function.nameSpace;
1469 while(ns && ns->name)
1471 strcpy(temp, ns->name);
1472 if(nsName[0]) strcat(temp, "::");
1473 strcat(temp, nsName);
1474 strcpy(nsName, temp);
1478 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1479 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1481 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);
1484 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1486 if(!function.dataType)
1487 function.dataType = ProcessTypeString(function.dataTypeString, false);
1489 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1491 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);
1494 // Generate Method Page
1496 if(!function.dataType.name)
1497 function.dataType.name = CopyString(function.name);
1498 DocPrintType(function.dataType, string, true, false);
1499 f.Printf("<br>%s", string);
1502 char * desc = ReadDoc(module, functionDoc, function, description, null);
1505 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1508 char fileName[MAX_LOCATION];
1509 FigureFileName(fileName, module, functionDoc, function, description, null);
1510 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1515 f.Printf("%s", desc);
1519 f.Printf("<br><br>\n");
1520 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1522 f.Printf($"<H3>Parameters</H3><br><br>\n");
1524 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1525 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1527 f.Printf("<TABLE valign=center>\n");
1530 for(param = function.dataType.params.first; param; param = param.next)
1532 // ADD DESCRIPTION HERE
1533 if(param.kind != voidType)
1535 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1538 DocPrintType(param, string, false, false);
1540 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1541 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1546 char fileName[MAX_LOCATION];
1547 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1548 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1550 f.Printf("</a> </TD>\n");
1553 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1556 f.Printf("</TR>\n");
1559 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1561 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1562 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1564 f.Printf("<TR><TD> </TD></TR>");
1567 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1569 DocPrintType(function.dataType.returnType, string, false, false);
1570 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1575 char fileName[MAX_LOCATION];
1576 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1577 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1579 f.Printf("</a> </TD>\n");
1582 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1585 f.Printf("</TR>\n");
1586 f.Printf("</TABLE>\n");
1588 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1589 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1591 f.Printf("</TABLE><br>\n");
1594 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1597 f.Printf($"<H3>Usage</H3><br>\n");
1600 char fileName[MAX_LOCATION];
1601 FigureFileName(fileName, module, functionDoc, function, usage, null);
1602 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1607 f.Printf("<br>%s\n", usageDoc);
1608 f.Printf("<br><br>\n");
1613 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1616 f.Printf($"<H3>Example</H3><br>\n");
1617 f.Printf($"<FONT face=\"Courier New\">\n");
1618 f.Printf("<br><TABLE >\n");
1621 char fileName[MAX_LOCATION];
1622 FigureFileName(fileName, module, functionDoc, function, example, null);
1623 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1625 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1628 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1629 f.Printf("</TABLE></FONT>\n");
1635 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1638 f.Printf($"<H3>Remarks</H3><br>\n");
1641 char fileName[MAX_LOCATION];
1642 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1643 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1648 f.Printf("<br>%s\n", remarksDoc);
1649 f.Printf("<br><br>\n");
1654 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1657 f.Printf($"<H3>See Also</H3><br>\n");
1660 char fileName[MAX_LOCATION];
1661 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1662 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1667 f.Printf("<br>%s\n", seeAlsoDoc);
1668 f.Printf("<br><br>\n");
1672 f.Printf("</FONT></BODY></HTML>\n");
1676 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, char * parentName, bool showPrivate)
1680 NameSpace * nameSpace = mainNameSpace;
1682 DataRow classesRow = null;
1683 DataRow functionsRow = null, definesRow = null;
1686 char fileName[MAX_LOCATION];
1688 strcpy(nsName, parentName ? parentName : "");
1692 strcat(nsName, "::");
1693 strcat(nsName, nameSpace->name);
1698 row = parentRow.AddRow();
1699 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1700 row.tag = (int)nameSpace;
1701 row.icon = mainForm.icons[typeNameSpace];
1705 // "Global NameSpace"
1707 page = parentRow.GetData(null);
1713 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1715 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1716 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1718 if(comNameSpace != null)
1720 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1722 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1724 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1729 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1731 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1733 if(nameSpace->classes.first)
1737 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1740 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1742 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1743 AddClass(classesRow, module, cl, nsName, showPrivate);
1750 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
1752 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1754 if(nameSpace->functions.first)
1758 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
1761 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
1763 char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
1765 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
1766 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int)fn;
1773 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
1775 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1777 if(nameSpace->defines.first)
1781 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
1784 //if(def.module == module)
1786 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
1788 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
1789 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int)def;
1797 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
1801 if(!member.dataType)
1802 member.dataType = ProcessTypeString(member.dataTypeString, false);
1806 DocPrintType(member.dataType, string, true, false);
1808 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
1809 for(c = 0; c<indent; c++)
1810 f.Printf(" ");
1811 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
1812 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
1813 if(member.type == normalMember)
1815 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
1820 char fileName[MAX_LOCATION];
1821 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
1822 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1824 f.Printf("</a></TD>");
1827 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1832 f.Printf("<TD valign=top height=22></TD>");
1834 if(member.type != normalMember)
1836 DataMember subMember;
1837 for(subMember = member.members.first; subMember; subMember = subMember.next)
1839 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
1841 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
1845 f.Printf("</TR><br>\n");
1848 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
1851 if(member.type == normalMember)
1853 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
1854 row.tag = (int)member;
1859 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
1860 row.icon = mainForm.icons[typeData];
1861 row.tag = (int)member;
1863 for(m = member.members.first; m; m = m.next)
1865 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
1866 AddDataMember(row, page, m);
1871 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
1873 char fileName[MAX_LOCATION];
1880 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
1881 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
1884 row = parentRow.AddRow();
1885 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
1887 row.collapsed = true;
1888 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
1891 if(cl.methods.first)
1893 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1895 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
1898 if(!method.dataType)
1899 ProcessMethodType(method);
1900 if(method.type == virtualMethod)
1902 if(method.dataType.thisClass)
1904 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
1905 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
1906 mRow.tag = (int)method;
1910 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
1911 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
1912 mRow.tag = (int)method;
1917 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
1918 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
1919 mRow.tag = (int)method;
1925 if(cl.membersAndProperties.first)
1927 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1929 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1932 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1936 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
1937 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
1938 mRow.tag = (int)prop;
1942 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
1943 AddDataMember(membersRow, page, (DataMember)prop);
1949 if(cl.conversions.first)
1951 for(prop = cl.conversions.first; prop; prop = prop.next)
1955 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
1956 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1957 if(name) name += 2; else name = prop.name;
1958 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
1959 mRow.tag = (int)prop;
1962 if(cl.type == enumClass)
1964 EnumClassData enumeration = (EnumClassData)cl.data;
1966 for(item = enumeration.values.first; item; item = item.next)
1969 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
1970 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
1971 mRow.tag = (int)item;
1976 class MainForm : Window
1978 size = { 1000, 600 };
1980 borderStyle = sizable;
1983 nativeDecorations = true;
1984 icon = { ":documentorIcon.png" };
1985 text = $"API Documentation Browser";
1987 BitmapResource icons[CodeObjectType];
1992 for(c = 0; c < CodeObjectType::enumSize; c++)
1994 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
1996 browser.AddField(DataField { dataType = class(APIPage) });
2001 Menu fileMenu { menu, $"File", f };
2002 Array<FileFilter> fileFilters
2004 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2005 { $"eC Symbol files (*.sym)", "sym" }
2008 FileDialog fileDialog
2010 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2012 MenuItem fileOpenItem
2014 fileMenu, $"Open...", o, ctrlO;
2016 bool NotifySelect(MenuItem selection, Modifiers mods)
2018 if(fileDialog.Modal() == ok)
2020 OpenModule(fileDialog.filePath);
2025 MenuItem fileSettingsItem
2027 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2029 bool NotifySelect(MenuItem selection, Modifiers mods)
2031 SettingsDialog { master = this }.Modal(); // Open the settings dialog to allow the user to change the directory for the eCdoc files
2035 MenuDivider { fileMenu };
2036 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2038 void OpenModule(char * filePath)
2040 char extension[MAX_EXTENSION];
2041 Module module = null;
2042 static char symbolsDir[MAX_LOCATION];
2044 FreeContext(globalContext);
2045 FreeExcludedSymbols(excludedSymbols);
2046 ::defines.Free(FreeModuleDefine);
2047 imports.Free(FreeModuleImport);
2049 FreeGlobalData(globalData);
2050 FreeTypeData(componentsApp);
2052 delete componentsApp;
2054 SetGlobalContext(globalContext);
2055 componentsApp = __ecere_COM_Initialize(false, 1, null);
2056 SetPrivateModule(componentsApp);
2058 StripLastDirectory(filePath, symbolsDir);
2059 SetSymbolsDir(symbolsDir);
2061 GetExtension(filePath, extension);
2063 mainForm.browser.Clear();
2065 ImportModule(filePath, normalImport, publicAccess, false);
2067 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll"))
2068 componentsApp.name = CopyString(filePath);
2070 for(module = componentsApp.allModules.first; module; module = module.next)
2072 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2076 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2077 AddComponents(componentsApp, false);
2079 for(module = componentsApp.allModules.first; module; module = module.next)
2081 if(module.name && (!strcmp(module.name, filePath)))
2084 if(!module) module = componentsApp;
2085 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int)module));
2087 SetSymbolsDir(null);
2092 this, anchor = { left = 0, top = 0, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2093 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2096 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2098 APIPage page = row.GetData(null);
2099 if(view.edit) view.OnLeftButtonDown(0,0,0);
2100 if(page && page.page) page = page.page;
2102 view.PositionCaret(true);
2103 if(page != view.page)
2105 Window activeChild = this.activeChild;
2110 activeChild.Activate();
2112 else if(!view.created)
2116 page = row.GetData(null);
2117 if(page && page.page)
2121 case 1: view.GoToAnchor("Classes"); break;
2122 case 2: view.GoToAnchor("Functions"); break;
2123 case 3: view.GoToAnchor("Definitions"); break;
2124 case 4: view.GoToAnchor("VirtualMethods"); break;
2125 case 5: view.GoToAnchor("Methods"); break;
2126 case 6: view.GoToAnchor("Members"); break;
2127 case 7: view.GoToAnchor("Conversions"); break;
2128 case 8: view.GoToAnchor("EnumerationValues"); break;
2132 sprintf(hex, "%p", row.tag);
2133 view.GoToAnchor(hex);
2139 view.SetScrollPosition(0, 0);
2147 this, anchor = { top = 0, bottom = 0, right = 0 };
2152 this, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2155 bool OnClose(bool parentClosing)
2158 view.OnLeftButtonDown(0,0,0);
2164 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2165 //mainForm.OpenModule("ec");
2166 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2167 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2169 int index = mainForm.browser.currentRow.index;
2170 int rowHeight = mainForm.browser.rowHeight;
2171 int height = mainForm.browser.clientSize.h;
2173 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2179 class EditDialog : Window
2181 borderStyle = sizable;
2182 size = { 600, 400 };
2187 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2191 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2195 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2199 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2200 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2202 class HelpView : HTMLView
2206 hasVertScroll = true;
2207 hasHorzScroll = true;
2209 char editString[MAX_LOCATION];
2214 page = mainForm.browser.currentRow.GetData(null);
2220 GoToAnchor(page.label);
2222 if(page.page) page = page.page;
2225 return HTMLView::OnCreate();
2234 char archiveFile[MAX_LOCATION];
2235 char fileName[MAX_FILENAME];
2236 char directory[MAX_LOCATION];
2239 SplitArchivePath(editString, archiveFile, &location);
2240 GetLastDirectory(location, fileName);
2241 StripLastDirectory(location, directory);
2242 archive = ArchiveOpen(archiveFile, { true } );
2246 ArchiveDir dir = archive.OpenDirectory(directory, null, replace);
2249 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2251 if(block.type == TEXT && block.textLen)
2259 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2261 if(block.type == BR)
2263 else if(block.type == TEXT)
2264 f.Write(block.text, 1, block.textLen);
2268 dir.AddFromFile(fileName, f, null, replace, 0, null, null);
2274 Block parent = textBlock.parent;
2275 while((block = parent.subBlocks.first))
2277 parent.subBlocks.Remove(block);
2280 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
2281 textBlock.text = CopyString($"[Add Text]");
2282 textBlock.textLen = strlen(textBlock.text);
2283 parent.subBlocks.Add(textBlock);
2291 PositionCaret(true);
2297 bool OnLeftButtonDown(int x, int y, Modifiers mods)
2301 if(edit && (!textBlock || overLink != textBlock.parent))
2304 HTMLView::OnLeftButtonDown(x, y, mods);
2305 selPosition = curPosition = 0;
2306 selBlock = textBlock;
2310 result = HTMLView::OnLeftButtonDown(x, y, mods);
2312 if(!edit && clickedLink)
2315 if(clickedLink == overLink && clickedLink.href)
2317 if(OnOpen(clickedLink.href))
2325 if(textBlock && overLink == textBlock.parent)
2327 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock);
2328 selBlock = textBlock;
2329 PositionCaret(true);
2337 bool OnLeftButtonUp(int x, int y, Modifiers mods)
2339 if(!edit || !textBlock || clickedLink != textBlock.parent)
2341 HTMLView::OnLeftButtonUp(x, y, mods);
2344 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock);
2345 selBlock = textBlock;
2346 PositionCaret(true);
2355 bool OnMouseMove(int x, int y, Modifiers mods)
2357 if(edit && selecting)
2359 curPosition = TextPosFromPoint(x, y, &textBlock);
2360 PositionCaret(true);
2363 return HTMLView::OnMouseMove(x, y, mods);
2366 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
2371 for(c = curPosition; c >= 0; c--)
2374 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
2375 ch = UTF8GetChar(textBlock.text + c, &numBytes);
2376 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2382 for(c = start; c < textBlock.textLen; c += numBytes)
2384 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
2385 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
2388 selPosition = start;
2391 PositionCaret(true);
2398 bool OnOpen(char * href)
2400 if(!strncmp(href, "api://", 6))
2402 int tag = (uint)strtoul(href + 6, null, 16);
2403 DataRow row = mainForm.browser.FindSubRow(tag);
2407 mainForm.browser.SelectRow(row);
2408 while((row = row.parent))
2409 row.collapsed = false;
2410 row = mainForm.browser.currentRow;
2411 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
2414 else if(!strncmp(href, "edit://", 7))
2417 int startX = clickedLink.startX, startY = clickedLink.startY;
2418 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
2420 if(block.type == TEXT) startX = block.startX, startY = block.startY;
2421 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
2423 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
2425 display.FontExtent(block.font.font, " ", 1, null, &th);
2428 block.parent.subBlocks.Insert(null, newBlock);
2433 block.parent.subBlocks.Insert(block, newBlock);
2434 startY += block.prev.height;
2436 newBlock.startX = startX;
2437 newBlock.startY = startY;
2438 newBlock.text = new0 char[1];
2442 textBlock = (Block)clickedLink.subBlocks.first;
2443 if(!strcmp(textBlock.text, $"[Add Text]"))
2445 textBlock.text[0] = 0;
2446 textBlock.textLen = 0;
2449 strcpy(editString, href + 7);
2450 selPosition = curPosition = 0;
2451 selBlock = textBlock;
2454 // PositionCaret(true);
2461 void DeleteSelection()
2463 if(textBlock != selBlock || curPosition != selPosition)
2465 if(textBlock == selBlock)
2467 // Within same block
2468 int start = Min(curPosition, selPosition);
2469 int end = Max(curPosition, selPosition);
2470 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
2471 textBlock.textLen -= end-start;
2472 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
2473 curPosition = start;
2474 selPosition = start;
2478 int startSel, endSel;
2479 Block startSelBlock = null, endSelBlock = null, b, next;
2481 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2483 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
2484 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
2486 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
2487 for(b = startSelBlock.next; b; b = next)
2489 bool isEnd = b == endSelBlock;
2490 next = GetNextBlock(b);
2491 b.parent.subBlocks.Remove(b);
2496 textBlock = startSelBlock;
2497 selBlock = startSelBlock;
2498 curPosition = startSel;
2499 selPosition = startSel;
2503 PositionCaret(true);
2508 String GetSelectionString()
2510 String selection = null;
2511 if(textBlock == selBlock)
2513 // Within same block
2514 int start = Min(curPosition, selPosition);
2515 int end = Max(curPosition, selPosition);
2516 int len = end - start;
2517 selection = new char[len + 1];
2518 memcpy(selection, textBlock.text + start, len);
2523 int startSel, endSel;
2524 Block startSelBlock = null, endSelBlock = null, b;
2527 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
2530 for(b = startSelBlock; b; b = GetNextBlock(b))
2532 int start = (b == startSelBlock) ? startSel : 0;
2533 int end = (b == endSelBlock) ? endSel : b.textLen;
2534 int len = end - start;
2536 if(b == endSelBlock)
2538 else if(b.type == TEXT)
2542 selection = new char[totalLen + 1];
2544 for(b = startSelBlock; b; b = GetNextBlock(b))
2546 int start = (b == startSelBlock) ? startSel : 0;
2547 int end = (b == endSelBlock) ? endSel : b.textLen;
2548 int len = end - start;
2549 memcpy(selection + totalLen, b.text + start, len);
2551 if(b == endSelBlock)
2553 else if(b.type == TEXT)
2554 selection[totalLen++] = '\n';
2556 selection[totalLen] = 0;
2561 void CopySelection()
2563 String s = GetSelectionString();
2566 int len = strlen(s);
2568 if(cb.Allocate(len + 1))
2570 memcpy(cb.text, s, len + 1);
2578 bool OnKeyDown(Key key, unichar ch)
2585 OnLeftButtonDown(0,0,0);
2587 case Key { end, shift = true }:
2589 curPosition = textBlock.textLen;
2592 selPosition = curPosition;
2593 selBlock = textBlock;
2595 PositionCaret(true);
2598 case Key { home, shift = true }:
2603 selPosition = curPosition;
2604 selBlock = textBlock;
2606 PositionCaret(true);
2609 case Key { home, ctrl = true, shift = true }:
2612 while(textBlock.prev)
2613 textBlock = textBlock.prev.prev;
2616 selPosition = curPosition;
2617 selBlock = textBlock;
2619 PositionCaret(true);
2622 case Key { end, ctrl = true, shift = true }:
2624 while(textBlock.next && textBlock.next.next)
2625 textBlock = textBlock.next.next;
2626 curPosition = textBlock.textLen;
2629 selPosition = curPosition;
2630 selBlock = textBlock;
2632 PositionCaret(true);
2638 return HTMLView::OnKeyDown(key, ch);
2642 bool OnKeyHit(Key key, unichar ch)
2648 case Key { up, shift = true }:
2651 if(caretY == textBlock.startY)
2655 textBlock = textBlock.prev.prev;
2656 curPosition = Min(curPosition, textBlock.textLen);
2659 selPosition = curPosition;
2660 selBlock = textBlock;
2663 PositionCaret(false);
2673 int sx = textBlock.startX, sy = textBlock.startY;
2674 char * text = textBlock.text;
2676 Block block = textBlock;
2677 while(block && block.type != TD) block = block.parent;
2680 Block table = block;
2681 while(table && table.type != TABLE) table = table.parent;
2683 maxW = block.w - 2* table.cellPadding;
2685 maxW = clientSize.w - 10 - sx;
2688 maxW = clientSize.w - 10 - sx;
2689 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
2693 int startPos = textPos;
2696 bool lineComplete = false;
2697 for(; textPos<textBlock.textLen && !lineComplete;)
2701 char * nextSpace = strchr(text + textPos, ' ');
2704 len = (nextSpace - (text + textPos)) + 1;
2706 len = textBlock.textLen - textPos;
2708 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
2710 if(x + width + w > maxW && x > 0)
2712 lineComplete = true;
2722 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
2725 curPosition = textPos;
2726 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
2729 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
2730 len = curPosition - startPos;
2731 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
2735 selPosition = curPosition;
2736 selBlock = textBlock;
2740 PositionCaret(false);
2744 if(sy == caretY - th || textPos == textBlock.textLen)
2746 if(textPos != textBlock.textLen)
2748 int c = textPos - 1;
2749 while(c > 0 && text[c] == ' ') c--;
2750 curPosition = c + 1;
2753 selPosition = curPosition;
2754 selBlock = textBlock;
2760 curPosition = textBlock.textLen;
2763 selPosition = curPosition;
2764 selBlock = textBlock;
2768 PositionCaret(false);
2772 sx = textBlock.startX;
2773 } while(textPos < textBlock.textLen);
2778 case Key { down, shift = true }:
2783 int sx = textBlock.startX, sy = textBlock.startY;
2784 char * text = textBlock.text;
2786 Block block = textBlock;
2787 while(block && block.type != TD) block = block.parent;
2790 Block table = block;
2791 while(table && table.type != TABLE) table = table.parent;
2793 maxW = block.w - 2* table.cellPadding;
2795 maxW = clientSize.w - 10 - sx;
2798 maxW = clientSize.w - 10 - sx;
2799 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
2801 while(!textPos || textPos < textBlock.textLen)
2803 int startPos = textPos;
2806 bool lineComplete = false;
2807 for(; (textPos < textBlock.textLen) && !lineComplete;)
2811 char * nextSpace = strchr(text + textPos, ' ');
2814 len = (nextSpace - (text + textPos)) + 1;
2816 len = textBlock.textLen - textPos;
2818 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
2820 if(x + width + w > maxW && x > 0)
2822 lineComplete = true;
2832 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
2834 curPosition = textPos;
2836 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
2839 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
2840 len = curPosition - startPos;
2841 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
2845 selPosition = curPosition;
2846 selBlock = textBlock;
2849 PositionCaret(false);
2855 curPosition = textBlock.textLen;
2858 selPosition = curPosition;
2859 selBlock = textBlock;
2862 PositionCaret(false);
2865 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
2869 textBlock = textBlock.next.next;
2870 sy = textBlock.startY;
2871 sx = textBlock.startX;
2872 text = textBlock.text;
2877 sx = textBlock.startX;
2881 /*if(textBlock.next && textBlock.next.next)
2883 textBlock = textBlock.next.next;
2884 selPosition = curPosition = Min(curPosition, textBlock.textLen);
2885 selBlock = textBlock;
2886 PositionCaret(false);
2890 case Key { right, shift = true, ctrl = true }:
2893 bool foundAlpha = false;
2895 Block line, lastLine;
2898 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
2900 int start = (line == textBlock) ? curPosition : 0;
2902 for(c = start; c < line.textLen; c++)
2904 char ch = line.text[c];
2905 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
2906 if(key.shift ? isAlUnder : !isAlUnder)
2920 selPosition = curPosition;
2921 selBlock = textBlock;
2925 PositionCaret(true);
2930 // No next word found,
2931 if(!found && (c != curPosition || line != textBlock))
2935 lastC = line.textLen-1;
2940 curPosition = line.textLen;
2943 selPosition = curPosition;
2944 selBlock = textBlock;
2949 PositionCaret(true);
2955 if(key.shift && found)
2957 curPosition = lastC+1;
2958 textBlock = lastLine;
2959 PositionCaret(true);
2964 case Key { left, ctrl = true, shift = true }:
2967 bool foundAlpha = false;
2969 Block line, lastLine;
2972 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
2975 if(curPosition == 0 && line != textBlock)
2978 lastC = line.textLen;
2982 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
2983 for(c = start; c>=0; c--)
2985 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3000 // No next word found,
3001 if(!found && curPosition > 0)
3011 textBlock = lastLine;
3012 curPosition = lastC;
3015 selPosition = curPosition;
3016 selBlock = textBlock;
3018 PositionCaret(true);
3023 case Key { right, shift = true }:
3025 if(curPosition < textBlock.textLen)
3027 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3030 selPosition = curPosition;
3031 selBlock = textBlock;
3033 PositionCaret(true);
3036 else if(textBlock.next && textBlock.next.next)
3038 textBlock = textBlock.next.next;
3042 selPosition = curPosition;
3043 selBlock = textBlock;
3045 PositionCaret(true);
3049 case Key { left, shift = true }:
3053 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3056 selPosition = curPosition;
3057 selBlock = textBlock;
3059 PositionCaret(true);
3062 else if(textBlock.prev)
3064 textBlock = textBlock.prev.prev;
3065 curPosition = textBlock.textLen;
3068 selPosition = curPosition;
3069 selBlock = textBlock;
3071 PositionCaret(true);
3076 if(textBlock == selBlock && curPosition == selPosition)
3080 int c = curPosition;
3082 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3083 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3084 textBlock.textLen -= nb;
3085 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3087 selPosition = curPosition;
3088 selBlock = textBlock;
3092 PositionCaret(true);
3095 else if(textBlock.prev)
3097 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3098 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3099 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3101 selPosition = curPosition = prevBlock.textLen;
3102 selBlock = textBlock;
3103 prevBlock.textLen += textBlock.textLen;
3104 textBlock.parent.subBlocks.Remove(prev);
3105 if(prev == selBlock)
3107 selBlock = textBlock;
3108 selPosition = curPosition;
3111 textBlock.parent.subBlocks.Remove(textBlock);
3112 if(textBlock == selBlock)
3114 selBlock = prevBlock;
3115 selPosition = curPosition;
3118 textBlock = prevBlock;
3122 PositionCaret(true);
3130 if(textBlock != selBlock || curPosition != selPosition)
3132 else if(textBlock.textLen > curPosition)
3134 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3135 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3136 textBlock.textLen -= nb;
3137 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3142 PositionCaret(true);
3145 else if(textBlock.next && textBlock.next.next)
3147 Block next = textBlock.next, nextBlock = textBlock.next.next;
3148 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3149 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3151 textBlock.textLen += nextBlock.textLen;
3152 textBlock.parent.subBlocks.Remove(next);
3153 if(next == selBlock)
3155 selBlock = textBlock;
3156 selPosition = curPosition;
3159 textBlock.parent.subBlocks.Remove(nextBlock);
3160 if(nextBlock == selBlock)
3162 selBlock = textBlock;
3163 selPosition = curPosition;
3169 PositionCaret(true);
3182 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3183 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3184 startY = textBlock.startY;
3185 startX = textBlock.startX;
3187 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3188 textBlock.parent.subBlocks.Insert(textBlock, block);
3189 textBlock.parent.subBlocks.Insert(block, newBlock);
3193 newBlock.textLen = textBlock.textLen - curPosition;
3194 newBlock.text = new char[newBlock.textLen+1];
3195 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3196 textBlock.textLen = curPosition;
3197 textBlock.text[curPosition] = 0;
3199 newBlock.startY = startY;
3200 newBlock.startX = startX;
3201 selPosition = curPosition = 0;
3206 textBlock = newBlock;
3207 selBlock = textBlock;
3208 PositionCaret(true);
3213 case Key { del, shift = true }:
3226 ClipBoard clipBoard { };
3227 if(clipBoard.Load())
3230 char * text = clipBoard.memory;
3238 parent = textBlock.parent;
3239 font = textBlock.font;
3244 if(ch == '\n' || ch == '\r' || !ch)
3246 int len = c - start;
3247 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
3248 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3249 memcpy(textBlock.text + curPosition, text + start, len);
3250 textBlock.textLen += len;
3252 selPosition = curPosition;
3253 selBlock = textBlock;
3256 Block block { type = BR, parent = parent, font = font };
3257 Block newBlock { type = TEXT, parent = parent, font = font };
3258 int startY = textBlock.startY, startX = textBlock.startX;
3261 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3262 textBlock.parent.subBlocks.Insert(textBlock, block);
3263 textBlock.parent.subBlocks.Insert(block, newBlock);
3267 newBlock.textLen = textBlock.textLen - curPosition;
3268 newBlock.text = new char[newBlock.textLen+1];
3269 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3270 textBlock.textLen = curPosition;
3271 textBlock.text[curPosition] = 0;
3273 newBlock.startY = startY;
3274 newBlock.startX = startX;
3275 selPosition = curPosition = 0;
3276 selBlock = textBlock;
3277 textBlock = newBlock;
3279 if(ch == '\r' && text[c+1] == '\n') c++;
3285 PositionCaret(true);
3293 // eC BUG HERE: (Should be fixed)
3294 if(!key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
3297 int len = UTF32toUTF8Len(&ch, 1, string, 5);
3302 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
3303 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3305 for(c = 0; c<len; c++)
3307 textBlock.text[curPosition] = string[c];
3308 textBlock.textLen++;
3311 selPosition = curPosition;
3312 selBlock = textBlock;
3315 //Clear(html.block);
3316 //CreateForms(html.block);
3321 PositionCaret(true);
3330 void OnResize(int width, int height)
3332 HTMLView::OnResize(width, height);
3333 PositionCaret(true);
3337 void PositionCaret(bool setCaretX)
3343 int sx = textBlock.startX, sy = textBlock.startY;
3344 char * text = textBlock.text;
3346 Block block = textBlock;
3347 while(block && block.type != TD) block = block.parent;
3350 Block table = block;
3351 while(table && table.type != TABLE) table = table.parent;
3353 maxW = block.w - 2* table.cellPadding;
3355 maxW = clientSize.w - 10 - sx;
3358 maxW = clientSize.w - 10 - sx;
3360 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3362 while(textPos < textBlock.textLen)
3364 int startPos = textPos;
3367 bool lineComplete = false;
3369 for(; textPos<textBlock.textLen && !lineComplete;)
3373 char * nextSpace = strchr(text + textPos, ' ');
3376 len = (nextSpace - (text + textPos)) + 1;
3378 len = textBlock.textLen - textPos;
3380 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3382 if(x + width + w > maxW && x > 0)
3384 lineComplete = true;
3397 if(curPosition < textPos || textPos == textBlock.textLen)
3399 int len = curPosition - startPos;
3400 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
3405 sx = textBlock.startX;
3410 SetCaret(sx, sy, th);
3412 Point scrollPos = scroll;
3413 bool doScroll = false;
3414 if(sy - scroll.y + th > clientSize.h)
3416 scrollPos.y = sy + th - clientSize.h;
3419 else if(sy - scroll.y < 0)
3424 if(sx - scroll.x + 10 > clientSize.w)
3426 scrollPos.x = sx + 10 - clientSize.w;
3429 else if(sx - scroll.x < 10)
3431 scrollPos.x = sx - 10;
3442 // Returns a character offset into the TextBlock from a window coordinate
3443 int TextPosFromPoint(int px, int py, Block * block)
3445 Block parentBlock = this.textBlock.parent;
3448 *block = this.textBlock;
3453 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
3455 int sx = textBlock.startX, sy = textBlock.startY;
3458 char * text = textBlock.text;
3460 Block b = textBlock;
3463 if(textBlock.type != TEXT) continue;
3465 while(b && b.type != TD) b = b.parent;
3469 while(table && table.type != TABLE) table = table.parent;
3471 maxW = b.w - 2* table.cellPadding;
3473 maxW = clientSize.w - 10 - sx;
3476 maxW = clientSize.w - 10 - sx;
3478 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
3479 //space = space/2+2;
3482 while(textPos < textBlock.textLen)
3484 int startPos = textPos;
3487 bool lineComplete = false;
3489 for(; textPos<textBlock.textLen && !lineComplete;)
3493 char * nextSpace = strchr(text + textPos, ' ');
3496 len = (nextSpace - (text + textPos)) + 1;
3498 len = textBlock.textLen - textPos;
3500 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3502 sx = x + textBlock.startX;
3503 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
3508 for(c = textPos; (ch = text[c]); c += numBytes)
3510 numBytes = UTF8_NUM_BYTES(ch);
3511 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
3512 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + w -w/2-space)
3519 if(x + width + w > maxW && x > 0)
3521 lineComplete = true;
3534 if(/*py >= sy && */py < sy + th)
3537 return textBlock.textLen;
3542 result = textBlock.textLen;
3548 Application componentsApp;
3550 class Documentor : GuiApplication
3554 Platform os = GetRuntimePlatform();
3555 componentsApp = __ecere_COM_Initialize(false, 1, null);
3556 SetPrivateModule(componentsApp);
3557 SetGlobalContext(globalContext);
3558 SetExcludedSymbols(&excludedSymbols);
3559 SetDefines(&::defines);
3560 SetImports(&imports);
3562 SetGlobalData(globalData);
3564 settingsContainer.dataOwner = &settings;
3565 settingsContainer.Load();
3566 if(!settings.docDir || !settings.docDir[0] )
3568 if(os == win32) // if Windows OS then
3570 char programFilesDir[MAX_LOCATION];
3571 char appData[MAX_LOCATION];
3572 char homeDrive[MAX_LOCATION];
3573 char winDir[MAX_LOCATION];
3574 GetEnvironment("APPDATA", appData, sizeof(appData));
3575 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
3576 GetEnvironment("windir", winDir, sizeof(winDir));
3577 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
3579 PathCat(programFilesDir, "ECERE SDK\\doc");
3580 settings.docDir = programFilesDir;
3582 else if(homeDrive && homeDrive[0])
3584 PathCat(homeDrive, "ECERE SDK\\doc");
3585 settings.docDir = homeDrive;
3587 else if(winDir && winDir[0])
3589 PathCat(winDir, "..\\ECERE SDK\\doc");
3590 settings.docDir = winDir;
3593 settings.docDir = "C:\\ECERE SDK\\doc";
3595 else // if Os is Linux, or Mac OSX or something else
3596 settings.docDir = "/usr/share/ecere/doc/";
3597 settingsContainer.Save();
3603 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
3605 AddComponents(module, true);
3606 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int)module);
3607 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int)eSystem_FindClass(componentsApp, "Window"));
3608 while((row = row.parent))
3609 row.collapsed = false;
3617 FreeContext(globalContext);
3618 FreeExcludedSymbols(excludedSymbols);
3619 ::defines.Free(FreeModuleDefine);
3620 imports.Free(FreeModuleImport);
3622 FreeGlobalData(globalData);
3623 FreeTypeData(componentsApp);
3625 delete componentsApp;
3629 MainForm mainForm { };