diff options
Diffstat (limited to 'wintable/scroll.h')
| -rw-r--r-- | wintable/scroll.h | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/wintable/scroll.h b/wintable/scroll.h new file mode 100644 index 0000000..1f333a8 --- /dev/null +++ b/wintable/scroll.h @@ -0,0 +1,130 @@ +// 9 december 2014 + +struct scrollParams { + intptr_t *pos; + intptr_t pagesize; + intptr_t length; + intptr_t scale; + void (*post)(struct table *); + int *wheelCarry; +}; + +static void scrollto(struct table *t, int which, struct scrollParams *p, intptr_t pos) +{ + RECT scrollArea; + SCROLLINFO si; + intptr_t xamount, yamount; + + if (pos < 0) + pos = 0; + if (pos > p->length - p->pagesize) + pos = p->length - p->pagesize; + + // we don't want to scroll the header + if (GetClientRect(t->hwnd, &scrollArea) == 0) + panic("error getting Table client rect for scrollto()"); + scrollArea.top += t->headerHeight; + + // negative because ScrollWindowEx() is "backwards" + xamount = -(pos - *(p->pos)) * p->scale; + yamount = 0; + if (which == SB_VERT) { + yamount = xamount; + xamount = 0; + } + + if (ScrollWindowEx(t->hwnd, xamount, yamount, + &scrollArea, &scrollArea, NULL, NULL, + SW_ERASE | SW_INVALIDATE) == ERROR) +;// TODO failure case ignored for now; see https://bugs.winehq.org/show_bug.cgi?id=37706 +// panic("error scrolling Table"); + // TODO call UpdateWindow()? + + *(p->pos) = pos; + + // now commit our new scrollbar setup... + ZeroMemory(&si, sizeof (SCROLLINFO)); + si.cbSize = sizeof (SCROLLINFO); + si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + si.nPage = p->pagesize; + si.nMin = 0; + si.nMax = p->length - 1; // endpoint inclusive + si.nPos = *(p->pos); + SetScrollInfo(t->hwnd, which, &si, TRUE); + + if (p->post != NULL) + (*(p->post))(t); +} + +static void scrollby(struct table *t, int which, struct scrollParams *p, intptr_t delta) +{ + scrollto(t, which, p, *(p->pos) + delta); +} + +static void scroll(struct table *t, int which, struct scrollParams *p, WPARAM wParam, LPARAM lParam) +{ + intptr_t pos; + SCROLLINFO si; + + pos = *(p->pos); + switch (LOWORD(wParam)) { + case SB_LEFT: // also SB_TOP + pos = 0; + break; + case SB_RIGHT: // also SB_BOTTOM + pos = p->length - p->pagesize; + break; + case SB_LINELEFT: // also SB_LINEUP + pos--; + break; + case SB_LINERIGHT: // also SB_LINEDOWN + pos++; + break; + case SB_PAGELEFT: // also SB_PAGEUP + pos -= p->pagesize; + break; + case SB_PAGERIGHT: // also SB_PAGEDOWN + pos += p->pagesize; + break; + case SB_THUMBPOSITION: + ZeroMemory(&si, sizeof (SCROLLINFO)); + si.cbSize = sizeof (SCROLLINFO); + si.fMask = SIF_POS; + if (GetScrollInfo(t->hwnd, which, &si) == 0) + panic("error getting thumb position for scroll() in Table"); + pos = si.nPos; + break; + case SB_THUMBTRACK: + ZeroMemory(&si, sizeof (SCROLLINFO)); + si.cbSize = sizeof (SCROLLINFO); + si.fMask = SIF_TRACKPOS; + if (GetScrollInfo(t->hwnd, which, &si) == 0) + panic("error getting thumb track position for scroll() in Table"); + pos = si.nTrackPos; + break; + } + scrollto(t, which, p, pos); +} + +static void wheelscroll(struct table *t, int which, struct scrollParams *p, WPARAM wParam, LPARAM lParam) +{ + int delta; + int lines; + UINT scrollAmount; + + delta = GET_WHEEL_DELTA_WPARAM(wParam); + // TODO make a note of what the appropriate hscroll constant is + if (SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &scrollAmount, 0) == 0) + // TODO use scrollAmount == 3 instead? + panic("error getting wheel scroll amount in wheelscroll()"); + if (scrollAmount == WHEEL_PAGESCROLL) + scrollAmount = p->pagesize; + if (scrollAmount == 0) // no mouse wheel scrolling (or t->pagesize == 0) + return; + // the rest of this is basically http://blogs.msdn.com/b/oldnewthing/archive/2003/08/07/54615.aspx and http://blogs.msdn.com/b/oldnewthing/archive/2003/08/11/54624.aspx + // see those pages for information on subtleties + delta += *(p->wheelCarry); + lines = delta * ((int) scrollAmount) / WHEEL_DELTA; + *(p->wheelCarry) = delta - lines * WHEEL_DELTA / ((int) scrollAmount); + scrollby(t, which, p, -lines); +} |
