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