a8f7c66dd50f4d7e953f580f5c828e47c37b0a70
[reactos.git] / win32ss / user / ntuser / scrollbar.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Scrollbars
5 * FILE: win32ss/user/ntuser/scrollbar.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
7 * Jason Filby (jasonfilby@yahoo.com)
8 */
9
10 #include <win32k.h>
11 DBG_DEFAULT_CHANNEL(UserScrollbar);
12
13 /* Definitions for scrollbar hit testing [See SCROLLBARINFO in MSDN] */
14 #define SCROLL_NOWHERE 0x00 /* Outside the scroll bar */
15 #define SCROLL_TOP_ARROW 0x01 /* Top or left arrow */
16 #define SCROLL_TOP_RECT 0x02 /* Rectangle between the top arrow and the thumb */
17 #define SCROLL_THUMB 0x03 /* Thumb rectangle */
18 #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */
19 #define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */
20
21 #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when
22 holding the button down */
23 #define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
24
25 #define SCROLL_TIMER 0 /* Scroll timer id */
26
27 /* Minimum size of the rectangle between the arrows */
28 #define SCROLL_MIN_RECT 4
29
30 /* Minimum size of the thumb in pixels */
31 #define SCROLL_MIN_THUMB 6
32
33 /* Overlap between arrows and thumb */
34 #define SCROLL_ARROW_THUMB_OVERLAP 0
35
36 //
37 //
38 //
39 #define MINTRACKTHUMB 8 /* Minimum size of the rectangle between the arrows */
40
41 /* What to do after SetScrollInfo() */
42 #define SA_SSI_HIDE 0x0001
43 #define SA_SSI_SHOW 0x0002
44 #define SA_SSI_REFRESH 0x0004
45 #define SA_SSI_REPAINT_ARROWS 0x0008
46
47 #define SBRG_SCROLLBAR 0 /* The scrollbar itself */
48 #define SBRG_TOPRIGHTBTN 1 /* The top or right button */
49 #define SBRG_PAGEUPRIGHT 2 /* The page up or page right region */
50 #define SBRG_SCROLLBOX 3 /* The scroll box */
51 #define SBRG_PAGEDOWNLEFT 4 /* The page down or page left region */
52 #define SBRG_BOTTOMLEFTBTN 5 /* The bottom or left button */
53
54 #define CHANGERGSTATE(item, status) \
55 if(Info->rgstate[(item)] != (status)) \
56 Chg = TRUE; \
57 Info->rgstate[(item)] = (status);
58
59 /* FUNCTIONS *****************************************************************/
60
61 /* Ported from WINE20020904 */
62 /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
63 * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
64 * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
65 * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
66 */
67 static inline void mirror_rect( const RECT *window_rect, RECT *rect )
68 {
69 int width = window_rect->right - window_rect->left;
70 int tmp = rect->left;
71 rect->left = width - rect->right;
72 rect->right = width - tmp;
73 }
74
75 PSBDATA FASTCALL
76 IntGetSBData(PWND pwnd, INT Bar)
77 {
78 PSBWND pSBWnd;
79 PSBINFO pSBInfo;
80
81 pSBInfo = pwnd->pSBInfo;
82 switch (Bar)
83 {
84 case SB_HORZ:
85 return &pSBInfo->Horz;
86 case SB_VERT:
87 return &pSBInfo->Vert;
88 case SB_CTL:
89 if ( pwnd->cbwndExtra != (sizeof(SBWND)-sizeof(WND)) )
90 {
91 ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n");
92 return 0;
93 }
94 pSBWnd = (PSBWND)pwnd;
95 return (PSBDATA)&pSBWnd->SBCalc;
96 default:
97 ERR("IntGetSBData Bad Bar!\n");
98 }
99 return NULL;
100 }
101
102 BOOL FASTCALL
103 IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect)
104 {
105 BOOL vertical;
106 *lprect = Wnd->rcClient;
107
108 RECTL_vOffsetRect( lprect, -Wnd->rcWindow.left, -Wnd->rcWindow.top );
109 if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
110 mirror_rect( &Wnd->rcWindow, lprect );
111
112 switch (nBar)
113 {
114 case SB_HORZ:
115 lprect->top = lprect->bottom;
116 lprect->bottom += UserGetSystemMetrics (SM_CYHSCROLL);
117 if (Wnd->style & WS_BORDER)
118 {
119 lprect->left--;
120 lprect->right++;
121 }
122 else if (Wnd->style & WS_VSCROLL)
123 {
124 lprect->right++;
125 }
126 vertical = FALSE;
127 break;
128
129 case SB_VERT:
130 if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR)
131 {
132 lprect->right = lprect->left;
133 lprect->left -= UserGetSystemMetrics(SM_CXVSCROLL);
134 }
135 else
136 {
137 lprect->left = lprect->right;
138 lprect->right += UserGetSystemMetrics(SM_CXVSCROLL);
139 }
140 if (Wnd->style & WS_BORDER)
141 {
142 lprect->top--;
143 lprect->bottom++;
144 }
145 else if (Wnd->style & WS_HSCROLL)
146 {
147 lprect->bottom++;
148 }
149 vertical = TRUE;
150 break;
151
152 case SB_CTL:
153 IntGetClientRect (Wnd, lprect);
154 vertical = !!(Wnd->style & SBS_VERT);
155 break;
156
157 default:
158 return FALSE;
159 }
160
161 return vertical;
162 }
163
164 BOOL FASTCALL
165 IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, PSBDATA pSBData)
166 {
167 INT Thumb, ThumbBox, ThumbPos, cxy, mx;
168 RECTL ClientRect;
169
170 switch(idObject)
171 {
172 case SB_HORZ:
173 Thumb = UserGetSystemMetrics(SM_CXHSCROLL);
174 cxy = psbi->rcScrollBar.right - psbi->rcScrollBar.left;
175 break;
176 case SB_VERT:
177 Thumb = UserGetSystemMetrics(SM_CYVSCROLL);
178 cxy = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top;
179 break;
180 case SB_CTL:
181 IntGetClientRect(Wnd, &ClientRect);
182 if(Wnd->style & SBS_VERT)
183 {
184 Thumb = UserGetSystemMetrics(SM_CYVSCROLL);
185 cxy = ClientRect.bottom - ClientRect.top;
186 }
187 else
188 {
189 Thumb = UserGetSystemMetrics(SM_CXHSCROLL);
190 cxy = ClientRect.right - ClientRect.left;
191 }
192 break;
193 default:
194 return FALSE;
195 }
196
197 ThumbPos = Thumb;
198 /* Calculate Thumb */
199 if(cxy <= (2 * Thumb))
200 {
201 Thumb = cxy / 2;
202 psbi->xyThumbTop = 0;
203 psbi->xyThumbBottom = 0;
204 ThumbPos = Thumb;
205 }
206 else
207 {
208 ThumbBox = pSBData->page ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB);
209 cxy -= (2 * Thumb);
210 if(cxy >= ThumbBox)
211 {
212 if(pSBData->page)
213 {
214 ThumbBox = max(EngMulDiv(cxy, pSBData->page, pSBData->posMax - pSBData->posMin + 1), ThumbBox);
215 }
216
217 if(cxy > ThumbBox)
218 {
219 mx = pSBData->posMax - max(pSBData->page - 1, 0);
220 if(pSBData->posMin < mx)
221 ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, pSBData->pos - pSBData->posMin, mx - pSBData->posMin);
222 else
223 ThumbPos = Thumb + ThumbBox;
224 }
225
226 psbi->xyThumbTop = ThumbPos;
227 psbi->xyThumbBottom = ThumbPos + ThumbBox;
228 }
229 else
230 {
231 psbi->xyThumbTop = 0;
232 psbi->xyThumbBottom = 0;
233 }
234 }
235 psbi->dxyLineButton = Thumb;
236
237 return TRUE;
238 }
239 /*
240 static VOID FASTCALL
241 IntUpdateSBInfo(PWND Window, int wBar)
242 {
243 PSCROLLBARINFO sbi;
244 PSBDATA pSBData;
245
246 ASSERT(Window);
247 ASSERT(Window->pSBInfo);
248 ASSERT(Window->pSBInfoex);
249
250 sbi = IntGetScrollbarInfoFromWindow(Window, wBar);
251 pSBData = IntGetSBData(Window, wBar);
252 IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar));
253 IntCalculateThumb(Window, wBar, sbi, pSBData);
254 }
255 */
256 static BOOL FASTCALL
257 co_IntGetScrollInfo(PWND Window, INT nBar, PSBDATA pSBData, LPSCROLLINFO lpsi)
258 {
259 UINT Mask;
260 LPSCROLLINFO psi;
261
262 ASSERT_REFS_CO(Window);
263
264 if(!SBID_IS_VALID(nBar))
265 {
266 EngSetLastError(ERROR_INVALID_PARAMETER);
267 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar);
268 return FALSE;
269 }
270
271 if (!Window->pSBInfo)
272 {
273 ERR("IntGetScrollInfo No window scrollbar info!\n");
274 return FALSE;
275 }
276
277 psi = IntGetScrollInfoFromWindow(Window, nBar);
278
279 if (lpsi->fMask == SIF_ALL)
280 {
281 Mask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
282 }
283 else
284 {
285 Mask = lpsi->fMask;
286 }
287
288 if (0 != (Mask & SIF_PAGE))
289 {
290 lpsi->nPage = psi->nPage;
291 }
292
293 if (0 != (Mask & SIF_POS))
294 {
295 lpsi->nPos = psi->nPos;
296 }
297
298 if (0 != (Mask & SIF_RANGE))
299 {
300 lpsi->nMin = psi->nMin;
301 lpsi->nMax = psi->nMax;
302 }
303
304 if (0 != (Mask & SIF_TRACKPOS))
305 {
306 lpsi->nTrackPos = psi->nTrackPos;
307 }
308
309 return TRUE;
310 }
311
312 BOOL FASTCALL
313 NEWco_IntGetScrollInfo(
314 PWND pWnd,
315 INT nBar,
316 PSBDATA pSBData,
317 LPSCROLLINFO lpsi)
318 {
319 UINT Mask;
320 PSBTRACK pSBTrack = pWnd->head.pti->pSBTrack;
321
322 if (!SBID_IS_VALID(nBar))
323 {
324 EngSetLastError(ERROR_INVALID_PARAMETER);
325 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar);
326 return FALSE;
327 }
328
329 if (!pWnd->pSBInfo || !pSBTrack) return FALSE;
330
331 Mask = lpsi->fMask;
332
333 if (0 != (Mask & SIF_PAGE))
334 {
335 lpsi->nPage = pSBData->page;
336 }
337
338 if (0 != (Mask & SIF_POS))
339 {
340 lpsi->nPos = pSBData->pos;
341 }
342
343 if (0 != (Mask & SIF_RANGE))
344 {
345 lpsi->nMin = pSBData->posMin;
346 lpsi->nMax = pSBData->posMax;
347 }
348
349 if (0 != (Mask & SIF_TRACKPOS))
350 {
351 if ( pSBTrack &&
352 pSBTrack->nBar == nBar &&
353 pSBTrack->spwndTrack == pWnd )
354 lpsi->nTrackPos = pSBTrack->posNew;
355 else
356 lpsi->nTrackPos = pSBData->pos;
357 }
358 return (Mask & SIF_ALL) !=0;
359 }
360
361 /*************************************************************************
362 * SCROLL_GetScrollBarInfo
363 *
364 * Internal helper for the API function
365 *
366 * PARAMS
367 * hwnd [I] Handle of window with scrollbar(s)
368 * idObject [I] One of OBJID_CLIENT, OBJID_HSCROLL, or OBJID_VSCROLL
369 * info [IO] cbSize specifies the size of the structure
370 *
371 * RETURNS
372 * FALSE if failed
373 */
374 #if 0
375 static BOOL SCROLL_GetScrollBarInfo(HWND hwnd, LONG idObject, LPSCROLLBARINFO info)
376 {
377 LPSCROLLBAR_INFO infoPtr;
378 INT nBar;
379 INT nDummy;
380 DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
381 BOOL pressed;
382 RECT rect;
383
384 switch (idObject)
385 {
386 case OBJID_CLIENT: nBar = SB_CTL; break;
387 case OBJID_HSCROLL: nBar = SB_HORZ; break;
388 case OBJID_VSCROLL: nBar = SB_VERT; break;
389 default: return FALSE;
390 }
391
392 /* handle invalid data structure */
393 if (info->cbSize != sizeof(*info))
394 return FALSE;
395
396 SCROLL_GetScrollBarRect(hwnd, nBar, &info->rcScrollBar, &nDummy,
397 &info->dxyLineButton, &info->xyThumbTop);
398 /* rcScrollBar needs to be in screen coordinates */
399 GetWindowRect(hwnd, &rect);
400 OffsetRect(&info->rcScrollBar, rect.left, rect.top);
401
402 info->xyThumbBottom = info->xyThumbTop + info->dxyLineButton;
403
404 infoPtr = SCROLL_GetInternalInfo(hwnd, nBar, TRUE);
405 if (!infoPtr)
406 return FALSE;
407
408 /* Scroll bar state */
409 info->rgstate[0] = 0;
410 if ((nBar == SB_HORZ && !(style & WS_HSCROLL))
411 || (nBar == SB_VERT && !(style & WS_VSCROLL)))
412 info->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
413 if (infoPtr->minVal >= infoPtr->maxVal - max(infoPtr->page - 1, 0))
414 {
415 if (!(info->rgstate[0] & STATE_SYSTEM_INVISIBLE))
416 info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE;
417 else
418 info->rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
419 }
420 if (nBar == SB_CTL && !IsWindowEnabled(hwnd))
421 info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE;
422
423 pressed = ((nBar == SB_VERT) == SCROLL_trackVertical && GetCapture() == hwnd);
424
425 /* Top/left arrow button state. MSDN says top/right, but I don't believe it */
426 info->rgstate[1] = 0;
427 if (pressed && SCROLL_trackHitTest == SCROLL_TOP_ARROW)
428 info->rgstate[1] |= STATE_SYSTEM_PRESSED;
429 if (infoPtr->flags & ESB_DISABLE_LTUP)
430 info->rgstate[1] |= STATE_SYSTEM_UNAVAILABLE;
431
432 /* Page up/left region state. MSDN says up/right, but I don't believe it */
433 info->rgstate[2] = 0;
434 if (infoPtr->curVal == infoPtr->minVal)
435 info->rgstate[2] |= STATE_SYSTEM_INVISIBLE;
436 if (pressed && SCROLL_trackHitTest == SCROLL_TOP_RECT)
437 info->rgstate[2] |= STATE_SYSTEM_PRESSED;
438
439 /* Thumb state */
440 info->rgstate[3] = 0;
441 if (pressed && SCROLL_trackHitTest == SCROLL_THUMB)
442 info->rgstate[3] |= STATE_SYSTEM_PRESSED;
443
444 /* Page down/right region state. MSDN says down/left, but I don't believe it */
445 info->rgstate[4] = 0;
446 if (infoPtr->curVal >= infoPtr->maxVal - 1)
447 info->rgstate[4] |= STATE_SYSTEM_INVISIBLE;
448 if (pressed && SCROLL_trackHitTest == SCROLL_BOTTOM_RECT)
449 info->rgstate[4] |= STATE_SYSTEM_PRESSED;
450
451 /* Bottom/right arrow button state. MSDN says bottom/left, but I don't believe it */
452 info->rgstate[5] = 0;
453 if (pressed && SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW)
454 info->rgstate[5] |= STATE_SYSTEM_PRESSED;
455 if (infoPtr->flags & ESB_DISABLE_RTDN)
456 info->rgstate[5] |= STATE_SYSTEM_UNAVAILABLE;
457
458 return TRUE;
459 }
460 #endif
461 static DWORD FASTCALL
462 co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
463 {
464 /*
465 * Update the scrollbar state and set action flags according to
466 * what has to be done graphics wise.
467 */
468
469 LPSCROLLINFO Info;
470 PSCROLLBARINFO psbi;
471 UINT new_flags;
472 INT action = 0;
473 PSBDATA pSBData;
474 DWORD OldPos = 0;
475 BOOL bChangeParams = FALSE; /* Don't show/hide scrollbar if params don't change */
476 UINT MaxPage;
477 int MaxPos;
478
479 ASSERT_REFS_CO(Window);
480
481 if(!SBID_IS_VALID(nBar))
482 {
483 EngSetLastError(ERROR_INVALID_PARAMETER);
484 ERR("Trying to set scrollinfo for unknown scrollbar type %d", nBar);
485 return FALSE;
486 }
487
488 if(!co_IntCreateScrollBars(Window))
489 {
490 return FALSE;
491 }
492
493 if (lpsi->cbSize != sizeof(SCROLLINFO) &&
494 lpsi->cbSize != (sizeof(SCROLLINFO) - sizeof(lpsi->nTrackPos)))
495 {
496 EngSetLastError(ERROR_INVALID_PARAMETER);
497 return 0;
498 }
499 if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL | SIF_PREVIOUSPOS))
500 {
501 EngSetLastError(ERROR_INVALID_PARAMETER);
502 return 0;
503 }
504
505 psbi = IntGetScrollbarInfoFromWindow(Window, nBar);
506 Info = IntGetScrollInfoFromWindow(Window, nBar);
507 pSBData = IntGetSBData(Window, nBar);
508
509 /* Set the page size */
510 if (lpsi->fMask & SIF_PAGE)
511 {
512 if (Info->nPage != lpsi->nPage)
513 {
514 Info->nPage = lpsi->nPage;
515 pSBData->page = lpsi->nPage;
516 bChangeParams = TRUE;
517 }
518 }
519
520 /* Set the scroll pos */
521 if (lpsi->fMask & SIF_POS)
522 {
523 if (Info->nPos != lpsi->nPos)
524 {
525 OldPos = Info->nPos;
526 Info->nPos = lpsi->nPos;
527 pSBData->pos = lpsi->nPos;
528 bChangeParams = TRUE;
529 }
530 }
531
532 /* Set the scroll range */
533 if (lpsi->fMask & SIF_RANGE)
534 {
535 if (lpsi->nMin > lpsi->nMax)
536 {
537 Info->nMin = lpsi->nMin;
538 Info->nMax = lpsi->nMin;
539 pSBData->posMin = lpsi->nMin;
540 pSBData->posMax = lpsi->nMin;
541 bChangeParams = TRUE;
542 }
543 else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax)
544 {
545 Info->nMin = lpsi->nMin;
546 Info->nMax = lpsi->nMax;
547 pSBData->posMin = lpsi->nMin;
548 pSBData->posMax = lpsi->nMax;
549 bChangeParams = TRUE;
550 }
551 }
552
553 /* Make sure the page size is valid */
554 MaxPage = abs(Info->nMax - Info->nMin) + 1;
555 if (Info->nPage > MaxPage)
556 {
557 pSBData->page = Info->nPage = MaxPage;
558 }
559
560 /* Make sure the pos is inside the range */
561 MaxPos = Info->nMax + 1 - (int)max(Info->nPage, 1);
562 ASSERT(MaxPos >= Info->nMin);
563 if (Info->nPos < Info->nMin)
564 {
565 pSBData->pos = Info->nPos = Info->nMin;
566 }
567 else if (Info->nPos > MaxPos)
568 {
569 pSBData->pos = Info->nPos = MaxPos;
570 }
571
572 /*
573 * Don't change the scrollbar state if SetScrollInfo is just called
574 * with SIF_DISABLENOSCROLL
575 */
576 if (!(lpsi->fMask & SIF_ALL))
577 {
578 //goto done;
579 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos;
580 }
581
582 /* Check if the scrollbar should be hidden or disabled */
583 if (lpsi->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
584 {
585 new_flags = Window->pSBInfo->WSBflags;
586 if (Info->nMin >= (int)(Info->nMax - max(Info->nPage - 1, 0)))
587 {
588 /* Hide or disable scroll-bar */
589 if (lpsi->fMask & SIF_DISABLENOSCROLL)
590 {
591 new_flags = ESB_DISABLE_BOTH;
592 bChangeParams = TRUE;
593 }
594 else if ((nBar != SB_CTL) && bChangeParams)
595 {
596 action = SA_SSI_HIDE;
597 }
598 }
599 else /* Show and enable scroll-bar only if no page only changed. */
600 if (lpsi->fMask != SIF_PAGE)
601 {
602 new_flags = ESB_ENABLE_BOTH;
603 if ((nBar != SB_CTL) && bChangeParams)
604 {
605 action |= SA_SSI_SHOW;
606 }
607 }
608
609 if (Window->pSBInfo->WSBflags != new_flags) /* Check arrow flags */
610 {
611 Window->pSBInfo->WSBflags = new_flags;
612 action |= SA_SSI_REPAINT_ARROWS;
613 }
614 }
615
616 //done:
617 if ( action & SA_SSI_HIDE )
618 {
619 co_UserShowScrollBar(Window, nBar, FALSE, FALSE);
620 }
621 else
622 {
623 if ( action & SA_SSI_SHOW )
624 if ( co_UserShowScrollBar(Window, nBar, TRUE, TRUE) )
625 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; /* SetWindowPos() already did the painting */
626 if (bRedraw)
627 { // FIXME: Arrows and interior.
628 RECTL UpdateRect = psbi->rcScrollBar;
629 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left;
630 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left;
631 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top;
632 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
633 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
634 } // FIXME: Arrows
635 /* else if( action & SA_SSI_REPAINT_ARROWS )
636 {
637 RECTL UpdateRect = psbi->rcScrollBar;
638 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left;
639 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left;
640 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top;
641 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
642 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
643 }
644 */ }
645 /* Return current position */
646 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos;
647 }
648
649 BOOL FASTCALL
650 co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi)
651 {
652 INT Bar;
653 PSCROLLBARINFO sbi;
654 PSBDATA pSBData;
655 ASSERT_REFS_CO(Window);
656
657 Bar = SBOBJ_TO_SBID(idObject);
658
659 if(!SBID_IS_VALID(Bar))
660 {
661 EngSetLastError(ERROR_INVALID_PARAMETER);
662 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar);
663 return FALSE;
664 }
665
666 if(!co_IntCreateScrollBars(Window))
667 {
668 ERR("Failed to create scrollbars for window.\n");
669 return FALSE;
670 }
671
672 sbi = IntGetScrollbarInfoFromWindow(Window, Bar);
673 pSBData = IntGetSBData(Window, Bar);
674
675 IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar));
676 IntCalculateThumb(Window, Bar, sbi, pSBData);
677
678 /* Scroll bar state */
679 psbi->rgstate[0] = 0;
680 if ((Bar == SB_HORZ && !(Window->style & WS_HSCROLL))
681 || (Bar == SB_VERT && !(Window->style & WS_VSCROLL)))
682 psbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
683 if (pSBData->posMin >= pSBData->posMax - max(pSBData->page - 1, 0))
684 {
685 if (!(psbi->rgstate[0] & STATE_SYSTEM_INVISIBLE))
686 psbi->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE;
687 else
688 psbi->rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
689 }
690 if (Bar == SB_CTL && !(Window->style & WS_DISABLED))
691 psbi->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE;
692
693 RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO));
694
695 return TRUE;
696 }
697
698 BOOL FASTCALL
699 co_IntSetScrollBarInfo(PWND Window, LONG idObject, PSETSCROLLBARINFO psbi)
700 {
701 INT Bar;
702 PSCROLLBARINFO sbi;
703 LPSCROLLINFO psi;
704 ASSERT_REFS_CO(Window);
705
706 Bar = SBOBJ_TO_SBID(idObject);
707
708 if(!SBID_IS_VALID(Bar))
709 {
710 EngSetLastError(ERROR_INVALID_PARAMETER);
711 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar);
712 return FALSE;
713 }
714
715 if(!co_IntCreateScrollBars(Window))
716 {
717 ERR("Failed to create scrollbars for window.\n");
718 return FALSE;
719 }
720
721 sbi = IntGetScrollbarInfoFromWindow(Window, Bar);
722 psi = IntGetScrollInfoFromWindow(Window, Bar);
723
724 psi->nTrackPos = psbi->nTrackPos;
725 sbi->reserved = psbi->reserved;
726 RtlCopyMemory(&sbi->rgstate, &psbi->rgstate, sizeof(psbi->rgstate));
727
728 return TRUE;
729 }
730
731 BOOL FASTCALL
732 co_IntCreateScrollBars(PWND Window)
733 {
734 PSCROLLBARINFO psbi;
735 PSBDATA pSBData;
736 ULONG Size, s;
737 INT i;
738
739 ASSERT_REFS_CO(Window);
740
741 if (Window->pSBInfo && Window->pSBInfoex)
742 {
743 /* No need to create it anymore */
744 return TRUE;
745 }
746
747 /* Allocate memory for all scrollbars (HORZ, VERT, CONTROL) */
748 Size = 3 * (sizeof(SBINFOEX));
749 if(!(Window->pSBInfoex = ExAllocatePoolWithTag(PagedPool, Size, TAG_SBARINFO)))
750 {
751 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window->head.h);
752 return FALSE;
753 }
754
755 RtlZeroMemory(Window->pSBInfoex, Size);
756
757 if(!(Window->pSBInfo = DesktopHeapAlloc( Window->head.rpdesk, sizeof(SBINFO))))
758 {
759 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window->head.h);
760 return FALSE;
761 }
762
763 RtlZeroMemory(Window->pSBInfo, sizeof(SBINFO));
764 Window->pSBInfo->Vert.posMax = 100;
765 Window->pSBInfo->Horz.posMax = 100;
766
767 co_WinPosGetNonClientSize(Window,
768 &Window->rcWindow,
769 &Window->rcClient);
770
771 for(s = SB_HORZ; s <= SB_VERT; s++)
772 {
773 psbi = IntGetScrollbarInfoFromWindow(Window, s);
774 psbi->cbSize = sizeof(SCROLLBARINFO);
775 for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++)
776 psbi->rgstate[i] = 0;
777
778 pSBData = IntGetSBData(Window, s);
779
780 IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar));
781 IntCalculateThumb(Window, s, psbi, pSBData);
782 }
783
784 return TRUE;
785 }
786
787 BOOL FASTCALL
788 IntDestroyScrollBars(PWND Window)
789 {
790 if (Window->pSBInfo && Window->pSBInfoex)
791 {
792 DesktopHeapFree(Window->head.rpdesk, Window->pSBInfo);
793 Window->pSBInfo = NULL;
794 ExFreePoolWithTag(Window->pSBInfoex, TAG_SBARINFO);
795 Window->pSBInfoex = NULL;
796 return TRUE;
797 }
798 return FALSE;
799 }
800
801 BOOL APIENTRY
802 IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows)
803 {
804 BOOL Chg = FALSE;
805 switch(wArrows)
806 {
807 case ESB_DISABLE_BOTH:
808 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
809 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
810 break;
811 case ESB_DISABLE_RTDN:
812 if(Horz)
813 {
814 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
815 }
816 else
817 {
818 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
819 }
820 break;
821 case ESB_DISABLE_LTUP:
822 if(Horz)
823 {
824 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE);
825 }
826 else
827 {
828 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE);
829 }
830 break;
831 case ESB_ENABLE_BOTH:
832 CHANGERGSTATE(SBRG_TOPRIGHTBTN, 0);
833 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, 0);
834 break;
835 }
836 return Chg;
837 }
838
839 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
840 DWORD FASTCALL
841 co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV)
842 {
843 ULONG old_style, set_bits = 0, clear_bits = 0;
844
845 ASSERT_REFS_CO(Wnd);
846
847 switch(nBar)
848 {
849 case SB_CTL:
850 {
851 //IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o!
852
853 co_WinPosShowWindow(Wnd, fShowH ? SW_SHOW : SW_HIDE);
854 return TRUE;
855 }
856 case SB_BOTH:
857 case SB_HORZ:
858 if (fShowH) set_bits |= WS_HSCROLL;
859 else clear_bits |= WS_HSCROLL;
860 if( nBar == SB_HORZ ) break;
861 /* Fall through */
862 case SB_VERT:
863 if (fShowV) set_bits |= WS_VSCROLL;
864 else clear_bits |= WS_VSCROLL;
865 break;
866 default:
867 EngSetLastError(ERROR_INVALID_PARAMETER);
868 return FALSE; /* Nothing to do! */
869 }
870
871 old_style = IntSetStyle( Wnd, set_bits, clear_bits );
872 if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits)
873 {
874 ///// Is this needed? Was tested w/o!
875 //if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ);
876 //if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT);
877 /////
878 /* Frame has been changed, let the window redraw itself */
879 co_WinPosSetWindowPos( Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
880 | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
881 return TRUE;
882 }
883 return FALSE; /* no frame changes */
884 }
885
886 static void
887 IntDrawScrollInterior(PWND pWnd, HDC hDC, INT nBar, BOOL Vertical, PSCROLLBARINFO ScrollBarInfo)
888 {
889 INT ThumbSize = ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop;
890 INT ThumbTop = ScrollBarInfo->xyThumbTop;
891 RECT Rect;
892 HBRUSH hSaveBrush, hBrush;
893 BOOL TopSelected = FALSE, BottomSelected = FALSE;
894
895 if (ScrollBarInfo->rgstate[SCROLL_TOP_RECT] & STATE_SYSTEM_PRESSED)
896 TopSelected = TRUE;
897 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_RECT] & STATE_SYSTEM_PRESSED)
898 BottomSelected = TRUE;
899
900 /*
901 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
902 * The window-owned scrollbars need to call DefWndControlColor
903 * to correctly setup default scrollbar colors
904 */
905 if (nBar == SB_CTL)
906 {
907 hBrush = GetControlBrush( pWnd, hDC, WM_CTLCOLORSCROLLBAR);
908 if (!hBrush)
909 hBrush = IntGetSysColorBrush(COLOR_SCROLLBAR);
910 }
911 else
912 {
913 hBrush = DefWndControlColor(hDC, CTLCOLOR_SCROLLBAR);
914 }
915
916 hSaveBrush = NtGdiSelectBrush(hDC, hBrush);
917
918 /* Calculate the scroll rectangle */
919 if (Vertical)
920 {
921 Rect.top = ScrollBarInfo->rcScrollBar.top + ScrollBarInfo->dxyLineButton;
922 Rect.bottom = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->dxyLineButton;
923 Rect.left = ScrollBarInfo->rcScrollBar.left;
924 Rect.right = ScrollBarInfo->rcScrollBar.right;
925 }
926 else
927 {
928 Rect.top = ScrollBarInfo->rcScrollBar.top;
929 Rect.bottom = ScrollBarInfo->rcScrollBar.bottom;
930 Rect.left = ScrollBarInfo->rcScrollBar.left + ScrollBarInfo->dxyLineButton;
931 Rect.right = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->dxyLineButton;
932 }
933
934 /* Draw the scroll rectangles and thumb */
935 if (!ScrollBarInfo->xyThumbBottom)
936 {
937 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left,
938 Rect.bottom - Rect.top, PATCOPY);
939
940 /* Cleanup and return */
941 NtGdiSelectBrush(hDC, hSaveBrush);
942 return;
943 }
944
945 ThumbTop -= ScrollBarInfo->dxyLineButton;
946
947 if (ScrollBarInfo->dxyLineButton)
948 {
949 if (Vertical)
950 {
951 if (ThumbSize)
952 {
953 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left,
954 ThumbTop, TopSelected ? BLACKNESS : PATCOPY);
955 Rect.top += ThumbTop;
956 NtGdiPatBlt(hDC, Rect.left, Rect.top + ThumbSize, Rect.right - Rect.left,
957 Rect.bottom - Rect.top - ThumbSize, BottomSelected ? BLACKNESS : PATCOPY);
958 Rect.bottom = Rect.top + ThumbSize;
959 }
960 else
961 {
962 if (ThumbTop)
963 {
964 NtGdiPatBlt(hDC, Rect.left, ScrollBarInfo->dxyLineButton,
965 Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY);
966 }
967 }
968 }
969 else
970 {
971 if (ThumbSize)
972 {
973 NtGdiPatBlt(hDC, Rect.left, Rect.top, ThumbTop,
974 Rect.bottom - Rect.top, TopSelected ? BLACKNESS : PATCOPY);
975 Rect.left += ThumbTop;
976 NtGdiPatBlt(hDC, Rect.left + ThumbSize, Rect.top,
977 Rect.right - Rect.left - ThumbSize, Rect.bottom - Rect.top,
978 BottomSelected ? BLACKNESS : PATCOPY);
979 Rect.right = Rect.left + ThumbSize;
980 }
981 else
982 {
983 if (ThumbTop)
984 {
985 NtGdiPatBlt(hDC, ScrollBarInfo->dxyLineButton, Rect.top,
986 Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY);
987 }
988 }
989 }
990 }
991
992 /* Draw the thumb */
993 if (ThumbSize)
994 DrawEdge(hDC, &Rect, EDGE_RAISED, BF_RECT | BF_MIDDLE);
995
996 /* Cleanup */
997 NtGdiSelectBrush(hDC, hSaveBrush);
998 }
999
1000
1001 static VOID FASTCALL
1002 IntDrawScrollArrows(HDC hDC, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical)
1003 {
1004 RECT RectLT, RectRB;
1005 INT ScrollDirFlagLT, ScrollDirFlagRB;
1006
1007 RectLT = RectRB = ScrollBarInfo->rcScrollBar;
1008 if (Vertical)
1009 {
1010 ScrollDirFlagLT = DFCS_SCROLLUP;
1011 ScrollDirFlagRB = DFCS_SCROLLDOWN;
1012 RectLT.bottom = RectLT.top + ScrollBarInfo->dxyLineButton;
1013 RectRB.top = RectRB.bottom - ScrollBarInfo->dxyLineButton;
1014 }
1015 else
1016 {
1017 ScrollDirFlagLT = DFCS_SCROLLLEFT;
1018 ScrollDirFlagRB = DFCS_SCROLLRIGHT;
1019 RectLT.right = RectLT.left + ScrollBarInfo->dxyLineButton;
1020 RectRB.left = RectRB.right - ScrollBarInfo->dxyLineButton;
1021 }
1022
1023 if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_PRESSED)
1024 {
1025 ScrollDirFlagLT |= DFCS_PUSHED | DFCS_FLAT;
1026 }
1027 if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE)
1028 {
1029 ScrollDirFlagLT |= DFCS_INACTIVE;
1030 }
1031 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_PRESSED)
1032 {
1033 ScrollDirFlagRB |= DFCS_PUSHED | DFCS_FLAT;
1034 }
1035 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE)
1036 {
1037 ScrollDirFlagRB |= DFCS_INACTIVE;
1038 }
1039
1040 DrawFrameControl(hDC, &RectLT, DFC_SCROLL, ScrollDirFlagLT);
1041 DrawFrameControl(hDC, &RectRB, DFC_SCROLL, ScrollDirFlagRB);
1042 }
1043
1044 static LONG FASTCALL
1045 IntScrollGetObjectId(INT SBType)
1046 {
1047 if (SBType == SB_VERT)
1048 return OBJID_VSCROLL;
1049 if (SBType == SB_HORZ)
1050 return OBJID_HSCROLL;
1051 return OBJID_CLIENT;
1052 }
1053
1054 void
1055 IntDrawScrollBar(PWND Wnd, HDC DC, INT Bar)
1056 {
1057 //PSBWND pSBWnd;
1058 //INT ThumbSize;
1059 PTHREADINFO pti;
1060 SCROLLBARINFO Info;
1061 BOOL Vertical;
1062
1063 pti = PsGetCurrentThreadWin32Thread();
1064
1065 /*
1066 * Get scroll bar info.
1067 */
1068 switch (Bar)
1069 {
1070 case SB_HORZ:
1071 Vertical = FALSE;
1072 break;
1073
1074 case SB_VERT:
1075 Vertical = TRUE;
1076 break;
1077
1078 case SB_CTL:
1079 Vertical = (Wnd->style & SBS_VERT) != 0;
1080 break;
1081
1082 default:
1083 return;
1084 }
1085
1086 if (!co_IntGetScrollBarInfo(Wnd, IntScrollGetObjectId(Bar), &Info))
1087 {
1088 return;
1089 }
1090
1091 if (RECTL_bIsEmptyRect(&Info.rcScrollBar))
1092 {
1093 return;
1094 }
1095
1096 //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop;
1097
1098 /*
1099 * Draw the arrows.
1100 */
1101 if (Info.dxyLineButton)
1102 {
1103 IntDrawScrollArrows(DC, &Info, Vertical);
1104 }
1105
1106 /*
1107 * Draw the interior.
1108 */
1109 IntDrawScrollInterior(Wnd, DC, Bar, Vertical, &Info);
1110
1111 /*
1112 * If scroll bar has focus, reposition the caret.
1113 */
1114 if ( Wnd == pti->MessageQueue->spwndFocus && Bar == SB_CTL )
1115 {
1116 if (Vertical)
1117 {
1118 co_IntSetCaretPos(Info.rcScrollBar.top + 1, Info.dxyLineButton + 1);
1119 }
1120 else
1121 {
1122 co_IntSetCaretPos(Info.dxyLineButton + 1, Info.rcScrollBar.top + 1);
1123 }
1124 }
1125 }
1126
1127
1128 LRESULT APIENTRY
1129 ScrollBarWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
1130 {
1131 LRESULT lResult = 0;
1132 PWND pWnd;
1133 pWnd = UserGetWindowObject(hWnd);
1134 if (!pWnd) return 0;
1135
1136 switch(Msg)
1137 {
1138 case WM_ENABLE:
1139 {
1140 if (pWnd->pSBInfo)
1141 {
1142 pWnd->pSBInfo->WSBflags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
1143 }
1144 }
1145 break;
1146 }
1147 return lResult;
1148 }
1149
1150 ////
1151
1152 BOOL
1153 APIENTRY
1154 NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
1155 {
1156 NTSTATUS Status;
1157 SCROLLBARINFO sbi;
1158 PWND Window;
1159 BOOL Ret;
1160 DECLARE_RETURN(BOOL);
1161 USER_REFERENCE_ENTRY Ref;
1162
1163 TRACE("Enter NtUserGetScrollBarInfo\n");
1164 UserEnterExclusive();
1165
1166 Status = MmCopyFromCaller(&sbi, psbi, sizeof(SCROLLBARINFO));
1167 if(!NT_SUCCESS(Status) || (sbi.cbSize != sizeof(SCROLLBARINFO)))
1168 {
1169 SetLastNtError(Status);
1170 RETURN(FALSE);
1171 }
1172
1173 if(!(Window = UserGetWindowObject(hWnd)))
1174 {
1175 RETURN(FALSE);
1176 }
1177
1178 UserRefObjectCo(Window, &Ref);
1179 Ret = co_IntGetScrollBarInfo(Window, idObject, &sbi);
1180 UserDerefObjectCo(Window);
1181
1182 Status = MmCopyToCaller(psbi, &sbi, sizeof(SCROLLBARINFO));
1183 if(!NT_SUCCESS(Status))
1184 {
1185 SetLastNtError(Status);
1186 Ret = FALSE;
1187 }
1188
1189 RETURN( Ret);
1190
1191 CLEANUP:
1192 TRACE("Leave NtUserGetScrollBarInfo, ret=%i\n",_ret_);
1193 UserLeave();
1194 END_CLEANUP;
1195
1196 }
1197
1198 BOOL
1199 APIENTRY
1200 NtUserSBGetParms(
1201 HWND hWnd,
1202 int fnBar,
1203 PSBDATA pSBData,
1204 LPSCROLLINFO lpsi)
1205 {
1206 PWND Window;
1207 SCROLLINFO psi;
1208 BOOL Ret;
1209 SBDATA SBDataSafe;
1210 DECLARE_RETURN(BOOL);
1211 USER_REFERENCE_ENTRY Ref;
1212
1213 TRACE("Enter NtUserGetScrollInfo\n");
1214 UserEnterShared();
1215
1216 _SEH2_TRY
1217 {
1218 RtlCopyMemory(&psi, lpsi, sizeof(SCROLLINFO));
1219 if (pSBData)
1220 {
1221 RtlCopyMemory(&SBDataSafe, pSBData, sizeof(SBDATA));
1222 }
1223 }
1224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1225 {
1226 ERR("NtUserGetScrollInfo Failed size.\n");
1227 SetLastNtError(_SEH2_GetExceptionCode());
1228 _SEH2_YIELD(RETURN(FALSE));
1229 }
1230 _SEH2_END
1231
1232 if(!(Window = UserGetWindowObject(hWnd)))
1233 {
1234 ERR("NtUserGetScrollInfo Bad window.\n");
1235 RETURN(FALSE);
1236 }
1237
1238 UserRefObjectCo(Window, &Ref);
1239 Ret = co_IntGetScrollInfo(Window, fnBar, &SBDataSafe, &psi);
1240 UserDerefObjectCo(Window);
1241
1242 _SEH2_TRY
1243 {
1244 RtlCopyMemory(lpsi, &psi, sizeof(SCROLLINFO));
1245 }
1246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1247 {
1248 ERR("NtUserGetScrollInfo Failed copy to user.\n");
1249 SetLastNtError(_SEH2_GetExceptionCode());
1250 _SEH2_YIELD(RETURN(FALSE));
1251 }
1252 _SEH2_END
1253
1254 RETURN( Ret);
1255
1256 CLEANUP:
1257 TRACE("Leave NtUserGetScrollInfo, ret=%i\n",_ret_);
1258 UserLeave();
1259 END_CLEANUP;
1260 }
1261
1262 BOOL
1263 APIENTRY
1264 NtUserEnableScrollBar(
1265 HWND hWnd,
1266 UINT wSBflags,
1267 UINT wArrows)
1268 {
1269 UINT OrigArrows;
1270 PWND Window = NULL;
1271 PSCROLLBARINFO InfoV = NULL, InfoH = NULL;
1272 BOOL Chg = FALSE;
1273 DECLARE_RETURN(BOOL);
1274 USER_REFERENCE_ENTRY Ref;
1275
1276 TRACE("Enter NtUserEnableScrollBar\n");
1277 UserEnterExclusive();
1278
1279 if (!(Window = UserGetWindowObject(hWnd)) ||
1280 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
1281 {
1282 RETURN(FALSE);
1283 }
1284 UserRefObjectCo(Window, &Ref);
1285
1286 if (!co_IntCreateScrollBars(Window))
1287 {
1288 RETURN( FALSE);
1289 }
1290
1291 OrigArrows = Window->pSBInfo->WSBflags;
1292 Window->pSBInfo->WSBflags = wArrows;
1293
1294 if (wSBflags == SB_CTL)
1295 {
1296 if ((wArrows == ESB_DISABLE_BOTH || wArrows == ESB_ENABLE_BOTH))
1297 IntEnableWindow(hWnd, (wArrows == ESB_ENABLE_BOTH));
1298
1299 RETURN(TRUE);
1300 }
1301
1302 if(wSBflags != SB_BOTH && !SBID_IS_VALID(wSBflags))
1303 {
1304 EngSetLastError(ERROR_INVALID_PARAMETER);
1305 ERR("Trying to set scrollinfo for unknown scrollbar type %u", wSBflags);
1306 RETURN(FALSE);
1307 }
1308
1309 switch(wSBflags)
1310 {
1311 case SB_BOTH:
1312 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT);
1313 /* Fall through */
1314 case SB_HORZ:
1315 InfoH = IntGetScrollbarInfoFromWindow(Window, SB_HORZ);
1316 break;
1317 case SB_VERT:
1318 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT);
1319 break;
1320 default:
1321 RETURN(FALSE);
1322 }
1323
1324 if(InfoV)
1325 Chg = IntEnableScrollBar(FALSE, InfoV, wArrows);
1326
1327 if(InfoH)
1328 Chg = (IntEnableScrollBar(TRUE, InfoH, wArrows) || Chg);
1329
1330 ERR("FIXME: EnableScrollBar wSBflags %u wArrows %u Chg %d\n", wSBflags, wArrows, Chg);
1331 // Done in user32:
1332 // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
1333
1334 RETURN( Chg);
1335 if (OrigArrows == wArrows) RETURN( FALSE);
1336 RETURN( TRUE);
1337
1338 CLEANUP:
1339 if (Window)
1340 UserDerefObjectCo(Window);
1341
1342 TRACE("Leave NtUserEnableScrollBar, ret=%i\n",_ret_);
1343 UserLeave();
1344 END_CLEANUP;
1345 }
1346
1347 DWORD
1348 APIENTRY
1349 NtUserSetScrollInfo(
1350 HWND hWnd,
1351 int fnBar,
1352 LPCSCROLLINFO lpsi,
1353 BOOL bRedraw)
1354 {
1355 PWND Window = NULL;
1356 NTSTATUS Status;
1357 SCROLLINFO ScrollInfo;
1358 DECLARE_RETURN(DWORD);
1359 USER_REFERENCE_ENTRY Ref;
1360
1361 TRACE("Enter NtUserSetScrollInfo\n");
1362 UserEnterExclusive();
1363
1364 if(!(Window = UserGetWindowObject(hWnd)) ||
1365 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
1366 {
1367 RETURN( 0);
1368 }
1369 UserRefObjectCo(Window, &Ref);
1370
1371 Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos));
1372 if(!NT_SUCCESS(Status))
1373 {
1374 SetLastNtError(Status);
1375 RETURN( 0);
1376 }
1377
1378 RETURN(co_IntSetScrollInfo(Window, fnBar, &ScrollInfo, bRedraw));
1379
1380 CLEANUP:
1381 if (Window)
1382 UserDerefObjectCo(Window);
1383
1384 TRACE("Leave NtUserSetScrollInfo, ret=%lu\n", _ret_);
1385 UserLeave();
1386 END_CLEANUP;
1387
1388 }
1389
1390 DWORD APIENTRY
1391 NtUserShowScrollBar(HWND hWnd, int nBar, DWORD bShow)
1392 {
1393 PWND Window;
1394 DECLARE_RETURN(DWORD);
1395 DWORD ret;
1396 USER_REFERENCE_ENTRY Ref;
1397
1398 TRACE("Enter NtUserShowScrollBar\n");
1399 UserEnterExclusive();
1400
1401 if (!(Window = UserGetWindowObject(hWnd)))
1402 {
1403 RETURN(0);
1404 }
1405
1406 UserRefObjectCo(Window, &Ref);
1407 ret = co_UserShowScrollBar(Window, nBar, (nBar == SB_VERT) ? 0 : bShow,
1408 (nBar == SB_HORZ) ? 0 : bShow);
1409 UserDerefObjectCo(Window);
1410
1411 RETURN(ret);
1412
1413 CLEANUP:
1414 TRACE("Leave NtUserShowScrollBar, ret%lu\n", _ret_);
1415 UserLeave();
1416 END_CLEANUP;
1417
1418 }
1419
1420
1421 //// Ugly NtUser API ////
1422
1423 BOOL
1424 APIENTRY
1425 NtUserSetScrollBarInfo(
1426 HWND hWnd,
1427 LONG idObject,
1428 SETSCROLLBARINFO *info)
1429 {
1430 PWND Window = NULL;
1431 SETSCROLLBARINFO Safeinfo;
1432 PSCROLLBARINFO sbi;
1433 LPSCROLLINFO psi;
1434 NTSTATUS Status;
1435 LONG Obj;
1436 DECLARE_RETURN(BOOL);
1437 USER_REFERENCE_ENTRY Ref;
1438
1439 TRACE("Enter NtUserSetScrollBarInfo\n");
1440 UserEnterExclusive();
1441
1442 if(!(Window = UserGetWindowObject(hWnd)))
1443 {
1444 RETURN( FALSE);
1445 }
1446 UserRefObjectCo(Window, &Ref);
1447
1448 Obj = SBOBJ_TO_SBID(idObject);
1449 if(!SBID_IS_VALID(Obj))
1450 {
1451 EngSetLastError(ERROR_INVALID_PARAMETER);
1452 ERR("Trying to set scrollinfo for unknown scrollbar type %d\n", Obj);
1453 RETURN( FALSE);
1454 }
1455
1456 if(!co_IntCreateScrollBars(Window))
1457 {
1458 RETURN(FALSE);
1459 }
1460
1461 Status = MmCopyFromCaller(&Safeinfo, info, sizeof(SETSCROLLBARINFO));
1462 if(!NT_SUCCESS(Status))
1463 {
1464 SetLastNtError(Status);
1465 RETURN(FALSE);
1466 }
1467
1468 sbi = IntGetScrollbarInfoFromWindow(Window, Obj);
1469 psi = IntGetScrollInfoFromWindow(Window, Obj);
1470
1471 psi->nTrackPos = Safeinfo.nTrackPos;
1472 sbi->reserved = Safeinfo.reserved;
1473 RtlCopyMemory(&sbi->rgstate, &Safeinfo.rgstate, sizeof(Safeinfo.rgstate));
1474
1475 RETURN(TRUE);
1476
1477 CLEANUP:
1478 if (Window)
1479 UserDerefObjectCo(Window);
1480
1481 TRACE("Leave NtUserSetScrollBarInfo, ret=%i\n",_ret_);
1482 UserLeave();
1483 END_CLEANUP;
1484 }
1485
1486 /* EOF */