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