fixed some scrollbar issues
[reactos.git] / reactos / subsys / win32k / ntuser / scrollbar.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: scrollbar.c,v 1.30 2004/04/17 11:00:14 weiden Exp $
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Scrollbars
24 * FILE: subsys/win32k/ntuser/scrollbar.c
25 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
26 * Jason Filby (jasonfilby@yahoo.com)
27 * REVISION HISTORY:
28 * 16-11-2002 Jason Filby Created
29 */
30 /* INCLUDES ******************************************************************/
31
32 #include <ddk/ntddk.h>
33 #include <win32k/win32k.h>
34 #include <internal/safe.h>
35 #include <include/object.h>
36 #include <include/window.h>
37 #include <include/class.h>
38 #include <include/error.h>
39 #include <include/winsta.h>
40 #include <include/winpos.h>
41 #include <include/rect.h>
42 #include <include/scroll.h>
43 #include <include/painting.h>
44 #include <include/tags.h>
45 #ifdef __USE_W32API
46 #include <oleacc.h>
47 #endif
48
49 #define NDEBUG
50 #include <debug.h>
51
52 #define MINTRACKTHUMB 8 /* Minimum size of the rectangle between the arrows */
53
54 #define SBRG_SCROLLBAR 0 /* the scrollbar itself */
55 #define SBRG_TOPRIGHTBTN 1 /* the top or right button */
56 #define SBRG_PAGEUPRIGHT 2 /* the page up or page right region */
57 #define SBRG_SCROLLBOX 3 /* the scroll box */
58 #define SBRG_PAGEDOWNLEFT 4 /* the page down or page left region */
59 #define SBRG_BOTTOMLEFTBTN 5 /* the bottom or left button */
60
61 #define CHANGERGSTATE(item, status) \
62 if(Info->rgstate[(item)] != (status)) \
63 Chg = TRUE; \
64 Info->rgstate[(item)] = (status);
65
66 /* FUNCTIONS *****************************************************************/
67
68 /* Ported from WINE20020904 */
69 /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
70 * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
71 * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
72 * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
73 */
74 BOOL FASTCALL
75 IntGetScrollBarRect (PWINDOW_OBJECT Window, INT nBar, PRECT lprect)
76 {
77 BOOL vertical;
78 RECT ClientRect = Window->ClientRect;
79 RECT WindowRect = Window->WindowRect;
80
81 switch (nBar)
82 {
83 case SB_HORZ:
84 lprect->left = ClientRect.left - WindowRect.left;
85 lprect->top = ClientRect.bottom - WindowRect.top;
86 lprect->right = ClientRect.right - WindowRect.left;
87 lprect->bottom = lprect->top + NtUserGetSystemMetrics (SM_CYHSCROLL);
88 vertical = FALSE;
89 break;
90
91 case SB_VERT:
92 lprect->left = ClientRect.right - WindowRect.left;
93 lprect->top = ClientRect.top - WindowRect.top;
94 lprect->right = lprect->left + NtUserGetSystemMetrics(SM_CXVSCROLL);
95 lprect->bottom = ClientRect.bottom - WindowRect.top;
96 vertical = TRUE;
97 break;
98
99 case SB_CTL:
100 IntGetClientRect (Window, lprect);
101 vertical = ((Window->Style & SBS_VERT) != 0);
102 break;
103
104 default:
105 IntReleaseWindowObject(Window);
106 return FALSE;
107 }
108
109 return vertical;
110 }
111
112 BOOL FASTCALL
113 IntCalculateThumb(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi)
114 {
115 INT Thumb, ThumbBox, ThumbPos, cxy, mx;
116 RECT ClientRect;
117
118 switch(idObject)
119 {
120 case SB_HORZ:
121 Thumb = NtUserGetSystemMetrics(SM_CXHSCROLL);
122 cxy = psbi->rcScrollBar.right - psbi->rcScrollBar.left;
123 break;
124 case SB_VERT:
125 Thumb = NtUserGetSystemMetrics(SM_CYVSCROLL);
126 cxy = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top;
127 break;
128 case SB_CTL:
129 IntGetClientRect (Window, &ClientRect);
130 if(Window->Style & SBS_VERT)
131 {
132 Thumb = NtUserGetSystemMetrics(SM_CYVSCROLL);
133 cxy = ClientRect.bottom - ClientRect.top;
134 }
135 else
136 {
137 Thumb = NtUserGetSystemMetrics(SM_CXHSCROLL);
138 cxy = ClientRect.right - ClientRect.left;
139 }
140 break;
141 default:
142 return FALSE;
143 }
144
145 ThumbPos = Thumb;
146 /* calculate Thumb */
147 if(cxy <= (2 * Thumb))
148 {
149 Thumb = cxy / 2;
150 psbi->xyThumbTop = 0;
151 psbi->xyThumbBottom = 0;
152 ThumbPos = Thumb;
153 }
154 else
155 {
156 ThumbBox = psi->nPage ? MINTRACKTHUMB : NtUserGetSystemMetrics(SM_CXHTHUMB);
157 cxy -= (2 * Thumb);
158 if(cxy >= ThumbBox)
159 {
160 if(psi->nPage)
161 {
162 ThumbBox = max(EngMulDiv(cxy, psi->nPage, psi->nMax - psi->nMin + 1), ThumbBox);
163 }
164
165 if(cxy > ThumbBox)
166 {
167 mx = psi->nMax - max(psi->nPage - 1, 0);
168 if(psi->nMin < mx)
169 ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, psi->nPos - psi->nMin, mx - psi->nMin);
170 else
171 ThumbPos = Thumb + ThumbBox;
172 }
173
174 psbi->xyThumbTop = ThumbPos;
175 psbi->xyThumbBottom = ThumbPos + ThumbBox;
176 }
177 else
178 {
179 psbi->xyThumbTop = 0;
180 psbi->xyThumbBottom = 0;
181 }
182 }
183 psbi->dxyLineButton = Thumb;
184
185 return TRUE;
186 }
187
188 static VOID FASTCALL
189 IntUpdateSBInfo(PWINDOW_OBJECT Window, int wBar)
190 {
191 PSCROLLBARINFO sbi;
192 LPSCROLLINFO psi;
193
194 ASSERT(Window);
195 ASSERT(Window->Scroll);
196
197 sbi = IntGetScrollbarInfoFromWindow(Window, wBar);
198 psi = IntGetScrollInfoFromWindow(Window, wBar);
199 IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar));
200 IntCalculateThumb(Window, wBar, sbi, psi);
201 }
202
203 static BOOL FASTCALL
204 IntGetScrollInfo(PWINDOW_OBJECT Window, INT nBar, LPSCROLLINFO lpsi)
205 {
206 UINT Mask;
207 LPSCROLLINFO psi;
208
209 if(!SBID_IS_VAILD(nBar))
210 {
211 SetLastWin32Error(ERROR_INVALID_PARAMETER);
212 DPRINT1("Trying to get scrollinfo for unknown scrollbar type %d", nBar);
213 return FALSE;
214 }
215
216 if(!IntCreateScrollBars(Window))
217 {
218 return FALSE;
219 }
220
221 psi = IntGetScrollInfoFromWindow(Window, nBar);
222
223 if (lpsi->fMask == SIF_ALL)
224 {
225 Mask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
226 }
227 else
228 {
229 Mask = lpsi->fMask;
230 }
231
232 if (0 != (Mask & SIF_PAGE))
233 {
234 lpsi->nPage = psi->nPage;
235 }
236
237 if (0 != (Mask & SIF_POS))
238 {
239 lpsi->nPos = psi->nPos;
240 }
241
242 if (0 != (Mask & SIF_RANGE))
243 {
244 lpsi->nMin = psi->nMin;
245 lpsi->nMax = psi->nMax;
246 }
247
248 if (0 != (Mask & SIF_TRACKPOS))
249 {
250 lpsi->nTrackPos = psi->nTrackPos;
251 }
252
253 return TRUE;
254 }
255
256 static DWORD FASTCALL
257 IntSetScrollInfo(PWINDOW_OBJECT Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
258 {
259 /*
260 * Update the scrollbar state and set action flags according to
261 * what has to be done graphics wise.
262 */
263
264 LPSCROLLINFO Info;
265 PSCROLLBARINFO psbi;
266 /* UINT new_flags;*/
267 BOOL bChangeParams = FALSE; /* don't show/hide scrollbar if params don't change */
268
269 if(!SBID_IS_VAILD(nBar))
270 {
271 SetLastWin32Error(ERROR_INVALID_PARAMETER);
272 DPRINT1("Trying to set scrollinfo for unknown scrollbar type %d", nBar);
273 return FALSE;
274 }
275
276 if(!IntCreateScrollBars(Window))
277 {
278 return FALSE;
279 }
280
281 if (lpsi->cbSize != sizeof(SCROLLINFO) &&
282 lpsi->cbSize != (sizeof(SCROLLINFO) - sizeof(lpsi->nTrackPos)))
283 {
284 SetLastWin32Error(ERROR_INVALID_PARAMETER);
285 return 0;
286 }
287 if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL))
288 {
289 SetLastWin32Error(ERROR_INVALID_PARAMETER);
290 return 0;
291 }
292
293 psbi = IntGetScrollbarInfoFromWindow(Window, nBar);
294 Info = IntGetScrollInfoFromWindow(Window, nBar);
295
296 /* Set the page size */
297 if (0 != (lpsi->fMask & SIF_PAGE))
298 {
299 if (Info->nPage != lpsi->nPage)
300 {
301 Info->nPage = lpsi->nPage;
302 bChangeParams = TRUE;
303 }
304 }
305
306 /* Set the scroll pos */
307 if (0 != (lpsi->fMask & SIF_POS))
308 {
309 if (Info->nPos != lpsi->nPos)
310 {
311 Info->nPos = lpsi->nPos;
312 }
313 }
314
315 /* Set the scroll range */
316 if (0 != (lpsi->fMask & SIF_RANGE))
317 {
318 /* Invalid range -> range is set to (0,0) */
319 if (lpsi->nMin > lpsi->nMax ||
320 0x80000000 <= (UINT)(lpsi->nMax - lpsi->nMin))
321 {
322 Info->nMin = 0;
323 Info->nMax = 0;
324 bChangeParams = TRUE;
325 }
326 else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax)
327 {
328 Info->nMin = lpsi->nMin;
329 Info->nMax = lpsi->nMax;
330 bChangeParams = TRUE;
331 }
332 }
333
334 /* Make sure the page size is valid */
335 if (Info->nPage < 0)
336 {
337 Info->nPage = 0;
338 }
339 else if (Info->nMax - Info->nMin + 1 < Info->nPage)
340 {
341 Info->nPage = Info->nMax - Info->nMin + 1;
342 }
343
344 /* Make sure the pos is inside the range */
345 if (Info->nPos < Info->nMin)
346 {
347 Info->nPos = Info->nMin;
348 }
349 else if (Info->nPos > Info->nMax - max(Info->nPage - 1, 0))
350 {
351 Info->nPos = Info->nMax - max(Info->nPage - 1, 0);
352 }
353
354 /*
355 * Don't change the scrollbar state if SetScrollInfo is just called
356 * with SIF_DISABLENOSCROLL
357 */
358 if (0 == (lpsi->fMask & SIF_ALL))
359 {
360 return Info->nPos;
361 }
362
363 /* Check if the scrollbar should be hidden or disabled */
364 if (0 != (lpsi->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL)))
365 {
366 if (Info->nMin >= Info->nMax - max(Info->nPage - 1, 0))
367 {
368 /* Hide or disable scroll-bar */
369 if (0 != (lpsi->fMask & SIF_DISABLENOSCROLL))
370 {
371 /* new_flags = ESB_DISABLE_BOTH;*/
372 }
373 else if ((nBar != SB_CTL) && bChangeParams)
374 {
375 NtUserShowScrollBar(Window->Self, nBar, FALSE);
376 return Info->nPos;
377 }
378 }
379 else /* Show and enable scroll-bar */
380 {
381 /* new_flags = 0;*/
382 if ((nBar != SB_CTL) && bChangeParams)
383 {
384 NtUserShowScrollBar(Window->Self, nBar, TRUE);
385 }
386 }
387
388 #if 0
389 if (infoPtr->flags != new_flags) /* check arrow flags */
390 {
391 infoPtr->flags = new_flags;
392 *Action |= SA_SSI_REPAINT_ARROWS;
393 }
394 #endif
395 }
396
397 if (bRedraw)
398 {
399 RECT UpdateRect = psbi->rcScrollBar;
400 UpdateRect.left -= Window->ClientRect.left - Window->WindowRect.left;
401 UpdateRect.right -= Window->ClientRect.left - Window->WindowRect.left;
402 UpdateRect.top -= Window->ClientRect.top - Window->WindowRect.top;
403 UpdateRect.bottom -= Window->ClientRect.top - Window->WindowRect.top;
404 IntRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
405 }
406
407 /* Return current position */
408 return Info->nPos;
409 }
410
411 BOOL FASTCALL
412 IntGetScrollBarInfo(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi)
413 {
414 INT Bar;
415 PSCROLLBARINFO sbi;
416 LPSCROLLINFO psi;
417
418 Bar = SBOBJ_TO_SBID(idObject);
419
420 if(!SBID_IS_VAILD(Bar))
421 {
422 SetLastWin32Error(ERROR_INVALID_PARAMETER);
423 DPRINT1("Trying to get scrollinfo for unknown scrollbar type %d", Bar);
424 return FALSE;
425 }
426
427 if(!IntCreateScrollBars(Window))
428 {
429 return FALSE;
430 }
431
432 sbi = IntGetScrollbarInfoFromWindow(Window, Bar);
433 psi = IntGetScrollInfoFromWindow(Window, Bar);
434
435 IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar));
436 IntCalculateThumb(Window, Bar, sbi, psi);
437
438 RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO));
439
440 return TRUE;
441 }
442
443 BOOL FASTCALL
444 IntCreateScrollBars(PWINDOW_OBJECT Window)
445 {
446 PSCROLLBARINFO psbi;
447 LPSCROLLINFO psi;
448 LRESULT Result;
449 ULONG Size, s;
450 INT i;
451
452 if(Window->Scroll)
453 {
454 /* no need to create it anymore */
455 return TRUE;
456 }
457
458 /* allocate memory for all scrollbars (HORZ, VERT, CONTROL) */
459 Size = 2 * (sizeof(WINDOW_SCROLLINFO));
460 if(!(Window->Scroll = ExAllocatePoolWithTag(PagedPool, Size, TAG_SBARINFO)))
461 {
462 DPRINT1("Unable to allocate memory for scrollbar information for window 0x%x\n", Window->Self);
463 return FALSE;
464 }
465
466 RtlZeroMemory(Window->Scroll, Size);
467
468 Result = WinPosGetNonClientSize(Window->Self,
469 &Window->WindowRect,
470 &Window->ClientRect);
471
472 for(s = SB_HORZ; s <= SB_VERT; s++)
473 {
474 psbi = IntGetScrollbarInfoFromWindow(Window, s);
475 psbi->cbSize = sizeof(SCROLLBARINFO);
476 for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++)
477 psbi->rgstate[i] = 0;
478
479 psi = IntGetScrollInfoFromWindow(Window, s);
480 psi->cbSize = sizeof(LPSCROLLINFO);
481 psi->nMax = 100;
482
483 IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar));
484 IntCalculateThumb(Window, s, psbi, psi);
485 }
486
487 return TRUE;
488 }
489
490 BOOL FASTCALL
491 IntDestroyScrollBars(PWINDOW_OBJECT Window)
492 {
493 if(Window->Scroll)
494 {
495 ExFreePool(Window->Scroll);
496 Window->Scroll = NULL;
497 return TRUE;
498 }
499 return FALSE;
500 }
501
502 BOOL STDCALL
503 IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows)
504 {
505 BOOL Chg = FALSE;
506 switch(wArrows)
507 {
508 case ESB_DISABLE_BOTH:
509 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
510 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
511 break;
512 case ESB_DISABLE_RTDN:
513 if(Horz)
514 {
515 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
516 }
517 else
518 {
519 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
520 }
521 break;
522 case ESB_DISABLE_LTUP:
523 if(Horz)
524 {
525 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
526 }
527 else
528 {
529 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
530 }
531 break;
532 case ESB_ENABLE_BOTH:
533 CHANGERGSTATE(SBRG_TOPRIGHTBTN, 0);
534 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, 0);
535 break;
536 }
537 return Chg;
538 }
539
540
541 BOOL
542 STDCALL
543 NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
544 {
545 NTSTATUS Status;
546 SCROLLBARINFO sbi;
547 PWINDOW_OBJECT Window;
548 BOOL Ret;
549
550 Status = MmCopyFromCaller(&sbi, psbi, sizeof(SCROLLBARINFO));
551 if(!NT_SUCCESS(Status) || (sbi.cbSize != sizeof(SCROLLBARINFO)))
552 {
553 SetLastNtError(Status);
554 return FALSE;
555 }
556
557 Window = IntGetWindowObject(hWnd);
558
559 if(!Window)
560 {
561 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
562 return FALSE;
563 }
564
565 Ret = IntGetScrollBarInfo(Window, idObject, &sbi);
566
567 Status = MmCopyToCaller(psbi, &sbi, sizeof(SCROLLBARINFO));
568 if(!NT_SUCCESS(Status))
569 {
570 SetLastNtError(Status);
571 Ret = FALSE;
572 }
573 IntReleaseWindowObject(Window);
574 return Ret;
575 }
576
577
578 BOOL
579 STDCALL
580 NtUserGetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
581 {
582 NTSTATUS Status;
583 PWINDOW_OBJECT Window;
584 SCROLLINFO psi;
585 DWORD sz;
586 BOOL Ret;
587
588 Status = MmCopyFromCaller(&psi.cbSize, &(lpsi->cbSize), sizeof(UINT));
589 if(!NT_SUCCESS(Status) ||
590 !((psi.cbSize == sizeof(SCROLLINFO)) || (psi.cbSize == sizeof(SCROLLINFO) - sizeof(psi.nTrackPos))))
591 {
592 SetLastNtError(Status);
593 return FALSE;
594 }
595 sz = psi.cbSize;
596 Status = MmCopyFromCaller(&psi, lpsi, sz);
597 if (!NT_SUCCESS(Status))
598 {
599 SetLastNtError(Status);
600 return FALSE;
601 }
602
603 Window = IntGetWindowObject(hwnd);
604
605 if(!Window)
606 {
607 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
608 return FALSE;
609 }
610
611 if(fnBar == SB_CTL)
612 {
613 IntSendMessage(Window->Self, SBM_GETSCROLLINFO, 0, (LPARAM)lpsi);
614 Ret = TRUE;
615 }
616 else
617 Ret = IntGetScrollInfo(Window, fnBar, &psi);
618
619 IntReleaseWindowObject(Window);
620
621 Status = MmCopyToCaller(lpsi, &psi, sz);
622 if(!NT_SUCCESS(Status))
623 {
624 SetLastNtError(Status);
625 return FALSE;
626 }
627
628 return Ret;
629 }
630
631
632 BOOL
633 STDCALL
634 NtUserEnableScrollBar(
635 HWND hWnd,
636 UINT wSBflags,
637 UINT wArrows)
638 {
639 PWINDOW_OBJECT Window;
640 PSCROLLBARINFO InfoV = NULL, InfoH = NULL;
641 BOOL Chg = FALSE;
642
643 Window = IntGetWindowObject(hWnd);
644
645 if(!Window)
646 {
647 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
648 return FALSE;
649 }
650
651 if(wSBflags == SB_CTL)
652 {
653 /* FIXME */
654 IntReleaseWindowObject(Window);
655 return FALSE;
656 }
657
658 if(wSBflags != SB_BOTH && !SBID_IS_VAILD(wSBflags))
659 {
660 IntReleaseWindowObject(Window);
661 SetLastWin32Error(ERROR_INVALID_PARAMETER);
662 DPRINT1("Trying to set scrollinfo for unknown scrollbar type %d", wSBflags);
663 return FALSE;
664 }
665
666 if(!IntCreateScrollBars(Window))
667 {
668 IntReleaseWindowObject(Window);
669 return FALSE;
670 }
671
672 switch(wSBflags)
673 {
674 case SB_BOTH:
675 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT);
676 /* fall through */
677 case SB_HORZ:
678 InfoH = IntGetScrollbarInfoFromWindow(Window, SB_HORZ);
679 break;
680 case SB_VERT:
681 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT);
682 break;
683 default:
684 IntReleaseWindowObject(Window);
685 return FALSE;
686 }
687
688 if(InfoV)
689 Chg = IntEnableScrollBar(FALSE, InfoV, wArrows);
690
691 if(InfoH)
692 Chg = (IntEnableScrollBar(TRUE, InfoH, wArrows) || Chg);
693
694 //if(Chg && (Window->Style & WS_VISIBLE))
695 /* FIXME - repaint scrollbars */
696
697 IntReleaseWindowObject(Window);
698 return TRUE;
699 }
700
701 BOOL
702 STDCALL
703 NtUserSetScrollBarInfo(
704 HWND hwnd,
705 LONG idObject,
706 SETSCROLLBARINFO *info)
707 {
708 PWINDOW_OBJECT Window;
709 SETSCROLLBARINFO Safeinfo;
710 PSCROLLBARINFO sbi;
711 LPSCROLLINFO psi;
712 NTSTATUS Status;
713 LONG Obj;
714
715 Window = IntGetWindowObject(hwnd);
716
717 if(!Window)
718 {
719 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
720 return FALSE;
721 }
722
723 Obj = SBOBJ_TO_SBID(idObject);
724 if(!SBID_IS_VAILD(Obj))
725 {
726 IntReleaseWindowObject(Window);
727 SetLastWin32Error(ERROR_INVALID_PARAMETER);
728 DPRINT1("Trying to set scrollinfo for unknown scrollbar type %d", Obj);
729 return FALSE;
730 }
731
732 if(!IntCreateScrollBars(Window))
733 {
734 IntReleaseWindowObject(Window);
735 return FALSE;
736 }
737
738 Status = MmCopyFromCaller(&Safeinfo, info, sizeof(SETSCROLLBARINFO));
739 if(!NT_SUCCESS(Status))
740 {
741 IntReleaseWindowObject(Window);
742 SetLastNtError(Status);
743 return FALSE;
744 }
745
746 sbi = IntGetScrollbarInfoFromWindow(Window, Obj);
747 psi = IntGetScrollInfoFromWindow(Window, Obj);
748
749 psi->nTrackPos = Safeinfo.nTrackPos;
750 sbi->reserved = Safeinfo.reserved;
751 RtlCopyMemory(&sbi->rgstate, &Safeinfo.rgstate, sizeof(Safeinfo.rgstate));
752
753 IntReleaseWindowObject(Window);
754 return TRUE;
755 }
756
757 DWORD
758 STDCALL
759 NtUserSetScrollInfo(
760 HWND hwnd,
761 int fnBar,
762 LPCSCROLLINFO lpsi,
763 BOOL bRedraw)
764 {
765 PWINDOW_OBJECT Window;
766 NTSTATUS Status;
767 SCROLLINFO ScrollInfo;
768 DWORD Ret;
769
770 Window = IntGetWindowObject(hwnd);
771
772 if(!Window)
773 {
774 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
775 return 0;
776 }
777
778 if(fnBar == SB_CTL)
779 {
780 Ret = IntSendMessage(hwnd, SBM_SETSCROLLINFO, (WPARAM)bRedraw, (LPARAM)lpsi);
781 IntReleaseWindowObject(Window);
782 return Ret;
783 }
784
785 Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos));
786 if(!NT_SUCCESS(Status))
787 {
788 IntReleaseWindowObject(Window);
789 SetLastNtError(Status);
790 return 0;
791 }
792
793 Ret = IntSetScrollInfo(Window, fnBar, &ScrollInfo, bRedraw);
794 IntReleaseWindowObject(Window);
795
796 return Ret;
797 }
798
799 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
800 DWORD STDCALL
801 NtUserShowScrollBar(HWND hWnd, int wBar, DWORD bShow)
802 {
803 DWORD Style, OldStyle;
804 PWINDOW_OBJECT Window = IntGetWindowObject(hWnd);
805
806 if (!Window)
807 {
808 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
809 return FALSE;
810 }
811
812 switch(wBar)
813 {
814 case SB_HORZ:
815 Style = WS_HSCROLL;
816 break;
817 case SB_VERT:
818 Style = WS_VSCROLL;
819 break;
820 case SB_BOTH:
821 Style = WS_HSCROLL | WS_VSCROLL;
822 break;
823 case SB_CTL:
824 break;
825 default:
826 IntReleaseWindowObject(Window);
827 SetLastWin32Error(ERROR_INVALID_PARAMETER);
828 return FALSE;
829 }
830
831 if(!IntCreateScrollBars(Window))
832 {
833 IntReleaseWindowObject(Window);
834 return FALSE;
835 }
836
837 if (wBar == SB_CTL)
838 {
839 IntUpdateSBInfo(Window, SB_CTL);
840
841 WinPosShowWindow(hWnd, bShow ? SW_SHOW : SW_HIDE);
842 IntReleaseWindowObject(Window);
843 return TRUE;
844 }
845
846 OldStyle = Window->Style;
847 if(bShow)
848 Window->Style |= Style;
849 else
850 Window->Style &= ~Style;
851
852 if(Window->Style != OldStyle)
853 {
854 if(Window->Style & WS_HSCROLL)
855 IntUpdateSBInfo(Window, SB_HORZ);
856 if(Window->Style & WS_VSCROLL)
857 IntUpdateSBInfo(Window, SB_VERT);
858
859 if(Window->Style & WS_VISIBLE)
860 {
861 /* Frame has been changed, let the window redraw itself */
862 WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
863 SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING);
864 }
865 }
866
867 IntReleaseWindowObject(Window);
868 return TRUE;
869 }
870
871 /* EOF */