ecere/gui/controls/EditBox: Fixed uninitialized 'prevGlyph' read
[sdk] / ecere / src / gui / controls / EditBox.ec
index af8aa7c..a811a1b 100644 (file)
@@ -17,7 +17,7 @@ char * strchrmax(const char * s, int c, int max)
    char ch;
    for(i = 0; i < max && (ch = s[i]); i++)
       if(ch == c)
-         return s + i;
+         return (char *)s + i;
    return null;
 }
 
@@ -304,15 +304,18 @@ static class AddCharAction : UndoAction
 {
    int y, x;
    unichar ch;
-   int addedSpaces, addedTabs;
+   int addedSpaces, addedTabs, xAdjustment;
    type = class(AddCharAction);
 
    void Undo(EditBox editBox)
    {
-      editBox.GoToPosition(null, (ch == '\n') ? (y + 1) : y, (ch == '\n') ? 0 : (x + 1));
+      editBox.GoToPosition(null, (ch == '\n') ? (y + 1) : y, (ch == '\n') ? 0 : (x + 1) - xAdjustment);
       editBox.BackSpace();
       if(addedTabs || addedSpaces)
-         editBox.DelCh(editBox.line, y, x - (addedSpaces + addedTabs), editBox.line, y, x, false);
+      {
+         editBox.DelCh(editBox.line, y, x - xAdjustment - (addedSpaces + addedTabs), editBox.line, y, x - xAdjustment, false);
+         editBox.GoToPosition(editBox.line, y, x);
+      }
       editBox.UpdateDirty();
    }
 
@@ -334,7 +337,7 @@ static class AddTextAction : UndoAction
 {
    int y1, x1, y2, x2;
    char * string;
-   int addedSpaces, addedTabs;
+   int addedSpaces, addedTabs, xAdjustment;
    type = class(AddTextAction);
 
 #ifdef _DEBUG
@@ -449,7 +452,7 @@ static class ReplaceTextAction : UndoAction
    char * oldString;
    char * newString;
    bool placeAfter;
-   int addedSpaces, addedTabs;
+   int addedSpaces, addedTabs, xAdjustment;
 
    type = class(ReplaceTextAction);
 
@@ -538,7 +541,7 @@ public class EditLine : struct
    int length;
    EditBox editBox;
 public:
-   property char * text
+   property const char * text
    {
       set
       {
@@ -668,7 +671,7 @@ public struct BufferLocation
 
 public enum EditBoxFindResult { notFound, found, wrapped };
 
-static char * keyWords1[] =
+static const char * keyWords1[] =
 {
    // C
    "return","break","continue","default","switch","case","if","else","for","while", "do","long","short",
@@ -706,12 +709,14 @@ static char * keyWords1[] =
    null
 };
 
-static char * keyWords2[] =
+static const char * keyWords2[] =
 {
-   "defined", "warning", null
+   "defined", "warning",
+   "include", "pragma", "elif", "ifdef", "ifndef", "endif", "undef", "line",
+   null
 };
 
-static char ** keyWords[] = { keyWords1, keyWords2 };
+static const char ** keyWords[] = { keyWords1, keyWords2 };
 #define NUM_KEYWORD_GROUPS (sizeof(keyWords) / sizeof(char **))
 //static int * keyLen[NUM_KEYWORD_GROUPS];
 static int keyLen[NUM_KEYWORD_GROUPS][sizeof(keyWords1)];
@@ -804,7 +809,7 @@ public:
    property EditLine firstLine { get { return lines.first; } };      // Change these to a List<EditLine>... (this.lines[10].text)
    property EditLine lastLine  { get { return lines.last; } };
    property EditLine line { get { return this.line; } }; // TODO: Add Set   this.line = this.lines[10]
-   property char * contents
+   property const char * contents
    {
       property_category $"Data"
       set
@@ -896,7 +901,7 @@ public:
       return null;
    }
 
-   void SetLineText(char * text)
+   void SetLineText(const char * text)
    {
       if(this)
       {
@@ -973,7 +978,7 @@ private:
 
    bool modified;
 
-   void (* FontExtent)(Display display, Font font, char * text, int len, int * width, int * height);
+   void (* FontExtent)(Display display, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * overHang);
 
    Color backColor;
    bool rightButtonDown;
@@ -1140,7 +1145,7 @@ private:
             void NotifyDestroyed(Window window, DialogResult result)
             {
                ReplaceDialog dialog = (ReplaceDialog)window;
-               char * replace = dialog.replaceString;
+               const char * replace = dialog.replaceString;
                if(replace)
                   strcpy(replaceString, replace);
                strcpy(searchString, dialog.searchString);
@@ -1206,7 +1211,7 @@ private:
          colorScheme.keywordColors = [ blue, blue ];
       }
 
-      FontExtent = Display::FontExtent;
+      FontExtent = Display::FontExtent2;
       font = fontObject;
       lines.offset = (uint)(uintptr)&((EditLine)0).prev;
 
@@ -1262,7 +1267,7 @@ private:
       lines.Free(EditLine::Free);
    }
 
-   void FlushBuffer(Surface surface, EditLine line, int wc, int * renderStart, int * x, int y, int numSpaces, bool drawSpaces, Box box)
+   void FlushBuffer(Surface surface, EditLine line, int wc, int * renderStart, int * x, int y, int * previousGlyph, int * oh, int numSpaces, bool drawSpaces, Box box)
    {
       int count = wc - *renderStart;
       if(count)
@@ -1273,18 +1278,24 @@ private:
 
             if(!numSpaces)
             {
+               int coh;
                //FontExtent(display, font, line.buffer + *renderStart, count, &w, null);
                surface.TextFont(font);
-               surface.TextExtent(line.buffer + *renderStart, count, &w, null);
-               if(*x + w + XOFFSET > 0)
-                  surface.WriteText(XOFFSET + *x,y, line.buffer + *renderStart, count);
+               surface.TextExtent2(line.buffer + *renderStart, count, &w, null, *previousGlyph, null, &coh);
+
+               if(*x + w + coh + XOFFSET > 0)
+               {
+                  surface.WriteText2(XOFFSET + *x,y, line.buffer + *renderStart, count, *previousGlyph, previousGlyph);
+                  *oh = coh;
+                  //surface.WriteText(XOFFSET + *x,y, line.buffer + *renderStart, count);
+               }
                *x += w;
             }
             else
             {
                w = numSpaces; // * space.w;
-               if(*x + w + XOFFSET > 0 && (drawSpaces || surface.GetTextOpacity()))
-                  surface.Area(XOFFSET + *x - 1, y, XOFFSET + *x + w, y + space.h-1);
+               if(*x + w + XOFFSET > 0 && (drawSpaces))
+                  surface.Area(XOFFSET + *x /*- 1*/ + *oh, y, XOFFSET + *x + w, y + space.h-1);
                   // WHATS UP WITH THIS...  surface.Area(XOFFSET + *x, y, XOFFSET + *x + w, y + space.h-1);
                *x += w;
             }
@@ -1473,6 +1484,25 @@ private:
       }
    }*/
 
+   static inline int countTabsExtraSpaces(char * buffer, int tabSize, int start, int end)
+   {
+      // TODO: Handle tabs position properly with UTF-8 (and everywhere else)
+      int p = 0, i, extra = 0;
+      for(i = 0; i < end; i++)
+      {
+         if(buffer[i] == '\t')
+         {
+            int t = tabSize - (p % tabSize);
+            p += t;
+            if(i >= start)
+               extra += t-1;
+         }
+         else
+            p++;
+      }
+      return extra;
+   }
+
    void OnRedraw(Surface surface)
    {
       EditLine line;
@@ -1491,7 +1521,7 @@ private:
 
       // Overwrite Caret Stuff
       int overWrite = 0;
-      int overWriteX, overWriteY;
+      int overWriteX = 0, overWriteY = 0;
       char overWriteCh;
 
       // ****** SYNTAX STATES ******
@@ -1507,6 +1537,13 @@ private:
       bool wasInMultiLine = style.wasInMultiLine;
       // ****** ************* ******
 
+      // For drawing selection background
+      EditLine selStartLine = this.y < this.selY ? this.line : this.selLine;
+      EditLine selEndLine   = this.y < this.selY ? this.selLine : this.line;
+      int selStartX = this.y < this.selY || (this.y == this.selY && this.x < this.selX) ? this.x : this.selX;
+      int selEndX   = this.y > this.selY || (this.y == this.selY && this.x > this.selX) ? this.x : this.selX;
+      ///////////////////////////////////
+
       if(!isEnabled)
          defaultTextColor = Color { 85, 85, 85 };
       textColor = defaultTextColor;
@@ -1557,7 +1594,7 @@ private:
    */
       surface.SetForeground(foreground);
       surface.SetBackground(background);
-      surface.TextOpacity(opacity);
+      surface.TextOpacity(false);
 
       surface.GetBox(box);
 
@@ -1569,7 +1606,7 @@ private:
          int start = 0;
          Color newTextColor = textColor = defaultTextColor;
          bool lineComplete = false;
-
+         int overHang = 0;
 
          // ****** SYNTAX HIGHLIGHTING ******
          bool lastWasStar = false;
@@ -1596,6 +1633,64 @@ private:
          }
    */
 
+         // Draw Selection Background all at once here
+         if(selected || line == this.line || line == this.selLine)
+         {
+            int sx = XOFFSET + x, sy = y;
+            int tw, th;
+            int oh = 0;
+            char * buffer = line.buffer;
+            if(line != this.line && line != this.selLine)
+            {
+               if(style.freeCaret)
+               {
+                  tw = clientSize.w - sx;
+                  th = space.h;
+               }
+               else
+               {
+                  surface.TextExtent2(buffer, line.count, &tw, &th, 0, null, &oh);
+                  tw += countTabsExtraSpaces(buffer, tabSize, 0, line.count) * space.w;
+               }
+            }
+            else if(line == selStartLine)
+            {
+               int prevGlyph = 0;
+               int start = Min(line.count, selStartX);
+               int end   = Min(line.count, selEndX);
+               surface.TextExtent2(buffer, start, &tw, &th, 0, &prevGlyph, null);
+               sx += tw;
+               sx += countTabsExtraSpaces(buffer, tabSize, 0, start) * space.w;
+               if(selStartX > start) sx += space.w * (selStartX - start);
+               if(style.freeCaret && line != selEndLine)
+               {
+                  tw = clientSize.w - sx;
+                  th = space.h;
+               }
+               else if(line != selEndLine)
+               {
+                  surface.TextExtent2(buffer + start, line.count - start, &tw, &th, prevGlyph, null, &oh);
+                  tw += countTabsExtraSpaces(buffer, tabSize, start, line.count) * space.w;
+               }
+               else
+               {
+                  surface.TextExtent2(buffer + start, end - start, &tw, &th, prevGlyph, null, &oh);
+                  tw += countTabsExtraSpaces(buffer, tabSize, start, end) * space.w;
+                  end = Max(end, selStartX);
+                  if(selEndX > end) { tw += space.w * (selEndX - end); th = space.h; }
+               }
+            }
+            else if(line == selEndLine)
+            {
+               int end = Min(line.count, selEndX);
+               surface.TextExtent2(buffer, end, &tw, &th, 0, null, &oh);
+               tw += countTabsExtraSpaces(buffer, tabSize, 0, end) * space.w;
+               if(selEndX - end) { tw += space.w * (selEndX - end); th = space.h; }
+            }
+            tw += oh;
+            surface.Area(sx, sy, sx + tw-1, sy + th-1);
+         }
+
          if(line == this.selLine && line == this.line)
          {
             end = Max(line.count, this.x);
@@ -1787,7 +1882,7 @@ private:
                         }
                         else if(x < box.right && !inQuotes && !inString && !inMultiLineComment && !inSingleLineComment && (isdigit(word[0]) || (word[0] == '.' && isdigit(word[1]))))
                         {
-                           char * dot = word[wordLen] == '.' ? word + wordLen : null;
+                           char * dot = word[wordLen] == '.' ? word + wordLen : (word[0] == '.' && (word == line.buffer || word[-1] == '-' || isspace(word[-1])) ? word : null);
                            bool isReal = dot != null;
                            char * s = null;
                            if(dot)
@@ -1827,7 +1922,7 @@ private:
                                     case 'f': case 'F': gotF++; if(gotF > 1 || !isReal) valid = false; break;
                                     case 'l': case 'L':
                                        gotL++;
-                                       if(gotL > 2 || isReal || (gotL == 2 && (s[i-1] != ch)))
+                                       if(gotL > 2 || (isReal && (gotL == 2 || gotF)) || (gotL == 2 && (s[i-1] != ch)))
                                        valid = false;
                                        break;
                                     case 'u': case 'U': gotU++; if(gotU > 1 || isReal) valid = false; break;
@@ -1869,14 +1964,14 @@ private:
                               if(firstWord)
                               {
                                  inPrep = true;
-                                 newTextColor = colorScheme.preprocessorColor;
+                                 newTextColor = wordLen == 1 ? colorScheme.keywordColors[1] : colorScheme.preprocessorColor;
                               }
                            }
                            if(x < box.right && !inQuotes && !inString && !inMultiLineComment && !inSingleLineComment)
                            {
                               for(g = 0; g < ((inPrep && word[0] != '#') ? 2 : 1); g++)
                               {
-                                 char ** keys = keyWords[g];
+                                 const char ** keys = keyWords[g];
                                  int * len = keyLen[g];
                                  for(ccc = 0; keys[ccc]; ccc++)
                                  {
@@ -1932,7 +2027,8 @@ private:
                      //if(!numSpaces)
                      {
                         int tw;
-                        FontExtent(display, font, line.buffer + start, bufferLen + wordLen, &tw, null);
+                        int oh;
+                        FontExtent(display, font, line.buffer + start, bufferLen + wordLen, &tw, null, 0, null, &oh);
                         w = tw;
                      }
                      /*else
@@ -1961,6 +2057,7 @@ private:
                bool flagTrailingSpace = false;
                int numSpaces = 0;
                int wc;
+               int previousGlyph = 0;
 
                // Render checking if we need to split because of selection or to find where to draw insert caret
                for(wc = start; wc < start + bufferLen; wc++)
@@ -1977,7 +2074,8 @@ private:
                   {
                      flagTrailingSpace = numSpaces && trailingSpace && style.syntax && start + bufferLen == line.count && line != this.line;
                      if(flagTrailingSpace) surface.SetBackground(red);
-                     FlushBuffer(surface, line, wc, &renderStart, &x, y, numSpaces, flagTrailingSpace, box);
+                     FlushBuffer(surface, line, wc, &renderStart, &x, y, &previousGlyph, &overHang, numSpaces, flagTrailingSpace, box);
+                     if(flagTrailingSpace) surface.SetBackground(background);
                      if(overWrite == 1)
                      {
                         overWriteX = x;
@@ -1986,8 +2084,6 @@ private:
                      }
                      numSpaces = 0;
 
-                     surface.TextOpacity(opacity);
-                     surface.SetBackground(background);
                      surface.SetForeground(foreground);
 
                      flush = false;
@@ -2007,7 +2103,8 @@ private:
                }
                flagTrailingSpace = numSpaces && trailingSpace && style.syntax && start + bufferLen == line.count && line != this.line;
                if(flagTrailingSpace) surface.SetBackground(red);
-               FlushBuffer(surface, line, wc, &renderStart, &x, y, numSpaces, flagTrailingSpace, box);
+               FlushBuffer(surface, line, wc, &renderStart, &x, y, &previousGlyph, &overHang, numSpaces, flagTrailingSpace, box);
+               if(flagTrailingSpace) surface.SetBackground(background);
                start += bufferLen;
             }
          }
@@ -2022,26 +2119,10 @@ private:
                overWriteCh = ' ';
                overWrite = 2;
             }
-            surface.TextOpacity(opacity);
             surface.SetBackground(background);
             surface.SetForeground(foreground);
          }
 
-         if(style.freeCaret && selected)
-         {
-            surface.SetBackground(selectionBackground);
-            surface.Area(x + XOFFSET - 1,y,clientSize.w-1,y+this.space.h-1);
-            // TEST: surface.Area(x + XOFFSET,y,clientSize.w-1,y+this.space.h-1);
-         }
-
-
-         /*
-         if(style.freeCaret && selected)
-         {
-            surface.SetBackground(selectionBackground);
-            surface.Area(x + XOFFSET - 1,y,clientSize.w-1,y+this.space.h-1);
-         }
-         */
          if(line.count && line.text[line.count - 1] == '\\')
          {
             continuedSingleLineComment = inSingleLineComment;
@@ -2132,7 +2213,10 @@ private:
                len = 1;
             }
             else
-               FontExtent(display, font, line.buffer + start, len, &w, null);
+            {
+               int oh;
+               FontExtent(display, font, line.buffer + start, len, &w, null, 0, null, &oh);
+            }
          }
          else
          {
@@ -2479,7 +2563,7 @@ private:
       return false;
    }
 
-   bool AddToLine(char * stringLine, int count, bool LFComing, int * addedSpacesPtr, int * addedTabsPtr)
+   bool AddToLine(const char * stringLine, int count, bool LFComing, int * addedSpacesPtr, int * addedTabsPtr, int * xAdjustmentPtr)
    {
       bool hadComment = false;
       // Add the line here
@@ -2505,7 +2589,7 @@ private:
          {
             int w;
             int numBytes = 1;
-            char * string;
+            const char * string;
             if(c < Min(this.x, line.count))
                string = line.buffer + c;
             else if(c < endX)
@@ -2521,8 +2605,9 @@ private:
             }
             else
             {
+               int oh;
                numBytes = UTF8_NUM_BYTES(*string);
-               FontExtent(display, this.font, string, numBytes, &w, null);
+               FontExtent(display, this.font, string, numBytes, &w, null, 0, null, &oh);
             }
             x += w;
 
@@ -2539,6 +2624,7 @@ private:
       {
          int addedSpaces = 0;
          int addedTabs = 0;
+         int xAdjustment = 0;
 
          // Add blank spaces if EES_FREECARET
          if(this.x > line.count)
@@ -2565,6 +2651,8 @@ private:
                      addedSpaces = wantedPosition - position;
                   else
                   {
+                     xAdjustment = wantedPosition - position;
+
                      // Put a first tab
                      addedTabs = 1;
                      position += this.tabSize - (position % this.tabSize);
@@ -2573,6 +2661,8 @@ private:
                      position += (addedTabs-1) * this.tabSize;
                      // Finish off with spaces
                      addedSpaces = wantedPosition - position;
+
+                     xAdjustment -= addedSpaces + addedTabs;
                   }
                }
                else
@@ -2601,7 +2691,6 @@ private:
             CopyBytes(line.buffer + this.x + addedTabs + addedSpaces, stringLine, count);
             if(addedTabs)
             {
-               *addedTabsPtr = addedTabs;
                FillBytes(line.buffer+line.count,'\t',addedTabs);
 #ifdef _DEBUG
       if(addedTabs > 4000 || addedTabs < 0)
@@ -2609,8 +2698,7 @@ private:
 #endif
                line.count += addedTabs;
             }
-            else if(addedTabs)
-               *addedTabsPtr = 0;
+
             if(addedSpaces)
             {
                FillBytes(line.buffer+line.count,' ',addedSpaces);
@@ -2619,10 +2707,11 @@ private:
          printf("Warning");
 #endif
                line.count += addedSpaces;
-               if(addedSpacesPtr) *addedSpacesPtr = addedSpaces;
             }
-            else if(addedSpacesPtr)
-               *addedSpacesPtr = 0;
+
+            if(addedTabsPtr) *addedTabsPtr = addedTabs;
+            if(addedSpacesPtr) *addedSpacesPtr = addedSpaces;
+            if(xAdjustmentPtr) *xAdjustmentPtr = xAdjustment;
 #ifdef _DEBUG
       if(count > 4000 || count < 0)
          printf("Warning");
@@ -2891,7 +2980,10 @@ private:
                         len = 1;
                      }
                      else
-                        FontExtent(display, this.font, line.buffer + start, len, &w, null);
+                     {
+                        int oh;
+                        FontExtent(display, this.font, line.buffer + start, len, &w, null, 0, null, &oh);
+                     }
                   }
                   else
                   {
@@ -2996,7 +3088,10 @@ private:
                len = 1;
             }
             else
-               FontExtent(display, font, line.buffer + start, len, &w, null);
+            {
+               int oh;
+               FontExtent(display, font, line.buffer + start, len, &w, null, 0, null, &oh);
+            }
          }
          else
          {
@@ -3021,7 +3116,10 @@ private:
                else
                   a--;
                if(a > start)
-                  FontExtent(display, font, line.buffer + start, a - start, &w, null);
+               {
+                  int oh;
+                  FontExtent(display, font, line.buffer + start, a - start, &w, null, 0, null, &oh);
+               }
                else
                   w = 0;
                if(position > x + (half ? ((w + lastW) / 2) : lastW)) break;
@@ -3111,7 +3209,7 @@ private:
    }
 
    /*
-   bool SaveFile(char * fileName)
+   bool SaveFile(const char * fileName)
    {
       File f = eFile_Open(fileName, FO_WRITE);
       if(f)
@@ -3541,8 +3639,9 @@ private:
    {
       if(FontExtent)
       {
-         FontExtent(display, font, " ", 1, (int *)&space.w, (int *)&space.h);
-         FontExtent(display, font, "W", 1, (int *)&large.w, (int *)&large.h);
+         int oh;
+         FontExtent(display, font, " ", 1, (int *)&space.w, (int *)&space.h, 0, null, &oh);
+         FontExtent(display, font, "W", 1, (int *)&large.w, (int *)&large.h, 0, null, &oh);
 
          space.w = Max(space.w, 1);
          large.w = Max(large.w, 1);
@@ -3567,7 +3666,7 @@ private:
 
    bool OnLoadGraphics()
    {
-      FontExtent = Display::FontExtent;
+      FontExtent = Display::FontExtent2;
       font = fontObject;
       ComputeFont();
       // UpdateCaretPosition(true);
@@ -3606,7 +3705,7 @@ private:
                int y;
                bool done = false;
                EditLine line = this.line;
-               int c;
+               int c = 0;
                for(y = this.y; y>= 0; y--)
                {
                   c = (y == this.y) ? (Min(this.x-1, line.count-1)) : line.count-1;
@@ -3854,8 +3953,8 @@ private:
                bool foundAlpha = false;
                bool found = false;
                int y = this.y;
-               EditLine line, lastLine;
-               int lastC, lastY;
+               EditLine line, lastLine = null;
+               int lastC = 0, lastY = 0;
 
                for(line = this.line; (line && !found); line = line.prev, y--)
                {
@@ -3976,9 +4075,9 @@ private:
                {
                   bool foundAlpha = false;
                   bool found = false;
-                  EditLine line, lastLine;
+                  EditLine line = null, lastLine = null;
                   int y = this.y;
-                  int lastC, lastY, lastNumBytes;
+                  int lastC = 0, lastY = 0, lastNumBytes = 0;
 
                   for(line = this.line; (line && !found); line = line.next, y++)
                   {
@@ -4825,7 +4924,7 @@ private:
                         char * newline;
                         int putsize;
 
-                        int indentwidth;
+                        int indentwidth = 0;
                         EditLine line = this.line;
 
                         //Only remove one tab if there is nothing else on the line.
@@ -4979,14 +5078,14 @@ private:
       UpdateDirty();
    }
 
-   bool _AddCh(unichar ch, int * addedSpacesPtr, int * addedTabsPtr)
+   bool _AddCh(unichar ch, int * addedSpacesPtr, int * addedTabsPtr, int * xAdjustmentPtr)
    {
       EditLine line;
-      int length, endX;
+      int length, endX = 0;
       bool result;
       ReplaceTextAction replaceAction = null;
       AddCharAction addCharAction = null;
-      int addedSpaces = 0, addedTabs = 0;
+      int addedSpaces = 0, addedTabs = 0, xAdjustment = 0;
 
       if(ch == '\r') return true;
       if(style.stuckCaret /*|EES_READONLY)*/ )
@@ -5120,9 +5219,10 @@ private:
          char string[5];
          int count = UTF32toUTF8Len(&ch, 1, string, 5);
          DelSel(&addedSpaces);
-         result = AddToLine(string, count, false, addedSpaces ? null : &addedSpaces, &addedTabs);
+         result = AddToLine(string, count, false, addedSpaces ? null : &addedSpaces, &addedTabs, &xAdjustment);
          if(addedSpacesPtr) *addedSpacesPtr = addedSpaces;
          if(addedTabsPtr) *addedTabsPtr = addedTabs;
+         if(xAdjustmentPtr) *xAdjustmentPtr = xAdjustment;
       }
       this.selX = this.x;
       this.selY = this.y;
@@ -5154,7 +5254,7 @@ public:
 
    bool AddCh(unichar ch)
    {
-      return _AddCh(ch, null, null);
+      return _AddCh(ch, null, null, null);
    }
 
    void Modified()
@@ -5178,6 +5278,11 @@ public:
       undoBuffer.Undo();
       itemEditUndo.disabled = undoBuffer.curAction == 0;
       itemEditRedo.disabled = undoBuffer.curAction == undoBuffer.count;
+
+      UpdateDirty();
+      SetSelectCursor();
+      SelectionEnables();
+
       if(savedAction == undoBuffer.curAction)
       {
          modifiedDocument = false;
@@ -5191,6 +5296,11 @@ public:
       undoBuffer.Redo();
       itemEditUndo.disabled = undoBuffer.curAction == 0;
       itemEditRedo.disabled = undoBuffer.curAction == undoBuffer.count;
+
+      UpdateDirty();
+      SetSelectCursor();
+      SelectionEnables();
+
       if(savedAction == undoBuffer.curAction)
       {
          modifiedDocument = false;
@@ -5243,14 +5353,14 @@ public:
    }
 
    // BASIC OUTPUT
-   bool AddS(char * string)
+   bool AddS(const char * string)
    {
       if(this)
       {
          bool ret = true;
-         char * line;
+         const char * line;
          int c, count;
-         int addedSpaces = 0, addedTabs = 0;
+         int addedSpaces = 0, addedTabs = 0, xAdjustment = 0;
          AddTextAction action = null;
          ReplaceTextAction replaceAction = null;
 
@@ -5323,7 +5433,7 @@ public:
          {
             if(string[c] == '\n' || string[c] == '\r')
             {
-               if(!AddToLine(line, count, true, addedSpaces ? null : &addedSpaces, addedTabs ? null : &addedTabs))
+               if(!AddToLine(line, count, true, addedSpaces ? null : &addedSpaces, addedTabs ? null : &addedTabs, xAdjustment ? null : &xAdjustment))
                {
                   ret = false;
                   break;
@@ -5358,7 +5468,7 @@ public:
 
          // Add the line here
          if(ret && count)
-            if(!AddToLine(line,count,false, addedSpaces ? null : &addedSpaces, addedTabs ? null : &addedTabs))
+            if(!AddToLine(line,count,false, addedSpaces ? null : &addedSpaces, addedTabs ? null : &addedTabs, xAdjustment ? null : &xAdjustment))
             {
                ret = false;
             }
@@ -5371,6 +5481,7 @@ public:
             action.x2 = x;
             action.addedSpaces = addedSpaces;
             action.addedTabs = addedTabs;
+            action.xAdjustment = xAdjustment;
          }
          else if(replaceAction)
          {
@@ -5378,6 +5489,7 @@ public:
             replaceAction.x3 = x;
             replaceAction.addedSpaces = addedSpaces;
             replaceAction.addedTabs = addedTabs;
+            replaceAction.xAdjustment = xAdjustment;
          }
 
          UpdateCaretPosition(true);
@@ -5406,10 +5518,10 @@ public:
    {
       bool result;
 
-      if((ch >= 32 /*&& ch <=126*/) || ch == '\n')
+      if((ch >= 32 /*&& ch <=126*/) || ch == '\n' || ch == '\t')
       //if((ch >= 32) || ch == '\n')
       {
-         int addedSpaces = 0, addedTabs = 0;
+         int addedSpaces = 0, addedTabs = 0, xAdjustment = 0;
          ReplaceTextAction replaceAction = null;
          AddCharAction addCharAction = null;
 
@@ -5473,19 +5585,20 @@ public:
             }
          }
          undoBuffer.dontRecord++;
-         result = _AddCh(ch, &addedSpaces, &addedTabs);
+         result = _AddCh(ch, &addedSpaces, &addedTabs, &xAdjustment);
          if(replaceAction)
          {
             replaceAction.x3 = x;
             replaceAction.y3 = y;
             replaceAction.addedSpaces = addedSpaces;
             replaceAction.addedTabs = addedTabs;
+            replaceAction.addedTabs = xAdjustment;
          }
          if(addCharAction)
          {
-            addCharAction.x -= addedTabs * (tabSize-1);
             addCharAction.addedSpaces = addedSpaces;
             addCharAction.addedTabs = addedTabs;
+            addCharAction.xAdjustment = xAdjustment;
          }
          undoBuffer.dontRecord--;
          if(ch == '\n')
@@ -5495,7 +5608,7 @@ public:
       }
    }
 
-   void PutS(char * string)
+   void PutS(const char * string)
    {
       if(this)
       {
@@ -5505,7 +5618,7 @@ public:
       }
    }
 
-   void Printf(char * format, ...)
+   void Printf(const char * format, ...)
    {
       if(this)
       {
@@ -5519,7 +5632,7 @@ public:
       }
    }
 
-   void SetContents(char * format, ...)
+   void SetContents(const char * format, ...)
    {
       if(this)
       {
@@ -6243,7 +6356,7 @@ public:
       itemEditRedo.disabled = undoBuffer.curAction == undoBuffer.count;
    }
 
-   EditBoxFindResult Find(char * text, bool matchWord, bool matchCase, bool isSearchDown)
+   EditBoxFindResult Find(const char * text, bool matchWord, bool matchCase, bool isSearchDown)
    {
       EditLine line;
       int num;
@@ -6301,7 +6414,7 @@ public:
       return notFound;
    }
 
-   EditBoxFindResult FindInSelection(char * text, bool matchWord, bool matchCase, EditLine l2, int y2, int x2)
+   EditBoxFindResult FindInSelection(const char * text, bool matchWord, bool matchCase, EditLine l2, int y2, int x2)
    {
       EditLine line;
       int y;
@@ -6536,7 +6649,7 @@ public:
       return result;
    }
 
-   bool Puts(char * string)
+   bool Puts(const char * string)
    {
       EditBox editBox = this.editBox;
       BufferLocation start { editBox.line, editBox.y, editBox.x };
@@ -6566,7 +6679,7 @@ public:
       {
          utf8Bytes[numBytes++] = ch;
          utf8Bytes[numBytes] = 0;
-         if(UTF8Validate(utf8Bytes))
+         if(UTF8Validate((char *)utf8Bytes))
          {
             editBox.AddCh(UTF8_GET_CHAR(utf8Bytes, numBytes));
             numBytes = 0;