Imported from Wine 0.9.2:
DIALOG_GetNextTabItem
GetNextDlgGroupItem
GetNextDlgTabItem

fixes user32 dialog test hang and decreases number of failure tests to 9
Modified: trunk/reactos/lib/user32/windows/dialog.c

Modified: trunk/reactos/lib/user32/windows/dialog.c
--- trunk/reactos/lib/user32/windows/dialog.c	2005-12-02 20:06:02 UTC (rev 19830)
+++ trunk/reactos/lib/user32/windows/dialog.c	2005-12-02 21:33:33 UTC (rev 19831)
@@ -1094,44 +1094,30 @@
         if(!hChildFirst)
         {
             if(GetParent(hwndCtrl) != hwndMain)
+                /* i.e. if we are not at the top level of the recursion */
                 hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch);
             else
-            {
-                if(fPrevious)
-                    hChildFirst = GetWindow(hwndCtrl,GW_HWNDLAST);
-                else
-                    hChildFirst = GetWindow(hwndCtrl,GW_HWNDFIRST);
-            }
+                hChildFirst = GetWindow(hwndCtrl, fPrevious ? GW_HWNDLAST : GW_HWNDFIRST);
         }
     }
 
     while(hChildFirst)
     {
-        BOOL bCtrl = FALSE;
-        while(hChildFirst)
+        dsStyle = GetWindowLongA(hChildFirst,GWL_STYLE);
+        exStyle = GetWindowLongA(hChildFirst,GWL_EXSTYLE);
+        if( (exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
         {
-            dsStyle = GetWindowLongA(hChildFirst,GWL_STYLE);
-            exStyle = GetWindowLongA(hChildFirst,GWL_EXSTYLE);
-            if( (dsStyle & DS_CONTROL || exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
-            {
-                bCtrl=TRUE;
-                break;
-            }
-            else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
-                break;
-            hChildFirst = GetWindow(hChildFirst,wndSearch);
+            HWND retWnd;
+            retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious );
+            if (retWnd) return (retWnd);
         }
-        if(hChildFirst)
+        else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
         {
-            if(bCtrl)
-                retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious );
-            else
-                retWnd = hChildFirst;
+            return (hChildFirst);
         }
-        if(retWnd) break;
         hChildFirst = GetWindow(hChildFirst,wndSearch);
     }
-    if(!retWnd && hwndCtrl)
+    if(hwndCtrl)
     {
         HWND hParent = GetParent(hwndCtrl);
         while(hParent)
@@ -1144,7 +1130,8 @@
         if(!retWnd)
             retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious );
     }
-    return retWnd;
+    return retWnd ? retWnd : hwndCtrl;
+
 }
 
 /**********************************************************************
@@ -1942,7 +1929,6 @@
   return (UINT)SendDlgItemMessageW( hDlg, nIDDlgItem, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
 }
 
-
 /*
  * @implemented
  */
@@ -1953,54 +1939,110 @@
   HWND hCtl,
   BOOL bPrevious)
 {
-	HWND hwnd, retvalue;
+    HWND hwnd, hwndNext, retvalue, hwndLastGroup = 0;
+    BOOL fLooped=FALSE;
+    BOOL fSkipping=FALSE;
 
-    if(hCtl)
-    {
+    if (hDlg == hCtl) hCtl = NULL;
+    if (!hCtl && bPrevious) return 0;
+
         /* if the hwndCtrl is the child of the control in the hwndDlg,
          * then the hwndDlg has to be the parent of the hwndCtrl */
-        if(GetParent(hCtl) != hDlg && GetParent(GetParent(hCtl)) == hDlg)
-            hDlg = GetParent(hCtl);
-    }
 
     if (hCtl)
     {
+        if (!IsChild (hDlg, hCtl)) return 0;
         /* Make sure hwndCtrl is a top-level child */
-        HWND parent = GetParent( hCtl );
-        while (parent && parent != hDlg) parent = GetParent(parent);
-        if (parent != hDlg) return 0;
+
     }
     else
     {
         /* No ctrl specified -> start from the beginning */
         if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0;
-        if (bPrevious) hCtl = GetWindow( hCtl, GW_HWNDLAST );
+        /* MSDN is wrong. fPrevious does not result in the last child */
+
+        /* No ctrl specified -> start from the beginning */
+        if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0;
+
+        /* MSDN is wrong. fPrevious does not result in the last child */
+
+        /* Maybe that first one is valid.  If so then we don't want to skip it*/
+        if ((GetWindowLongW( hCtl, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
+        {
+            return hCtl;
+        }
+
     }
 
+    /* Always go forward around the group and list of controls; for the 
+     * previous control keep track; for the next break when you find one
+     */
     retvalue = hCtl;
-    hwnd = GetWindow( hCtl, GW_HWNDNEXT );
-    while (1)
+    hwnd = hCtl;
+    while (hwndNext = GetWindow (hwnd, GW_HWNDNEXT),
+           1)
     {
-        if (!hwnd || (GetWindowLongW( hwnd, GWL_STYLE ) & WS_GROUP))
+        while (!hwndNext)
         {
-            /* Wrap-around to the beginning of the group */
-            HWND tmp;
+            /* Climb out until there is a next sibling of the ancestor or we
+             * reach the top (in which case we loop back to the start)
+             */
+            if (hDlg == GetParent (hwnd))
+            {
+                /* Wrap around to the beginning of the list, within the same
+                 * group. (Once only)
+                 */
+                if (fLooped) goto end;
+                fLooped = TRUE;
+                hwndNext = GetWindow (hDlg, GW_CHILD);
+            }
+            else
+            {
+                hwnd = GetParent (hwnd);
+                hwndNext = GetWindow (hwnd, GW_HWNDNEXT);
+            }
+        }
+        hwnd = hwndNext;
 
-            hwnd = GetWindow( hDlg, GW_CHILD );
-            for (tmp = hwnd; tmp; tmp = GetWindow( tmp, GW_HWNDNEXT ) )
+        /* Wander down the leading edge of controlparents */
+        while ( (GetWindowLongW (hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) &&
+                ((GetWindowLongW (hwnd, GWL_STYLE) & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) &&
+                (hwndNext = GetWindow (hwnd, GW_CHILD)))
+            hwnd = hwndNext;
+        /* Question.  If the control is a control parent but either has no
+         * children or is not visible/enabled then if it has a WS_GROUP does
+         * it count?  For that matter does it count anyway?
+         * I believe it doesn't count.
+         */
+
+        if ((GetWindowLongW (hwnd, GWL_STYLE) & WS_GROUP))
+        {
+            hwndLastGroup = hwnd;
+            if (!fSkipping)
             {
-                if (GetWindowLongW( tmp, GWL_STYLE ) & WS_GROUP) hwnd = tmp;
-                if (tmp == hCtl) break;
+                /* Look for the beginning of the group */
+                fSkipping = TRUE;
             }
         }
-        if (hwnd == hCtl) break;
-        if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
+
+        if (hwnd == hCtl)
         {
+            if (!fSkipping) break;
+            if (hwndLastGroup == hwnd) break;
+            hwnd = hwndLastGroup;
+            fSkipping = FALSE;
+            fLooped = FALSE;
+        }
+
+        if (!fSkipping &&
+            (GetWindowLongW (hwnd, GWL_STYLE) & (WS_VISIBLE|WS_DISABLED)) ==
+             WS_VISIBLE)
+        {
             retvalue = hwnd;
             if (!bPrevious) break;
         }
-        hwnd = GetWindow( hwnd, GW_HWNDNEXT );
     }
+end:
     return retvalue;
 }
 
@@ -2015,9 +2057,19 @@
   HWND hCtl,
   BOOL bPrevious)
 {
+	/* Undocumented but tested under Win2000 and WinME */
+	if (hDlg == hCtl) hCtl = NULL;
+
+	/* Contrary to MSDN documentation, tested under Win2000 and WinME
+	* NB GetLastError returns whatever was set before the function was
+	* called.
+	*/
+	if (!hCtl && bPrevious) return 0;
+
 	return DIALOG_GetNextTabItem(hDlg, hDlg, hCtl, bPrevious);
 }
 
+
 #if 0
 BOOL
 STDCALL