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