/* handle a hscroll message */ void gtab_msg_hscroll(HWND hwnd, lpTable ptab, int opcode, int pos) { int change; switch(opcode) { case SB_THUMBPOSITION: case SB_THUMBTRACK: change = pos - ptab->scroll_dx; break; case SB_LINEUP: change = -(ptab->avewidth); break; case SB_LINEDOWN: change = ptab->avewidth; break; case SB_PAGEUP: change = - (ptab->winwidth * 2 / 3); break; case SB_PAGEDOWN: change = (ptab->winwidth * 2 / 3); break; default: return; } gtab_dohscroll(hwnd, ptab, change); }
int gtab_mousewheel(HWND hwnd, lpTable ptab, DWORD fwKeys, int zDelta) { static ULONG uScrollLines = 0; if (fwKeys & MK_MBUTTON) { return 1; } if (uScrollLines == 0) { SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uScrollLines, FALSE); if (uScrollLines == 0) { uScrollLines = 3; } } zDelta /= -WHEEL_DELTA; if (fwKeys & MK_CONTROL) { // // Left-Right scroll // if (ptab->hdr.selectmode & TM_ROW) { if (fwKeys & MK_SHIFT) { zDelta = (zDelta > 0) ? ptab->rowwidth : -ptab->rowwidth; } gtab_dohscroll(hwnd, ptab, ptab->avewidth * zDelta); return 0; } return 1; } if (fwKeys & MK_SHIFT) { // // Page scroll // if (ptab->nlines > 3) { zDelta *= ptab->nlines - 3; } } else { if (uScrollLines) { zDelta *= uScrollLines; zDelta = min(zDelta, ptab->nlines - 3); } } gtab_dovscroll(hwnd, ptab, zDelta); return 0; }
/* set sizes that are based on window size and scroll pos * set: * winwidth * nlines * cellpos start, clip start/end * alloc linedata and init */ void gtab_setsize( HWND hwnd, lpTable ptab ) { RECT rc; int nlines; long change; SCROLLINFO si; GetClientRect(hwnd, &rc); ptab->winwidth = rc.right - rc.left; nlines = (rc.bottom - rc.top) / ptab->rowheight; /* nlines is the number of whole lines - add one extra * for the partial line at the bottom */ nlines += 1; /* alloc space for nlines of data - if nlines has changed */ if (nlines != ptab->nlines) { gtab_freelinedata(ptab); ptab->nlines = nlines; if (!gtab_alloclinedata(hwnd, ptab)) { ptab->nlines = 0; return; } } si.cbSize = sizeof(si); si.fMask = SIF_PAGE|SIF_RANGE; si.nMin = 0; /* set scroll vertical range */ si.nMax = ptab->hdr.nrows; si.nPage = ptab->nlines; if (si.nMax < 0) { si.nMax = 0; change = -(ptab->toprow); } else if (ptab->toprow > si.nMax) { change = si.nMax - ptab->toprow; } else { change = 0; } /* the scroll range must be 16-bits for Win3 * scale until this is true */ ptab->scrollscale = 1; while (si.nMax > 32766) { ptab->scrollscale *= 16; si.nMax /= 16; si.nPage /= 16; } if (!si.nPage) si.nPage = 1; SetScrollInfo(hwnd, SB_VERT, &si, TRUE); gtab_dovscroll(hwnd, ptab, change); /* set horz scroll range */ si.nMax = ptab->rowwidth; si.nPage = ptab->winwidth; if (si.nMax < 0) { si.nMax = 0; change = -(ptab->scroll_dx); } else if (ptab->scroll_dx > si.nMax) { change = si.nMax - ptab->scroll_dx; } else { change = 0; } /* horz scroll range will always be < 16 bits */ SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); gtab_dohscroll(hwnd, ptab, change); }
/* handle key-down events - scroll windows and/or move selection */ int gtab_key(HWND hwnd, lpTable ptab, int vkey) { long startrow, ncells, startcell; BOOL bControl = FALSE; BOOL bShift = FALSE; if (GetKeyState(VK_CONTROL) & 0x8000) { bControl = TRUE; } if (GetKeyState(VK_SHIFT) & 0x8000) { /* ignore shift key here if TM_MANY -multiple selection flag- is * not selected */ if (ptab->hdr.selectmode & TM_MANY) { bShift = TRUE; } } switch(vkey) { case VK_UP: if (bControl) { /* control-uparrow scrolls window without selection. * the selection is de-selected (to avoid surprises * moving back to it). */ gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE); gtab_dovscroll(hwnd, ptab, -1); } else { /* uparrow moves selection up one line */ gtab_changesel(hwnd, ptab, -1, 0, FALSE, bShift); } return(0); case VK_DOWN: if (bControl) { /* control downarrow scrolls window without * a selection. */ gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE); gtab_dovscroll(hwnd, ptab, 1); } else { /* the normal gtab_changesel behaviour is * that if the selected line is not visible now, * we scroll it to the top of the window. This is fine * in most cases but causes unacceptable jumps when * repeatedly scrolling down with the down key. * * Thus we now have an argument to changesel to say * that in this case, if you need to move the line onto * the window, move it to the bottom and not the top */ gtab_changesel(hwnd, ptab, 1, 0, TRUE, bShift); } return(0); case VK_LEFT: /* if cell-selection mode, move left one cell. * otherwise the whole row is selected - scroll * the line left a little */ if (ptab->hdr.selectmode & TM_ROW) { if (bControl) { /* ctrl-left moves to start of line */ gtab_dohscroll(hwnd, ptab, -(ptab->scroll_dx)); } else { gtab_dohscroll(hwnd, ptab, -(ptab->avewidth)); } } else { gtab_changesel(hwnd, ptab, 0, -1, FALSE, bShift); } return(0); case VK_RIGHT: /* if cell-selection mode, move right one cell. * otherwise the whole row is selected - scroll * the line right a little */ if (ptab->hdr.selectmode & TM_ROW) { if (bControl) { /* control-right moves to right end of line */ gtab_dohscroll(hwnd, ptab, ptab->rowwidth - ptab->winwidth); } else { gtab_dohscroll(hwnd, ptab, ptab->avewidth); } } else { gtab_changesel(hwnd, ptab, 0, 1, TRUE, bShift); } return(0); case VK_HOME: if (bControl) { /* control-home == top of file */ gtab_dovscroll(hwnd, ptab, -(ptab->toprow)); } /* top of window */ gtab_selhome(hwnd, ptab, bShift); gtab_showsel(hwnd, ptab, FALSE); return(0); case VK_END: if (bControl) { /* control-end -> end of file */ startrow = ptab->hdr.nrows-1; } else { startrow = gtab_linetorow(hwnd, ptab, ptab->nlines - 1); if (startrow >= ptab->hdr.nrows) { startrow = ptab->hdr.nrows-1; } } startcell = 0; ncells = ptab->hdr.ncols; if (!(ptab->hdr.selectmode & TM_ROW)) { startcell = ptab->hdr.ncols-1; ncells = 1; } if (bShift) { gtab_extendsel(hwnd, ptab, startrow, startcell, TRUE); } else { gtab_select(hwnd, ptab, startrow, startcell, 1, ncells, TRUE); } /* we have selected the bottom line. We don't want to * move it up into the window, since the intended * effect is to select the lowest line. This doesn't * apply to the ctrl-end behaviour (move to bottom of * buffer. */ if (bControl) { /* move the selection to make it visible - but move it * to the bottom and not to the top of the window */ gtab_showsel(hwnd, ptab, TRUE); } return(0); case VK_RETURN: if (ptab->select.nrows != 0) { gtab_showsel(hwnd, ptab, FALSE); gtab_enter(hwnd, ptab, ptab->select.startrow, ptab->select.startcell, ptab->select.nrows, ptab->select.ncells); } return(0); case VK_SPACE: /* toggle the selection */ if (ptab->select.nrows == 0) { /* no selection - make one */ gtab_changesel(hwnd, ptab, 0, 0, TRUE, FALSE); } else { /* there is a selection - deselect it */ gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE); } return(0); case VK_PRIOR: /* page up */ if (ptab->nlines > 3) { gtab_dovscroll(hwnd, ptab, -(ptab->nlines - 3)); } gtab_selhome(hwnd, ptab, bShift); return(0); case VK_NEXT: /* page down */ /* scroll down one page */ if (ptab->nlines > 3) { gtab_dovscroll(hwnd, ptab, (ptab->nlines - 3)); } /* select new bottom line */ startrow = gtab_linetorow(hwnd, ptab, ptab->nlines - 1); if (startrow >= ptab->hdr.nrows) { startrow = ptab->hdr.nrows-1; } startcell = 0; ncells = ptab->hdr.ncols; if (!(ptab->hdr.selectmode & TM_ROW)) { startcell = ptab->hdr.ncols-1; ncells = 1; } /* select bottom line, but don't call showsel * since we don't want to adjust it's position - we * want it to remain at the bottom of the window */ if (bShift) { gtab_extendsel(hwnd, ptab, startrow, startcell, TRUE); } else { gtab_select(hwnd, ptab, startrow, startcell, 1, ncells, TRUE); } return(0); default: return(1); } }