Exemplo n.º 1
0
/*
 * set selection and send 'TQ_ENTER' event to owner
 */
void
gtab_enter(HWND hwnd, lpTable ptab, long row, long col, long nrows,
        long ncells)
{
    /* clear existing sel if valid and visible */
    if ((ptab->select.nrows != 0) && (ptab->selvisible == TRUE)) {

        /* only clear sel if it is different from the new one */
        if ((ptab->select.startrow != row) ||
                (ptab->select.startcell != col) ||
                (ptab->select.nrows != nrows) ||
                (ptab->select.ncells != ncells)) {
            gtab_invertsel(hwnd, ptab, NULL);
            ptab->selvisible = FALSE;
        }
    }

    /* set select fields and send TQ_ENTER */
    if (row < ptab->hdr.nrows) {
        ptab->select.startrow = row;
        ptab->select.startcell = col;
        ptab->select.nrows = nrows;
        ptab->select.ncells = ncells;
    } else {
        ptab->select.nrows = 0;
        ptab->select.startrow = 0;
        ptab->select.startcell = 0;
        ptab->select.ncells = 0;
    }

    /* paint in selection */
    if (nrows != 0) {
        if (!ptab->selvisible) {
            gtab_invertsel(hwnd, ptab, NULL);
            ptab->selvisible = TRUE;
        }
        /* do this at end because it could cause a layout-change */
        gtab_sendtq(hwnd, TQ_ENTER, (LPARAM) &ptab->select);
    } else {
        if (ptab->selvisible) {
            gtab_invertsel(hwnd, ptab, NULL);
        }
        ptab->selvisible = FALSE;
    }
}
Exemplo n.º 2
0
/* 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);
}
Exemplo n.º 3
0
/*
 * update a contiguous block of invalid cells by calling the owner window
 */
void
gtab_updatecontig(HWND hwnd, lpTable ptab, int line, int cell1, int count)
{
	lpLineData pline;
	lpCellData cd;
	CellDataList list;
	lpProps colprops;
	int i;

	pline = &ptab->pdata[line];
	cd = &pline->pdata[cell1];

	list.id = ptab->hdr.id;
	list.row = gtab_linetorow(hwnd, ptab, line);
	list.startcell = cell1;
	list.ncells = count;
	list.plist = cd;

	/* clear out prop flags */
	for (i = 0; i < count; i++) {
		cd[i].props.valid = 0;
		if (cd[i].nchars > 0) {
			cd[i].ptext[0] = '\0';
		}
	}

	if (list.row < ptab->hdr.nrows) {
		gtab_sendtq(hwnd, TQ_GETDATA, (long) (LPSTR) &list);
	}

	/* for each cell, mark valid and set properties */
	for (i = 0; i < count; i++) {
		cd[i].flags |= CELL_VALID;
		gtab_delcr(cd[i].ptext);
		/* fetch properties from hdr and colhdr */
		colprops = &ptab->pcolhdr[i + cell1].props;
		if (!(cd[i].props.valid & P_FCOLOUR)) {
			if (colprops->valid & P_FCOLOUR) {
				cd[i].props.valid |= P_FCOLOUR;
				cd[i].props.forecolour = colprops->forecolour;
			} else if (ptab->hdr.props.valid & P_FCOLOUR) {
				cd[i].props.valid |= P_FCOLOUR;
				cd[i].props.forecolour =
					ptab->hdr.props.forecolour;
			}
		}

		if (!(cd[i].props.valid & P_BCOLOUR)) {
			if (colprops->valid & P_BCOLOUR) {
				cd[i].props.valid |= P_BCOLOUR;
				cd[i].props.backcolour = colprops->backcolour;
			} else if (ptab->hdr.props.valid & P_BCOLOUR) {
				cd[i].props.valid |= P_BCOLOUR;
				cd[i].props.backcolour =
					ptab->hdr.props.backcolour;
			}
		}

		if (!(cd[i].props.valid & P_FONT)) {
			if (colprops->valid & P_FONT) {
				cd[i].props.valid |= P_FONT;
				cd[i].props.hFont = colprops->hFont;
			} else if (ptab->hdr.props.valid & P_FONT) {
				cd[i].props.valid |= P_FONT;
				cd[i].props.hFont = ptab->hdr.props.hFont;
			}
		}

		if (!(cd[i].props.valid & P_ALIGN)) {
			if (colprops->valid & P_ALIGN) {
				cd[i].props.valid |= P_ALIGN;
				cd[i].props.alignment = colprops->alignment;
			} else if (ptab->hdr.props.valid & P_ALIGN) {
				cd[i].props.valid |= P_ALIGN;
				cd[i].props.alignment =
					ptab->hdr.props.alignment;
			}
		}

		if (!(cd[i].props.valid & P_BOX)) {
			if (colprops->valid & P_BOX) {
				cd[i].props.valid |= P_BOX;
				cd[i].props.box = colprops->box;
			} else if (ptab->hdr.props.valid & P_BOX) {
				cd[i].props.valid |= P_BOX;
				cd[i].props.box = ptab->hdr.props.box;
			}
		}
		/* you can't set width/height per cell - this
		 * is ignored at cell level.
		 */
	}

}
Exemplo n.º 4
0
LRESULT
gtab_wndproc(
            HWND hwnd,
            UINT msg,
            WPARAM wParam,
            LPARAM lParam
            )
{
    CREATESTRUCT FAR * csp;
    HWND hOwner;
    lpTable ptab;
    lpTableSelection pselect;
    long oldtop;
    long change;

    switch (msg) {

        case WM_CREATE:
            /* create window. set the wnd extra bytes to
             * contain the owner window and a null table.
             * Owner window is either in lParam or the parent.
             * Then wait for TM_NEWID.
             */
            csp = (CREATESTRUCT FAR *) lParam;
            if (csp->lpCreateParams == NULL) {
                hOwner = GetParent(hwnd);
            } else {
                hOwner = (HWND) csp->lpCreateParams;
            }
            ptab = NULL;

            SetWindowLongPtr(hwnd, WL_TABLE, (LONG_PTR) ptab);
            SetWindowLongPtr(hwnd, WW_OWNER, (LONG_PTR) hOwner);

            SetScrollRange(hwnd, SB_VERT, 0, 0, TRUE);
            SetScrollRange(hwnd, SB_HORZ, 0, 0, TRUE);
            break;

        case TM_NEWID:
            /* complete change of table.
             * close old table, discard memory and
             * build new table
             */
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_sendtq(hwnd, TQ_CLOSE, ptab->hdr.id);
                gtab_deltable(hwnd, ptab);
                SetCursor((HCURSOR)hNormCurs);
                SetWindowLongPtr(hwnd, WL_TABLE, 0);
            }
            if ( (ptab = gtab_buildtable(hwnd, (DWORD_PTR)lParam)) != NULL) {
                SetWindowLongPtr(hwnd, WL_TABLE, (LONG_PTR) ptab);
                gtab_setsize(hwnd, ptab);
            } else {
                SetScrollRange(hwnd, SB_VERT, 0, 0, TRUE);
                SetScrollRange(hwnd, SB_HORZ, 0, 0, TRUE);
            }
            InvalidateRect(hwnd, NULL, TRUE);
            break;

        case TM_NEWLAYOUT:
            /* change of layout but for same id. no TQ_CLOSE,
             * but otherwise same as TM_NEWID
             */
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_deltable(hwnd, ptab);
                SetCursor((HCURSOR)hNormCurs);
                SetWindowLongPtr(hwnd, WL_TABLE, 0);
            }
            if ( (ptab = gtab_buildtable(hwnd, (DWORD_PTR)lParam)) != NULL) {
                SetWindowLongPtr(hwnd, WL_TABLE, (LONG_PTR) ptab);
                gtab_setsize(hwnd, ptab);
            } else {
                SetScrollRange(hwnd, SB_VERT, 0, 0, TRUE);
                SetScrollRange(hwnd, SB_HORZ, 0, 0, TRUE);
            }
            InvalidateRect(hwnd, NULL, TRUE);
            break;

        case TM_REFRESH:
            /* data in table has changed. nrows may have
             * changed. ncols and col types have not changed
             */
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_newsize(hwnd, ptab);
                gtab_sendtq(hwnd, TQ_SHOWWHITESPACE, (LPARAM) &ptab->show_whitespace);
            }
            InvalidateRect(hwnd, NULL, TRUE);
            break;

        case TM_SELECT:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                pselect = (lpTableSelection) lParam;

                gtab_select(hwnd, ptab, pselect->startrow,
                            pselect->startcell,
                            pselect->nrows,
                            pselect->ncells,
                            TRUE);
                gtab_showsel_middle(hwnd, ptab, pselect->dyRowsFromTop);
            }
            break;

        case TM_GETSELECTION:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                pselect = (lpTableSelection) lParam;

                *pselect = ptab->select;
            }
            break;

        case TM_PRINT:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                return gtab_print(hwnd, ptab, (lpPrintContext) lParam);
            }
            return FALSE;

        case TM_SETTABWIDTH:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (!ptab)
                return 0;
            ptab->tabchars = (int)lParam;
            InvalidateRect(hwnd, NULL, FALSE);
            break;

        case TM_TOPROW:

            /* return top row. if wParam is TRUE, set lParam
             * as the new toprow
             */
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab == NULL) {
                return(0);
            }
            oldtop = ptab->toprow;
            if ((wParam) && (lParam < ptab->hdr.nrows)) {
                change = (long)lParam - ptab->toprow;
                change -= ptab->hdr.fixedrows;
                gtab_dovscroll(hwnd, ptab, change);
            }
            return(oldtop);

        case TM_ENDROW:
            /* return the last visible row in the window */
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab == NULL) {
                return(0);
            }
            return(ptab->nlines + ptab->toprow - 1);


        case TM_APPEND:
            /* new rows have been added to the end of the
             * table, but the rest of the table has not
             * been changed. Update without forcing redraw of
             * everything.
             * lParam contains the new total nr of rows
             */
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_append(hwnd, ptab, (int) wParam, (DWORD_PTR)lParam);
                return(TRUE);
            }
            break;

        case WM_SIZE:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_setsize(hwnd, ptab);
            }
            break;

        case WM_ERASEBKGND:
            return TRUE;

        case WM_DESTROY:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_sendtq(hwnd, TQ_CLOSE, ptab->hdr.id);
                gtab_deltable(hwnd, ptab);
            }
            break;

        case WM_SYSCOLORCHANGE:
            InvalidateRect(hwnd, NULL, TRUE);
            break;

        case WM_PAINT:
            gtab_paint(hwnd);
            break;

        case WM_HSCROLL:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_msg_hscroll(hwnd, ptab,
                                 GET_SCROLL_OPCODE(wParam, lParam),
                                 GET_SCROLL_POS(wParam, lParam));
            }
            break;

        case WM_VSCROLL:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_msg_vscroll(hwnd, ptab,
                                 GET_SCROLL_OPCODE(wParam, lParam),
                                 GET_SCROLL_POS(wParam, lParam));
            }
            break;

        case WM_MOUSEMOVE:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_move(hwnd, ptab, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));
            } else {
                SetCursor((HCURSOR)hNormCurs);
            }
            break;

        case WM_LBUTTONDOWN:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_press(hwnd, ptab, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));
            }
            break;

        case WM_RBUTTONDOWN:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_rightclick(hwnd, ptab, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));
            }
            break;

        case WM_LBUTTONUP:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_release(hwnd, ptab,
                             (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));
            }
            break;

        case WM_LBUTTONDBLCLK:
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                gtab_dblclick(hwnd, ptab,
                              (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));
            }
            break;

        case WM_KEYDOWN:
            /* handle key presses for cursor movement about
             * the table, and return/space for selection.
             * Any key we don't handle is passed to the owner window
             * for him to handle.
             * The table window should have the focus
             */
            ptab = (lpTable) GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                if (gtab_key(hwnd, ptab, (int)wParam) != 0) {
                    hOwner = (HWND) GetWindowLongPtr(hwnd, WW_OWNER);
                    return(SendMessage(hOwner, WM_KEYDOWN, wParam, lParam));
                } else {
                    return(0);
                }
            }
            break;

#ifdef WM_MOUSEWHEEL
        case WM_MOUSEWHEEL:
            ptab = (lpTable)GetWindowLongPtr(hwnd, WL_TABLE);
            if (ptab != NULL) {
                if (gtab_mousewheel(hwnd,ptab, LOWORD(wParam), (short)HIWORD(wParam))) {
                    hOwner = (HWND)GetWindowLongPtr(hwnd, WW_OWNER);
                    return SendMessage(hOwner, WM_MOUSEWHEEL, wParam, lParam);
                }
            }
            break;
#endif

        default:
            return(DefWindowProc(hwnd, msg, wParam, lParam));
    }
    return(TRUE);
}
Exemplo n.º 5
0
/*
 * build up a Table struct (excluding data allocation and
 * anything to do with font or window size).
 * return ptr to this or NULL if error
 */
lpTable
gtab_buildtable(
               HWND hwnd,
               DWORD_PTR id
               )
{
    lpTable ptab;
    int ncols, i;
    ColPropsList cplist;

    ptab = (lpTable) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Table));
    if (ptab == NULL) {
        return(NULL);
    }

    // get the tab width. most clients will not support this
    if (gtab_sendtq(hwnd, TQ_TABS, (LPARAM) &ptab->tabchars) == FALSE) {
        ptab->tabchars = TABWIDTH_DEFAULT;
    }

    // get the show whitespace value
    if (gtab_sendtq(hwnd, TQ_SHOWWHITESPACE, (LPARAM) &ptab->show_whitespace) == FALSE) {
        ptab->show_whitespace = FALSE;
    }

    /* get the row/column count from owner window */
    ptab->hdr.id = id;
    ptab->hdr.props.valid = 0;
    ptab->hdr.sendscroll = FALSE;
    if (gtab_sendtq(hwnd, TQ_GETSIZE, (LPARAM) &ptab->hdr) == FALSE) {
        return(NULL);
    }

    ncols = ptab->hdr.ncols;
    ptab->pcolhdr = (lpColProps) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ColProps) * ncols);
    if (ptab->pcolhdr == NULL) {
        /* should prob send TQ_CLOSE at this point */
        return(NULL);
    }

    /* init col properties to default */
    for (i=0; i < ncols; i++) {
        ptab->pcolhdr[i].props.valid = 0;
        ptab->pcolhdr[i].nchars = 0;
    }
    /* get the column props from owner */
    cplist.plist = ptab->pcolhdr;
    cplist.id = id;
    cplist.startcol = 0;
    cplist.ncols = ncols;
    gtab_sendtq(hwnd, TQ_GETCOLPROPS, (LPARAM) &cplist);

    /* init remaining fields */
    ptab->pcellpos = (lpCellPos) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CellPos) * ncols);
    if (ptab->pcellpos == NULL) {
        return(NULL);
    }

    ptab->scrollscale = 1;
    ptab->scroll_dx = 0;
    ptab->toprow = 0;
    ptab->pdata = NULL;
    ptab->nlines = 0;
    ptab->trackmode = TRACK_NONE;

    /* we have to notify owner of the current selection
     * whenever it is changed
     */
    ptab->select.id = id;
    gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE);

    /* calc ave height/width, cell widths and min height.
     * these change only when cell properties / col count changes -
     * ie only on rebuild-header events
     */
    gtab_calcwidths(hwnd, ptab);
    return(ptab);
}
Exemplo n.º 6
0
/*
 * replace old selection with new. Notify owner if bNotify. Change
 * display to reflect new display.
 */
void
gtab_select(
        HWND hwnd,
        lpTable ptab,
        long row,
        long col,
        long nrows,
        long ncells,
        BOOL bNotify)
{

    /* if in ROW mode, force col and ncells to reflect the entire row. */
    if (ptab->hdr.selectmode & TM_ROW) {
        col = 0;
        ncells = ptab->hdr.ncols;
    }

    /* clear existing sel if valid and visible */
    if ((ptab->select.nrows != 0) && (ptab->selvisible == TRUE)) {

        /* only clear sel if it is different from the new one */
        if ((ptab->select.startrow != row) ||
                (ptab->select.startcell != col) ||
                (ptab->select.nrows != nrows) ||
                (ptab->select.ncells != ncells)) {

            gtab_invertsel(hwnd, ptab, NULL);
            ptab->selvisible = FALSE;
        }
    }

    /* set select fields and send TQ_SELECT */
    if (row < ptab->hdr.nrows) {
        ptab->select.startrow = row;
        ptab->select.startcell = col;
        ptab->select.nrows = nrows;
        ptab->select.ncells = ncells;
    } else {
        ptab->select.nrows = 0;
        ptab->select.startrow = 0;
        ptab->select.startcell = 0;
        ptab->select.ncells = 0;
    }

    if (bNotify) {
        gtab_sendtq(hwnd, TQ_SELECT, (LPARAM) &ptab->select);
    }

    /* paint in selection */
    if (nrows != 0) {
        if (!ptab->selvisible) {
            gtab_invertsel(hwnd, ptab, NULL);
            ptab->selvisible = TRUE;
        }
    } else {
        if (ptab->selvisible) {
            gtab_invertsel(hwnd, ptab, NULL);
            ptab->selvisible = FALSE;
        }
        ptab->selvisible = FALSE;
    }
}
Exemplo n.º 7
0
/*
 * 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;
    }
}