Regedit:  Optimizations to refreshing; refreshing is still slightly slower than Windows regedit
Modified: trunk/reactos/subsys/system/regedit/treeview.c

Modified: trunk/reactos/subsys/system/regedit/treeview.c
--- trunk/reactos/subsys/system/regedit/treeview.c	2005-09-27 13:42:20 UTC (rev 18123)
+++ trunk/reactos/subsys/system/regedit/treeview.c	2005-09-27 13:47:46 UTC (rev 18124)
@@ -134,21 +134,24 @@
     HTREEITEM childItem;
     LPCTSTR KeyPath;
     DWORD dwCount, dwIndex, dwMaxSubKeyLen;
-    LPSTR Name;
+    LPSTR Name = NULL;
     TVITEM tvItem;
-    
+    LPTSTR pszNodes = NULL;
+    BOOL bSuccess = FALSE;
+    LPTSTR s;
+
     KeyPath = GetItemPath(hwndTV, hItem, &hRoot);
 
     if (*KeyPath) {
         if (RegOpenKeyEx(hRoot, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
-            return FALSE;
+            goto done;
         }
     } else {
         hKey = hRoot;
     }
 
     if (RegQueryInfoKey(hKey, 0, 0, 0, &dwCount, &dwMaxSubKeyLen, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) {
-        return FALSE;
+        goto done;
     }
 
     /* Set the number of children again */
@@ -156,24 +159,65 @@
     tvItem.hItem = hItem;
     tvItem.cChildren = dwCount;
     if (!TreeView_SetItem(hwndTV, &tvItem)) {
-        return FALSE;
+        goto done;
     }
 
     /* We don't have to bother with the rest if it's not expanded. */
     if (TreeView_GetItemState(hwndTV, hItem, TVIS_EXPANDED) == 0) {
         RegCloseKey(hKey);
-        return TRUE;
+        bSuccess = TRUE;
+        goto done;
     }
 
     dwMaxSubKeyLen++; /* account for the \0 terminator */
     if (!(Name = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLen * sizeof(TCHAR)))) {
-        return FALSE;
+        goto done;
     }
     tvItem.cchTextMax = dwMaxSubKeyLen;
     if (!(tvItem.pszText = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLen * sizeof(TCHAR)))) {
-        return FALSE;
+        goto done;
     }
 
+    /* Get all of the tree node siblings in one contiguous block of memory */
+    {
+        DWORD dwPhysicalSize = 0;
+        DWORD dwActualSize = 0;
+        DWORD dwNewPhysicalSize;
+        LPTSTR pszNewNodes;
+        DWORD dwStep = 10000;
+
+        for (childItem = TreeView_GetChild(hwndTV, hItem); childItem;
+                childItem = TreeView_GetNextSibling(hwndTV, childItem)) {
+
+            if (dwActualSize + dwMaxSubKeyLen + 1 > dwPhysicalSize)
+            {
+                dwNewPhysicalSize = dwActualSize + dwMaxSubKeyLen + 1 + dwStep;
+
+                if (pszNodes)
+                    pszNewNodes = (LPTSTR) HeapReAlloc(GetProcessHeap(), 0, pszNodes, dwNewPhysicalSize * sizeof(TCHAR));
+                else
+                    pszNewNodes = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, dwNewPhysicalSize * sizeof(TCHAR));
+                if (!pszNewNodes)
+                    goto done;
+
+                dwPhysicalSize = dwNewPhysicalSize;
+                pszNodes = pszNewNodes;
+            }
+
+            tvItem.mask = TVIF_TEXT;
+            tvItem.hItem = childItem;
+            tvItem.pszText = &pszNodes[dwActualSize];
+            tvItem.cchTextMax = dwPhysicalSize - dwActualSize;
+            if (!TreeView_GetItem(hwndTV, &tvItem))
+                goto done;
+
+            dwActualSize += _tcslen(&pszNodes[dwActualSize]) + 1;
+        }
+
+        if (pszNodes)
+            pszNodes[dwActualSize] = '\0';
+    }
+
     /* Now go through all the children in the registry, and check if any have to be added. */
     for (dwIndex = 0; dwIndex < dwCount; dwIndex++) {
         DWORD cName = dwMaxSubKeyLen, dwSubCount;
@@ -184,36 +228,29 @@
             continue;
         }
 
-        /* Find the number of children of the node. */
-        dwSubCount = 0;
-        if (RegOpenKeyEx(hKey, Name, 0, KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS) {
-            if (RegQueryInfoKey(hSubKey, 0, 0, 0, &dwSubCount, 0, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) {
-                dwSubCount = 0;
+        /* Check if the node is already in there. */
+        if (pszNodes) {
+            for (s = pszNodes; *s; s += _tcslen(s) + 1) {
+                if (!strcmp(s, Name)) {
+                    found = TRUE;
+                    break;
+                }
             }
-            RegCloseKey(hSubKey);
         }
 
-        /* Check if the node is already in there. */
-        for (childItem = TreeView_GetChild(hwndTV, hItem); childItem;
-                childItem = TreeView_GetNextSibling(hwndTV, childItem)) {
-            tvItem.mask = TVIF_TEXT;
-            tvItem.hItem = childItem;
-            if (!TreeView_GetItem(hwndTV, &tvItem)) {
-                return FALSE;
+        if (found == FALSE) {
+            /* Find the number of children of the node. */
+            dwSubCount = 0;
+            if (RegOpenKeyEx(hKey, Name, 0, KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS) {
+                if (RegQueryInfoKey(hSubKey, 0, 0, 0, &dwSubCount, 0, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) {
+                    dwSubCount = 0;
+                }
+                RegCloseKey(hSubKey);
             }
 
-            if (!strcmp(tvItem.pszText, Name)) {
-                found = TRUE;
-                break;
-            }
-        }
-
-        if (found == FALSE) {
             AddEntryToTree(hwndTV, hItem, Name, NULL, dwSubCount);
         }
     }
-    HeapFree(GetProcessHeap(), 0, Name);
-    HeapFree(GetProcessHeap(), 0, tvItem.pszText);
     RegCloseKey(hKey);
 
     /* Now go through all the children in the tree, and check if any have to be removed. */
@@ -225,8 +262,14 @@
         }
         childItem = nextItem;
     }
+    bSuccess = TRUE;
 
-    return TRUE;
+done:
+    if (pszNodes)
+        HeapFree(GetProcessHeap(), 0, pszNodes);
+    if (Name)
+        HeapFree(GetProcessHeap(), 0, Name);
+    return bSuccess;
 }
 
 BOOL RefreshTreeView(HWND hwndTV)