Annotation of mstools/samples/sdktools/windiff/table.c, revision 1.1.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.