/* called when row data + possible nrows changes. * other changes are ignored */ void gtab_newsize( HWND hwnd, lpTable ptab ) { TableHdr hdr; /* get new row count */ hdr = ptab->hdr; gtab_sendtq(hwnd, TQ_GETSIZE, (LPARAM) &hdr); if (hdr.nrows != ptab->hdr.nrows) { ptab->hdr.nrows = hdr.nrows; gtab_setsize(hwnd, ptab); } gtab_invallines(hwnd, ptab, 0, ptab->nlines); InvalidateRect(hwnd, NULL, FALSE); }
/* new rows have been added to the table. adjust the scroll range and * position, and redraw the rows if the end of the table is currently * visible. * rows = the new total row count. */ void gtab_append( HWND hwnd, lpTable ptab, int rows, DWORD_PTR id ) { long oldrows; int line, nupdates; RECT rc; SCROLLINFO si; /* change to the new id */ ptab->hdr.id = id; ptab->select.id = id; /* update the header, but remember the old nr of rows * so we know where to start updating */ oldrows = ptab->hdr.nrows; /* check that the new nr of rows is not smaller. */ if (oldrows >= rows) { return; } ptab->hdr.nrows = rows; si.cbSize = sizeof(si); si.fMask = SIF_PAGE|SIF_RANGE; si.nMin = 0; /* set the vertical scroll range */ si.nMax = rows; si.nPage = ptab->nlines; if (si.nMax < 0) { si.nMax = 0; } /* force the scroll range into 16-bits for win 3.1 */ ptab->scrollscale = 1; while (si.nMax > 32766) { ptab->scrollscale *= 16; si.nMax /= 16; si.nPage /= 16; } if (!si.nPage) si.nPage = 1; /* now set the scroll bar range and position */ SetScrollInfo(hwnd, SB_VERT, &si, TRUE); if (si.nMax > 0) { SetScrollPos(hwnd, SB_VERT, (int) (ptab->toprow / ptab->scrollscale), TRUE); } /* calculate which screen lines need to be updated - find what * screen line the start of the new section is at */ line = gtab_rowtoline(hwnd, ptab, oldrows); if (line == -1) { /* not visible -> no more to do */ return; } /* how many lines to update - rest of screen or nr of * new lines if less than rest of screen */ nupdates = min((ptab->nlines - line), (int)(rows - oldrows)); /* invalidate the screen line buffers to indicate data * needs to be refetch from parent window */ gtab_invallines(hwnd, ptab, line, nupdates); /* calculate the region of the screen to be repainted - * left and right are same as window. top and bottom * need to be calculated from screen line height */ GetClientRect(hwnd, &rc); rc.top += line * ptab->rowheight; rc.bottom = rc.top + (nupdates * ptab->rowheight); /* force a repaint of the updated region */ InvalidateRect(hwnd, &rc, FALSE); }
/* * set new vertical scroll pos, * adjust linedata array * set line win-relative start posns & clip top/bottom posns * revise display. */ void gtab_dovscroll(HWND hwnd, lpTable ptab, long change) { int cury, i; long ncopy; lpCellPos cp; LineData ldtemp; RECT rc, rcpaint; long range; long newtop; int newpos; BOOL fWasVisible = FALSE; if (ptab->selvisible) { fWasVisible = TRUE; ptab->selvisible = FALSE; gtab_invertsel(hwnd, ptab, NULL); } range = ptab->hdr.nrows - (ptab->nlines - 1); newtop = ptab->toprow + change; if (range < 0) { range = 0; } if (newtop > range) { change = range - ptab->toprow; } else if (newtop < 0) { change = -(ptab->toprow); } ptab->toprow += change; newpos = (int) (newtop / ptab->scrollscale); SetScrollPos(hwnd, SB_VERT, newpos, TRUE); if (ptab->hdr.sendscroll) { gtab_sendtq(hwnd, TQ_SCROLL, ptab->toprow); } /* adjust data ptrs rather than invalidate, to retain the * data we know is still valid */ if (abs(change) >= ptab->nlines) { gtab_invallines(hwnd, ptab, ptab->hdr.fixedrows, ptab->nlines - ptab->hdr.fixedrows); InvalidateRect(hwnd, NULL, FALSE); change = 0; } else if (change < 0) { /* copy data down */ ncopy = (ptab->nlines - ptab->hdr.fixedrows) - abs(change); for (i = ptab->nlines - 1; i >= (ptab->hdr.fixedrows + abs(change)); i--) { ldtemp = ptab->pdata[i - abs(change)]; ptab->pdata[i - abs(change)] = ptab->pdata[i]; ptab->pdata[i] = ldtemp; } gtab_invallines(hwnd, ptab, ptab->hdr.fixedrows, (int) abs(change)); } else if (change > 0) { ncopy = (ptab->nlines - ptab->hdr.fixedrows) - change; for (i = ptab->hdr.fixedrows; i < (ncopy + ptab->hdr.fixedrows); i++) { ldtemp = ptab->pdata[i + change]; ptab->pdata[i + change] = ptab->pdata[i]; ptab->pdata[i] = ldtemp; } gtab_invallines(hwnd, ptab, (int) ncopy + ptab->hdr.fixedrows, (int) change); } /* scroll window */ GetClientRect(hwnd, &rc); rcpaint = rc; if (change > 0) { rc.top += (int) (change + ptab->hdr.fixedrows) * ptab->rowheight; rcpaint.top = (ptab->hdr.fixedrows * ptab->rowheight); rcpaint.top += rc.bottom - rc.top; } else if (change < 0) { rc.top += (ptab->hdr.fixedrows * ptab->rowheight); rc.bottom += (int) (change * ptab->rowheight); rcpaint.bottom -= rc.bottom - rc.top; } /* loop through each line setting relative posn and clipping */ /* set up all rows - the fixed/moveable difference for * rows is made at fetch-time during painting, when we remember * which absolute row nr to ask for, for a given screen line */ cury = 0; for (i = 0; i < ptab->nlines; i++) { cp = &ptab->pdata[i].linepos; cp->start = cury; cp->clipstart = cury; cp->clipend = cury + cp->size; cury += cp->size; } /* now move and repaint the window */ if (change != 0) { if (rc.top < rc.bottom) { ScrollWindow(hwnd, 0, (int) -(change * ptab->rowheight), &rc, NULL); } // don't repaint the fixed rows rc.top = 0; rc.bottom = ptab->hdr.fixedrows * ptab->rowheight; ValidateRect(hwnd, &rc); /* force repaint now, not just post message for later, * since we want to repaint that line before the next * scroll down occurs */ ValidateRect(hwnd, &rcpaint); RedrawWindow(hwnd, &rcpaint, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_INTERNALPAINT); } if (fWasVisible) { gtab_invertsel(hwnd, ptab, NULL); ptab->selvisible = TRUE; } }