[Win32SS]
authorJames Tabor <james.tabor@reactos.org>
Thu, 30 Jul 2015 07:49:09 +0000 (07:49 +0000)
committerJames Tabor <james.tabor@reactos.org>
Thu, 30 Jul 2015 07:49:09 +0000 (07:49 +0000)
- Start ordering functions into separate files.

svn path=/trunk/; revision=68582

reactos/win32ss/CMakeLists.txt
reactos/win32ss/user/ntuser/defwnd.c
reactos/win32ss/user/ntuser/nonclient.c [new file with mode: 0644]
reactos/win32ss/user/ntuser/painting.c
reactos/win32ss/user/ntuser/painting.h
reactos/win32ss/user/ntuser/scrollex.c [new file with mode: 0644]
reactos/win32ss/user/ntuser/userfuncs.h

index f933547..24477f2 100644 (file)
@@ -129,11 +129,13 @@ list(APPEND SOURCE
     user/ntuser/monitor.c
     user/ntuser/mouse.c
     user/ntuser/msgqueue.c
+    user/ntuser/nonclient.c
     user/ntuser/ntstubs.c
     user/ntuser/ntuser.c
     user/ntuser/painting.c
     user/ntuser/prop.c
     user/ntuser/scrollbar.c
+    user/ntuser/scrollex.c
     user/ntuser/session.c
     user/ntuser/shutdown.c
     user/ntuser/simplecall.c
index 579d2d9..410019a 100644 (file)
 
 DBG_DEFAULT_CHANNEL(UserDefwnd);
 
-#define UserHasDlgFrameStyle(Style, ExStyle)                                   \
- (((ExStyle) & WS_EX_DLGMODALFRAME) ||                                         \
-  (((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
-
-#define UserHasThickFrameStyle(Style, ExStyle)                                 \
-  (((Style) & WS_THICKFRAME) &&                                                \
-   (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
-
-#define UserHasThinFrameStyle(Style, ExStyle)                                  \
-  (((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
-
-#define ON_LEFT_BORDER(hit) \
- (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
-#define ON_RIGHT_BORDER(hit) \
- (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
-#define ON_TOP_BORDER(hit) \
- (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
-#define ON_BOTTOM_BORDER(hit) \
- (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
 
 HBRUSH FASTCALL
 DefWndControlColor(HDC hDC, UINT ctlType)
@@ -119,538 +100,6 @@ DefWndHandleWindowPosChanged(PWND pWnd, WINDOWPOS* Pos)
    return 0;
 }
 
-VOID FASTCALL
-UserDrawWindowFrame(HDC hdc,
-                    RECTL *rect,
-                   ULONG width,
-                   ULONG height)
-{
-   HBRUSH hbrush = NtGdiSelectBrush( hdc, gpsi->hbrGray );
-   NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left - width, height, PATINVERT );
-   NtGdiPatBlt( hdc, rect->left, rect->top + height, width, rect->bottom - rect->top - height, PATINVERT );
-   NtGdiPatBlt( hdc, rect->left + width, rect->bottom - 1, rect->right - rect->left - width, -(LONG)height, PATINVERT );
-   NtGdiPatBlt( hdc, rect->right - 1, rect->top, -(LONG)width, rect->bottom - rect->top - height, PATINVERT );
-   NtGdiSelectBrush( hdc, hbrush );
-}
-
-VOID FASTCALL
-UserDrawMovingFrame(HDC hdc,
-                    RECTL *rect,
-                    BOOL thickframe)
-{
-   if (thickframe) UserDrawWindowFrame(hdc, rect, UserGetSystemMetrics(SM_CXFRAME), UserGetSystemMetrics(SM_CYFRAME));
-   else UserDrawWindowFrame(hdc, rect, 1, 1);
-}
-
-/***********************************************************************
- *           NC_GetInsideRect
- *
- * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
- * but without the borders (if any).
- */
-void FASTCALL
-NC_GetInsideRect(PWND Wnd, RECT *rect)
-{
-    ULONG Style;
-    ULONG ExStyle;
-
-    Style = Wnd->style;
-    ExStyle = Wnd->ExStyle;
-
-    rect->top    = rect->left = 0;
-    rect->right  = Wnd->rcWindow.right - Wnd->rcWindow.left;
-    rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
-
-    if (Style & WS_ICONIC) return;
-
-    /* Remove frame from rectangle */
-    if (UserHasThickFrameStyle(Style, ExStyle ))
-    {
-        RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME));
-    }
-    else
-    {
-        if (UserHasDlgFrameStyle(Style, ExStyle ))
-        {
-            RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
-            /* FIXME: this isn't in NC_AdjustRect? why not? */
-            if (ExStyle & WS_EX_DLGMODALFRAME)
-                   RECTL_vInflateRect( rect, -1, 0 );
-        }
-        else
-        {
-            if (UserHasThinFrameStyle(Style, ExStyle))
-            {
-                RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
-            }
-        }
-    }
-    /* We have additional border information if the window
-     * is a child (but not an MDI child) */
-    if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
-    {
-       if (ExStyle & WS_EX_CLIENTEDGE)
-          RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXEDGE), -UserGetSystemMetrics(SM_CYEDGE));
-       if (ExStyle & WS_EX_STATICEDGE)
-          RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
-    }
-}
-
-LONG FASTCALL
-DefWndStartSizeMove(PWND Wnd, WPARAM wParam, POINT *capturePoint)
-{
-   LONG hittest = 0;
-   POINT pt;
-   MSG msg;
-   RECT rectWindow;
-   ULONG Style = Wnd->style;
-   PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
-
-   rectWindow = Wnd->rcWindow;
-
-   if ((wParam & 0xfff0) == SC_MOVE)
-   {
-       /* Move pointer at the center of the caption */
-       RECT rect = rectWindow;
-       /* Note: to be exactly centered we should take the different types
-        * of border into account, but it shouldn't make more than a few pixels
-        * of difference so let's not bother with that */
-       if (Style & WS_SYSMENU)
-          rect.left += UserGetSystemMetrics(SM_CXSIZE) + 1;
-       if (Style & WS_MINIMIZEBOX)
-         rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
-       if (Style & WS_MAXIMIZEBOX)
-          rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
-       pt.x = (rect.right + rect.left) / 2;
-       pt.y = rect.top + UserGetSystemMetrics(SM_CYSIZE)/2;
-       hittest = HTCAPTION;
-       *capturePoint = pt;
-   }
-   else  /* SC_SIZE */
-   {
-       pt.x = pt.y = 0;
-       while (!hittest)
-       {
-          if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) return 0;
-          if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
-
-         switch(msg.message)
-           {
-           case WM_MOUSEMOVE:
-             //// Clamp the mouse position to the window rectangle when starting a window resize.
-              pt.x = min( max( msg.pt.x, rectWindow.left ), rectWindow.right - 1 );
-              pt.y = min( max( msg.pt.y, rectWindow.top ), rectWindow.bottom - 1 );
-             hittest = GetNCHitEx(Wnd, pt);
-             if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) hittest = 0;
-             break;
-
-           case WM_LBUTTONUP:
-             return 0;
-
-           case WM_KEYDOWN:
-             switch (msg.wParam)
-               {
-               case VK_UP:
-                 hittest = HTTOP;
-                 pt.x = (rectWindow.left+rectWindow.right)/2;
-                 pt.y =  rectWindow.top + UserGetSystemMetrics(SM_CYFRAME) / 2;
-                 break;
-               case VK_DOWN:
-                 hittest = HTBOTTOM;
-                 pt.x = (rectWindow.left+rectWindow.right)/2;
-                 pt.y =  rectWindow.bottom - UserGetSystemMetrics(SM_CYFRAME) / 2;
-                 break;
-               case VK_LEFT:
-                 hittest = HTLEFT;
-                 pt.x =  rectWindow.left + UserGetSystemMetrics(SM_CXFRAME) / 2;
-                 pt.y = (rectWindow.top+rectWindow.bottom)/2;
-                 break;
-               case VK_RIGHT:
-                 hittest = HTRIGHT;
-                 pt.x =  rectWindow.right - UserGetSystemMetrics(SM_CXFRAME) / 2;
-                 pt.y = (rectWindow.top+rectWindow.bottom)/2;
-                 break;
-               case VK_RETURN:
-               case VK_ESCAPE:
-                 return 0;
-               }
-            default:
-              IntTranslateKbdMessage( &msg, 0 );
-              pti->TIF_flags |= TIF_MOVESIZETRACKING;
-              IntDispatchMessage( &msg );
-              pti->TIF_flags |= TIF_MOVESIZETRACKING;
-              break;
-           }
-       }
-       *capturePoint = pt;
-    }
-    UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
-    co_IntSendMessage(UserHMGetHandle(Wnd), WM_SETCURSOR, (WPARAM)UserHMGetHandle(Wnd), MAKELONG(hittest, WM_MOUSEMOVE));
-    return hittest;
-}
-
-//
-//  System Command Size and Move
-//
-//  Perform SC_MOVE and SC_SIZE commands.
-//
-VOID FASTCALL
-DefWndDoSizeMove(PWND pwnd, WORD wParam)
-{
-   MSG msg;
-   RECT sizingRect, mouseRect, origRect, unmodRect;
-   HDC hdc;
-   LONG hittest = (LONG)(wParam & 0x0f);
-   PCURICON_OBJECT DragCursor = NULL, OldCursor = NULL;
-   POINT minTrack, maxTrack;
-   POINT capturePoint, pt;
-   ULONG Style, ExStyle;
-   BOOL thickframe;
-   BOOL iconic;
-   BOOL moved = FALSE;
-   BOOL DragFullWindows = FALSE;
-   PWND pWndParent = NULL;
-   WPARAM syscommand = (wParam & 0xfff0);
-   PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
-   //PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
-   //                  The task bar can grow in size and can not reduce due to the change
-   //                  in the work area.
-
-   Style = pwnd->style;
-   ExStyle = pwnd->ExStyle;
-   iconic = (Style & WS_MINIMIZE) != 0;
-
-   if ((Style & WS_MAXIMIZE) || !IntIsWindowVisible(pwnd)) return;
-
-   thickframe = UserHasThickFrameStyle(Style, ExStyle) && !iconic;
-
-   //
-   // Show window contents while dragging the window, get flag from registry data.
-   //
-   UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
-
-   pt.x = pti->ptLast.x;
-   pt.y = pti->ptLast.y;
-   capturePoint = pt;
-   UserClipCursor( NULL );
-
-   TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
-          pwnd, syscommand, hittest, pt.x, pt.y);
-
-   if (syscommand == SC_MOVE)
-   {
-      if (!hittest) hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
-      if (!hittest) return;
-   }
-   else  /* SC_SIZE */
-   {
-      if (!thickframe) return;
-      if (hittest && (syscommand != SC_MOUSEMENU))
-      {
-          hittest += (HTLEFT - WMSZ_LEFT);
-      }
-      else
-      {
-          co_UserSetCapture(UserHMGetHandle(pwnd));
-          hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
-         if (!hittest)
-          {
-              IntReleaseCapture();
-              return;
-          }
-      }
-   }
-
-   /* Get min/max info */
-
-   co_WinPosGetMinMaxInfo(pwnd, NULL, NULL, &minTrack, &maxTrack);
-   sizingRect = pwnd->rcWindow;
-   origRect = sizingRect;
-   if (Style & WS_CHILD)
-   {
-      pWndParent = IntGetParent(pwnd);
-      IntGetClientRect( pWndParent, &mouseRect );
-      IntMapWindowPoints( pWndParent, 0, (LPPOINT)&mouseRect, 2 );
-      IntMapWindowPoints( 0, pWndParent, (LPPOINT)&sizingRect, 2 );
-      unmodRect = sizingRect;
-   }
-   else
-   {
-      if (!(ExStyle & WS_EX_TOPMOST))
-      {
-        UserSystemParametersInfo(SPI_GETWORKAREA, 0, &mouseRect, 0);
-      }
-      else
-      {
-        RECTL_vSetRect(&mouseRect, 0, 0, UserGetSystemMetrics(SM_CXSCREEN), UserGetSystemMetrics(SM_CYSCREEN));
-      }
-      unmodRect = sizingRect;
-   }
-
-   if (ON_LEFT_BORDER(hittest))
-   {
-      mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x+capturePoint.x-sizingRect.left );
-      mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x+capturePoint.x-sizingRect.left );
-   }
-   else if (ON_RIGHT_BORDER(hittest))
-   {
-      mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x+capturePoint.x-sizingRect.right );
-      mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x+capturePoint.x-sizingRect.right );
-   }
-   if (ON_TOP_BORDER(hittest))
-   {
-      mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y+capturePoint.y-sizingRect.top );
-      mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y+capturePoint.y-sizingRect.top);
-   }
-   else if (ON_BOTTOM_BORDER(hittest))
-   {
-      mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y+capturePoint.y-sizingRect.bottom );
-      mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y+capturePoint.y-sizingRect.bottom );
-   }
-
-   hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE );
-   if (iconic)
-   {
-       DragCursor = pwnd->pcls->spicn;
-       if (DragCursor)
-       {
-           UserReferenceObject(DragCursor);
-       }
-       else
-       {
-           HCURSOR CursorHandle = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
-           if (CursorHandle)
-           {
-               DragCursor = UserGetCurIconObject(CursorHandle);
-           }
-           else
-           {
-               iconic = FALSE;
-           }
-       }
-   }
-
-   /* repaint the window before moving it around */
-   co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
-
-   IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
-
-   co_IntSendMessage( UserHMGetHandle(pwnd), WM_ENTERSIZEMOVE, 0, 0 );
-
-   MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, UserHMGetHandle(pwnd));
-
-   if (IntGetCapture() != UserHMGetHandle(pwnd)) co_UserSetCapture( UserHMGetHandle(pwnd) );
-
-   pwnd->head.pti->TIF_flags |= TIF_MOVESIZETRACKING;
-
-   for(;;)
-   {
-      int dx = 0, dy = 0;
-
-      if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) break;
-      if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
-
-      /* Exit on button-up, Return, or Esc */
-      if ((msg.message == WM_LBUTTONUP) ||
-         ((msg.message == WM_KEYDOWN) &&
-          ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
-
-      if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
-      {
-         IntTranslateKbdMessage( &msg , 0 );
-         IntDispatchMessage( &msg );
-         continue;  /* We are not interested in other messages */
-      }
-
-      pt = msg.pt;
-
-      if (msg.message == WM_KEYDOWN) switch(msg.wParam)
-      {
-       case VK_UP:    pt.y -= 8; break;
-       case VK_DOWN:  pt.y += 8; break;
-       case VK_LEFT:  pt.x -= 8; break;
-       case VK_RIGHT: pt.x += 8; break;
-      }
-
-      pt.x = max( pt.x, mouseRect.left );
-      pt.x = min( pt.x, mouseRect.right - 1 );
-      pt.y = max( pt.y, mouseRect.top );
-      pt.y = min( pt.y, mouseRect.bottom - 1 );
-
-      dx = pt.x - capturePoint.x;
-      dy = pt.y - capturePoint.y;
-
-      if (dx || dy)
-      {
-         if ( !moved )
-         {
-             moved = TRUE;
-          if ( iconic ) /* ok, no system popup tracking */
-          {
-              OldCursor = UserSetCursor(DragCursor, FALSE);
-              UserShowCursor( TRUE );
-          }
-          else if(!DragFullWindows)
-             UserDrawMovingFrame( hdc, &sizingRect, thickframe );
-         }
-
-         if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
-         else
-         {
-             RECT newRect = unmodRect;
-
-             if (!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
-             if (hittest == HTCAPTION) RECTL_vOffsetRect( &newRect, dx, dy );
-             if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
-             else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
-             if (ON_TOP_BORDER(hittest)) newRect.top += dy;
-             else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
-             capturePoint = pt;
-
-              //
-              //  Save the new position to the unmodified rectangle. This allows explorer task bar
-              //  sizing. Explorer will forces back the position unless a certain amount of sizing
-              //  has occurred.
-              //
-              unmodRect = newRect;
-
-             /* determine the hit location */
-              if (syscommand == SC_SIZE)
-              {
-                  WPARAM wpSizingHit = 0;
-
-                  if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
-                      wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
-                  co_IntSendMessage( UserHMGetHandle(pwnd), WM_SIZING, wpSizingHit, (LPARAM)&newRect );
-              }
-              else
-                  co_IntSendMessage( UserHMGetHandle(pwnd), WM_MOVING, 0, (LPARAM)&newRect );
-
-             if (!iconic)
-              {
-                 if (!DragFullWindows)
-                     UserDrawMovingFrame( hdc, &newRect, thickframe );
-                 else
-                 {  // Moving the whole window now!
-                    PWND pwndTemp;
-                    //// This causes the mdi child window to jump up when it is moved.
-                    //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
-                   co_WinPosSetWindowPos( pwnd,
-                                          0,
-                                          newRect.left,
-                                          newRect.top,
-                                          newRect.right - newRect.left,
-                                          newRect.bottom - newRect.top,
-                                         ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
-
-                    // Update all the windows after the move or size, including this window.
-                    for ( pwndTemp = pwnd->head.rpdesk->pDeskInfo->spwnd->spwndChild;
-                          pwndTemp;
-                          pwndTemp = pwndTemp->spwndNext )
-                    {
-                       RECTL rect;
-                       // Only the windows that overlap will be redrawn.
-                       if (RECTL_bIntersectRect( &rect, &pwnd->rcWindow, &pwndTemp->rcWindow ))
-                       {
-                          co_UserRedrawWindow( pwndTemp, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
-                       }
-                    }
-                 }
-              }
-              sizingRect = newRect;
-         }
-      }
-   }
-
-   pwnd->head.pti->TIF_flags &= ~TIF_MOVESIZETRACKING;
-
-   IntReleaseCapture();
-
-   if ( iconic )
-   {
-      if ( moved ) /* restore cursors, show icon title later on */
-      {
-          UserShowCursor( FALSE );
-          OldCursor = UserSetCursor(OldCursor, FALSE);
-      }
-
-      /* It could be that the cursor was already changed while we were proceeding,
-       * so we must unreference whatever cursor was current at the time we restored the old one.
-       * Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
-       */
-      if (OldCursor) UserDereferenceObject(OldCursor);
-   }
-   else if ( moved && !DragFullWindows )
-      UserDrawMovingFrame( hdc, &sizingRect, thickframe );
-
-   UserReleaseDC(NULL, hdc, FALSE);
-
-   //// This causes the mdi child window to jump up when it is moved.
-   //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
-
-   if (co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)UserHMGetHandle(pwnd), (LPARAM)&sizingRect))
-   {
-      ERR("DoSizeMove : WH_CBT Call Hook return!\n");
-      moved = FALSE;
-   }
-
-   IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
-
-   MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
-
-   co_IntSendMessage( UserHMGetHandle(pwnd), WM_EXITSIZEMOVE, 0, 0 );
-   //// wine mdi hack
-   co_IntSendMessage( UserHMGetHandle(pwnd), WM_SETVISIBLE, !!(pwnd->style & WS_MINIMIZE), 0L);
-   ////
-   /* window moved or resized */
-   if (moved)
-   {
-      /* if the moving/resizing isn't canceled call SetWindowPos
-       * with the new position or the new size of the window
-       */
-      if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
-      {
-         /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
-         if (!DragFullWindows || iconic )
-         {
-           co_WinPosSetWindowPos( pwnd,
-                                  0,
-                                  sizingRect.left,
-                                  sizingRect.top,
-                                  sizingRect.right - sizingRect.left,
-                                  sizingRect.bottom - sizingRect.top,
-                                 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
-          }
-      }
-      else
-      { /* restore previous size/position */
-       if ( DragFullWindows )
-       {
-         co_WinPosSetWindowPos( pwnd,
-                                0,
-                                origRect.left,
-                                origRect.top,
-                                origRect.right - origRect.left,
-                                origRect.bottom - origRect.top,
-                               ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
-        }
-      }
-   }
-
-   if ( IntIsWindow(UserHMGetHandle(pwnd)) )
-   {
-     if ( iconic )
-     {
-       /* Single click brings up the system menu when iconized */
-       if ( !moved )
-        {
-           if( Style & WS_SYSMENU )
-             co_IntSendMessage( UserHMGetHandle(pwnd), WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
-        }
-     }
-   }
-}
-
 //
 // Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
 //
@@ -1197,230 +646,4 @@ IntDefWindowProc(
    return lResult;
 }
 
-PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd )
-{
-    PCURICON_OBJECT pIcon = NULL;
-    HICON hIcon;
-
-   //FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
-   //FIXME: Hence we must return a pointer with no reference count.
-   //FIXME: This is bad and we should feel bad.
-   //FIXME: Stop whining over wine code.
-
-   hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
-   if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
-
-   if (!hIcon && pWnd->pcls->spicnSm)
-       return pWnd->pcls->spicnSm;
-   if (!hIcon && pWnd->pcls->spicn)
-       return pWnd->pcls->spicn;
-
-   if (!hIcon && (pWnd->style & DS_MODALFRAME))
-   {
-      if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
-      if (!hIcon) hIcon = gpsi->hIconWindows;   // Reg size.
-   }
-   if (hIcon)
-   {
-       pIcon = UserGetCurIconObject(hIcon);
-       if (pIcon)
-       {
-           UserDereferenceObject(pIcon);
-       }
-   }
-   return pIcon;
-}
-
-DWORD FASTCALL
-GetNCHitEx(PWND pWnd, POINT pt)
-{
-   RECT rcWindow, rcClient;
-   DWORD Style, ExStyle;
-
-   if (!pWnd) return HTNOWHERE;
-
-   if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
-   {
-      rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0;
-      rcWindow.right  = UserGetSystemMetrics(SM_CXSCREEN);
-      rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN);
-      rcClient.right  = UserGetSystemMetrics(SM_CXSCREEN);
-      rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN);
-   }
-   else
-   {
-      rcClient = pWnd->rcClient;
-      rcWindow = pWnd->rcWindow;
-   }
-
-   if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE;
-
-   Style = pWnd->style;
-   ExStyle = pWnd->ExStyle;
-
-   if (Style & WS_MINIMIZE) return HTCAPTION;
-
-   if (RECTL_bPointInRect( &rcClient,  pt.x, pt.y )) return HTCLIENT;
-
-   /* Check borders */
-   if (HAS_THICKFRAME( Style, ExStyle ))
-   {
-      RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) );
-      if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y ))
-      {
-            /* Check top sizing border */
-            if (pt.y < rcWindow.top)
-            {
-                if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
-                if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
-                return HTTOP;
-            }
-            /* Check bottom sizing border */
-            if (pt.y >= rcWindow.bottom)
-            {
-                if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
-                if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
-                return HTBOTTOM;
-            }
-            /* Check left sizing border */
-            if (pt.x < rcWindow.left)
-            {
-                if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
-                if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
-                return HTLEFT;
-            }
-            /* Check right sizing border */
-            if (pt.x >= rcWindow.right)
-            {
-                if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
-                if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
-                return HTRIGHT;
-            }
-        }
-    }
-    else  /* No thick frame */
-    {
-        if (HAS_DLGFRAME( Style, ExStyle ))
-            RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
-        else if (HAS_THINFRAME( Style, ExStyle ))
-            RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
-        if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y  )) return HTBORDER;
-    }
-
-    /* Check caption */
-
-    if ((Style & WS_CAPTION) == WS_CAPTION)
-    {
-        if (ExStyle & WS_EX_TOOLWINDOW)
-            rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1;
-        else
-            rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1;
-        if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y ))
-        {
-            BOOL min_or_max_box = (Style & WS_SYSMENU) && (Style & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX));
-            if (ExStyle & WS_EX_LAYOUTRTL)
-            {
-                /* Check system menu */
-                if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
-                {
-                    rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
-                    if (pt.x > rcWindow.right) return HTSYSMENU;
-                }
-
-                /* Check close button */
-                if (Style & WS_SYSMENU)
-                {
-                    rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION);
-                    if (pt.x < rcWindow.left) return HTCLOSE;
-                }
-
-                /* Check maximize box */
-                /* In Win95 there is automatically a Maximize button when there is a minimize one */
-                if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
-                {
-                    rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
-                    if (pt.x < rcWindow.left) return HTMAXBUTTON;
-                }
-
-                /* Check minimize box */
-                if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
-                {
-                    rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
-                    if (pt.x < rcWindow.left) return HTMINBUTTON;
-                }
-            }
-            else
-            {
-                /* Check system menu */
-                if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
-                {
-                    rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1;
-                    if (pt.x < rcWindow.left) return HTSYSMENU;
-                }
-
-                /* Check close button */
-                if (Style & WS_SYSMENU)
-                {
-                    rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION);
-                    if (pt.x > rcWindow.right) return HTCLOSE;
-                }
-
-                /* Check maximize box */
-                /* In Win95 there is automatically a Maximize button when there is a minimize one */
-                if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
-                {
-                    rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
-                    if (pt.x > rcWindow.right) return HTMAXBUTTON;
-                }
-
-                /* Check minimize box */
-                if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
-                {
-                    rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
-                    if (pt.x > rcWindow.right) return HTMINBUTTON;
-                }
-            }
-            return HTCAPTION;
-        }
-    }
-
-      /* Check menu bar */
-
-    if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) &&
-        (pt.x >= rcClient.left) && (pt.x < rcClient.right))
-        return HTMENU;
-
-      /* Check vertical scroll bar */
-
-    if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR;
-    if (Style & WS_VSCROLL)
-    {
-        if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
-            rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL);
-        else
-            rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL);
-        if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL;
-    }
-
-      /* Check horizontal scroll bar */
-
-    if (Style & WS_HSCROLL)
-    {
-        rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL);
-        if (RECTL_bPointInRect( &rcClient, pt.x, pt.y ))
-        {
-            /* Check size box */
-            if ((Style & WS_VSCROLL) &&
-                ((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) ||
-                (((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL)))))
-                return HTSIZE;
-            return HTHSCROLL;
-        }
-    }
-
-    /* Has to return HTNOWHERE if nothing was found
-       Could happen when a window has a customized non client area */
-    return HTNOWHERE;
-}
-
 /* EOF */
diff --git a/reactos/win32ss/user/ntuser/nonclient.c b/reactos/win32ss/user/ntuser/nonclient.c
new file mode 100644 (file)
index 0000000..6a10bab
--- /dev/null
@@ -0,0 +1,793 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS Win32k subsystem
+ * PURPOSE:          Miscellaneous User functions
+ * FILE:             win32ss/user/ntuser/nonclient.c
+ * PROGRAMER:
+ */
+
+#include <win32k.h>
+#include <windowsx.h>
+
+DBG_DEFAULT_CHANNEL(UserDefwnd);
+
+#define UserHasDlgFrameStyle(Style, ExStyle)                                   \
+ (((ExStyle) & WS_EX_DLGMODALFRAME) ||                                         \
+  (((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
+
+#define UserHasThickFrameStyle(Style, ExStyle)                                 \
+  (((Style) & WS_THICKFRAME) &&                                                \
+   (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
+
+#define UserHasThinFrameStyle(Style, ExStyle)                                  \
+  (((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
+
+#define ON_LEFT_BORDER(hit) \
+ (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
+#define ON_RIGHT_BORDER(hit) \
+ (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
+#define ON_TOP_BORDER(hit) \
+ (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
+#define ON_BOTTOM_BORDER(hit) \
+ (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
+
+
+VOID FASTCALL
+UserDrawWindowFrame(HDC hdc,
+                    RECTL *rect,
+                   ULONG width,
+                   ULONG height)
+{
+   HBRUSH hbrush = NtGdiSelectBrush( hdc, gpsi->hbrGray );
+   NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left - width, height, PATINVERT );
+   NtGdiPatBlt( hdc, rect->left, rect->top + height, width, rect->bottom - rect->top - height, PATINVERT );
+   NtGdiPatBlt( hdc, rect->left + width, rect->bottom - 1, rect->right - rect->left - width, -(LONG)height, PATINVERT );
+   NtGdiPatBlt( hdc, rect->right - 1, rect->top, -(LONG)width, rect->bottom - rect->top - height, PATINVERT );
+   NtGdiSelectBrush( hdc, hbrush );
+}
+
+VOID FASTCALL
+UserDrawMovingFrame(HDC hdc,
+                    RECTL *rect,
+                    BOOL thickframe)
+{
+   if (thickframe) UserDrawWindowFrame(hdc, rect, UserGetSystemMetrics(SM_CXFRAME), UserGetSystemMetrics(SM_CYFRAME));
+   else UserDrawWindowFrame(hdc, rect, 1, 1);
+}
+
+/***********************************************************************
+ *           NC_GetInsideRect
+ *
+ * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
+ * but without the borders (if any).
+ */
+void FASTCALL
+NC_GetInsideRect(PWND Wnd, RECT *rect)
+{
+    ULONG Style;
+    ULONG ExStyle;
+
+    Style = Wnd->style;
+    ExStyle = Wnd->ExStyle;
+
+    rect->top    = rect->left = 0;
+    rect->right  = Wnd->rcWindow.right - Wnd->rcWindow.left;
+    rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
+
+    if (Style & WS_ICONIC) return;
+
+    /* Remove frame from rectangle */
+    if (UserHasThickFrameStyle(Style, ExStyle ))
+    {
+        RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME));
+    }
+    else
+    {
+        if (UserHasDlgFrameStyle(Style, ExStyle ))
+        {
+            RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
+            /* FIXME: this isn't in NC_AdjustRect? why not? */
+            if (ExStyle & WS_EX_DLGMODALFRAME)
+                   RECTL_vInflateRect( rect, -1, 0 );
+        }
+        else
+        {
+            if (UserHasThinFrameStyle(Style, ExStyle))
+            {
+                RECTL_vInflateRect(rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
+            }
+        }
+    }
+    /* We have additional border information if the window
+     * is a child (but not an MDI child) */
+    if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
+    {
+       if (ExStyle & WS_EX_CLIENTEDGE)
+          RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXEDGE), -UserGetSystemMetrics(SM_CYEDGE));
+       if (ExStyle & WS_EX_STATICEDGE)
+          RECTL_vInflateRect (rect, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
+    }
+}
+
+LONG FASTCALL
+DefWndStartSizeMove(PWND Wnd, WPARAM wParam, POINT *capturePoint)
+{
+   LONG hittest = 0;
+   POINT pt;
+   MSG msg;
+   RECT rectWindow;
+   ULONG Style = Wnd->style;
+   PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+   rectWindow = Wnd->rcWindow;
+
+   if ((wParam & 0xfff0) == SC_MOVE)
+   {
+       /* Move pointer at the center of the caption */
+       RECT rect = rectWindow;
+       /* Note: to be exactly centered we should take the different types
+        * of border into account, but it shouldn't make more than a few pixels
+        * of difference so let's not bother with that */
+       if (Style & WS_SYSMENU)
+          rect.left += UserGetSystemMetrics(SM_CXSIZE) + 1;
+       if (Style & WS_MINIMIZEBOX)
+         rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
+       if (Style & WS_MAXIMIZEBOX)
+          rect.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
+       pt.x = (rect.right + rect.left) / 2;
+       pt.y = rect.top + UserGetSystemMetrics(SM_CYSIZE)/2;
+       hittest = HTCAPTION;
+       *capturePoint = pt;
+   }
+   else  /* SC_SIZE */
+   {
+       pt.x = pt.y = 0;
+       while (!hittest)
+       {
+          if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) return 0;
+          if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
+
+         switch(msg.message)
+           {
+           case WM_MOUSEMOVE:
+             //// Clamp the mouse position to the window rectangle when starting a window resize.
+              pt.x = min( max( msg.pt.x, rectWindow.left ), rectWindow.right - 1 );
+              pt.y = min( max( msg.pt.y, rectWindow.top ), rectWindow.bottom - 1 );
+             hittest = GetNCHitEx(Wnd, pt);
+             if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT)) hittest = 0;
+             break;
+
+           case WM_LBUTTONUP:
+             return 0;
+
+           case WM_KEYDOWN:
+             switch (msg.wParam)
+               {
+               case VK_UP:
+                 hittest = HTTOP;
+                 pt.x = (rectWindow.left+rectWindow.right)/2;
+                 pt.y =  rectWindow.top + UserGetSystemMetrics(SM_CYFRAME) / 2;
+                 break;
+               case VK_DOWN:
+                 hittest = HTBOTTOM;
+                 pt.x = (rectWindow.left+rectWindow.right)/2;
+                 pt.y =  rectWindow.bottom - UserGetSystemMetrics(SM_CYFRAME) / 2;
+                 break;
+               case VK_LEFT:
+                 hittest = HTLEFT;
+                 pt.x =  rectWindow.left + UserGetSystemMetrics(SM_CXFRAME) / 2;
+                 pt.y = (rectWindow.top+rectWindow.bottom)/2;
+                 break;
+               case VK_RIGHT:
+                 hittest = HTRIGHT;
+                 pt.x =  rectWindow.right - UserGetSystemMetrics(SM_CXFRAME) / 2;
+                 pt.y = (rectWindow.top+rectWindow.bottom)/2;
+                 break;
+               case VK_RETURN:
+               case VK_ESCAPE:
+                 return 0;
+               }
+            default:
+              IntTranslateKbdMessage( &msg, 0 );
+              pti->TIF_flags |= TIF_MOVESIZETRACKING;
+              IntDispatchMessage( &msg );
+              pti->TIF_flags |= TIF_MOVESIZETRACKING;
+              break;
+           }
+       }
+       *capturePoint = pt;
+    }
+    UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
+    co_IntSendMessage(UserHMGetHandle(Wnd), WM_SETCURSOR, (WPARAM)UserHMGetHandle(Wnd), MAKELONG(hittest, WM_MOUSEMOVE));
+    return hittest;
+}
+
+//
+//  System Command Size and Move
+//
+//  Perform SC_MOVE and SC_SIZE commands.
+//
+VOID FASTCALL
+DefWndDoSizeMove(PWND pwnd, WORD wParam)
+{
+   MSG msg;
+   RECT sizingRect, mouseRect, origRect, unmodRect;
+   HDC hdc;
+   LONG hittest = (LONG)(wParam & 0x0f);
+   PCURICON_OBJECT DragCursor = NULL, OldCursor = NULL;
+   POINT minTrack, maxTrack;
+   POINT capturePoint, pt;
+   ULONG Style, ExStyle;
+   BOOL thickframe;
+   BOOL iconic;
+   BOOL moved = FALSE;
+   BOOL DragFullWindows = FALSE;
+   PWND pWndParent = NULL;
+   WPARAM syscommand = (wParam & 0xfff0);
+   PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+   //PMONITOR mon = 0; Don't port sync from wine!!! This breaks explorer task bar sizing!!
+   //                  The task bar can grow in size and can not reduce due to the change
+   //                  in the work area.
+
+   Style = pwnd->style;
+   ExStyle = pwnd->ExStyle;
+   iconic = (Style & WS_MINIMIZE) != 0;
+
+   if ((Style & WS_MAXIMIZE) || !IntIsWindowVisible(pwnd)) return;
+
+   thickframe = UserHasThickFrameStyle(Style, ExStyle) && !iconic;
+
+   //
+   // Show window contents while dragging the window, get flag from registry data.
+   //
+   UserSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
+
+   pt.x = pti->ptLast.x;
+   pt.y = pti->ptLast.y;
+   capturePoint = pt;
+   UserClipCursor( NULL );
+
+   TRACE("pwnd %p command %04lx, hittest %d, pos %d,%d\n",
+          pwnd, syscommand, hittest, pt.x, pt.y);
+
+   if (syscommand == SC_MOVE)
+   {
+      if (!hittest) hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
+      if (!hittest) return;
+   }
+   else  /* SC_SIZE */
+   {
+      if (!thickframe) return;
+      if (hittest && (syscommand != SC_MOUSEMENU))
+      {
+          hittest += (HTLEFT - WMSZ_LEFT);
+      }
+      else
+      {
+          co_UserSetCapture(UserHMGetHandle(pwnd));
+          hittest = DefWndStartSizeMove(pwnd, wParam, &capturePoint);
+         if (!hittest)
+          {
+              IntReleaseCapture();
+              return;
+          }
+      }
+   }
+
+   /* Get min/max info */
+
+   co_WinPosGetMinMaxInfo(pwnd, NULL, NULL, &minTrack, &maxTrack);
+   sizingRect = pwnd->rcWindow;
+   origRect = sizingRect;
+   if (Style & WS_CHILD)
+   {
+      pWndParent = IntGetParent(pwnd);
+      IntGetClientRect( pWndParent, &mouseRect );
+      IntMapWindowPoints( pWndParent, 0, (LPPOINT)&mouseRect, 2 );
+      IntMapWindowPoints( 0, pWndParent, (LPPOINT)&sizingRect, 2 );
+      unmodRect = sizingRect;
+   }
+   else
+   {
+      if (!(ExStyle & WS_EX_TOPMOST))
+      {
+        UserSystemParametersInfo(SPI_GETWORKAREA, 0, &mouseRect, 0);
+      }
+      else
+      {
+        RECTL_vSetRect(&mouseRect, 0, 0, UserGetSystemMetrics(SM_CXSCREEN), UserGetSystemMetrics(SM_CYSCREEN));
+      }
+      unmodRect = sizingRect;
+   }
+
+   if (ON_LEFT_BORDER(hittest))
+   {
+      mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x+capturePoint.x-sizingRect.left );
+      mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x+capturePoint.x-sizingRect.left );
+   }
+   else if (ON_RIGHT_BORDER(hittest))
+   {
+      mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x+capturePoint.x-sizingRect.right );
+      mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x+capturePoint.x-sizingRect.right );
+   }
+   if (ON_TOP_BORDER(hittest))
+   {
+      mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y+capturePoint.y-sizingRect.top );
+      mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y+capturePoint.y-sizingRect.top);
+   }
+   else if (ON_BOTTOM_BORDER(hittest))
+   {
+      mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y+capturePoint.y-sizingRect.bottom );
+      mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y+capturePoint.y-sizingRect.bottom );
+   }
+
+   hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE );
+   if (iconic)
+   {
+       DragCursor = pwnd->pcls->spicn;
+       if (DragCursor)
+       {
+           UserReferenceObject(DragCursor);
+       }
+       else
+       {
+           HCURSOR CursorHandle = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 );
+           if (CursorHandle)
+           {
+               DragCursor = UserGetCurIconObject(CursorHandle);
+           }
+           else
+           {
+               iconic = FALSE;
+           }
+       }
+   }
+
+   /* repaint the window before moving it around */
+   co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN);
+
+   IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZESTART, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
+
+   co_IntSendMessage( UserHMGetHandle(pwnd), WM_ENTERSIZEMOVE, 0, 0 );
+
+   MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, UserHMGetHandle(pwnd));
+
+   if (IntGetCapture() != UserHMGetHandle(pwnd)) co_UserSetCapture( UserHMGetHandle(pwnd) );
+
+   pwnd->head.pti->TIF_flags |= TIF_MOVESIZETRACKING;
+
+   for(;;)
+   {
+      int dx = 0, dy = 0;
+
+      if (!co_IntGetPeekMessage(&msg, 0, 0, 0, PM_REMOVE, TRUE)) break;
+      if (IntCallMsgFilter( &msg, MSGF_SIZE )) continue;
+
+      /* Exit on button-up, Return, or Esc */
+      if ((msg.message == WM_LBUTTONUP) ||
+         ((msg.message == WM_KEYDOWN) &&
+          ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
+
+      if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
+      {
+         IntTranslateKbdMessage( &msg , 0 );
+         IntDispatchMessage( &msg );
+         continue;  /* We are not interested in other messages */
+      }
+
+      pt = msg.pt;
+
+      if (msg.message == WM_KEYDOWN) switch(msg.wParam)
+      {
+       case VK_UP:    pt.y -= 8; break;
+       case VK_DOWN:  pt.y += 8; break;
+       case VK_LEFT:  pt.x -= 8; break;
+       case VK_RIGHT: pt.x += 8; break;
+      }
+
+      pt.x = max( pt.x, mouseRect.left );
+      pt.x = min( pt.x, mouseRect.right - 1 );
+      pt.y = max( pt.y, mouseRect.top );
+      pt.y = min( pt.y, mouseRect.bottom - 1 );
+
+      dx = pt.x - capturePoint.x;
+      dy = pt.y - capturePoint.y;
+
+      if (dx || dy)
+      {
+         if ( !moved )
+         {
+             moved = TRUE;
+          if ( iconic ) /* ok, no system popup tracking */
+          {
+              OldCursor = UserSetCursor(DragCursor, FALSE);
+              UserShowCursor( TRUE );
+          }
+          else if(!DragFullWindows)
+             UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+         }
+
+         if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE);
+         else
+         {
+             RECT newRect = unmodRect;
+
+             if (!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+             if (hittest == HTCAPTION) RECTL_vOffsetRect( &newRect, dx, dy );
+             if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
+             else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
+             if (ON_TOP_BORDER(hittest)) newRect.top += dy;
+             else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
+             capturePoint = pt;
+
+              //
+              //  Save the new position to the unmodified rectangle. This allows explorer task bar
+              //  sizing. Explorer will forces back the position unless a certain amount of sizing
+              //  has occurred.
+              //
+              unmodRect = newRect;
+
+             /* determine the hit location */
+              if (syscommand == SC_SIZE)
+              {
+                  WPARAM wpSizingHit = 0;
+
+                  if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
+                      wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
+                  co_IntSendMessage( UserHMGetHandle(pwnd), WM_SIZING, wpSizingHit, (LPARAM)&newRect );
+              }
+              else
+                  co_IntSendMessage( UserHMGetHandle(pwnd), WM_MOVING, 0, (LPARAM)&newRect );
+
+             if (!iconic)
+              {
+                 if (!DragFullWindows)
+                     UserDrawMovingFrame( hdc, &newRect, thickframe );
+                 else
+                 {  // Moving the whole window now!
+                    PWND pwndTemp;
+                    //// This causes the mdi child window to jump up when it is moved.
+                    //IntMapWindowPoints( 0, pWndParent, (POINT *)&rect, 2 );
+                   co_WinPosSetWindowPos( pwnd,
+                                          0,
+                                          newRect.left,
+                                          newRect.top,
+                                          newRect.right - newRect.left,
+                                          newRect.bottom - newRect.top,
+                                         ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+
+                    // Update all the windows after the move or size, including this window.
+                    for ( pwndTemp = pwnd->head.rpdesk->pDeskInfo->spwnd->spwndChild;
+                          pwndTemp;
+                          pwndTemp = pwndTemp->spwndNext )
+                    {
+                       RECTL rect;
+                       // Only the windows that overlap will be redrawn.
+                       if (RECTL_bIntersectRect( &rect, &pwnd->rcWindow, &pwndTemp->rcWindow ))
+                       {
+                          co_UserRedrawWindow( pwndTemp, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
+                       }
+                    }
+                 }
+              }
+              sizingRect = newRect;
+         }
+      }
+   }
+
+   pwnd->head.pti->TIF_flags &= ~TIF_MOVESIZETRACKING;
+
+   IntReleaseCapture();
+
+   if ( iconic )
+   {
+      if ( moved ) /* restore cursors, show icon title later on */
+      {
+          UserShowCursor( FALSE );
+          OldCursor = UserSetCursor(OldCursor, FALSE);
+      }
+
+      /* It could be that the cursor was already changed while we were proceeding,
+       * so we must unreference whatever cursor was current at the time we restored the old one.
+       * Maybe it is DragCursor, but maybe it is another one and DragCursor got already freed.
+       */
+      if (OldCursor) UserDereferenceObject(OldCursor);
+   }
+   else if ( moved && !DragFullWindows )
+      UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+
+   UserReleaseDC(NULL, hdc, FALSE);
+
+   //// This causes the mdi child window to jump up when it is moved.
+   //if (pWndParent) IntMapWindowPoints( 0, pWndParent, (POINT *)&sizingRect, 2 );
+
+   if (co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)UserHMGetHandle(pwnd), (LPARAM)&sizingRect))
+   {
+      ERR("DoSizeMove : WH_CBT Call Hook return!\n");
+      moved = FALSE;
+   }
+
+   IntNotifyWinEvent( EVENT_SYSTEM_MOVESIZEEND, pwnd, OBJID_WINDOW, CHILDID_SELF, 0);
+
+   MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
+
+   co_IntSendMessage( UserHMGetHandle(pwnd), WM_EXITSIZEMOVE, 0, 0 );
+   //// wine mdi hack
+   co_IntSendMessage( UserHMGetHandle(pwnd), WM_SETVISIBLE, !!(pwnd->style & WS_MINIMIZE), 0L);
+   ////
+   /* window moved or resized */
+   if (moved)
+   {
+      /* if the moving/resizing isn't canceled call SetWindowPos
+       * with the new position or the new size of the window
+       */
+      if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
+      {
+         /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
+         if (!DragFullWindows || iconic )
+         {
+           co_WinPosSetWindowPos( pwnd,
+                                  0,
+                                  sizingRect.left,
+                                  sizingRect.top,
+                                  sizingRect.right - sizingRect.left,
+                                  sizingRect.bottom - sizingRect.top,
+                                 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+          }
+      }
+      else
+      { /* restore previous size/position */
+       if ( DragFullWindows )
+       {
+         co_WinPosSetWindowPos( pwnd,
+                                0,
+                                origRect.left,
+                                origRect.top,
+                                origRect.right - origRect.left,
+                                origRect.bottom - origRect.top,
+                               ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+        }
+      }
+   }
+
+   if ( IntIsWindow(UserHMGetHandle(pwnd)) )
+   {
+     if ( iconic )
+     {
+       /* Single click brings up the system menu when iconized */
+       if ( !moved )
+        {
+           if( Style & WS_SYSMENU )
+             co_IntSendMessage( UserHMGetHandle(pwnd), WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
+        }
+     }
+   }
+}
+
+PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd )
+{
+    PCURICON_OBJECT pIcon = NULL;
+    HICON hIcon;
+
+   //FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon".
+   //FIXME: Hence we must return a pointer with no reference count.
+   //FIXME: This is bad and we should feel bad.
+   //FIXME: Stop whining over wine code.
+
+   hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp);
+   if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
+
+   if (!hIcon && pWnd->pcls->spicnSm)
+       return pWnd->pcls->spicnSm;
+   if (!hIcon && pWnd->pcls->spicn)
+       return pWnd->pcls->spicn;
+
+   if (!hIcon && (pWnd->style & DS_MODALFRAME))
+   {
+      if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
+      if (!hIcon) hIcon = gpsi->hIconWindows;   // Reg size.
+   }
+   if (hIcon)
+   {
+       pIcon = UserGetCurIconObject(hIcon);
+       if (pIcon)
+       {
+           UserDereferenceObject(pIcon);
+       }
+   }
+   return pIcon;
+}
+
+DWORD FASTCALL
+GetNCHitEx(PWND pWnd, POINT pt)
+{
+   RECT rcWindow, rcClient;
+   DWORD Style, ExStyle;
+
+   if (!pWnd) return HTNOWHERE;
+
+   if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP)
+   {
+      rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0;
+      rcWindow.right  = UserGetSystemMetrics(SM_CXSCREEN);
+      rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN);
+      rcClient.right  = UserGetSystemMetrics(SM_CXSCREEN);
+      rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN);
+   }
+   else
+   {
+      rcClient = pWnd->rcClient;
+      rcWindow = pWnd->rcWindow;
+   }
+
+   if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE;
+
+   Style = pWnd->style;
+   ExStyle = pWnd->ExStyle;
+
+   if (Style & WS_MINIMIZE) return HTCAPTION;
+
+   if (RECTL_bPointInRect( &rcClient,  pt.x, pt.y )) return HTCLIENT;
+
+   /* Check borders */
+   if (HAS_THICKFRAME( Style, ExStyle ))
+   {
+      RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) );
+      if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y ))
+      {
+            /* Check top sizing border */
+            if (pt.y < rcWindow.top)
+            {
+                if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
+                if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
+                return HTTOP;
+            }
+            /* Check bottom sizing border */
+            if (pt.y >= rcWindow.bottom)
+            {
+                if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
+                if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
+                return HTBOTTOM;
+            }
+            /* Check left sizing border */
+            if (pt.x < rcWindow.left)
+            {
+                if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
+                if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
+                return HTLEFT;
+            }
+            /* Check right sizing border */
+            if (pt.x >= rcWindow.right)
+            {
+                if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
+                if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
+                return HTRIGHT;
+            }
+        }
+    }
+    else  /* No thick frame */
+    {
+        if (HAS_DLGFRAME( Style, ExStyle ))
+            RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME));
+        else if (HAS_THINFRAME( Style, ExStyle ))
+            RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER));
+        if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y  )) return HTBORDER;
+    }
+
+    /* Check caption */
+
+    if ((Style & WS_CAPTION) == WS_CAPTION)
+    {
+        if (ExStyle & WS_EX_TOOLWINDOW)
+            rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1;
+        else
+            rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1;
+        if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y ))
+        {
+            BOOL min_or_max_box = (Style & WS_SYSMENU) && (Style & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX));
+            if (ExStyle & WS_EX_LAYOUTRTL)
+            {
+                /* Check system menu */
+                if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
+                {
+                    rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
+                    if (pt.x > rcWindow.right) return HTSYSMENU;
+                }
+
+                /* Check close button */
+                if (Style & WS_SYSMENU)
+                {
+                    rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION);
+                    if (pt.x < rcWindow.left) return HTCLOSE;
+                }
+
+                /* Check maximize box */
+                /* In Win95 there is automatically a Maximize button when there is a minimize one */
+                if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
+                {
+                    rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
+                    if (pt.x < rcWindow.left) return HTMAXBUTTON;
+                }
+
+                /* Check minimize box */
+                if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
+                {
+                    rcWindow.left += UserGetSystemMetrics(SM_CXSIZE);
+                    if (pt.x < rcWindow.left) return HTMINBUTTON;
+                }
+            }
+            else
+            {
+                /* Check system menu */
+                if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd))
+                {
+                    rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1;
+                    if (pt.x < rcWindow.left) return HTSYSMENU;
+                }
+
+                /* Check close button */
+                if (Style & WS_SYSMENU)
+                {
+                    rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION);
+                    if (pt.x > rcWindow.right) return HTCLOSE;
+                }
+
+                /* Check maximize box */
+                /* In Win95 there is automatically a Maximize button when there is a minimize one */
+                if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
+                {
+                    rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
+                    if (pt.x > rcWindow.right) return HTMAXBUTTON;
+                }
+
+                /* Check minimize box */
+                if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW))
+                {
+                    rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE);
+                    if (pt.x > rcWindow.right) return HTMINBUTTON;
+                }
+            }
+            return HTCAPTION;
+        }
+    }
+
+      /* Check menu bar */
+
+    if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) &&
+        (pt.x >= rcClient.left) && (pt.x < rcClient.right))
+        return HTMENU;
+
+      /* Check vertical scroll bar */
+
+    if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR;
+    if (Style & WS_VSCROLL)
+    {
+        if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
+            rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL);
+        else
+            rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL);
+        if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL;
+    }
+
+      /* Check horizontal scroll bar */
+
+    if (Style & WS_HSCROLL)
+    {
+        rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL);
+        if (RECTL_bPointInRect( &rcClient, pt.x, pt.y ))
+        {
+            /* Check size box */
+            if ((Style & WS_VSCROLL) &&
+                ((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) ||
+                (((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL)))))
+                return HTSIZE;
+            return HTHSCROLL;
+        }
+    }
+
+    /* Has to return HTNOWHERE if nothing was found
+       Could happen when a window has a customized non client area */
+    return HTNOWHERE;
+}
+
+/* EOF */
index 7f86ccd..a79c130 100644 (file)
@@ -1127,55 +1127,6 @@ IntGetPaintMessage(
    return TRUE;
 }
 
-static
-HWND FASTCALL
-co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags)
-{
-   PDESKTOP Desktop;
-   PTHRDCARETINFO CaretInfo;
-   PTHREADINFO pti;
-   PUSER_MESSAGE_QUEUE ActiveMessageQueue;
-   HWND hWndCaret;
-   PWND WndCaret;
-
-   ASSERT_REFS_CO(Window);
-
-   pti = PsGetCurrentThreadWin32Thread();
-   Desktop = pti->rpdesk;
-   ActiveMessageQueue = Desktop->ActiveMessageQueue;
-   if (!ActiveMessageQueue) return 0;
-   CaretInfo = ActiveMessageQueue->CaretInfo;
-   hWndCaret = CaretInfo->hWnd;
-
-   WndCaret = ValidateHwndNoErr(hWndCaret);
-
-   // FIXME: Check for WndCaret can be NULL
-   if (WndCaret == Window ||
-         ((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
-   {
-      POINT pt, FromOffset, ToOffset;
-      RECTL rcCaret;
-
-      pt.x = CaretInfo->Pos.x;
-      pt.y = CaretInfo->Pos.y;
-      IntGetClientOrigin(WndCaret, &FromOffset);
-      IntGetClientOrigin(Window, &ToOffset);
-      rcCaret.left = pt.x;
-      rcCaret.top = pt.y;
-      rcCaret.right = pt.x + CaretInfo->Size.cx;
-      rcCaret.bottom = pt.y + CaretInfo->Size.cy;
-      if (RECTL_bIntersectRect(lprc, lprc, &rcCaret))
-      {
-         co_UserHideCaret(0);
-         lprc->left = pt.x;
-         lprc->top = pt.y;
-         return hWndCaret;
-      }
-   }
-
-   return 0;
-}
-
 BOOL
 FASTCALL
 IntPrintWindow(
@@ -1914,553 +1865,6 @@ CLEANUP:
    END_CLEANUP;
 }
 
-/*
-    Old GetUpdateRgn, for scrolls, see above note.
- */
-INT FASTCALL
-co_IntGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
-{
-    int RegionType;
-    RECTL Rect;
-    PREGION UpdateRgn;
-
-    ASSERT_REFS_CO(Window);
-
-    if (bErase)
-    {
-       co_IntPaintWindows(Window, RDW_NOCHILDREN, FALSE);
-    }
-
-    Window->state &= ~WNDS_UPDATEDIRTY;
-
-    if (Window->hrgnUpdate == NULL)
-    {
-        REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
-        return NULLREGION;
-    }
-
-    UpdateRgn = REGION_LockRgn(Window->hrgnUpdate);
-    if (!UpdateRgn)
-       return ERROR;
-
-    Rect = Window->rcClient;
-    IntIntersectWithParents(Window, &Rect);
-    REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
-    RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
-    REGION_bOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
-    REGION_UnlockRgn(UpdateRgn);
-
-    return RegionType;
-}
-
-static
-INT FASTCALL
-UserScrollDC(
-   HDC hDC,
-   INT dx,
-   INT dy,
-   const RECTL *prcScroll,
-   const RECTL *prcClip,
-   HRGN hrgnUpdate,
-   PREGION RgnUpdate,
-   RECTL *prcUpdate)
-{
-   PDC pDC;
-   RECTL rcScroll, rcClip, rcSrc, rcDst;
-   INT Result;
-
-   if (GdiGetClipBox(hDC, &rcClip) == ERROR)
-   {
-       ERR("GdiGetClipBox failed for HDC %p\n", hDC);
-       return ERROR;
-   }
-
-   rcScroll = rcClip;
-   if (prcClip)
-   {
-      RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
-   }
-
-   if (prcScroll)
-   {
-      rcScroll = *prcScroll;
-      RECTL_bIntersectRect(&rcSrc, &rcClip, prcScroll);
-   }
-   else
-   {
-      rcSrc = rcClip;
-   }
-
-   rcDst = rcSrc;
-   RECTL_vOffsetRect(&rcDst, dx, dy);
-   RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
-
-   if (!NtGdiBitBlt( hDC,
-                     rcDst.left,
-                     rcDst.top,
-                     rcDst.right - rcDst.left,
-                     rcDst.bottom - rcDst.top,
-                     hDC,
-                     rcDst.left - dx,
-                     rcDst.top - dy,
-                     SRCCOPY,
-                     0,
-                     0))
-   {
-      return ERROR;
-   }
-
-   /* Calculate the region that was invalidated by moving or
-      could not be copied, because it was not visible */
-   if (RgnUpdate || hrgnUpdate || prcUpdate)
-   {
-      PREGION RgnOwn, RgnTmp;
-
-      pDC = DC_LockDc(hDC);
-      if (!pDC)
-      {
-         return ERROR;
-      }
-
-       if (hrgnUpdate)
-       {
-           NT_ASSERT(RgnUpdate == NULL);
-           RgnUpdate = REGION_LockRgn(hrgnUpdate);
-           if (!RgnUpdate)
-           {
-               DC_UnlockDc(pDC);
-               return ERROR;
-           }
-       }
-
-      /* Begin with the shifted and then clipped scroll rect */
-      rcDst = rcScroll;
-      RECTL_vOffsetRect(&rcDst, dx, dy);
-      RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
-      if (RgnUpdate)
-      {
-         RgnOwn = RgnUpdate;
-         REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
-      }
-      else
-      {
-         RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
-      }
-
-      /* Add the source rect */
-      RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
-      IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
-
-      /* Substract the part of the dest that was visible in source */
-      IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
-      REGION_bOffsetRgn(RgnTmp, dx, dy);
-      Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
-
-      /* DO NOT Unlock DC while messing with prgnVis! */
-      DC_UnlockDc(pDC);
-
-      REGION_Delete(RgnTmp);
-
-      if (prcUpdate)
-      {
-         REGION_GetRgnBox(RgnOwn, prcUpdate);
-      }
-
-      if (hrgnUpdate)
-      {
-         REGION_UnlockRgn(RgnUpdate);
-      }
-      else if (!RgnUpdate)
-      {
-         REGION_Delete(RgnOwn);
-      }
-   }
-   else
-      Result = NULLREGION;
-
-   return Result;
-}
-
-/*
- * NtUserScrollDC
- *
- * Status
- *    @implemented
- */
-BOOL APIENTRY
-NtUserScrollDC(
-   HDC hDC,
-   INT dx,
-   INT dy,
-   const RECT *prcUnsafeScroll,
-   const RECT *prcUnsafeClip,
-   HRGN hrgnUpdate,
-   LPRECT prcUnsafeUpdate)
-{
-   DECLARE_RETURN(DWORD);
-   RECTL rcScroll, rcClip, rcUpdate;
-   NTSTATUS Status = STATUS_SUCCESS;
-   DWORD Result;
-
-   TRACE("Enter NtUserScrollDC\n");
-   UserEnterExclusive();
-
-   _SEH2_TRY
-   {
-      if (prcUnsafeScroll)
-      {
-         ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
-         rcScroll = *prcUnsafeScroll;
-      }
-      if (prcUnsafeClip)
-      {
-         ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
-         rcClip = *prcUnsafeClip;
-      }
-      if (prcUnsafeUpdate)
-      {
-         ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
-      }
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-      Status = _SEH2_GetExceptionCode();
-   }
-   _SEH2_END
-   if (!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN(FALSE);
-   }
-
-   Result = UserScrollDC( hDC,
-                          dx,
-                          dy,
-                          prcUnsafeScroll? &rcScroll : 0,
-                          prcUnsafeClip? &rcClip : 0,
-                          hrgnUpdate,
-                          NULL,
-                          prcUnsafeUpdate? &rcUpdate : NULL);
-   if(Result == ERROR)
-   {
-         /* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */
-      RETURN(FALSE);
-   }
-
-   if (prcUnsafeUpdate)
-   {
-      _SEH2_TRY
-      {
-         *prcUnsafeUpdate = rcUpdate;
-      }
-      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-      {
-         Status = _SEH2_GetExceptionCode();
-      }
-      _SEH2_END
-      if (!NT_SUCCESS(Status))
-      {
-         /* FIXME: SetLastError? */
-         /* FIXME: correct? We have already scrolled! */
-         RETURN(FALSE);
-      }
-   }
-
-   RETURN(TRUE);
-
-CLEANUP:
-   TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-/*
- * NtUserScrollWindowEx
- *
- * Status
- *    @implemented
- */
-
-DWORD APIENTRY
-NtUserScrollWindowEx(
-   HWND hWnd,
-   INT dx,
-   INT dy,
-   const RECT *prcUnsafeScroll,
-   const RECT *prcUnsafeClip,
-   HRGN hrgnUpdate,
-   LPRECT prcUnsafeUpdate,
-   UINT flags)
-{
-   RECTL rcScroll, rcClip, rcCaret, rcUpdate;
-   INT Result;
-   PWND Window = NULL, CaretWnd;
-   HDC hDC;
-   PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
-   HWND hwndCaret;
-   DWORD dcxflags = 0;
-   int rdw_flags;
-   NTSTATUS Status = STATUS_SUCCESS;
-   DECLARE_RETURN(DWORD);
-   USER_REFERENCE_ENTRY Ref, CaretRef;
-
-   TRACE("Enter NtUserScrollWindowEx\n");
-   UserEnterExclusive();
-
-   Window = UserGetWindowObject(hWnd);
-   if (!Window || !IntIsWindowDrawable(Window))
-   {
-      Window = NULL; /* prevent deref at cleanup */
-      RETURN( ERROR);
-   }
-   UserRefObjectCo(Window, &Ref);
-
-   IntGetClientRect(Window, &rcClip);
-
-   _SEH2_TRY
-   {
-      if (prcUnsafeScroll)
-      {
-         ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
-         RECTL_bIntersectRect(&rcScroll, &rcClip, prcUnsafeScroll);
-      }
-      else
-         rcScroll = rcClip;
-
-      if (prcUnsafeClip)
-      {
-         ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
-         RECTL_bIntersectRect(&rcClip, &rcClip, prcUnsafeClip);
-      }
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-      Status = _SEH2_GetExceptionCode();
-   }
-   _SEH2_END
-
-   if (!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN(ERROR);
-   }
-
-   if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
-         (dx == 0 && dy == 0))
-   {
-      RETURN(NULLREGION);
-   }
-
-   /* We must use a copy of the region, as we can't hold an exclusive lock
-    * on it while doing callouts to user-mode */
-   RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
-   if(!RgnUpdate)
-   {
-       EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-       RETURN(ERROR);
-   }
-
-   if (hrgnUpdate)
-   {
-       RgnTemp = REGION_LockRgn(hrgnUpdate);
-       if (!RgnTemp)
-       {
-           EngSetLastError(ERROR_INVALID_HANDLE);
-           RETURN(ERROR);
-       }
-       IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
-       REGION_UnlockRgn(RgnTemp);
-   }
-
-   /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
-   if (flags & SW_SCROLLWNDDCE)
-   {
-      dcxflags = DCX_USESTYLE;
-
-      if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
-         dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
-
-      if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
-         dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
-   }
-   else
-   {
-       /* So in this case ScrollWindowEx uses Cache DC. */
-       dcxflags = DCX_CACHE|DCX_USESTYLE;
-       if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
-   }
-
-   hDC = UserGetDCEx(Window, 0, dcxflags);
-   if (!hDC)
-   {
-      /* FIXME: SetLastError? */
-      RETURN(ERROR);
-   }
-
-   rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
-
-   rcCaret = rcScroll;
-   hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
-
-   Result = UserScrollDC( hDC,
-                          dx,
-                          dy,
-                          &rcScroll,
-                          &rcClip,
-                          NULL,
-                          RgnUpdate,
-                          prcUnsafeUpdate? &rcUpdate : NULL);
-
-   UserReleaseDC(Window, hDC, FALSE);
-
-   /*
-    * Take into account the fact that some damage may have occurred during
-    * the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
-    */
-
-   RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
-   if (!RgnTemp)
-   {
-       EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-       RETURN(ERROR);
-   }
-
-   if (co_IntGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
-   {
-      PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
-      if (RgnClip)
-      {
-          if (hrgnUpdate)
-          {
-             RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
-             IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
-          }
-
-          REGION_bOffsetRgn(RgnTemp, dx, dy);
-
-          IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
-
-          if (hrgnUpdate)
-              IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
-
-          co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
-
-          REGION_Delete(RgnClip);
-      }
-   }
-   REGION_Delete(RgnTemp);
-
-   if (flags & SW_SCROLLCHILDREN)
-   {
-      PWND Child;
-      RECTL rcChild;
-      POINT ClientOrigin;
-      USER_REFERENCE_ENTRY WndRef;
-      RECTL rcDummy;
-      LPARAM lParam;
-
-      IntGetClientOrigin(Window, &ClientOrigin);
-
-      for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
-      {
-         rcChild = Child->rcWindow;
-         rcChild.left -= ClientOrigin.x;
-         rcChild.top -= ClientOrigin.y;
-         rcChild.right -= ClientOrigin.x;
-         rcChild.bottom -= ClientOrigin.y;
-
-         if (!prcUnsafeScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
-         {
-            UserRefObjectCo(Child, &WndRef);
-
-            if (Window->spwndParent == UserGetDesktopWindow()) // Window->spwndParent->fnid == FNID_DESKTOP )
-               lParam = MAKELONG(Child->rcClient.left, Child->rcClient.top);
-            else
-               lParam = MAKELONG(rcChild.left + dx, rcChild.top + dy);
-
-            /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
-            /* windows sometimes a WM_MOVE */                  
-            co_IntSendMessage(UserHMGetHandle(Child), WM_MOVE, 0, lParam);
-            
-            UserDerefObjectCo(Child);
-         }
-      }
-   }
-
-   if (flags & (SW_INVALIDATE | SW_ERASE))
-   {
-      co_UserRedrawWindow( Window,
-                           NULL,
-                           RgnUpdate,
-                           rdw_flags |                                    /*    HACK    */
-                          ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : RDW_NOCHILDREN) );
-   }
-
-   if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
-   {
-      UserRefObjectCo(CaretWnd, &CaretRef);
-
-      co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
-      co_UserShowCaret(CaretWnd);
-
-      UserDerefObjectCo(CaretWnd);
-   }
-
-   if (prcUnsafeUpdate)
-   {
-      _SEH2_TRY
-      {
-         /* Probe here, to not fail on invalid pointer before scrolling */
-         ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
-         *prcUnsafeUpdate = rcUpdate;
-      }
-      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-      {
-         Status = _SEH2_GetExceptionCode();
-      }
-      _SEH2_END
-
-      if (!NT_SUCCESS(Status))
-      {
-         SetLastNtError(Status);
-         RETURN(ERROR);
-      }
-   }
-
-   RETURN(Result);
-
-CLEANUP:
-   if (hrgnUpdate && (_ret_ != ERROR))
-   {
-       /* Give everything back to the caller */
-       RgnTemp = REGION_LockRgn(hrgnUpdate);
-       /* The handle should still be valid */
-       ASSERT(RgnTemp);
-       if (RgnWinupd)
-           IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
-       else
-           IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
-       REGION_UnlockRgn(RgnTemp);
-   }
-
-   if (RgnWinupd)
-   {
-       REGION_Delete(RgnWinupd);
-   }
-
-   if (RgnUpdate)
-   {
-      REGION_Delete(RgnUpdate);
-   }
-
-   if (Window)
-      UserDerefObjectCo(Window);
-
-   TRACE("Leave NtUserScrollWindowEx, ret=%lu\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
 static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
 
 BOOL
index c212d6f..307ddbd 100644 (file)
@@ -32,3 +32,5 @@ BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT);
 HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);
 PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND );
 BOOL FASTCALL IntFlashWindowEx(PWND,PFLASHWINFO);
+BOOL FASTCALL IntIntersectWithParents(PWND, RECTL *);
+BOOL FASTCALL IntIsWindowDrawable(PWND);
\ No newline at end of file
diff --git a/reactos/win32ss/user/ntuser/scrollex.c b/reactos/win32ss/user/ntuser/scrollex.c
new file mode 100644 (file)
index 0000000..e0cd635
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ *  COPYRIGHT:        See COPYING in the top level directory
+ *  PROJECT:          ReactOS Win32k subsystem
+ *  PURPOSE:          Window scrolling function
+ *  FILE:             win32ss/user/ntuser/scrollex.c
+ *  PROGRAMER:        Filip Navara (xnavara@volny.cz)
+ */
+
+#include <win32k.h>
+
+DBG_DEFAULT_CHANNEL(UserPainting);
+
+static
+HWND FASTCALL
+co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags)
+{
+   PDESKTOP Desktop;
+   PTHRDCARETINFO CaretInfo;
+   PTHREADINFO pti;
+   PUSER_MESSAGE_QUEUE ActiveMessageQueue;
+   HWND hWndCaret;
+   PWND WndCaret;
+
+   ASSERT_REFS_CO(Window);
+
+   pti = PsGetCurrentThreadWin32Thread();
+   Desktop = pti->rpdesk;
+   ActiveMessageQueue = Desktop->ActiveMessageQueue;
+   if (!ActiveMessageQueue) return 0;
+   CaretInfo = ActiveMessageQueue->CaretInfo;
+   hWndCaret = CaretInfo->hWnd;
+
+   WndCaret = ValidateHwndNoErr(hWndCaret);
+
+   // FIXME: Check for WndCaret can be NULL
+   if (WndCaret == Window ||
+         ((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
+   {
+      POINT pt, FromOffset, ToOffset;
+      RECTL rcCaret;
+
+      pt.x = CaretInfo->Pos.x;
+      pt.y = CaretInfo->Pos.y;
+      IntGetClientOrigin(WndCaret, &FromOffset);
+      IntGetClientOrigin(Window, &ToOffset);
+      rcCaret.left = pt.x;
+      rcCaret.top = pt.y;
+      rcCaret.right = pt.x + CaretInfo->Size.cx;
+      rcCaret.bottom = pt.y + CaretInfo->Size.cy;
+      if (RECTL_bIntersectRect(lprc, lprc, &rcCaret))
+      {
+         co_UserHideCaret(0);
+         lprc->left = pt.x;
+         lprc->top = pt.y;
+         return hWndCaret;
+      }
+   }
+
+   return 0;
+}
+
+/*
+    Old GetUpdateRgn, for scrolls, see above note.
+ */
+INT FASTCALL
+co_IntGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
+{
+    int RegionType;
+    RECTL Rect;
+    PREGION UpdateRgn;
+
+    ASSERT_REFS_CO(Window);
+
+    if (bErase)
+    {
+       co_IntPaintWindows(Window, RDW_NOCHILDREN, FALSE);
+    }
+
+    Window->state &= ~WNDS_UPDATEDIRTY;
+
+    if (Window->hrgnUpdate == NULL)
+    {
+        REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
+        return NULLREGION;
+    }
+
+    UpdateRgn = REGION_LockRgn(Window->hrgnUpdate);
+    if (!UpdateRgn)
+       return ERROR;
+
+    Rect = Window->rcClient;
+    IntIntersectWithParents(Window, &Rect);
+    REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
+    RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
+    REGION_bOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
+    REGION_UnlockRgn(UpdateRgn);
+
+    return RegionType;
+}
+
+static
+INT FASTCALL
+UserScrollDC(
+   HDC hDC,
+   INT dx,
+   INT dy,
+   const RECTL *prcScroll,
+   const RECTL *prcClip,
+   HRGN hrgnUpdate,
+   PREGION RgnUpdate,
+   RECTL *prcUpdate)
+{
+   PDC pDC;
+   RECTL rcScroll, rcClip, rcSrc, rcDst;
+   INT Result;
+
+   if (GdiGetClipBox(hDC, &rcClip) == ERROR)
+   {
+       ERR("GdiGetClipBox failed for HDC %p\n", hDC);
+       return ERROR;
+   }
+
+   rcScroll = rcClip;
+   if (prcClip)
+   {
+      RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
+   }
+
+   if (prcScroll)
+   {
+      rcScroll = *prcScroll;
+      RECTL_bIntersectRect(&rcSrc, &rcClip, prcScroll);
+   }
+   else
+   {
+      rcSrc = rcClip;
+   }
+
+   rcDst = rcSrc;
+   RECTL_vOffsetRect(&rcDst, dx, dy);
+   RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
+
+   if (!NtGdiBitBlt( hDC,
+                     rcDst.left,
+                     rcDst.top,
+                     rcDst.right - rcDst.left,
+                     rcDst.bottom - rcDst.top,
+                     hDC,
+                     rcDst.left - dx,
+                     rcDst.top - dy,
+                     SRCCOPY,
+                     0,
+                     0))
+   {
+      return ERROR;
+   }
+
+   /* Calculate the region that was invalidated by moving or
+      could not be copied, because it was not visible */
+   if (RgnUpdate || hrgnUpdate || prcUpdate)
+   {
+      PREGION RgnOwn, RgnTmp;
+
+      pDC = DC_LockDc(hDC);
+      if (!pDC)
+      {
+         return ERROR;
+      }
+
+       if (hrgnUpdate)
+       {
+           NT_ASSERT(RgnUpdate == NULL);
+           RgnUpdate = REGION_LockRgn(hrgnUpdate);
+           if (!RgnUpdate)
+           {
+               DC_UnlockDc(pDC);
+               return ERROR;
+           }
+       }
+
+      /* Begin with the shifted and then clipped scroll rect */
+      rcDst = rcScroll;
+      RECTL_vOffsetRect(&rcDst, dx, dy);
+      RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
+      if (RgnUpdate)
+      {
+         RgnOwn = RgnUpdate;
+         REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
+      }
+      else
+      {
+         RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
+      }
+
+      /* Add the source rect */
+      RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
+      IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
+
+      /* Substract the part of the dest that was visible in source */
+      IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
+      REGION_bOffsetRgn(RgnTmp, dx, dy);
+      Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
+
+      /* DO NOT Unlock DC while messing with prgnVis! */
+      DC_UnlockDc(pDC);
+
+      REGION_Delete(RgnTmp);
+
+      if (prcUpdate)
+      {
+         REGION_GetRgnBox(RgnOwn, prcUpdate);
+      }
+
+      if (hrgnUpdate)
+      {
+         REGION_UnlockRgn(RgnUpdate);
+      }
+      else if (!RgnUpdate)
+      {
+         REGION_Delete(RgnOwn);
+      }
+   }
+   else
+      Result = NULLREGION;
+
+   return Result;
+}
+
+/*
+ * NtUserScrollDC
+ *
+ * Status
+ *    @implemented
+ */
+BOOL APIENTRY
+NtUserScrollDC(
+   HDC hDC,
+   INT dx,
+   INT dy,
+   const RECT *prcUnsafeScroll,
+   const RECT *prcUnsafeClip,
+   HRGN hrgnUpdate,
+   LPRECT prcUnsafeUpdate)
+{
+   DECLARE_RETURN(DWORD);
+   RECTL rcScroll, rcClip, rcUpdate;
+   NTSTATUS Status = STATUS_SUCCESS;
+   DWORD Result;
+
+   TRACE("Enter NtUserScrollDC\n");
+   UserEnterExclusive();
+
+   _SEH2_TRY
+   {
+      if (prcUnsafeScroll)
+      {
+         ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
+         rcScroll = *prcUnsafeScroll;
+      }
+      if (prcUnsafeClip)
+      {
+         ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
+         rcClip = *prcUnsafeClip;
+      }
+      if (prcUnsafeUpdate)
+      {
+         ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
+      }
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      Status = _SEH2_GetExceptionCode();
+   }
+   _SEH2_END
+   if (!NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      RETURN(FALSE);
+   }
+
+   Result = UserScrollDC( hDC,
+                          dx,
+                          dy,
+                          prcUnsafeScroll? &rcScroll : 0,
+                          prcUnsafeClip? &rcClip : 0,
+                          hrgnUpdate,
+                          NULL,
+                          prcUnsafeUpdate? &rcUpdate : NULL);
+   if(Result == ERROR)
+   {
+         /* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */
+      RETURN(FALSE);
+   }
+
+   if (prcUnsafeUpdate)
+   {
+      _SEH2_TRY
+      {
+         *prcUnsafeUpdate = rcUpdate;
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+         Status = _SEH2_GetExceptionCode();
+      }
+      _SEH2_END
+      if (!NT_SUCCESS(Status))
+      {
+         /* FIXME: SetLastError? */
+         /* FIXME: correct? We have already scrolled! */
+         RETURN(FALSE);
+      }
+   }
+
+   RETURN(TRUE);
+
+CLEANUP:
+   TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+/*
+ * NtUserScrollWindowEx
+ *
+ * Status
+ *    @implemented
+ */
+
+DWORD APIENTRY
+NtUserScrollWindowEx(
+   HWND hWnd,
+   INT dx,
+   INT dy,
+   const RECT *prcUnsafeScroll,
+   const RECT *prcUnsafeClip,
+   HRGN hrgnUpdate,
+   LPRECT prcUnsafeUpdate,
+   UINT flags)
+{
+   RECTL rcScroll, rcClip, rcCaret, rcUpdate;
+   INT Result;
+   PWND Window = NULL, CaretWnd;
+   HDC hDC;
+   PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
+   HWND hwndCaret;
+   DWORD dcxflags = 0;
+   int rdw_flags;
+   NTSTATUS Status = STATUS_SUCCESS;
+   DECLARE_RETURN(DWORD);
+   USER_REFERENCE_ENTRY Ref, CaretRef;
+
+   TRACE("Enter NtUserScrollWindowEx\n");
+   UserEnterExclusive();
+
+   Window = UserGetWindowObject(hWnd);
+   if (!Window || !IntIsWindowDrawable(Window))
+   {
+      Window = NULL; /* prevent deref at cleanup */
+      RETURN( ERROR);
+   }
+   UserRefObjectCo(Window, &Ref);
+
+   IntGetClientRect(Window, &rcClip);
+
+   _SEH2_TRY
+   {
+      if (prcUnsafeScroll)
+      {
+         ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
+         RECTL_bIntersectRect(&rcScroll, &rcClip, prcUnsafeScroll);
+      }
+      else
+         rcScroll = rcClip;
+
+      if (prcUnsafeClip)
+      {
+         ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
+         RECTL_bIntersectRect(&rcClip, &rcClip, prcUnsafeClip);
+      }
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      Status = _SEH2_GetExceptionCode();
+   }
+   _SEH2_END
+
+   if (!NT_SUCCESS(Status))
+   {
+      SetLastNtError(Status);
+      RETURN(ERROR);
+   }
+
+   if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
+         (dx == 0 && dy == 0))
+   {
+      RETURN(NULLREGION);
+   }
+
+   /* We must use a copy of the region, as we can't hold an exclusive lock
+    * on it while doing callouts to user-mode */
+   RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
+   if(!RgnUpdate)
+   {
+       EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+       RETURN(ERROR);
+   }
+
+   if (hrgnUpdate)
+   {
+       RgnTemp = REGION_LockRgn(hrgnUpdate);
+       if (!RgnTemp)
+       {
+           EngSetLastError(ERROR_INVALID_HANDLE);
+           RETURN(ERROR);
+       }
+       IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
+       REGION_UnlockRgn(RgnTemp);
+   }
+
+   /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
+   if (flags & SW_SCROLLWNDDCE)
+   {
+      dcxflags = DCX_USESTYLE;
+
+      if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
+         dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
+
+      if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
+         dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
+   }
+   else
+   {
+       /* So in this case ScrollWindowEx uses Cache DC. */
+       dcxflags = DCX_CACHE|DCX_USESTYLE;
+       if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
+   }
+
+   hDC = UserGetDCEx(Window, 0, dcxflags);
+   if (!hDC)
+   {
+      /* FIXME: SetLastError? */
+      RETURN(ERROR);
+   }
+
+   rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
+
+   rcCaret = rcScroll;
+   hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
+
+   Result = UserScrollDC( hDC,
+                          dx,
+                          dy,
+                          &rcScroll,
+                          &rcClip,
+                          NULL,
+                          RgnUpdate,
+                          prcUnsafeUpdate? &rcUpdate : NULL);
+
+   UserReleaseDC(Window, hDC, FALSE);
+
+   /*
+    * Take into account the fact that some damage may have occurred during
+    * the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
+    */
+
+   RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
+   if (!RgnTemp)
+   {
+       EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+       RETURN(ERROR);
+   }
+
+   if (co_IntGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
+   {
+      PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
+      if (RgnClip)
+      {
+          if (hrgnUpdate)
+          {
+             RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
+             IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
+          }
+
+          REGION_bOffsetRgn(RgnTemp, dx, dy);
+
+          IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
+
+          if (hrgnUpdate)
+              IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
+
+          co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
+
+          REGION_Delete(RgnClip);
+      }
+   }
+   REGION_Delete(RgnTemp);
+
+   if (flags & SW_SCROLLCHILDREN)
+   {
+      PWND Child;
+      RECTL rcChild;
+      POINT ClientOrigin;
+      USER_REFERENCE_ENTRY WndRef;
+      RECTL rcDummy;
+      LPARAM lParam;
+
+      IntGetClientOrigin(Window, &ClientOrigin);
+
+      for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
+      {
+         rcChild = Child->rcWindow;
+         rcChild.left -= ClientOrigin.x;
+         rcChild.top -= ClientOrigin.y;
+         rcChild.right -= ClientOrigin.x;
+         rcChild.bottom -= ClientOrigin.y;
+
+         if (!prcUnsafeScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
+         {
+            UserRefObjectCo(Child, &WndRef);
+
+            if (Window->spwndParent == UserGetDesktopWindow()) // Window->spwndParent->fnid == FNID_DESKTOP )
+               lParam = MAKELONG(Child->rcClient.left, Child->rcClient.top);
+            else
+               lParam = MAKELONG(rcChild.left + dx, rcChild.top + dy);
+
+            /* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
+            /* windows sometimes a WM_MOVE */                  
+            co_IntSendMessage(UserHMGetHandle(Child), WM_MOVE, 0, lParam);
+            
+            UserDerefObjectCo(Child);
+         }
+      }
+   }
+
+   if (flags & (SW_INVALIDATE | SW_ERASE))
+   {
+      co_UserRedrawWindow( Window,
+                           NULL,
+                           RgnUpdate,
+                           rdw_flags |                                    /*    HACK    */
+                          ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : RDW_NOCHILDREN) );
+   }
+
+   if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
+   {
+      UserRefObjectCo(CaretWnd, &CaretRef);
+
+      co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
+      co_UserShowCaret(CaretWnd);
+
+      UserDerefObjectCo(CaretWnd);
+   }
+
+   if (prcUnsafeUpdate)
+   {
+      _SEH2_TRY
+      {
+         /* Probe here, to not fail on invalid pointer before scrolling */
+         ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
+         *prcUnsafeUpdate = rcUpdate;
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+         Status = _SEH2_GetExceptionCode();
+      }
+      _SEH2_END
+
+      if (!NT_SUCCESS(Status))
+      {
+         SetLastNtError(Status);
+         RETURN(ERROR);
+      }
+   }
+
+   RETURN(Result);
+
+CLEANUP:
+   if (hrgnUpdate && (_ret_ != ERROR))
+   {
+       /* Give everything back to the caller */
+       RgnTemp = REGION_LockRgn(hrgnUpdate);
+       /* The handle should still be valid */
+       ASSERT(RgnTemp);
+       if (RgnWinupd)
+           IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
+       else
+           IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
+       REGION_UnlockRgn(RgnTemp);
+   }
+
+   if (RgnWinupd)
+   {
+       REGION_Delete(RgnWinupd);
+   }
+
+   if (RgnUpdate)
+   {
+      REGION_Delete(RgnUpdate);
+   }
+
+   if (Window)
+      UserDerefObjectCo(Window);
+
+   TRACE("Leave NtUserScrollWindowEx, ret=%lu\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
+
+/* EOF */
index d46911d..2f0e386 100644 (file)
@@ -123,7 +123,10 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu);
 
 /*************** SCROLLBAR.C ***************/
 
-DWORD FASTCALL
-co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
+DWORD FASTCALL co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
+
+/************** NONCLIENT **************/
+
+VOID FASTCALL DefWndDoSizeMove(PWND pwnd, WORD wParam);
 
 /* EOF */