Annotation of mstools/samples/sdktools/windiff/tpaint.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: TPAINT.C
                     14: *
                     15: * Paint functions
                     16: *
                     17: * Functions:
                     18: *
                     19: * GetTextExtent()
                     20: * gtab_updatecontig()
                     21: * gtab_delcr()
                     22: * gtab_updateline()
                     23: * gtab_updatecontig()
                     24: * gtab_boxcell()
                     25: * gtab_paintcell()
                     26: * gtab_paint()
                     27: * gtab_vsep()
                     28: * gtab_hsep()
                     29: * gtab_drawvertline()
                     30: * gtab_invertsel()
                     31: * 
                     32: * Comments:
                     33: *
                     34: * See table.h for interface design.
                     35: *
                     36: ****************************************************************************/
                     37: #include <string.h>
                     38: #include <windows.h>
                     39: #include <commdlg.h>
                     40: 
                     41: #include "gutils.h"
                     42: #include "table.h"
                     43: #include "tpriv.h"
                     44: 
                     45: 
                     46: /***************************************************************************
                     47:  * Function: GetTextExtent
                     48:  *
                     49:  * Purpose:
                     50:  * 
                     51:  * Calls GetTextExtentPoint - for ease of porting.
                     52:  */
                     53:  int
                     54: GetTextExtent(HDC hdc, LPSTR text, int len)
                     55: {
                     56:     SIZE sz;
                     57: 
                     58:     GetTextExtentPoint(hdc, text, len, &sz);
                     59:     return(sz.cx);
                     60: }
                     61: 
                     62: void gtab_updatecontig(HWND hwnd, lpTable ptab, int line, int cell1, int count);
                     63: 
                     64: /***************************************************************************
                     65:  * Function: gtab_delcr
                     66:  *
                     67:  * Purpose:
                     68:  *
                     69:  * change all cr/lf chars in input text to spaces 
                     70:  */
                     71: void gtab_delcr(LPSTR ptext)
                     72: {
                     73:         LPSTR chp;
                     74: 
                     75:         if (ptext == NULL) {
                     76:                 return;
                     77:         }
                     78:         for(chp = ptext; (chp = strchr(chp, '\r')) != NULL; ) {
                     79:                 *chp = ' ';
                     80:         }
                     81:         for(chp = ptext; (chp = strchr(chp, '\n')) != NULL; ) {
                     82:                 *chp = ' ';
                     83:         }
                     84: }
                     85: 
                     86: /***************************************************************************
                     87:  * Function: gtab_updateline
                     88:  *
                     89:  * Purpose:
                     90:  *
                     91:  * Ensures that all visible cells in the given line have valid
                     92:  * text and property contents. loop through the cells, picking out
                     93:  * contiguous blocks of visible, invalid cells and call
                     94:  * gtab_updatecontig to update these from the owner window.
                     95:  */
                     96: void
                     97: gtab_updateline(HWND hwnd, lpTable ptab, int line)
                     98: {
                     99:         lpCellPos ppos;
                    100:         int cell1, cellcount;
                    101:         lpLineData pline;
                    102:         lpCellData cd;
                    103:         int i;
                    104: 
                    105:         pline = &ptab->pdata[line];
                    106:         cell1 = 0;
                    107:         cellcount = 0;
                    108:         for (i = 0; i < ptab->hdr.ncols; i++) {
                    109:                 ppos = &ptab->pcellpos[i];
                    110:                 cd = &pline->pdata[i];
                    111:                 if (ppos->clipstart < ppos->clipend) {
                    112:                         if ((cd->flags & CELL_VALID) == 0) {
                    113:                                 /* add a cell to the list to be updated*/
                    114:                                 if (cellcount++ == 0) {
                    115:                                         cell1 = i;
                    116:                                 }
                    117:                         } else {
                    118:                                 /* this cell already valid - so end of
                    119:                                  * a contig block. if the contig
                    120:                                  * block just ended contained cells to update,
                    121:                                  * do it now
                    122:                                  */
                    123:                                 if (cellcount > 0) {
                    124:                                         gtab_updatecontig(hwnd, ptab,
                    125:                                           line, cell1, cellcount);
                    126:                                 }
                    127:                                 cellcount = 0;
                    128:                         }
                    129:                 }
                    130:                 /* cell not visible - end of a contig block. If it was a
                    131:                  * non-empty contig block, then update it now.
                    132:                  */
                    133:                 if (cellcount > 0)  {
                    134:                         gtab_updatecontig(hwnd, ptab, line, cell1, cellcount);
                    135:                         cellcount = 0;  
                    136:                 }
                    137:         }
                    138:         if (cellcount > 0) {
                    139:                 gtab_updatecontig(hwnd, ptab, line, cell1, cellcount);
                    140:                 cellcount = 0;
                    141:         }
                    142: }
                    143: 
                    144: /***************************************************************************
                    145:  * Function: gtab_updatecontig
                    146:  *
                    147:  * Purpose:
                    148:  *
                    149:  * Updates a contiguous block of invalid cells by calling the owner window
                    150:  */
                    151: void
                    152: gtab_updatecontig(HWND hwnd, lpTable ptab, int line, int cell1, int count)
                    153: {
                    154:         lpLineData pline;
                    155:         lpCellData cd;
                    156:         CellDataList list;
                    157:         lpProps colprops;
                    158:         int i;
                    159: 
                    160:         pline = &ptab->pdata[line];
                    161:         cd = &pline->pdata[cell1];
                    162: 
                    163:         list.id = ptab->hdr.id;
                    164:         list.row = gtab_linetorow(hwnd, ptab, line);
                    165:         list.startcell = cell1;
                    166:         list.ncells = count;
                    167:         list.plist = cd;
                    168: 
                    169:         /* clear out prop flags */
                    170:         for (i = 0; i < count; i++) {
                    171:                 cd[i].props.valid = 0;
                    172:                 if (cd[i].nchars > 0) {
                    173:                         cd[i].ptext[0] = '\0';
                    174:                 }
                    175:         }
                    176: 
                    177:         if (list.row < ptab->hdr.nrows) {
                    178:                 gtab_sendtq(hwnd, TQ_GETDATA, (long) (LPSTR) &list);
                    179:         }
                    180: 
                    181:         /* for each cell, mark valid and set properties */
                    182:         for (i = 0; i < count; i++) {
                    183:                 cd[i].flags |= CELL_VALID;
                    184:                 gtab_delcr(cd[i].ptext);
                    185:                 /* fetch properties from hdr and colhdr */
                    186:                 colprops = &ptab->pcolhdr[i + cell1].props;
                    187:                 if (!(cd[i].props.valid & P_FCOLOUR)) {
                    188:                         if (colprops->valid & P_FCOLOUR) {
                    189:                                 cd[i].props.valid |= P_FCOLOUR;
                    190:                                 cd[i].props.forecolour = colprops->forecolour;
                    191:                         } else if (ptab->hdr.props.valid & P_FCOLOUR) {
                    192:                                 cd[i].props.valid |= P_FCOLOUR;
                    193:                                 cd[i].props.forecolour =
                    194:                                         ptab->hdr.props.forecolour;
                    195:                         }
                    196:                 }
                    197: 
                    198:                 if (!(cd[i].props.valid & P_BCOLOUR)) {
                    199:                         if (colprops->valid & P_BCOLOUR) {
                    200:                                 cd[i].props.valid |= P_BCOLOUR;
                    201:                                 cd[i].props.backcolour = colprops->backcolour;
                    202:                         } else if (ptab->hdr.props.valid & P_BCOLOUR) {
                    203:                                 cd[i].props.valid |= P_BCOLOUR;
                    204:                                 cd[i].props.backcolour =
                    205:                                         ptab->hdr.props.backcolour;
                    206:                         }
                    207:                 }
                    208: 
                    209:                 if (!(cd[i].props.valid & P_FONT)) {
                    210:                         if (colprops->valid & P_FONT) {
                    211:                                 cd[i].props.valid |= P_FONT;
                    212:                                 cd[i].props.hFont = colprops->hFont;
                    213:                         } else if (ptab->hdr.props.valid & P_FONT) {
                    214:                                 cd[i].props.valid |= P_FONT;
                    215:                                 cd[i].props.hFont = ptab->hdr.props.hFont;
                    216:                         }
                    217:                 }
                    218: 
                    219:                 if (!(cd[i].props.valid & P_ALIGN)) {
                    220:                         if (colprops->valid & P_ALIGN) {
                    221:                                 cd[i].props.valid |= P_ALIGN;
                    222:                                 cd[i].props.alignment = colprops->alignment;
                    223:                         } else if (ptab->hdr.props.valid & P_ALIGN) {
                    224:                                 cd[i].props.valid |= P_ALIGN;
                    225:                                 cd[i].props.alignment =
                    226:                                         ptab->hdr.props.alignment;
                    227:                         }
                    228:                 }
                    229: 
                    230:                 if (!(cd[i].props.valid & P_BOX)) {
                    231:                         if (colprops->valid & P_BOX) {
                    232:                                 cd[i].props.valid |= P_BOX;
                    233:                                 cd[i].props.box = colprops->box;
                    234:                         } else if (ptab->hdr.props.valid & P_BOX) {
                    235:                                 cd[i].props.valid |= P_BOX;
                    236:                                 cd[i].props.box = ptab->hdr.props.box;
                    237:                         }
                    238:                 }
                    239:                 /* you can't set width/height per cell - this
                    240:                  * is ignored at cell level.
                    241:                  */
                    242:         }
                    243: 
                    244: }
                    245: 
                    246: /***************************************************************************
                    247:  * Function: gtab_boxcell
                    248:  *
                    249:  * Purpose:
                    250:  *
                    251:  * Draws box around a cell in a table.
                    252:  */ 
                    253: void
                    254: gtab_boxcell(HWND hwnd, HDC hdc, LPRECT rcp, LPRECT pclip, UINT boxmode)
                    255: {
                    256:         if (boxmode & P_BOXTOP) {
                    257:                 MoveToEx(hdc, max(rcp->left, pclip->left),
                    258:                         max(rcp->top, pclip->top), NULL);
                    259:                 LineTo(hdc, min(rcp->right, pclip->right),
                    260:                         max(rcp->top, pclip->top));
                    261:         }
                    262:         if (boxmode & P_BOXBOTTOM) {
                    263:                 MoveToEx(hdc, max(rcp->left, pclip->left),
                    264:                         min(rcp->bottom, pclip->bottom), NULL);
                    265:                 LineTo(hdc, min(rcp->right, pclip->right),
                    266:                         min(rcp->bottom, pclip->bottom));
                    267:         }
                    268:         if (boxmode & P_BOXLEFT) {
                    269:                 MoveToEx(hdc, max(rcp->left, pclip->left),
                    270:                         max(rcp->top, pclip->top), NULL);
                    271:                 MoveToEx(hdc, max(rcp->left, pclip->left),
                    272:                         min(rcp->bottom, pclip->bottom), NULL);
                    273:         }
                    274:         if (boxmode & P_BOXRIGHT) {
                    275:                 MoveToEx(hdc, min(rcp->right, pclip->right),
                    276:                         max(rcp->top, pclip->top), NULL);
                    277:                 LineTo(hdc, min(rcp->right, pclip->right),
                    278:                         min(rcp->bottom, pclip->bottom));
                    279:         }
                    280: }
                    281: 
                    282: /***************************************************************************
                    283:  * Function: gtab_paintcell
                    284:  *
                    285:  * Purpose:
                    286:  *
                    287:  * Paints a cell.
                    288:  */
                    289: void
                    290: gtab_paintcell(HWND hwnd, HDC hdc, lpTable ptab, int line, int cell)
                    291: {
                    292:         lpLineData pline;
                    293:         lpCellData cd;
                    294:         lpCellPos ppos;
                    295:         RECT rc, rcbox;
                    296:         int cx, x, y, tabwidth;
                    297:         UINT align;
                    298:         LPSTR chp, tabp;
                    299:         DWORD fcol, bkcol;
                    300:         HFONT hfont;
                    301:         TEXTMETRIC tm;
                    302:         HBRUSH hbr;
                    303: 
                    304:         /* init pointers to cell text and properties */
                    305:         pline = &ptab->pdata[line];
                    306:         cd = &pline->pdata[cell];
                    307:         ppos = &ptab->pcellpos[cell];
                    308: 
                    309:         /* clip all output to this rectangle */
                    310:         rc.top = pline->linepos.clipstart;
                    311:         rc.bottom = pline->linepos.clipend;
                    312:         rc.left = ppos->clipstart;
                    313:         rc.right = ppos->clipend;
                    314: 
                    315: 
                    316:         /* check cell properties and colours */
                    317:         if (cd->props.valid & P_ALIGN) {
                    318:                 align = cd->props.alignment;
                    319:         } else {
                    320:                 align = P_LEFT;
                    321:         }
                    322:         if (cd->props.valid & P_FONT) {
                    323:                 hfont = SelectObject(hdc, cd->props.hFont);
                    324:                 GetTextMetrics(hdc, &tm);
                    325:                 tabwidth = tm.tmAveCharWidth * 8;
                    326:         } else {
                    327:                 tabwidth = ptab->avewidth * 8;
                    328:         }
                    329: 
                    330:         /* set colours if not default */
                    331:         if (cd->props.valid & P_FCOLOUR) {
                    332:                 fcol = SetTextColor(hdc, cd->props.forecolour);
                    333:         }
                    334:         if (cd->props.valid & P_BCOLOUR) {
                    335:                 /* there is a non-default background colour.
                    336:                  * create a brush and fill the entire cell with it
                    337:                  */
                    338:                 hbr = CreateSolidBrush(cd->props.backcolour);
                    339:                 FillRect(hdc, &rc, hbr);
                    340:                 DeleteObject(hbr);
                    341: 
                    342:                 /* also set colour as background colour for the text */
                    343:                 bkcol = SetBkColor(hdc, cd->props.backcolour);
                    344:         }
                    345: 
                    346:         /* calc offset of text within cell for right-align or centering */
                    347:         if (align == P_LEFT) {
                    348:                 cx = ptab->avewidth/2;
                    349:         } else {
                    350:                 if (cd->ptext == NULL) {
                    351:                         cx = 0;
                    352:                 } else {
                    353:                         cx = LOWORD(GetTextExtent(hdc, cd->ptext,
                    354:                                         lstrlen(cd->ptext)));
                    355:                 }
                    356:                 if (align == P_CENTRE) {
                    357:                         cx = (ppos->size - cx) / 2;
                    358:                 } else {
                    359:                         cx = ppos->size - cx - (ptab->avewidth/2);
                    360:                 }
                    361:         }
                    362:         cx += ppos->start;
                    363: 
                    364:         /* expand tabs on output */
                    365:         x = 0;
                    366:         y = pline->linepos.start;
                    367: 
                    368:         for (chp = cd->ptext;
                    369:             ((chp != NULL) && ((tabp = strchr(chp, '\t')) != NULL)); ) {
                    370:                 /* perform output upto tab char */
                    371:                 ExtTextOut(hdc, x+cx, y, ETO_CLIPPED, &rc, chp, tabp-chp, NULL);
                    372:                 
                    373:                 /* advance past the tab */
                    374:                 x += LOWORD(GetTextExtent(hdc, chp, tabp - chp));
                    375:                 x = ( (x + tabwidth) / tabwidth) * tabwidth;
                    376:                 chp = ++tabp;
                    377:         }
                    378: 
                    379:         /*no more tabs - output rest of string */
                    380:         if (chp != NULL) {
                    381:                 ExtTextOut(hdc, x+cx, y, ETO_CLIPPED, &rc,
                    382:                                 chp, lstrlen(chp), NULL);
                    383:         }
                    384: 
                    385:         /* reset colours to original if not default */
                    386:         if (cd->props.valid & P_FCOLOUR) {
                    387:                 SetTextColor(hdc, fcol);
                    388:         }
                    389:         if (cd->props.valid & P_BCOLOUR) {
                    390:                 SetBkColor(hdc, bkcol);
                    391:         }
                    392:         if (cd->props.valid & P_FONT) {
                    393:                 SelectObject(hdc, hfont);
                    394:         }
                    395: 
                    396:         /* now box cell if marked */
                    397:         if (cd->props.valid & P_BOX) {
                    398:                 if (cd->props.box != 0) {
                    399:                         rcbox.top = pline->linepos.start;
                    400:                         rcbox.bottom = rcbox.top + pline->linepos.size;
                    401:                         rcbox.left = ppos->start;
                    402:                         rcbox.right = ppos->start + ppos->size;
                    403:                         gtab_boxcell(hwnd, hdc, &rcbox, &rc, cd->props.box);
                    404:                 }
                    405:         }
                    406: }
                    407: 
                    408: /***************************************************************************
                    409:  * Function: gtab_paint
                    410:  *
                    411:  * Purpose:
                    412:  *
                    413:  * Fetch and paint the specified line 
                    414:  */
                    415: void
                    416: gtab_paint(HWND hwnd, HDC hdc, lpTable ptab, int line)
                    417: {
                    418:         lpCellPos ppos;
                    419:         int i;
                    420: 
                    421:         gtab_updateline(hwnd, ptab, line);
                    422: 
                    423:         for (i = 0; i < ptab->hdr.ncols; i++) {
                    424:                 ppos = &ptab->pcellpos[i];
                    425:                 if (ppos->clipstart < ppos->clipend) {
                    426:                         gtab_paintcell(hwnd, hdc, ptab, line, i);
                    427:                 }
                    428:         }
                    429: }
                    430: 
                    431: 
                    432: /***************************************************************************
                    433:  * Function: gtab_vsep
                    434:  *
                    435:  * Purpose:
                    436:  *
                    437:  */
                    438: void
                    439: gtab_vsep(HWND hwnd, lpTable ptab, HDC hdc)
                    440: {
                    441:         int x;
                    442:         RECT rc;
                    443: 
                    444:         if (ptab->hdr.fixedcols < 1) {
                    445:                 return;
                    446:         }
                    447:         x = ptab->pcellpos[ptab->hdr.fixedcols - 1].clipend+1;
                    448:         GetClientRect(hwnd, &rc);
                    449:         MoveToEx(hdc, x, rc.top, NULL);
                    450:         LineTo(hdc, x, rc.bottom);
                    451: }
                    452: 
                    453: /***************************************************************************
                    454:  * Function: gtab_hsep
                    455:  *
                    456:  * Purpose:
                    457:  */
                    458: void
                    459: gtab_hsep(HWND hwnd, lpTable ptab, HDC hdc)
                    460: {
                    461:         int y;
                    462:         RECT rc;
                    463: 
                    464:         if (ptab->hdr.fixedrows < 1) {
                    465:                 return;
                    466:         }
                    467:         y = ptab->rowheight * ptab->hdr.fixedrows;
                    468:         GetClientRect(hwnd, &rc);
                    469:         MoveToEx(hdc, rc.left, y-1, NULL);
                    470:         LineTo(hdc, rc.right, y-1);
                    471: }
                    472: 
                    473: /***************************************************************************
                    474:  * Function: gtab_drawverline
                    475:  *
                    476:  * Purpose:
                    477:  *
                    478:  * Draw in (inverting) the dotted selection lines for tracking a col width
                    479:  */
                    480: void
                    481: gtab_drawvertline(HWND hwnd, lpTable ptab)
                    482: {
                    483:         RECT rc;
                    484:         HDC hdc;
                    485:         HPEN hpen;
                    486: 
                    487:         hdc = GetDC(hwnd);
                    488:         SetROP2(hdc, R2_XORPEN);
                    489:         hpen = SelectObject(hdc, hpenDotted);
                    490:         GetClientRect(hwnd, &rc);
                    491: 
                    492:         MoveToEx(hdc, ptab->trackline1, rc.top, NULL);
                    493:         LineTo(hdc, ptab->trackline1, rc.bottom);
                    494:         if (ptab->trackline2 != -1) {
                    495:                 MoveToEx(hdc, ptab->trackline2, rc.top, NULL);
                    496:                 LineTo(hdc, ptab->trackline2, rc.bottom);
                    497:         }
                    498: 
                    499:         SelectObject(hdc, hpen);
                    500:         ReleaseDC(hwnd, hdc);
                    501: }
                    502:         
                    503: 
                    504: /***************************************************************************
                    505:  * Function: gtab_invertsel
                    506:  *
                    507:  * Purpose:
                    508:  *
                    509:  * Mark the selected line, if visible, in the style chosen by the
                    510:  * client app. This can be TM_SOLID, meaning an inversion of
                    511:  * the whole selected area or TM_FOCUS, meaning, inversion of the first
                    512:  * cell, and then a dotted focus rectangle for the rest.
                    513:  *
                    514:  * This function inverts either style, and so will turn the selection
                    515:  * both on and off.
                    516:  */
                    517: void
                    518: gtab_invertsel(HWND hwnd, lpTable ptab, HDC hdc_in)
                    519: {
                    520:         HDC hdc;
                    521:         int line;
                    522:         RECT rc;
                    523:         int lastcell;
                    524: 
                    525: 
                    526:         /* is row visible on screen ?  */
                    527:         line = gtab_rowtoline(hwnd, ptab, ptab->select.startrow);
                    528:         if (line < 0) {
                    529:                 return;
                    530:         }
                    531: 
                    532:         /* selection mode includes a flag TM_FOCUS indicating we should
                    533:          * use a focus rect instead of the traditional inversion for
                    534:          * selections in this table. This interferes with multiple backgrnd
                    535:          * colours less.  However we still do inversion for fixedcols.
                    536:          */
                    537: 
                    538:         lastcell = (int)(ptab->select.startcell + ptab->select.ncells - 1);
                    539: 
                    540:         rc.top = ptab->pdata[line].linepos.clipstart;
                    541:         rc.bottom = ptab->pdata[line].linepos.clipend;
                    542: 
                    543:         /*
                    544:          * invert the whole area for TM_SOLID or just the first
                    545:          * cell for TM_FOCUS
                    546:          */
                    547:         rc.left = ptab->pcellpos[ptab->select.startcell].clipstart;
                    548:         if (ptab->hdr.selectmode & TM_FOCUS) {
                    549:                 rc.right = ptab->pcellpos[ptab->select.startcell].clipend;
                    550:         }else {
                    551:                 rc.right = ptab->pcellpos[lastcell].clipend;
                    552:         }
                    553: 
                    554:         if (hdc_in == NULL) {
                    555:                 hdc = GetDC(hwnd);
                    556:         } else {
                    557:                 hdc = hdc_in;
                    558:         }
                    559: 
                    560:         InvertRect(hdc, &rc);
                    561: 
                    562:         /*
                    563:          * draw focus rectangle around remaining cells on this line, if there
                    564:          * are any
                    565:          */
                    566:         if (ptab->hdr.selectmode & TM_FOCUS) {
                    567:                 if (ptab->select.ncells > 1) {
                    568:                         rc.left = ptab->pcellpos[ptab->select.startcell+1].clipstart;
                    569:                         rc.right = ptab->pcellpos[lastcell].clipend;
                    570:                         DrawFocusRect(hdc, &rc);
                    571:                 }
                    572:         }
                    573: 
                    574:         if (hdc_in == NULL) {
                    575:                 ReleaseDC(hwnd, hdc);
                    576:         }
                    577: }

unix.superglobalmegacorp.com

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