cleaned all trailing white space from source files.
[sdk] / documentor / src / Documentor.ec
index 2cc1a7c..e01391e 100644 (file)
@@ -8,7 +8,10 @@ static Context globalContext { };
 static OldList defines { };
 static OldList imports { };
 static NameSpace globalData;
-static OldList excludedSymbols { offset = (uint)&((Symbol)0).left }; 
+static OldList excludedSymbols { offset = (uint)&((Symbol)0).left };
+static bool readOnly;
+
+define app = (GuiApplication)__thisModule.application;
 
 #define UTF8_NUM_BYTES(x)  (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
 
@@ -27,7 +30,7 @@ static bool editing = true;
 
 enum CodeObjectType { typeClass, typeData, typeMethod, typeEvent, typeProperty, typeNameSpace, typeDataType, typeEnumValue, typeDataPrivate, typeMethodPrivate, typePropertyPrivate };
 
-static char * iconNames[CodeObjectType] = 
+static char * iconNames[CodeObjectType] =
 {
    "<:ecere>constructs/class.png",
    "<:ecere>constructs/data.png",
@@ -189,7 +192,7 @@ static void _PrintType(Type type, char * string, bool printName, bool printFunct
                DocPrintType(type.returnType, string, false, fullName);
                strcat(string, " ");
             }
-            
+
             // DANGER: Testing This
             if(printName)
             {
@@ -267,7 +270,7 @@ static void _PrintType(Type type, char * string, bool printName, bool printFunct
                      strcat(size, arrayType.enumClass.string);
                   else if(arrayType.arraySizeExp)
                      PrintExpression(arrayType.arraySizeExp, size);
-                  //sprintf(string, "%s[%s]", baseType, size); 
+                  //sprintf(string, "%s[%s]", baseType, size);
                   strcat(size, "]");
 
                   arrayType = arrayType.arrayType;
@@ -283,10 +286,10 @@ static void _PrintType(Type type, char * string, bool printName, bool printFunct
                   strcpy(size, type.enumClass.string);
                else if(type.arraySizeExp)
                   PrintExpression(type.arraySizeExp, size);
-               //sprintf(string, "%s[%s]", baseType, size); 
+               //sprintf(string, "%s[%s]", baseType, size);
                strcat(string, baseType);
                strcat(string, "[");
-               strcat(string, size); 
+               strcat(string, size);
                strcat(string, "]");
                */
 
@@ -396,6 +399,16 @@ public:
    {
       page.Generate(f);
    }
+
+   virtual Module GetModule()
+   {
+      return page ? page.GetModule() : null;
+   }
+
+   virtual NameSpace * GetNameSpace()
+   {
+      return page ? page.GetNameSpace() : null;
+   }
 };
 
 enum DocumentationType
@@ -486,7 +499,7 @@ static void FigureFileName(char * fileName, Module module, DocumentationType typ
       case example: strcat(fileName, "example"); break;
       case seeAlso: strcat(fileName, "seeAlso"); break;
       case returnValue: strcat(fileName, "returnValue"); break;
-      case enumerationValue: 
+      case enumerationValue:
          strcat(fileName, "enumeration values/");
          strcat(fileName, ((NamedLink)data).name);
          break;
@@ -551,7 +564,7 @@ static char * ReadDoc(Module module, DocumentationType type, void * object, Docu
       if(!contents[c])
          delete contents;
    }
-   if(editing && !contents)
+   if(editing && !contents && !readOnly)
       contents = CopyString($"[Add Text]");
    return contents;
 }
@@ -560,7 +573,17 @@ class APIPageNameSpace : APIPage
 {
    NameSpace * nameSpace;
    Module module;
-   
+
+   Module GetModule()
+   {
+      return module;
+   }
+
+   NameSpace * GetNameSpace()
+   {
+      return nameSpace;
+   }
+
    void Generate(File f)
    {
       char string[1024];
@@ -603,7 +626,7 @@ class APIPageNameSpace : APIPage
          strcpy(nsName, temp);
          ns = ns->parent;
       }
-      if(nsName[0]) 
+      if(nsName[0])
          f.Printf($"Parent namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", nameSpace->parent, nsName);
 
       f.Printf("<br>");
@@ -635,7 +658,7 @@ class APIPageNameSpace : APIPage
             if(first)
             {
                f.Printf($"<H3>Sub Namespaces</H3><br><br>\n");
-               f.Printf("<TABLE >\n");
+               f.Printf("<TABLE>\n");
                first = false;
             }
             f.Printf("<TR>");
@@ -673,7 +696,7 @@ class APIPageNameSpace : APIPage
                if(first)
                {
                   f.Printf($"<a name=Classes></a><H3>Classes</H3><br><br>\n");
-                  f.Printf("<TABLE >\n");
+                  f.Printf("<TABLE>\n");
                   first = false;
                }
 
@@ -713,7 +736,7 @@ class APIPageNameSpace : APIPage
             if(first)
             {
                f.Printf($"<a name=Functions></a><H3>Functions</H3><br><br>\n");
-               f.Printf("<TABLE >\n");
+               f.Printf("<TABLE>\n");
                first = false;
             }
             f.Printf("<TR>");
@@ -748,7 +771,7 @@ class APIPageNameSpace : APIPage
             if(first)
             {
                f.Printf($"<a name=Definitions></a><H3>Definitions</H3><br><br>\n");
-               f.Printf("<TABLE >\n");
+               f.Printf("<TABLE>\n");
                first = false;
             }
             f.Printf("<TR>");
@@ -782,6 +805,16 @@ class APIPageClass : APIPage
 {
    Class cl;
 
+   Module GetModule()
+   {
+      return cl.module;
+   }
+
+   NameSpace * GetNameSpace()
+   {
+      return cl.nameSpace;
+   }
+
    void Generate(File f)
    {
       char string[1024];
@@ -806,7 +839,7 @@ class APIPageClass : APIPage
       f.Printf("<FONT FACE=\"Arial\" SIZE=\"6\">%s</FONT><br><br>\n", name);
 
       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);
-      if(nsName[0]) 
+      if(nsName[0])
          f.Printf($"Namespace: <a href=\"api://%p\" style=\"text-decoration: none;\">%s</a><br>\n", cl.nameSpace, nsName);
 
       {
@@ -837,7 +870,7 @@ class APIPageClass : APIPage
          }
          f.Printf($"Type: %s<br>\n", classType);
       }
-      
+
       if(cl.type != systemClass && cl.base)
       {
          f.Printf($"Base Class: ");
@@ -877,9 +910,9 @@ class APIPageClass : APIPage
          if(enumeration.values.first)
          {
             NamedLink item;
-                        
+
             f.Printf($"<a name=EnumerationValues></a><H3>Enumeration Values</H3><br><br>\n");
-            f.Printf("<TABLE >\n");
+            f.Printf("<TABLE>\n");
 
             for(item = enumeration.values.first; item; item = item.next)
             {
@@ -911,7 +944,7 @@ class APIPageClass : APIPage
                }
                else
                   dataClass = base;
-               
+
                f.Printf("<TR>");
                f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\">&nbsp;&nbsp;%s</TD>", item, iconNames[typeEnumValue], item.name);
                if(dataClass.type == systemClass)
@@ -948,7 +981,7 @@ class APIPageClass : APIPage
       if(cl.conversions.first)
       {
          f.Printf($"<a name=Conversions></a><H3>Conversions</H3><br><br>\n");
-         f.Printf("<TABLE >\n");
+         f.Printf("<TABLE>\n");
          for(prop = cl.conversions.first; prop; prop = prop.next)
          {
             if((prop.memberAccess == publicAccess || (prop.memberAccess == privateAccess && showPrivate)) && prop.name)
@@ -961,10 +994,10 @@ class APIPageClass : APIPage
                if(name) name += 2; else name = prop.name;
 
                f.Printf("<TR>");
-               
+
                string[0] = 0;
                DocPrintType(type, string, true, false);
-               
+
                f.Printf("<TD valign=top height=22 nowrap=1><a name=%p></a><img valign=center src=\"%s\">&nbsp;&nbsp;%s</TD>", prop, iconNames[typeDataType], string);
                if(desc)
                {
@@ -980,9 +1013,9 @@ class APIPageClass : APIPage
                      f.Printf("<TD valign=top height=22>%s</TD>", desc);
                   delete desc;
                }
-               
+
                f.Printf("</TR>\n");
-               
+
                FreeType(type);
             }
          }
@@ -999,7 +1032,7 @@ class APIPageClass : APIPage
                if(first)
                {
                   f.Printf($"<a name=Members></a><H3>Properties and Members</H3><br><br>\n");
-                  f.Printf("<TABLE >\n");
+                  f.Printf("<TABLE>\n");
                   first = false;
                }
 
@@ -1053,7 +1086,7 @@ class APIPageClass : APIPage
                if(first)
                {
                   f.Printf($"<a name=VirtualMethods></a><H3>Virtual Methods</H3><br><br>\n");
-                  f.Printf("<TABLE >\n");
+                  f.Printf("<TABLE>\n");
                   first = false;
                }
                if(!method.dataType)
@@ -1091,7 +1124,7 @@ class APIPageClass : APIPage
                if(first)
                {
                   f.Printf($"<a name=Methods></a><H3>Non-Virtual Methods</H3><br><br>\n");
-                  f.Printf("<TABLE >\n");
+                  f.Printf("<TABLE>\n");
                   first = false;
                }
 
@@ -1114,7 +1147,7 @@ class APIPageClass : APIPage
                      f.Printf("<TD valign=top height=22>%s</TD>", desc);
                   delete desc;
                }
-               
+
                f.Printf("</TR><br>\n");
             }
          }
@@ -1146,7 +1179,7 @@ class APIPageClass : APIPage
          {
             f.Printf($"<H3>Example</H3><br>\n");
             f.Printf($"<FONT face=\"Courier New\">\n");
-            f.Printf("<br><TABLE >\n");
+            f.Printf("<br><TABLE>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1183,7 +1216,7 @@ class APIPageClass : APIPage
             delete remarksDoc;
          }
       }
-      
+
       if(cl.type != systemClass)
       {
          bool first = true;
@@ -1234,6 +1267,17 @@ class APIPageClass : APIPage
 class APIPageMethod : APIPage
 {
    Method method;
+
+   Module GetModule()
+   {
+      return method._class.module;
+   }
+
+   NameSpace * GetNameSpace()
+   {
+      return method._class.nameSpace;
+   }
+
    void Generate(File f)
    {
       Class cl = method._class;
@@ -1326,13 +1370,13 @@ class APIPageMethod : APIPage
                   FigureFileName(fileName, module, methodDoc, method, parameter, param);
                   f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
                   f.Puts(desc);
-                  f.Printf("s</a>&nbsp;</TD>\n");
+                  f.Printf("</a></TD>\n");
                }
                else
                   f.Printf("<TD valign=top height=22>%s&nbsp;</TD>\n", desc);
                delete desc;
             }
-            
+
             f.Printf("</TR>\n");
          }
       }
@@ -1395,7 +1439,7 @@ class APIPageMethod : APIPage
          {
             f.Printf($"<H3>Example</H3><br>\n");
             f.Printf($"<FONT face=\"Courier New\">\n");
-            f.Printf("<br><TABLE >\n");
+            f.Printf("<br><TABLE>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1445,7 +1489,7 @@ class APIPageMethod : APIPage
             }
             else
                f.Printf("<br>%s\n", method, seeAlsoDoc);
-            
+
             f.Printf("<br><br>\n");
             delete seeAlsoDoc;
          }
@@ -1457,6 +1501,17 @@ class APIPageMethod : APIPage
 class APIPageFunction : APIPage
 {
    GlobalFunction function;
+
+   Module GetModule()
+   {
+      return function.module;
+   }
+
+   NameSpace * GetNameSpace()
+   {
+      return function.nameSpace;
+   }
+
    void Generate(File f)
    {
       char string[1024];
@@ -1546,7 +1601,8 @@ class APIPageFunction : APIPage
                   char fileName[MAX_LOCATION];
                   FigureFileName(fileName, module, functionDoc, function, parameter, param);
                   f.Printf("<TD valign=top height=22><a style=\"text-decoration:none;\" href=\"edit://%s\">", fileName);
-                  f.Puts(desc);
+                  if(desc)
+                     f.Puts(desc);
                   f.Printf("</a>&nbsp;</TD>\n");
                }
                else
@@ -1615,7 +1671,7 @@ class APIPageFunction : APIPage
          {
             f.Printf($"<H3>Example</H3><br>\n");
             f.Printf($"<FONT face=\"Courier New\">\n");
-            f.Printf("<br><TABLE >\n");
+            f.Printf("<br><TABLE>\n");
             if(editing)
             {
                char fileName[MAX_LOCATION];
@@ -1684,7 +1740,7 @@ static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpa
    APIPage page;
 
    char fileName[MAX_LOCATION];
-   
+
    strcpy(nsName, parentName ? parentName : "");
    if(nameSpace->name)
    {
@@ -1751,7 +1807,7 @@ static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpa
    {
       for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
       {
-         if(nameSpace->functions.first)                            
+         if(nameSpace->functions.first)
          {
             BTNamedLink link;
             GlobalFunction fn;
@@ -1769,7 +1825,7 @@ static void AddNameSpace(DataRow parentRow, Module module, NameSpace mainNameSpa
          }
       }
    }
-   
+
    if(mainNameSpace.defines.first || (comNameSpace && comNameSpace.defines.first))
    {
       for(nameSpace = mainNameSpace ; nameSpace; nameSpace = (nameSpace == mainNameSpace) ? comNameSpace : null)
@@ -1830,7 +1886,7 @@ static void AddDataMemberToPage(File f, DataMember member, int indent, bool show
    }
    else
       f.Printf("<TD valign=top height=22></TD>");
-   
+
    if(member.type != normalMember)
    {
       DataMember subMember;
@@ -2028,7 +2084,13 @@ class MainForm : Window
 
       bool NotifySelect(MenuItem selection, Modifiers mods)
       {
-         SettingsDialog { master = this }.Modal(); // Open the settings dialog to allow the user to change the directory for the eCdoc files
+         if(SettingsDialog { master = this }.Modal() == ok) // Open the settings dialog to allow the user to change the directory for the eCdoc files
+         {
+            // Refresh docs
+            view.edit = false;
+            view.Destroy(0);
+            view.Create();
+         }
          return true;
       }
    };
@@ -2045,7 +2107,7 @@ class MainForm : Window
       FreeExcludedSymbols(excludedSymbols);
       ::defines.Free(FreeModuleDefine);
       imports.Free(FreeModuleImport);
-      
+
       FreeGlobalData(globalData);
       FreeTypeData(componentsApp);
       FreeIncludeFiles();
@@ -2066,7 +2128,7 @@ class MainForm : Window
 
       if(extension[0] && strcmpi(extension, "so") && strcmpi(extension, "dll"))
          componentsApp.name = CopyString(filePath);
-      
+
       for(module = componentsApp.allModules.first; module; module = module.next)
       {
          if(module.name && (!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM")))
@@ -2111,7 +2173,7 @@ class MainForm : Window
          }
          else if(!view.created)
             view.Create();
-         
+
          {
             page = row.GetData(null);
             if(page && page.page)
@@ -2211,9 +2273,41 @@ class HelpView : HTMLView
    bool OnCreate()
    {
       TempFile f { };
+
       page = mainForm.browser.currentRow.GetData(null);
       if(page)
       {
+         // Writability test
+         {
+            char docFile[MAX_LOCATION];
+            Archive archive;
+            Module module = page ? page.GetModule() : null;
+            NameSpace * ns = page ? page.GetNameSpace() : null;
+
+            sprintf(docFile, "%s/%s.eCdoc", settings.docDir, (!module || !module.name || (ns && ns->name && !strcmp(ns->name, "namespaces/ecere/namespaces/com"))) ? "ecereCOM" : module.name);
+
+            if(FileExists(docFile))
+            {
+               archive = ArchiveOpen(docFile, { true } );
+               readOnly = archive == null;
+               delete archive;
+            }
+            else
+            {
+               readOnly = true;
+               archive = ArchiveOpen(docFile, { true } );
+               if(archive)
+               {
+                  // Must create root directory on archive creation
+                  ArchiveDir dir = archive.OpenDirectory("", null, replace);
+                  if(dir)
+                     readOnly = false;
+                  delete dir;
+               }
+               delete archive;
+            }
+         }
+
          page.Generate(f);
          f.Seek(0, start);
          OpenFile(f, null);
@@ -2235,12 +2329,13 @@ class HelpView : HTMLView
       char fileName[MAX_FILENAME];
       char directory[MAX_LOCATION];
       char * location;
-      Archive archive;
-      SplitArchivePath(editString, archiveFile, &location);
-      GetLastDirectory(location, fileName);
-      StripLastDirectory(location, directory);
-      archive = ArchiveOpen(archiveFile, { true } );
-      // if(archive)
+      Archive archive = null;
+      if(SplitArchivePath(editString, archiveFile, &location))
+      {
+         GetLastDirectory(location, fileName);
+         StripLastDirectory(location, directory);
+         archive = ArchiveOpen(archiveFile, { true } );
+      }
       {
          TempFile f { };
          ArchiveDir dir = archive ? archive.OpenDirectory(directory, null, replace) : null;
@@ -2301,7 +2396,8 @@ class HelpView : HTMLView
 
       if(edit && (!textBlock || overLink != textBlock.parent))
       {
-         SaveEdit();
+         if(!readOnly)
+            SaveEdit();
          HTMLView::OnLeftButtonDown(x, y, mods);
          selPosition = curPosition = 0;
          selBlock = textBlock;
@@ -2713,7 +2809,7 @@ class HelpView : HTMLView
                            len = (nextSpace - (text + textPos)) + 1;
                         else
                            len = textBlock.textLen - textPos;
-                        
+
                         display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
 
                         if(x + width + w > maxW && x > 0)
@@ -2823,7 +2919,7 @@ class HelpView : HTMLView
                         len = (nextSpace - (text + textPos)) + 1;
                      else
                         len = textBlock.textLen - textPos;
-                     
+
                      display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
 
                      if(x + width + w > maxW && x > 0)
@@ -2870,7 +2966,7 @@ class HelpView : HTMLView
                      Update(null);
                      PositionCaret(false);
                      return false;
-                  } 
+                  }
                   else if(textPos == textBlock.textLen && textBlock.next && textBlock.next.next)
                   {
                      startPos = 0;
@@ -2886,7 +2982,7 @@ class HelpView : HTMLView
                      sx = textBlock.startX;
                   }
                }
-               
+
                /*if(textBlock.next && textBlock.next.next)
                {
                   textBlock = textBlock.next.next;
@@ -2936,7 +3032,7 @@ class HelpView : HTMLView
                         break;
                      }
                   }
-                  // No next word found, 
+                  // No next word found,
                   if(!found && (c != curPosition || line != textBlock))
                   {
                      found = true;
@@ -3006,7 +3102,7 @@ class HelpView : HTMLView
                         }
                      }
                   }
-                  // No next word found, 
+                  // No next word found,
                   if(!found && curPosition > 0)
                   {
                      foundAlpha = true;
@@ -3082,6 +3178,7 @@ class HelpView : HTMLView
                }
                break;
             case backSpace:
+               if(readOnly) break;
                if(textBlock == selBlock && curPosition == selPosition)
                {
                   if(curPosition)
@@ -3136,6 +3233,7 @@ class HelpView : HTMLView
                   DeleteSelection();
                break;
             case del:
+               if(readOnly) break;
                if(textBlock != selBlock || curPosition != selPosition)
                   DeleteSelection();
                else if(textBlock.textLen > curPosition)
@@ -3186,6 +3284,7 @@ class HelpView : HTMLView
                Block newBlock;
                int startY, startX;
 
+               if(readOnly) break;
                DeleteSelection();
 
                block = { type = BR, parent = textBlock.parent, font = textBlock.font };
@@ -3220,6 +3319,7 @@ class HelpView : HTMLView
             }
             case ctrlX:
             case Key { del, shift = true }:
+               if(readOnly) break;
                // Cut
                CopySelection();
                DeleteSelection();
@@ -3231,76 +3331,77 @@ class HelpView : HTMLView
                break;
             case shiftInsert:
             case ctrlV:
-            {
-               ClipBoard clipBoard { };
-               if(clipBoard.Load())
-               {  
-                  int c;
-                  char * text = clipBoard.memory;
-                  char ch;
-                  int start = 0;
-                  Block parent;
-                  FontEntry font;
+               if(!readOnly)
+               {
+                  ClipBoard clipBoard { };
+                  if(clipBoard.Load())
+                  {
+                     int c;
+                     char * text = clipBoard.memory;
+                     char ch;
+                     int start = 0;
+                     Block parent;
+                     FontEntry font;
 
-                  DeleteSelection();
+                     DeleteSelection();
 
-                  parent = textBlock.parent;
-                  font = textBlock.font;
+                     parent = textBlock.parent;
+                     font = textBlock.font;
 
-                  for(c = 0; ; c++)
-                  {
-                     ch = text[c];
-                     if(ch == '\n' || ch == '\r' || !ch)
+                     for(c = 0; ; c++)
                      {
-                        int len = c - start;
-                        textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
-                        memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
-                        memcpy(textBlock.text + curPosition, text + start, len);
-                        textBlock.textLen += len;
-                        curPosition += len;
-                        selPosition = curPosition;
-                        selBlock = textBlock;
-                        if(!ch) break;
+                        ch = text[c];
+                        if(ch == '\n' || ch == '\r' || !ch)
                         {
-                           Block block { type = BR, parent = parent, font = font };
-                           Block newBlock { type = TEXT, parent = parent, font = font };
-                           int startY = textBlock.startY, startX = textBlock.startX;
-                           int tw = 0, th = 0;
-
-                           display.FontExtent(textBlock.font.font, " ", 1, null, &th);
-                           textBlock.parent.subBlocks.Insert(textBlock, block);
-                           textBlock.parent.subBlocks.Insert(block, newBlock);
-
-                           startY += th;
-
-                           newBlock.textLen = textBlock.textLen - curPosition;
-                           newBlock.text = new char[newBlock.textLen+1];
-                           memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
-                           textBlock.textLen = curPosition;
-                           textBlock.text[curPosition] = 0;
-
-                           newBlock.startY = startY;
-                           newBlock.startX = startX;
-                           selPosition = curPosition = 0;
+                           int len = c - start;
+                           textBlock.text = renew textBlock.text char[textBlock.textLen + 1 + len];
+                           memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
+                           memcpy(textBlock.text + curPosition, text + start, len);
+                           textBlock.textLen += len;
+                           curPosition += len;
+                           selPosition = curPosition;
                            selBlock = textBlock;
-                           textBlock = newBlock;
+                           if(!ch) break;
+                           {
+                              Block block { type = BR, parent = parent, font = font };
+                              Block newBlock { type = TEXT, parent = parent, font = font };
+                              int startY = textBlock.startY, startX = textBlock.startX;
+                              int tw = 0, th = 0;
+
+                              display.FontExtent(textBlock.font.font, " ", 1, null, &th);
+                              textBlock.parent.subBlocks.Insert(textBlock, block);
+                              textBlock.parent.subBlocks.Insert(block, newBlock);
+
+                              startY += th;
+
+                              newBlock.textLen = textBlock.textLen - curPosition;
+                              newBlock.text = new char[newBlock.textLen+1];
+                              memcpy(newBlock.text, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
+                              textBlock.textLen = curPosition;
+                              textBlock.text[curPosition] = 0;
+
+                              newBlock.startY = startY;
+                              newBlock.startX = startX;
+                              selPosition = curPosition = 0;
+                              selBlock = textBlock;
+                              textBlock = newBlock;
+                           }
+                           if(ch == '\r' && text[c+1] == '\n') c++;
+                           start = c + 1;
                         }
-                        if(ch == '\r' && text[c+1] == '\n') c++;
-                        start = c + 1;
                      }
+                     ComputeMinSizes();
+                     ComputeSizes();
+                     PositionCaret(true);
+                     Update(null);
                   }
-                  ComputeMinSizes();
-                  ComputeSizes();
-                  PositionCaret(true);
-                  Update(null);
+                  delete clipBoard;
                }
-               delete clipBoard;
                break;
-            }
             default:
             {
                // eC BUG HERE: (Should be fixed)
-               if(!key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
+               if(!readOnly && !key.ctrl && !key.alt && ch >= 32 && ch != 128 /*&& ch < 128*/)
                {
                   char string[5];
                   int len = UTF32toUTF8Len(&ch, 1, string, 5);
@@ -3310,7 +3411,7 @@ class HelpView : HTMLView
 
                   textBlock.text = renew textBlock.text char[textBlock.textLen + len + 1];
                   memmove(textBlock.text + curPosition + len, textBlock.text + curPosition, textBlock.textLen - curPosition + 1);
-                  
+
                   for(c = 0; c<len; c++)
                   {
                      textBlock.text[curPosition] = string[c];
@@ -3319,7 +3420,7 @@ class HelpView : HTMLView
                   }
                   selPosition = curPosition;
                   selBlock = textBlock;
-                  
+
                   {
                      //Clear(html.block);
                      //CreateForms(html.block);
@@ -3365,7 +3466,7 @@ class HelpView : HTMLView
          }
          else
             maxW = clientSize.w - 10 - sx;
-         
+
          display.FontExtent(textBlock.font.font, " ", 1, null, &th);
 
          while(textPos < textBlock.textLen)
@@ -3385,7 +3486,7 @@ class HelpView : HTMLView
                   len = (nextSpace - (text + textPos)) + 1;
                else
                   len = textBlock.textLen - textPos;
-               
+
                display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
 
                if(x + width + w > maxW && x > 0)
@@ -3483,7 +3584,7 @@ class HelpView : HTMLView
          }
          else
             maxW = clientSize.w - 10 - sx;
-         
+
          display.FontExtent(textBlock.font.font, " ", 1, &space, &th);
          //space = space/2+2;
          space = 2;
@@ -3505,7 +3606,7 @@ class HelpView : HTMLView
                   len = (nextSpace - (text + textPos)) + 1;
                else
                   len = textBlock.textLen - textPos;
-               
+
                display.FontExtent(textBlock.font.font, text + textPos, len, &w, &th);
 
                sx = x + textBlock.startX;
@@ -3567,7 +3668,7 @@ class Documentor : GuiApplication
       SetExcludedSymbols(&excludedSymbols);
       SetDefines(&::defines);
       SetImports(&imports);
-      
+
       SetGlobalData(globalData);
 
       settingsContainer.dataOwner = &settings;
@@ -3577,7 +3678,7 @@ class Documentor : GuiApplication
          if(os == win32) // if Windows OS then
          {
             char programFilesDir[MAX_LOCATION];
-            char appData[MAX_LOCATION]; 
+            char appData[MAX_LOCATION];
             char homeDrive[MAX_LOCATION];
             char winDir[MAX_LOCATION];
             GetEnvironment("APPDATA", appData, sizeof(appData));
@@ -3618,11 +3719,32 @@ class Documentor : GuiApplication
             row.collapsed = false;
       #endif
       }
+
+      commandThread.Create();
+      return true;
+   }
+
+   bool Cycle(bool idle)
+   {
+      if(quit)
+         mainForm.Destroy(0);
       return true;
    }
 
    void Terminate()
    {
+      PrintLn("Exited");
+      console.Flush();
+      quit = true;
+      if(commandThread.created)
+      {
+         console.CloseInput();
+         console.CloseOutput();
+         app.Unlock();
+         commandThread.Wait();
+         app.Lock();
+      }
+
       FreeContext(globalContext);
       FreeExcludedSymbols(excludedSymbols);
       ::defines.Free(FreeModuleDefine);
@@ -3635,4 +3757,28 @@ class Documentor : GuiApplication
    }
 }
 
+ConsoleFile console { };
 MainForm mainForm { };
+bool quit;
+
+Thread commandThread
+{
+   unsigned int Main()
+   {
+      while(!quit)
+      {
+         char command[1024];
+         console.GetLine(command, sizeof(command));
+         if(!quit && command[0])
+         {
+            app.Lock();
+            if(!strcmpi(command, "Activate"))
+               mainForm.Activate();
+            else if(!strcmpi(command, "Quit"))
+               quit = true;
+            app.Unlock();
+         }
+      }
+      return 0;
+   }
+};