ecere/gui/controls/ListBox: Fixed remaining issue caused by moving fix
[sdk] / ecere / src / gui / controls / ListBox.ec
index d48ea6d..e35a3a6 100644 (file)
@@ -52,15 +52,16 @@ extern int __ecereVMethodID_class_OnSaveEdit;
 
 private:
 
-public class DataField 
+public class DataField
 {
 public:
    property Class dataType
    {
-      set { dataType = value; if(value) alignment = value.defaultAlignment; }
+      set { dataType = value; if(value) { alignment = (Alignment)value.defaultAlignment; } }  // NOTE: Class::defaultAlignment does not seem to be used anywhere
       get { return dataType; }
    }
    property bool editable { set { editable = value; } };
+   property bool fixed { set { fixed = value; } get { return fixed; } };
    property Alignment alignment
    {
       set
@@ -69,6 +70,7 @@ public:
          if(headButton) headButton.alignment = value;
          if(listBox) listBox.Update(null);
       }
+      get { return alignment; }
    };
    property int width
    {
@@ -112,12 +114,12 @@ public:
                }
                index++;
             }
-            return -1;
          }
+         return -1;
       }
    };
    property int sortOrder { get { return this ? sortOrder : 0; } };
-   property char * header
+   property const char * header
    {
       set
       {
@@ -131,7 +133,7 @@ public:
       set
       {
          userData = value;
-      } 
+      }
       get
       {
          return this ? userData : null;
@@ -139,7 +141,7 @@ public:
    };
    property bool freeData
    {
-      set { freeData = value; } get { return freeData; }      
+      set { freeData = value; } get { return freeData; }
    };
    property DataField prev { get { return prev; } };
    property DataField next { get { return next; } };
@@ -148,9 +150,6 @@ public:
    {
       if(prev != after)
       {
-         int position = 0;
-         DataField field;
-
          listBox.fields.Move(this, after);
 
          // Fix up positions
@@ -159,6 +158,44 @@ public:
       }
    }
 
+   void AutoSize()
+   {
+      if(listBox && dataType)
+      {
+         Display display = listBox.display;
+         Font boldFont = listBox.boldFont.font;
+         Font font = listBox.fontObject;
+         DataRow row;
+         int width = 0;
+         if(header)
+            display.FontExtent(boldFont, header, strlen(header), &width, null);
+         width += EXTRA_SPACE;
+         for(row = listBox.firstRow; row; row = row.GetNextRow())
+         {
+            ListBoxCell cell;
+            uint i;
+            for(i = 0, cell = row.cells.first; i != index; i++, cell = cell.next);
+            if(cell && cell.isSet && dataType)
+            {
+               static char tempString[4096];
+               const String string;
+               int tw = 0;
+               if(dataType.type == normalClass || dataType.type == noHeadClass)
+                  string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, cell.data[0], tempString, userData, null);
+               else
+                  string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, cell.data, tempString, userData, null);
+               if(string)
+                  display.FontExtent(row.header ? boldFont : font, string, strlen(string), &tw, null);
+               else
+                  display.FontExtent(row.header ? boldFont : font, "", 0, &tw, null);
+               if(tw > width) width = tw;
+            }
+         }
+         if(width)
+            property::width = width;
+      }
+   }
+
 private:
    DataField()
    {
@@ -183,11 +220,11 @@ private:
          listBox.fields.Remove(this);
          for(field = listBox.fields.first; field; field = field.next)
          {
-            if(field.index >= index) 
+            if(field.index >= index)
                field.index--;
          }
          if(listBox.currentField == this)
-            listBox.currentField = null;            
+            listBox.currentField = null;
          listBox.numFields--;
          listBox.OnResize(listBox.clientSize.w, listBox.clientSize.h);
          listBox = null;
@@ -195,47 +232,51 @@ private:
    }
 
    DataField prev, next;
-   char * header;
+   const char * header;
    Class dataType;
    int width;
    uint index;
    int x;
    Button headButton;
    int sortOrder;
-   int alignment;
+   Alignment alignment;
    bool editable;
    ListBox listBox;
    bool defaultField;
    void * userData;
    bool freeData;
+   bool fixed;
 };
 
 public class DataRow
 {
    class_no_expansion
+#ifdef _DEBUG
+   bool skipCheck;
+#endif
 public:
-   property int tag { set { tag = value; } get { return tag; } };
+   property int64 tag { set { if(this) tag = value; } get { return this ? tag : 0; } };
    property DataRow previous { get { return prev; } };
    property DataRow next { get { return next; } };
    property int index { get { return (this && (!parent || parent.IsExpanded())) ? index : -1; } };
-   property char * string
+   property const char * string
    {
       set { SetData(listBox.fields.first, value); }
       get { return GetData(listBox.fields.first); }
    };
    property bool isHeader { set { header = value; } get { return this ? header : false; } };
-   property BitmapResource icon { set { icon = value; } get { return icon; } };
+   property BitmapResource icon { set { if(this) icon = value; } get { return this ? icon : null; } };
    property bool collapsed
    {
       set
       {
-         if(collapsed != value)
+         if(this && collapsed != value)
          {
             collapsed = value;
             if(parent.IsExpanded())
             {
                DataRow search;
-               int index;
+               int ix;
 
                if(value)
                {
@@ -248,11 +289,11 @@ public:
                      if(!listBox.clickedRow)
                         listBox.clickedRow = this;
                   }
-                  if(listBox.currentRow && !listBox.currentRow.parent.IsExpanded()) 
+                  if(listBox.currentRow && !listBox.currentRow.parent.IsExpanded())
                   {
                      listBox.SetCurrentRow(this, true);
                   }
-                  if(listBox.firstRowShown && !listBox.firstRowShown.parent.IsExpanded()) 
+                  if(listBox.firstRowShown && !listBox.firstRowShown.parent.IsExpanded())
                   {
                      listBox.firstRowShown = GetPrevRow();
                      if(!listBox.firstRowShown)
@@ -260,23 +301,26 @@ public:
                   }
                }
 
-               // TODO: FIX row indices
-               index = this.index+1;
+               ix = index+1;
                for(search = GetNextRow(); search; search = search.GetNextRow())
-                  search.index = index++;
-               listBox.rowCount = index;
+                  search.index = ix++;
+               listBox.rowCount = ix;
 
                listBox.HideEditBox(false, false, true);
 
                listBox.SetScrollArea(
                   listBox.width,
-                  (listBox.rowCount * listBox.rowHeight) + 
+                  (listBox.rowCount * listBox.rowHeight) +
                   ((listBox.style.header) ? listBox.rowHeight : 0) -
                   ((!((listBox.clientSize.h+1) % listBox.rowHeight)) ? listBox.rowHeight : 0), true);
                listBox.Update(null);
                listBox.NotifyCollapse(listBox.master, listBox, this, value);
             }
          }
+#ifdef _DEBUG
+         if(this && !skipCheck)
+            listBox.CheckConsistency();
+#endif
       }
       get { return this ? collapsed : false; }
    };
@@ -300,24 +344,25 @@ public:
          {
             DataRow search;
             DataRow after = value ? value.subRows.last : listBox.rows.last;
+            int ixCount = (!collapsed && subRows.count) ? GetLastRow().index - index + 1 : 1;
             if(parent.IsExpanded())
             {
                for(search = GetNextRow(); search; search = search.GetNextRow())
-                  search.index--;         
-               listBox.rowCount--;
+                  search.index -= ixCount;
+               listBox.rowCount -= ixCount;
             }
 
             listBox.HideEditBox(false, false, true);
 
             /*
-            if(this == listBox.clickedRow) 
+            if(this == listBox.clickedRow)
             {
                listBox.clickedRow = GetNextRow();
                if(!listBox.clickedRow)
                   listBox.clickedRow = GetPrevRow();
             }
 
-            if(this == listBox.currentRow) 
+            if(this == listBox.currentRow)
             {
                DataRow newCurrentRow = GetNextRow();
                if(!listBox.newCurrentRow)
@@ -325,7 +370,7 @@ public:
                listBox.SetCurrentRow(newCurrentRow, true);
             }
 
-            if(this == listBox.firstRowShown) 
+            if(this == listBox.firstRowShown)
             {
                listBox.firstRowShown = GetPrevRow();
                if(!listBox.firstRowShown)
@@ -343,29 +388,39 @@ public:
             parent = value;
 
             if(value && listBox.style.expandOnAdd)
+            {
+#ifdef _DEBUG
+               value.skipCheck = true;
+#endif
                value.collapsed = false;
+#ifdef _DEBUG
+               value.skipCheck = false;
+#endif
+            }
 
-            if(value.IsExpanded(this))
+            if(value.IsExpanded())
             {
                DataRow search;
 
                if(after && after.subRows.first && !after.collapsed)
                {
-                  for(search = after.subRows.last; !search.collapsed && search.subRows.last; )
-                     search = search.subRows.last;
+                  search = after.GetLastRow();
                   index = search.index + 1;
                }
                else
                   index = after ? (after.index + 1) : (index + 1);
 
-               listBox.rowCount++;
+               listBox.rowCount += ixCount;
 
-               for(search = GetNextRow(); search; search = search.GetNextRow())
-                  search.index++;            
+               {
+                  int ix = index+1;
+                  for(search = GetNextRow(); search; search = search.GetNextRow())
+                     search.index = ix++;
+               }
 
                listBox.SetScrollArea(
                   listBox.width,
-                  (listBox.rowCount * listBox.rowHeight) + 
+                  (listBox.rowCount * listBox.rowHeight) +
                   ((listBox.style.header) ? listBox.rowHeight : 0) -
                   ((!((listBox.clientSize.h+1) % listBox.rowHeight)) ? listBox.rowHeight : 0), true);
                if(listBox.style.autoScroll)
@@ -419,6 +474,7 @@ public:
       }
    }
 
+   // NOTE: This does not support reparenting (Use row.parent = first)
    void Move(DataRow after)
    {
       if(this)
@@ -427,50 +483,85 @@ public:
          if(listBox && prev != after)
          {
             DataRow search;
-            int afterIndex = -1;
             int headerSize = ((listBox.style.header) ? listBox.rowHeight : 0);
             int height = listBox.clientSize.h + 1 - headerSize;
+            int ixCount = (!collapsed && subRows.count) ? GetLastRow().index - index + 1 : 1;
 
             if(!after || after.index < index)
             {
-               if(after == listBox.firstRowShown.prev) 
+               if((after && after == listBox.firstRowShown.prev) || (!after && !parent /*&& listBox.firstRowShown.prev*/))
                   listBox.firstRowShown = this;
 
                // All rows between AFTER (exclusive) and ROW (exclusive) are incremented by one
                // ROW is equal to AFTER's index + 1
 
-               // TODO: Fix indices
-               for(search = after ? after.next : listBox.rows.first; search && search != this; search = search.GetNextRow())
-                  search.index++;
+               for(search = after ? after.next : (parent ? parent.subRows.first : listBox.rows.first); search && search != this; search = search.GetNextRow())
+                  search.index += ixCount;
 
                if(after && after.subRows.first && !after.collapsed)
                {
-                  for(search = after.subRows.last; !search.collapsed && search.subRows.last; )
-                     search = search.subRows.last;
+                  search = after.GetLastRow();
                   index = search.index + 1;
                }
                else
-                  index = after ? (after.index + 1) : 0;
+                  index = after ? (after.index + 1) : parent ? parent.index + 1 : 0;
+
+               // Fix indices of sub rows
+               if(!collapsed)
+               {
+                  int c, ix = index+1;
+                  for(c = 1, search = GetNextRow(); search && c < ixCount; c++, search = search.GetNextRow())
+                     search.index = ix++;
+               }
             }
             else
             {
+               DataRow nextRow;
+               int afterIXCount = 1;
+
+               nextRow = GetNextRow();
                if(this == listBox.firstRowShown)
-               {
-                  listBox.firstRowShown = GetNextRow();
-               }
+                  listBox.firstRowShown = nextRow;
 
                // All rows between ROW (exclusive) and AFTER (inclusive) are decremented by one
                // ROW is equal to AFTER's index
 
-               // TODO: Fix indices
-               for(search = GetNextRow(); search; search = search.GetNextRow())
+               for(search = nextRow; search; search = search.GetNextRow())
                {
-                  search.index--;
+                  search.index -= ixCount;
                   if(search == after) break;
                }
-               index = after ? (after.index + 1) : 0;
+
+               // Fix up's after's sub rows
+               if(after && !after.collapsed)
+               {
+                  DataRow last = after.GetLastRow();
+                  if(last != after)
+                  {
+                     int ix = after.index+1;
+                     for(search = after.GetNextRow(); search; search = search.GetNextRow())
+                     {
+                        afterIXCount++;
+                        search.index = ix++;
+                        if(search == last) break;
+                     }
+                  }
+               }
+               index = after.index + afterIXCount;
+
+               // Fix indices of sub rows
+               if(!collapsed)
+               {
+                  int c, ix = index+1;
+                  for(c = 1, search = GetNextRow(); search && c < ixCount; c++, search = search.GetNextRow())
+                     search.index = ix++;
+               }
             }
-            listBox.rows.Move(this, after);
+            (parent ? parent.subRows : listBox.rows).Move(this, after);
+
+#ifdef _DEBUG
+            listBox.CheckConsistency();
+#endif
 
             listBox.HideEditBox(true, false, true);
             if(listBox)
@@ -505,7 +596,7 @@ public:
             if((field.dataType.type == normalClass || field.dataType.type == noHeadClass))
                return cell.data[0];
             else
-               return (void *)cell.data;   // Cast for MemoryGuard
+               return cell.data;
          }
       }
       return null;
@@ -525,25 +616,25 @@ public:
                if(dataType.type == normalClass || dataType.type == noHeadClass)
                {
                   if(cell.data[0] && field.freeData)
-                     dataType._vTbl[__ecereVMethodID_class_OnFree](dataType, cell.data[0]);
+                     ((void (*)(void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnFree])(dataType, cell.data[0]);
 
                   if(eClass_IsDerived(dataType, class(char *)) && field.freeData)
-                     dataType._vTbl[__ecereVMethodID_class_OnCopy](dataType, cell.data, newData);
+                     ((void (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCopy])(dataType, cell.data, newData);
                   else
                      cell.data[0] = (void *)newData;
                }
                else
                {
                   // Free old data first
-                  dataType._vTbl[__ecereVMethodID_class_OnFree](dataType, cell.data);
-                  dataType._vTbl[__ecereVMethodID_class_OnCopy](dataType, cell.data, newData);
+                  ((void (*)(void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnFree])(dataType, cell.data);
+                  ((void (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCopy])(dataType, cell.data, newData);
                }
             }
             cell.isSet = true;
             listBox.modifiedDocument = true;
             listBox.Update(null);
             if(dataType && (dataType.type == normalClass || dataType.type == noHeadClass))
-               return (void *)cell.data;     // Cast for MemoryGuard
+               return cell.data;
             else
                return &cell.data;
          }
@@ -565,13 +656,13 @@ public:
                if(dataType.type == normalClass || dataType.type == noHeadClass)
                {
                   if(cell.data[0] && field.freeData)
-                     dataType._vTbl[__ecereVMethodID_class_OnFree](dataType, cell.data[0]);
+                     ((void (*)(void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnFree])(dataType, cell.data[0]);
                   cell.data[0] = null;
                }
                else
                {
                   // Free old data first
-                  dataType._vTbl[__ecereVMethodID_class_OnFree](dataType, cell.data);
+                  ((void (*)(void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnFree])(dataType, cell.data);
                }
             }
             cell.isSet = false;
@@ -580,7 +671,7 @@ public:
       }
    }
 
-   DataRow FindRow(int tag)
+   DataRow FindRow(int64 tag)
    {
       DataRow row = null;
       for(row = subRows.first; row; row = row.next)
@@ -591,7 +682,7 @@ public:
       return row;
    }
 
-   DataRow FindSubRow(int tag)
+   DataRow FindSubRow(int64 tag)
    {
       DataRow row = null;
       for(row = subRows.first; row; row = row.next)
@@ -630,16 +721,16 @@ public:
                      break;
                if(field)
                {
-                  int size = (field.dataType && field.dataType.typeSize) ? 
+                  int size = (field.dataType && field.dataType.typeSize) ?
                      (sizeof(class ListBoxCell) + field.dataType.typeSize - sizeof(void *)) : sizeof(class ListBoxCell);
                   ListBoxCell cell = (ListBoxCell)new0 byte[size];
                   row.cells.Add(cell);
-                  FillBytes(cell.data, 0, size - (uint)&((ListBoxCell)0).data);
+                  FillBytes(cell.data, 0, size - (uint)(uintptr)&((ListBoxCell)0).data);
                   cell.isSet = false;
                }
             }
 
-            if(IsExpanded(this))
+            if(IsExpanded())
             {
                DataRow search;
 
@@ -654,13 +745,12 @@ public:
 
                listBox.rowCount++;
 
-               // TODO: Fix indices
                for(search = row.GetNextRow(); search; search = search.GetNextRow())
-                  search.index++;            
+                  search.index++;
 
                listBox.SetScrollArea(
                   listBox.width,
-                  (listBox.rowCount * listBox.rowHeight) + 
+                  (listBox.rowCount * listBox.rowHeight) +
                   ((listBox.style.header) ? listBox.rowHeight : 0) -
                   ((!((listBox.clientSize.h+1) % listBox.rowHeight)) ? listBox.rowHeight : 0), true);
                if(listBox.style.autoScroll)
@@ -669,6 +759,9 @@ public:
 
             listBox.modifiedDocument = true;
          }
+#ifdef _DEBUG
+         listBox.CheckConsistency();
+#endif
          return row;
       }
       return null;
@@ -681,16 +774,16 @@ public:
       return null;
    }
 
-   DataRow AddStringf(char * format, ...)
+   DataRow AddStringf(const char * format, ...)
    {
       if(this)
       {
          DataRow row;
          char string[MAX_F_STRING];
          va_list args;
-
          va_start(args, format);
-         vsprintf(string, format, args);
+         vsnprintf(string, sizeof(string), format, args);
+         string[sizeof(string)-1] = 0;
          va_end(args);
 
          row = AddRow();
@@ -700,7 +793,7 @@ public:
       return null;
    }
 
-   DataRow AddString(char * string)
+   DataRow AddString(const char * string)
    {
       if(this)
       {
@@ -716,7 +809,7 @@ public:
 private:
    DataRow()
    {
-      subRows.offset = (uint)&((DataRow)0).prev;
+      subRows.offset = (uint)(uintptr)&((DataRow)0).prev;
    }
 
    ~DataRow()
@@ -738,16 +831,16 @@ private:
          {
             DataField field;
             for(field = listBox.fields.first; field && field.index != cellIndex; field = field.next);
-            if(field.dataType && _vTbl[__ecereVMethodID_class_OnFree])
+            if(field && field.dataType)
             {
                // TOCHECK: Is this check good? Will need incref/decref sometime?
                if(field.dataType.type == normalClass || field.dataType.type == noHeadClass)
                {
                   if(cell.data[0] && field.freeData)
-                     field.dataType._vTbl[__ecereVMethodID_class_OnFree](field.dataType, cell.data[0]);
+                     ((void (*)(void *, void *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnFree])(field.dataType, cell.data[0]);
                }
                else
-                  field.dataType._vTbl[__ecereVMethodID_class_OnFree](field.dataType, cell.data);
+                  ((void (*)(void *, void *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnFree])(field.dataType, cell.data);
             }
          }
          next = cell.next;
@@ -765,8 +858,8 @@ private:
       int result = 0;
       ListBoxCell cell1, cell2;
       uint index;
-      for(index = 0, cell1 = cells.first, cell2 = b.cells.first; 
-          index != sortField.index; 
+      for(index = 0, cell1 = cells.first, cell2 = b.cells.first;
+          index != sortField.index;
           index++, cell1 = cell1.next, cell2 = cell2.next);
    /*
       if(!cell1.isSet && !cell2.isSet)
@@ -784,14 +877,14 @@ private:
       {
          if(sortField.dataType.type == normalClass || sortField.dataType.type == noHeadClass)
          {
-            result = sortField.dataType._vTbl[__ecereVMethodID_class_OnCompare](sortField.dataType, 
-               (cell1.isSet && cell1.data) ? cell1.data[0] : null, 
+            result = ((int (*)(void *, void *, void *))(void *)sortField.dataType._vTbl[__ecereVMethodID_class_OnCompare])(sortField.dataType,
+               (cell1.isSet && cell1.data) ? cell1.data[0] : null,
                (cell2.isSet && cell2.data) ? cell2.data[0] : null);
          }
          else
          {
-            result = sortField.dataType._vTbl[__ecereVMethodID_class_OnCompare](sortField.dataType, 
-               cell1.isSet ? cell1.data : null, 
+            result = ((int (*)(void *, void *, void *))(void *)sortField.dataType._vTbl[__ecereVMethodID_class_OnCompare])(sortField.dataType,
+               cell1.isSet ? cell1.data : null,
                cell2.isSet ? cell2.data : null);
          }
       }
@@ -812,12 +905,11 @@ private:
       {
          _SortSubRows(listBox.sortField, listBox.sortField.sortOrder);
 
-         // TODO: Recompute row indices
          {
             DataRow search;
-            int index = this.index;
+            int ix = index;
             for(search = this; search; search = search.GetNextRow())
-               search.index = index++;
+               search.index = ix++;
          }
          if(scrollToCurrent)
          {
@@ -849,9 +941,9 @@ private:
    {
       DataRow row;
       // Find Next row
-      if(subRows.first && !collapsed) 
+      if(subRows.first && !collapsed)
          row = subRows.first;
-      else 
+      else
       {
          for(row = this; row; row = row.parent)
          {
@@ -861,9 +953,17 @@ private:
       return row;
    }
 
+   private DataRow GetLastRow()
+   {
+      DataRow row = this;
+      while(row && !row.collapsed && row.subRows.last)
+         row = row.subRows.last;
+      return row;
+   }
+
    DataRow prev, next;
    OldList cells;
-   int tag;
+   int64 tag;
    SelectedFlag selectedFlag;
    ListBox listBox;
    bool header;
@@ -886,12 +986,12 @@ public class ListBox : CommonControl
 
 public:
    // Properties
-   property bool freeSelect { property_category "Behavior" set { style.freeSelect = value; } get { return style.freeSelect; } };
-   property DataRow currentRow { property_category "Private" /*"Behavior"*/ set { SetCurrentRow(value, false); } get { return currentRow; } };
+   property bool freeSelect { property_category $"Behavior" set { style.freeSelect = value; } get { return style.freeSelect; } };
+   property DataRow currentRow { property_category $"Private" /*"Behavior"*/ set { if(this) SetCurrentRow(value, false); } get { return this ? currentRow : null; } };
    property DataField currentField
    {
       get { return currentField; }
-      // TODO: Needs definition of what this is, testing
+      // TODO: Document what this does
       set
       {
          currentField = value;
@@ -903,7 +1003,7 @@ public:
 
    property int rowHeight
    {
-      property_category "Appearance" 
+      property_category $"Appearance"
       isset { return style.heightSet; }
       set
       {
@@ -920,11 +1020,11 @@ public:
             OnApplyGraphics();
          }
       }
-      get { return rowHeight; }
+      get { return this ? rowHeight : 0; }
    };
    property Seconds typingTimeout
    {
-      property_category "Behavior" 
+      property_category $"Behavior"
       set
       {
          typedString[0] = '\0';
@@ -933,15 +1033,15 @@ public:
       }
       get { return typingTimeOut; }
    };
-   property bool moveRows { property_category "Behavior" set { style.moveRows = value; } get { return style.moveRows; } };
-   property bool moveFields { property_category "Behavior" set { style.moveFields = value; } get { return style.moveFields; } };
-   property bool resizable { property_category "Behavior" set { style.resizable = value; } get { return style.resizable; } };
-   property bool autoScroll { property_category "Behavior" set { style.autoScroll = value; } get { return style.autoScroll; } };
-   property bool alwaysHighLight { property_category "Appearance" set { style.alwaysHL = value; } get { return style.alwaysHL; } };
-   property bool hasClearHeader { property_category "Appearance" set { style.clearHeader = value; if(value) property::hasHeader = true; } get { return style.clearHeader; } };
+   property bool moveRows { property_category $"Behavior" set { style.moveRows = value; } get { return style.moveRows; } };
+   property bool moveFields { property_category $"Behavior" set { style.moveFields = value; } get { return style.moveFields; } };
+   property bool resizable { property_category $"Behavior" set { style.resizable = value; } get { return style.resizable; } };
+   property bool autoScroll { property_category $"Behavior" set { style.autoScroll = value; } get { return style.autoScroll; } };
+   property bool alwaysHighLight { property_category $"Appearance" set { style.alwaysHL = value; } get { return style.alwaysHL; } };
+   property bool hasClearHeader { property_category $"Appearance" set { style.clearHeader = value; if(value) property::hasHeader = true; } get { return style.clearHeader; } };
    property bool hasHeader
    {
-      property_category "Appearance" 
+      property_category $"Appearance"
       set
       {
          if(value && !style.header)
@@ -956,6 +1056,7 @@ public:
                size.h = rowHeight;
                NotifyPushed = HeaderPushed;
                NotifyClicked = HeaderClicked;
+               NotifyDoubleClick = HeaderDoubleClicked;
                NotifyReleased = HeaderReleased;
                NotifyMouseMove = HeaderMouseMove;
             };
@@ -966,18 +1067,18 @@ public:
          style.header = value;
       }
       get { return style.header; }
-   };   
-   property bool multiSelect { property_category "Behavior" set { style.multiSelect = value; } get { return style.multiSelect; } };
-   property bool alwaysEdit { property_category "Behavior" set { style.alwaysEdit = value; } get { return style.alwaysEdit; } };
-   property bool fullRowSelect { property_category "Appearance" set { style.fullRowSelect = value; } get { return style.fullRowSelect; } };
-   property bool collapseControl { property_category "Appearance" set { style.collapse = value; } get { return style.collapse; } };
-   property bool treeBranches { property_category "Appearance" set { style.treeBranch = value; } get { return style.treeBranch; } };
-   property bool rootCollapseButton { property_category "Appearance" set { style.rootCollapse = value; } get { return style.rootCollapse; } };
-   property bool sortable { property_category "Behavior" set { style.sortable = value; } get { return style.sortable; } };
-   property bool noDragging { property_category "Behavior" set { style.noDragging = value; } get { return style.noDragging; } };
+   };
+   property bool multiSelect { property_category $"Behavior" set { style.multiSelect = value; } get { return style.multiSelect; } };
+   property bool alwaysEdit { property_category $"Behavior" set { style.alwaysEdit = value; } get { return style.alwaysEdit; } };
+   property bool fullRowSelect { property_category $"Appearance" set { style.fullRowSelect = value; } get { return style.fullRowSelect; } };
+   property bool collapseControl { property_category $"Appearance" set { style.collapse = value; } get { return style.collapse; } };
+   property bool treeBranches { property_category $"Appearance" set { style.treeBranch = value; } get { return style.treeBranch; } };
+   property bool rootCollapseButton { property_category $"Appearance" set { style.rootCollapse = value; } get { return style.rootCollapse; } };
+   property bool sortable { property_category $"Behavior" set { style.sortable = value; } get { return style.sortable; } };
+   property bool noDragging { property_category $"Behavior" set { style.noDragging = value; } get { return style.noDragging; } };
    property bool fillLastField
    {
-      property_category "Behavior" 
+      property_category $"Behavior"
       set
       {
          style.fillLastField = value;
@@ -1028,8 +1129,24 @@ public:
    virtual bool Window::NotifyResized(ListBox listBox, DataField field, Modifiers mods);
    virtual bool Window::NotifyCollapse(ListBox listBox, DataRow row, bool collapsed);
    virtual bool Window::NotifyKeyHit(ListBox listBox, DataRow row, Key key, unichar ch);
-   virtual bool Window::NotifyModified(ListBox listBox, DataRow row);   
+   virtual bool Window::NotifyModified(ListBox listBox, DataRow row);
    virtual bool Window::NotifyEditing(ListBox listBox, DataRow row);
+   virtual void Window::NotifyMoved(ListBox listBox, DataRow row, Modifiers mods);
+
+#ifdef _DEBUG
+   private void CheckConsistency()
+   {
+#if 0
+      DataRow r;
+      int index = 0;
+      for(r = rows.first; r; r = r.GetNextRow())
+      {
+         if(r.index != index++)
+            PrintLn("bug");
+      }
+#endif
+   }
+#endif
 
    // Methods
    void AddField(DataField addedField)
@@ -1040,7 +1157,6 @@ public:
          if(fields.first && ((DataField)fields.first).defaultField)
          {
             DataField defaultField = fields.first;
-            // TODO:
             defaultField.Free();
             delete defaultField;
          }
@@ -1052,7 +1168,7 @@ public:
          incref addedField;
          addedField.listBox = this;
          fields.Add(addedField);
-      
+
          addedField.sortOrder = 1;
          addedField.index = numFields;
          numFields++;
@@ -1066,13 +1182,14 @@ public:
                stayOnTop = true;
                inactive = true;
                dontScrollVert = true;
-               id = (uint)addedField;
+               id = (int64)(intptr)addedField;
                text = addedField.header;
                bevel = (!guiApp.textMode && !style.clearHeader);
                ellipsis = true;
                alignment = addedField.alignment;
                NotifyPushed = HeaderPushed;
                NotifyClicked = HeaderClicked;
+               NotifyDoubleClick = HeaderDoubleClicked;
                NotifyReleased = HeaderReleased;
                NotifyMouseMove = HeaderMouseMove;
             };
@@ -1088,16 +1205,16 @@ public:
             field = addedField;
             for(row = rows.first; row; )
             {
-               int size = (field.dataType && field.dataType.typeSize) ? 
+               int size = (field.dataType && field.dataType.typeSize) ?
                   (sizeof(class ListBoxCell) + field.dataType.typeSize - sizeof(void *)) : sizeof(class ListBoxCell);
                ListBoxCell cell = (ListBoxCell)new0 byte[size];
                row.cells.Add(cell);
-               FillBytes(cell.data, 0, size - (uint)&((ListBoxCell)0).data);
+               FillBytes(cell.data, 0, size - (uint)(uintptr)&((ListBoxCell)0).data);
                cell.isSet = false;
 
-               if(row.subRows.first) 
+               if(row.subRows.first)
                   row = row.subRows.first;
-               else 
+               else
                {
                   for(; row; row = row.parent)
                   {
@@ -1115,9 +1232,9 @@ public:
       if(this)
       {
          DataField field;
+         Clear();    // Ensure data is cleared first
          while((field = fields.first))
          {
-            //delete field;
             field.Free();
             delete field;
          }
@@ -1135,6 +1252,9 @@ public:
             int index = field.index;
             DataRow row;
 
+            if(sortField == field)
+               sortField = null;
+
             for(row = rows.first; row; )
             {
                int c;
@@ -1149,19 +1269,19 @@ public:
                      if(field.dataType.type == normalClass || field.dataType.type == noHeadClass)
                      {
                         if(cell.data[0] && field.freeData)
-                           field.dataType._vTbl[__ecereVMethodID_class_OnFree](field.dataType, cell.data[0]);
+                           ((void (*)(void *, void *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnFree])(field.dataType, cell.data[0]);
                      }
                      else
-                        field.dataType._vTbl[__ecereVMethodID_class_OnFree](field.dataType, cell.data);
+                        ((void (*)(void *, void *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnFree])(field.dataType, cell.data);
                   }
 
                   row.cells.Remove(cell);
                   delete cell;
                }
 
-               if(row.subRows.first) 
+               if(row.subRows.first)
                   row = row.subRows.first;
-               else 
+               else
                {
                   for(; row; row = row.parent)
                   {
@@ -1185,24 +1305,22 @@ public:
       if(row)
       {
          DataRow search;
-         DataField field;
-         int c;
 
          row.index = 0;
          rows.Insert(null, row);
          row.listBox = this;
 
          for(search = row.GetNextRow(); search; search = search.GetNextRow())
-            search.index++;         
+            search.index++;
 
-         this.rowCount++;
+         rowCount++;
          row.cells.Clear();
-         
+
          firstRowShown = row;
 
          SetScrollArea(
             width,
-            (rowCount * rowHeight) + 
+            (rowCount * rowHeight) +
             ((style.header) ? rowHeight : 0) -
             ((!((clientSize.h+1) % rowHeight)) ? rowHeight : 0), true);
          if(style.autoScroll)
@@ -1229,8 +1347,7 @@ public:
                // Find very last row
                {
                   DataRow lastRow;
-                  for(lastRow = rows.last; lastRow && !lastRow.collapsed && lastRow.subRows.last; lastRow)
-                     lastRow = lastRow.subRows.last;
+                  for(lastRow = rows.last; lastRow && !lastRow.collapsed && lastRow.subRows.last; lastRow = lastRow.subRows.last);
                   row.index = lastRow ? (lastRow.index + 1) : 0;
                }
 
@@ -1246,11 +1363,11 @@ public:
                         break;
                   if(field)
                   {
-                     int size = (field.dataType && field.dataType.typeSize) ? 
+                     int size = (field.dataType && field.dataType.typeSize) ?
                         (sizeof(class ListBoxCell) + field.dataType.typeSize - sizeof(void *)) : sizeof(class ListBoxCell);
                      ListBoxCell cell = (ListBoxCell) new0 byte[size];
                      row.cells.Add(cell);
-                     FillBytes(cell.data, 0, size - (uint)&((ListBoxCell)0).data);
+                     FillBytes(cell.data, 0, size - (uint)(uintptr)&((ListBoxCell)0).data);
                      cell.isSet = false;
                   }
                }
@@ -1263,13 +1380,16 @@ public:
                if(rowHeight)
                   SetScrollArea(
                      width,
-                     (rowCount * rowHeight) + 
+                     (rowCount * rowHeight) +
                      ((style.header) ? rowHeight : 0) -
                      ((!((clientSize.h+1) % rowHeight)) ? rowHeight : 0), true);
                if(style.autoScroll)
                   SetScrollPosition(0, MAXINT - rowHeight);
                modifiedDocument = true;
             }
+#ifdef _DEBUG
+            CheckConsistency();
+#endif
             return row;
          }
       }
@@ -1299,11 +1419,10 @@ public:
             rows.Insert(after, row);
             row.listBox = this;
 
-            // TODO: FIX row indices
             for(search = row.GetNextRow(); search; search = search.GetNextRow())
-               search.index++;         
+               search.index++;
 
-            this.rowCount++;
+            rowCount++;
             row.cells.Clear();
             for(c = 0; c<fields.count; c++)
             {
@@ -1312,11 +1431,11 @@ public:
                      break;
                if(field)
                {
-                  int size = (field.dataType && field.dataType.typeSize) ? 
+                  int size = (field.dataType && field.dataType.typeSize) ?
                      (sizeof(class ListBoxCell) + field.dataType.typeSize - sizeof(void *)) : sizeof(class ListBoxCell);
                   ListBoxCell cell = (ListBoxCell) new0 byte[size];
                   row.cells.Add(cell);
-                  FillBytes(cell.data, 0, size - (uint)&((ListBoxCell)0).data);
+                  FillBytes(cell.data, 0, size - (uint)(uintptr)&((ListBoxCell)0).data);
                   cell.isSet = false;
                }
             }
@@ -1327,19 +1446,22 @@ public:
 
             SetScrollArea(
                width,
-               (rowCount * rowHeight) + 
+               (rowCount * rowHeight) +
                ((style.header) ? rowHeight : 0) -
                ((!((clientSize.h+1) % rowHeight)) ? rowHeight : 0), true);
             if(style.autoScroll)
                SetScrollPosition(0, MAXINT - rowHeight);
             modifiedDocument = true;
+#ifdef _DEBUG
+            CheckConsistency();
+#endif
             return row;
          }
       }
       return null;
    }
 
-   DataRow AddStringf(char * format, ...)
+   DataRow AddStringf(const char * format, ...)
    {
       if(this)
       {
@@ -1349,7 +1471,8 @@ public:
          va_list args;
 
          va_start(args, format);
-         vsprintf(string, format ? format : "", args);
+         vsnprintf(string, sizeof(string), format ? format : "", args);
+         string[sizeof(string)-1] = 0;
          va_end(args);
 
          row = AddRow();
@@ -1359,7 +1482,7 @@ public:
       return null;
    }
 
-   DataRow AddString(char * string)
+   DataRow AddString(const char * string)
    {
       if(this)
       {
@@ -1381,27 +1504,34 @@ public:
       if(!row) row = currentRow;
       if(row)
       {
-         DataRow search;
+         DataRow sub, next, search;
          // Trying to move this here (Messed up deleting watches)
          //HideEditBox(false, false, true);
+
+         // Delete Sub Rows
+         for(sub = row.subRows.first; sub; sub = next)
+         {
+            next = sub.next;
+            DeleteRow(sub);
+         }
+
          if(row.parent.IsExpanded())
          {
-            // TODO: FIX row indices
             for(search = row.GetNextRow(); search; search = search.GetNextRow())
-               search.index--;         
-            this.rowCount--;
+               search.index--;
+            rowCount--;
          }
 
          HideEditBox(false, false, true);
 
-         if(row == clickedRow) 
+         if(row == clickedRow)
          {
             clickedRow = row.GetNextRow();
             if(!clickedRow)
                clickedRow = row.GetPrevRow();
          }
 
-         if(row == currentRow) 
+         if(row == currentRow)
          {
             DataRow newCurrentRow = row.GetNextRow();
             if(!newCurrentRow)
@@ -1409,7 +1539,7 @@ public:
             SetCurrentRow(newCurrentRow, true);
          }
 
-         if(row == firstRowShown) 
+         if(row == firstRowShown)
          {
             firstRowShown = row.GetPrevRow();
             if(!firstRowShown)
@@ -1422,18 +1552,21 @@ public:
          //HideEditBox(false, false, true);
 
          SetScrollArea(
-            this.width,
-            (this.rowCount * rowHeight) + 
+            width,
+            (rowCount * rowHeight) +
             ((style.header) ? rowHeight : 0) -
             ((!((clientSize.h+1) % rowHeight)) ? rowHeight : 0), true);
 
          modifiedDocument = true;
 
          Update(null);
+#ifdef _DEBUG
+         CheckConsistency();
+#endif
       }
    }
 
-   DataRow FindRow(int tag)
+   DataRow FindRow(int64 tag)
    {
       if(this)
       {
@@ -1448,11 +1581,10 @@ public:
       return null;
    }
 
-   DataRow FindString(char * searchedString)
+   DataRow FindString(const char * searchedString)
    {
       DataField field;
       bool checkNextField = true;
-      int len = searchedString ? strlen(searchedString) : 0;
 
       for(field = fields.first; field; field = field.next)
       {
@@ -1466,7 +1598,7 @@ public:
                   void * data = row.GetData(field);
                   char tempString[1024] = "";
                   bool needClass = false;
-                  char * string = (char *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString](field.dataType, data, tempString, null, &needClass);
+                  const char * string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
 
                   if(string && string[0])
                      checkNextField = false;
@@ -1480,7 +1612,7 @@ public:
       return null;
    }
 
-   DataRow FindSubString(char * subString)
+   DataRow FindSubString(const char * subString)
    {
       DataField field;
       bool checkNextField = true;
@@ -1500,7 +1632,7 @@ public:
                      void * data = row.GetData(field);
                      char tempString[1024] = "";
                      bool needClass = false;
-                     char * string = (char *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString](field.dataType, data, tempString, null, &needClass);
+                     const char * string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
 
                      if(string && string[0])
                         checkNextField = false;
@@ -1515,13 +1647,13 @@ public:
       return null;
    }
 
-   DataRow FindSubStringi(char * subString)
+   DataRow FindSubStringi(const char * subString)
    {
       DataField field;
       bool checkNextField = true;
       int len = subString ? strlen(subString) : 0;
       DataRow result = null;
-      char * bestResult = null;
+      const char * bestResult = null;
       int bestLen = 0;
 
       if(len)
@@ -1538,7 +1670,7 @@ public:
                      void * data = row.GetData(field);
                      char tempString[1024] = "";
                      bool needClass = false;
-                     char * string = (char *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString](field.dataType, data, tempString, null, &needClass);
+                     const char * string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
 
                      if(string && string[0])
                         checkNextField = false;
@@ -1567,7 +1699,7 @@ public:
       return result;
    }
 
-   DataRow FindSubStringAfter(DataRow after, char * subString)
+   DataRow FindSubStringAfter(DataRow after, const char * subString)
    {
       DataField field;
       bool checkNextField = true;
@@ -1587,7 +1719,7 @@ public:
                      void * data = row.GetData(field);
                      char tempString[1024] = "";
                      bool needClass = false;
-                     char * string = (char *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString](field.dataType, data, tempString, null, &needClass);
+                     const char * string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass);
 
                      if(string && string[0])
                         checkNextField = false;
@@ -1602,12 +1734,12 @@ public:
       return null;
    }
 
-   DataRow FindSubRow(int tag)
+   DataRow FindSubRow(int64 tag)
    {
       if(this)
       {
          DataRow row = null;
-      
+
          for(row = rows.first; row; row = row.next)
          {
             if(!row.noneRow && row.tag == tag)
@@ -1632,10 +1764,10 @@ public:
 
          HideEditBox(false, true, false);
          editData.Destroy(0);
-               
+
          firstRowShown = currentRow = null;
          ClearEx();
-     
+
          if(master)
          {
             if(style.freeSelect)
@@ -1647,12 +1779,12 @@ public:
          if(style.alwaysEdit && currentRow)
             currentRow.Edit(currentField);
 
-      
-         this.rowCount = 0;
-      
+
+         rowCount = 0;
+
          SetScrollArea(
-               this.width,
-               (this.rowCount * rowHeight) + 
+               width,
+               (rowCount * rowHeight) +
                ((style.header) ? rowHeight : 0) -
                ((rowHeight && !((clientSize.h+1) % rowHeight)) ? rowHeight : 0), true);
          Update(null);
@@ -1675,7 +1807,6 @@ public:
          for(search = rows.first; search; search = search.next)
             search._SortSubRows(field, order);
 
-         // TODO: Recompute row indices
          {
             int index = 0;
             for(search = rows.first; search; search = search.GetNextRow())
@@ -1727,17 +1858,17 @@ public:
       return (void *)currentRow.GetData(field);
    }
 
-   int GetTag()
+   int64 GetTag()
    {
-      return currentRow.tag;
+      return currentRow ? currentRow.tag : 0;
    }
 
 private:
    ListBox()
    {
       DataField defaultField { };
-      rows.offset = (uint)&((DataRow)0).prev;
-      fields.offset = (uint)&((DataField)0).prev;
+      rows.offset = (uint)(uintptr)&((DataRow)0).prev;
+      fields.offset = (uint)(uintptr)&((DataField)0).prev;
       style.fullRowSelect = true;
       style.fillLastField = true;
       style.expandOnAdd = true;
@@ -1776,6 +1907,7 @@ private:
    void ClearEx()
    {
       DataRow row;
+      clickedRow = null;
       while((row = rows.first))
       {
          rows.Remove(row);
@@ -1790,7 +1922,7 @@ private:
       if(*row)
       {
          if(!*field) *field = this ? currentField : null;
-         if(!*field && this) 
+         if(!*field && this)
          {
             for(*field = fields.first; (*field).index != 0; *field = (*field).next);
          }
@@ -1810,10 +1942,9 @@ private:
    {
       if(editData && editData.visible)
       {
-         Class dataType = currentField.dataType;
-         if(save) 
+         if(save)
             editData.SaveData();
-         
+
          editData.visible = false;
          NotifyEditDone(master, this, currentRow);
 
@@ -1826,7 +1957,7 @@ private:
             int height = rowHeight - (style.alwaysEdit ? 1 : 0);
             int y = currentRow.index * rowHeight + (style.header ? rowHeight : 0);
             int x = currentField.x;
-            int width = (!currentField.next && style.fillLastField && (!hasHorzScroll || clientSize.w - currentField.x > currentField.width + EXTRA_SPACE)) ? 
+            int width = (!currentField.next && style.fillLastField && (!hasHorzScroll || clientSize.w - currentField.x > currentField.width + EXTRA_SPACE)) ?
                   clientSize.w - currentField.x : (currentField.width + EXTRA_SPACE);
 
             if(!style.alwaysEdit)
@@ -1845,9 +1976,7 @@ private:
             */
             PopupEditBox(currentField, repositionOnly);
          }
-         else
-            printf("");
-            
+
          /*else
             currentField = null;*/
       }
@@ -1855,7 +1984,7 @@ private:
 
    void SetCurrentRow(DataRow row, bool notify)
    {
-      if(currentRow != row || (currentRow && currentRow.selectedFlag == unselected))
+      if(this && (currentRow != row || (currentRow && currentRow.selectedFlag == unselected)))
       {
          int headerSize = ((style.header) ? rowHeight : 0);
          int height = clientSize.h + 1 - headerSize;
@@ -1874,7 +2003,8 @@ private:
 
             for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
                selRow.selectedFlag = unselected;
-            currentRow.selectedFlag = selected;
+            if(currentRow)
+               currentRow.selectedFlag = selected;
 
             clickedRow = row;
          }
@@ -1909,6 +2039,38 @@ private:
       }
    }
 
+   void RepositionFieldEditor()
+   {
+      if(editData && editData.visible)
+      {
+         int height = rowHeight - (style.alwaysEdit ? 1 : 0);
+         int x = 0;
+         int y = currentRow.index * rowHeight + (style.header ? rowHeight : 0);
+         int width = 0;
+         DataField field;
+
+         if(style.collapse && !(style.treeBranch))
+            x += 15;
+         for(field = fields.first; field; field = field.next)
+         {
+            width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
+               clientSize.w - field.x : (field.width + EXTRA_SPACE);
+            if(field == currentField) break;
+            x += width;
+         }
+         if(!style.alwaysEdit)
+         {
+            editData.position = { x, y - editData.clientStart.y };
+            editData.size = { width, height + editData.clientStart.y * 2 };
+         }
+         else
+         {
+            editData.position = { x, y };
+            editData.size = { width, height };
+         }
+      }
+   }
+
    void PopupEditBox(DataField whichField, bool repositionOnly)
    {
       if((!editData || !editData.visible || currentField != whichField) && currentRow)
@@ -1920,7 +2082,7 @@ private:
             int height = rowHeight - (style.alwaysEdit ? 1 : 0);
             int x = 0;
             int y = currentRow.index * rowHeight + (style.header ? rowHeight : 0);
-            int width;
+            int width = 0;
             //void * data = currentRow.GetData(whichField);
             DataField field;
             DataRow row = null;
@@ -1931,7 +2093,7 @@ private:
 
             for(field = fields.first; field; field = field.next)
             {
-               width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+               width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
                   clientSize.w - field.x : (field.width + EXTRA_SPACE);
                if(field == whichField) break;
                x += width;
@@ -1948,7 +2110,7 @@ private:
                   background = dataBoxBackground;
                   foreground = dataBoxForeground;
 
-                  bool NotifyChanged(bool closingDropDown)
+                  bool NotifyChanged(DataBox dataBox, bool closingDropDown)
                   {
                      DataRow row = null;
                      DataField field = null;
@@ -1980,7 +2142,7 @@ private:
                      bool result = DataBox::OnKeyDown(key, ch);
                      if(visible && active)   // Added this check here, because we will not use enter/escape otherwise, and lose DataBox's result
                      {
-                        if((SmartKey)key == enter || (SmartKey)key == escape) 
+                        if((SmartKey)key == enter || (SmartKey)key == escape)
                            return true;
                      }
                      return result;
@@ -2045,14 +2207,14 @@ private:
          DataField field;
 
          // Fill out indent column
-         if(style.collapse && !(style.treeBranch) && rows.first)
+         if(style.collapse && !(style.treeBranch) && (style.header || rows.first))
          {
             x += 15;
-            surface.SetBackground(activeBorder);
+            surface.SetBackground(formColor);
             surface.Area(-scroll.x, 0, x, clientSize.h);
          }
 
-         surface.SetForeground(activeBorder);
+         surface.SetForeground(formColor);
          for(row = firstRowShown; row; row = row.GetNextRow())
          {
             y += rowHeight;
@@ -2064,9 +2226,9 @@ private:
          // Vertical lines
          for(field = fields.first; field; field = field.next)
          {
-            int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+            int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
                clientSize.w - field.x : (field.width + EXTRA_SPACE);
-            if(field.prev)
+            if(field.prev && y > 0)
                surface.VLine(0, y-1, x);
             x += width;
          }
@@ -2104,7 +2266,7 @@ private:
                int y1 = y + PLUSY + 4;
                int y2;
                DataRow child;
-            
+
                for(child = row.collapsed ? null : row.subRows.first; child && child != row; )
                {
                   numRows++;
@@ -2177,11 +2339,12 @@ private:
          int indent = 0;
          DataRow parent;
          Bitmap icon = row.icon ? row.icon.bitmap : null;
-         int collapseRowStart;
+         int collapseRowStart = 0;
+         bool lastWasHeader = row.header;
 
          for(parent = row.parent; parent; parent = parent.parent)
          {
-            if(!parent.header)
+            if(!parent.header || lastWasHeader)
             {
                if(style.treeBranch)
                   indent += 20;
@@ -2237,8 +2400,12 @@ private:
          // Draw the current row background
          if(row.header)
          {
-            background = activeBorder;
-            surface.SetBackground(activeBorder);
+            Color colors[] = { formColor, azure, mistyRose, linen, floralWhite, lavender, lavenderBlush, lemonChiffon };
+            int level = 0;
+            DataRow p = row;
+            while((p = p.parent)) level++;
+            background = colors[level % (sizeof(colors)/sizeof(colors[0]))];
+            surface.SetBackground(background);
             surface.Area(rowStart, y, clientSize.w, (y + rowHeight) - 1);
             foreground = branchesColor;
          }
@@ -2247,7 +2414,7 @@ private:
             if(dataDisplayFlags.selected && (isActive || style.alwaysHL || (style.alwaysEdit && style.fullRowSelect)))
             {
                if(!isActive && style.alwaysEdit)
-                  background = activeBorder;
+                  background = formColor;
                else
                   background = selectionColor ? selectionColor : SELECTION_COLOR;
                if(style.fullRowSelect)
@@ -2285,15 +2452,16 @@ private:
             surface.SetForeground(foreground);
             surface.SetBackground(background);
 
-            class(String)._vTbl[__ecereVMethodID_class_OnDisplay](class(String), "(none)", surface, x, y - 1 + (rowHeight - fontH)/2, width - EXTRA_SPACE/2, null, Alignment::left, dataDisplayFlags);
+            ((void (*)(void *, const void *, void *, int, int, int, void *, uint, uint))(void *)class(String)._vTbl[__ecereVMethodID_class_OnDisplay])(class(String), "(none)", surface, x, y - 1 + (rowHeight - fontH)/2, width - EXTRA_SPACE/2, null, Alignment::left, dataDisplayFlags);
          }
          else
          {
+            if(opacity < 1) surface.TextOpacity(false);
             // Draw the rows
             for(field = fields.first; field; field = field.next)
             {
                uint index;
-               int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+               int width = ((!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) || row.header) ?
                   clientSize.w - field.x : (field.width + EXTRA_SPACE);
 
                // Box clip = { x, y+1, x + field.width - EXTRA_SPACE - 1, y + rowHeight - 2 };
@@ -2312,7 +2480,7 @@ private:
                   foreground = this.foreground;
                }
 
-               if(!isActive && dataDisplayFlags.selected && style.alwaysEdit && field.editable)
+               if(!isActive && dataDisplayFlags.selected && style.alwaysEdit && field.editable && opacity)
                {
                   surface.Clip(null);
                   surface.SetBackground(background);
@@ -2338,20 +2506,24 @@ private:
                   surface.SetBackground(background);
 
                   if(field.dataType.type == noHeadClass || field.dataType.type == normalClass)
-                     field.dataType._vTbl[__ecereVMethodID_class_OnDisplay](field.dataType, cell.data[0], surface, x, y - 1 + (rowHeight - fontH)/2, width - EXTRA_SPACE/2, field.userData, field.alignment, dataDisplayFlags);
+                     ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnDisplay])(field.dataType, cell.data[0], surface, x, y - 1 + (rowHeight - fontH)/2, width - EXTRA_SPACE/2, field.userData, field.alignment, dataDisplayFlags);
                   else
-                     field.dataType._vTbl[__ecereVMethodID_class_OnDisplay](field.dataType, cell.data, surface, x, y - 1 + (rowHeight - fontH)/2, width - EXTRA_SPACE/2, field.userData, field.alignment, dataDisplayFlags);
+                     ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnDisplay])(field.dataType, cell.data, surface, x, y - 1 + (rowHeight - fontH)/2, width - EXTRA_SPACE/2, field.userData, field.alignment, dataDisplayFlags);
                }
 
                if(!isActive && dataDisplayFlags.selected && style.alwaysEdit && field.editable)
-                  background = activeBorder;
+                  background = formColor;
 
                if(!dataDisplayFlags.firstField && !dataDisplayFlags.fullRow)
                {
-                  background = activeBorder;
+                  background = formColor;
                   foreground = this.background;
                }
 
+#ifdef _DEBUG
+               // surface.WriteTextf(x + 100, y,  "ix: %d", row.index);
+#endif
+
                x += width;// + EXTRA_SPACE;
 
                if(row.header) break;
@@ -2367,7 +2539,7 @@ private:
                surface.SetForeground(row.header ? headerCollapseForeground : this.foreground);
                surface.Rectangle(collapseRowStart + 3 + plusIndent, y + PLUSY, collapseRowStart + 11 + plusIndent, y + PLUSY + 8);
 
-               surface.SetBackground(row.header ? (activeBorder) : (this.background)); //white
+               surface.SetBackground(row.header ? (formColor) : (this.background)); //white
                surface.Area(collapseRowStart + 4 + plusIndent, y + PLUSY + 1, collapseRowStart + 10 + plusIndent, y + PLUSY + 7);
 
                surface.HLine(collapseRowStart + 5 + plusIndent, collapseRowStart + 9 + plusIndent, y+PLUSY+4);
@@ -2400,17 +2572,17 @@ private:
             break;
       }
       if(firstRowShown) surface.Clip(null);
-      if(this.dragRow && this.dropIndex != -1)
+      if(dragRow && dropIndex != -1)
       {
-         int dropIndex = this.dropIndex;
+         int ix = dropIndex;
          int y;
 
-         if(!style.multiSelect && currentRow.index < this.dropIndex)
-            dropIndex++;
+         if(!style.multiSelect && currentRow.index < dropIndex)
+            ix++;
          surface.DrawingChar(223);
 
          y = style.header ? rowHeight : 0;
-         y += dropIndex * rowHeight - scroll.y;
+         y += ix * rowHeight - scroll.y;
 
          surface.SetForeground(Color { 85, 85, 255 });
          surface.HLine(0, clientSize.w-1, y);
@@ -2420,11 +2592,11 @@ private:
 
    void OnDrawOverChildren(Surface surface)
    {
-      if(draggingField && this.dropField)
+      if(draggingField && dropField)
       {
-         int position = this.dropField.x;
+         int position = dropField.x;
          if(draggingField.x < position)
-            position += this.dropField.width + EXTRA_SPACE;
+            position += dropField.width + EXTRA_SPACE;
 
          surface.SetForeground(Color { 85, 85, 255 });
          surface.VLine(0, rowHeight - 1, position - scroll.x - 2);
@@ -2433,7 +2605,7 @@ private:
       if(sortField && !style.clearHeader && style.header)
       {
          DataField field = sortField;
-         int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+         int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
             clientSize.w - field.x : (field.width + EXTRA_SPACE);
          int tw = 0, th = 0;
          if(field.header)
@@ -2442,9 +2614,9 @@ private:
          {
             bool up = field.sortOrder == 1;
             int x = 4, y = 4;
-            Box clip = 
-            { 
-               field.x + 2 - scroll.x, 0, 
+            Box clip =
+            {
+               field.x + 2 - scroll.x, 0,
                field.x + width + EXTRA_SPACE - 1 - scroll.x, rowHeight
             };
             surface.Clip(&clip);
@@ -2454,12 +2626,12 @@ private:
                   x = field.x + (width + EXTRA_SPACE - tw) / 2 + tw + EXTRA_SPACE + 4;
                else
                   x = field.x + tw + EXTRA_SPACE + 4;
-             
+
                x = Min(x, field.x + width - 4);
             }
             else if(field.alignment == right)
             {
-               x = field.x + width - tw - EXTRA_SPACE - 4;
+               x = field.x + width - tw - 2*EXTRA_SPACE - 4;
                x = Max(x, field.x + 2);
             }
             x -= scroll.x;
@@ -2478,7 +2650,7 @@ private:
                   surface.PutPixel(x + 1, y + 5);
                   surface.PutPixel(x + 1, y + 3);
                   surface.PutPixel(x + 2, y + 1);
-            
+
                   surface.SetForeground(white);
                   surface.DrawLine(x + 4, y, x + 7, y + 5);
                   surface.PutPixel(x + 6, y + 5);
@@ -2494,7 +2666,7 @@ private:
                   surface.PutPixel(x + 1, y+1);
                   surface.PutPixel(x + 1, y+3);
                   surface.PutPixel(x + 2, y+5);
-            
+
                   surface.SetForeground(white);
                   surface.DrawLine(x + 4, y+6, x + 7, y+1);
                   surface.PutPixel(x + 6, y+1);
@@ -2527,13 +2699,13 @@ private:
 
       SetScrollArea(
          width,
-         (rowCount * rowHeight) + 
+         (rowCount * rowHeight) +
          ((style.header) ? rowHeight : 0) -
          ((!((clientSize.h+1) % rowHeight)) ? rowHeight : 0), true);
 
       for(field = fields.first; field; field = field.next)
       {
-         int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+         int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
             clientSize.w - field.x : (field.width + EXTRA_SPACE);
          if(style.header && field.headButton)
          {
@@ -2562,6 +2734,8 @@ private:
       {
          HideEditBox(true, false, true);
       }
+      else if(editData && editData.visible)
+         RepositionFieldEditor();
    }
 
    void AdaptToFieldWidth(DataField field, bool doScroll)
@@ -2585,11 +2759,11 @@ private:
 
    bool HeaderPushed(Button control, int x, int y, Modifiers mods)
    {
-      DataField field = (DataField)control.id;
+      DataField field = (DataField)(intptr)control.id;
       // false: dont destroy edit box
       HideEditBox(true, false, true);
       if(style.resizable && ((!field && x < RESIZE_BORDER && fields.last) ||
-         (field && x < RESIZE_BORDER && field.prev) || 
+         (field && x < RESIZE_BORDER && field.prev) ||
          (field && x >= control.clientSize.w - RESIZE_BORDER)))
       {
          if(!field)
@@ -2597,14 +2771,16 @@ private:
          else if(x < RESIZE_BORDER && field.prev)
             field = field.prev;
 
+         if(field.fixed) return false;
          resizingField = field;
-         this.resizeX = x + control.position.x;
-         this.startWidth = field.width;
-         this.oldX = x - scroll.x;
+         resizeX = x + control.position.x;
+         startWidth = field.width;
+         oldX = x - scroll.x;
          return false;
       }
       else if(field)
       {
+         if(field.fixed) return false;
          draggingField = field;
          if(style.moveFields)
             field.headButton.stayDown = true;
@@ -2626,15 +2802,15 @@ private:
          x += control.position.x;
 
          // Tweak to prevent shrinking field if we're actually moving right
-         if(x - scroll.x > this.oldX && 
-            this.startWidth + x - this.resizeX < field.width)
+         if(x - scroll.x > oldX &&
+            startWidth + x - resizeX < field.width)
          {
-            this.oldX = x - scroll.x;
+            oldX = x - scroll.x;
             return true;
          }
-         this.oldX = x - scroll.x;
+         oldX = x - scroll.x;
 
-         field.width = this.startWidth + x - this.resizeX;
+         field.width = startWidth + x - resizeX;
          field.width = Max(field.width, - EXTRA_SPACE);
 
          AdaptToFieldWidth(field, true);
@@ -2648,9 +2824,9 @@ private:
             int fieldX = 0;
             for(field = fields.first; field; field = field.next)
             {
-               fieldX += ((field.width || style.resizable) ? 
+               fieldX += ((field.width || style.resizable) ?
                   field.width : clientSize.w) + EXTRA_SPACE;
-               if(fieldX > x) 
+               if(fieldX > x)
                   break;
             }
             if(draggingField == field)
@@ -2660,7 +2836,7 @@ private:
                        field.x >= field.x + field.width + EXTRA_SPACE - clientSize.w)
                {
                   SetScrollPosition(
-                     field.x + field.width + EXTRA_SPACE - clientSize.w, 
+                     field.x + field.width + EXTRA_SPACE - clientSize.w,
                      scroll.y);
                }
                else if(field.x + field.width + EXTRA_SPACE - clientSize.w > scroll.x ||
@@ -2668,9 +2844,9 @@ private:
                   SetScrollPosition(field.x, scroll.y);
                field = null;
             }
-            if(this.dropField != field)
+            if(dropField != field)
             {
-               this.dropField = field;
+               dropField = field;
                if(field)
                {
                   int position = field.x;
@@ -2688,7 +2864,7 @@ private:
                         SetScrollPosition(position, scroll.y);
                   }
 
-                  this.movingFields = true;
+                  movingFields = true;
                }
                Update(null);
             }
@@ -2696,11 +2872,14 @@ private:
       }
       else if(style.resizable)
       {
-         DataField field = (DataField)control.id;
+         DataField field = (DataField)(intptr)control.id;
          if(field)
          {
             if(x < RESIZE_BORDER && field.prev)
-               control.cursor = guiApp.GetCursor(sizeWE);
+            {
+               if(!field.prev.fixed)
+                  control.cursor = guiApp.GetCursor(sizeWE);
+            }
             else if(x >= control.clientSize.w - RESIZE_BORDER)
                control.cursor = guiApp.GetCursor(sizeWE);
             else
@@ -2728,7 +2907,7 @@ private:
       if(draggingField)
       {
          bool result = true;
-         
+
          if(style.moveFields)
          {
             if(dropField)
@@ -2741,15 +2920,15 @@ private:
                x += draggingField.x;
                for(field = fields.first; field; field = field.next)
                {
-                  fieldX += ((field.width || style.resizable) ? 
+                  fieldX += ((field.width || style.resizable) ?
                      field.width : clientSize.w) + EXTRA_SPACE;
-                  if(fieldX > x) 
+                  if(fieldX > x)
                   {
                      switchField = field;
                      break;
                   }
                }
-               if(switchField && draggingField != switchField && this.dropField)
+               if(switchField && draggingField != switchField && dropField)
                {
                   for(field = fields.first; field; field = field.next)
                   {
@@ -2781,9 +2960,9 @@ private:
 
    bool HeaderClicked(Button control, int x, int y, Modifiers mods)
    {
-      if(style.header && !this.dropField && style.sortable)
+      if(style.header && !dropField && style.sortable)
       {
-         DataField field = (DataField)control.id;
+         DataField field = (DataField)(intptr)control.id;
          if(sortField == field)
             field.sortOrder *= -1;
          else
@@ -2797,6 +2976,32 @@ private:
       return true;
    }
 
+   bool HeaderDoubleClicked(Button control, int x, int y, Modifiers mods)
+   {
+      if(style.resizable)
+      {
+         DataField field = (DataField)(intptr)control.id;
+         if(field)
+         {
+            if(x < RESIZE_BORDER && field.prev)
+               field = field.prev;
+            else if(x >= control.clientSize.w - RESIZE_BORDER);
+            else
+               field = null;
+         }
+         else
+         {
+            if(x < RESIZE_BORDER && fields.last)
+               field = fields.last;
+            else
+               field = null;
+         }
+         if(field)
+            field.AutoSize();
+      }
+      return false;
+   }
+
    watch(visible)
    {
       if(style.freeSelect)
@@ -2804,7 +3009,7 @@ private:
          if(!visible)
          {
             ReleaseCapture();
-            this.rolledOver = this.dragging = false;
+            rolledOver = dragging = false;
          }
          /*else
             Capture();*/
@@ -2813,7 +3018,7 @@ private:
 
    bool OnLoadGraphics()
    {
-      display.FontExtent(fontObject, "W", 1, null, &fontH); 
+      display.FontExtent(fontObject, "W", 1, null, &fontH);
       if(!style.heightSet)
       {
          rowHeight = Max(fontH + 2, 16) + (style.alwaysEdit ? 1 : 0);
@@ -2845,7 +3050,7 @@ private:
    {
       if(rows.first)
       {
-         if(!initSize.w && (!anchor.left.type || !anchor.right.type) /**w*/)
+         if(!initSize.w && (!anchor.left.type || !anchor.right.type) && !*w)
          {
             // Use widest item
             DataRow row;
@@ -2853,7 +3058,7 @@ private:
             Font font = fontObject;
             Font boldFont = this.boldFont.font;
             Display display = this.display;
-            
+
             for(row = rows.first; row; row = row.GetNextRow())
             {
                Bitmap icon = row.icon ? row.icon.bitmap : null;
@@ -2891,14 +3096,13 @@ private:
                      // Should always be as many cells in the row as fields in the listbox
                      if(cell && cell.isSet && field.dataType)
                      {
-                        Bitmap icon = null;
-                        char tempString[1024];
-                        char * string;
+                        static char tempString[4096];
+                        const char * string;
                         int tw, th;
-                        if(field.dataType.type == normalClass || field.dataType.type == noHeadClass)
-                           string = (char *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString](field.dataType, cell.data[0], tempString, field.userData, null);
+                        if(field.dataType.type == normalClass || field.dataType.type == noHeadClass)
+                           string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, cell.data[0], tempString, field.userData, null);
                         else
-                           string = (char *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString](field.dataType, cell.data, tempString, field.userData, null);
+                           string = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, cell.data, tempString, field.userData, null);
                         /* GCC-4.4 Bug!
                        if(!string) string = "";
                         display.FontExtent(row.header ? boldFont : font, string, strlen(string), &tw, &th);
@@ -2919,7 +3123,7 @@ private:
          }
          if(!*h)
          {
-            *h = Min(this.maxShown, this.rowCount) * rowHeight;
+            *h = Min(maxShown, rowCount) * rowHeight;
          }
       }
       else
@@ -2958,7 +3162,7 @@ private:
       {
         // Resize left
          DataField field = resizingField;
-         field.width = this.startWidth + x - this.resizeX;
+         field.width = startWidth + x - resizeX;
          field.width = Max(field.width, - EXTRA_SPACE);
 
          AdaptToFieldWidth(field, true);
@@ -2975,7 +3179,7 @@ private:
 
          for(field = fields.first; field; field = field.next)
          {
-            int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+            int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
                clientSize.w - field.x : (field.width + EXTRA_SPACE);
 
             if(field.prev)
@@ -2992,37 +3196,37 @@ private:
 
       if((editData && editData.visible) || (style.alwaysEdit))
          return true;
-      
+
       if(x == MAXINT && y == MAXINT)
       {
-         x = this.mouseX;
-         y = this.mouseY;
+         x = mouseX;
+         y = mouseY;
          isTimer = true;
       }
 
       // ADDED THIS CHECK FOR FieldDropBox LEAKS
-      if(/*!mods.isSideEffect && */(this.rolledOver || !this.dragging))
+      if(/*!mods.isSideEffect && */(rolledOver || !dragging))
       {
          int rowY = (style.header) ? rowHeight : 0;
-         DataRow row = null;
+         DataRow row = null, nextRow;
          int rowIndex;
 
          mouseX = x;
          mouseY = y;
 
-         if(this.dragging &&
-            ((vertScroll && vertScroll.visible && 
+         if(dragging &&
+            ((vertScroll && vertScroll.visible &&
              (y < 0 || y >= clientSize.h)) ||
-             (horzScroll && horzScroll.visible && 
+             (horzScroll && horzScroll.visible &&
              (x < 0 || x >= clientSize.w))))
          {
             timer.Start();
             if(isTimer)
             {
-               if(vertScroll && vertScroll.visible && 
+               if(vertScroll && vertScroll.visible &&
                   (y < 0 || y >= clientSize.h))
                   vertScroll.Action((y<0)?up:down, 0, 0);
-               if(horzScroll && horzScroll.visible && 
+               if(horzScroll && horzScroll.visible &&
                   (x < 0 || x >= clientSize.w))
                   horzScroll.Action((x<0)?up:down, 0, 0);
             }
@@ -3033,19 +3237,29 @@ private:
          // This must be done after the scrolling took place
          rowIndex = firstRowShown ? firstRowShown.index : -1;
          y = Max(y, 0);
-         y = Min(y, clientSize.h-1);
-         for(row = firstRowShown; row; row = row.GetNextRow(), rowIndex ++)
+         y = Min(y, clientSize.h - ((dragRow && style.moveRows) ? rowHeight : 0)-1);
+         for(row = firstRowShown; row; row = nextRow, rowIndex ++)
          {
+            nextRow = row.GetNextRow();
             rowY += rowHeight;
-            if(rowY > y)
+            if(rowY > y || !nextRow)
             {
                break;
             }
          }
 
+         if(dragRow && style.moveRows)
+         {
+            if(row && row == currentRow)
+               row = row.GetNextRow();
+
+            if(row && row.parent == currentRow)
+               row = row.GetNextRow();
+         }
+
          if(row && currentRow != row)
          {
-            if(this.dragRow && style.moveRows)
+            if(dragRow && style.moveRows)
             {
                if(row.selectedFlag == selected || row.selectedFlag == tempSelected)
                   rowIndex = -1;
@@ -3053,21 +3267,21 @@ private:
                {
                   DataRow thisRow;
                   for(thisRow = rows.first; thisRow; thisRow = thisRow.GetNextRow())
-                     if((thisRow.selectedFlag == selected || thisRow.selectedFlag == tempSelected) || 
+                     if((thisRow.selectedFlag == selected || thisRow.selectedFlag == tempSelected) ||
                         thisRow == row)
                         break;
                   if(thisRow != row)
                      rowIndex++;
                }
-               if(this.dropIndex != rowIndex)
+               if(dropIndex != rowIndex)
                {
-                  this.dropIndex = rowIndex;
-                  this.editRow = null;
+                  dropIndex = rowIndex;
+                  editRow = null;
                   Update(null);
-                  this.movedRow = true;
+                  movedRow = true;
                }
             }
-            else if((style.freeSelect  || this.dragging) && ((realX>= 0 && realY >= 0 && realX< clientSize.w && realY < clientSize.h) || this.rolledOver))
+            else if((style.freeSelect  || dragging) && ((realX>= 0 && realY >= 0 && realX< clientSize.w && realY < clientSize.h) || rolledOver))
             {
                if(!(style.multiSelect))
                {
@@ -3125,8 +3339,8 @@ private:
 
    bool OnMouseOver(int x, int y, Modifiers mods)
    {
-      if(this.dragging)
-         this.rolledOver = true;
+      if(dragging)
+         rolledOver = true;
       return true;
    }
 
@@ -3167,7 +3381,7 @@ private:
 
          for(field = fields.first; field; field = field.next)
          {
-            int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+            int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
                clientSize.w - field.x : (field.width + EXTRA_SPACE);
 
             if(field.prev)
@@ -3175,8 +3389,8 @@ private:
                if(Abs(x - vx) < 2)
                {
                   resizingField = field.prev;
-                  this.resizeX = x;
-                  this.startWidth = resizingField.width;
+                  resizeX = x;
+                  startWidth = resizingField.width;
                   Capture();
                   SetMouseRangeToClient();
                   break;
@@ -3193,7 +3407,6 @@ private:
          int rowIndex = firstRowShown ? firstRowShown.index : -1;
          DataRow previousRow = currentRow;
          DataRow newCurrentRow = null;
-         DataField newCurrentField = null;
          bool moveMultiple = false;
          int numSelected = 0;
          int rowStart = -scroll.x;
@@ -3221,7 +3434,7 @@ private:
          for(row = firstRowShown; row; row = row.GetNextRow(), rowIndex ++)
          {
             rowY += rowHeight;
-            if(rowY > y || (style.multiSelect && !row.GetNextRow())) 
+            if(rowY > y || (style.multiSelect && !row.GetNextRow()))
             {
                int plusIndent = 0;
                if(style.treeBranch)
@@ -3237,7 +3450,7 @@ private:
                if(style.collapse && row.subRows.first && (row.parent || !(style.treeBranch) || (style.rootCollapse)) &&
                   (x >= rowStart + 3 + plusIndent && y >= rowY - rowHeight + PLUSY && x <= rowStart + 11 + plusIndent && y <= rowY - rowHeight + PLUSY + 8))
                */
-               if(style.collapse && 
+               if(style.collapse &&
                   (x >= rowStart && y >= rowY - rowHeight && x <= rowStart + 18 + plusIndent && y <= rowY + rowHeight-1))
                {
                   if(row.subRows.first && (row.parent || !(style.treeBranch) || (style.rootCollapse)) && x >= plusIndent)
@@ -3259,9 +3472,9 @@ private:
                         for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
                            selRow.selectedFlag = unselected;
                         clickedRow = row;
-                        //this.clickedRowIndex = rowIndex;
+                        //clickedRowIndex = rowIndex;
                      }
-                     else if(style.moveRows && !(mods.shift) && 
+                     else if(style.moveRows && !(mods.shift) &&
                         (row.selectedFlag == selected || row.selectedFlag == tempSelected) &&
                         !right && !(mods.isActivate))
                         moveMultiple = true;
@@ -3277,7 +3490,7 @@ private:
                               row.selectedFlag = selected;
                            }
                            clickedRow = row;
-                           //this.clickedRowIndex = rowIndex;
+                           //clickedRowIndex = rowIndex;
                         }
                         else
                         {
@@ -3308,7 +3521,7 @@ private:
                                     {
                                        if(selRow != clickedRow)
                                        {
-                                          if(selRow.selectedFlag) 
+                                          if(selRow.selectedFlag)
                                              selRow.selectedFlag = tempUnselected;
                                           else
                                              selRow.selectedFlag = tempSelected;
@@ -3352,7 +3565,7 @@ private:
                               else
                                  row.selectedFlag = tempSelected;
                               clickedRow = row;
-                              //this.clickedRowIndex = rowIndex;
+                              //clickedRowIndex = rowIndex;
                            }
                         }
                      }
@@ -3433,7 +3646,7 @@ private:
 
          if(style.freeSelect)
             NotifyHighlight(master, this, currentRow, mods);
-         else if((moveMultiple || (!(style.multiSelect) && previousRow == currentRow)) && 
+         else if((moveMultiple || (!(style.multiSelect) && previousRow == currentRow)) &&
             newCurrentRow && !(mods.shift))
          {
             if(!right)
@@ -3442,9 +3655,11 @@ private:
                {
                   if(style.moveRows)
                   {
-                     this.dragRow = currentRow;
-                     this.dropIndex = -1;
-                     this.movedRow = false;
+                     dragRow = currentRow;
+                     dropIndex = -1;
+                     movedRow = false;
+
+                     Capture();
                   }
                   if(editData && editData.visible && style.alwaysEdit)
                   {
@@ -3463,24 +3678,24 @@ private:
 
                      for(field = fields.first; field; field = field.next)
                      {
-                        int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+                        int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
                            clientSize.w - field.x : (field.width + EXTRA_SPACE);
 
                         if(!field.prev) width -= indent;
                         if(x >= sx && x < sx + width)
-                           break;                     
+                           break;
                         sx += width;
                      }
                      if(field == currentField)
                         editData.Deactivate();
                      else
                      {
-                        currentRow.Edit(field);                     
+                        currentRow.Edit(field);
                         editData.Activate();
                      }
                   }
                   else if(!(mods.ctrl) && numSelected <= 1)
-                     this.editRow = currentRow;
+                     editRow = currentRow;
 
                   if(style.noDragging && newCurrentRow)
                     NotifyReclick(master, this, newCurrentRow, mods);
@@ -3491,14 +3706,12 @@ private:
                   // activate it
                   if(editData && editData.visible && newCurrentRow)
                   {
-                     DataField field, whichField;
+                     DataField field;
                      int sx = -scroll.x;
                      int indent = 0;
 
                      if(style.collapse && !(style.treeBranch))
                         sx += 15;
-                  
-                     whichField = currentField;
 
                      {
                         DataRow parent;
@@ -3510,7 +3723,7 @@ private:
 
                      for(field = fields.first; field; field = field.next)
                      {
-                        int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+                        int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
                            clientSize.w - field.x : (field.width + EXTRA_SPACE);
                         if(!field.prev) width -= indent;
                         if(x >= sx && x < sx + width && newCurrentRow)
@@ -3535,8 +3748,7 @@ private:
          }
          else
          {
-            result = NotifySelect(master, this, 
-               currentRow ? currentRow : null, mods);
+            DataField f = null;
             if(result && style.alwaysEdit && currentRow)
             {
                if(newCurrentRow)
@@ -3556,19 +3768,25 @@ private:
 
                   for(field = fields.first; field; field = field.next)
                   {
-                     int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+                     int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
                         clientSize.w - field.x : (field.width + EXTRA_SPACE);
 
                      if(!field.prev) width -= indent;
                      if(x >= sx && x < sx + width)
                      {
-                        currentField = field;
+                        f = currentField = field;
                         break;
                      }
                      sx += width;
                   }
                }
-               currentRow.Edit(currentField);
+            }
+            // Moved NotifySelect after setting currentField for the NotifySelect implementation to be aware of which field is now selected (e.g. WatchesView)
+            result = NotifySelect(master, this, currentRow, mods);
+            if(result && style.alwaysEdit && currentRow)
+            {
+               // In case the user specifically clicked on a field (f is set), override any change to currentField that NotifySelect could have done
+               currentRow.Edit(f ? f : currentField);
 
                // If the user clicked exactly on the edited field,
                // activate it
@@ -3604,16 +3822,16 @@ private:
       {
          if(!style.noDragging)
          {
-            this.dragging = true;
+            dragging = true;
             Capture();
          }
          if(x >= 0 && y >= 0 && x < clientSize.w && y < clientSize.h)
-            this.rolledOver = true;
+            rolledOver = true;
          Update(null);
       }
       else
       {
-         this.dragging = false;
+         dragging = false;
          OnLeftButtonUp(x, y, mods);
       }
       return result;
@@ -3637,30 +3855,31 @@ private:
       {
          DataRow row, switchRow = rows.last;
          int rowY = (style.header) ? rowHeight : 0;
+         while(switchRow.lastRow) switchRow = switchRow.lastRow;
          for(row = firstRowShown; row; row = row.GetNextRow())
          {
             rowY += rowHeight;
-            if(rowY > y) 
+            if(rowY > y)
             {
                switchRow = row;
                break;
             }
          }
-         if(this.editRow == switchRow && y >= 0)
+         if(editRow == switchRow && y >= 0)
          {
             // Find which field
             DataField field;
             int fieldX = 0;
             for(field = fields.first; field; field = field.next)
             {
-               int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ? 
+               int width = (!field.next && style.fillLastField && (!hasHorzScroll || clientSize.w - field.x > field.width + EXTRA_SPACE)) ?
                   clientSize.w - field.x : (field.width + EXTRA_SPACE);
                fieldX += width;
 
-               if(fieldX > x + scroll.x) 
+               if(fieldX > x + scroll.x)
                   break;
             }
-            
+
             if(field && field.editable)
             {
                // true: destroy edit box
@@ -3672,9 +3891,9 @@ private:
          }
          else if(style.moveRows && switchRow)
          {
-            if(this.dragRow == switchRow && this.movedRow == false)
+            if(dragRow == switchRow && movedRow == false)
             {
-               DataRow row = this.dragRow;
+               DataRow row = dragRow;
                DataRow selRow;
                if(!(mods.ctrl))
                {
@@ -3703,7 +3922,7 @@ private:
                clickedRow = row;
             }
             else
-            { 
+            {
                if(style.multiSelect)
                {
                   if(!switchRow.selectedFlag)
@@ -3738,25 +3957,57 @@ private:
                {
                   for(row = rows.first; row; row = row.GetNextRow())
                   {
-                     if(row == switchRow || row == this.dragRow)
+                     if(row == switchRow || row == dragRow)
                         break;
                   }
 
                   // Switch row first: move before
                   if(row == switchRow)
                   {
-                     if(NotifyMove(master, this, switchRow.prev, mods))
-                        dragRow.Move(switchRow.prev);
+                     DataRow actualMoveRow;
+
+                     if(!switchRow.prev && switchRow.parent == dragRow.parent)
+                        actualMoveRow = null;
+                     else
+                     {
+                        actualMoveRow = switchRow.prev ? switchRow.prev : switchRow;
+                        while(actualMoveRow && actualMoveRow.parent != dragRow.parent && actualMoveRow.parent)
+                           actualMoveRow = actualMoveRow.parent;
+                     }
+
+                     if(!actualMoveRow || (actualMoveRow && actualMoveRow.parent == dragRow.parent))
+                        if(NotifyMove(master, this, actualMoveRow, mods))
+                        {
+                           dragRow.Move(actualMoveRow);
+                           NotifyMoved(master, this, actualMoveRow, mods);
+                        }
                   }
                   // Dragged row first: move after
                   else
                   {
-                     if(NotifyMove(master, this, switchRow, mods))
-                        dragRow.Move(switchRow);
+                     DataRow actualMoveRow = switchRow;
+                     DataRow nextRow = switchRow.GetNextRow();
+
+                     while(nextRow && nextRow.parent != dragRow.parent)
+                        nextRow = nextRow.parent ? nextRow.parent.next : null;
+                     if(nextRow)
+                        actualMoveRow = nextRow.prev;
+
+                     if(!nextRow)
+                        actualMoveRow = dragRow.parent ? dragRow.parent.subRows.last : rows.last;
+
+                     if(!actualMoveRow || (actualMoveRow != dragRow && actualMoveRow.parent == dragRow.parent))
+                        if(NotifyMove(master, this, actualMoveRow, mods))
+                        {
+                           dragRow.Move(actualMoveRow);
+                           NotifyMoved(master, this, actualMoveRow, mods);
+                        }
                   }
                }
             }
          }
+         if(dragRow)
+            ReleaseCapture();
          dragRow = null;
          editRow = null;
          movedRow = false;
@@ -3765,11 +4016,11 @@ private:
       }
 
       timer.Stop();
-      if(this.dragging || style.freeSelect)
+      if(dragging || style.freeSelect)
       {
-         if(this.dragging)
+         if(dragging)
          {
-            this.rolledOver = this.dragging = false;
+            rolledOver = dragging = false;
          }
          if(x >= 0 && y >= 0 && x < clientSize.w && y < clientSize.h && currentRow && style.freeSelect)
          {
@@ -3808,7 +4059,7 @@ private:
       for(row = firstRowShown; row; row = row.GetNextRow())
       {
          rowY += rowHeight;
-         if(rowY > y || (style.multiSelect && !row.GetNextRow())) 
+         if(rowY > y || (style.multiSelect && !row.GetNextRow()))
          {
             if(style.treeBranch)
             {
@@ -3871,13 +4122,13 @@ private:
             bool looped = false;
             if(len == 1 && currentRow)
                startRow = (next = startRow.GetNextRow(), (next ? next : rows.first));
-        
+
             for(row = startRow; row != startRow || !looped; next = row.GetNextRow(), row = next ? next : rows.first)
             {
                void * data = row.GetData(field);
                char tempString[1024] = "";
                bool needClass = false;
-               char * string = data ? (char *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString](field.dataType, data, tempString, null, &needClass) : null;
+               const char * string = data ? ((const char *(*)(void *, void *, char *, void *, bool *))(void *)field.dataType._vTbl[__ecereVMethodID_class_OnGetString])(field.dataType, data, tempString, null, &needClass) : null;
 
                if(string && string[0])
                   checkNextField = false;
@@ -3886,16 +4137,10 @@ private:
                   if(style.multiSelect)
                   {
                      DataRow selRow;
-                     bool foundRow = false;
 
-                     //this.clickedRowIndex = 0;
                      clickedRow = row;
                      for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
-                     {
-                        if(selRow == row) foundRow = true;
                         selRow.selectedFlag = unselected;
-                        //if(!foundRow) this.clickedRowIndex++;
-                     }
                      row.selectedFlag = selected;
                   }
                   SetCurrentRow(row, true);
@@ -3905,9 +4150,9 @@ private:
                looped = true;
             }
             typingTimer.Stop();
-            if(this.typingTimeOut && !keyHit)
+            if(typingTimeOut && !keyHit)
                typingTimer.Start();
-            if(!result || !this.typingTimeOut || keyHit)
+            if(!result || !typingTimeOut || keyHit)
                typedString[len-1] = '\0';
          }
          if(!checkNextField || result) break;
@@ -3929,7 +4174,7 @@ private:
       }
       else if(key == escape)
       {
-         if(resizingField || this.movingFields || (editData && editData.visible) || this.dragRow)
+         if(resizingField || movingFields || (editData && editData.visible) || dragRow)
          {
             if(editData && editData.visible && style.alwaysEdit && !editData.active)
                return true;
@@ -3937,26 +4182,29 @@ private:
             HideEditBox(false, false, false);
             if(resizingField)
             {
-               resizingField.width = this.startWidth;
+               resizingField.width = startWidth;
                AdaptToFieldWidth(resizingField, true);
                resizingField = null;
                ReleaseCapture();
             }
-            this.dragRow = null;
-            if(this.dragging)
+            if(dragRow)
+               ReleaseCapture();
+
+            dragRow = null;
+            if(dragging)
             {
-               this.dragging = false;
+               dragging = false;
                ReleaseCapture();
             }
 
-            this.movingFields = false;
+            movingFields = false;
             draggingField = null;
             Update(null);
             return false;
-         }      
+         }
       }
 
-      if(!currentField || !currentField.editable)            
+      if(!currentField || !currentField.editable)
          for(field = fields.first; field; field = field.next)
          {
             if(field.editable)
@@ -3965,17 +4213,28 @@ private:
                break;
             }
          }
-      if(key == f2 && currentField && currentField.editable)
+      if((key == f2 || (style.alwaysEdit && (key == ctrlV || key == ctrlC || key == ctrlX || key == shiftInsert || key == ctrlInsert || key == shiftDel))) &&
+            currentField && currentField.editable)
       {
          PopupEditBox(currentField, false);
          if(editData && editData.visible)
          {
             if(style.alwaysEdit)
+            {
                editData.Activate();
+               if(key == ctrlV || key == ctrlC || key == ctrlX || key == shiftInsert || key == ctrlInsert || key == shiftDel)
+               {
+                  editData.OnKeyHit(key, ch);
+                  StopEditing(true);
+               }
+               else
+                  // For Installer to pop up file dialog
+                  NotifyKeyDown(master, this, currentRow, key, ch);
+            }
             return false;
          }
       }
+
       if(!NotifyKeyDown(master, this, currentRow, key, ch))
          return false;
 
@@ -3986,8 +4245,8 @@ private:
             return editData.OnKeyDown(key, ch);
          return true;   // We want to pick up the OnKeyHit to replace contents, but skip GoToLetter
       }
-      
-      if(ch != 128 && !key.alt && !key.ctrl && GoToLetter(ch, false))
+
+      if(ch >=32 && ch != 128 && !key.alt && !key.ctrl && GoToLetter(ch, false))
       {
          /*if(inactive && window.state != Hidden)
             NotifyHighlight(master, this, currentRow, 0);
@@ -4033,260 +4292,258 @@ private:
          }
       }
 
-      if(!(style.multiSelect) && (key.ctrl))
-         return true;
-
-      if(editData && editData.visible && ch && !key.alt && !key.ctrl && editData.active)
+      if(editData && editData.visible && ch && !key.alt && !key.ctrl && editData.active && (key.code != tab || (editData._class == class(EditBox) && ((EditBox)editData).tabKey)))
          return false;
 
-      switch(key.code)
+      if(!key.alt && (style.multiSelect || !key.ctrl))
       {
-         case left:
-            if(style.alwaysEdit)
-            {
-               if(currentField)
+         switch(key.code)
+         {
+            case left:
+               if(style.alwaysEdit)
                {
-                  DataField field;
-                  for(field = currentField.prev; field; field = field.prev)
+                  if(currentField)
                   {
-                     if(field.editable)
+                     DataField field;
+                     for(field = currentField.prev; field; field = field.prev)
                      {
-                        currentField = field;
-                        HideEditBox(true, true, false);
-                        PopupEditBox(currentField, false);
-                        return false;
-                     }                     
+                        if(field.editable)
+                        {
+                           currentField = field;
+                           HideEditBox(true, true, false);
+                           PopupEditBox(currentField, false);
+                           return false;
+                        }
+                     }
                   }
                }
-            }
-            if(style.collapse && currentRow /*&& !currentField*/)  // THIS PREVENTED COLLAPSING THE PROPERTY SHEET
-            {
-               if(currentRow.subRows.first && !currentRow.collapsed)
+               if(style.collapse && currentRow /*&& !currentField*/)  // THIS PREVENTED COLLAPSING THE PROPERTY SHEET
                {
-                  currentRow.collapsed = true;
+                  if(currentRow.subRows.first && !currentRow.collapsed)
+                  {
+                     currentRow.collapsed = true;
+                  }
+                  else if(currentRow.parent)
+                     SetCurrentRow(currentRow.parent, true);
+                  return false;
                }
-               else if(currentRow.parent)
-                  SetCurrentRow(currentRow.parent, true);
-               return false;
-            }
-            break;
-         case right:
-            if(style.collapse && currentRow && currentRow.subRows.first)
-            {
-               if(currentRow.collapsed)
-                  currentRow.collapsed = false;
-               else
-                  SetCurrentRow(currentRow.subRows.first, true);
-               return false;
-            }
-            else if(style.alwaysEdit)
-            {
-               if(currentField)
+               break;
+            case right:
+               if(style.collapse && currentRow && currentRow.subRows.first)
                {
-                  DataField field;
-                  for(field = currentField.next; field; field = field.next)
+                  if(currentRow.collapsed)
+                     currentRow.collapsed = false;
+                  else
+                     SetCurrentRow(currentRow.subRows.first, true);
+                  return false;
+               }
+               else if(style.alwaysEdit)
+               {
+                  if(currentField)
                   {
-                     if(field.editable)
+                     DataField field;
+                     for(field = currentField.next; field; field = field.next)
                      {
-                        currentField = field;
-                        HideEditBox(true, true, false);
-                        PopupEditBox(currentField, false);
-                        break;
-                     }                     
+                        if(field.editable)
+                        {
+                           currentField = field;
+                           HideEditBox(true, true, false);
+                           PopupEditBox(currentField, false);
+                           break;
+                        }
+                     }
                   }
                }
-            }
-            break;
-         case down: case up:
-         case pageDown: case pageUp:
-         case end: case home:
-         {
-            int headerSize = ((style.header) ? rowHeight : 0);
-            int height = clientSize.h + 1 - headerSize;
-            DataRow oldRow;
+               break;
+            case down: case up:
+            case pageDown: case pageUp:
+            case end: case home:
+            {
+               int headerSize = ((style.header) ? rowHeight : 0);
+               int height = clientSize.h + 1 - headerSize;
+               DataRow oldRow;
 
-            // true: destroy edit box
-            // !!! TESTING true HERE !!!
-            HideEditBox(true, true, false);
-            // HideEditBox(false, true, false);
-            
-            oldRow = currentRow;
+               // true: destroy edit box
+               // !!! TESTING true HERE !!!
+               HideEditBox(true, true, false);
+               // HideEditBox(false, true, false);
 
-            SNAPDOWN(height, rowHeight);
-            if((!currentRow || key.code == home) && key.code != end)
-            {
-               currentRow = rows.first;
-            }
-            else
-            {
-               DataRow next;
-               switch(key.code)
+               oldRow = currentRow;
+
+               SNAPDOWN(height, rowHeight);
+               if((!currentRow || key.code == home) && key.code != end)
                {
-                  case down:
-                     if(!(style.multiSelect) && currentRow && !currentRow.selectedFlag)
-                        next = currentRow;
-                     else
-                        next = currentRow.GetNextRow();
-                     if(next)
+                  currentRow = rows.first;
+               }
+               else
+               {
+                  DataRow next;
+                  switch(key.code)
+                  {
+                     case down:
+                        if(!(style.multiSelect) && currentRow && !currentRow.selectedFlag)
+                           next = currentRow;
+                        else
+                           next = currentRow.GetNextRow();
+                        if(next)
+                        {
+                           currentRow = next;
+                        }
+                        break;
+                     case up:
+                        if(!(style.multiSelect) && currentRow && !currentRow.selectedFlag)
+                           next = currentRow;
+                        else
+                           next = currentRow.GetPrevRow();
+
+                        if(next)
+                        {
+                           currentRow = next;
+                        }
+                        break;
+                     case end:
+                        currentRow = lastRow.GetLastRow();
+                        break;
+                     case pageUp:
                      {
-                        currentRow = next;
+                        int c;
+                        for(c = 0;
+                        currentRow && (next = currentRow.GetPrevRow()) && c < height / rowHeight;
+                            c++, currentRow = next);
+                        break;
                      }
-                     break;
-                  case up:
-                     if(!(style.multiSelect) && currentRow && !currentRow.selectedFlag)
-                        next = currentRow;
-                     else
-                        next = currentRow.GetPrevRow();
-
-                     if(next)
+                     case pageDown:
                      {
-                        currentRow = next;
+                        int c;
+                        for(c = 0;
+                            currentRow && (next = currentRow.GetNextRow()) && c < height / rowHeight;
+                            c++, currentRow = next);
+                        break;
                      }
-                     break;
-                  case end:
-                     // TODO: Find very last row
-                     for(currentRow = rows.last; currentRow && !currentRow.collapsed && currentRow.subRows.last;)
-                        currentRow = currentRow.subRows.last;
-                     break;
-                  case pageUp:
-                  {
-                     int c;
-                     for(c = 0;
-                     currentRow && (next = currentRow.GetPrevRow()) && c < height / rowHeight;
-                         c++, currentRow = next);
-                     break;
-                  }
-                  case pageDown:
-                  {
-                     int c;
-                     for(c = 0;
-                         currentRow && (next = currentRow.GetNextRow()) && c < height / rowHeight;
-                         c++, currentRow = next);
-                     break;
                   }
                }
-            }
-            if(currentRow && currentRow.index * rowHeight > scroll.y + height - rowHeight)
-               SetScrollPosition(scroll.x, currentRow.index * rowHeight - height + rowHeight);
-            else if(!currentRow || currentRow.index * rowHeight < scroll.y)
-               SetScrollPosition(scroll.x, currentRow ? currentRow.index * rowHeight : 0);
-
-            if(style.multiSelect)
-            {
-               DataRow selRow;
+               if(currentRow && currentRow.index * rowHeight > scroll.y + height - rowHeight)
+                  SetScrollPosition(scroll.x, currentRow.index * rowHeight - height + rowHeight);
+               else if(!currentRow || currentRow.index * rowHeight < scroll.y)
+                  SetScrollPosition(scroll.x, currentRow ? currentRow.index * rowHeight : 0);
 
-               if(!(key.shift) && (key.ctrl))
+               if(style.multiSelect)
                {
-                  DataRow row;
-                  for(row = rows.first; row; row = row.GetNextRow())
+                  DataRow selRow;
+
+                  if(!(key.shift) && (key.ctrl))
                   {
-                     if(row.selectedFlag == tempSelected)
-                        row.selectedFlag = selected;
-                     else if(row.selectedFlag == tempUnselected)
-                        row.selectedFlag = unselected;
+                     DataRow row;
+                     for(row = rows.first; row; row = row.GetNextRow())
+                     {
+                        if(row.selectedFlag == tempSelected)
+                           row.selectedFlag = selected;
+                        else if(row.selectedFlag == tempUnselected)
+                           row.selectedFlag = unselected;
+                     }
                   }
-               }
 
-               if(!(key.ctrl))
-               {
-                  for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
-                     selRow.selectedFlag = unselected;
-               }
-               else
-               {
-                  for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
+                  if(!(key.ctrl))
                   {
-                     if(selRow.selectedFlag == tempUnselected) selRow.selectedFlag = selected;
-                     else if(selRow.selectedFlag == tempSelected) selRow.selectedFlag = unselected;
+                     for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
+                        selRow.selectedFlag = unselected;
+                  }
+                  else
+                  {
+                     for(selRow = rows.first; selRow; selRow = selRow.GetNextRow())
+                     {
+                        if(selRow.selectedFlag == tempUnselected) selRow.selectedFlag = selected;
+                        else if(selRow.selectedFlag == tempSelected) selRow.selectedFlag = unselected;
+                     }
                   }
-               }
 
-               if(key.shift)
-               {
-                  if(currentRow.index >= clickedRow.index)
+                  if(key.shift)
                   {
-                     for(selRow = clickedRow; selRow; selRow = selRow.GetNextRow())
+                     if(currentRow.index >= clickedRow.index)
+                     {
+                        for(selRow = clickedRow; selRow; selRow = selRow.GetNextRow())
+                        {
+                           if(key.ctrl)
+                           {
+                              if(selRow.selectedFlag) selRow.selectedFlag = tempUnselected; else selRow.selectedFlag = tempSelected;
+                           }
+                           else
+                              selRow.selectedFlag = selected;
+                           if(selRow == currentRow)
+                              break;
+                        }
+                     }
+                     else
                      {
-                        if(key.ctrl)
+                        for(selRow = currentRow; selRow; selRow = selRow.GetNextRow())
                         {
-                           if(selRow.selectedFlag) selRow.selectedFlag = tempUnselected; else selRow.selectedFlag = tempSelected;
+                           if(key.ctrl)
+                           {
+                              if(selRow.selectedFlag) selRow.selectedFlag = tempUnselected; else selRow.selectedFlag = tempSelected;
+                           }
+                           else
+                              selRow.selectedFlag = selected;
+                           if(selRow == clickedRow)
+                              break;
                         }
-                        else
-                           selRow.selectedFlag = selected;
-                        if(selRow == currentRow)
-                           break;
                      }
                   }
                   else
                   {
-                     for(selRow = currentRow; selRow; selRow = selRow.GetNextRow())
+                     if(!(key.ctrl) && currentRow)
                      {
-                        if(key.ctrl)
-                        {
-                           if(selRow.selectedFlag) selRow.selectedFlag = tempUnselected; else selRow.selectedFlag = tempSelected;
-                        }
-                        else
-                           selRow.selectedFlag = selected;
-                        if(selRow == clickedRow)
-                           break;
+                        currentRow.selectedFlag = selected;
                      }
+
+                     clickedRow = currentRow;
                   }
                }
                else
                {
-                  if(!(key.ctrl) && currentRow)
-                  {
-                     currentRow.selectedFlag = selected;
-                  }
-
-                  clickedRow = currentRow;
+                  if(oldRow) oldRow.selectedFlag = unselected;
+                  if(currentRow) currentRow.selectedFlag = selected;
                }
-            }
-            else
-            {
-               if(oldRow) oldRow.selectedFlag = unselected;
-               if(currentRow) currentRow.selectedFlag = selected;
-            }
 
-            if(currentRow)
-            {
-               if(style.freeSelect)
-                  NotifyHighlight(master, this, currentRow, 0);
-               else
-                  NotifySelect(master, this, currentRow, 0);
+               if(currentRow)
+               {
+                  if(style.freeSelect)
+                     NotifyHighlight(master, this, currentRow, 0);
+                  else
+                     NotifySelect(master, this, currentRow, 0);
 
-               if(style.alwaysEdit && currentRow)
-                  currentRow.Edit(currentField /*null*/);
+                  if(style.alwaysEdit && currentRow)
+                     currentRow.Edit(currentField /*null*/);
+               }
+               Update(null);
+               return false;
             }
-            Update(null);
-            return false;
-         }
-         case space:
-         {
-            if(style.multiSelect && currentRow)
+            case space:
             {
-               if(currentRow.selectedFlag)
+               if(style.multiSelect && currentRow)
                {
-                  if(key.ctrl)
-                     currentRow.selectedFlag = unselected;
-               }
-               else
-                  currentRow.selectedFlag = selected;
-               Update(null);
+                  if(currentRow.selectedFlag)
+                  {
+                     if(key.ctrl)
+                        currentRow.selectedFlag = unselected;
+                  }
+                  else
+                     currentRow.selectedFlag = selected;
+                  Update(null);
 
-               if(style.freeSelect)
-                  NotifyHighlight(master, this, currentRow, 0);
-               else
-                  NotifySelect(master, this, currentRow, 0);
+                  if(style.freeSelect)
+                     NotifyHighlight(master, this, currentRow, 0);
+                  else
+                     NotifySelect(master, this, currentRow, 0);
+               }
+               break;
             }
-            break;
          }
       }
+
       if(!NotifyKeyHit(master, this, currentRow, key, ch))
          return false;
 
-      if(ch != 128 && !key.alt && !key.ctrl && GoToLetter(ch, true))
+      if(ch >=32 && ch != 128 && !key.alt && !key.ctrl && GoToLetter(ch, true))
       {
          /*if(inactive && window.state != Hidden)
             return NotifyHighlight(master, this, currentRow, 0);
@@ -4299,7 +4556,6 @@ private:
       return true;
    }
 
-
    void OnHScroll(ScrollBarAction action, int position, Key key)
    {
       Update(null);
@@ -4331,7 +4587,7 @@ private:
    int rowCount;
    int rowHeight;
    int fontH;
-   double typingTimeOut;
+   public double typingTimeOut;
    char * typedString;
 
    int mouseX, mouseY;
@@ -4357,7 +4613,7 @@ private:
    {
       delay = 0.5; // typingTimeOut
       userData = this;
-      
+
       bool DelayExpired()
       {
          typedString[0] = '\0';
@@ -4396,6 +4652,6 @@ private:
 
    // Only used for OnMouseMove so far, for avoiding problems with consequential mouse moves
    bool insideNotifySelect;
-   Color selectionColor, selectionText, stippleColor;
+   ColorAlpha selectionColor, selectionText, stippleColor;
    stippleColor = 0xFFFFFF80;
 };