TABLE.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:31k
源码类别:
Windows编程
开发平台:
Visual C++
- /******************************************************************************
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1993-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- ******************************************************************************/
- /****************************** Module Header *******************************
- * Module Name: TABLE.C
- *
- * Standard table class and main interface functions.
- *
- * Functions:
- *
- * gtab_init()
- * gtab_deltools()
- * gtab_sendtq()
- * gtab_freelinedata()
- * gtab_wndproc()
- * gtab_createtools()
- * gtab_deltable()
- * gtab_buildtable()
- * gtab_setsize()
- * gtab_newsize()
- * gtab_calcwidths()
- * gtab_alloclinedata()
- * gtab_invallines()
- * gtab_append()
- *
- * Comments:
- *
- * The table class communicates with its 'owner' window to
- * get the layout info and the data to display. The owner window handle
- * can be sent as the lParam in CreateWindow - if not, the parent window will
- * be used.
- *
- * After creating the window, send it a TM_NEWID message, with a 'data id'
- * as the lParam. This is any non-zero 32-bit value. The table will then call
- * back to its owner window to find out how many rows/columns, then to fetch
- * the name/properties of each column, and finally to get the data to display.
- *
- * Send TM_NEWID of 0 to close (or destroy the window) - wait for TQ_CLOSE
- * (in either case) before discarding data. Send
- * TM_REFRESH if data or row-count changes; send TM_NEWLAYOUT if column
- * properties or nr cols change etc - this is the same as sending TM_NEWID
- * except that no TQ_CLOSE happens on TM_NEWLAYOUT.
- *
- * TQ_SELECT is sent whenever the current selection changes. TQ_ENTER is sent
- * when enter or double-click occurs.
- *
- ****************************************************************************/
- #include <windows.h>
- #include <commdlg.h>
- #include "gutils.h"
- #include "table.h"
- #include "tpriv.h"
- /* global tools etc */
- extern HANDLE hLibInst;
- HANDLE hVertCurs;
- HANDLE hNormCurs;
- HPEN hpenDotted;
- UINT gtab_msgcode;
- /* function prototypes */
- long FAR PASCAL gtab_wndproc(HWND, UINT, UINT, long);
- void gtab_createtools(void);
- void gtab_deltable(HWND hwnd, lpTable ptab);
- lpTable gtab_buildtable(HWND hwnd, DWORD id);
- void gtab_setsize(HWND hwnd, lpTable ptab);
- void gtab_newsize(HWND hwnd, lpTable ptab);
- void gtab_calcwidths(HWND hwnd, lpTable ptab);
- BOOL gtab_alloclinedata(HWND hwnd, HANDLE heap, lpTable ptab);
- void gtab_invallines(HWND hwnd, lpTable ptab, int start, int count);
- void gtab_append(HWND hwnd, lpTable ptab, int rows, DWORD id);
- /***************************************************************************
- * Function: gtab_init
- *
- * Purpose:
- *
- * Initialise window class - called from DLL main init
- */
- void
- gtab_init(void)
- {
- WNDCLASS wc;
- gtab_createtools();
- gtab_msgcode = RegisterWindowMessage(TableMessage);
- wc.style = CS_GLOBALCLASS | CS_DBLCLKS;
- wc.lpfnWndProc = gtab_wndproc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = WLTOTAL;
- wc.hInstance = hLibInst;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszClassName = TableClassName;
- wc.lpszMenuName = NULL;
- RegisterClass(&wc);
- }
- /***************************************************************************
- * Function: gtab_createtools
- *
- * Purpose:
- *
- * Load cursors and pens.
- */
- void
- gtab_createtools(void)
- {
- hVertCurs = LoadCursor(hLibInst, "VertLine");
- hNormCurs = LoadCursor(NULL, IDC_ARROW);
- hpenDotted = CreatePen(PS_DOT, 1, RGB(0, 0, 0));
- }
- /***************************************************************************
- * Function: gtab_deltools
- *
- * Purpose:
- *
- * Delete pen
- */
- void
- gtab_deltools(void)
- {
- DeleteObject(hpenDotted);
- }
- /***************************************************************************
- * Function: gtab_wndproc
- *
- * Purpose:
- *
- * Window procedure for table
- */
- long FAR PASCAL
- gtab_wndproc(HWND hwnd, UINT msg, UINT wParam, long lParam)
- {
- CREATESTRUCT FAR * csp;
- HWND hOwner;
- lpTable ptab;
- HANDLE hHeap;
- PAINTSTRUCT ps;
- int y, y2, i;
- HDC hDC;
- lpTableSelection pselect;
- long oldtop;
- long change;
- switch(msg) {
- case WM_CREATE:
- /* create window. set the wnd extra bytes to
- * contain the owner window, a heap 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) (long) csp->lpCreateParams;
- }
- ptab = NULL;
- hHeap = gmem_init();
- SetWindowLong(hwnd, WL_TABLE, (LONG) ptab);
- SetWindowLong(hwnd, WW_OWNER, (LONG) hOwner);
- SetWindowLong(hwnd, WW_HEAP, (LONG) hHeap);
- 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) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_sendtq(hwnd, TQ_CLOSE, ptab->hdr.id);
- gtab_deltable(hwnd, ptab);
- SetCursor(hNormCurs);
- SetWindowLong(hwnd, WL_TABLE, 0);
- }
- if ( (ptab = gtab_buildtable(hwnd, lParam)) != NULL) {
- SetWindowLong(hwnd, WL_TABLE, (long) (LPSTR) 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) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_deltable(hwnd, ptab);
- SetCursor(hNormCurs);
- SetWindowLong(hwnd, WL_TABLE, 0);
- }
- if ( (ptab = gtab_buildtable(hwnd, lParam)) != NULL) {
- SetWindowLong(hwnd, WL_TABLE, (long) (LPSTR) 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) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_newsize(hwnd, ptab);
- }
- InvalidateRect(hwnd, NULL, TRUE);
- break;
- case TM_SELECT:
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- pselect = (lpTableSelection) lParam;
- /*
- * we only support TM_SINGLE - so force the
- * selection to a single row or cell.
- */
- gtab_select(hwnd, ptab, pselect->startrow,
- pselect->startcell,
- 1,
- (ptab->hdr.selectmode & TM_ROW) ?
- ptab->hdr.ncols : 1,
- TRUE);
- gtab_showsel_middle(hwnd, ptab);
- }
- break;
- case TM_PRINT:
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- hHeap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
- if (ptab != NULL) {
- gtab_print(hwnd, ptab, hHeap, (lpPrintContext) lParam);
- return(TRUE);
- }
- case TM_TOPROW:
- /* return top row. if wParam is TRUE, set lParam
- * as the new toprow
- */
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab == NULL) {
- return(0);
- }
- oldtop = ptab->toprow;
- if ((wParam) && (lParam < ptab->hdr.nrows)) {
- change = 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) GetWindowLong(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 no
- * been change. Update without forcing redraw of
- * everything.
- * lParam contains the new total nr of rows
- */
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_append(hwnd, ptab, wParam, lParam);
- return(TRUE);
- }
- break;
- case WM_SIZE:
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_setsize(hwnd, ptab);
- }
- break;
- case WM_DESTROY:
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_sendtq(hwnd, TQ_CLOSE, ptab->hdr.id);
- gtab_deltable(hwnd, ptab);
- }
- hHeap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
- gmem_freeall(hHeap);
- break;
- case WM_PAINT:
- hDC = BeginPaint(hwnd, &ps);
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- /* separator lines between fixed rows/columns
- * (ie headers) and the rest - if enabled
- */
- /* paint here first for good impression,
- * and again after to clean up!!
- */
- if (ptab->hdr.vseparator) {
- gtab_vsep(hwnd, ptab, hDC);
- }
- if (ptab->hdr.hseparator) {
- gtab_hsep(hwnd, ptab, hDC);
- }
- /* paint only the rows that need painting */
- for (i = 0; i < ptab->nlines; i++) {
- y = ptab->pdata[i].linepos.start;
- y2 = y + ptab->pdata[i].linepos.size;
- if ( (y <= ps.rcPaint.bottom) &&
- (y2 >= ps.rcPaint.top)) {
- gtab_paint(hwnd, hDC, ptab, i);
- }
- }
- if (ptab->hdr.vseparator) {
- gtab_vsep(hwnd, ptab, hDC);
- }
- if (ptab->hdr.hseparator) {
- gtab_hsep(hwnd, ptab, hDC);
- }
- if (ptab->selvisible) {
- gtab_invertsel(hwnd, ptab, hDC);
- }
- }
- EndPaint(hwnd, &ps);
- break;
- case WM_HSCROLL:
- ptab = (lpTable) GetWindowLong(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) GetWindowLong(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) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_move(hwnd, ptab, LOWORD(lParam), HIWORD(lParam));
- } else {
- SetCursor(hNormCurs);
- }
- break;
- case WM_LBUTTONDOWN:
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_press(hwnd, ptab, LOWORD(lParam), HIWORD(lParam));
- }
- break;
- case WM_LBUTTONUP:
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_release(hwnd, ptab,
- LOWORD(lParam), HIWORD(lParam));
- }
- break;
- case WM_LBUTTONDBLCLK:
- ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- gtab_dblclick(hwnd, ptab,
- LOWORD(lParam), 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) GetWindowLong(hwnd, WL_TABLE);
- if (ptab != NULL) {
- if (gtab_key(hwnd, ptab, wParam) != 0) {
- /* pass key to owner since
- * we don't know what to do with it
- */
- hOwner = (HANDLE) GetWindowLong(hwnd, WW_OWNER);
- return(SendMessage(hOwner, WM_KEYDOWN,
- wParam, lParam));
- } else {
- return(0);
- }
- }
- break;
- default:
- return(DefWindowProc(hwnd, msg, wParam, lParam));
- }
- return(TRUE);
- }
- /***************************************************************************
- * Function: gtab_sendtq
- *
- * Purpose:
- *
- * Send a table-query message to the owner window. Returns message
- * value.
- */
- long
- gtab_sendtq(HWND hwnd, UINT cmd, long lParam)
- {
- HWND hOwner;
- hOwner = (HANDLE) GetWindowLong(hwnd, WW_OWNER);
- return (SendMessage(hOwner, gtab_msgcode, cmd, lParam));
- }
- /***************************************************************************
- * Function: gtab_freelinedata
- *
- * Purpose:
- *
- * Free the memory allocated for the array of lines (each containing
- * an array of Cells, each containing an array of chars for the actual
- * data). Called on any occasion that would change the number of visible lines
- */
- void
- gtab_freelinedata(HANDLE hHeap, lpTable ptab)
- {
- int i, j, ncols;
- lpCellData cd;
- ncols = ptab->hdr.ncols;
- /* for each line */
- for(i = 0; i < ptab->nlines; i++) {
- /* for each cell */
- for (j = 0; j < ncols; j++) {
- /* free up the actual text space */
- cd = &ptab->pdata[i].pdata[j];
- gmem_free(hHeap, (LPSTR) cd->ptext, cd->nchars);
- }
- /* dealloc array of CellData */
- gmem_free(hHeap, (LPSTR) ptab->pdata[i].pdata,
- sizeof(CellData) * ncols);
- }
- /* de-alloc array of linedatas */
- gmem_free(hHeap, (LPSTR) ptab->pdata,
- sizeof(LineData) * ptab->nlines);
- ptab->pdata = NULL;
- }
- /***************************************************************************
- * Function: gtab_alloclinedata
- *
- * Purpose:
- *
- * Allocate and init array of linedatas (include cell array
- * and text for each cell)
- */
- BOOL
- gtab_alloclinedata(HWND hwnd, HANDLE heap, lpTable ptab)
- {
- lpLineData pline;
- lpCellData cd;
- int i, j;
- ptab->pdata = (lpLineData) gmem_get(heap,
- sizeof(LineData) * ptab->nlines);
- if (ptab->pdata == NULL) {
- return(FALSE);
- }
- for (i = 0; i < ptab->nlines; i++) {
- pline = &ptab->pdata[i];
- pline->linepos.size = ptab->rowheight;
- pline->pdata = (lpCellData) gmem_get(heap,
- sizeof(CellData) * ptab->hdr.ncols);
- if (pline->pdata == NULL) {
- return(FALSE);
- }
- for (j = 0; j < ptab->hdr.ncols; j++) {
- cd = &pline->pdata[j];
- cd->props.valid = 0;
- cd->flags = 0;
- cd->nchars = ptab->pcolhdr[j].nchars;
- if (cd->nchars > 0) {
- cd->ptext = gmem_get(heap, cd->nchars);
- if (cd->ptext == NULL) {
- return(FALSE);
- }
- }
- }
- }
- }
- /***************************************************************************
- * Function: gtab_deltable
- *
- * Purpose:
- *
- * Free up all table data structures. Called for new layout or new data.
- */
- void
- gtab_deltable(HWND hwnd, lpTable ptab)
- {
- HANDLE hHeap;
- int ncols;
- if (ptab == NULL) {
- return;
- }
- hHeap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
- ncols = ptab->hdr.ncols;
- if (ptab->pcolhdr != NULL) {
- gmem_free(hHeap, (LPSTR) ptab->pcolhdr,
- sizeof(ColProps) * ncols);
- }
- if (ptab->pcellpos != NULL) {
- gmem_free(hHeap, (LPSTR) ptab->pcellpos,
- sizeof(CellPos) * ncols);
- }
- if (ptab->pdata != NULL) {
- gtab_freelinedata(hHeap, ptab);
- }
- gmem_free(hHeap, (LPSTR) ptab, sizeof(Table));
- }
- /***************************************************************************
- * Function: gtab_buildtable
- *
- * Purpose:
- *
- * 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 id)
- {
- lpTable ptab;
- HANDLE hHeap;
- int ncols, i;
- ColPropsList cplist;
- hHeap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
- ptab = (lpTable) gmem_get(hHeap, sizeof(Table));
- if (ptab == NULL) {
- return(NULL);
- }
- /* 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, (long) (LPSTR)&ptab->hdr) == FALSE) {
- return(NULL);
- }
- ncols = ptab->hdr.ncols;
- ptab->pcolhdr = (lpColProps) gmem_get(hHeap, 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, (long) (LPSTR)&cplist);
- /* init remaining fields */
- ptab->pcellpos = (lpCellPos) gmem_get(hHeap, 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);
- }
- /***************************************************************************
- * Function: gtab_setsize
- *
- * Purpose:
- *
- * 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;
- HANDLE heap;
- long range, change;
- 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) {
- heap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
- gtab_freelinedata(heap, ptab);
- ptab->nlines = nlines;
- if (!gtab_alloclinedata(hwnd, heap, ptab)) {
- ptab->nlines = 0;
- return;
- }
- }
- /* set scroll vertical range */
- range = ptab->hdr.nrows - (ptab->nlines - 1);
- if (range < 0) {
- range = 0;
- change = -(ptab->toprow);
- } else if (ptab->toprow > range) {
- change = range - ptab->toprow;
- } else {
- change = 0;
- }
- /* the scroll range must be 16-bits for Win3
- * scale until this is true
- */
- ptab->scrollscale = 1;
- while (range > 32766) {
- ptab->scrollscale *= 16;
- range /= 16;
- }
- SetScrollRange(hwnd, SB_VERT, 0, (int) range, TRUE);
- gtab_dovscroll(hwnd, ptab, change);
- /* set horz scroll range */
- range = ptab->rowwidth - ptab->winwidth;
- if (range < 0) {
- range = 0;
- change = -(ptab->scroll_dx);
- } else if (ptab->scroll_dx > range) {
- change = range - ptab->scroll_dx;
- } else {
- change = 0;
- }
- /* horz scroll range will always be < 16 bits */
- SetScrollRange(hwnd, SB_HORZ, 0, (int) range, TRUE);
- gtab_dohscroll(hwnd, ptab, change);
- }
- /***************************************************************************
- * Function: gtab_calcwidths
- *
- * Purpose:
- *
- * Set column widths/height and totals (based on column props)
- * - no assumption of window size (see gtab_setsize)
- * sets avewidth,rowheight,cellpos.size,rowwidth (total of cellpos.size)
- */
- void
- gtab_calcwidths(HWND hwnd, lpTable ptab)
- {
- int i, cxtotal, cx, ave;
- TEXTMETRIC tm, tmcol;
- HDC hdc;
- lpProps hdrprops, cellprops;
- HFONT hfont;
- hdrprops = &ptab->hdr.props;
- hdc = GetDC(hwnd);
- if (hdrprops->valid & P_FONT) {
- hfont = SelectObject(hdc, hdrprops->hFont);
- }
- GetTextMetrics(hdc, &tm);
- if (hdrprops->valid & P_FONT) {
- SelectObject(hdc, hfont);
- }
- ReleaseDC(hwnd, hdc);
- /* get width and height of average character */
- ptab->avewidth = tm.tmAveCharWidth;
- ptab->rowheight = tm.tmHeight + tm.tmExternalLeading;
- if (hdrprops->valid & P_HEIGHT) {
- ptab->rowheight = hdrprops->height;
- }
- /* set pixel width of each cell (and add up for row total)
- * based on ave width * nr chars, unless P_WIDTH set
- */
- cxtotal = 0;
- for (i = 0; i < ptab->hdr.ncols; i++) {
- cellprops = &ptab->pcolhdr[i].props;
- if (cellprops->valid & P_WIDTH) {
- cx = cellprops->width;
- } else if (hdrprops->valid & P_WIDTH) {
- cx = hdrprops->width;
- } else {
- if (cellprops->valid & P_FONT) {
- hdc = GetDC(hwnd);
- hfont = SelectObject(hdc, cellprops->hFont);
- GetTextMetrics(hdc, &tmcol);
- SelectObject(hdc, hfont);
- ReleaseDC(hwnd, hdc);
- ave = tmcol.tmAveCharWidth;
- } else {
- ave = ptab->avewidth;
- }
- /* ave width * nchars */
- cx = ptab->pcolhdr[i].nchars + 1;
- cx *= ave;
- }
- /* add 2 pixels for box lines */
- cx += 2;
- ptab->pcellpos[i].size = cx;
- cxtotal += cx;
- }
- ptab->rowwidth = cxtotal;
- }
- /***************************************************************************
- * Function: gtab_newsize
- *
- * Purpose:
- *
- * 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, (long) (LPSTR) &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, TRUE);
- }
- void
- gtab_invallines(HWND hwnd, lpTable ptab, int start, int count)
- {
- int i, j;
- for (i = start; i < start + count; i++) {
- for (j = 0; j < ptab->hdr.ncols; j++) {
- ptab->pdata[i].pdata[j].flags = 0;
- }
- }
- }
- /***************************************************************************
- * Function: gtab_append
- *
- * Purpose:
- *
- * 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 id)
- {
- long range;
- long oldrows;
- int line, nupdates;
- RECT rc;
- /* 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. this is
- * illegal at this point and should be ignored
- */
- if (oldrows >= rows) {
- return;
- }
- ptab->hdr.nrows = rows;
- /* set the vertical scroll range */
- range = rows - (ptab->nlines - 1);
- if (range < 0) {
- range = 0;
- }
- /* force the scroll range into 16-bits for win 3.1 */
- ptab->scrollscale = 1;
- while (range > 32766) {
- ptab->scrollscale *= 16;
- range /= 16;
- }
- /* now set the scroll bar range and position */
- SetScrollRange(hwnd, SB_VERT, 0, (int) range, TRUE);
- if (range > 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, TRUE);
- }