Annotation of mstools/samples/sdktools/windiff/table.c, revision 1.1

1.1     ! root        1: 
        !             2: /******************************************************************************\
        !             3: *       This is a part of the Microsoft Source Code Samples. 
        !             4: *       Copyright (C) 1993 Microsoft Corporation.
        !             5: *       All rights reserved. 
        !             6: *       This source code is only intended as a supplement to 
        !             7: *       Microsoft Development Tools and/or WinHelp documentation.
        !             8: *       See these sources for detailed information regarding the 
        !             9: *       Microsoft samples programs.
        !            10: \******************************************************************************/
        !            11: 
        !            12: /****************************** Module Header *******************************
        !            13: * Module Name: TABLE.C
        !            14: *
        !            15: * Standard table class and main interface functions.
        !            16: *
        !            17: * Functions:
        !            18: *
        !            19: * gtab_init()
        !            20: * gtab_deltools()
        !            21: * gtab_sendtq()
        !            22: * gtab_freelinedata()
        !            23: * gtab_wndproc()
        !            24: * gtab_createtools()
        !            25: * gtab_deltable()
        !            26: * gtab_buildtable()
        !            27: * gtab_setsize()
        !            28: * gtab_newsize()
        !            29: * gtab_calcwidths()
        !            30: * gtab_alloclinedata()
        !            31: * gtab_invallines()
        !            32: * gtab_append()
        !            33: *
        !            34: * Comments:
        !            35: *
        !            36: * The table class communicates with its 'owner' window to
        !            37: * get the layout info and the data to display. The owner window handle
        !            38: * can be sent as the lParam in CreateWindow - if not, the parent window will
        !            39: * be used.
        !            40: *
        !            41: * After creating the window, send it a TM_NEWID message, with a 'data id'
        !            42: * as the lParam. This is any non-zero 32-bit value. The table will then call
        !            43: * back to its owner window to find out how many rows/columns, then to fetch
        !            44: * the name/properties of each column, and finally to get the data to display.
        !            45: *
        !            46: * Send TM_NEWID of 0 to close (or destroy the window) - wait for TQ_CLOSE
        !            47: * (in either case) before discarding data. Send
        !            48: * TM_REFRESH if data or row-count changes; send TM_NEWLAYOUT if column
        !            49: * properties or nr cols change etc - this is the same as sending TM_NEWID
        !            50: * except that no TQ_CLOSE happens on TM_NEWLAYOUT.
        !            51: *
        !            52: * TQ_SELECT is sent whenever the current selection changes. TQ_ENTER is sent
        !            53: * when enter or double-click occurs.
        !            54: *
        !            55: ****************************************************************************/
        !            56: 
        !            57: #include <windows.h>
        !            58: #include <commdlg.h>
        !            59: 
        !            60: #include "gutils.h"
        !            61: #include "table.h"
        !            62: #include "tpriv.h"
        !            63: 
        !            64: /* global tools etc */
        !            65: extern HANDLE hLibInst;
        !            66: HANDLE hVertCurs;
        !            67: HANDLE hNormCurs;
        !            68: HPEN hpenDotted;
        !            69: UINT gtab_msgcode;
        !            70: 
        !            71: /* function prototypes */
        !            72: long FAR PASCAL gtab_wndproc(HWND, UINT, UINT, long);
        !            73: void gtab_createtools(void);
        !            74: void gtab_deltable(HWND hwnd, lpTable ptab);
        !            75: lpTable gtab_buildtable(HWND hwnd, DWORD id);
        !            76: void gtab_setsize(HWND hwnd, lpTable ptab);
        !            77: void gtab_newsize(HWND hwnd, lpTable ptab);
        !            78: void gtab_calcwidths(HWND hwnd, lpTable ptab);
        !            79: BOOL gtab_alloclinedata(HWND hwnd, HANDLE heap, lpTable ptab);
        !            80: void gtab_invallines(HWND hwnd, lpTable ptab, int start, int count);
        !            81: void gtab_append(HWND hwnd, lpTable ptab, int rows, DWORD id);
        !            82: 
        !            83: /***************************************************************************
        !            84:  * Function: gtab_init
        !            85:  *
        !            86:  * Purpose:
        !            87:  *
        !            88:  * Initialise window class - called from DLL main init
        !            89:  */
        !            90: void
        !            91: gtab_init(void)
        !            92: {
        !            93:         WNDCLASS wc;
        !            94: 
        !            95:         gtab_createtools();
        !            96:         gtab_msgcode = RegisterWindowMessage(TableMessage);
        !            97: 
        !            98:         wc.style = CS_GLOBALCLASS | CS_DBLCLKS;
        !            99:         wc.lpfnWndProc = gtab_wndproc;
        !           100:         wc.cbClsExtra = 0;
        !           101:         wc.cbWndExtra = WLTOTAL;
        !           102:         wc.hInstance = hLibInst;
        !           103:         wc.hIcon = NULL;
        !           104:         wc.hCursor = NULL;
        !           105:         wc.hbrBackground = GetStockObject(WHITE_BRUSH);
        !           106:         wc.lpszClassName = TableClassName;
        !           107:         wc.lpszMenuName = NULL;
        !           108: 
        !           109:         RegisterClass(&wc);
        !           110: }
        !           111: 
        !           112: /***************************************************************************
        !           113:  * Function: gtab_createtools
        !           114:  *
        !           115:  * Purpose:
        !           116:  *
        !           117:  * Load cursors and pens.
        !           118:  */
        !           119:  void
        !           120: gtab_createtools(void)
        !           121: {
        !           122:         hVertCurs = LoadCursor(hLibInst, "VertLine");
        !           123:         hNormCurs = LoadCursor(NULL, IDC_ARROW);
        !           124: 
        !           125:         hpenDotted = CreatePen(PS_DOT, 1, RGB(0, 0, 0));
        !           126: }
        !           127: 
        !           128: /***************************************************************************
        !           129:  * Function: gtab_deltools
        !           130:  *
        !           131:  * Purpose:
        !           132:  *
        !           133:  * Delete pen
        !           134:  */
        !           135:  void
        !           136: gtab_deltools(void)
        !           137: {
        !           138:         DeleteObject(hpenDotted);
        !           139: }
        !           140: 
        !           141: 
        !           142: /***************************************************************************
        !           143:  * Function: gtab_wndproc
        !           144:  *
        !           145:  * Purpose:
        !           146:  *
        !           147:  * Window procedure for table
        !           148:  */
        !           149:  long FAR PASCAL
        !           150: gtab_wndproc(HWND hwnd, UINT msg, UINT wParam, long lParam)
        !           151: {
        !           152:         CREATESTRUCT FAR * csp;
        !           153:         HWND hOwner;
        !           154:         lpTable ptab;
        !           155:         HANDLE hHeap;
        !           156:         PAINTSTRUCT ps;
        !           157:         int y, y2, i;
        !           158:         HDC hDC;
        !           159:         lpTableSelection pselect;
        !           160:         long oldtop;
        !           161:         long change;
        !           162: 
        !           163:         switch(msg) {
        !           164: 
        !           165:         case WM_CREATE:
        !           166:                 /* create window. set the wnd extra bytes to
        !           167:                  * contain the owner window, a heap and a null table.
        !           168:                  * Owner window is either in lParam or the parent.
        !           169:                  * Then wait for TM_NEWID.
        !           170:                  */
        !           171:                 csp = (CREATESTRUCT FAR *) lParam;
        !           172:                 if (csp->lpCreateParams == NULL) {
        !           173:                         hOwner = GetParent(hwnd);
        !           174:                 } else {
        !           175:                         hOwner = (HWND) (long) csp->lpCreateParams;
        !           176:                 }
        !           177:                 ptab = NULL;
        !           178:                 hHeap = gmem_init();
        !           179:                 SetWindowLong(hwnd, WL_TABLE, (LONG) ptab);
        !           180:                 SetWindowLong(hwnd, WW_OWNER, (LONG) hOwner);
        !           181:                 SetWindowLong(hwnd, WW_HEAP, (LONG) hHeap);
        !           182: 
        !           183:                 SetScrollRange(hwnd, SB_VERT, 0, 0, TRUE);
        !           184:                 SetScrollRange(hwnd, SB_HORZ, 0, 0, TRUE);
        !           185:                 break;
        !           186: 
        !           187:         case TM_NEWID:
        !           188:                 /* complete change of table.
        !           189:                  * close old table, discard memory and
        !           190:                  * build new table
        !           191:                  */
        !           192:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           193:                 if (ptab != NULL) {
        !           194:                         gtab_sendtq(hwnd, TQ_CLOSE, ptab->hdr.id);
        !           195:                         gtab_deltable(hwnd, ptab);
        !           196:                         SetCursor(hNormCurs);
        !           197:                         SetWindowLong(hwnd, WL_TABLE, 0);
        !           198:                 }
        !           199:                 if ( (ptab = gtab_buildtable(hwnd, lParam)) != NULL) {
        !           200:                         SetWindowLong(hwnd, WL_TABLE, (long) (LPSTR) ptab);
        !           201:                         gtab_setsize(hwnd, ptab);
        !           202:                 } else {
        !           203:                         SetScrollRange(hwnd, SB_VERT, 0, 0, TRUE);
        !           204:                         SetScrollRange(hwnd, SB_HORZ, 0, 0, TRUE);
        !           205:                 }
        !           206:                 InvalidateRect(hwnd, NULL, TRUE);
        !           207:                 break;
        !           208: 
        !           209:         case TM_NEWLAYOUT:
        !           210:                 /* change of layout but for same id. no TQ_CLOSE,
        !           211:                  * but otherwise same as TM_NEWID
        !           212:                  */
        !           213:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           214:                 if (ptab != NULL) {
        !           215:                         gtab_deltable(hwnd, ptab);
        !           216:                         SetCursor(hNormCurs);
        !           217:                         SetWindowLong(hwnd, WL_TABLE, 0);
        !           218:                 }
        !           219:                 if ( (ptab = gtab_buildtable(hwnd, lParam)) != NULL) {
        !           220:                         SetWindowLong(hwnd, WL_TABLE, (long) (LPSTR) ptab);
        !           221:                         gtab_setsize(hwnd, ptab);
        !           222:                 } else {
        !           223:                         SetScrollRange(hwnd, SB_VERT, 0, 0, TRUE);
        !           224:                         SetScrollRange(hwnd, SB_HORZ, 0, 0, TRUE);
        !           225:                 }
        !           226:                 InvalidateRect(hwnd, NULL, TRUE);
        !           227:                 break;
        !           228: 
        !           229:         case TM_REFRESH:
        !           230:                 /* data in table has changed. nrows may have
        !           231:                  * changed. ncols and col types have not changed
        !           232:                  */
        !           233:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           234:                 if (ptab != NULL) {
        !           235:                         gtab_newsize(hwnd, ptab);
        !           236:                 }
        !           237:                 InvalidateRect(hwnd, NULL, TRUE);
        !           238:                 break;
        !           239: 
        !           240:         case TM_SELECT:
        !           241:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           242:                 if (ptab != NULL) {
        !           243:                         pselect = (lpTableSelection) lParam;
        !           244: 
        !           245:                         /*
        !           246:                          * we only support TM_SINGLE - so force the
        !           247:                          * selection to a single row or cell.
        !           248:                          */
        !           249:                         gtab_select(hwnd, ptab, pselect->startrow,
        !           250:                                 pselect->startcell,
        !           251:                                 1,
        !           252:                                 (ptab->hdr.selectmode & TM_ROW) ?
        !           253:                                         ptab->hdr.ncols : 1,
        !           254:                                 TRUE);
        !           255:                         gtab_showsel_middle(hwnd, ptab);
        !           256:                 }
        !           257:                 break;
        !           258: 
        !           259:         case TM_PRINT:
        !           260:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           261:                 hHeap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
        !           262:                 if (ptab != NULL) {
        !           263:                         gtab_print(hwnd, ptab, hHeap, (lpPrintContext) lParam);
        !           264:                         return(TRUE);
        !           265:                 }
        !           266: 
        !           267:         case TM_TOPROW:
        !           268: 
        !           269:                 /* return top row. if wParam is TRUE, set lParam
        !           270:                  * as the new toprow
        !           271:                  */
        !           272:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           273:                 if (ptab == NULL) {
        !           274:                         return(0);
        !           275:                 }
        !           276:                 oldtop = ptab->toprow;
        !           277:                 if ((wParam) && (lParam < ptab->hdr.nrows)) {
        !           278:                         change = lParam - ptab->toprow;
        !           279:                         change -= ptab->hdr.fixedrows;
        !           280:                         gtab_dovscroll(hwnd, ptab, change);
        !           281:                 }
        !           282:                 return(oldtop);
        !           283: 
        !           284:         case TM_ENDROW:
        !           285:                 /* return the last visible row in the window */
        !           286:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           287:                 if (ptab == NULL) {
        !           288:                         return(0);
        !           289:                 }
        !           290:                 return(ptab->nlines + ptab->toprow - 1);
        !           291: 
        !           292: 
        !           293:         case TM_APPEND:
        !           294:                 /* new rows have been added to the end of the
        !           295:                  * table, but the rest of the table has no
        !           296:                  * been change. Update without forcing redraw of
        !           297:                  * everything.
        !           298:                  * lParam contains the new total nr of rows
        !           299:                  */
        !           300:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           301:                 if (ptab != NULL) {
        !           302:                         gtab_append(hwnd, ptab, wParam, lParam);
        !           303:                         return(TRUE);
        !           304:                 }
        !           305:                 break;
        !           306: 
        !           307:         case WM_SIZE:
        !           308:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           309:                 if (ptab != NULL) {
        !           310:                         gtab_setsize(hwnd, ptab);
        !           311:                 }
        !           312:                 break;
        !           313: 
        !           314:         case WM_DESTROY:
        !           315:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           316:                 if (ptab != NULL) {
        !           317:                         gtab_sendtq(hwnd, TQ_CLOSE, ptab->hdr.id);
        !           318:                         gtab_deltable(hwnd, ptab);
        !           319:                 }
        !           320:                 hHeap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
        !           321:                 gmem_freeall(hHeap);
        !           322:                 break;
        !           323: 
        !           324:         case WM_PAINT:
        !           325:                 hDC = BeginPaint(hwnd, &ps);
        !           326:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           327:                 if (ptab != NULL) {
        !           328:                         /* separator lines between fixed rows/columns
        !           329:                          * (ie headers) and the rest - if enabled
        !           330:                          */
        !           331:                         /* paint here first for good impression,
        !           332:                          * and again after to clean up!!
        !           333:                          */
        !           334:                         if (ptab->hdr.vseparator) {
        !           335:                                 gtab_vsep(hwnd, ptab, hDC);
        !           336:                         }
        !           337:                         if (ptab->hdr.hseparator) {
        !           338:                                 gtab_hsep(hwnd, ptab, hDC);
        !           339:                         }
        !           340: 
        !           341:                         /* paint only the rows that need painting */
        !           342:                         for (i = 0; i < ptab->nlines; i++) {
        !           343:                                 y = ptab->pdata[i].linepos.start;
        !           344:                                 y2 = y + ptab->pdata[i].linepos.size;
        !           345:                                 if ( (y <= ps.rcPaint.bottom) &&
        !           346:                                      (y2 >= ps.rcPaint.top)) {
        !           347:                                         gtab_paint(hwnd, hDC, ptab, i);
        !           348:                                 }
        !           349:                         }
        !           350:                         if (ptab->hdr.vseparator) {
        !           351:                                 gtab_vsep(hwnd, ptab, hDC);
        !           352:                         }
        !           353:                         if (ptab->hdr.hseparator) {
        !           354:                                 gtab_hsep(hwnd, ptab, hDC);
        !           355:                         }
        !           356:                         if (ptab->selvisible) {
        !           357:                                 gtab_invertsel(hwnd, ptab, hDC);
        !           358:                         }
        !           359:                 }
        !           360: 
        !           361:                 EndPaint(hwnd, &ps);
        !           362:                 break;
        !           363: 
        !           364:         case WM_HSCROLL:
        !           365:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           366:                 if (ptab != NULL) {
        !           367:                         gtab_msg_hscroll(hwnd, ptab,
        !           368:                           GET_SCROLL_OPCODE(wParam, lParam),
        !           369:                           GET_SCROLL_POS(wParam, lParam));
        !           370:                 }
        !           371:                 break;
        !           372: 
        !           373:         case WM_VSCROLL:
        !           374:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           375:                 if (ptab != NULL) {
        !           376:                         gtab_msg_vscroll(hwnd, ptab,
        !           377:                           GET_SCROLL_OPCODE(wParam, lParam),
        !           378:                           GET_SCROLL_POS(wParam, lParam));
        !           379:                 }
        !           380:                 break;
        !           381: 
        !           382:         case WM_MOUSEMOVE:
        !           383:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           384:                 if (ptab != NULL) {
        !           385:                         gtab_move(hwnd, ptab, LOWORD(lParam), HIWORD(lParam));
        !           386:                 } else {
        !           387:                         SetCursor(hNormCurs);
        !           388:                 }
        !           389:                 break;
        !           390: 
        !           391:         case WM_LBUTTONDOWN:
        !           392:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           393:                 if (ptab != NULL) {
        !           394:                         gtab_press(hwnd, ptab, LOWORD(lParam), HIWORD(lParam));
        !           395:                 }
        !           396:                 break;
        !           397: 
        !           398:         case WM_LBUTTONUP:
        !           399:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           400:                 if (ptab != NULL) {
        !           401:                         gtab_release(hwnd, ptab,
        !           402:                                 LOWORD(lParam), HIWORD(lParam));
        !           403:                 }
        !           404:                 break;
        !           405: 
        !           406:         case WM_LBUTTONDBLCLK:
        !           407:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           408:                 if (ptab != NULL) {
        !           409:                         gtab_dblclick(hwnd, ptab,
        !           410:                                 LOWORD(lParam), HIWORD(lParam));
        !           411:                 }
        !           412:                 break;
        !           413: 
        !           414:         case WM_KEYDOWN:
        !           415:                 /* handle key presses for cursor movement about
        !           416:                  * the table, and return/space for selection.
        !           417:                  * Any key we don't handle is passed to the owner window
        !           418:                  * for him to handle.
        !           419:                  * The table window should have the focus
        !           420:                  */
        !           421:                 ptab = (lpTable) GetWindowLong(hwnd, WL_TABLE);
        !           422:                 if (ptab != NULL) {
        !           423:                         if (gtab_key(hwnd, ptab, wParam) != 0) {
        !           424:                                 /* pass key to owner since
        !           425:                                  * we don't know what to do with it
        !           426:                                  */
        !           427:                                 hOwner = (HANDLE) GetWindowLong(hwnd, WW_OWNER);
        !           428:                                 return(SendMessage(hOwner, WM_KEYDOWN,
        !           429:                                         wParam, lParam));
        !           430:                         } else {
        !           431:                                 return(0);      
        !           432:                         }
        !           433:                 }
        !           434:                 break;
        !           435: 
        !           436:         default:
        !           437:                 return(DefWindowProc(hwnd, msg, wParam, lParam));
        !           438:         }
        !           439:         return(TRUE);
        !           440: }
        !           441: 
        !           442: /***************************************************************************
        !           443:  * Function: gtab_sendtq
        !           444:  *
        !           445:  * Purpose:
        !           446:  *
        !           447:  * Send a table-query message to the owner window. Returns message
        !           448:  * value.
        !           449:  */
        !           450: long
        !           451: gtab_sendtq(HWND hwnd, UINT cmd, long lParam)
        !           452: {
        !           453:         HWND hOwner;
        !           454: 
        !           455:         hOwner = (HANDLE) GetWindowLong(hwnd, WW_OWNER);
        !           456:         return (SendMessage(hOwner, gtab_msgcode, cmd, lParam));
        !           457: }
        !           458: 
        !           459: /***************************************************************************
        !           460:  * Function: gtab_freelinedata
        !           461:  *
        !           462:  * Purpose:
        !           463:  *
        !           464:  * Free the memory allocated for the array of lines (each containing
        !           465:  * an array of Cells, each containing an array of chars for the actual
        !           466:  * data). Called on any occasion that would change the number of visible lines
        !           467:  */
        !           468: void
        !           469: gtab_freelinedata(HANDLE hHeap, lpTable ptab)
        !           470: {
        !           471:         int i, j, ncols;
        !           472:         lpCellData cd;
        !           473: 
        !           474: 
        !           475:         ncols = ptab->hdr.ncols;
        !           476: 
        !           477:         /* for each line */
        !           478:         for(i = 0; i < ptab->nlines; i++) {
        !           479:                 /* for each cell */
        !           480:                 for (j = 0; j < ncols; j++) {
        !           481:                         /* free up the actual text space */
        !           482:                         cd = &ptab->pdata[i].pdata[j];
        !           483:                         gmem_free(hHeap, (LPSTR) cd->ptext, cd->nchars);
        !           484:                 }
        !           485:                 /* dealloc array of CellData */
        !           486:                 gmem_free(hHeap, (LPSTR) ptab->pdata[i].pdata,
        !           487:                         sizeof(CellData) * ncols);
        !           488:         }
        !           489:         /* de-alloc array of linedatas */
        !           490:         gmem_free(hHeap, (LPSTR) ptab->pdata,
        !           491:                 sizeof(LineData) * ptab->nlines);
        !           492:         ptab->pdata = NULL;
        !           493: }
        !           494: 
        !           495: /***************************************************************************
        !           496:  * Function: gtab_alloclinedata
        !           497:  *
        !           498:  * Purpose:
        !           499:  *
        !           500:  * Allocate and init array of linedatas (include cell array
        !           501:  * and text for each cell)
        !           502:  */
        !           503: BOOL
        !           504: gtab_alloclinedata(HWND hwnd, HANDLE heap, lpTable ptab)
        !           505: {
        !           506:         lpLineData pline;
        !           507:         lpCellData cd;
        !           508:         int i, j;
        !           509: 
        !           510:         ptab->pdata = (lpLineData) gmem_get(heap,
        !           511:                 sizeof(LineData) * ptab->nlines);
        !           512:         if (ptab->pdata == NULL) {
        !           513:                 return(FALSE);
        !           514:         }
        !           515:         for (i = 0; i < ptab->nlines; i++) {
        !           516:                 pline = &ptab->pdata[i];
        !           517:                 pline->linepos.size = ptab->rowheight;
        !           518:                 pline->pdata = (lpCellData) gmem_get(heap,
        !           519:                         sizeof(CellData) * ptab->hdr.ncols);
        !           520:                 if (pline->pdata == NULL) {
        !           521:                         return(FALSE);
        !           522:                 }
        !           523:                 for (j = 0; j < ptab->hdr.ncols; j++) {
        !           524:                         cd = &pline->pdata[j];
        !           525:                         cd->props.valid = 0;
        !           526:                         cd->flags = 0;
        !           527:                         cd->nchars = ptab->pcolhdr[j].nchars;
        !           528:                         if (cd->nchars > 0) {
        !           529:                                 cd->ptext = gmem_get(heap, cd->nchars);
        !           530:                                 if (cd->ptext == NULL) {
        !           531:                                         return(FALSE);
        !           532:                                 }
        !           533:                         }
        !           534:                 }
        !           535:         }
        !           536: }
        !           537: 
        !           538: /***************************************************************************
        !           539:  * Function: gtab_deltable
        !           540:  *
        !           541:  * Purpose:
        !           542:  *
        !           543:  * Free up all table data structures. Called for new layout or new data.
        !           544:  */
        !           545: void
        !           546: gtab_deltable(HWND hwnd, lpTable ptab)
        !           547: {
        !           548:         HANDLE hHeap;
        !           549:         int ncols;
        !           550: 
        !           551:         if (ptab == NULL) {
        !           552:                 return;
        !           553:         }
        !           554:         hHeap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
        !           555:         ncols = ptab->hdr.ncols;
        !           556: 
        !           557:         if (ptab->pcolhdr != NULL) {
        !           558:                 gmem_free(hHeap, (LPSTR) ptab->pcolhdr,
        !           559:                         sizeof(ColProps) * ncols);
        !           560:         }
        !           561:         if (ptab->pcellpos != NULL) {
        !           562:                 gmem_free(hHeap, (LPSTR) ptab->pcellpos,
        !           563:                         sizeof(CellPos) * ncols);
        !           564:         }
        !           565:         if (ptab->pdata != NULL) {
        !           566:                 gtab_freelinedata(hHeap, ptab);
        !           567:         }
        !           568:         gmem_free(hHeap, (LPSTR) ptab, sizeof(Table));
        !           569: }
        !           570: 
        !           571: 
        !           572: /***************************************************************************
        !           573:  * Function: gtab_buildtable
        !           574:  *
        !           575:  * Purpose:
        !           576:  *
        !           577:  * Build up a Table struct (excluding data allocation and
        !           578:  * anything to do with font or window size).
        !           579:  * Return ptr to this or NULL if error
        !           580:  */
        !           581: lpTable
        !           582: gtab_buildtable(HWND hwnd, DWORD id)
        !           583: {
        !           584:         lpTable ptab;
        !           585:         HANDLE hHeap;
        !           586:         int ncols, i;
        !           587:         ColPropsList cplist;
        !           588: 
        !           589:         hHeap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
        !           590:         ptab = (lpTable) gmem_get(hHeap, sizeof(Table));
        !           591:         if (ptab == NULL) {
        !           592:                 return(NULL);
        !           593:         }
        !           594: 
        !           595:         /* get the row/column count from owner window */
        !           596:         ptab->hdr.id = id;
        !           597:         ptab->hdr.props.valid = 0;
        !           598:         ptab->hdr.sendscroll = FALSE;
        !           599:         if (gtab_sendtq(hwnd, TQ_GETSIZE, (long) (LPSTR)&ptab->hdr) == FALSE) {
        !           600:                 return(NULL);
        !           601:         }
        !           602: 
        !           603:         ncols = ptab->hdr.ncols;
        !           604:         ptab->pcolhdr = (lpColProps) gmem_get(hHeap, sizeof(ColProps) * ncols);
        !           605:         if (ptab->pcolhdr == NULL) {
        !           606:                 /* should prob send TQ_CLOSE at this point */
        !           607:                 return(NULL);
        !           608:         }
        !           609: 
        !           610:         /* init col properties to default */
        !           611:         for (i=0; i < ncols; i++) {
        !           612:                 ptab->pcolhdr[i].props.valid = 0;
        !           613:                 ptab->pcolhdr[i].nchars = 0;
        !           614:         }
        !           615:         /* get the column props from owner */
        !           616:         cplist.plist = ptab->pcolhdr;
        !           617:         cplist.id = id;
        !           618:         cplist.startcol = 0;
        !           619:         cplist.ncols = ncols;
        !           620:         gtab_sendtq(hwnd, TQ_GETCOLPROPS, (long) (LPSTR)&cplist);
        !           621: 
        !           622:         /* init remaining fields */
        !           623:         ptab->pcellpos = (lpCellPos) gmem_get(hHeap, sizeof(CellPos) * ncols);
        !           624:         if (ptab->pcellpos == NULL) {
        !           625:                 return(NULL);
        !           626:         }
        !           627: 
        !           628:         ptab->scrollscale = 1;
        !           629:         ptab->scroll_dx = 0;
        !           630:         ptab->toprow = 0;
        !           631:         ptab->pdata = NULL;
        !           632:         ptab->nlines = 0;
        !           633:         ptab->trackmode = TRACK_NONE;
        !           634: 
        !           635:         /* we have to notify owner of the current selection
        !           636:          * whenever it is changed
        !           637:          */
        !           638:         ptab->select.id = id;
        !           639:         gtab_select(hwnd, ptab, 0, 0, 0, 0, TRUE);
        !           640: 
        !           641:         /* calc ave height/width, cell widths and min height.
        !           642:          * these change only when cell properties / col count changes -
        !           643:          * ie only on rebuild-header events
        !           644:          */
        !           645:         gtab_calcwidths(hwnd, ptab);
        !           646:         return(ptab);
        !           647: }
        !           648: 
        !           649: /***************************************************************************
        !           650:  * Function: gtab_setsize
        !           651:  *
        !           652:  * Purpose:
        !           653:  *
        !           654:  * Set sizes that are based on window size and scroll pos
        !           655:  * set:
        !           656:  *      winwidth
        !           657:  *      nlines
        !           658:  *      cellpos start, clip start/end
        !           659:  * Alloc linedata and init
        !           660:  */
        !           661: void
        !           662: gtab_setsize(HWND hwnd, lpTable ptab)
        !           663: {
        !           664:         RECT rc;
        !           665:         int nlines;
        !           666:         HANDLE heap;
        !           667:         long range, change;
        !           668: 
        !           669:         GetClientRect(hwnd, &rc);
        !           670:         ptab->winwidth = rc.right - rc.left;
        !           671:         nlines = (rc.bottom - rc.top) / ptab->rowheight;
        !           672:         /* nlines is the number of whole lines - add one extra
        !           673:          * for the partial line at the bottom
        !           674:          */
        !           675:         nlines += 1;
        !           676: 
        !           677:         /* alloc space for nlines of data - if nlines has changed */
        !           678:         if (nlines != ptab->nlines) {
        !           679:                 heap = (HANDLE) GetWindowLong(hwnd, WW_HEAP);
        !           680:                 gtab_freelinedata(heap, ptab);
        !           681:                 ptab->nlines = nlines;
        !           682:                 if (!gtab_alloclinedata(hwnd, heap, ptab)) {
        !           683:                         ptab->nlines = 0;
        !           684:                         return;
        !           685:                 }
        !           686:         }
        !           687: 
        !           688:         /* set scroll vertical range */
        !           689:         range = ptab->hdr.nrows - (ptab->nlines - 1);
        !           690:         if (range < 0) {
        !           691:                 range = 0;
        !           692:                 change =  -(ptab->toprow);
        !           693:         } else if (ptab->toprow > range) {
        !           694:                 change = range - ptab->toprow;
        !           695:         } else {
        !           696:                 change = 0;
        !           697:         }
        !           698:         /* the scroll range must be 16-bits for Win3
        !           699:          * scale until this is true
        !           700:          */
        !           701:         ptab->scrollscale = 1;
        !           702:         while (range > 32766) {
        !           703:                 ptab->scrollscale *= 16;
        !           704:                 range /= 16;
        !           705:         }
        !           706: 
        !           707:         SetScrollRange(hwnd, SB_VERT, 0, (int) range, TRUE);
        !           708:         gtab_dovscroll(hwnd, ptab, change);
        !           709: 
        !           710:         /* set horz scroll range */
        !           711:         range = ptab->rowwidth - ptab->winwidth;
        !           712:         if (range < 0) {
        !           713:                 range = 0;
        !           714:                 change = -(ptab->scroll_dx);
        !           715:         } else if (ptab->scroll_dx > range) {
        !           716:                 change = range - ptab->scroll_dx;
        !           717:         } else {
        !           718:                 change = 0;
        !           719:         }
        !           720:         /* horz scroll range will always be < 16 bits */
        !           721:         SetScrollRange(hwnd, SB_HORZ, 0, (int) range, TRUE);
        !           722:         gtab_dohscroll(hwnd, ptab, change);
        !           723: }
        !           724: 
        !           725: /***************************************************************************
        !           726:  * Function: gtab_calcwidths
        !           727:  *
        !           728:  * Purpose:
        !           729:  *
        !           730:  * Set column widths/height and totals (based on column props)
        !           731:  * - no assumption of window size (see gtab_setsize)
        !           732:  * sets avewidth,rowheight,cellpos.size,rowwidth (total of cellpos.size)
        !           733:  */
        !           734: void
        !           735: gtab_calcwidths(HWND hwnd, lpTable ptab)
        !           736: {
        !           737:         int i, cxtotal, cx, ave;
        !           738:         TEXTMETRIC tm, tmcol;
        !           739:         HDC hdc;
        !           740:         lpProps hdrprops, cellprops;
        !           741:         HFONT hfont;
        !           742: 
        !           743:         hdrprops = &ptab->hdr.props;
        !           744:         hdc = GetDC(hwnd);
        !           745:         if (hdrprops->valid & P_FONT) {
        !           746:                 hfont = SelectObject(hdc, hdrprops->hFont);
        !           747:         }
        !           748:         GetTextMetrics(hdc, &tm);
        !           749:         if (hdrprops->valid & P_FONT) {
        !           750:                 SelectObject(hdc, hfont);
        !           751:         }
        !           752:         ReleaseDC(hwnd, hdc);
        !           753: 
        !           754:         /* get width and height of average character */
        !           755:         ptab->avewidth = tm.tmAveCharWidth;
        !           756:         ptab->rowheight = tm.tmHeight + tm.tmExternalLeading;
        !           757:         if (hdrprops->valid & P_HEIGHT) {
        !           758:                 ptab->rowheight = hdrprops->height;
        !           759:         }
        !           760: 
        !           761:         /* set pixel width of each cell (and add up for row total)
        !           762:          * based on ave width * nr chars, unless P_WIDTH set
        !           763:          */
        !           764:         cxtotal = 0;
        !           765:         for (i = 0; i < ptab->hdr.ncols; i++) {
        !           766:                 cellprops = &ptab->pcolhdr[i].props;
        !           767: 
        !           768:                 if (cellprops->valid & P_WIDTH) {
        !           769:                         cx = cellprops->width;
        !           770:                 } else if (hdrprops->valid & P_WIDTH) {
        !           771:                         cx = hdrprops->width;
        !           772:                 } else {
        !           773: 
        !           774:                         if (cellprops->valid & P_FONT) {
        !           775:                                 hdc = GetDC(hwnd);
        !           776:                                 hfont = SelectObject(hdc, cellprops->hFont);
        !           777:                                 GetTextMetrics(hdc, &tmcol);
        !           778:                                 SelectObject(hdc, hfont);
        !           779:                                 ReleaseDC(hwnd, hdc);
        !           780:                                 ave = tmcol.tmAveCharWidth;
        !           781:                         } else {
        !           782:                                 ave = ptab->avewidth;
        !           783:                         }
        !           784:                         /* ave width * nchars */
        !           785:                         cx =  ptab->pcolhdr[i].nchars + 1;
        !           786:                         cx *= ave;
        !           787:                 }
        !           788:                 /* add 2 pixels for box lines */
        !           789:                 cx += 2;
        !           790:                 ptab->pcellpos[i].size = cx;
        !           791:                 cxtotal += cx;
        !           792:         }
        !           793:         ptab->rowwidth = cxtotal;
        !           794: }
        !           795: 
        !           796: /***************************************************************************
        !           797:  * Function: gtab_newsize
        !           798:  *
        !           799:  * Purpose:
        !           800:  *
        !           801:  * Called when row data + possible nrows changes.
        !           802:  * other changes are ignored
        !           803:  */
        !           804: void
        !           805: gtab_newsize(HWND hwnd, lpTable ptab)
        !           806: {
        !           807:         TableHdr hdr;
        !           808: 
        !           809:         /* get new row count */
        !           810:         hdr = ptab->hdr;
        !           811:         gtab_sendtq(hwnd, TQ_GETSIZE, (long) (LPSTR) &hdr);
        !           812:         if (hdr.nrows != ptab->hdr.nrows) {
        !           813:                 ptab->hdr.nrows = hdr.nrows;
        !           814:                 gtab_setsize(hwnd, ptab);
        !           815:         }
        !           816: 
        !           817:         gtab_invallines(hwnd, ptab, 0, ptab->nlines);
        !           818: 
        !           819:         InvalidateRect(hwnd, NULL, TRUE);
        !           820: }
        !           821: 
        !           822: void
        !           823: gtab_invallines(HWND hwnd, lpTable ptab, int start, int count)
        !           824: {
        !           825:         int i, j;
        !           826: 
        !           827:         for (i = start; i < start + count; i++) {
        !           828:                 for (j = 0; j < ptab->hdr.ncols; j++) {
        !           829:                         ptab->pdata[i].pdata[j].flags = 0;
        !           830:                 }
        !           831:         }
        !           832: }
        !           833: 
        !           834: /***************************************************************************
        !           835:  * Function: gtab_append
        !           836:  *
        !           837:  * Purpose:
        !           838:  *
        !           839:  * New rows have been added to the table. Adjust the scroll range and
        !           840:  * position, and redraw the rows if the end of the table is currently
        !           841:  * visible.
        !           842:  * rows = the new total row count.
        !           843:  */
        !           844: void
        !           845: gtab_append(HWND hwnd, lpTable ptab, int rows, DWORD id)
        !           846: {
        !           847:         long range;
        !           848:         long oldrows;
        !           849:         int line, nupdates;
        !           850:         RECT rc;
        !           851: 
        !           852: 
        !           853:         /* change to the new id */
        !           854:         ptab->hdr.id = id;
        !           855:         ptab->select.id = id;
        !           856: 
        !           857:         /* update the header, but remember the old nr of rows
        !           858:          * so we know where to start updating
        !           859:          */
        !           860:         oldrows = ptab->hdr.nrows;
        !           861: 
        !           862:         /* check that the new nr of rows is not smaller. this is
        !           863:          * illegal at this point and should be ignored
        !           864:          */
        !           865:         if (oldrows >= rows) {
        !           866:                 return; 
        !           867:         }
        !           868: 
        !           869:         ptab->hdr.nrows = rows;
        !           870: 
        !           871:         /* set the vertical scroll range */
        !           872:         range = rows - (ptab->nlines - 1);
        !           873: 
        !           874:         if (range < 0) {
        !           875:                 range = 0;      
        !           876:         }
        !           877: 
        !           878:         /* force the scroll range into 16-bits for win 3.1 */
        !           879:         ptab->scrollscale = 1;
        !           880:         while (range > 32766) {
        !           881:                 ptab->scrollscale *= 16;
        !           882:                 range /= 16;
        !           883:         }
        !           884: 
        !           885:         /* now set the scroll bar range and position */
        !           886:         SetScrollRange(hwnd, SB_VERT, 0, (int) range, TRUE);
        !           887:         if (range > 0) {
        !           888:                 SetScrollPos(hwnd, SB_VERT,
        !           889:                         (int) (ptab->toprow / ptab->scrollscale), TRUE);
        !           890:         }
        !           891: 
        !           892:         /* calculate which screen lines need to be updated - find what
        !           893:          * screen line the start of the new section is at
        !           894:          */
        !           895:         line = gtab_rowtoline(hwnd, ptab, oldrows);
        !           896:         if (line == -1) {
        !           897:                 /* not visible -> no more to do */
        !           898:                 return;
        !           899:         }
        !           900: 
        !           901:         /* how many lines to update - rest of screen or nr of
        !           902:          * new lines if less than rest of screen
        !           903:          */
        !           904:         nupdates = min((ptab->nlines - line), (int)(rows - oldrows));
        !           905: 
        !           906:         /* invalidate the screen line buffers to indicate data
        !           907:          * needs to be refetch from parent window
        !           908:          */
        !           909:         gtab_invallines(hwnd, ptab, line, nupdates);
        !           910: 
        !           911:         /* calculate the region of the screen to be repainted -
        !           912:          * left and right are same as window. top and bottom
        !           913:          * need to be calculated from screen line height
        !           914:          */
        !           915:         
        !           916:         GetClientRect(hwnd, &rc);
        !           917:         rc.top += line * ptab->rowheight;
        !           918:         rc.bottom = rc.top + (nupdates * ptab->rowheight);
        !           919: 
        !           920:         /* force a repaint of the updated region */
        !           921:         InvalidateRect(hwnd, &rc, TRUE);
        !           922: }
        !           923:         
        !           924: 
        !           925: 
        !           926:         

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.