2 #if !defined(EAR_TO_ECON_ECDOC)
6 import "SettingsDialog"
8 IDESettings ideSettings;
10 IDESettingsContainer settingsContainer
12 dataOwner = &ideSettings;
13 dataClass = class(IDESettings);
16 static Context globalContext { };
17 static OldList defines { };
18 static OldList imports { };
19 static NameSpace globalData;
20 static OldList excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left };
23 define app = (GuiApplication)__thisModule.application;
25 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
28 /*extern */int __ecereVMethodID_class_OnGetString;
32 static __attribute__((unused)) void Dummy()
35 a.OnGetString(null, null, null);
38 static bool editing = true;
40 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
42 static const char * iconNames[CodeObjectType] =
44 "<:ecere>constructs/class.png",
45 "<:ecere>constructs/data.png",
46 "<:ecere>constructs/method.png",
47 "<:ecere>constructs/event.png",
48 "<:ecere>constructs/property.png",
49 "<:ecere>constructs/namespace.png",
50 "<:ecere>constructs/dataType.png",
51 "<:ecere>constructs/enumValue.png",
52 "<:ecere>constructs/dataPrivate.png",
53 "<:ecere>constructs/methodPrivate.png",
54 "<:ecere>constructs/propertyPrivate.png"
57 void GetTemplateString(Class c, char * templateString)
59 Module m = c.module.application;
60 const char * n = c.name;
61 char * lt = strchr(n, '<');
67 memcpy(templateString, n, lt-n);
68 templateString[lt-n] = 0;
69 strcat(templateString, "</a>");
71 for(s = lt; (ch = *s); s++)
73 if(ch == '<' || ch == '>' || ch == ',')
78 char * d = templateString + strlen(templateString);
80 TrimLSpaces(curName, curName);
81 TrimRSpaces(curName, curName);
82 pc = eSystem_FindClass(m, curName);
84 sprintf(d, "%s<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name);
89 strcat(templateString, "<");
91 strcat(templateString, ">");
93 strcat(templateString, ", ");
100 curName[len++] = ' ';
102 strcat(templateString, curName);
110 // WARNING : This function expects a null terminated string since it recursively concatenate...
111 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
115 if(type.constant && (type.kind != pointerType && type.kind != arrayType))
116 strcat(string, "const ");
120 if(type._class && type._class.string)
123 strcat(string, type._class.string);
126 if(type._class.registered)
129 const char * s = type._class.registered.name;
130 sprintf(hex, "%p", type._class.registered.templateClass ? type._class.registered.templateClass : type._class.registered);
131 strcat(string, "<a href=\"api://");
133 strcat(string, "\" style=\"text-decoration: none;\">");
137 GetTemplateString(type._class.registered, n);
141 strcat(string, type._class.registered.name);
142 strcat(string, "</a>");
145 strcat(string, type._class.string);
152 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
153 if(funcType && funcType.kind == functionType)
156 DocPrintType(funcType.returnType, string, false, fullName);
157 strcat(string, "(*");
158 if(printName || funcType.thisClass)
161 if(funcType.thisClass)
163 strcat(string, funcType.thisClass.string);
164 strcat(string, "::");
167 strcat(string, type.name);
169 strcat(string, ")(");
170 for(param = funcType.params.first; param; param = param.next)
172 DocPrintType(param, string, false, fullName);
173 if(param.next) strcat(string, ", ");
179 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
180 if(string[strlen(string)-1] == '(')
183 strcat(string, " *");
187 case voidType: strcat(string, "void"); break;
188 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
189 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
190 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
191 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
192 case floatType: strcat(string, "float"); break;
193 case doubleType: strcat(string, "double"); break;
197 strcat(string, "struct ");
198 strcat(string, type.enumName);
200 else if(type.typeName)
202 strcat(string, type.typeName);
207 strcat(string, "struct ");
208 strcat(string,"(unnamed)");
211 strcat(string, "struct {");
212 for(member = type.members.first; member; member = member.next)
214 DocPrintType(member, string, true, fullName);
223 strcat(string, "union ");
224 strcat(string, type.enumName);
226 else if(type.typeName)
228 strcat(string, type.typeName);
232 strcat(string, "union ");
233 strcat(string,"(unnamed)");
239 strcat(string, "enum ");
240 strcat(string, type.enumName);
242 else if(type.typeName)
244 strcat(string, type.typeName);
247 strcat(string, "enum");
254 strcat(string, "dllexport ");
255 DocPrintType(type.returnType, string, false, fullName);
259 // DANGER: Testing This
265 strcat(string, type.name);
268 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
269 if(name) name += 2; else name = type.name;
270 strcat(string, "<b>");
271 strcat(string, name);
272 strcat(string, "</b>");
281 for(param = type.params.first; param; param = param.next)
283 DocPrintType(param, string, true, fullName);
284 if(param.next) strcat(string, ", ");
293 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
294 if(funcType && funcType.kind == functionType)
297 DocPrintType(funcType.returnType, string, false, fullName);
298 strcat(string, "(*");
299 if(printName || funcType.thisClass)
302 if(funcType.thisClass)
304 strcat(string, funcType.thisClass.string);
305 strcat(string, "::");
308 strcat(string, type.name);
310 strcat(string, ")(");
311 for(param = funcType.params.first; param; param = param.next)
313 DocPrintType(param, string, false, fullName);
314 if(param.next) strcat(string, ", ");
320 char baseType[1024], size[256];
321 Type arrayType = type;
325 while(arrayType.kind == TypeKind::arrayType)
328 if(arrayType.enumClass)
329 strcat(size, arrayType.enumClass.string);
330 else if(arrayType.arraySizeExp)
331 PrintExpression(arrayType.arraySizeExp, size);
332 //sprintf(string, "%s[%s]", baseType, size);
335 arrayType = arrayType.arrayType;
337 _PrintType(arrayType, baseType, printName, printFunction, fullName);
338 strcat(string, baseType);
339 strcat(string, size);
343 DocPrintType(type.arrayType, baseType, printName, fullName);
345 strcpy(size, type.enumClass.string);
346 else if(type.arraySizeExp)
347 PrintExpression(type.arraySizeExp, size);
348 //sprintf(string, "%s[%s]", baseType, size);
349 strcat(string, baseType);
351 strcat(string, size);
359 strcat(string, "...");
362 _PrintType(type.method.dataType, string, false, printFunction, fullName);
365 strcat(string, "subclass(");
366 strcat(string, type._class ? type._class.string : "int");
372 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
375 strcat(string, type.name);
380 void DocPrintType(Type type, char * string, bool printName, bool fullName)
383 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
384 if(funcType && funcType.kind == functionType && type != funcType)
388 DocPrintType(funcType.returnType, string, false, fullName);
390 _PrintType(type, string, printName, false, fullName);
394 strcat(string, type.name);
401 for(param = funcType.params.first; param; param = param.next)
403 DocPrintType(param, string, true, fullName);
404 if(param.next) strcat(string, ", ");
409 _PrintType(type, string, printName, true, fullName);
412 Map<String, bool> modulesAdded { };
413 void AddComponents(Module module, bool isDll)
418 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")) && !modulesAdded["ecereCOM"])
420 row = mainForm.browser.AddRow();
421 modulesAdded["ecereCOM"] = true;
422 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
423 row.tag = (int64)null;
424 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
427 for(m = module.modules.first; m; m = m.next)
429 if(m.importMode == publicAccess || !isDll)
430 AddComponents(m.module, true);
433 // PUT MODULE DESCRIPTION HERE
434 if(module.name && !modulesAdded[module.name] && strcmp(module.name, "ecereCOM"))
436 row = mainForm.browser.AddRow();
437 modulesAdded[module.name] = true;
438 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
439 row.tag = (int64)module;
440 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
442 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
454 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
459 virtual void Generate(File f)
464 virtual Module GetModule()
466 return page ? page.GetModule() : null;
469 virtual NameSpace * GetNameSpace()
471 return page ? page.GetNameSpace() : null;
475 enum DocumentationType
484 enum DocumentationItem
501 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
505 sprintf(hex, "%p", module);
506 strcat(fileName, hex);
507 strcat(fileName, "/");
508 sprintf(hex, "%p", object);
509 strcat(fileName, hex);
510 strcat(fileName, "/");
511 sprintf(hex, "%p", data);
512 strcat(fileName, hex);
513 strcat(fileName, "/");
514 if(type == nameSpaceDoc)
515 strcat(fileName, "namespace");
516 else if(type == functionDoc)
517 strcat(fileName, "function");
518 else if(type == classDoc)
519 strcat(fileName, "class");
520 else if(type == methodDoc)
521 strcat(fileName, "method");
522 strcat(fileName, "/");
523 if(item == description)
524 strcat(fileName, "description");
525 else if(item == usage)
526 strcat(fileName, "usage");
527 else if(item == remarks)
528 strcat(fileName, "remarks");
529 else if(item == example)
530 strcat(fileName, "example");
531 else if(item == seeAlso)
532 strcat(fileName, "seeAlso");
533 else if(item == enumerationValue)
534 strcat(fileName, "enumerationValue");
535 else if(item == definition)
536 strcat(fileName, "definition");
537 else if(item == conversion)
538 strcat(fileName, "conversion");
539 else if(item == memberDescription)
540 strcat(fileName, "memberDescription");
541 else if(item == propertyDescription)
542 strcat(fileName, "propertyDescription");
543 else if(item == parameter)
544 strcat(fileName, "parameter");
545 else if(item == returnValue)
546 strcat(fileName, "returnValue");
549 static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
551 char docPath[MAX_LOCATION];
552 NameSpace * nameSpace, * ns;
554 Method method = null;
555 GlobalFunction function = null;
556 char nsName[1024], temp[1024];
559 case nameSpaceDoc: nameSpace = object; break;
560 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
561 case functionDoc: function = object; nameSpace = function.nameSpace; break;
562 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
568 while(ns && ns->name)
570 strcpy(temp, ns->name);
572 strcat(temp, nsName);
573 strcpy(nsName, temp);
578 PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
579 //ChangeExtension(docPath, "eCdoc", docPath);
580 PathCatSlash(docPath, nsName);
583 char * name = getDocFileNameFromTypeName(cl.name);
584 PathCatSlash(docPath, name);
588 PathCatSlash(docPath, "_global-defs");
589 ChangeExtension(docPath, "econ", docPath);
592 strcpy(path, ideSettings.docDir);
593 PathCatSlash(path, docPath);
596 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
598 String contents = null;
599 NamespaceDoc nsDoc = null;
600 ClassDoc clDoc = null;
601 FunctionDoc fnDoc = null;
602 MethodDoc mdDoc = null;
604 char filePath[MAX_LOCATION];
605 Method method = null;
606 GlobalFunction function = null;
608 ItemDoc doc = getDoc(filePath, module, type, object, item, data, false);
612 case functionDoc: function = object; break;
613 case methodDoc: method = object; break;
618 if(eClass_IsDerived(doc._class, class(ClassDoc)))
620 clDoc = (ClassDoc)doc;
622 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
624 nsDoc = (NamespaceDoc)doc;
630 ItemDoc itDoc = null;
631 if(type == functionDoc)
633 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
634 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
635 if(name) name += 2; else name = function.name;
636 if(it.Index(name, false))
639 else if(type == methodDoc)
641 MapIterator<String, MethodDoc> it { map = clDoc.methods };
642 if(it.Index(method.name, false))
648 case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break;
649 case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break;
650 case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break;
651 case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break;
652 case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break;
653 case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break;
654 case enumerationValue:
655 if(clDoc && clDoc.values)
657 itDoc = clDoc.values[((NamedLink)data).name];
658 if(itDoc) s = itDoc.description;
662 if(nsDoc && nsDoc.defines)
664 itDoc = nsDoc.defines[((Definition)data).name];
665 if(itDoc) s = itDoc.description;
669 if(clDoc && clDoc.conversions)
671 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
672 if(name) name += 2; else name = ((Property)data).name;
673 itDoc = clDoc.conversions[name];
674 if(itDoc) s = itDoc.description;
677 case memberDescription:
678 if(clDoc && clDoc.fields)
680 itDoc = clDoc.fields[((DataMember)data).name];
681 if(itDoc) s = itDoc.description;
684 case propertyDescription:
685 if(clDoc && clDoc.properties)
687 itDoc = clDoc.properties[((Property)data).name];
688 if(itDoc) s = itDoc.description;
692 if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters))
694 char * name = ((Type)data).name;
695 itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ;
696 if(itDoc) s = itDoc.description;
701 contents = CopyString(s);
703 if(editing && !contents && !readOnly)
704 contents = CopyString($"[Add Text]");
708 // The filePath is returned!
709 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
713 Method method = null;
719 case classDoc: cl = (Class)object; break;
720 case methodDoc: method = object; cl = method._class; break;
723 FigureFilePath(filePath, module, type, object, item, data);
725 entry = docCache[filePath];
731 File f = FileOpen(filePath, read);
734 ECONParser parser { f = f };
735 JSONResult jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
739 if(jsonResult != success)
741 PrintLn("error: problem parsing file: ", filePath);
746 doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
749 incref doc; // Reference to return
754 entry.timeStamp = now;
757 docCache[filePath] = { now, doc };
758 incref doc; // Reference for the cache
761 //void pruneDocCache()
762 // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
764 MapIterator<String, DocCacheEntry> it { map = docCache };
765 Array<const String> toRemove { };
766 for(entry : docCache; now - entry.timeStamp > 30)
767 toRemove.Add(&entry);
768 while(toRemove.count)
770 if(it.Index(toRemove.lastIterator.data, false))
775 toRemove.Remove(toRemove.lastIterator.pointer);
782 class APIPageNameSpace : APIPage
784 NameSpace * nameSpace;
792 NameSpace * GetNameSpace()
797 void Generate(File f)
799 char nsName[1024], temp[1024];
805 while(ns && ns->name)
807 strcpy(temp, ns->name);
808 if(nsName[0]) strcat(temp, "::");
809 strcat(temp, nsName);
810 strcpy(nsName, temp);
813 // Generate Class Page
814 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
817 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
818 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);
821 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
824 ns = nameSpace->parent;
825 while(ns && ns->name)
827 strcpy(temp, ns->name);
828 if(nsName[0]) strcat(temp, "::");
829 strcat(temp, nsName);
830 strcpy(nsName, temp);
834 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
838 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
841 f.Printf($"<H3>Description</H3><BR>\n");
844 char fileName[MAX_LOCATION];
845 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
846 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
851 f.Printf("%s", desc);
852 f.Printf("<br><br><br>");
857 if(nameSpace->nameSpaces.first)
860 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
862 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
865 f.Printf($"<H3>Sub Namespaces</H3><BR>\n");
866 f.Printf("<TABLE>\n");
870 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);
875 char fileName[MAX_LOCATION];
876 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
877 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
879 f.Printf("</a></TD>");
882 f.Printf("<TD valign=top height=22> %s</TD>", desc);
885 f.Printf("</TR><br>\n");
888 f.Printf("</TABLE><br><br>\n");
891 if(nameSpace->classes.first)
894 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
896 Class cl = link.data;
897 Module module = cl.module ? cl.module : this.module;
898 if(!cl.templateClass) // && !cl.internalDecl)
900 char * desc = ReadDoc(module, classDoc, cl, description, null);
904 f.Printf($"<a name=Classes></a><H3>Classes</H3><BR>\n");
905 f.Printf("<TABLE>\n");
911 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);
916 char fileName[MAX_LOCATION];
917 FigureFileName(fileName, module, classDoc, cl, description, null);
918 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
920 f.Printf("</a></TD>");
923 f.Printf("<TD valign=top height=22>%s</TD>", desc);
930 f.Printf("</TABLE><br><br>\n");
933 if(nameSpace->functions.first)
936 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
938 GlobalFunction function = link.data;
939 Module module = function.module ? function.module : this.module;
940 char * desc = ReadDoc(module, functionDoc, function, description, null);
941 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
942 if(name) name += 2; else name = function.name;
945 f.Printf($"<a name=Functions></a><H3>Functions</H3><BR>\n");
946 f.Printf("<TABLE>\n");
950 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);
955 char fileName[MAX_LOCATION];
956 FigureFileName(fileName, module, functionDoc, function, description, null);
957 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
959 f.Printf("</a></TD>");
962 f.Printf("<TD valign=top height=22> %s</TD>", desc);
965 f.Printf("</TR><br>\n");
968 f.Printf("</TABLE><br><br>\n");
971 if(nameSpace->defines.first)
974 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
976 DefinedExpression def = link.data;
977 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
980 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><BR>\n");
981 f.Printf("<TABLE>\n");
985 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);
986 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
991 char fileName[MAX_LOCATION];
992 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
993 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
995 f.Printf("</a></TD>");
998 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1001 f.Printf("</TR><br>\n");
1004 f.Printf("</TABLE><br><br>\n");
1007 f.Printf("</FONT></BODY></HTML>\n");
1011 class APIPageClass : APIPage
1020 NameSpace * GetNameSpace()
1022 return cl.nameSpace;
1025 void Generate(File f)
1030 char nsName[1024], temp[1024];
1031 NameSpace * ns = cl.nameSpace;
1032 Module module = cl.module;
1035 while(ns && ns->name)
1037 strcpy(temp, ns->name);
1038 if(nsName[0]) strcat(temp, "::");
1039 strcat(temp, nsName);
1040 strcpy(nsName, temp);
1043 // Generate Class Page
1044 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1045 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1047 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);
1049 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1052 const char * classType = null;
1056 classType = $"Bit Collection";
1059 classType = $"Enumeration";
1062 classType = $"Structure";
1065 classType = $"Class";
1068 classType = $"Class (No header)";
1071 classType = $"Unit";
1074 classType = $"Basic Data Type";
1077 f.Printf($"Type: %s<br>\n", classType);
1080 if(cl.type != systemClass && cl.base)
1082 f.Printf($"Base Class: ");
1083 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1085 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1087 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1088 f.Printf("%s", cl.dataTypeString);
1090 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1095 char * desc = ReadDoc(module, classDoc, cl, description, null);
1098 f.Printf($"<br><H3>Description</H3><BR>\n");
1101 char fileName[MAX_LOCATION];
1102 FigureFileName(fileName, module, classDoc, cl, description, null);
1103 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1108 f.Printf("%s", desc);
1109 f.Printf("<br><br><br>");
1114 if(cl.type == enumClass)
1116 EnumClassData enumeration = (EnumClassData)cl.data;
1117 if(enumeration.values.first)
1121 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><BR>\n");
1122 f.Printf("<TABLE>\n");
1124 for(item = enumeration.values.first; item; item = item.next)
1126 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1127 bool needClass = true;
1130 char tempString[1024];
1132 while(base.type == enumClass) base = base.base;
1134 if(base.type == systemClass ||
1135 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1138 base.dataType = ProcessTypeString(base.dataTypeString, false);
1140 if(base.dataType.kind != classType)
1145 PrintType(base.dataType, string, false, true);
1146 classSym = FindClass(string);
1147 dataClass = classSym ? classSym.registered : null;
1150 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1156 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);
1157 if(dataClass.type == systemClass)
1160 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1163 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1165 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1167 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1172 char fileName[MAX_LOCATION];
1173 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1174 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1176 f.Printf("</a></TD>");
1179 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1184 f.Printf("</TABLE><BR>\n");
1188 if(cl.conversions.first)
1190 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><BR>\n");
1191 f.Printf("<TABLE>\n");
1192 for(prop = cl.conversions.first; prop; prop = prop.next)
1194 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1196 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1198 Type type = ProcessTypeString(prop.name, false);
1199 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1200 if(name) name += 2; else name = prop.name;
1205 DocPrintType(type, string, true, false);
1207 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1212 char fileName[MAX_LOCATION];
1213 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1214 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1216 f.Printf("</a></TD>");
1219 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1223 f.Printf("</TR>\n");
1228 f.Printf("</TABLE><br><br>\n");
1231 if(cl.membersAndProperties.first)
1234 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1236 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1240 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><BR>\n");
1241 f.Printf("<TABLE>\n");
1247 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1249 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1253 DocPrintType(prop.dataType, string, true, false);
1255 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);
1256 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1261 char fileName[MAX_LOCATION];
1262 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1263 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1265 f.Printf("</a></TD>");
1268 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1271 f.Printf("</TR>\n");
1275 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1280 f.Printf("</TABLE><br><br>\n");
1283 if(cl.methods.first)
1287 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1289 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1291 char * desc = ReadDoc(module, methodDoc, method, description, null);
1294 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><BR>\n");
1295 f.Printf("<TABLE>\n");
1298 if(!method.dataType)
1299 ProcessMethodType(method);
1302 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);
1307 char fileName[MAX_LOCATION];
1308 FigureFileName(fileName, module, methodDoc, method, description, null);
1309 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1311 f.Printf("</a></TD>");
1314 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1317 f.Printf("</TR><br>\n");
1321 f.Printf("</TABLE><br><br>\n");
1323 // Non-Virtual Methods
1325 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1327 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1329 char * desc = ReadDoc(module, methodDoc, method, description, null);
1332 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><BR>\n");
1333 f.Printf("<TABLE>\n");
1337 if(!method.dataType)
1338 ProcessMethodType(method);
1341 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);
1346 char fileName[MAX_LOCATION];
1347 FigureFileName(fileName, module, methodDoc, method, description, null);
1348 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1350 f.Printf("</a></TD>");
1353 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1357 f.Printf("</TR><br>\n");
1361 f.Printf("</TABLE><br><br>\n");
1364 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1367 f.Printf($"<H3>Usage</H3><BR>\n");
1370 char fileName[MAX_LOCATION];
1371 FigureFileName(fileName, module, classDoc, cl, usage, null);
1372 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1377 f.Printf("<br>%s\n", usageDoc);
1378 f.Printf("<br><br><br>\n");
1383 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1386 f.Printf($"<H3>Example</H3><BR>\n");
1387 f.Printf($"<FONT face=\"Courier New\">\n");
1388 f.Printf("<br><TABLE>\n");
1391 char fileName[MAX_LOCATION];
1392 FigureFileName(fileName, module, classDoc, cl, example, null);
1393 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1395 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1398 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1400 f.Printf("</TABLE></FONT>\n");
1401 f.Printf("<br><br>\n");
1406 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1410 f.Printf($"<H3>Remarks</H3><BR>\n");
1413 char fileName[MAX_LOCATION];
1414 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1415 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1420 f.Printf("<br>%s\n", remarksDoc);
1421 f.Printf("<br><br><br>\n");
1426 if(cl.type != systemClass)
1430 for(c = cl.derivatives.first; c; c = c.next)
1432 Class deriv = c.data;
1433 // TO VERIFY: Does this properly check public status?
1434 if(eSystem_FindClass(componentsApp, deriv.fullName))
1438 f.Printf($"<H3>Derived Classes</H3><BR>\n");
1443 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1447 f.Printf("<br><br>\n");
1450 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1453 f.Printf($"<H3>See Also</H3>\n");
1456 char fileName[MAX_LOCATION];
1457 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1458 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1463 f.Printf("<br>%s\n", seeAlsoDoc);
1464 f.Printf("<br><br>\n");
1468 f.Printf("</FONT></BODY></HTML>\n");
1472 class APIPageMethod : APIPage
1478 return method._class.module;
1481 NameSpace * GetNameSpace()
1483 return method._class.nameSpace;
1486 void Generate(File f)
1488 Class cl = method._class;
1490 Module module = cl.module;
1492 char nsName[1024], temp[1024];
1493 NameSpace * ns = cl.nameSpace;
1496 while(ns && ns->name)
1498 strcpy(temp, ns->name);
1499 if(nsName[0]) strcat(temp, "::");
1500 strcat(temp, nsName);
1501 strcpy(nsName, temp);
1505 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1506 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1508 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);
1510 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1511 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1512 if(method.dataType.staticMethod)
1514 f.Printf($"this pointer class: None<br>\n");
1516 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1518 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);
1521 // Generate Method Page
1523 if(!method.dataType.name)
1524 method.dataType.name = CopyString(method.name);
1525 DocPrintType(method.dataType, string, true, false);
1526 f.Printf("<br>%s", string);
1529 char * desc = ReadDoc(module, methodDoc, method, description, null);
1532 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1535 char fileName[MAX_LOCATION];
1536 FigureFileName(fileName, module, methodDoc, method, description, null);
1537 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1542 f.Printf("%s", desc);
1543 f.Printf("<BR><BR>");
1548 f.Printf("<br><br>\n");
1549 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1551 f.Printf($"<H3>Parameters</H3><BR>\n");
1553 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1554 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1556 f.Printf("<TABLE valign=center>\n");
1559 for(param = method.dataType.params.first; param; param = param.next)
1561 // ADD DESCRIPTION HERE
1562 if(param.kind != voidType)
1564 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1567 DocPrintType(param, string, false, false);
1569 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1570 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1575 char fileName[MAX_LOCATION];
1576 FigureFileName(fileName, module, methodDoc, method, parameter, param);
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", desc);
1586 f.Printf("</TR>\n");
1589 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1591 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1592 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1594 f.Printf("<TR><TD> </TD></TR>");
1597 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1599 DocPrintType(method.dataType.returnType, string, false, false);
1600 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1605 char fileName[MAX_LOCATION];
1606 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1607 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1609 f.Printf("</a> </TD>\n");
1612 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1615 f.Printf("</TR>\n");
1616 f.Printf("</TABLE>\n");
1618 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1619 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1621 f.Printf("</TABLE><br>\n");
1624 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1627 f.Printf($"<H3>Usage</H3><BR>\n");
1630 char fileName[MAX_LOCATION];
1631 FigureFileName(fileName, module, methodDoc, method, usage, null);
1632 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1637 f.Printf("<br>%s\n", usageDoc);
1638 f.Printf("<br><br><br>\n");
1643 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1646 f.Printf($"<H3>Example</H3><BR>\n");
1647 f.Printf($"<FONT face=\"Courier New\">\n");
1648 f.Printf("<br><TABLE>\n");
1651 char fileName[MAX_LOCATION];
1652 FigureFileName(fileName, module, methodDoc, method, example, null);
1653 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1655 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1658 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1659 f.Printf("</TABLE></FONT>\n");
1660 f.Printf("<br><br>\n");
1665 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1668 f.Printf($"<H3>Remarks</H3><BR>\n");
1671 char fileName[MAX_LOCATION];
1672 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1673 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1678 f.Printf("<br>%s\n", method, remarksDoc);
1679 f.Printf("<br><br><br>\n");
1684 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1687 f.Printf($"<H3>See Also</H3><BR>\n");
1690 char fileName[MAX_LOCATION];
1691 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1692 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1697 f.Printf("<br>%s\n", method, seeAlsoDoc);
1699 f.Printf("<br><br><br>\n");
1703 f.Printf("</FONT></BODY></HTML>\n");
1707 class APIPageFunction : APIPage
1709 GlobalFunction function;
1713 return function.module;
1716 NameSpace * GetNameSpace()
1718 return function.nameSpace;
1721 void Generate(File f)
1724 Module module = function.module;
1726 char nsName[1024], temp[1024];
1727 NameSpace * ns = function.nameSpace;
1730 while(ns && ns->name)
1732 strcpy(temp, ns->name);
1733 if(nsName[0]) strcat(temp, "::");
1734 strcat(temp, nsName);
1735 strcpy(nsName, temp);
1739 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1740 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1742 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);
1745 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1747 if(!function.dataType)
1748 function.dataType = ProcessTypeString(function.dataTypeString, false);
1750 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1752 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);
1755 // Generate Method Page
1757 if(!function.dataType.name)
1758 function.dataType.name = CopyString(function.name);
1759 DocPrintType(function.dataType, string, true, false);
1760 f.Printf("<br>%s", string);
1763 char * desc = ReadDoc(module, functionDoc, function, description, null);
1766 f.Printf($"<br><br><H3>Description</H3><BR>\n");
1769 char fileName[MAX_LOCATION];
1770 FigureFileName(fileName, module, functionDoc, function, description, null);
1771 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1776 f.Printf("%s", desc);
1778 f.Printf("<BR><BR>");
1781 f.Printf("<br><br>\n");
1782 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1784 f.Printf($"<H3>Parameters</H3><BR>\n");
1786 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1787 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1789 f.Printf("<TABLE valign=center>\n");
1792 for(param = function.dataType.params.first; param; param = param.next)
1794 // ADD DESCRIPTION HERE
1795 if(param.kind != voidType)
1797 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1800 DocPrintType(param, string, false, false);
1802 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1803 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1808 char fileName[MAX_LOCATION];
1809 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1810 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1813 f.Printf("</a> </TD>\n");
1816 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1819 f.Printf("</TR>\n");
1822 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1824 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1825 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1827 f.Printf("<TR><TD> </TD></TR>");
1830 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1832 DocPrintType(function.dataType.returnType, string, false, false);
1833 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1838 char fileName[MAX_LOCATION];
1839 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1840 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1842 f.Printf("</a> </TD>\n");
1845 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1848 f.Printf("</TR>\n");
1849 f.Printf("</TABLE>\n");
1851 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1852 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1854 f.Printf("</TABLE><br>\n");
1857 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1860 f.Printf($"<H3>Usage</H3><BR>\n");
1863 char fileName[MAX_LOCATION];
1864 FigureFileName(fileName, module, functionDoc, function, usage, null);
1865 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1870 f.Printf("<br>%s\n", usageDoc);
1871 f.Printf("<br><br><br>\n");
1876 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1879 f.Printf($"<H3>Example</H3><BR>\n");
1880 f.Printf($"<FONT face=\"Courier New\">\n");
1881 f.Printf("<br><TABLE>\n");
1884 char fileName[MAX_LOCATION];
1885 FigureFileName(fileName, module, functionDoc, function, example, null);
1886 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1888 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1891 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1892 f.Printf("</TABLE></FONT>\n");
1893 f.Printf("<br><br>\n");
1898 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1901 f.Printf($"<H3>Remarks</H3><BR>\n");
1904 char fileName[MAX_LOCATION];
1905 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1906 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1911 f.Printf("<br>%s\n", remarksDoc);
1912 f.Printf("<br><br><br>\n");
1917 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1920 f.Printf($"<H3>See Also</H3><BR>\n");
1923 char fileName[MAX_LOCATION];
1924 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1925 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1930 f.Printf("<br>%s\n", seeAlsoDoc);
1931 f.Printf("<br><br><br>\n");
1935 f.Printf("</FONT></BODY></HTML>\n");
1939 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1943 NameSpace * nameSpace = mainNameSpace;
1945 DataRow classesRow = null;
1946 DataRow functionsRow = null, definesRow = null;
1949 strcpy(nsName, parentName ? parentName : "");
1953 strcat(nsName, "::");
1954 strcat(nsName, nameSpace->name);
1959 row = parentRow.AddRow();
1960 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1961 row.tag = (int64)nameSpace;
1962 row.icon = mainForm.icons[typeNameSpace];
1966 // "Global NameSpace"
1968 page = parentRow.GetData(null);
1971 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1973 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1974 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1976 if(comNameSpace != null)
1978 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1980 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1982 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1987 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1989 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1991 if(nameSpace->classes.first)
1995 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1998 if(!cl.templateClass /*&& !cl.internalDecl*/ && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
2000 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
2001 AddClass(classesRow, module, cl, nsName, showPrivate);
2008 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2010 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2012 if(nameSpace->functions.first)
2016 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2019 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2021 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2023 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2024 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2031 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2033 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2035 if(nameSpace->defines.first)
2039 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2042 //if(def.module == module)
2044 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2046 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2047 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2055 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2059 if(!member.dataType)
2060 member.dataType = ProcessTypeString(member.dataTypeString, false);
2064 DocPrintType(member.dataType, string, true, false);
2066 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2067 for(c = 0; c<indent; c++)
2068 f.Printf(" ");
2069 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2070 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2071 if(member.type == normalMember)
2073 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2078 char fileName[MAX_LOCATION];
2079 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2080 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2082 f.Printf("</a></TD>");
2085 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2090 f.Printf("<TD valign=top height=22></TD>");
2092 if(member.type != normalMember)
2094 DataMember subMember;
2095 for(subMember = member.members.first; subMember; subMember = subMember.next)
2097 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2099 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2103 f.Printf("</TR><br>\n");
2106 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2109 if(member.type == normalMember)
2111 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2112 row.tag = (int64)member;
2117 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2118 row.icon = mainForm.icons[typeData];
2119 row.tag = (int64)member;
2121 for(m = member.members.first; m; m = m.next)
2123 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2124 AddDataMember(row, page, m);
2129 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2134 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2135 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2138 row = parentRow.AddRow();
2139 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2140 row.tag = (int64)cl;
2141 row.collapsed = true;
2142 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2145 if(cl.methods.first)
2147 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2149 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2152 if(!method.dataType)
2153 ProcessMethodType(method);
2154 if(method.type == virtualMethod)
2156 if(method.dataType.thisClass)
2158 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2159 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2160 mRow.tag = (int64)method;
2164 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2165 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2166 mRow.tag = (int64)method;
2171 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2172 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2173 mRow.tag = (int64)method;
2179 if(cl.membersAndProperties.first)
2181 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2183 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2186 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2190 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2191 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2192 mRow.tag = (int64)prop;
2196 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2197 AddDataMember(membersRow, page, (DataMember)prop);
2203 if(cl.conversions.first)
2205 for(prop = cl.conversions.first; prop; prop = prop.next)
2209 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2210 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2211 if(name) name += 2; else name = prop.name;
2212 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2213 mRow.tag = (int64)prop;
2216 if(cl.type == enumClass)
2218 EnumClassData enumeration = (EnumClassData)cl.data;
2220 for(item = enumeration.values.first; item; item = item.next)
2223 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2224 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2225 mRow.tag = (int64)item;
2230 class AddressBar : Window
2232 background = activeBorder;
2236 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2238 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2240 MainForm mainForm = (MainForm)parent;
2241 FileDialog fileDialog = mainForm.fileDialog;
2242 if(fileDialog.Modal() == ok)
2243 mainForm.OpenModule(fileDialog.filePath);
2249 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2252 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2254 ((MainForm)parent).Back();
2260 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2263 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2265 ((MainForm)parent).Forward();
2271 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2273 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2275 ((MainForm)parent).Home();
2279 /* TODO: Search (#143/#441)
2280 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2281 Update this in the NotifyUpdate. Enter goes to the exact match.
2283 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2287 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2289 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2291 if(!disabled && (SmartKey)key == enter)
2292 ((MainForm)parent).Go(editBox.contents);
2296 void NotifyUpdate(EditBox editBox)
2298 String location = ((MainForm)parent).view.location;
2299 disabled = !strcmp(location ? location : "", editBox.contents);
2304 bool OnKeyHit(Key key, unichar ch)
2307 ((MainForm)parent).view.MakeActive();
2312 class MainForm : Window
2314 size = { 1000, 600 };
2316 borderStyle = sizable;
2319 icon = { ":documentorIcon.png" };
2320 text = $"API Documentation Browser";
2322 BitmapResource icons[CodeObjectType];
2327 for(c = 0; c < CodeObjectType::enumSize; c++)
2329 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2331 browser.AddField(DataField { dataType = class(APIPage) });
2336 Menu fileMenu { menu, $"File", f };
2337 Array<FileFilter> fileFilters
2339 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2340 { $"eC Symbol files (*.sym)", "sym" }
2343 FileDialog fileDialog
2345 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2347 MenuItem fileOpenItem
2349 fileMenu, $"Open...", o, ctrlO;
2351 bool NotifySelect(MenuItem selection, Modifiers mods)
2353 if(fileDialog.Modal() == ok)
2355 OpenModule(fileDialog.filePath);
2360 MenuItem fileSettingsItem
2362 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2364 bool NotifySelect(MenuItem selection, Modifiers mods)
2366 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2376 MenuDivider { fileMenu };
2377 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2379 void OpenModule(const char * filePath)
2381 char moduleName[MAX_LOCATION];
2382 char extension[MAX_EXTENSION];
2383 Module module = null;
2384 static char symbolsDir[MAX_LOCATION];
2387 modulesAdded.RemoveAll();
2389 FreeContext(globalContext);
2390 FreeExcludedSymbols(excludedSymbols);
2391 ::defines.Free(FreeModuleDefine);
2392 imports.Free(FreeModuleImport);
2394 FreeGlobalData(globalData);
2398 FreeTypeData(componentsApp);
2399 delete componentsApp;
2402 componentsApp = __ecere_COM_Initialize(false, 1, null);
2403 SetPrivateModule(componentsApp);
2405 StripLastDirectory(filePath, symbolsDir);
2406 SetSymbolsDir(symbolsDir);
2408 GetExtension(filePath, extension);
2410 mainForm.browser.Clear();
2412 ImportModule(filePath, normalImport, publicAccess, false);
2414 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2415 componentsApp.name = CopyString(filePath);
2417 for(module = componentsApp.allModules.first; module; module = module.next)
2419 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2423 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2424 AddComponents(componentsApp, false);
2426 GetLastDirectory(filePath, moduleName);
2427 // Extension, path and lib prefix get removed in Module::name
2430 StripExtension(moduleName);
2431 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2433 int len = strlen(moduleName) - 3;
2434 memmove(moduleName, moduleName + 3, len);
2435 moduleName[len] = 0;
2439 for(module = componentsApp.allModules.first; module; module = module.next)
2441 if(module.name && (!strcmp(module.name, moduleName)))
2444 if(!module) module = componentsApp;
2445 homeModule = module;
2446 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2448 SetSymbolsDir(null);
2451 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2454 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2455 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2458 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2460 APIPage page = row.GetData(null);
2461 if(view.edit) view.OnLeftButtonDown(0,0,0);
2462 if(page && page.page) page = page.page;
2464 view.PositionCaret(true);
2465 if(page != view.page)
2467 Window activeChild = this.activeChild;
2469 // Back / Forward Support
2470 if(row && !dontRecordHistory)
2472 if(history.count > historyPos+1)
2473 history.count = historyPos+1;
2474 historyPos = history.count-1;
2475 addressBar.back.disabled = (historyPos == 0);
2476 addressBar.forward.disabled = (historyPos >= history.count-1);
2478 history.Add((Instance)(uint64)row.tag);
2479 historyPos = history.count-1;
2481 addressBar.back.disabled = (historyPos == 0);
2482 addressBar.forward.disabled = (historyPos >= history.count-1);
2488 activeChild.Activate();
2490 else if(!view.created)
2494 page = row.GetData(null);
2495 if(page && page.page)
2499 case 1: view.GoToAnchor("Classes"); break;
2500 case 2: view.GoToAnchor("Functions"); break;
2501 case 3: view.GoToAnchor("Definitions"); break;
2502 case 4: view.GoToAnchor("VirtualMethods"); break;
2503 case 5: view.GoToAnchor("Methods"); break;
2504 case 6: view.GoToAnchor("Members"); break;
2505 case 7: view.GoToAnchor("Conversions"); break;
2506 case 8: view.GoToAnchor("EnumerationValues"); break;
2510 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2511 view.GoToAnchor(hex);
2517 view.SetScrollPosition(0, 0);
2525 this, anchor = { top = 26, bottom = 0, right = 0 };
2530 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2533 bool OnClose(bool parentClosing)
2536 view.OnLeftButtonDown(0,0,0);
2542 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2543 //mainForm.OpenModule("ec");
2544 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2545 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2547 int index = mainForm.browser.currentRow.index;
2548 int rowHeight = mainForm.browser.rowHeight;
2549 int height = mainForm.browser.clientSize.h;
2551 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2556 Array<Instance> history { };
2558 bool dontRecordHistory;
2561 bool OnKeyHit(Key key, unichar ch)
2565 case altLeft: Back(); return false;
2566 case altRight: Forward(); return false;
2573 if(historyPos < history.count-1)
2577 addressBar.back.disabled = (historyPos == 0);
2578 addressBar.forward.disabled = (historyPos >= history.count-1);
2579 sprintf(location, "api://%p", history[historyPos]);
2580 dontRecordHistory = true;
2581 view.OnOpen(location);
2582 dontRecordHistory = false;
2594 addressBar.back.disabled = (historyPos == 0);
2595 addressBar.forward.disabled = (historyPos >= history.count-1);
2596 sprintf(location, "api://%p", history[historyPos]);
2597 dontRecordHistory = true;
2598 view.OnOpen(location);
2599 dontRecordHistory = false;
2607 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2611 class EditDialog : Window
2613 borderStyle = sizable;
2614 size = { 600, 400 };
2619 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2623 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2627 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2631 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2632 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2634 class HelpView : HTMLView
2638 hasVertScroll = true;
2639 hasHorzScroll = true;
2641 char editString[MAX_LOCATION];
2647 page = mainForm.browser.currentRow.GetData(null);
2652 char docDir[MAX_LOCATION];
2654 strcpy(docDir, ideSettings.docDir);
2655 if(FileExists(docDir).isDirectory)
2657 PathCatSlash(docDir, "___docWriteTest");
2658 if(FileExists(docDir).isDirectory)
2661 if(!FileExists(docDir))
2667 if(FileExists(docDir).isDirectory)
2679 GoToAnchor(page.label);
2681 if(page.page) page = page.page;
2684 return HTMLView::OnCreate();
2695 String contents = null;
2698 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2700 if(block.type == TEXT && block.textLen)
2708 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2710 if(block.type == BR)
2712 else if(block.type == TEXT)
2713 f.Write(block.text, 1, block.textLen);
2717 if((len = f.GetSize()))
2719 contents = new char[len+1];
2720 f.Read(contents, 1, len);
2721 contents[len] = '\0';
2725 char docPath[MAX_LOCATION];
2726 char temp[MAX_LOCATION];
2727 char part[MAX_FILENAME];
2731 DocumentationType type;
2732 DocumentationItem item;
2734 NamespaceDoc nsDoc = null;
2735 ClassDoc clDoc = null;
2736 FunctionDoc fnDoc = null;
2737 MethodDoc mdDoc = null;
2739 Method method = null;
2740 GlobalFunction function = null;
2742 strcpy(temp, editString);
2743 SplitDirectory(temp, part, temp);
2744 module = (Module)strtoull(part, null, 16);
2745 SplitDirectory(temp, part, temp);
2746 object = (void *)strtoull(part, null, 16);
2747 SplitDirectory(temp, part, temp);
2748 data = (void *)strtoull(part, null, 16);
2749 SplitDirectory(temp, part, temp);
2750 if(!strcmp(part, "namespace"))
2751 type = nameSpaceDoc;
2752 else if(!strcmp(part, "function"))
2754 else if(!strcmp(part, "class"))
2756 else if(!strcmp(part, "method"))
2758 SplitDirectory(temp, part, temp);
2759 if(!strcmp(part, "description"))
2761 else if(!strcmp(part, "usage"))
2763 else if(!strcmp(part, "remarks"))
2765 else if(!strcmp(part, "example"))
2767 else if(!strcmp(part, "seeAlso"))
2769 else if(!strcmp(part, "enumerationValue"))
2770 item = enumerationValue;
2771 else if(!strcmp(part, "definition"))
2773 else if(!strcmp(part, "conversion"))
2775 else if(!strcmp(part, "memberDescription"))
2776 item = memberDescription;
2777 else if(!strcmp(part, "propertyDescription"))
2778 item = propertyDescription;
2779 else if(!strcmp(part, "parameter"))
2781 else if(!strcmp(part, "returnValue"))
2784 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2786 /* Why invalidate this entry here?
2788 MapIterator<const String, DocCacheEntry> it { map = docCache };
2789 if(it.Index(docPath, false))
2798 case classDoc: cl = (Class)object; break;
2799 case functionDoc: function = object; break;
2800 case methodDoc: method = object; cl = method._class; break;
2805 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2807 clDoc = (ClassDoc)doc;
2809 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2811 nsDoc = (NamespaceDoc)doc;
2817 if(type == functionDoc)
2819 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2820 if(name) name += 2; else name = function.name;
2821 fnDoc = nsDoc.functions ? nsDoc.functions[name] : null;
2822 if(!empty && !fnDoc)
2824 if(!nsDoc.functions) nsDoc.functions = { };
2825 nsDoc.functions[name] = fnDoc = { };
2828 else if(type == methodDoc)
2830 mdDoc = clDoc.methods ? clDoc.methods[method.name] : null;
2831 if(!empty && !mdDoc)
2833 if(!clDoc.methods && !empty) clDoc.methods = { };
2834 clDoc.methods[method.name] = mdDoc = { };
2838 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2843 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2844 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2845 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2846 else { nsDoc.description = contents; contents = null; }
2849 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2850 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2851 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2854 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2855 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2856 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2859 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2860 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2861 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2864 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2865 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2866 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2869 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2870 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2872 case enumerationValue:
2874 ValueDoc itDoc = clDoc.values ? clDoc.values[((NamedLink)data).name] : null;
2877 if(!empty && !itDoc)
2879 if(!clDoc.values) clDoc.values = { };
2880 clDoc.values[((NamedLink)data).name] = itDoc = { };
2882 itDoc.description = contents; contents = null;
2885 MapIterator<String, ValueDoc> it { map = clDoc.values };
2886 if(it.Index(((NamedLink)data).name, false))
2895 DefineDoc itDoc = nsDoc.defines ? nsDoc.defines[((Definition)data).name] : null;
2898 if(!empty && !itDoc)
2900 if(!nsDoc.defines) nsDoc.defines = { };
2901 nsDoc.defines[((Definition)data).name] = itDoc = { };
2903 itDoc.description = contents; contents = null;
2906 MapIterator<String, DefineDoc> it { map = nsDoc.defines };
2907 if(it.Index(((Definition)data).name, false))
2916 ConversionDoc itDoc;
2917 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2918 if(name) name += 2; else name = ((Property)data).name;
2919 itDoc = clDoc.conversions ? clDoc.conversions[name] : null;
2922 if(!empty && !itDoc)
2924 if(!clDoc.conversions) clDoc.conversions = { };
2925 clDoc.conversions[name] = itDoc = { };
2927 itDoc.description = contents; contents = null;
2930 MapIterator<String, ConversionDoc> it { map = clDoc.conversions };
2931 if(it.Index(name, false))
2938 case memberDescription:
2940 FieldDoc itDoc = clDoc.fields ? clDoc.fields[((DataMember)data).name] : null;
2943 if(!empty && !itDoc)
2945 if(!clDoc.fields) clDoc.fields = { };
2946 clDoc.fields[((DataMember)data).name] = itDoc = { };
2948 itDoc.description = contents; contents = null;
2951 MapIterator<String, FieldDoc> it { map = clDoc.fields };
2952 if(it.Index(((DataMember)data).name, false))
2959 case propertyDescription:
2961 PropertyDoc itDoc = clDoc.properties ? clDoc.properties[((Property)data).name] : null;
2964 if(!empty && !itDoc)
2966 if(!clDoc.properties) clDoc.properties = { };
2967 clDoc.properties[((Property)data).name] = itDoc = { };
2969 itDoc.description = contents, contents = null;
2972 MapIterator<String, PropertyDoc> it { map = clDoc.properties };
2973 if(it.Index(((Property)data).name, false))
2982 if(type == functionDoc || type == methodDoc)
2984 Map<String, ParameterDoc> * parameters = (type == functionDoc) ? &fnDoc.parameters : &mdDoc.parameters;
2985 char * name = ((Type)data).name;
2986 ParameterDoc itDoc = *parameters ? (*parameters)[name] : null;
2989 while(prev) position++, prev = prev.prev;
2993 if(!empty && !itDoc)
2995 if(!*parameters) *parameters = { };
2996 (*parameters)[name] = itDoc = { };
2998 itDoc.description = contents; contents = null;
2999 itDoc.position = position;
3002 MapIterator<String, ParameterDoc> it { map = *parameters };
3003 if(it.Index(((Type)data).name, false))
3015 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
3017 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
3018 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
3019 if(name) name += 2; else name = function.name;
3020 if(it.Index(name, false))
3024 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
3026 MapIterator<String, MethodDoc> it { map = clDoc.methods };
3027 if(it.Index(method.name, false))
3033 if(nsDoc.functions && !nsDoc.functions.count) delete nsDoc.functions;
3034 if(nsDoc.defines && !nsDoc.defines.count) delete nsDoc.defines;
3038 if(clDoc && clDoc.conversions && !clDoc.conversions.count) delete clDoc.conversions;
3039 if(clDoc && clDoc.properties && !clDoc.properties.count) delete clDoc.properties;
3040 if(clDoc && clDoc.fields && !clDoc.fields.count) delete clDoc.fields;
3041 if(clDoc && clDoc.methods && !clDoc.methods.count) delete clDoc.methods;
3042 if(clDoc && clDoc.values && !clDoc.values.count) delete clDoc.values;
3047 char dirPath[MAX_LOCATION];
3048 StripLastDirectory(docPath, dirPath);
3049 if(FileExists(docPath))
3050 DeleteFile(docPath);
3051 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
3054 if(!FileExists(dirPath))
3056 if((f = FileOpen(docPath, write)))
3058 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3062 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3071 Block parent = textBlock.parent;
3072 while((block = parent.subBlocks.first))
3074 parent.subBlocks.Remove(block);
3077 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3078 textBlock.text = CopyString($"[Add Text]");
3079 textBlock.textLen = strlen(textBlock.text);
3080 parent.subBlocks.Add(textBlock);
3088 PositionCaret(true);
3093 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3097 if(edit && (!textBlock || overLink != textBlock.parent))
3101 HTMLView::OnLeftButtonDown(x, y, mods);
3102 selPosition = curPosition = 0;
3103 selBlock = textBlock;
3107 result = HTMLView::OnLeftButtonDown(x, y, mods);
3109 if(!edit && clickedLink)
3112 if(clickedLink == overLink && clickedLink.href)
3114 if(OnOpen(clickedLink.href))
3122 if(textBlock && overLink == textBlock.parent)
3124 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3125 selBlock = textBlock;
3126 PositionCaret(true);
3134 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3136 if(!edit || !textBlock || clickedLink != textBlock.parent)
3138 HTMLView::OnLeftButtonUp(x, y, mods);
3141 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3142 selBlock = textBlock;
3143 PositionCaret(true);
3154 bool OnMouseMove(int x, int y, Modifiers mods)
3156 if(edit && selecting)
3158 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3159 PositionCaret(true);
3162 return HTMLView::OnMouseMove(x, y, mods);
3165 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3167 if(edit && textBlock)
3173 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3174 selBlock = textBlock;
3175 for(c = curPosition; c >= 0; c--)
3178 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3179 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3180 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3186 for(c = start; c < textBlock.textLen; c += numBytes)
3188 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3189 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3192 selPosition = start;
3195 PositionCaret(true);
3203 bool OnOpen(char * href)
3205 if(!strncmp(href, "api://", 6))
3207 int64 tag = (int64)strtoull(href + 6, null, 16);
3208 DataRow row = mainForm.browser.FindSubRow(tag);
3212 mainForm.browser.SelectRow(row);
3213 while((row = row.parent))
3214 row.collapsed = false;
3215 row = mainForm.browser.currentRow;
3216 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3219 else if(!strncmp(href, "edit://", 7))
3222 int startX = clickedLink.startX, startY = clickedLink.startY;
3223 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3225 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3226 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3228 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3230 display.FontExtent(block.font.font, " ", 1, null, &th);
3233 block.parent.subBlocks.Insert(null, newBlock);
3238 block.parent.subBlocks.Insert(block, newBlock);
3239 startY += block.prev.height;
3241 newBlock.startX = startX;
3242 newBlock.startY = startY;
3243 newBlock.text = new0 char[1];
3247 textBlock = (Block)clickedLink.subBlocks.first;
3248 if(!strcmp(textBlock.text, $"[Add Text]"))
3250 textBlock.text[0] = 0;
3251 textBlock.textLen = 0;
3254 strcpy(editString, href + 7);
3255 selPosition = curPosition = 0;
3256 selBlock = textBlock;
3259 // PositionCaret(true);
3261 // TOCHECK: Adding this here seemed to fixed caret positioning bugs
3269 void DeleteSelection()
3271 if(textBlock != selBlock || curPosition != selPosition)
3273 if(textBlock == selBlock)
3275 // Within same block
3276 int start = Min(curPosition, selPosition);
3277 int end = Max(curPosition, selPosition);
3278 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3279 textBlock.textLen -= end-start;
3280 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3281 curPosition = start;
3282 selPosition = start;
3286 int startSel, endSel;
3287 Block startSelBlock = null, endSelBlock = null, b, next;
3289 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3291 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3292 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3294 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3295 for(b = startSelBlock.next; b; b = next)
3297 bool isEnd = b == endSelBlock;
3298 next = GetNextBlock(b);
3299 b.parent.subBlocks.Remove(b);
3304 textBlock = startSelBlock;
3305 selBlock = startSelBlock;
3306 curPosition = startSel;
3307 selPosition = startSel;
3311 PositionCaret(true);
3316 String GetSelectionString()
3318 String selection = null;
3319 if(textBlock == selBlock)
3321 // Within same block
3322 int start = Min(curPosition, selPosition);
3323 int end = Max(curPosition, selPosition);
3324 int len = end - start;
3325 selection = new char[len + 1];
3326 memcpy(selection, textBlock.text + start, len);
3331 int startSel, endSel;
3332 Block startSelBlock = null, endSelBlock = null, b;
3335 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3338 for(b = startSelBlock; b; b = GetNextBlock(b))
3340 int start = (b == startSelBlock) ? startSel : 0;
3341 int end = (b == endSelBlock) ? endSel : b.textLen;
3342 int len = end - start;
3344 if(b == endSelBlock)
3346 else if(b.type == TEXT)
3350 selection = new char[totalLen + 1];
3352 for(b = startSelBlock; b; b = GetNextBlock(b))
3354 int start = (b == startSelBlock) ? startSel : 0;
3355 int end = (b == endSelBlock) ? endSel : b.textLen;
3356 int len = end - start;
3357 memcpy(selection + totalLen, b.text + start, len);
3359 if(b == endSelBlock)
3361 else if(b.type == TEXT)
3362 selection[totalLen++] = '\n';
3364 selection[totalLen] = 0;
3369 void CopySelection()
3371 String s = GetSelectionString();
3374 int len = strlen(s);
3376 if(cb.Allocate(len + 1))
3378 memcpy(cb.text, s, len + 1);
3386 bool OnKeyDown(Key key, unichar ch)
3393 OnLeftButtonDown(0,0,0);
3395 case Key { end, shift = true }:
3397 curPosition = textBlock.textLen;
3400 selPosition = curPosition;
3401 selBlock = textBlock;
3403 PositionCaret(true);
3406 case Key { home, shift = true }:
3411 selPosition = curPosition;
3412 selBlock = textBlock;
3414 PositionCaret(true);
3417 case Key { home, ctrl = true, shift = true }:
3420 while(textBlock.prev)
3421 textBlock = textBlock.prev.prev;
3424 selPosition = curPosition;
3425 selBlock = textBlock;
3427 PositionCaret(true);
3430 case Key { end, ctrl = true, shift = true }:
3432 while(textBlock.next && textBlock.next.next)
3433 textBlock = textBlock.next.next;
3434 curPosition = textBlock.textLen;
3437 selPosition = curPosition;
3438 selBlock = textBlock;
3440 PositionCaret(true);
3446 return HTMLView::OnKeyDown(key, ch);
3450 bool OnKeyHit(Key key, unichar ch)
3456 case Key { up, shift = true }:
3459 if(caretY == textBlock.startY)
3463 textBlock = textBlock.prev.prev;
3464 curPosition = Min(curPosition, textBlock.textLen);
3467 selPosition = curPosition;
3468 selBlock = textBlock;
3471 PositionCaret(false);
3481 int sx = textBlock.startX, sy = textBlock.startY;
3482 char * text = textBlock.text;
3484 Block block = textBlock;
3485 while(block && block.type != TD) block = block.parent;
3488 Block table = block;
3489 while(table && table.type != TABLE) table = table.parent;
3491 maxW = block.w - 2* table.cellPadding;
3493 maxW = clientSize.w - 10 - sx;
3496 maxW = clientSize.w - 10 - sx;
3497 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3501 int startPos = textPos;
3504 bool lineComplete = false;
3505 for(; textPos<textBlock.textLen && !lineComplete;)
3509 char * nextSpace = strchr(text + textPos, ' ');
3512 len = (nextSpace - (text + textPos)) + 1;
3514 len = textBlock.textLen - textPos;
3516 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3518 if(x + width + w > maxW && x > 0)
3520 lineComplete = true;
3530 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3533 curPosition = textPos;
3534 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3537 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3538 len = curPosition - startPos;
3539 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3543 selPosition = curPosition;
3544 selBlock = textBlock;
3548 PositionCaret(false);
3552 if(sy == caretY - th || textPos == textBlock.textLen)
3554 if(textPos != textBlock.textLen)
3556 int c = textPos - 1;
3557 while(c > 0 && text[c] == ' ') c--;
3558 curPosition = c + 1;
3561 selPosition = curPosition;
3562 selBlock = textBlock;
3568 curPosition = textBlock.textLen;
3571 selPosition = curPosition;
3572 selBlock = textBlock;
3576 PositionCaret(false);
3580 sx = textBlock.startX;
3581 } while(textPos < textBlock.textLen);
3586 case Key { down, shift = true }:
3591 int sx = textBlock.startX, sy = textBlock.startY;
3592 char * text = textBlock.text;
3594 Block block = textBlock;
3595 while(block && block.type != TD) block = block.parent;
3598 Block table = block;
3599 while(table && table.type != TABLE) table = table.parent;
3601 maxW = block.w - 2* table.cellPadding;
3603 maxW = clientSize.w - 10 - sx;
3606 maxW = clientSize.w - 10 - sx;
3607 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3609 while(!textPos || textPos < textBlock.textLen)
3611 int startPos = textPos;
3614 bool lineComplete = false;
3615 for(; (textPos < textBlock.textLen) && !lineComplete;)
3619 char * nextSpace = strchr(text + textPos, ' ');
3622 len = (nextSpace - (text + textPos)) + 1;
3624 len = textBlock.textLen - textPos;
3626 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3628 if(x + width + w > maxW && x > 0)
3630 lineComplete = true;
3640 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3642 curPosition = textPos;
3644 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3647 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3648 len = curPosition - startPos;
3649 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3653 selPosition = curPosition;
3654 selBlock = textBlock;
3657 PositionCaret(false);
3663 curPosition = textBlock.textLen;
3666 selPosition = curPosition;
3667 selBlock = textBlock;
3670 PositionCaret(false);
3673 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3677 textBlock = textBlock.next.next;
3678 sy = textBlock.startY;
3679 sx = textBlock.startX;
3680 text = textBlock.text;
3685 sx = textBlock.startX;
3689 /*if(textBlock.next && textBlock.next.next)
3691 textBlock = textBlock.next.next;
3692 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3693 selBlock = textBlock;
3694 PositionCaret(false);
3698 case Key { right, shift = true, ctrl = true }:
3701 bool foundAlpha = false;
3703 Block line, lastLine;
3706 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3708 int start = (line == textBlock) ? curPosition : 0;
3710 for(c = start; c < line.textLen; c++)
3712 char ch = line.text[c];
3713 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3714 if(key.shift ? isAlUnder : !isAlUnder)
3728 selPosition = curPosition;
3729 selBlock = textBlock;
3733 PositionCaret(true);
3738 // No next word found,
3739 if(!found && (c != curPosition || line != textBlock))
3743 lastC = line.textLen-1;
3748 curPosition = line.textLen;
3751 selPosition = curPosition;
3752 selBlock = textBlock;
3757 PositionCaret(true);
3763 if(key.shift && found)
3765 curPosition = lastC+1;
3766 textBlock = lastLine;
3767 PositionCaret(true);
3772 case Key { left, ctrl = true, shift = true }:
3775 bool foundAlpha = false;
3777 Block line, lastLine;
3780 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3783 if(curPosition == 0 && line != textBlock)
3786 lastC = line.textLen;
3790 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3791 for(c = start; c>=0; c--)
3793 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3808 // No next word found,
3809 if(!found && curPosition > 0)
3819 textBlock = lastLine;
3820 curPosition = lastC;
3823 selPosition = curPosition;
3824 selBlock = textBlock;
3826 PositionCaret(true);
3831 case Key { right, shift = true }:
3833 if(curPosition < textBlock.textLen)
3835 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3838 selPosition = curPosition;
3839 selBlock = textBlock;
3841 PositionCaret(true);
3844 else if(textBlock.next && textBlock.next.next)
3846 textBlock = textBlock.next.next;
3850 selPosition = curPosition;
3851 selBlock = textBlock;
3853 PositionCaret(true);
3857 case Key { left, shift = true }:
3861 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3864 selPosition = curPosition;
3865 selBlock = textBlock;
3867 PositionCaret(true);
3870 else if(textBlock.prev)
3872 textBlock = textBlock.prev.prev;
3873 curPosition = textBlock.textLen;
3876 selPosition = curPosition;
3877 selBlock = textBlock;
3879 PositionCaret(true);
3885 if(textBlock == selBlock && curPosition == selPosition)
3889 int c = curPosition;
3891 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3892 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3893 textBlock.textLen -= nb;
3894 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3896 selPosition = curPosition;
3897 selBlock = textBlock;
3901 PositionCaret(true);
3904 else if(textBlock.prev)
3906 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3907 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3908 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3910 selPosition = curPosition = prevBlock.textLen;
3911 selBlock = textBlock;
3912 prevBlock.textLen += textBlock.textLen;
3913 textBlock.parent.subBlocks.Remove(prev);
3914 if(prev == selBlock)
3916 selBlock = textBlock;
3917 selPosition = curPosition;
3920 textBlock.parent.subBlocks.Remove(textBlock);
3921 if(textBlock == selBlock)
3923 selBlock = prevBlock;
3924 selPosition = curPosition;
3927 textBlock = prevBlock;
3931 PositionCaret(true);
3940 if(textBlock != selBlock || curPosition != selPosition)
3942 else if(textBlock.textLen > curPosition)
3944 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3945 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3946 textBlock.textLen -= nb;
3947 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3952 PositionCaret(true);
3955 else if(textBlock.next && textBlock.next.next)
3957 Block next = textBlock.next, nextBlock = textBlock.next.next;
3958 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3959 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3961 textBlock.textLen += nextBlock.textLen;
3962 textBlock.parent.subBlocks.Remove(next);
3963 if(next == selBlock)
3965 selBlock = textBlock;
3966 selPosition = curPosition;
3969 textBlock.parent.subBlocks.Remove(nextBlock);
3970 if(nextBlock == selBlock)
3972 selBlock = textBlock;
3973 selPosition = curPosition;
3979 PositionCaret(true);
3993 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3994 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3995 startY = textBlock.startY;
3996 startX = textBlock.startX;
3998 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3999 textBlock.parent.subBlocks.Insert(textBlock, block);
4000 textBlock.parent.subBlocks.Insert(block, newBlock);
4004 newBlock.textLen = textBlock.textLen - curPosition;
4005 newBlock.text = new char[newBlock.textLen+1];
4006 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4007 textBlock.textLen = curPosition;
4008 textBlock.text[curPosition] = 0;
4010 newBlock.startY = startY;
4011 newBlock.startX = startX;
4012 selPosition = curPosition = 0;
4017 textBlock = newBlock;
4018 selBlock = textBlock;
4019 PositionCaret(true);
4024 case Key { del, shift = true }:
4039 ClipBoard clipBoard { };
4040 if(clipBoard.Load())
4043 char * text = clipBoard.memory;
4051 parent = textBlock.parent;
4052 font = textBlock.font;
4057 if(ch == '\n' || ch == '\r' || !ch)
4059 int len = c - start;
4060 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
4061 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4062 memcpy(textBlock.text + curPosition, text + start, len);
4063 textBlock.textLen += len;
4065 selPosition = curPosition;
4066 selBlock = textBlock;
4069 Block block { type = BR, parent = parent, font = font };
4070 Block newBlock { type = TEXT, parent = parent, font = font };
4071 int startY = textBlock.startY, startX = textBlock.startX;
4074 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4075 textBlock.parent.subBlocks.Insert(textBlock, block);
4076 textBlock.parent.subBlocks.Insert(block, newBlock);
4080 newBlock.textLen = textBlock.textLen - curPosition;
4081 newBlock.text = new char[newBlock.textLen+1];
4082 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4083 textBlock.textLen = curPosition;
4084 textBlock.text[curPosition] = 0;
4086 newBlock.startY = startY;
4087 newBlock.startX = startX;
4088 selPosition = curPosition = 0;
4089 selBlock = textBlock;
4090 textBlock = newBlock;
4092 if(ch == '\r' && text[c+1] == '\n') c++;
4098 PositionCaret(true);
4106 // eC BUG HERE: (Should be fixed)
4107 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4110 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4115 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4116 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4118 for(c = 0; c<len; c++)
4120 textBlock.text[curPosition] = string[c];
4121 textBlock.textLen++;
4124 selPosition = curPosition;
4125 selBlock = textBlock;
4128 //Clear(html.block);
4129 //CreateForms(html.block);
4134 PositionCaret(true);
4143 void OnResize(int width, int height)
4145 HTMLView::OnResize(width, height);
4146 PositionCaret(true);
4150 void PositionCaret(bool setCaretX)
4156 int sx = textBlock.startX, sy = textBlock.startY;
4157 char * text = textBlock.text;
4159 Block block = textBlock;
4161 while(block && block.type != TD) block = block.parent;
4164 Block table = block;
4165 while(table && table.type != TABLE) table = table.parent;
4167 maxW = block.w - 2* table.cellPadding;
4169 maxW = clientSize.w - 10 - sx;
4172 maxW = clientSize.w - 10 - sx;
4174 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4176 // Work around to re-align with first line having different indentation because of before <A> of current block
4178 Block parent = textBlock.parent;
4179 while(parent && parent.type == ANCHOR) parent = parent.parent;
4180 if(parent && parent.subBlocks.first && ((Block)parent.subBlocks.first).type == TEXT)
4181 xOffset = sx - ((Block)parent.subBlocks.first).startX;
4184 while(textPos < textBlock.textLen)
4186 int startPos = textPos;
4189 bool lineComplete = false;
4191 for(; textPos<textBlock.textLen && !lineComplete;)
4195 char * nextSpace = strchr(text + textPos, ' ');
4198 len = (nextSpace - (text + textPos)) + 1;
4200 len = textBlock.textLen - textPos;
4202 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4204 if(x + width + w > maxW && x > 0)
4206 lineComplete = true;
4219 if(curPosition < textPos || textPos == textBlock.textLen)
4221 int len = curPosition - startPos;
4222 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4227 sx = textBlock.startX - xOffset;
4232 SetCaret(sx-1, sy, th);
4234 Point scrollPos = scroll;
4235 bool doScroll = false;
4236 if(sy - scroll.y + th > clientSize.h)
4238 scrollPos.y = sy + th - clientSize.h;
4241 else if(sy - scroll.y < 0)
4246 if(sx - scroll.x + 10 > clientSize.w)
4248 scrollPos.x = sx + 10 - clientSize.w;
4251 else if(sx - scroll.x < 10)
4253 scrollPos.x = sx - 10;
4264 // Returns a character offset into the TextBlock from a window coordinate
4265 int TextPosFromPoint(int px, int py, Block * block, bool half)
4267 Block parentBlock = this.textBlock.parent;
4270 *block = this.textBlock;
4275 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4277 int sx = textBlock.startX, sy = textBlock.startY;
4280 char * text = textBlock.text;
4282 Block b = textBlock;
4286 if(textBlock.type != TEXT) continue;
4288 while(b && b.type != TD) b = b.parent;
4292 while(table && table.type != TABLE) table = table.parent;
4294 maxW = b.w - 2* table.cellPadding;
4296 maxW = clientSize.w - 10 - sx;
4299 maxW = clientSize.w - 10 - sx;
4301 // Work around to re-align with first line having different indentation because of before <A> of current block
4303 Block parent = textBlock.parent;
4304 while(parent && parent.type == ANCHOR) parent = parent.parent;
4305 if(parent && parent.subBlocks.first && ((Block)parent.subBlocks.first).type == TEXT)
4306 xOffset = sx - ((Block)parent.subBlocks.first).startX;
4309 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4310 //space = space/2+2;
4313 while(textPos < textBlock.textLen)
4317 bool lineComplete = false;
4319 for(; textPos<textBlock.textLen && !lineComplete;)
4323 char * nextSpace = strchr(text + textPos, ' ');
4326 len = (nextSpace - (text + textPos)) + 1;
4328 len = textBlock.textLen - textPos;
4330 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4332 sx = x + textBlock.startX - xOffset;
4333 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4338 for(c = textPos; (ch = text[c]); c += numBytes)
4340 numBytes = UTF8_NUM_BYTES(ch);
4341 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4342 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4349 if(x + width + w > maxW && x > 0)
4351 lineComplete = true;
4364 if(/*py >= sy && */py < sy + th)
4367 return textBlock.textLen;
4372 result = textBlock.textLen;
4378 Application componentsApp;
4380 class Documentor : GuiApplication
4384 Platform os = __runtimePlatform;
4385 SetGlobalContext(globalContext);
4386 SetExcludedSymbols(&excludedSymbols);
4387 SetDefines(&::defines);
4388 SetImports(&imports);
4389 SetInDocumentor(true);
4391 SetGlobalData(globalData);
4393 settingsContainer.dataOwner = &ideSettings;
4394 settingsContainer.Load();
4395 if(!ideSettings.docDir || !ideSettings.docDir[0] )
4397 if(os == win32) // if Windows OS then
4399 char programFilesDir[MAX_LOCATION];
4400 char appData[MAX_LOCATION];
4401 char homeDrive[MAX_LOCATION];
4402 char winDir[MAX_LOCATION];
4403 GetEnvironment("APPDATA", appData, sizeof(appData));
4404 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4405 GetEnvironment("windir", winDir, sizeof(winDir));
4406 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4408 PathCat(programFilesDir, "ECERE SDK\\doc");
4409 ideSettings.docDir = programFilesDir;
4411 else if(homeDrive[0])
4413 PathCat(homeDrive, "ECERE SDK\\doc");
4414 ideSettings.docDir = homeDrive;
4418 PathCat(winDir, "..\\ECERE SDK\\doc");
4419 ideSettings.docDir = winDir;
4422 ideSettings.docDir = "C:\\ECERE SDK\\doc";
4424 else // if Os is Linux, or Mac OSX or something else
4425 ideSettings.docDir = "/usr/share/ecere/doc/";
4426 settingsContainer.Save();
4432 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4434 AddComponents(module, true);
4435 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4436 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4437 while((row = row.parent))
4438 row.collapsed = false;
4442 commandThread.Create();
4446 bool Cycle(bool idle)
4449 mainForm.Destroy(0);
4458 if(commandThread.created)
4460 console.CloseInput();
4461 console.CloseOutput();
4463 commandThread.Wait();
4467 FreeContext(globalContext);
4468 FreeExcludedSymbols(excludedSymbols);
4469 ::defines.Free(FreeModuleDefine);
4470 imports.Free(FreeModuleImport);
4472 FreeGlobalData(globalData);
4473 FreeTypeData(componentsApp);
4475 delete componentsApp;
4479 ConsoleFile console { };
4480 MainForm mainForm { };
4483 Thread commandThread
4490 console.GetLine(command, sizeof(command));
4491 if(!quit && command[0])
4494 if(!strcmpi(command, "Activate"))
4495 mainForm.Activate();
4496 else if(!strcmpi(command, "Quit"))
4504 #endif // !defined(EAR_TO_ECON_ECDOC)
4509 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4510 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4514 property bool isEmpty
4520 (description && *description));
4530 class MoreDoc : ItemDoc
4533 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4534 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4535 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4536 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4542 property bool isEmpty
4547 (usage && *usage) ||
4548 (example && *example) ||
4549 (remarks && *remarks) ||
4563 class NamespaceDoc : ItemDoc
4566 Map<String, DefineDoc> defines;
4567 Map<String, FunctionDoc> functions;
4569 property bool isEmpty
4574 (defines && defines.count) ||
4575 (functions && functions.count) ||
4586 class DefineDoc : ItemDoc { }
4588 class FunctionDoc : MoreDoc
4591 Map<String, ParameterDoc> parameters;
4592 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4595 property bool isEmpty
4600 (parameters && parameters.count) ||
4601 (returnValue && *returnValue) ||
4612 class ParameterDoc : ItemDoc
4618 class ClassDoc : MoreDoc
4621 Map<String, ValueDoc> values;
4622 Map<String, FieldDoc> fields;
4623 Map<String, PropertyDoc> properties;
4624 Map<String, ConversionDoc> conversions;
4625 Map<String, MethodDoc> methods;
4627 property bool isEmpty
4632 (values && values.count) ||
4633 (fields && fields.count) ||
4634 (properties && properties.count) ||
4635 (conversions && conversions.count) ||
4636 (methods && methods.count) ||
4650 class ValueDoc : ItemDoc { }
4652 class FieldDoc : ItemDoc { }
4654 class PropertyDoc : ItemDoc { }
4656 class ConversionDoc : ItemDoc { }
4658 class MethodDoc : FunctionDoc { }
4660 char * getDocFileNameFromTypeName(const char * typeName)
4662 char * docFileName = new char[MAX_FILENAME];
4663 const char * swap = "pointer";
4664 const char * s = typeName;
4665 char * d = docFileName;
4666 const char * end = s + strlen(typeName);
4667 int swapLen = strlen(swap);
4685 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4688 Time timeStamp; // Should this be last accessed, or last retrieved?
4697 Map<String, DocCacheEntry> docCache { };