2 #if !defined(EAR_TO_ECON_ECDOC)
6 import "SettingsDialog"
8 static Context globalContext { };
9 static OldList defines { };
10 static OldList imports { };
11 static NameSpace globalData;
12 static OldList excludedSymbols { offset = (uint)(uintptr)&((Symbol)0).left };
15 define app = (GuiApplication)__thisModule.application;
17 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
20 /*extern */int __ecereVMethodID_class_OnGetString;
24 static __attribute__((unused)) void Dummy()
27 a.OnGetString(null, null, null);
30 static bool editing = true;
32 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
34 static const char * iconNames[CodeObjectType] =
36 "<:ecere>constructs/class.png",
37 "<:ecere>constructs/data.png",
38 "<:ecere>constructs/method.png",
39 "<:ecere>constructs/event.png",
40 "<:ecere>constructs/property.png",
41 "<:ecere>constructs/namespace.png",
42 "<:ecere>constructs/dataType.png",
43 "<:ecere>constructs/enumValue.png",
44 "<:ecere>constructs/dataPrivate.png",
45 "<:ecere>constructs/methodPrivate.png",
46 "<:ecere>constructs/propertyPrivate.png"
49 IDESettings settings { }; // instantiate the IDESettings class from the IDESettings.ec file. Do this at a global level so that all methods can access settings.
51 IDESettingsContainer settingsContainer
55 dataOwner = &settings;
58 void GetTemplateString(Class c, char * templateString)
60 Module m = c.module.application;
61 const char * n = c.name;
62 char * lt = strchr(n, '<');
68 memcpy(templateString, n, lt-n);
69 templateString[lt-n] = 0;
70 strcat(templateString, "</a>");
72 for(s = lt; (ch = *s); s++)
74 if(ch == '<' || ch == '>' || ch == ',')
79 char * d = templateString + strlen(templateString);
81 TrimLSpaces(curName, curName);
82 TrimRSpaces(curName, curName);
83 pc = eSystem_FindClass(m, curName);
85 sprintf(d, "%s<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", !strncmp(curName, "const ", 6) ? "const " : "", pc, pc.name);
90 strcat(templateString, "<");
92 strcat(templateString, ">");
94 strcat(templateString, ", ");
101 curName[len++] = ' ';
103 strcat(templateString, curName);
111 // WARNING : This function expects a null terminated string since it recursively concatenate...
112 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
116 if(type.constant && (type.kind != pointerType && type.kind != arrayType))
117 strcat(string, "const ");
121 if(type._class && type._class.string)
124 strcat(string, type._class.string);
127 if(type._class.registered)
130 const char * s = type._class.registered.name;
131 sprintf(hex, "%p", type._class.registered.templateClass ? type._class.registered.templateClass : type._class.registered);
132 strcat(string, "<a href=\"api://");
134 strcat(string, "\" style=\"text-decoration: none;\">");
138 GetTemplateString(type._class.registered, n);
142 strcat(string, type._class.registered.name);
143 strcat(string, "</a>");
146 strcat(string, type._class.string);
153 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
154 if(funcType && funcType.kind == functionType)
157 DocPrintType(funcType.returnType, string, false, fullName);
158 strcat(string, "(*");
159 if(printName || funcType.thisClass)
162 if(funcType.thisClass)
164 strcat(string, funcType.thisClass.string);
165 strcat(string, "::");
168 strcat(string, type.name);
170 strcat(string, ")(");
171 for(param = funcType.params.first; param; param = param.next)
173 DocPrintType(param, string, false, fullName);
174 if(param.next) strcat(string, ", ");
180 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
181 if(string[strlen(string)-1] == '(')
184 strcat(string, " *");
188 case voidType: strcat(string, "void"); break;
189 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
190 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
191 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
192 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
193 case floatType: strcat(string, "float"); break;
194 case doubleType: strcat(string, "double"); break;
198 strcat(string, "struct ");
199 strcat(string, type.enumName);
201 else if(type.typeName)
203 strcat(string, type.typeName);
208 strcat(string, "struct ");
209 strcat(string,"(unnamed)");
212 strcat(string, "struct {");
213 for(member = type.members.first; member; member = member.next)
215 DocPrintType(member, string, true, fullName);
224 strcat(string, "union ");
225 strcat(string, type.enumName);
227 else if(type.typeName)
229 strcat(string, type.typeName);
233 strcat(string, "union ");
234 strcat(string,"(unnamed)");
240 strcat(string, "enum ");
241 strcat(string, type.enumName);
243 else if(type.typeName)
245 strcat(string, type.typeName);
248 strcat(string, "enum");
255 strcat(string, "dllexport ");
256 DocPrintType(type.returnType, string, false, fullName);
260 // DANGER: Testing This
266 strcat(string, type.name);
269 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
270 if(name) name += 2; else name = type.name;
271 strcat(string, "<b>");
272 strcat(string, name);
273 strcat(string, "</b>");
282 for(param = type.params.first; param; param = param.next)
284 DocPrintType(param, string, true, fullName);
285 if(param.next) strcat(string, ", ");
294 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
295 if(funcType && funcType.kind == functionType)
298 DocPrintType(funcType.returnType, string, false, fullName);
299 strcat(string, "(*");
300 if(printName || funcType.thisClass)
303 if(funcType.thisClass)
305 strcat(string, funcType.thisClass.string);
306 strcat(string, "::");
309 strcat(string, type.name);
311 strcat(string, ")(");
312 for(param = funcType.params.first; param; param = param.next)
314 DocPrintType(param, string, false, fullName);
315 if(param.next) strcat(string, ", ");
321 char baseType[1024], size[256];
322 Type arrayType = type;
326 while(arrayType.kind == TypeKind::arrayType)
329 if(arrayType.enumClass)
330 strcat(size, arrayType.enumClass.string);
331 else if(arrayType.arraySizeExp)
332 PrintExpression(arrayType.arraySizeExp, size);
333 //sprintf(string, "%s[%s]", baseType, size);
336 arrayType = arrayType.arrayType;
338 _PrintType(arrayType, baseType, printName, printFunction, fullName);
339 strcat(string, baseType);
340 strcat(string, size);
344 DocPrintType(type.arrayType, baseType, printName, fullName);
346 strcpy(size, type.enumClass.string);
347 else if(type.arraySizeExp)
348 PrintExpression(type.arraySizeExp, size);
349 //sprintf(string, "%s[%s]", baseType, size);
350 strcat(string, baseType);
352 strcat(string, size);
360 strcat(string, "...");
363 _PrintType(type.method.dataType, string, false, printFunction, fullName);
366 strcat(string, "subclass(");
367 strcat(string, type._class ? type._class.string : "int");
373 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
376 strcat(string, type.name);
381 void DocPrintType(Type type, char * string, bool printName, bool fullName)
384 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
385 if(funcType && funcType.kind == functionType && type != funcType)
389 DocPrintType(funcType.returnType, string, false, fullName);
391 _PrintType(type, string, printName, false, fullName);
395 strcat(string, type.name);
402 for(param = funcType.params.first; param; param = param.next)
404 DocPrintType(param, string, true, fullName);
405 if(param.next) strcat(string, ", ");
410 _PrintType(type, string, printName, true, fullName);
413 void AddComponents(Module module, bool isDll)
418 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
420 row = mainForm.browser.AddRow();
421 row.SetData(null, APIPageNameSpace { name = "ecereCOM", nameSpace = &module.application.systemNameSpace });
422 row.tag = (int64)null;
423 AddNameSpace(row, null, module.application.systemNameSpace, null, "", !isDll);
426 for(m = module.modules.first; m; m = m.next)
428 if(m.importMode == publicAccess || !isDll)
429 AddComponents(m.module, true);
432 // PUT MODULE DESCRIPTION HERE
433 if(module.name && strcmp(module.name, "ecereCOM"))
435 row = mainForm.browser.AddRow();
436 row.SetData(null, APIPageNameSpace { name = module.name, module = module, nameSpace = &module.publicNameSpace });
437 row.tag = (int64)module;
438 AddNameSpace(row, module, module.publicNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
440 AddNameSpace(row, module, module.privateNameSpace, null /*module.application.systemNameSpace*/, "", !isDll);
452 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
457 virtual void Generate(File f)
462 virtual Module GetModule()
464 return page ? page.GetModule() : null;
467 virtual NameSpace * GetNameSpace()
469 return page ? page.GetNameSpace() : null;
473 enum DocumentationType
482 enum DocumentationItem
499 static void FigureFileName(char * fileName, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
503 sprintf(hex, "%p", module);
504 strcat(fileName, hex);
505 strcat(fileName, "/");
506 sprintf(hex, "%p", object);
507 strcat(fileName, hex);
508 strcat(fileName, "/");
509 sprintf(hex, "%p", data);
510 strcat(fileName, hex);
511 strcat(fileName, "/");
512 if(type == nameSpaceDoc)
513 strcat(fileName, "namespace");
514 else if(type == functionDoc)
515 strcat(fileName, "function");
516 else if(type == classDoc)
517 strcat(fileName, "class");
518 else if(type == methodDoc)
519 strcat(fileName, "method");
520 strcat(fileName, "/");
521 if(item == description)
522 strcat(fileName, "description");
523 else if(item == usage)
524 strcat(fileName, "usage");
525 else if(item == remarks)
526 strcat(fileName, "remarks");
527 else if(item == example)
528 strcat(fileName, "example");
529 else if(item == seeAlso)
530 strcat(fileName, "seeAlso");
531 else if(item == enumerationValue)
532 strcat(fileName, "enumerationValue");
533 else if(item == definition)
534 strcat(fileName, "definition");
535 else if(item == conversion)
536 strcat(fileName, "conversion");
537 else if(item == memberDescription)
538 strcat(fileName, "memberDescription");
539 else if(item == propertyDescription)
540 strcat(fileName, "propertyDescription");
541 else if(item == parameter)
542 strcat(fileName, "parameter");
543 else if(item == returnValue)
544 strcat(fileName, "returnValue");
547 static void FigureFilePath(char * path, Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
549 char docPath[MAX_LOCATION];
550 NameSpace * nameSpace, * ns;
552 Method method = null;
553 GlobalFunction function = null;
554 char nsName[1024], temp[1024];
557 case nameSpaceDoc: nameSpace = object; break;
558 case classDoc: cl = (Class)object; nameSpace = cl.nameSpace; break;
559 case functionDoc: function = object; nameSpace = function.nameSpace; break;
560 case methodDoc: method = object; cl = method._class; nameSpace = cl.nameSpace; break;
566 while(ns && ns->name)
568 strcpy(temp, ns->name);
570 strcat(temp, nsName);
571 strcpy(nsName, temp);
576 PathCatSlash(docPath, (!module || !module.name || !strcmp(nsName, "namespaces/ecere/namespaces/com")) ? "ecereCOM" : module.name);
577 //ChangeExtension(docPath, "eCdoc", docPath);
578 PathCatSlash(docPath, nsName);
581 char * name = getDocFileNameFromTypeName(cl.name);
582 PathCatSlash(docPath, name);
586 PathCatSlash(docPath, "_global-defs");
587 ChangeExtension(docPath, "econ", docPath);
590 strcpy(path, settings.docDir);
591 PathCatSlash(path, docPath);
594 static char * ReadDoc(Module module, DocumentationType type, void * object, DocumentationItem item, void * data)
596 String contents = null;
597 bool docRetrieved = false;
598 NamespaceDoc nsDoc = null;
599 ClassDoc clDoc = null;
600 FunctionDoc fnDoc = null;
601 MethodDoc mdDoc = null;
603 char filePath[MAX_LOCATION];
604 Method method = null;
605 GlobalFunction function = null;
607 ItemDoc doc = getDoc(filePath, module, type, object, item, data, false);
611 case functionDoc: function = object; break;
612 case methodDoc: method = object; break;
617 if(eClass_IsDerived(doc._class, class(ClassDoc)))
619 clDoc = (ClassDoc)doc;
622 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
624 nsDoc = (NamespaceDoc)doc;
631 ItemDoc itDoc = null;
632 if(type == functionDoc)
634 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
635 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
636 if(name) name += 2; else name = function.name;
637 if(it.Index(name, false))
640 else if(type == methodDoc)
642 MapIterator<String, MethodDoc> it { map = clDoc.methods };
643 if(it.Index(method.name, false))
649 case description: s = type == methodDoc ? mdDoc.description : type == functionDoc ? fnDoc.description : type == classDoc ? clDoc.description : nsDoc.description; break;
650 case usage: s = type == methodDoc ? mdDoc.usage : type == functionDoc ? fnDoc.usage : type == classDoc ? clDoc.usage : null; break;
651 case remarks: s = type == methodDoc ? mdDoc.remarks : type == functionDoc ? fnDoc.remarks : type == classDoc ? clDoc.remarks : null; break;
652 case example: s = type == methodDoc ? mdDoc.example : type == functionDoc ? fnDoc.example : type == classDoc ? clDoc.example : null; break;
653 case seeAlso: s = type == methodDoc ? mdDoc.also : type == functionDoc ? fnDoc.also : type == classDoc ? clDoc.also : null; break;
654 case returnValue: s = type == methodDoc ? mdDoc.returnValue : type == functionDoc ? fnDoc.returnValue : null; break;
655 case enumerationValue:
656 if(clDoc && clDoc.values)
658 itDoc = clDoc.values[((NamedLink)data).name];
659 if(itDoc) s = itDoc.description;
663 if(nsDoc && nsDoc.defines)
665 itDoc = nsDoc.defines[((Definition)data).name];
666 if(itDoc) s = itDoc.description;
670 if(clDoc && clDoc.conversions)
672 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
673 if(name) name += 2; else name = ((Property)data).name;
674 itDoc = clDoc.conversions[name];
675 if(itDoc) s = itDoc.description;
678 case memberDescription:
679 if(clDoc && clDoc.fields)
681 itDoc = clDoc.fields[((DataMember)data).name];
682 if(itDoc) s = itDoc.description;
685 case propertyDescription:
686 if(clDoc && clDoc.properties)
688 itDoc = clDoc.properties[((Property)data).name];
689 if(itDoc) s = itDoc.description;
693 if((type == functionDoc && fnDoc && fnDoc.parameters) || (type == methodDoc && mdDoc && mdDoc.parameters))
695 char * name = ((Type)data).name;
696 itDoc = ((type == functionDoc) ? fnDoc.parameters : mdDoc.parameters)[name] ;
697 if(itDoc) s = itDoc.description;
702 contents = CopyString(s);
704 if(editing && !contents && !readOnly)
705 contents = CopyString($"[Add Text]");
709 // The filePath is returned!
710 ItemDoc getDoc(char * filePath, Module module, DocumentationType type, void * object, DocumentationItem item, void * data, bool create)
714 Method method = null;
720 case classDoc: cl = (Class)object; break;
721 case methodDoc: method = object; cl = method._class; break;
724 FigureFilePath(filePath, module, type, object, item, data);
726 entry = docCache[filePath];
732 File f = FileOpen(filePath, read);
735 JSONParser parser { f = f, eCON = true };
736 JSONResult jsonResult;
737 jsonResult = parser.GetObject(cl ? class(ClassDoc) : class(NamespaceDoc), &doc);
741 if(jsonResult != success)
743 PrintLn("error: problem parsing file: ", filePath);
748 doc = cl ? (ItemDoc)ClassDoc { } : (ItemDoc)NamespaceDoc { };
751 incref doc; // Reference to return
756 entry.timeStamp = now;
759 docCache[filePath] = { now, doc };
760 incref doc; // Reference for the cache
763 //void pruneDocCache()
764 // NOTE: If we want time stamp to be last retrieved, the pruning should be done before the retrieval
766 MapIterator<String, DocCacheEntry> it { map = docCache };
767 Array<const String> toRemove { };
768 for(entry : docCache; now - entry.timeStamp > 30)
769 toRemove.Add(&entry);
770 while(toRemove.count)
772 if(it.Index(toRemove.lastIterator.data, false))
777 toRemove.Remove(toRemove.lastIterator.pointer);
784 class APIPageNameSpace : APIPage
786 NameSpace * nameSpace;
794 NameSpace * GetNameSpace()
799 void Generate(File f)
801 char nsName[1024], temp[1024];
807 while(ns && ns->name)
809 strcpy(temp, ns->name);
810 if(nsName[0]) strcat(temp, "::");
811 strcat(temp, nsName);
812 strcpy(nsName, temp);
815 // Generate Class Page
816 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
819 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", nsName );
820 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);
823 f.Printf($"<FONT FACE=\"Arial\" SIZE=\"6\">Module %s</FONT><br>\n", (!module || !module.name || !strcmp(nsName, "ecere::com")) ? "ecereCOM" : module.name);
826 ns = nameSpace->parent;
827 while(ns && ns->name)
829 strcpy(temp, ns->name);
830 if(nsName[0]) strcat(temp, "::");
831 strcat(temp, nsName);
832 strcpy(nsName, temp);
836 f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
840 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, description, null);
843 f.Printf($"<H3>Description</H3><br><br>\n");
846 char fileName[MAX_LOCATION];
847 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, description, null);
848 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
850 f.Printf("</a><br><br>");
853 f.Printf("%s<br><br>", desc);
858 if(nameSpace->nameSpaces.first)
861 for(ns = (NameSpace *)nameSpace->nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
863 char * desc = ReadDoc(module, nameSpaceDoc, ns, description, null);
866 f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
867 f.Printf("<TABLE>\n");
871 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);
876 char fileName[MAX_LOCATION];
877 FigureFileName(fileName, module, nameSpaceDoc, ns, description, null);
878 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
880 f.Printf("</a></TD>");
883 f.Printf("<TD valign=top height=22> %s</TD>", desc);
886 f.Printf("</TR><br>\n");
889 f.Printf("</TABLE><br>\n");
892 if(nameSpace->classes.first)
895 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
897 Class cl = link.data;
898 if(!cl.templateClass)
900 char * desc = ReadDoc(module, classDoc, cl, description, null);
904 f.Printf($"<a name=Classes></a><H3>Classes</H3><br><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>\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 char * desc = ReadDoc(module, functionDoc, function, description, null);
940 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
941 if(name) name += 2; else name = function.name;
944 f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
945 f.Printf("<TABLE>\n");
949 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);
954 char fileName[MAX_LOCATION];
955 FigureFileName(fileName, module, functionDoc, function, description, null);
956 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
958 f.Printf("</a></TD>");
961 f.Printf("<TD valign=top height=22> %s</TD>", desc);
964 f.Printf("</TR><br>\n");
967 f.Printf("</TABLE><br>\n");
970 if(nameSpace->defines.first)
973 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
975 DefinedExpression def = link.data;
976 char * desc = ReadDoc(module, nameSpaceDoc, nameSpace, definition, def);
979 f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
980 f.Printf("<TABLE>\n");
984 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);
985 f.Printf("<TD valign=top height=22>%s</TD>", def.value);
990 char fileName[MAX_LOCATION];
991 FigureFileName(fileName, module, nameSpaceDoc, nameSpace, definition, def);
992 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
994 f.Printf("</a></TD>");
997 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1000 f.Printf("</TR><br>\n");
1003 f.Printf("</TABLE><br>\n");
1006 f.Printf("</FONT></BODY></HTML>\n");
1010 class APIPageClass : APIPage
1019 NameSpace * GetNameSpace()
1021 return cl.nameSpace;
1024 void Generate(File f)
1029 char nsName[1024], temp[1024];
1030 NameSpace * ns = cl.nameSpace;
1031 Module module = cl.module;
1034 while(ns && ns->name)
1036 strcpy(temp, ns->name);
1037 if(nsName[0]) strcat(temp, "::");
1038 strcat(temp, nsName);
1039 strcpy(nsName, temp);
1042 // Generate Class Page
1043 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1044 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1046 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);
1048 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1051 const char * classType = null;
1055 classType = $"Bit Collection";
1058 classType = $"Enumeration";
1061 classType = $"Structure";
1064 classType = $"Class";
1067 classType = $"Class (No header)";
1070 classType = $"Unit";
1073 classType = $"Basic Data Type";
1076 f.Printf($"Type: %s<br>\n", classType);
1079 if(cl.type != systemClass && cl.base)
1081 f.Printf($"Base Class: ");
1082 if(!strcmp(cl.base.name, "struct") || !strcmp(cl.base.name, "class"))
1084 f.Printf(cl.type == bitClass ? cl.dataTypeString : $"None");
1086 else if(cl.type == enumClass && !strcmp(cl.base.name, "enum"))
1087 f.Printf("%s", cl.dataTypeString);
1089 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", cl.base.templateClass ? cl.base.templateClass : cl.base, cl.base.name);
1094 char * desc = ReadDoc(module, classDoc, cl, description, null);
1097 f.Printf($"<br><H3>Description</H3><br><br>\n");
1100 char fileName[MAX_LOCATION];
1101 FigureFileName(fileName, module, classDoc, cl, description, null);
1102 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1104 f.Printf("</a><br><br>");
1107 f.Printf("%s<br><br>", desc);
1112 if(cl.type == enumClass)
1114 EnumClassData enumeration = (EnumClassData)cl.data;
1115 if(enumeration.values.first)
1119 f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
1120 f.Printf("<TABLE>\n");
1122 for(item = enumeration.values.first; item; item = item.next)
1124 char * desc = ReadDoc(module, classDoc, cl, enumerationValue, item);
1125 bool needClass = true;
1128 char tempString[1024];
1130 while(base.type == enumClass) base = base.base;
1132 if(base.type == systemClass ||
1133 (base.type == bitClass && base.membersAndProperties.first && !strcmp(cl.fullName, ((DataMember)base.membersAndProperties.first).dataTypeString)))
1136 base.dataType = ProcessTypeString(base.dataTypeString, false);
1138 if(base.dataType.kind != classType)
1143 PrintType(base.dataType, string, false, true);
1144 classSym = FindClass(string);
1145 dataClass = classSym ? classSym.registered : null;
1148 dataClass = base.dataType._class ? base.dataType._class.registered : null;
1154 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);
1155 if(dataClass.type == systemClass)
1158 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)dataClass._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1161 s = ((char *(*)(void *, void *, char *, void *, bool *))(void *)eSystem_FindClass(componentsApp, "class")._vTbl[__ecereVMethodID_class_OnGetString])(dataClass, &item.data, tempString, null, &needClass);
1163 f.Printf("<TD valign=top height=22 nowrap=1>%s { %s }</TD>", dataClass.name, s);
1165 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", s);
1170 char fileName[MAX_LOCATION];
1171 FigureFileName(fileName, module, classDoc, cl, enumerationValue, item);
1172 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1174 f.Printf("</a></TD>");
1177 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1182 f.Printf("</TABLE><BR>\n");
1186 if(cl.conversions.first)
1188 f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
1189 f.Printf("<TABLE>\n");
1190 for(prop = cl.conversions.first; prop; prop = prop.next)
1192 if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
1194 char * desc = ReadDoc(module, classDoc, cl, conversion, prop);
1196 Type type = ProcessTypeString(prop.name, false);
1197 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
1198 if(name) name += 2; else name = prop.name;
1203 DocPrintType(type, string, true, false);
1205 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\"> %s</TD>", prop, iconNames[typeDataType], string);
1210 char fileName[MAX_LOCATION];
1211 FigureFileName(fileName, module, classDoc, cl, conversion, prop);
1212 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1214 f.Printf("</a></TD>");
1217 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1221 f.Printf("</TR>\n");
1226 f.Printf("</TABLE><br>\n");
1229 if(cl.membersAndProperties.first)
1232 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
1234 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
1238 f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
1239 f.Printf("<TABLE>\n");
1245 char * desc = ReadDoc(module, classDoc, cl, propertyDescription, prop);
1247 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
1251 DocPrintType(prop.dataType, string, true, false);
1253 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);
1254 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", string);
1259 char fileName[MAX_LOCATION];
1260 FigureFileName(fileName, module, classDoc, cl, propertyDescription, prop);
1261 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1263 f.Printf("</a></TD>");
1266 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1269 f.Printf("</TR>\n");
1273 AddDataMemberToPage(f, (DataMember)prop, 0, showPrivate);
1278 f.Printf("</TABLE><br>\n");
1281 if(cl.methods.first)
1285 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1287 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type == virtualMethod)
1289 char * desc = ReadDoc(module, methodDoc, method, description, null);
1292 f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
1293 f.Printf("<TABLE>\n");
1296 if(!method.dataType)
1297 ProcessMethodType(method);
1300 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);
1305 char fileName[MAX_LOCATION];
1306 FigureFileName(fileName, module, methodDoc, method, description, null);
1307 f.Printf("<TD valign=top height=22> <a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1309 f.Printf("</a></TD>");
1312 f.Printf("<TD valign=top height=22> %s</TD>", desc);
1315 f.Printf("</TR><br>\n");
1319 f.Printf("</TABLE><br>\n");
1321 // Non-Virtual Methods
1323 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
1325 if((method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate)) && method.type != virtualMethod)
1327 char * desc = ReadDoc(module, methodDoc, method, description, null);
1330 f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
1331 f.Printf("<TABLE>\n");
1335 if(!method.dataType)
1336 ProcessMethodType(method);
1339 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);
1344 char fileName[MAX_LOCATION];
1345 FigureFileName(fileName, module, methodDoc, method, description, null);
1346 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1348 f.Printf("</a></TD>");
1351 f.Printf("<TD valign=top height=22>%s</TD>", desc);
1355 f.Printf("</TR><br>\n");
1359 f.Printf("</TABLE><br>\n");
1362 char * usageDoc = ReadDoc(module, classDoc, cl, usage, null);
1365 f.Printf($"<H3>Usage</H3><br>\n");
1368 char fileName[MAX_LOCATION];
1369 FigureFileName(fileName, module, classDoc, cl, usage, null);
1370 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1375 f.Printf("<br>%s\n", usageDoc);
1376 f.Printf("<br><br>\n");
1381 char * exampleDoc = ReadDoc(module, classDoc, cl, example, null);
1384 f.Printf($"<H3>Example</H3><br>\n");
1385 f.Printf($"<FONT face=\"Courier New\">\n");
1386 f.Printf("<br><TABLE>\n");
1389 char fileName[MAX_LOCATION];
1390 FigureFileName(fileName, module, classDoc, cl, example, null);
1391 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1393 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1396 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1398 f.Printf("</TABLE></FONT>\n");
1404 char * remarksDoc = ReadDoc(module, classDoc, cl, remarks, null);
1408 f.Printf($"<H3>Remarks</H3><br>\n");
1411 char fileName[MAX_LOCATION];
1412 FigureFileName(fileName, module, classDoc, cl, remarks, null);
1413 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1418 f.Printf("<br>%s\n", remarksDoc);
1419 f.Printf("<br><br>\n");
1424 if(cl.type != systemClass)
1428 for(c = cl.derivatives.first; c; c = c.next)
1430 Class deriv = c.data;
1431 // TO VERIFY: Does this properly check public status?
1432 if(eSystem_FindClass(componentsApp, deriv.fullName))
1436 f.Printf($"<H3>Derived Classes</H3><br>\n");
1442 f.Printf("<a href=\"api://%p\" style=\"text-decoration: none;\">%s</a>", deriv, deriv.name);
1446 f.Printf("<br><br>\n");
1449 char * seeAlsoDoc = ReadDoc(module, classDoc, cl, seeAlso, null);
1452 f.Printf($"<H3>See Also</H3><br>\n");
1455 char fileName[MAX_LOCATION];
1456 FigureFileName(fileName, module, classDoc, cl, seeAlso, null);
1457 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1462 f.Printf("<br>%s\n", seeAlsoDoc);
1463 f.Printf("<br><br>\n");
1467 f.Printf("</FONT></BODY></HTML>\n");
1471 class APIPageMethod : APIPage
1477 return method._class.module;
1480 NameSpace * GetNameSpace()
1482 return method._class.nameSpace;
1485 void Generate(File f)
1487 Class cl = method._class;
1489 Module module = cl.module;
1491 char nsName[1024], temp[1024];
1492 NameSpace * ns = cl.nameSpace;
1495 while(ns && ns->name)
1497 strcpy(temp, ns->name);
1498 if(nsName[0]) strcat(temp, "::");
1499 strcat(temp, nsName);
1500 strcpy(nsName, temp);
1504 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1505 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1507 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);
1509 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
1510 f.Printf("Class: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl, cl.name);
1511 if(method.dataType.staticMethod)
1513 f.Printf($"this pointer class: None<br>\n");
1515 else if(method.dataType.thisClass && method.dataType.thisClass.registered && (method.dataType.thisClass.registered != method._class || method.type == virtualMethod))
1517 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);
1520 // Generate Method Page
1522 if(!method.dataType.name)
1523 method.dataType.name = CopyString(method.name);
1524 DocPrintType(method.dataType, string, true, false);
1525 f.Printf("<br>%s", string);
1528 char * desc = ReadDoc(module, methodDoc, method, description, null);
1531 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1534 char fileName[MAX_LOCATION];
1535 FigureFileName(fileName, module, methodDoc, method, description, null);
1536 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1541 f.Printf("%s", desc);
1546 f.Printf("<br><br>\n");
1547 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1549 f.Printf($"<H3>Parameters</H3><br><br>\n");
1551 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1552 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1554 f.Printf("<TABLE valign=center>\n");
1557 for(param = method.dataType.params.first; param; param = param.next)
1559 // ADD DESCRIPTION HERE
1560 if(param.kind != voidType)
1562 char * desc = ReadDoc(module, methodDoc, method, parameter, param);
1565 DocPrintType(param, string, false, false);
1567 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1568 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1573 char fileName[MAX_LOCATION];
1574 FigureFileName(fileName, module, methodDoc, method, parameter, param);
1575 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1577 f.Printf("</a></TD>\n");
1580 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1584 f.Printf("</TR>\n");
1587 if(method.dataType.returnType && method.dataType.returnType.kind != voidType)
1589 char * desc = ReadDoc(module, methodDoc, method, returnValue, null);
1590 if(method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType)
1592 f.Printf("<TR><TD> </TD></TR>");
1595 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1597 DocPrintType(method.dataType.returnType, string, false, false);
1598 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1603 char fileName[MAX_LOCATION];
1604 FigureFileName(fileName, module, methodDoc, method, returnValue, null);
1605 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1607 f.Printf("</a> </TD>\n");
1610 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1613 f.Printf("</TR>\n");
1614 f.Printf("</TABLE>\n");
1616 if((method.dataType.returnType && method.dataType.returnType.kind != voidType) ||
1617 (method.dataType.params.first && ((Type)method.dataType.params.first).kind != voidType))
1619 f.Printf("</TABLE><br>\n");
1622 char * usageDoc = ReadDoc(module, methodDoc, method, usage, null);
1625 f.Printf($"<H3>Usage</H3><br>\n");
1628 char fileName[MAX_LOCATION];
1629 FigureFileName(fileName, module, methodDoc, method, usage, null);
1630 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1635 f.Printf("<br>%s\n", usageDoc);
1636 f.Printf("<br><br>\n");
1641 char * exampleDoc = ReadDoc(module, methodDoc, method, example, null);
1644 f.Printf($"<H3>Example</H3><br>\n");
1645 f.Printf($"<FONT face=\"Courier New\">\n");
1646 f.Printf("<br><TABLE>\n");
1649 char fileName[MAX_LOCATION];
1650 FigureFileName(fileName, module, methodDoc, method, example, null);
1651 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1653 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1656 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1657 f.Printf("</TABLE></FONT>\n");
1663 char * remarksDoc = ReadDoc(module, methodDoc, method, remarks, null);
1666 f.Printf($"<H3>Remarks</H3><br>\n");
1669 char fileName[MAX_LOCATION];
1670 FigureFileName(fileName, module, methodDoc, method, remarks, null);
1671 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1676 f.Printf("<br>%s\n", method, remarksDoc);
1677 f.Printf("<br><br>\n");
1682 char * seeAlsoDoc = ReadDoc(module, methodDoc, method, seeAlso, null);
1685 f.Printf($"<H3>See Also</H3><br>\n");
1688 char fileName[MAX_LOCATION];
1689 FigureFileName(fileName, module, methodDoc, method, seeAlso, null);
1690 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1695 f.Printf("<br>%s\n", method, seeAlsoDoc);
1697 f.Printf("<br><br>\n");
1701 f.Printf("</FONT></BODY></HTML>\n");
1705 class APIPageFunction : APIPage
1707 GlobalFunction function;
1711 return function.module;
1714 NameSpace * GetNameSpace()
1716 return function.nameSpace;
1719 void Generate(File f)
1722 Module module = function.module;
1724 char nsName[1024], temp[1024];
1725 NameSpace * ns = function.nameSpace;
1728 while(ns && ns->name)
1730 strcpy(temp, ns->name);
1731 if(nsName[0]) strcat(temp, "::");
1732 strcat(temp, nsName);
1733 strcpy(nsName, temp);
1737 f.Printf($"<HTML><HEAD><TITLE>API Reference</TITLE></HEAD>\n<BODY><FONT SIZE=\"3\">\n");
1738 f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
1740 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);
1743 f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", function.nameSpace, nsName);
1745 if(!function.dataType)
1746 function.dataType = ProcessTypeString(function.dataTypeString, false);
1748 if(function.dataType.thisClass && function.dataType.thisClass.registered)
1750 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);
1753 // Generate Method Page
1755 if(!function.dataType.name)
1756 function.dataType.name = CopyString(function.name);
1757 DocPrintType(function.dataType, string, true, false);
1758 f.Printf("<br>%s", string);
1761 char * desc = ReadDoc(module, functionDoc, function, description, null);
1764 f.Printf($"<br><br><H3>Description</H3><br><br>\n");
1767 char fileName[MAX_LOCATION];
1768 FigureFileName(fileName, module, functionDoc, function, description, null);
1769 f.Printf("<a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1774 f.Printf("%s", desc);
1778 f.Printf("<br><br>\n");
1779 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1781 f.Printf($"<H3>Parameters</H3><br><br>\n");
1783 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1784 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1786 f.Printf("<TABLE valign=center>\n");
1789 for(param = function.dataType.params.first; param; param = param.next)
1791 // ADD DESCRIPTION HERE
1792 if(param.kind != voidType)
1794 char * desc = ReadDoc(module, functionDoc, function, parameter, param);
1797 DocPrintType(param, string, false, false);
1799 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", param.name ? param.name : "");
1800 f.Printf("<TD valign=top height=22 nowrap=1>%s </TD>\n", string);
1805 char fileName[MAX_LOCATION];
1806 FigureFileName(fileName, module, functionDoc, function, parameter, param);
1807 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1810 f.Printf("</a> </TD>\n");
1813 f.Printf("<TD valign=top height=22>%s </TD>\n", desc);
1816 f.Printf("</TR>\n");
1819 if(function.dataType.returnType && function.dataType.returnType.kind != voidType)
1821 char * desc = ReadDoc(module, functionDoc, function, returnValue, null);
1822 if(function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType)
1824 f.Printf("<TR><TD> </TD></TR>");
1827 f.Printf($"<TD valign=top height=22 nowrap=1><B>Return Value</B></TD>\n");
1829 DocPrintType(function.dataType.returnType, string, false, false);
1830 f.Printf("<TD valign=top height=22>%s </TD>\n", string);
1835 char fileName[MAX_LOCATION];
1836 FigureFileName(fileName, module, functionDoc, function, returnValue, null);
1837 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1839 f.Printf("</a> </TD>\n");
1842 f.Printf("<TD valign=top height=22>%s </TD>\n", function, desc);
1845 f.Printf("</TR>\n");
1846 f.Printf("</TABLE>\n");
1848 if((function.dataType.returnType && function.dataType.returnType.kind != voidType) ||
1849 (function.dataType.params.first && ((Type)function.dataType.params.first).kind != voidType))
1851 f.Printf("</TABLE><br>\n");
1854 char * usageDoc = ReadDoc(module, functionDoc, function, usage, null);
1857 f.Printf($"<H3>Usage</H3><br>\n");
1860 char fileName[MAX_LOCATION];
1861 FigureFileName(fileName, module, functionDoc, function, usage, null);
1862 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1867 f.Printf("<br>%s\n", usageDoc);
1868 f.Printf("<br><br>\n");
1873 char * exampleDoc = ReadDoc(module, functionDoc, function, example, null);
1876 f.Printf($"<H3>Example</H3><br>\n");
1877 f.Printf($"<FONT face=\"Courier New\">\n");
1878 f.Printf("<br><TABLE>\n");
1881 char fileName[MAX_LOCATION];
1882 FigureFileName(fileName, module, functionDoc, function, example, null);
1883 f.Printf("<TR><TD><CODE><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1885 f.Printf("</a></CODE></TD></TR>\n"); // bgcolor=#CFC9C0
1888 f.Printf("<TR><TD><CODE>%s</CODE></TD></TR>\n", exampleDoc); // bgcolor=#CFC9C0
1889 f.Printf("</TABLE></FONT>\n");
1895 char * remarksDoc = ReadDoc(module, functionDoc, function, remarks, null);
1898 f.Printf($"<H3>Remarks</H3><br>\n");
1901 char fileName[MAX_LOCATION];
1902 FigureFileName(fileName, module, functionDoc, function, remarks, null);
1903 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1908 f.Printf("<br>%s\n", remarksDoc);
1909 f.Printf("<br><br>\n");
1914 char * seeAlsoDoc = ReadDoc(module, functionDoc, function, seeAlso, null);
1917 f.Printf($"<H3>See Also</H3><br>\n");
1920 char fileName[MAX_LOCATION];
1921 FigureFileName(fileName, module, functionDoc, function, seeAlso, null);
1922 f.Printf("<br><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
1927 f.Printf("<br>%s\n", seeAlsoDoc);
1928 f.Printf("<br><br>\n");
1932 f.Printf("</FONT></BODY></HTML>\n");
1936 static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpace, NameSpace comNameSpace, const char * parentName, bool showPrivate)
1940 NameSpace * nameSpace = mainNameSpace;
1942 DataRow classesRow = null;
1943 DataRow functionsRow = null, definesRow = null;
1946 strcpy(nsName, parentName ? parentName : "");
1950 strcat(nsName, "::");
1951 strcat(nsName, nameSpace->name);
1956 row = parentRow.AddRow();
1957 row.SetData(null, (page = APIPageNameSpace { nameSpace->name, module = module, nameSpace = nameSpace, showPrivate = showPrivate }));
1958 row.tag = (int64)nameSpace;
1959 row.icon = mainForm.icons[typeNameSpace];
1963 // "Global NameSpace"
1965 page = parentRow.GetData(null);
1968 for(ns = (NameSpace *)mainNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1970 NameSpace * comNS = (comNameSpace != null) ? (NameSpace *)comNameSpace.nameSpaces.FindString(ns->name) : null;
1971 AddNameSpace(row, module, ns, comNS, nsName, showPrivate);
1973 if(comNameSpace != null)
1975 for(ns = (NameSpace *)comNameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
1977 if(!mainNameSpace.nameSpaces.FindString(ns->name))
1979 AddNameSpace(row, module, ns, null, nsName, showPrivate);
1984 if(mainNameSpace.classes.first || (comNameSpace && comNameSpace.classes.first))
1986 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
1988 if(nameSpace->classes.first)
1992 for(link = (BTNamedLink)nameSpace->classes.first; link; link = (BTNamedLink)((BTNode)link).next)
1995 if(!cl.templateClass && (!module || cl.module == module || (!cl.module.name && !strcmp(module.name, "ecere"))))
1997 if(!classesRow) { classesRow = row.AddRow(); classesRow.SetData(null, APIPage { $"Classes", page = page }); classesRow.collapsed = true; classesRow.icon = mainForm.icons[typeClass]; classesRow.tag = 1; }
1998 AddClass(classesRow, module, cl, nsName, showPrivate);
2005 if(mainNameSpace.functions.first || (comNameSpace && comNameSpace.functions.first))
2007 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2009 if(nameSpace->functions.first)
2013 for(link = (BTNamedLink)nameSpace->functions.first; link; link = (BTNamedLink)((BTNode)link).next)
2016 if(!module || fn.module == module || (!fn.module.name && !strcmp(module.name, "ecere")))
2018 const char * name = ( name = RSearchString(fn.name, "::", strlen(fn.name), false, false), name ? name + 2 : fn.name);
2020 if(!functionsRow) { functionsRow = row.AddRow(); functionsRow.SetData(null, APIPage { $"Functions", page = page }); functionsRow.collapsed = true; functionsRow.icon = mainForm.icons[typeMethod]; functionsRow.tag = 2; };
2021 fnRow = functionsRow.AddRow(); fnRow.SetData(null, APIPageFunction { name, function = fn }); fnRow.icon = mainForm.icons[typeMethod]; fnRow.tag = (int64)fn;
2028 if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
2030 for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
2032 if(nameSpace->defines.first)
2036 for(link = (BTNamedLink)nameSpace->defines.first; link; link = (BTNamedLink)((BTNode)link).next)
2039 //if(def.module == module)
2041 char * name = ( name = RSearchString(def.name, "::", strlen(def.name), false, false), name ? name + 2 : def.name);
2043 if(!definesRow) { definesRow = row.AddRow(); definesRow.SetData(null, APIPage { $"Definitions", page = page }); definesRow.collapsed = true; definesRow.icon = mainForm.icons[typeData]; definesRow.tag = 3; };
2044 defRow = definesRow.AddRow(); defRow.SetData(null, APIPage { name, page = page }); defRow.icon = mainForm.icons[typeData]; defRow.tag = (int64)def;
2052 static void AddDataMemberToPage(File f, DataMember member, int indent, bool showPrivate)
2056 if(!member.dataType)
2057 member.dataType = ProcessTypeString(member.dataTypeString, false);
2061 DocPrintType(member.dataType, string, true, false);
2063 f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a>", member);
2064 for(c = 0; c<indent; c++)
2065 f.Printf(" ");
2066 f.Printf("<img valign=center src=\"%s\"> %s</TD>", iconNames[typeData], member.name ? member.name : ((member.type == structMember) ? "(struct)" : "(union)"));
2067 f.Printf("<TD valign=top height=22 nowrap=1>%s</TD>", (member.type == normalMember) ? string : "");
2068 if(member.type == normalMember)
2070 char * desc = ReadDoc(member._class.module, classDoc, member._class, memberDescription, member);
2075 char fileName[MAX_LOCATION];
2076 FigureFileName(fileName, member._class.module, classDoc, member._class, memberDescription, member);
2077 f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
2079 f.Printf("</a></TD>");
2082 f.Printf("<TD valign=top height=22>%s</TD>", desc);
2087 f.Printf("<TD valign=top height=22></TD>");
2089 if(member.type != normalMember)
2091 DataMember subMember;
2092 for(subMember = member.members.first; subMember; subMember = subMember.next)
2094 if((subMember.memberAccess == publicAccess || (subMember.memberAccess == privateAccess && showPrivate)))
2096 AddDataMemberToPage(f, subMember, indent + 1, showPrivate);
2100 f.Printf("</TR><br>\n");
2103 static void AddDataMember(DataRow parentRow, APIPage page, DataMember member)
2106 if(member.type == normalMember)
2108 row = parentRow.AddRow(); row.SetData(null, APIPage { member.name, page = page }); row.icon = mainForm.icons[typeData];
2109 row.tag = (int64)member;
2114 row = parentRow.AddRow(); row.SetData(null, APIPage { (member.type == unionMember) ? "(union)" : "(struct)", page });
2115 row.icon = mainForm.icons[typeData];
2116 row.tag = (int64)member;
2118 for(m = member.members.first; m; m = m.next)
2120 if(m.memberAccess == publicAccess || (m.memberAccess == privateAccess && page.showPrivate))
2121 AddDataMember(row, page, m);
2126 static void AddClass(DataRow parentRow, Module module, Class cl, char * nsName, bool showPrivate)
2131 DataRow methodsRow = null, virtualsRow = null, eventsRow = null;
2132 DataRow propertiesRow = null, membersRow = null, conversionsRow = null, enumRow = null;
2135 row = parentRow.AddRow();
2136 row.SetData(null, (page = APIPageClass { cl.name, cl = cl, showPrivate = showPrivate }));
2137 row.tag = (int64)cl;
2138 row.collapsed = true;
2139 row.icon = (cl.type == enumClass || cl.type == unitClass || cl.type == systemClass) ? mainForm.icons[typeDataType] : mainForm.icons[typeClass];
2142 if(cl.methods.first)
2144 for(method = (Method)cl.methods.first; method; method = (Method)((BTNode)method).next)
2146 if(method.memberAccess == publicAccess || (method.memberAccess == privateAccess && showPrivate))
2149 if(!method.dataType)
2150 ProcessMethodType(method);
2151 if(method.type == virtualMethod)
2153 if(method.dataType.thisClass)
2155 if(!eventsRow) { eventsRow = row.AddRow(); eventsRow.SetData(null, APIPage { $"Events", page = page }); eventsRow.collapsed = true; eventsRow.icon = mainForm.icons[typeEvent]; eventsRow.tag = 4; }
2156 mRow = eventsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeEvent];
2157 mRow.tag = (int64)method;
2161 if(!virtualsRow) { virtualsRow = row.AddRow(); virtualsRow.SetData(null, APIPage { $"Virtual Methods", page = page }); virtualsRow.collapsed = true; virtualsRow.icon = mainForm.icons[typeMethod]; virtualsRow.tag = 4; }
2162 mRow = virtualsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2163 mRow.tag = (int64)method;
2168 if(!methodsRow) { methodsRow = row.AddRow(); methodsRow.SetData(null, APIPage { $"Methods", page = page }); methodsRow.collapsed = true; methodsRow.icon = mainForm.icons[typeMethod]; methodsRow.tag = 5; }
2169 mRow = methodsRow.AddRow(); mRow.SetData(null, APIPageMethod { method.name, method = method }); mRow.icon = mainForm.icons[typeMethod];
2170 mRow.tag = (int64)method;
2176 if(cl.membersAndProperties.first)
2178 for(prop = (Property)cl.membersAndProperties.first; prop; prop = prop.next)
2180 if(prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate))
2183 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2187 if(!propertiesRow) { propertiesRow = row.AddRow(); propertiesRow.SetData(null, APIPage { $"Properties", page = page }); propertiesRow.collapsed = true; propertiesRow.icon = mainForm.icons[typeProperty]; propertiesRow.tag = 6; }
2188 mRow = propertiesRow.AddRow(); mRow.SetData(null, APIPage { prop.name, page }); mRow.icon = mainForm.icons[typeProperty];
2189 mRow.tag = (int64)prop;
2193 if(!membersRow) { membersRow = row.AddRow(); membersRow.SetData(null, APIPage { $"Data Members", page = page }); membersRow.collapsed = true; membersRow.icon = mainForm.icons[typeData]; membersRow.tag = 6; }
2194 AddDataMember(membersRow, page, (DataMember)prop);
2200 if(cl.conversions.first)
2202 for(prop = cl.conversions.first; prop; prop = prop.next)
2206 if(!conversionsRow) { conversionsRow = row.AddRow(); conversionsRow.SetData(null, APIPage { $"Conversions", page = page }); conversionsRow.collapsed = true; conversionsRow.icon = mainForm.icons[typeDataType]; conversionsRow.tag = 7; }
2207 name = RSearchString(prop.name, "::", strlen(prop.name), true, false);
2208 if(name) name += 2; else name = prop.name;
2209 mRow = conversionsRow.AddRow(); mRow.SetData(null, APIPage { name, page = page }); mRow.icon = mainForm.icons[typeDataType];
2210 mRow.tag = (int64)prop;
2213 if(cl.type == enumClass)
2215 EnumClassData enumeration = (EnumClassData)cl.data;
2217 for(item = enumeration.values.first; item; item = item.next)
2220 if(!enumRow) { enumRow = row.AddRow(); enumRow.SetData(null, APIPage { $"Enumeration Values", page = page }); enumRow.collapsed = true; enumRow.icon = mainForm.icons[typeEnumValue]; enumRow.tag = 8; }
2221 mRow = enumRow.AddRow(); mRow.SetData(null, APIPage { item.name, page = page }); mRow.icon = mainForm.icons[typeEnumValue];
2222 mRow.tag = (int64)item;
2227 class AddressBar : Window
2229 background = activeBorder;
2233 this, bevelOver = true, inactive = true, anchor = Anchor { left = 0, top = 0, bottom = 0 }, size = Size { 24 }, bitmap = { ":actions/docOpen.png" };
2235 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2237 MainForm mainForm = (MainForm)parent;
2238 FileDialog fileDialog = mainForm.fileDialog;
2239 if(fileDialog.Modal() == ok)
2240 mainForm.OpenModule(fileDialog.filePath);
2246 this, bevelOver = true, inactive = true, anchor = Anchor { left = 28, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altLeft, bitmap = { "<:ecere>actions/goPrevious.png" };
2249 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2251 ((MainForm)parent).Back();
2257 this, bevelOver = true, inactive = true, anchor = Anchor { left = 52, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = altRight, bitmap = { "<:ecere>actions/goNext.png" };
2260 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2262 ((MainForm)parent).Forward();
2268 this, bevelOver = true, inactive = true, anchor = Anchor { left = 80, top = 0, bottom = 0 }, size = Size { 24 }, hotKey = ctrlH, bitmap = { "<:ecere>actions/goHome.png" };
2270 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2272 ((MainForm)parent).Home();
2276 /* TODO: Search (#143/#441)
2277 When there's something in the search box, list matching sections, the exact match first,instead of the Hierarchy in the ListBox.
2278 Update this in the NotifyUpdate. Enter goes to the exact match.
2280 Label { this, anchor = Anchor { left = (124+12) }, labeledWindow = search };
2284 this, text = "Search:", anchor = Anchor { left = (16+48+124), right = 60, top = 0, bottom = 0 }, hotKey = altD;
2286 bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
2288 if(!disabled && (SmartKey)key == enter)
2289 ((MainForm)parent).Go(editBox.contents);
2293 void NotifyUpdate(EditBox editBox)
2295 String location = ((MainForm)parent).view.location;
2296 disabled = !strcmp(location ? location : "", editBox.contents);
2301 bool OnKeyHit(Key key, unichar ch)
2304 ((MainForm)parent).view.MakeActive();
2309 class MainForm : Window
2311 size = { 1000, 600 };
2313 borderStyle = sizable;
2316 icon = { ":documentorIcon.png" };
2317 text = $"API Documentation Browser";
2319 BitmapResource icons[CodeObjectType];
2324 for(c = 0; c < CodeObjectType::enumSize; c++)
2326 icons[c] = BitmapResource { iconNames[c], window = this, alphaBlend = true };
2328 browser.AddField(DataField { dataType = class(APIPage) });
2333 Menu fileMenu { menu, $"File", f };
2334 Array<FileFilter> fileFilters
2336 { $"eC Shared Library files (*.dll, *.so, *.dylib)", "dll, so, dylib" },
2337 { $"eC Symbol files (*.sym)", "sym" }
2340 FileDialog fileDialog
2342 filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
2344 MenuItem fileOpenItem
2346 fileMenu, $"Open...", o, ctrlO;
2348 bool NotifySelect(MenuItem selection, Modifiers mods)
2350 if(fileDialog.Modal() == ok)
2352 OpenModule(fileDialog.filePath);
2357 MenuItem fileSettingsItem
2359 fileMenu, $"Settings...", s, ctrlS; // set the Settings item to the file menu with shortcut keys:s and ctrl+s
2361 bool NotifySelect(MenuItem selection, Modifiers mods)
2363 if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
2373 MenuDivider { fileMenu };
2374 MenuItem fileExit { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
2376 void OpenModule(const char * filePath)
2378 char moduleName[MAX_LOCATION];
2379 char extension[MAX_EXTENSION];
2380 Module module = null;
2381 static char symbolsDir[MAX_LOCATION];
2385 FreeContext(globalContext);
2386 FreeExcludedSymbols(excludedSymbols);
2387 ::defines.Free(FreeModuleDefine);
2388 imports.Free(FreeModuleImport);
2390 FreeGlobalData(globalData);
2394 FreeTypeData(componentsApp);
2395 delete componentsApp;
2398 componentsApp = __ecere_COM_Initialize(false, 1, null);
2399 SetPrivateModule(componentsApp);
2401 StripLastDirectory(filePath, symbolsDir);
2402 SetSymbolsDir(symbolsDir);
2404 GetExtension(filePath, extension);
2406 mainForm.browser.Clear();
2408 ImportModule(filePath, normalImport, publicAccess, false);
2410 if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll") && strcmpi(extension, "dylib"))
2411 componentsApp.name = CopyString(filePath);
2413 for(module = componentsApp.allModules.first; module; module = module.next)
2415 if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
2419 eModule_LoadStrict(componentsApp, "ecereCOM", publicAccess /*privateAccess*/);
2420 AddComponents(componentsApp, false);
2422 GetLastDirectory(filePath, moduleName);
2423 // Extension, path and lib prefix get removed in Module::name
2426 StripExtension(moduleName);
2427 if((!strcmpi(extension, "so") || !strcmpi(extension, "dylib")) && strstr(moduleName, "lib") == moduleName)
2429 int len = strlen(moduleName) - 3;
2430 memmove(moduleName, moduleName + 3, len);
2431 moduleName[len] = 0;
2435 for(module = componentsApp.allModules.first; module; module = module.next)
2437 if(module.name && (!strcmp(module.name, moduleName)))
2440 if(!module) module = componentsApp;
2441 homeModule = module;
2442 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)module));
2444 SetSymbolsDir(null);
2447 AddressBar addressBar { this, borderStyle = bevel, anchor = Anchor { top = 0, left = 0, right = 0 }, size.h = 26, hotKey = altD };
2450 this, anchor = { left = 0, top = 26, bottom = 0 }, borderStyle = 0, background = aliceBlue;
2451 treeBranches = true; collapseControl = true; fullRowSelect = false; rootCollapseButton = true;
2454 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2456 APIPage page = row.GetData(null);
2457 if(view.edit) view.OnLeftButtonDown(0,0,0);
2458 if(page && page.page) page = page.page;
2460 view.PositionCaret(true);
2461 if(page != view.page)
2463 Window activeChild = this.activeChild;
2465 // Back / Forward Support
2466 if(row && !dontRecordHistory)
2468 if(history.count > historyPos+1)
2469 history.count = historyPos+1;
2470 historyPos = history.count-1;
2471 addressBar.back.disabled = (historyPos == 0);
2472 addressBar.forward.disabled = (historyPos >= history.count-1);
2474 history.Add((Instance)(uint64)row.tag);
2475 historyPos = history.count-1;
2477 addressBar.back.disabled = (historyPos == 0);
2478 addressBar.forward.disabled = (historyPos >= history.count-1);
2484 activeChild.Activate();
2486 else if(!view.created)
2490 page = row.GetData(null);
2491 if(page && page.page)
2495 case 1: view.GoToAnchor("Classes"); break;
2496 case 2: view.GoToAnchor("Functions"); break;
2497 case 3: view.GoToAnchor("Definitions"); break;
2498 case 4: view.GoToAnchor("VirtualMethods"); break;
2499 case 5: view.GoToAnchor("Methods"); break;
2500 case 6: view.GoToAnchor("Members"); break;
2501 case 7: view.GoToAnchor("Conversions"); break;
2502 case 8: view.GoToAnchor("EnumerationValues"); break;
2506 sprintf(hex, "%p", (void *)(uintptr)row.tag);
2507 view.GoToAnchor(hex);
2513 view.SetScrollPosition(0, 0);
2521 this, anchor = { top = 26, bottom = 0, right = 0 };
2526 this, anchor.top = 26, leftPane = browser, rightPane = view, split = 300 /*scaleSplit = 0.3 */
2529 bool OnClose(bool parentClosing)
2532 view.OnLeftButtonDown(0,0,0);
2538 mainForm.OpenModule((((GuiApplication)__thisModule).argc > 1) ? ((GuiApplication)__thisModule).argv[1] : "ecere");
2539 //mainForm.OpenModule("ec");
2540 //mainForm.OpenModule("c:/games/chess/debug/chess.sym");
2541 //mainForm.OpenModule("c:/ide/Objects.IDE.Win32.Debug/ide.sym");
2543 int index = mainForm.browser.currentRow.index;
2544 int rowHeight = mainForm.browser.rowHeight;
2545 int height = mainForm.browser.clientSize.h;
2547 mainForm.browser.scroll = { 0, index * rowHeight - height / 2 };
2552 Array<Instance> history { };
2554 bool dontRecordHistory;
2559 if(historyPos < history.count-1)
2563 addressBar.back.disabled = (historyPos == 0);
2564 addressBar.forward.disabled = (historyPos >= history.count-1);
2565 sprintf(location, "api://%p", history[historyPos]);
2566 dontRecordHistory = true;
2567 view.OnOpen(location);
2568 dontRecordHistory = false;
2580 addressBar.back.disabled = (historyPos == 0);
2581 addressBar.forward.disabled = (historyPos >= history.count-1);
2582 sprintf(location, "api://%p", history[historyPos]);
2583 dontRecordHistory = true;
2584 view.OnOpen(location);
2585 dontRecordHistory = false;
2593 mainForm.browser.SelectRow(mainForm.browser.FindSubRow((int64)homeModule));
2597 class EditDialog : Window
2599 borderStyle = sizable;
2600 size = { 600, 400 };
2605 this, anchor = { left = 16, top = 16, right = 18, bottom = 61 }
2609 this, text = $"Save Changes", anchor = { horz = 184, vert = 160 }
2613 this, text = $"Cancel", anchor = { horz = 254, vert = 160 }
2617 #define UTF8_IS_FIRST(x) (__extension__({ byte b = x; (!(b) || !((b) & 0x80) || (b) & 0x40); }))
2618 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
2620 class HelpView : HTMLView
2624 hasVertScroll = true;
2625 hasHorzScroll = true;
2627 char editString[MAX_LOCATION];
2633 page = mainForm.browser.currentRow.GetData(null);
2638 char docDir[MAX_LOCATION];
2640 strcpy(docDir, settings.docDir);
2641 if(FileExists(docDir).isDirectory)
2643 PathCatSlash(docDir, "___docWriteTest");
2644 if(FileExists(docDir).isDirectory)
2647 if(!FileExists(docDir))
2653 if(FileExists(docDir).isDirectory)
2665 GoToAnchor(page.label);
2667 if(page.page) page = page.page;
2670 return HTMLView::OnCreate();
2681 String contents = null;
2684 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2686 if(block.type == TEXT && block.textLen)
2694 for(block = textBlock.parent.subBlocks.first; block; block = block.next)
2696 if(block.type == BR)
2698 else if(block.type == TEXT)
2699 f.Write(block.text, 1, block.textLen);
2703 if((len = f.GetSize()))
2705 contents = new char[len+1];
2706 f.Read(contents, 1, len);
2707 contents[len] = '\0';
2711 char docPath[MAX_LOCATION];
2712 char temp[MAX_LOCATION];
2713 char part[MAX_FILENAME];
2717 DocumentationType type;
2718 DocumentationItem item;
2720 bool docRetrieved = false;
2721 NamespaceDoc nsDoc = null;
2722 ClassDoc clDoc = null;
2723 FunctionDoc fnDoc = null;
2724 MethodDoc mdDoc = null;
2726 Method method = null;
2727 GlobalFunction function = null;
2729 strcpy(temp, editString);
2730 SplitDirectory(temp, part, temp);
2731 module = (Module)strtoull(part, null, 16);
2732 SplitDirectory(temp, part, temp);
2733 object = (void *)strtoull(part, null, 16);
2734 SplitDirectory(temp, part, temp);
2735 data = (void *)strtoull(part, null, 16);
2736 SplitDirectory(temp, part, temp);
2737 if(!strcmp(part, "namespace"))
2738 type = nameSpaceDoc;
2739 else if(!strcmp(part, "function"))
2741 else if(!strcmp(part, "class"))
2743 else if(!strcmp(part, "method"))
2745 SplitDirectory(temp, part, temp);
2746 if(!strcmp(part, "description"))
2748 else if(!strcmp(part, "usage"))
2750 else if(!strcmp(part, "remarks"))
2752 else if(!strcmp(part, "example"))
2754 else if(!strcmp(part, "seeAlso"))
2756 else if(!strcmp(part, "enumerationValue"))
2757 item = enumerationValue;
2758 else if(!strcmp(part, "definition"))
2760 else if(!strcmp(part, "conversion"))
2762 else if(!strcmp(part, "memberDescription"))
2763 item = memberDescription;
2764 else if(!strcmp(part, "propertyDescription"))
2765 item = propertyDescription;
2766 else if(!strcmp(part, "parameter"))
2768 else if(!strcmp(part, "returnValue"))
2771 doc = getDoc(docPath, module, type, object, item, data, !empty && contents);
2773 /* Why invalidate this entry here?
2775 MapIterator<const String, DocCacheEntry> it { map = docCache };
2776 if(it.Index(docPath, false))
2785 case classDoc: cl = (Class)object; break;
2786 case functionDoc: function = object; break;
2787 case methodDoc: method = object; cl = method._class; break;
2792 if(eClass_IsDerived(doc._class, class(ClassDoc)))
2794 clDoc = (ClassDoc)doc;
2795 docRetrieved = true;
2797 else if(eClass_IsDerived(doc._class, class(NamespaceDoc)))
2799 nsDoc = (NamespaceDoc)doc;
2800 docRetrieved = true;
2806 if(type == functionDoc)
2808 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2809 if(name) name += 2; else name = function.name;
2810 if(!nsDoc.functions && !empty) nsDoc.functions = { };
2811 fnDoc = nsDoc.functions[name];
2812 if(!fnDoc && !empty)
2815 nsDoc.functions[name] = fnDoc;
2818 else if(type == methodDoc)
2820 if(!clDoc.methods && !empty) clDoc.methods = { };
2821 mdDoc = clDoc.methods[method.name];
2822 if(!mdDoc && !empty)
2825 clDoc.methods[method.name] = mdDoc;
2829 if(!empty || mdDoc || fnDoc || (type == classDoc && clDoc) || (type == nameSpaceDoc && nsDoc))
2834 if(type == methodDoc) { mdDoc.description = contents; contents = null; }
2835 else if(type == functionDoc) { fnDoc.description = contents; contents = null; }
2836 else if(type == classDoc) { clDoc.description = contents; contents = null; }
2837 else { nsDoc.description = contents; contents = null; }
2840 if(type == methodDoc) { mdDoc.usage = contents; contents = null; }
2841 else if(type == functionDoc) { fnDoc.usage = contents; contents = null; }
2842 else if(type == classDoc) { clDoc.usage = contents; contents = null; }
2845 if(type == methodDoc) { mdDoc.remarks = contents; contents = null; }
2846 else if(type == functionDoc) { fnDoc.remarks = contents; contents = null; }
2847 else if(type == classDoc) { clDoc.remarks = contents; contents = null; }
2850 if(type == methodDoc) { mdDoc.example = contents; contents = null; }
2851 else if(type == functionDoc) { fnDoc.example = contents; contents = null; }
2852 else if(type == classDoc) { clDoc.example = contents; contents = null; }
2855 if(type == methodDoc) { mdDoc.also = contents; contents = null; }
2856 else if(type == functionDoc) { fnDoc.also = contents; contents = null; }
2857 else if(type == classDoc) { clDoc.also = contents; contents = null; }
2860 if(type == methodDoc) { mdDoc.returnValue = contents; contents = null; }
2861 else if(type == functionDoc) { fnDoc.returnValue = contents; contents = null; }
2863 case enumerationValue:
2866 if(!clDoc.values) clDoc.values = { };
2867 itDoc = clDoc.values[((NamedLink)data).name];
2871 clDoc.values[((NamedLink)data).name] = itDoc;
2873 itDoc.description = contents; contents = null;
2879 if(!nsDoc.defines) nsDoc.defines = { };
2880 itDoc = nsDoc.defines[((Definition)data).name];
2884 nsDoc.defines[((Definition)data).name] = itDoc;
2886 itDoc.description = contents; contents = null;
2891 ConversionDoc itDoc;
2892 const char * name = RSearchString(((Property)data).name, "::", strlen(((Property)data).name), true, false);
2893 if(name) name += 2; else name = ((Property)data).name;
2894 if(!clDoc.conversions) clDoc.conversions = { };
2895 itDoc = clDoc.conversions[name];
2899 clDoc.conversions[name] = itDoc;
2901 itDoc.description = contents; contents = null;
2904 case memberDescription:
2907 if(!clDoc.fields) clDoc.fields = { };
2908 itDoc = clDoc.fields[((DataMember)data).name];
2912 clDoc.fields[((DataMember)data).name] = itDoc;
2914 itDoc.description = contents; contents = null;
2917 case propertyDescription:
2920 if(!clDoc.properties) clDoc.properties = { };
2921 itDoc = clDoc.properties[((Property)data).name];
2925 clDoc.properties[((Property)data).name] = itDoc;
2927 itDoc.description = contents; contents = null;
2935 for(prev = data; prev; prev = prev.prev);
2936 name = ((Type)data).name;
2937 if(type == functionDoc)
2939 if(!fnDoc.parameters) fnDoc.parameters = { };
2940 itDoc = fnDoc.parameters[name];
2944 fnDoc.parameters[name] = itDoc;
2946 itDoc.description = contents; contents = null;
2948 else if(type == methodDoc)
2950 if(!mdDoc.parameters) mdDoc.parameters = { };
2951 itDoc = mdDoc.parameters[name];
2955 mdDoc.parameters[name] = itDoc;
2957 itDoc.description = contents; contents = null;
2965 if(type == functionDoc && fnDoc && fnDoc.isEmpty)
2967 MapIterator<String, FunctionDoc> it { map = nsDoc.functions };
2968 const char * name = RSearchString(function.name, "::", strlen(function.name), true, false);
2969 if(name) name += 2; else name = function.name;
2970 if(it.Index(name, false))
2976 else if(type == methodDoc && mdDoc && mdDoc.isEmpty)
2978 MapIterator<String, MethodDoc> it { map = clDoc.methods };
2979 if(it.Index(method.name, false))
2988 char dirPath[MAX_LOCATION];
2989 StripLastDirectory(docPath, dirPath);
2990 if(FileExists(docPath))
2991 DeleteFile(docPath);
2992 if(cl ? (clDoc && !clDoc.isEmpty) : (nsDoc && !nsDoc.isEmpty))
2995 if(!FileExists(dirPath))
2997 if((f = FileOpen(docPath, write)))
2999 WriteECONObject(f, cl ? class(ClassDoc) : class(NamespaceDoc), doc, 0);
3003 PrintLn("error: writeClassDocFile -- problem opening file: ", docPath);
3012 Block parent = textBlock.parent;
3013 while((block = parent.subBlocks.first))
3015 parent.subBlocks.Remove(block);
3018 textBlock = Block { type = TEXT, parent = parent, font = parent.font };
3019 textBlock.text = CopyString($"[Add Text]");
3020 textBlock.textLen = strlen(textBlock.text);
3021 parent.subBlocks.Add(textBlock);
3029 PositionCaret(true);
3034 bool OnLeftButtonDown(int x, int y, Modifiers mods)
3038 if(edit && (!textBlock || overLink != textBlock.parent))
3042 HTMLView::OnLeftButtonDown(x, y, mods);
3043 selPosition = curPosition = 0;
3044 selBlock = textBlock;
3048 result = HTMLView::OnLeftButtonDown(x, y, mods);
3050 if(!edit && clickedLink)
3053 if(clickedLink == overLink && clickedLink.href)
3055 if(OnOpen(clickedLink.href))
3063 if(textBlock && overLink == textBlock.parent)
3065 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3066 selBlock = textBlock;
3067 PositionCaret(true);
3075 bool OnLeftButtonUp(int x, int y, Modifiers mods)
3077 if(!edit || !textBlock || clickedLink != textBlock.parent)
3079 HTMLView::OnLeftButtonUp(x, y, mods);
3082 selPosition = curPosition = TextPosFromPoint(x, y, &textBlock, true);
3083 selBlock = textBlock;
3084 PositionCaret(true);
3095 bool OnMouseMove(int x, int y, Modifiers mods)
3097 if(edit && selecting)
3099 curPosition = TextPosFromPoint(x, y, &textBlock, true);
3100 PositionCaret(true);
3103 return HTMLView::OnMouseMove(x, y, mods);
3106 bool OnLeftDoubleClick(int mx, int my, Modifiers mods)
3108 if(edit && textBlock)
3114 selPosition = curPosition = TextPosFromPoint(mx, my, &textBlock, false);
3115 selBlock = textBlock;
3116 for(c = curPosition; c >= 0; c--)
3119 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[c])) c--;
3120 ch = UTF8GetChar(textBlock.text + c, &numBytes);
3121 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3127 for(c = start; c < textBlock.textLen; c += numBytes)
3129 unichar ch = UTF8GetChar(textBlock.text + c, &numBytes);
3130 if(!CharMatchCategories(ch, letters|numbers|marks|connector))
3133 selPosition = start;
3136 PositionCaret(true);
3144 bool OnOpen(char * href)
3146 if(!strncmp(href, "api://", 6))
3148 int64 tag = (int64)strtoull(href + 6, null, 16);
3149 DataRow row = mainForm.browser.FindSubRow(tag);
3153 mainForm.browser.SelectRow(row);
3154 while((row = row.parent))
3155 row.collapsed = false;
3156 row = mainForm.browser.currentRow;
3157 mainForm.browser.scroll = { 0, row.index * mainForm.browser.rowHeight - mainForm.browser.clientSize.h / 2 };
3160 else if(!strncmp(href, "edit://", 7))
3163 int startX = clickedLink.startX, startY = clickedLink.startY;
3164 for(block = (Block)clickedLink.subBlocks.first; block; block = block.next)
3166 if(block.type == TEXT) startX = block.startX, startY = block.startY;
3167 if(block.type == BR && (!block.prev || !block.next || block.next.type != TEXT))
3169 Block newBlock { type = TEXT, parent = block.parent, font = block.parent.font };
3171 display.FontExtent(block.font.font, " ", 1, null, &th);
3174 block.parent.subBlocks.Insert(null, newBlock);
3179 block.parent.subBlocks.Insert(block, newBlock);
3180 startY += block.prev.height;
3182 newBlock.startX = startX;
3183 newBlock.startY = startY;
3184 newBlock.text = new0 char[1];
3188 textBlock = (Block)clickedLink.subBlocks.first;
3189 if(!strcmp(textBlock.text, $"[Add Text]"))
3191 textBlock.text[0] = 0;
3192 textBlock.textLen = 0;
3195 strcpy(editString, href + 7);
3196 selPosition = curPosition = 0;
3197 selBlock = textBlock;
3200 // PositionCaret(true);
3207 void DeleteSelection()
3209 if(textBlock != selBlock || curPosition != selPosition)
3211 if(textBlock == selBlock)
3213 // Within same block
3214 int start = Min(curPosition, selPosition);
3215 int end = Max(curPosition, selPosition);
3216 memmove(textBlock.text + start, textBlock.text + end, textBlock.textLen - end);
3217 textBlock.textLen -= end-start;
3218 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3219 curPosition = start;
3220 selPosition = start;
3224 int startSel, endSel;
3225 Block startSelBlock = null, endSelBlock = null, b, next;
3227 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3229 startSelBlock.text = renew startSelBlock.text char[startSel + endSelBlock.textLen - endSel + 1];
3230 memcpy(startSelBlock.text + startSel, endSelBlock.text + endSel, endSelBlock.textLen - endSel + 1);
3232 startSelBlock.textLen = startSel + endSelBlock.textLen - endSel;
3233 for(b = startSelBlock.next; b; b = next)
3235 bool isEnd = b == endSelBlock;
3236 next = GetNextBlock(b);
3237 b.parent.subBlocks.Remove(b);
3242 textBlock = startSelBlock;
3243 selBlock = startSelBlock;
3244 curPosition = startSel;
3245 selPosition = startSel;
3249 PositionCaret(true);
3254 String GetSelectionString()
3256 String selection = null;
3257 if(textBlock == selBlock)
3259 // Within same block
3260 int start = Min(curPosition, selPosition);
3261 int end = Max(curPosition, selPosition);
3262 int len = end - start;
3263 selection = new char[len + 1];
3264 memcpy(selection, textBlock.text + start, len);
3269 int startSel, endSel;
3270 Block startSelBlock = null, endSelBlock = null, b;
3273 NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel);
3276 for(b = startSelBlock; b; b = GetNextBlock(b))
3278 int start = (b == startSelBlock) ? startSel : 0;
3279 int end = (b == endSelBlock) ? endSel : b.textLen;
3280 int len = end - start;
3282 if(b == endSelBlock)
3284 else if(b.type == TEXT)
3288 selection = new char[totalLen + 1];
3290 for(b = startSelBlock; b; b = GetNextBlock(b))
3292 int start = (b == startSelBlock) ? startSel : 0;
3293 int end = (b == endSelBlock) ? endSel : b.textLen;
3294 int len = end - start;
3295 memcpy(selection + totalLen, b.text + start, len);
3297 if(b == endSelBlock)
3299 else if(b.type == TEXT)
3300 selection[totalLen++] = '\n';
3302 selection[totalLen] = 0;
3307 void CopySelection()
3309 String s = GetSelectionString();
3312 int len = strlen(s);
3314 if(cb.Allocate(len + 1))
3316 memcpy(cb.text, s, len + 1);
3324 bool OnKeyDown(Key key, unichar ch)
3331 OnLeftButtonDown(0,0,0);
3333 case Key { end, shift = true }:
3335 curPosition = textBlock.textLen;
3338 selPosition = curPosition;
3339 selBlock = textBlock;
3341 PositionCaret(true);
3344 case Key { home, shift = true }:
3349 selPosition = curPosition;
3350 selBlock = textBlock;
3352 PositionCaret(true);
3355 case Key { home, ctrl = true, shift = true }:
3358 while(textBlock.prev)
3359 textBlock = textBlock.prev.prev;
3362 selPosition = curPosition;
3363 selBlock = textBlock;
3365 PositionCaret(true);
3368 case Key { end, ctrl = true, shift = true }:
3370 while(textBlock.next && textBlock.next.next)
3371 textBlock = textBlock.next.next;
3372 curPosition = textBlock.textLen;
3375 selPosition = curPosition;
3376 selBlock = textBlock;
3378 PositionCaret(true);
3384 return HTMLView::OnKeyDown(key, ch);
3388 bool OnKeyHit(Key key, unichar ch)
3394 case Key { up, shift = true }:
3397 if(caretY == textBlock.startY)
3401 textBlock = textBlock.prev.prev;
3402 curPosition = Min(curPosition, textBlock.textLen);
3405 selPosition = curPosition;
3406 selBlock = textBlock;
3409 PositionCaret(false);
3419 int sx = textBlock.startX, sy = textBlock.startY;
3420 char * text = textBlock.text;
3422 Block block = textBlock;
3423 while(block && block.type != TD) block = block.parent;
3426 Block table = block;
3427 while(table && table.type != TABLE) table = table.parent;
3429 maxW = block.w - 2* table.cellPadding;
3431 maxW = clientSize.w - 10 - sx;
3434 maxW = clientSize.w - 10 - sx;
3435 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3439 int startPos = textPos;
3442 bool lineComplete = false;
3443 for(; textPos<textBlock.textLen && !lineComplete;)
3447 char * nextSpace = strchr(text + textPos, ' ');
3450 len = (nextSpace - (text + textPos)) + 1;
3452 len = textBlock.textLen - textPos;
3454 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3456 if(x + width + w > maxW && x > 0)
3458 lineComplete = true;
3468 if(textPos == textBlock.textLen || (sy == caretY - th && caretX <= x + width + sx))
3471 curPosition = textPos;
3472 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3475 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3476 len = curPosition - startPos;
3477 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3481 selPosition = curPosition;
3482 selBlock = textBlock;
3486 PositionCaret(false);
3490 if(sy == caretY - th || textPos == textBlock.textLen)
3492 if(textPos != textBlock.textLen)
3494 int c = textPos - 1;
3495 while(c > 0 && text[c] == ' ') c--;
3496 curPosition = c + 1;
3499 selPosition = curPosition;
3500 selBlock = textBlock;
3506 curPosition = textBlock.textLen;
3509 selPosition = curPosition;
3510 selBlock = textBlock;
3514 PositionCaret(false);
3518 sx = textBlock.startX;
3519 } while(textPos < textBlock.textLen);
3524 case Key { down, shift = true }:
3529 int sx = textBlock.startX, sy = textBlock.startY;
3530 char * text = textBlock.text;
3532 Block block = textBlock;
3533 while(block && block.type != TD) block = block.parent;
3536 Block table = block;
3537 while(table && table.type != TABLE) table = table.parent;
3539 maxW = block.w - 2* table.cellPadding;
3541 maxW = clientSize.w - 10 - sx;
3544 maxW = clientSize.w - 10 - sx;
3545 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3547 while(!textPos || textPos < textBlock.textLen)
3549 int startPos = textPos;
3552 bool lineComplete = false;
3553 for(; (textPos < textBlock.textLen) && !lineComplete;)
3557 char * nextSpace = strchr(text + textPos, ' ');
3560 len = (nextSpace - (text + textPos)) + 1;
3562 len = textBlock.textLen - textPos;
3564 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
3566 if(x + width + w > maxW && x > 0)
3568 lineComplete = true;
3578 if(sy > caretY && (textPos == textBlock.textLen || caretX <= x + width + sx))
3580 curPosition = textPos;
3582 while(curPosition > 0 && x + sx > caretX && textPos > startPos)
3585 while(curPosition > 0 && !UTF8_IS_FIRST(text[--curPosition]));
3586 len = curPosition - startPos;
3587 display.FontExtent(textBlock.font.font, text + startPos, len, &x, null);
3591 selPosition = curPosition;
3592 selBlock = textBlock;
3595 PositionCaret(false);
3601 curPosition = textBlock.textLen;
3604 selPosition = curPosition;
3605 selBlock = textBlock;
3608 PositionCaret(false);
3611 else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
3615 textBlock = textBlock.next.next;
3616 sy = textBlock.startY;
3617 sx = textBlock.startX;
3618 text = textBlock.text;
3623 sx = textBlock.startX;
3627 /*if(textBlock.next && textBlock.next.next)
3629 textBlock = textBlock.next.next;
3630 selPosition = curPosition = Min(curPosition, textBlock.textLen);
3631 selBlock = textBlock;
3632 PositionCaret(false);
3636 case Key { right, shift = true, ctrl = true }:
3639 bool foundAlpha = false;
3641 Block line, lastLine;
3644 for(line = textBlock; (line && !found); line = line.next ? line.next.next : null)
3646 int start = (line == textBlock) ? curPosition : 0;
3648 for(c = start; c < line.textLen; c++)
3650 char ch = line.text[c];
3651 bool isAlUnder = CharMatchCategories(ch, letters|numbers|marks|connector);
3652 if(key.shift ? isAlUnder : !isAlUnder)
3666 selPosition = curPosition;
3667 selBlock = textBlock;
3671 PositionCaret(true);
3676 // No next word found,
3677 if(!found && (c != curPosition || line != textBlock))
3681 lastC = line.textLen-1;
3686 curPosition = line.textLen;
3689 selPosition = curPosition;
3690 selBlock = textBlock;
3695 PositionCaret(true);
3701 if(key.shift && found)
3703 curPosition = lastC+1;
3704 textBlock = lastLine;
3705 PositionCaret(true);
3710 case Key { left, ctrl = true, shift = true }:
3713 bool foundAlpha = false;
3715 Block line, lastLine;
3718 for(line = textBlock; (line && !found); line = line.prev ? line.prev.prev : null)
3721 if(curPosition == 0 && line != textBlock)
3724 lastC = line.textLen;
3728 if(line == textBlock) start = curPosition-1; else start = line.textLen-1;
3729 for(c = start; c>=0; c--)
3731 if(CharMatchCategories(line.text[c], letters|numbers|marks|connector))
3746 // No next word found,
3747 if(!found && curPosition > 0)
3757 textBlock = lastLine;
3758 curPosition = lastC;
3761 selPosition = curPosition;
3762 selBlock = textBlock;
3764 PositionCaret(true);
3769 case Key { right, shift = true }:
3771 if(curPosition < textBlock.textLen)
3773 curPosition += UTF8_NUM_BYTES(textBlock.text[curPosition]);
3776 selPosition = curPosition;
3777 selBlock = textBlock;
3779 PositionCaret(true);
3782 else if(textBlock.next && textBlock.next.next)
3784 textBlock = textBlock.next.next;
3788 selPosition = curPosition;
3789 selBlock = textBlock;
3791 PositionCaret(true);
3795 case Key { left, shift = true }:
3799 while(curPosition > 0 && !UTF8_IS_FIRST(textBlock.text[--curPosition]));
3802 selPosition = curPosition;
3803 selBlock = textBlock;
3805 PositionCaret(true);
3808 else if(textBlock.prev)
3810 textBlock = textBlock.prev.prev;
3811 curPosition = textBlock.textLen;
3814 selPosition = curPosition;
3815 selBlock = textBlock;
3817 PositionCaret(true);
3823 if(textBlock == selBlock && curPosition == selPosition)
3827 int c = curPosition;
3829 while(c > 0 && !UTF8_IS_FIRST(textBlock.text[--c])) nb++;
3830 memmove(textBlock.text + curPosition - nb, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3831 textBlock.textLen -= nb;
3832 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3834 selPosition = curPosition;
3835 selBlock = textBlock;
3839 PositionCaret(true);
3842 else if(textBlock.prev)
3844 Block prev = textBlock.prev, prevBlock = textBlock.prev.prev;
3845 prevBlock.text = renew prevBlock.text char[prevBlock.textLen + textBlock.textLen + 1];
3846 memcpy(prevBlock.text + prevBlock.textLen, textBlock.text, textBlock.textLen + 1);
3848 selPosition = curPosition = prevBlock.textLen;
3849 selBlock = textBlock;
3850 prevBlock.textLen += textBlock.textLen;
3851 textBlock.parent.subBlocks.Remove(prev);
3852 if(prev == selBlock)
3854 selBlock = textBlock;
3855 selPosition = curPosition;
3858 textBlock.parent.subBlocks.Remove(textBlock);
3859 if(textBlock == selBlock)
3861 selBlock = prevBlock;
3862 selPosition = curPosition;
3865 textBlock = prevBlock;
3869 PositionCaret(true);
3878 if(textBlock != selBlock || curPosition != selPosition)
3880 else if(textBlock.textLen > curPosition)
3882 int nb = UTF8_NUM_BYTES(textBlock.text[curPosition]);
3883 memmove(textBlock.text + curPosition, textBlock.text + curPosition + nb, textBlock.textLen - curPosition + 1 - nb + 1);
3884 textBlock.textLen -= nb;
3885 textBlock.text = renew textBlock.text char[textBlock.textLen + 1];
3890 PositionCaret(true);
3893 else if(textBlock.next && textBlock.next.next)
3895 Block next = textBlock.next, nextBlock = textBlock.next.next;
3896 textBlock.text = renew textBlock.text char[textBlock.textLen + nextBlock.textLen + 1];
3897 memcpy(textBlock.text + textBlock.textLen, nextBlock.text, nextBlock.textLen + 1);
3899 textBlock.textLen += nextBlock.textLen;
3900 textBlock.parent.subBlocks.Remove(next);
3901 if(next == selBlock)
3903 selBlock = textBlock;
3904 selPosition = curPosition;
3907 textBlock.parent.subBlocks.Remove(nextBlock);
3908 if(nextBlock == selBlock)
3910 selBlock = textBlock;
3911 selPosition = curPosition;
3917 PositionCaret(true);
3931 block = { type = BR, parent = textBlock.parent, font = textBlock.font };
3932 newBlock = { type = TEXT, parent = textBlock.parent, font = textBlock.font };
3933 startY = textBlock.startY;
3934 startX = textBlock.startX;
3936 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
3937 textBlock.parent.subBlocks.Insert(textBlock, block);
3938 textBlock.parent.subBlocks.Insert(block, newBlock);
3942 newBlock.textLen = textBlock.textLen - curPosition;
3943 newBlock.text = new char[newBlock.textLen+1];
3944 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
3945 textBlock.textLen = curPosition;
3946 textBlock.text[curPosition] = 0;
3948 newBlock.startY = startY;
3949 newBlock.startX = startX;
3950 selPosition = curPosition = 0;
3955 textBlock = newBlock;
3956 selBlock = textBlock;
3957 PositionCaret(true);
3962 case Key { del, shift = true }:
3977 ClipBoard clipBoard { };
3978 if(clipBoard.Load())
3981 char * text = clipBoard.memory;
3989 parent = textBlock.parent;
3990 font = textBlock.font;
3995 if(ch == '\n' || ch == '\r' || !ch)
3997 int len = c - start;
3998 textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
3999 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4000 memcpy(textBlock.text + curPosition, text + start, len);
4001 textBlock.textLen += len;
4003 selPosition = curPosition;
4004 selBlock = textBlock;
4007 Block block { type = BR, parent = parent, font = font };
4008 Block newBlock { type = TEXT, parent = parent, font = font };
4009 int startY = textBlock.startY, startX = textBlock.startX;
4012 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4013 textBlock.parent.subBlocks.Insert(textBlock, block);
4014 textBlock.parent.subBlocks.Insert(block, newBlock);
4018 newBlock.textLen = textBlock.textLen - curPosition;
4019 newBlock.text = new char[newBlock.textLen+1];
4020 memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4021 textBlock.textLen = curPosition;
4022 textBlock.text[curPosition] = 0;
4024 newBlock.startY = startY;
4025 newBlock.startX = startX;
4026 selPosition = curPosition = 0;
4027 selBlock = textBlock;
4028 textBlock = newBlock;
4030 if(ch == '\r' && text[c+1] == '\n') c++;
4036 PositionCaret(true);
4044 // eC BUG HERE: (Should be fixed)
4045 if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
4048 int len = UTF32toUTF8Len(&ch, 1, string, 5);
4053 textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
4054 memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
4056 for(c = 0; c<len; c++)
4058 textBlock.text[curPosition] = string[c];
4059 textBlock.textLen++;
4062 selPosition = curPosition;
4063 selBlock = textBlock;
4066 //Clear(html.block);
4067 //CreateForms(html.block);
4072 PositionCaret(true);
4081 void OnResize(int width, int height)
4083 HTMLView::OnResize(width, height);
4084 PositionCaret(true);
4088 void PositionCaret(bool setCaretX)
4094 int sx = textBlock.startX, sy = textBlock.startY;
4095 char * text = textBlock.text;
4097 Block block = textBlock;
4098 while(block && block.type != TD) block = block.parent;
4101 Block table = block;
4102 while(table && table.type != TABLE) table = table.parent;
4104 maxW = block.w - 2* table.cellPadding;
4106 maxW = clientSize.w - 10 - sx;
4109 maxW = clientSize.w - 10 - sx;
4111 display.FontExtent(textBlock.font.font, " ", 1, null, &th);
4113 while(textPos < textBlock.textLen)
4115 int startPos = textPos;
4118 bool lineComplete = false;
4120 for(; textPos<textBlock.textLen && !lineComplete;)
4124 char * nextSpace = strchr(text + textPos, ' ');
4127 len = (nextSpace - (text + textPos)) + 1;
4129 len = textBlock.textLen - textPos;
4131 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4133 if(x + width + w > maxW && x > 0)
4135 lineComplete = true;
4148 if(curPosition < textPos || textPos == textBlock.textLen)
4150 int len = curPosition - startPos;
4151 display.FontExtent(textBlock.font.font, text + startPos, len, &tw, null);
4156 sx = textBlock.startX;
4161 SetCaret(sx, sy, th);
4163 Point scrollPos = scroll;
4164 bool doScroll = false;
4165 if(sy - scroll.y + th > clientSize.h)
4167 scrollPos.y = sy + th - clientSize.h;
4170 else if(sy - scroll.y < 0)
4175 if(sx - scroll.x + 10 > clientSize.w)
4177 scrollPos.x = sx + 10 - clientSize.w;
4180 else if(sx - scroll.x < 10)
4182 scrollPos.x = sx - 10;
4193 // Returns a character offset into the TextBlock from a window coordinate
4194 int TextPosFromPoint(int px, int py, Block * block, bool half)
4196 Block parentBlock = this.textBlock.parent;
4199 *block = this.textBlock;
4204 for(textBlock = parentBlock.subBlocks.first; textBlock; textBlock = textBlock.next)
4206 int sx = textBlock.startX, sy = textBlock.startY;
4209 char * text = textBlock.text;
4211 Block b = textBlock;
4214 if(textBlock.type != TEXT) continue;
4216 while(b && b.type != TD) b = b.parent;
4220 while(table && table.type != TABLE) table = table.parent;
4222 maxW = b.w - 2* table.cellPadding;
4224 maxW = clientSize.w - 10 - sx;
4227 maxW = clientSize.w - 10 - sx;
4229 display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
4230 //space = space/2+2;
4233 while(textPos < textBlock.textLen)
4237 bool lineComplete = false;
4239 for(; textPos<textBlock.textLen && !lineComplete;)
4243 char * nextSpace = strchr(text + textPos, ' ');
4246 len = (nextSpace - (text + textPos)) + 1;
4248 len = textBlock.textLen - textPos;
4250 display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
4252 sx = x + textBlock.startX;
4253 if(/*py >= sy && */py < sy + th && /*px >= sx-space && */px < sx + w-space)
4258 for(c = textPos; (ch = text[c]); c += numBytes)
4260 numBytes = UTF8_NUM_BYTES(ch);
4261 display.FontExtent(textBlock.font.font, text + c, numBytes, &w, &th);
4262 if(/*py >= sy && */py < sy + th && /*px >= sx-w/2-space && */px < sx + (half ? w/2 : w) -space)
4269 if(x + width + w > maxW && x > 0)
4271 lineComplete = true;
4284 if(/*py >= sy && */py < sy + th)
4287 return textBlock.textLen;
4292 result = textBlock.textLen;
4298 Application componentsApp;
4300 class Documentor : GuiApplication
4304 Platform os = __runtimePlatform;
4305 SetGlobalContext(globalContext);
4306 SetExcludedSymbols(&excludedSymbols);
4307 SetDefines(&::defines);
4308 SetImports(&imports);
4309 SetInDocumentor(true);
4311 SetGlobalData(globalData);
4313 settingsContainer.dataOwner = &settings;
4314 settingsContainer.Load();
4315 if(!settings.docDir || !settings.docDir[0] )
4317 if(os == win32) // if Windows OS then
4319 char programFilesDir[MAX_LOCATION];
4320 char appData[MAX_LOCATION];
4321 char homeDrive[MAX_LOCATION];
4322 char winDir[MAX_LOCATION];
4323 GetEnvironment("APPDATA", appData, sizeof(appData));
4324 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
4325 GetEnvironment("windir", winDir, sizeof(winDir));
4326 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
4328 PathCat(programFilesDir, "ECERE SDK\\doc");
4329 settings.docDir = programFilesDir;
4331 else if(homeDrive[0])
4333 PathCat(homeDrive, "ECERE SDK\\doc");
4334 settings.docDir = homeDrive;
4338 PathCat(winDir, "..\\ECERE SDK\\doc");
4339 settings.docDir = winDir;
4342 settings.docDir = "C:\\ECERE SDK\\doc";
4344 else // if Os is Linux, or Mac OSX or something else
4345 settings.docDir = "/usr/share/ecere/doc/";
4346 settingsContainer.Save();
4352 Module module = eModule_Load(componentsApp, "ecere" /*argv[1]*/, privateAccess);
4354 AddComponents(module, true);
4355 mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)module);
4356 // mainForm.browser.currentRow = row = mainForm.browser.FindSubRow((int64)eSystem_FindClass(componentsApp, "Window"));
4357 while((row = row.parent))
4358 row.collapsed = false;
4362 commandThread.Create();
4366 bool Cycle(bool idle)
4369 mainForm.Destroy(0);
4378 if(commandThread.created)
4380 console.CloseInput();
4381 console.CloseOutput();
4383 commandThread.Wait();
4387 FreeContext(globalContext);
4388 FreeExcludedSymbols(excludedSymbols);
4389 ::defines.Free(FreeModuleDefine);
4390 imports.Free(FreeModuleImport);
4392 FreeGlobalData(globalData);
4393 FreeTypeData(componentsApp);
4395 delete componentsApp;
4399 ConsoleFile console { };
4400 MainForm mainForm { };
4403 Thread commandThread
4410 console.GetLine(command, sizeof(command));
4411 if(!quit && command[0])
4414 if(!strcmpi(command, "Activate"))
4415 mainForm.Activate();
4416 else if(!strcmpi(command, "Quit"))
4424 #endif // !defined(EAR_TO_ECON_ECDOC)
4429 property String name { get { return this ? name : null; } set { delete name; name = CopyString(value); } isset { return name && *name; } }
4430 property String description { get { return this ? description : null; } set { delete description; description = CopyString(value); } isset { return description && *description; } }
4434 property bool isEmpty
4440 (description && *description));
4450 class MoreDoc : ItemDoc
4453 property String usage { get { return this ? usage : null; } set { delete usage; usage = CopyString(value); } isset { return usage && *usage; } }
4454 property String example { get { return this ? example : null; } set { delete example; example = CopyString(value); } isset { return example && *example; } }
4455 property String remarks { get { return this ? remarks : null; } set { delete remarks; remarks = CopyString(value); } isset { return remarks && *remarks; } }
4456 property String also { get { return this ? also : null; } set { delete also; also = CopyString(value); } isset { return also && *also; } }
4462 property bool isEmpty
4467 (usage && *usage) ||
4468 (example && *example) ||
4469 (remarks && *remarks) ||
4483 class NamespaceDoc : ItemDoc
4486 Map<String, DefineDoc> defines;
4487 Map<String, FunctionDoc> functions;
4489 property bool isEmpty
4494 (defines && defines.count) ||
4495 (functions && functions.count) ||
4506 class DefineDoc : ItemDoc { }
4508 class FunctionDoc : MoreDoc
4511 Map<String, ParameterDoc> parameters;
4512 property String returnValue { get { return this ? returnValue : null; } set { delete returnValue; returnValue = CopyString(value); } isset { return returnValue && *returnValue; } }
4515 property bool isEmpty
4520 (parameters && parameters.count) ||
4521 (returnValue && *returnValue) ||
4532 class ParameterDoc : ItemDoc
4538 class ClassDoc : MoreDoc
4541 Map<String, ValueDoc> values;
4542 Map<String, FieldDoc> fields;
4543 Map<String, PropertyDoc> properties;
4544 Map<String, ConversionDoc> conversions;
4545 Map<String, MethodDoc> methods;
4547 property bool isEmpty
4552 (values && values.count) ||
4553 (fields && fields.count) ||
4554 (properties && properties.count) ||
4555 (conversions && conversions.count) ||
4556 (methods && methods.count) ||
4570 class ValueDoc : ItemDoc { }
4572 class FieldDoc : ItemDoc { }
4574 class PropertyDoc : ItemDoc { }
4576 class ConversionDoc : ItemDoc { }
4578 class MethodDoc : FunctionDoc { }
4580 char * getDocFileNameFromTypeName(const char * typeName)
4582 char * docFileName = new char[MAX_FILENAME];
4583 const char * swap = "pointer";
4584 const char * s = typeName;
4585 char * d = docFileName;
4586 const char * end = s + strlen(typeName);
4587 int swapLen = strlen(swap);
4605 class DocCacheEntry //: struct // TOCHECK: Why does this causes an error: 'struct __ecereNameSpace__ecere__com__MapIterator' has no member named 'data'
4608 Time timeStamp; // Should this be last accessed, or last retrieved?
4617 Map<String, DocCacheEntry> docCache { };