2003-05-18 17:16:18 +00:00
|
|
|
/*
|
|
|
|
* ReactOS W32 Subsystem
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
2003-09-24 13:41:40 +00:00
|
|
|
/* $Id: scrollbar.c,v 1.15 2003/09/24 13:41:40 weiden Exp $
|
2002-11-24 20:15:37 +00:00
|
|
|
*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* PURPOSE: Scrollbars
|
|
|
|
* FILE: subsys/win32k/ntuser/scrollbar.c
|
2003-09-24 13:41:40 +00:00
|
|
|
* PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
|
|
|
* Jason Filby (jasonfilby@yahoo.com)
|
2002-11-24 20:15:37 +00:00
|
|
|
* REVISION HISTORY:
|
|
|
|
* 16-11-2002 Jason Filby Created
|
|
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
|
|
|
#include <ddk/ntddk.h>
|
|
|
|
#include <win32k/win32k.h>
|
2003-09-24 13:41:40 +00:00
|
|
|
#include <internal/safe.h>
|
2002-11-24 20:15:37 +00:00
|
|
|
#include <include/object.h>
|
|
|
|
#include <include/window.h>
|
|
|
|
#include <include/class.h>
|
|
|
|
#include <include/error.h>
|
|
|
|
#include <include/winsta.h>
|
|
|
|
#include <include/winpos.h>
|
|
|
|
#include <include/rect.h>
|
2003-05-18 17:16:18 +00:00
|
|
|
#include <include/scroll.h>
|
2002-11-24 20:15:37 +00:00
|
|
|
|
|
|
|
//#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
#define MINTRACKTHUMB 8 /* Minimum size of the rectangle between the arrows */
|
2002-11-24 20:15:37 +00:00
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
#define SBRG_SCROLLBAR 0 /* the scrollbar itself */
|
|
|
|
#define SBRG_TOPRIGHTBTN 1 /* the top or right button */
|
|
|
|
#define SBRG_PAGEUPRIGHT 2 /* the page up or page right region */
|
|
|
|
#define SBRG_SCROLLBOX 3 /* the scroll box */
|
|
|
|
#define SBRG_PAGEDOWNLEFT 4 /* the page down or page left region */
|
|
|
|
#define SBRG_BOTTOMLEFTBTN 5 /* the bottom or left button */
|
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
#define SBU_TOPRIGHT 0x10
|
|
|
|
#define SBU_BOTTOMLEFT 0x20
|
|
|
|
#define SBU_SCROLLBOX 0x40
|
|
|
|
|
|
|
|
#ifndef SIZEOF_LONG_LONG
|
|
|
|
// FIXME enable this!
|
|
|
|
//#define SIZEOF_LONG_LONG 8
|
|
|
|
#endif
|
|
|
|
|
2003-09-08 15:08:56 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* MulDiv (copied from kernel32)
|
|
|
|
*/
|
|
|
|
static INT IntMulDiv(
|
|
|
|
INT nMultiplicand,
|
|
|
|
INT nMultiplier,
|
|
|
|
INT nDivisor)
|
|
|
|
{
|
|
|
|
#if SIZEOF_LONG_LONG >= 8
|
|
|
|
long long ret;
|
|
|
|
|
|
|
|
if (!nDivisor) return -1;
|
|
|
|
|
|
|
|
/* We want to deal with a positive divisor to simplify the logic. */
|
|
|
|
if (nDivisor < 0)
|
|
|
|
{
|
|
|
|
nMultiplicand = - nMultiplicand;
|
|
|
|
nDivisor = -nDivisor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the result is positive, we "add" to round. else, we subtract to round. */
|
|
|
|
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
|
|
|
|
( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
|
|
|
|
ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
|
|
|
|
else
|
|
|
|
ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
|
|
|
|
|
|
|
|
if ((ret > 2147483647) || (ret < -2147483647)) return -1;
|
|
|
|
return ret;
|
|
|
|
#else
|
|
|
|
if (!nDivisor) return -1;
|
|
|
|
|
|
|
|
/* We want to deal with a positive divisor to simplify the logic. */
|
|
|
|
if (nDivisor < 0)
|
|
|
|
{
|
|
|
|
nMultiplicand = - nMultiplicand;
|
|
|
|
nDivisor = -nDivisor;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the result is positive, we "add" to round. else, we subtract to round. */
|
|
|
|
if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
|
|
|
|
( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
|
|
|
|
return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
|
|
|
|
|
|
|
|
return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
|
2002-11-24 20:15:37 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
|
|
/* Ported from WINE20020904 */
|
|
|
|
/* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
|
|
|
|
* SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
|
|
|
|
* 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
|
|
|
|
* the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
|
|
|
|
*/
|
2003-09-07 09:55:52 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
IntGetScrollBarRect (PWINDOW_OBJECT Window, INT nBar, PRECT lprect)
|
2002-11-24 20:15:37 +00:00
|
|
|
{
|
|
|
|
BOOL vertical;
|
2002-12-21 19:25:41 +00:00
|
|
|
RECT ClientRect = Window->ClientRect;
|
|
|
|
RECT WindowRect = Window->WindowRect;
|
2002-11-24 20:15:37 +00:00
|
|
|
|
|
|
|
switch (nBar)
|
|
|
|
{
|
|
|
|
case SB_HORZ:
|
2003-09-12 12:54:26 +00:00
|
|
|
lprect->left = ClientRect.left - WindowRect.left + 1;
|
2002-12-21 19:25:41 +00:00
|
|
|
lprect->top = ClientRect.bottom - WindowRect.top;
|
2003-09-12 12:54:26 +00:00
|
|
|
lprect->right = ClientRect.right - WindowRect.left - 1;
|
2002-11-24 20:15:37 +00:00
|
|
|
lprect->bottom = lprect->top + NtUserGetSystemMetrics (SM_CYHSCROLL);
|
|
|
|
if (Window->Style & WS_BORDER)
|
|
|
|
{
|
|
|
|
lprect->left--;
|
|
|
|
lprect->right++;
|
|
|
|
}
|
|
|
|
vertical = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SB_VERT:
|
2003-05-26 10:52:15 +00:00
|
|
|
lprect->left = (ClientRect.right - WindowRect.left);
|
|
|
|
lprect->top = (ClientRect.top - WindowRect.top) + 1;
|
|
|
|
lprect->right = (lprect->left + NtUserGetSystemMetrics (SM_CXVSCROLL));
|
|
|
|
lprect->bottom = (ClientRect.bottom - WindowRect.top) - 1;
|
2002-11-24 20:15:37 +00:00
|
|
|
if (Window->Style & WS_BORDER)
|
|
|
|
{
|
|
|
|
lprect->top--;
|
|
|
|
lprect->bottom++;
|
|
|
|
}
|
|
|
|
else if (Window->Style & WS_HSCROLL)
|
|
|
|
lprect->bottom++;
|
|
|
|
vertical = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SB_CTL:
|
2003-08-19 11:48:50 +00:00
|
|
|
IntGetClientRect (Window, lprect);
|
2002-11-24 20:15:37 +00:00
|
|
|
vertical = ((Window->Style & SBS_VERT) != 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2003-08-19 11:48:50 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
2002-11-24 20:15:37 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return vertical;
|
|
|
|
}
|
|
|
|
|
2003-09-08 15:08:56 +00:00
|
|
|
BOOL FASTCALL
|
|
|
|
IntCalculateThumb(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi)
|
|
|
|
{
|
2003-09-12 12:54:26 +00:00
|
|
|
INT Thumb, ThumbBox, ThumbPos, cxy, mx;
|
2003-09-24 13:41:40 +00:00
|
|
|
RECT ClientRect;
|
|
|
|
|
2003-09-08 15:08:56 +00:00
|
|
|
switch(idObject)
|
|
|
|
{
|
|
|
|
case SB_HORZ:
|
2003-09-12 12:54:26 +00:00
|
|
|
Thumb = NtUserGetSystemMetrics(SM_CXHSCROLL);
|
2003-09-08 15:08:56 +00:00
|
|
|
cxy = psbi->rcScrollBar.right - psbi->rcScrollBar.left;
|
2003-09-12 12:54:26 +00:00
|
|
|
break;
|
2003-09-08 15:08:56 +00:00
|
|
|
case SB_VERT:
|
2003-09-12 12:54:26 +00:00
|
|
|
Thumb = NtUserGetSystemMetrics(SM_CYVSCROLL);
|
2003-09-08 15:08:56 +00:00
|
|
|
cxy = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top;
|
2003-09-12 12:54:26 +00:00
|
|
|
break;
|
2003-09-08 15:08:56 +00:00
|
|
|
case SB_CTL:
|
2003-09-24 13:41:40 +00:00
|
|
|
IntGetClientRect (Window, &ClientRect);
|
|
|
|
if(Window->Style & SBS_VERT)
|
|
|
|
{
|
|
|
|
Thumb = NtUserGetSystemMetrics(SM_CYVSCROLL);
|
|
|
|
cxy = ClientRect.bottom - ClientRect.top;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Thumb = NtUserGetSystemMetrics(SM_CXHSCROLL);
|
|
|
|
cxy = ClientRect.right - ClientRect.left;
|
|
|
|
}
|
|
|
|
break;
|
2003-09-08 15:08:56 +00:00
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-09-12 12:54:26 +00:00
|
|
|
|
|
|
|
ThumbPos = Thumb;
|
|
|
|
/* calculate Thumb */
|
|
|
|
if(cxy <= (2 * Thumb))
|
|
|
|
{
|
|
|
|
Thumb = cxy / 2;
|
|
|
|
psbi->xyThumbTop = 0;
|
|
|
|
psbi->xyThumbBottom = 0;
|
|
|
|
ThumbPos = Thumb;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ThumbBox = psi->nPage ? MINTRACKTHUMB : NtUserGetSystemMetrics(SM_CXHTHUMB);
|
|
|
|
cxy -= (2 * Thumb);
|
|
|
|
if(cxy >= ThumbBox)
|
|
|
|
{
|
|
|
|
if(psi->nPage)
|
|
|
|
{
|
|
|
|
ThumbBox = max(IntMulDiv(cxy, psi->nPage, psi->nMax - psi->nMin + 1), ThumbBox);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cxy > ThumbBox)
|
|
|
|
{
|
|
|
|
mx = psi->nMax - max(psi->nPage - 1, 0);
|
|
|
|
if(psi->nMin < mx)
|
|
|
|
ThumbPos = Thumb + IntMulDiv(cxy, psi->nPos - psi->nMin, psi->nMax - psi->nMin + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
psbi->xyThumbTop = ThumbPos;
|
|
|
|
psbi->xyThumbBottom = ThumbPos + ThumbBox;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
psbi->xyThumbTop = 0;
|
|
|
|
psbi->xyThumbBottom = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
psbi->dxyLineButton = Thumb;
|
|
|
|
|
|
|
|
return TRUE;
|
2003-09-08 15:08:56 +00:00
|
|
|
}
|
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
BOOL FASTCALL
|
|
|
|
IntGetScrollInfo(PWINDOW_OBJECT Window, INT nBar, LPSCROLLINFO lpsi)
|
|
|
|
{
|
|
|
|
UINT Mask;
|
|
|
|
LPSCROLLINFO psi;
|
|
|
|
PSCROLLBARINFO Info;
|
|
|
|
|
|
|
|
switch(nBar)
|
|
|
|
{
|
|
|
|
case SB_HORZ:
|
|
|
|
Info = Window->pHScroll;
|
|
|
|
if(Info)
|
|
|
|
break;
|
|
|
|
/* fall through */
|
|
|
|
case SB_VERT:
|
|
|
|
Info = Window->pVScroll;
|
|
|
|
if(Info)
|
|
|
|
break;
|
|
|
|
/* fall through */
|
|
|
|
case SB_CTL:
|
|
|
|
/* FIXME
|
|
|
|
Send a SBM_GETSCROLLINFO message to the window. Fail if the window
|
|
|
|
doesn't handle the message
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Info = Window->wExtra;
|
|
|
|
if(Info)
|
|
|
|
break;
|
|
|
|
/* fall through */
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
psi = (LPSCROLLINFO)((PSCROLLBARINFO)(Info + 1));
|
|
|
|
|
|
|
|
if(lpsi->fMask == SIF_ALL)
|
|
|
|
Mask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
|
|
|
|
else
|
|
|
|
Mask = lpsi->fMask;
|
|
|
|
|
|
|
|
if(Mask & SIF_PAGE)
|
|
|
|
{
|
|
|
|
lpsi->nPage = psi->nPage;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Mask & SIF_POS)
|
|
|
|
{
|
|
|
|
lpsi->nPos = psi->nPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Mask & SIF_RANGE)
|
|
|
|
{
|
|
|
|
lpsi->nMin = psi->nMin;
|
|
|
|
lpsi->nMax = psi->nMax;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD FASTCALL
|
|
|
|
IntSetScrollInfo(PWINDOW_OBJECT Window, INT nBar, LPSCROLLINFO lpsi, DWORD *Action)
|
|
|
|
{
|
|
|
|
PSCROLLBARINFO Info = NULL;
|
|
|
|
LPSCROLLINFO psi;
|
|
|
|
BOOL Chg = FALSE;
|
|
|
|
UINT Mask;
|
|
|
|
DWORD Ret;
|
|
|
|
|
|
|
|
if(((lpsi->cbSize != sizeof(SCROLLINFO)) &&
|
|
|
|
(lpsi->cbSize != sizeof(SCROLLINFO) - sizeof(lpsi->nTrackPos))))
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(nBar)
|
|
|
|
{
|
|
|
|
case SB_HORZ:
|
|
|
|
Info = Window->pHScroll;
|
|
|
|
if(Info)
|
|
|
|
break;
|
|
|
|
/* fall through */
|
|
|
|
case SB_VERT:
|
|
|
|
Info = Window->pVScroll;
|
|
|
|
if(Info)
|
|
|
|
break;
|
|
|
|
/* fall through */
|
|
|
|
case SB_CTL:
|
|
|
|
/* FIXME
|
|
|
|
Send SBM_SETSCROLLINFO message, propably optimize it to SBM_SETPOS or SBM_SETRANGE.
|
|
|
|
If the window doesn't handle the message return 0
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Info = Window->wExtra;
|
|
|
|
if(Info)
|
|
|
|
break;
|
|
|
|
/* fall through */
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
psi = (LPSCROLLINFO)((PSCROLLBARINFO)(Info + 1));
|
|
|
|
|
|
|
|
if(lpsi->fMask == SIF_ALL)
|
|
|
|
Mask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
|
|
|
|
else
|
|
|
|
Mask = lpsi->fMask;
|
|
|
|
|
|
|
|
if(Action)
|
|
|
|
*Action = 0;
|
|
|
|
|
|
|
|
if(Mask & SIF_DISABLENOSCROLL)
|
|
|
|
{
|
|
|
|
/* FIXME */
|
|
|
|
}
|
|
|
|
|
|
|
|
if((Mask & SIF_RANGE) && ((psi->nMin != lpsi->nMin) || (psi->nMax != lpsi->nMax)))
|
|
|
|
{
|
|
|
|
/* Invalid range -> range is set to (0,0) */
|
|
|
|
if((lpsi->nMin > lpsi->nMax) ||
|
|
|
|
((UINT)(lpsi->nMax - lpsi->nMin) >= 0x80000000))
|
|
|
|
{
|
|
|
|
psi->nMin = 0;
|
|
|
|
psi->nMax = 0;
|
|
|
|
Chg = TRUE;
|
|
|
|
if(Action)
|
|
|
|
*Action |= SBU_SCROLLBOX;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(psi->nMin != lpsi->nMin ||
|
|
|
|
psi->nMax != lpsi->nMax )
|
|
|
|
{
|
|
|
|
//*action |= SA_SSI_REFRESH;
|
|
|
|
psi->nMin = lpsi->nMin;
|
|
|
|
psi->nMax = lpsi->nMax;
|
|
|
|
Chg = TRUE;
|
|
|
|
if(Action)
|
|
|
|
*Action |= SBU_SCROLLBOX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if((Mask & SIF_PAGE) && (psi->nPage != lpsi->nPage))
|
|
|
|
{
|
|
|
|
psi->nPage = lpsi->nPage;
|
|
|
|
Chg = TRUE;
|
|
|
|
if(Action)
|
|
|
|
*Action |= SBU_SCROLLBOX;
|
|
|
|
if(psi->nPage < 0) psi->nPage = 0;
|
|
|
|
else if(psi->nPage > psi->nMax - psi->nMin + 1)
|
|
|
|
psi->nPage = psi->nMax - psi->nMin + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((Mask & SIF_POS) && (psi->nPos != lpsi->nPos))
|
|
|
|
{
|
|
|
|
psi->nPos = lpsi->nPos;
|
|
|
|
Chg = TRUE;
|
|
|
|
if(Action)
|
|
|
|
*Action |= SBU_SCROLLBOX;
|
|
|
|
if(psi->nPos < psi->nMin)
|
|
|
|
psi->nPos = psi->nMin;
|
|
|
|
else if(psi->nPos > psi->nMax - max(psi->nPage - 1, 0))
|
|
|
|
psi->nPos = psi->nMax - max(psi->nPage - 1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME check assigned values */
|
|
|
|
|
|
|
|
Ret = psi->nPos;
|
|
|
|
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL FASTCALL
|
|
|
|
IntGetScrollBarInfo(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi)
|
|
|
|
{
|
|
|
|
INT Bar;
|
|
|
|
PSCROLLBARINFO sbi;
|
|
|
|
LPSCROLLINFO psi;
|
|
|
|
|
|
|
|
switch(idObject)
|
|
|
|
{
|
|
|
|
case OBJID_HSCROLL:
|
|
|
|
if(Window->pHScroll)
|
|
|
|
{
|
|
|
|
Bar = SB_HORZ;
|
|
|
|
sbi = Window->pHScroll;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through */
|
|
|
|
case OBJID_VSCROLL:
|
|
|
|
if(Window->pVScroll)
|
|
|
|
{
|
|
|
|
Bar = SB_VERT;
|
|
|
|
sbi = Window->pVScroll;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through */
|
|
|
|
case OBJID_CLIENT:
|
|
|
|
|
|
|
|
/* FIXME
|
|
|
|
Send a SBM_GETSCROLLBARINFO message if Window is not a system scrollbar.
|
|
|
|
If the window doesn't handle the message return FALSE.
|
|
|
|
*/
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if(Window->wExtra)
|
|
|
|
{
|
|
|
|
Bar = SB_CTL;
|
|
|
|
sbi = Window->wExtra;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through */
|
|
|
|
default:
|
|
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
psi = (LPSCROLLINFO)((PSCROLLBARINFO)(sbi + 1));
|
|
|
|
|
|
|
|
IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar));
|
|
|
|
IntCalculateThumb(Window, Bar, sbi, psi);
|
|
|
|
|
|
|
|
RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO));
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2003-09-07 09:55:52 +00:00
|
|
|
DWORD FASTCALL
|
|
|
|
IntCreateScrollBar(PWINDOW_OBJECT Window, LONG idObject)
|
2002-11-24 20:15:37 +00:00
|
|
|
{
|
2002-12-21 19:25:41 +00:00
|
|
|
PSCROLLBARINFO psbi;
|
2003-09-08 15:08:56 +00:00
|
|
|
LPSCROLLINFO psi;
|
2002-12-21 19:25:41 +00:00
|
|
|
LRESULT Result;
|
2003-01-24 22:42:15 +00:00
|
|
|
INT i;
|
2002-11-24 20:15:37 +00:00
|
|
|
|
2003-09-08 15:08:56 +00:00
|
|
|
psbi = ExAllocatePool(PagedPool, sizeof(SCROLLBARINFO) + sizeof(SCROLLINFO));
|
2003-09-07 09:55:52 +00:00
|
|
|
if(!psbi)
|
|
|
|
return FALSE;
|
2003-09-08 15:08:56 +00:00
|
|
|
|
|
|
|
psi = (LPSCROLLINFO)((PSCROLLBARINFO)(psbi + 1));
|
|
|
|
|
|
|
|
psi->cbSize = sizeof(LPSCROLLINFO);
|
|
|
|
psi->nMin = 0;
|
|
|
|
psi->nMax = 100;
|
|
|
|
psi->nPage = 0;
|
|
|
|
psi->nPos = 0;
|
|
|
|
psi->nTrackPos = 0;
|
2003-09-07 09:55:52 +00:00
|
|
|
|
2003-01-24 22:42:15 +00:00
|
|
|
Result = WinPosGetNonClientSize(Window->Self,
|
2002-12-21 19:25:41 +00:00
|
|
|
&Window->WindowRect,
|
|
|
|
&Window->ClientRect);
|
|
|
|
|
2003-05-18 22:11:41 +00:00
|
|
|
psbi->cbSize = sizeof(SCROLLBARINFO);
|
2002-11-24 20:15:37 +00:00
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++)
|
2003-01-24 22:42:15 +00:00
|
|
|
psbi->rgstate[i] = 0;
|
|
|
|
|
2002-11-24 20:15:37 +00:00
|
|
|
switch(idObject)
|
|
|
|
{
|
2002-12-21 19:25:41 +00:00
|
|
|
case SB_HORZ:
|
|
|
|
Window->pHScroll = psbi;
|
|
|
|
break;
|
|
|
|
case SB_VERT:
|
|
|
|
Window->pVScroll = psbi;
|
|
|
|
break;
|
|
|
|
case SB_CTL:
|
|
|
|
Window->wExtra = psbi;
|
|
|
|
break;
|
2002-11-24 20:15:37 +00:00
|
|
|
default:
|
2003-09-07 09:55:52 +00:00
|
|
|
ExFreePool(psbi);
|
2002-11-24 20:15:37 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-09-08 15:08:56 +00:00
|
|
|
IntGetScrollBarRect(Window, idObject, &(psbi->rcScrollBar));
|
|
|
|
IntCalculateThumb(Window, idObject, psbi, psi);
|
2002-11-24 20:15:37 +00:00
|
|
|
|
2002-12-21 19:25:41 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-09-07 09:55:52 +00:00
|
|
|
BOOL FASTCALL
|
|
|
|
IntDestroyScrollBar(PWINDOW_OBJECT Window, LONG idObject)
|
2002-12-21 19:25:41 +00:00
|
|
|
{
|
|
|
|
switch(idObject)
|
|
|
|
{
|
|
|
|
case SB_HORZ:
|
2003-09-07 09:55:52 +00:00
|
|
|
if(Window->pHScroll)
|
|
|
|
{
|
|
|
|
ExFreePool(Window->pHScroll);
|
|
|
|
Window->pHScroll = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
2002-12-21 19:25:41 +00:00
|
|
|
case SB_VERT:
|
2003-09-07 09:55:52 +00:00
|
|
|
if(Window->pVScroll)
|
|
|
|
{
|
|
|
|
ExFreePool(Window->pVScroll);
|
|
|
|
Window->pVScroll = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
2002-12-21 19:25:41 +00:00
|
|
|
case SB_CTL:
|
2003-09-07 09:55:52 +00:00
|
|
|
if(Window->wExtra)
|
|
|
|
{
|
|
|
|
ExFreePool(Window->wExtra);
|
|
|
|
Window->wExtra = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2002-12-21 19:25:41 +00:00
|
|
|
return FALSE;
|
2002-11-24 20:15:37 +00:00
|
|
|
}
|
2003-09-07 09:55:52 +00:00
|
|
|
return FALSE;
|
2002-11-24 20:15:37 +00:00
|
|
|
}
|
|
|
|
|
2003-09-08 02:14:20 +00:00
|
|
|
#define CHANGERGSTATE(item, status) \
|
|
|
|
if(Info->rgstate[(item)] != (status)) \
|
|
|
|
Chg = TRUE; \
|
|
|
|
Info->rgstate[(item)] = (status);
|
|
|
|
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows)
|
|
|
|
{
|
|
|
|
BOOL Chg = FALSE;
|
|
|
|
switch(wArrows)
|
|
|
|
{
|
|
|
|
case ESB_DISABLE_BOTH:
|
|
|
|
CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
|
|
|
|
CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
|
|
|
|
break;
|
|
|
|
case ESB_DISABLE_RTDN:
|
|
|
|
if(Horz)
|
|
|
|
{
|
|
|
|
CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ESB_DISABLE_LTUP:
|
|
|
|
if(Horz)
|
|
|
|
{
|
|
|
|
CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ESB_ENABLE_BOTH:
|
|
|
|
CHANGERGSTATE(SBRG_TOPRIGHTBTN, 0);
|
|
|
|
CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return Chg;
|
|
|
|
}
|
|
|
|
|
2003-09-07 09:55:52 +00:00
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
BOOL
|
2002-12-21 19:25:41 +00:00
|
|
|
STDCALL
|
|
|
|
NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
|
2002-11-24 20:15:37 +00:00
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
SCROLLBARINFO sbi;
|
2003-09-07 09:55:52 +00:00
|
|
|
PWINDOW_OBJECT Window;
|
2003-09-24 13:41:40 +00:00
|
|
|
BOOL Ret;
|
|
|
|
|
|
|
|
Status = MmCopyFromCaller(&sbi, psbi, sizeof(SCROLLBARINFO));
|
|
|
|
if(!NT_SUCCESS(Status) || (sbi.cbSize != sizeof(SCROLLBARINFO)))
|
2003-09-07 09:55:52 +00:00
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
SetLastNtError(Status);
|
2003-09-07 09:55:52 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2003-09-24 13:41:40 +00:00
|
|
|
|
2003-09-07 09:55:52 +00:00
|
|
|
Window = IntGetWindowObject(hWnd);
|
2002-11-24 20:15:37 +00:00
|
|
|
|
2003-09-07 09:55:52 +00:00
|
|
|
if(!Window)
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2002-11-24 20:15:37 +00:00
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
Ret = IntGetScrollBarInfo(Window, idObject, &sbi);
|
|
|
|
|
|
|
|
Status = MmCopyToCaller(psbi, &sbi, sizeof(SCROLLBARINFO));
|
|
|
|
if(!NT_SUCCESS(Status))
|
2003-09-07 09:55:52 +00:00
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
SetLastNtError(Status);
|
|
|
|
Ret = FALSE;
|
2003-09-07 09:55:52 +00:00
|
|
|
}
|
|
|
|
IntReleaseWindowObject(Window);
|
2003-09-24 13:41:40 +00:00
|
|
|
return Ret;
|
2002-11-24 20:15:37 +00:00
|
|
|
}
|
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
|
|
|
|
BOOL
|
|
|
|
STDCALL
|
|
|
|
NtUserGetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
|
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
NTSTATUS Status;
|
2003-09-07 11:52:54 +00:00
|
|
|
PWINDOW_OBJECT Window;
|
2003-09-24 13:41:40 +00:00
|
|
|
SCROLLINFO psi;
|
|
|
|
BOOL Ret;
|
2003-09-07 11:52:54 +00:00
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
Status = MmCopyFromCaller(&psi, lpsi, sizeof(SCROLLINFO) - sizeof(psi.nTrackPos));
|
|
|
|
if(!NT_SUCCESS(Status) ||
|
|
|
|
(psi.cbSize != sizeof(SCROLLINFO)) || (psi.cbSize != sizeof(SCROLLINFO) - sizeof(psi.nTrackPos)))
|
2003-09-12 12:54:26 +00:00
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
SetLastNtError(Status);
|
|
|
|
return FALSE;
|
2003-09-12 12:54:26 +00:00
|
|
|
}
|
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
Window = IntGetWindowObject(hwnd);
|
|
|
|
|
|
|
|
if(!Window)
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
Ret = IntGetScrollInfo(Window, fnBar, &psi);
|
2003-09-12 12:54:26 +00:00
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
2003-09-24 13:41:40 +00:00
|
|
|
return Ret;
|
2003-09-07 11:52:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-09-08 02:14:20 +00:00
|
|
|
BOOL
|
2002-11-24 20:15:37 +00:00
|
|
|
STDCALL
|
|
|
|
NtUserEnableScrollBar(
|
2003-09-07 09:55:52 +00:00
|
|
|
HWND hWnd,
|
|
|
|
UINT wSBflags,
|
|
|
|
UINT wArrows)
|
2002-11-24 20:15:37 +00:00
|
|
|
{
|
2003-09-07 11:52:54 +00:00
|
|
|
PWINDOW_OBJECT Window;
|
|
|
|
PSCROLLBARINFO InfoV = NULL, InfoH = NULL;
|
2003-09-08 02:14:20 +00:00
|
|
|
BOOL Chg = FALSE;
|
2003-09-07 11:52:54 +00:00
|
|
|
|
|
|
|
Window = IntGetWindowObject(hWnd);
|
|
|
|
|
|
|
|
if(!Window)
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(wSBflags)
|
|
|
|
{
|
|
|
|
case SB_BOTH:
|
|
|
|
InfoV = Window->pVScroll;
|
|
|
|
/* fall through */
|
|
|
|
case SB_HORZ:
|
|
|
|
InfoH = Window->pHScroll;
|
|
|
|
break;
|
|
|
|
case SB_VERT:
|
|
|
|
InfoV = Window->pVScroll;
|
|
|
|
break;
|
|
|
|
case SB_CTL:
|
|
|
|
InfoV = Window->wExtra;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-09-08 02:14:20 +00:00
|
|
|
if(InfoV)
|
|
|
|
Chg = IntEnableScrollBar(FALSE, InfoV, wArrows);
|
|
|
|
|
|
|
|
if(InfoH)
|
|
|
|
Chg = (IntEnableScrollBar(TRUE, InfoH, wArrows) || Chg);
|
|
|
|
|
2003-09-08 15:08:56 +00:00
|
|
|
//if(Chg && (Window->Style & WS_VISIBLE))
|
2003-09-08 02:14:20 +00:00
|
|
|
/* FIXME - repaint scrollbars */
|
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
return TRUE;
|
2002-11-24 20:15:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
STDCALL
|
|
|
|
NtUserScrollDC(
|
2003-09-07 09:55:52 +00:00
|
|
|
HDC hDC,
|
|
|
|
int dx,
|
|
|
|
int dy,
|
|
|
|
CONST RECT *lprcScroll,
|
|
|
|
CONST RECT *lprcClip ,
|
|
|
|
HRGN hrgnUpdate,
|
|
|
|
LPRECT lprcUpdate)
|
2002-11-24 20:15:37 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
STDCALL
|
|
|
|
NtUserSetScrollInfo(
|
2003-09-07 09:55:52 +00:00
|
|
|
HWND hwnd,
|
|
|
|
int fnBar,
|
2003-09-12 12:54:26 +00:00
|
|
|
LPSCROLLINFO lpsi,
|
2003-09-24 13:41:40 +00:00
|
|
|
DWORD *Changed)
|
2002-11-24 20:15:37 +00:00
|
|
|
{
|
2003-09-07 11:52:54 +00:00
|
|
|
PWINDOW_OBJECT Window;
|
2003-09-24 13:41:40 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
SCROLLINFO ScrollInfo;
|
|
|
|
DWORD Ret, Action;
|
2003-09-07 11:52:54 +00:00
|
|
|
|
|
|
|
Window = IntGetWindowObject(hwnd);
|
2002-11-24 20:15:37 +00:00
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
if(!Window)
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos));
|
|
|
|
if(!NT_SUCCESS(Status))
|
2003-09-07 11:52:54 +00:00
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return 0;
|
2003-09-07 11:52:54 +00:00
|
|
|
}
|
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
Ret = IntSetScrollInfo(Window, fnBar, &ScrollInfo, &Action);
|
2003-09-08 15:08:56 +00:00
|
|
|
|
2003-09-24 13:41:40 +00:00
|
|
|
if(Changed)
|
2003-09-12 12:54:26 +00:00
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
if(Action && (Window->Style & WS_VISIBLE))
|
2003-09-12 12:54:26 +00:00
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
MmCopyToCaller(Changed, &Action, sizeof(DWORD));
|
2003-09-12 12:54:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-09-24 13:41:40 +00:00
|
|
|
MmCopyToCaller(Changed, &Action, sizeof(DWORD));
|
2003-09-12 12:54:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-07 11:52:54 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
2003-09-24 13:41:40 +00:00
|
|
|
|
2003-09-08 15:08:56 +00:00
|
|
|
return Ret;
|
2002-11-24 20:15:37 +00:00
|
|
|
}
|
|
|
|
|
2002-12-21 19:25:41 +00:00
|
|
|
/* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
|
2002-11-24 20:15:37 +00:00
|
|
|
DWORD
|
|
|
|
STDCALL
|
|
|
|
NtUserShowScrollBar(HWND hWnd, int wBar, DWORD bShow)
|
|
|
|
{
|
2002-12-21 19:25:41 +00:00
|
|
|
BOOL fShowV = (wBar == SB_VERT) ? 0 : bShow;
|
|
|
|
BOOL fShowH = (wBar == SB_HORZ) ? 0 : bShow;
|
2003-08-19 11:48:50 +00:00
|
|
|
PWINDOW_OBJECT Window = IntGetWindowObject(hWnd);
|
2003-09-07 09:55:52 +00:00
|
|
|
if(!Window)
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2002-11-24 20:15:37 +00:00
|
|
|
|
2002-12-21 19:25:41 +00:00
|
|
|
switch (wBar)
|
|
|
|
{
|
|
|
|
case SB_CTL:
|
2003-09-07 09:55:52 +00:00
|
|
|
WinPosShowWindow (hWnd, fShowH ? SW_SHOW : SW_HIDE);
|
2002-12-21 19:25:41 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case SB_BOTH:
|
|
|
|
case SB_HORZ:
|
|
|
|
if (fShowH)
|
|
|
|
{
|
|
|
|
fShowH = !(Window->Style & WS_HSCROLL);
|
|
|
|
Window->Style |= WS_HSCROLL;
|
|
|
|
}
|
|
|
|
else /* hide it */
|
|
|
|
{
|
|
|
|
fShowH = (Window->Style & WS_HSCROLL);
|
|
|
|
Window->Style &= ~WS_HSCROLL;
|
|
|
|
}
|
|
|
|
if (wBar == SB_HORZ)
|
|
|
|
{
|
|
|
|
fShowV = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through */
|
|
|
|
|
|
|
|
case SB_VERT:
|
|
|
|
if (fShowV)
|
|
|
|
{
|
|
|
|
fShowV = !(Window->Style & WS_VSCROLL);
|
|
|
|
Window->Style |= WS_VSCROLL;
|
|
|
|
}
|
|
|
|
else /* hide it */
|
|
|
|
{
|
|
|
|
fShowV = (Window->Style & WS_VSCROLL);
|
|
|
|
Window->Style &= ~WS_VSCROLL;
|
|
|
|
}
|
|
|
|
if (wBar == SB_VERT)
|
|
|
|
fShowH = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return FALSE; /* Nothing to do! */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fShowH || fShowV) /* frame has been changed, let the window redraw itself */
|
|
|
|
{
|
2003-09-07 09:55:52 +00:00
|
|
|
WinPosSetWindowPos (hWnd, 0, 0, 0, 0, 0,
|
2002-12-21 19:25:41 +00:00
|
|
|
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE; /* no frame changes */
|
2002-11-24 20:15:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|