Annotation of mstools/samples/sdktools/imagedit/workwp.c, revision 1.1

1.1     ! root        1: /***************************************************************************
        !             2:  *                                                                         *
        !             3:  *  MODULE      : WorkWP.c                                                 *
        !             4:  *                                                                         *
        !             5:  *  DESCRIPTION : Functions controlling the workspace window.              *
        !             6:  *                                                                         *
        !             7:  *  HISTORY     : 6/21/89 LR                                               *
        !             8:  *                                                                         *
        !             9:  ***************************************************************************/
        !            10: 
        !            11: #include "imagedit.h"
        !            12: 
        !            13: #include <stdlib.h>
        !            14: 
        !            15: 
        !            16: /*
        !            17:  * This structure is used in conjunction with DeltaGenInit() and DeltaGen().
        !            18:  */
        !            19: typedef struct _DELTAGEN { /* dg */
        !            20:     BOOL fSwap;
        !            21:     INT xf;
        !            22:     INT yf;
        !            23:     INT dx;
        !            24:     INT dy;
        !            25:     INT d;
        !            26:     INT incx;
        !            27:     INT incy;
        !            28:     INT inc1;
        !            29:     INT inc2;
        !            30: } DELTAGEN;
        !            31: typedef DELTAGEN *PDELTAGEN;
        !            32: 
        !            33: 
        !            34: STATICFN VOID NEAR WorkPaint(HWND hwnd);
        !            35: STATICFN VOID WorkButtonDown(HWND hwnd, UINT msg, PPOINT ppt);
        !            36: STATICFN VOID WorkButtonMouseMove(HWND hwnd, UINT msg, PPOINT ppt);
        !            37: STATICFN VOID WorkButtonUp(HWND hwnd, UINT msg, PPOINT ppt);
        !            38: STATICFN VOID NEAR SnapPointToGrid(PPOINT ppt);
        !            39: STATICFN VOID DrawToPoint(HWND hwnd, PPOINT ppt, BOOL fBrush);
        !            40: STATICFN BOOL NEAR DeltaGenInit(PDELTAGEN pdg, INT x0, INT y0,
        !            41:     INT xf, INT yf, PINT px, PINT py);
        !            42: STATICFN BOOL NEAR DeltaGen(PDELTAGEN pdg, PINT px, PINT py);
        !            43: STATICFN VOID DrawPoint(HWND hwnd, PPOINT ppt, BOOL fBrush);
        !            44: STATICFN VOID NEAR RubberBandLine(BOOL fFirstTime);
        !            45: STATICFN VOID NEAR RectDPDraw(HWND hwnd);
        !            46: STATICFN VOID NEAR RubberBandRect(BOOL fFirstTime);
        !            47: STATICFN VOID NEAR CircleDPDraw(HWND hwnd);
        !            48: STATICFN VOID NEAR RubberBandCircle(BOOL fFirstTime);
        !            49: STATICFN VOID NEAR MarkHotSpotPosition(INT x, INT y);
        !            50: STATICFN VOID NEAR StartRubberBanding(HWND hwnd);
        !            51: STATICFN VOID NEAR EndRubberBanding(HWND hwnd);
        !            52: 
        !            53: 
        !            54: static BOOL fDrawing = FALSE;           // TRUE if mouse button is down.
        !            55: static BOOL fLeftButtonDown;            // TRUE if left button was pressed.
        !            56: static POINT ptStart;                   // Saves the starting point.
        !            57: static POINT ptEnd;                     // Saves the ending point.
        !            58: static POINT ptPrev;                    // Saves the previous point.
        !            59: static HDC hdcRubberBand;               // DC used during rubber banding.
        !            60: static BOOL fRubberBanding = FALSE;     // Tracking is in progress.
        !            61: 
        !            62: 
        !            63: 
        !            64: /****************************************************************************
        !            65:  * WorkWndProc
        !            66:  *                                                                          *
        !            67:  * purpose: Processes basic create and size and paint messages for the      *
        !            68:  *          workspace window.
        !            69:  *                                                                          *
        !            70:  ****************************************************************************/
        !            71: 
        !            72: WINDOWPROC WorkWndProc(
        !            73:     HWND hwnd,
        !            74:     UINT msg,
        !            75:     WPARAM wParam,
        !            76:     LPARAM lParam)
        !            77: {
        !            78:     LPCREATESTRUCT cs;
        !            79:     POINT pt;
        !            80: 
        !            81:     switch (msg) {
        !            82:         case WM_CREATE:
        !            83:             /* set up image variables */
        !            84:             cs = (LPCREATESTRUCT)lParam;
        !            85:             gcxWorkSpace = cs->cx;
        !            86:             gcyWorkSpace = cs->cy;
        !            87:             break;
        !            88: 
        !            89:         case WM_SIZE:
        !            90:             gcxWorkSpace = LOWORD(lParam);
        !            91:             gcyWorkSpace = HIWORD(lParam);
        !            92: 
        !            93:             break;
        !            94: 
        !            95:         case WM_PAINT:
        !            96:             WorkPaint(hwnd);
        !            97:             break;
        !            98: 
        !            99:         case WM_MOUSEMOVE:
        !           100:             ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
        !           101:             WorkButtonMouseMove(hwnd, msg, &pt);
        !           102:             break;
        !           103: 
        !           104:         case WM_RBUTTONDOWN:
        !           105:         case WM_LBUTTONDOWN:
        !           106:             ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
        !           107:             WorkButtonDown(hwnd, msg, &pt);
        !           108:             break;
        !           109: 
        !           110:         case WM_LBUTTONUP:
        !           111:         case WM_RBUTTONUP:
        !           112:             ((pt).x = ((*((POINTS *)&(lParam)))).x, (pt).y = ((*((POINTS *)&(lParam)))).y);
        !           113:             WorkButtonUp(hwnd, msg, &pt);
        !           114:             break;
        !           115: 
        !           116:         case WM_KEYDOWN:
        !           117:             switch (wParam) {
        !           118:                 case VK_ESCAPE:
        !           119:                     if (fDrawing) {
        !           120:                         if (fRubberBanding) {
        !           121:                             EndRubberBanding(hwnd);
        !           122:                             WorkUpdate();
        !           123:                         }
        !           124: 
        !           125:                         PropBarClearSize();
        !           126:                         ReleaseCapture();
        !           127:                         fDrawing = FALSE;
        !           128:                     }
        !           129: 
        !           130:                     break;
        !           131:             }
        !           132: 
        !           133:             break;
        !           134: 
        !           135:         default:
        !           136:             return DefWindowProc(hwnd, msg, wParam, lParam);
        !           137:     }
        !           138: 
        !           139:     return 0;
        !           140: }
        !           141: 
        !           142: 
        !           143: 
        !           144: /****************************************************************************
        !           145: * WorkPaint
        !           146: *
        !           147: * Handles WM_PAINT for the workspace window.
        !           148: *
        !           149: * History:
        !           150: *
        !           151: ****************************************************************************/
        !           152: 
        !           153: STATICFN VOID NEAR WorkPaint(    HWND hwnd)
        !           154: {
        !           155:     register INT i;
        !           156:     PAINTSTRUCT ps;
        !           157:     HCURSOR hcurOld;
        !           158:     HDC hdcTemp;
        !           159:     HBITMAP hbmTemp;
        !           160: 
        !           161:     hcurOld = SetCursor(hcurWait);
        !           162:     BeginPaint(hwnd, &ps);
        !           163: 
        !           164:     /*
        !           165:      * Do they want a grid and is there enough room to show the lines?
        !           166:      */
        !           167:     if (gfGrid && gZoomFactor > 1) {
        !           168:         /*
        !           169:          * Stretch the bits onto a temporary DC.
        !           170:          */
        !           171:         hdcTemp = CreateCompatibleDC(ghdcImage);
        !           172:         hbmTemp = CreateCompatibleBitmap(ghdcImage,
        !           173:                 gcxWorkSpace, gcyWorkSpace);
        !           174:         SelectObject(hdcTemp, hbmTemp);
        !           175:         StretchBlt(hdcTemp, 0, 0, gcxWorkSpace, gcyWorkSpace,
        !           176:                 ghdcImage, 0, 0, gcxImage, gcyImage, SRCCOPY);
        !           177: 
        !           178:         /*
        !           179:          * Draw the grid lines on the temp DC.
        !           180:          */
        !           181:         for (i = gZoomFactor - 1; i < gcxWorkSpace; i += gZoomFactor)
        !           182:             PatBlt(hdcTemp, i, 0, 1, gcyWorkSpace, BLACKNESS);
        !           183:         for (i = gZoomFactor - 1; i < gcyWorkSpace; i += gZoomFactor)
        !           184:             PatBlt(hdcTemp, 0, i, gcxWorkSpace, 1, BLACKNESS);
        !           185: 
        !           186:         /*
        !           187:          * Copy the bits to the screen.
        !           188:          */
        !           189:         BitBlt(ps.hdc, 0, 0, gcxWorkSpace, gcyWorkSpace,
        !           190:                 hdcTemp, 0, 0, SRCCOPY);
        !           191: 
        !           192:         DeleteDC(hdcTemp);
        !           193:         DeleteObject(hbmTemp);
        !           194:     }
        !           195:     else {
        !           196:         /*
        !           197:          * No grid.  Just stretch the image to the screen.
        !           198:          */
        !           199:         StretchBlt(ps.hdc, 0, 0, gcxWorkSpace, gcyWorkSpace,
        !           200:                 ghdcImage, 0, 0, gcxImage, gcyImage, SRCCOPY);
        !           201:     }
        !           202: 
        !           203:     EndPaint(hwnd, &ps);
        !           204:     SetCursor(hcurOld);
        !           205: }
        !           206: 
        !           207: 
        !           208: 
        !           209: /****************************************************************************
        !           210: * WorkUpdate
        !           211: *
        !           212: * This function updates the workspace window.
        !           213: *
        !           214: * History:
        !           215: *
        !           216: ****************************************************************************/
        !           217: 
        !           218: VOID WorkUpdate(VOID)
        !           219: {
        !           220:     /*
        !           221:      * Invalidate the workspace window.  Because the image will be
        !           222:      * be blt'ed onto it, we do not need to force the background to
        !           223:      * be cleared first.
        !           224:      */
        !           225:     InvalidateRect(ghwndWork, NULL, FALSE);
        !           226: }
        !           227: 
        !           228: 
        !           229: 
        !           230: /****************************************************************************
        !           231: * WorkReset
        !           232: *
        !           233: * This function reset the workspace window.  It should be called
        !           234: * any time that a new image is loaded (because the size could
        !           235: * change) or the size of the main window changes (because the
        !           236: * workspace window needs to be resized to fit).
        !           237: *
        !           238: * History:
        !           239: *
        !           240: ****************************************************************************/
        !           241: 
        !           242: VOID WorkReset(VOID)
        !           243: {
        !           244:     RECT rcClient;
        !           245:     INT cx;
        !           246:     INT cy;
        !           247:     INT xScale;
        !           248:     INT yScale;
        !           249:     INT cxBorder;
        !           250:     INT cyBorder;
        !           251: 
        !           252:     cxBorder = GetSystemMetrics(SM_CXBORDER);
        !           253:     cyBorder = GetSystemMetrics(SM_CYBORDER);
        !           254: 
        !           255:     if (!gcxImage || !gcyImage) {
        !           256:         gZoomFactor = 1;
        !           257:     }
        !           258:     else {
        !           259:         GetClientRect(ghwndMain, &rcClient);
        !           260:         cx = rcClient.right - (2 * PALETTEMARGIN) - (2 * cxBorder);
        !           261:         cy = rcClient.bottom - (2 * PALETTEMARGIN) - (2 * cyBorder) -
        !           262:                 gcyPropBar;
        !           263: 
        !           264:         xScale = cx / gcxImage;
        !           265:         yScale = cy / gcyImage;
        !           266: 
        !           267:         if (xScale > 0 && yScale > 0)
        !           268:             gZoomFactor = min(xScale, yScale);
        !           269:         else
        !           270:             gZoomFactor = 1;
        !           271:     }
        !           272: 
        !           273:     SetWindowPos(ghwndWork, NULL,
        !           274:             PALETTEMARGIN, PALETTEMARGIN + gcyPropBar,
        !           275:             (gZoomFactor * gcxImage) + (2 * cxBorder),
        !           276:             (gZoomFactor * gcyImage) + (2 * cyBorder),
        !           277:             SWP_NOACTIVATE | SWP_NOZORDER);
        !           278:     WorkUpdate();
        !           279: }
        !           280: 
        !           281: 
        !           282: 
        !           283: /************************************************************************
        !           284: * WorkButtonDown
        !           285: *
        !           286: *
        !           287: *
        !           288: * Arguments:
        !           289: *
        !           290: * History:
        !           291: *
        !           292: ************************************************************************/
        !           293: 
        !           294: STATICFN VOID WorkButtonDown(
        !           295:     HWND hwnd,
        !           296:     UINT msg,
        !           297:     PPOINT ppt)
        !           298: {
        !           299:     /*
        !           300:      * If the other button is already down, just ignore this one.
        !           301:      */
        !           302:     if (fDrawing)
        !           303:         return;
        !           304: 
        !           305:     SetFocus(hwnd);
        !           306:     fLeftButtonDown = (msg == WM_LBUTTONDOWN) ? TRUE : FALSE;
        !           307: 
        !           308:     SnapPointToGrid(ppt);
        !           309:     ptStart = ptPrev = ptEnd = *ppt;
        !           310: 
        !           311:     if (fLeftButtonDown) {
        !           312:         ghbrDraw = ghbrLeft;
        !           313:         ghbrDrawSolid = ghbrLeftSolid;
        !           314:         gfDrawMode = gfModeLeft;
        !           315:         ghpenDraw = ghpenLeft;
        !           316:     }
        !           317:     else {
        !           318:         ghbrDraw = ghbrRight;
        !           319:         ghbrDrawSolid = ghbrRightSolid;
        !           320:         gfDrawMode = gfModeRight;
        !           321:         ghpenDraw = ghpenRight;
        !           322:     }
        !           323: 
        !           324:     /*
        !           325:      * If this tool draws on the down-click, update the undo
        !           326:      * buffer now.
        !           327:      */
        !           328:     if (gaTools[gCurTool].fDrawOnDown)
        !           329:         ImageUpdateUndo();
        !           330: 
        !           331:     SetCapture(ghwndWork);
        !           332:     fDrawing = TRUE;
        !           333: 
        !           334:     (*gpfnDrawProc)(hwnd, msg, *ppt);
        !           335: 
        !           336:     PropBarSetSize(ptStart, ptEnd);
        !           337: }
        !           338: 
        !           339: 
        !           340: 
        !           341: /************************************************************************
        !           342: * WorkButtonMouseMove
        !           343: *
        !           344: *
        !           345: *
        !           346: * Arguments:
        !           347: *
        !           348: * History:
        !           349: *
        !           350: ************************************************************************/
        !           351: 
        !           352: STATICFN VOID WorkButtonMouseMove(
        !           353:     HWND hwnd,
        !           354:     UINT msg,
        !           355:     PPOINT ppt)
        !           356: {
        !           357:     static POINT ptNZLast;  // Saves the last point (non-zoomed).
        !           358:     POINT ptNZ;
        !           359: 
        !           360:     SetCursor(gaTools[gCurTool].hcur);
        !           361: 
        !           362:     SnapPointToGrid(ppt);
        !           363: 
        !           364:     /*
        !           365:      * Calculate the point as it would be on the actual image
        !           366:      * (non-zoomed).
        !           367:      */
        !           368:     ptNZ.x = ppt->x / gZoomFactor;
        !           369:     ptNZ.y = ppt->y / gZoomFactor;
        !           370: 
        !           371:     /*
        !           372:      * Only call the drawing proc if the point changed enough to
        !           373:      * jump over a zoomed pixels width (it jumped a grid square).
        !           374:      * This prevents calling the DrawProc for a mouse move of
        !           375:      * a single pixel (unless the zoom factor is 1, of course).
        !           376:      */
        !           377:     if (ptNZLast.x != ptNZ.x || ptNZLast.y != ptNZ.y) {
        !           378:         ptEnd = *ppt;
        !           379:         (*gpfnDrawProc)(hwnd, msg, *ppt);
        !           380:         ptPrev = ptEnd;
        !           381: 
        !           382:         PropBarSetPos(ptNZ.x, ptNZ.y);
        !           383: 
        !           384:         if (fDrawing)
        !           385:             PropBarSetSize(ptStart, ptEnd);
        !           386: 
        !           387:         ptNZLast = ptNZ;
        !           388:     }
        !           389: }
        !           390: 
        !           391: 
        !           392: 
        !           393: /************************************************************************
        !           394: * WorkButtonUp
        !           395: *
        !           396: *
        !           397: *
        !           398: * Arguments:
        !           399: *
        !           400: * History:
        !           401: *
        !           402: ************************************************************************/
        !           403: 
        !           404: STATICFN VOID WorkButtonUp(
        !           405:     HWND hwnd,
        !           406:     UINT msg,
        !           407:     PPOINT ppt)
        !           408: {
        !           409:     /*
        !           410:      * Pass this on to the draw procs, but only if we are still drawing.
        !           411:      * The drawing could have been cancelled by the Escape key, in
        !           412:      * which case we just ignore the button up message.
        !           413:      */
        !           414:     if (fDrawing) {
        !           415:         SnapPointToGrid(ppt);
        !           416: 
        !           417:         /*
        !           418:          * If this tool draws on the up-click, update the undo
        !           419:          * buffer now.
        !           420:          */
        !           421:         if (gaTools[gCurTool].fDrawOnUp)
        !           422:             ImageUpdateUndo();
        !           423: 
        !           424:         (*gpfnDrawProc)(hwnd, msg, *ppt);
        !           425: 
        !           426:         ReleaseCapture();
        !           427:         fDrawing = FALSE;
        !           428:     }
        !           429: }
        !           430: 
        !           431: 
        !           432: 
        !           433: /******************************************************************************
        !           434:  * SnapPointToGrid
        !           435:  *
        !           436:  * PURPOSE : Snap the current mouse coordinate to the nearest grid intersection.
        !           437:  *
        !           438:  * PARAMS  : PPOINT ppt : current mouse coordinates
        !           439:  *
        !           440:  *****************************************************************************/
        !           441: 
        !           442: STATICFN VOID NEAR SnapPointToGrid(
        !           443:     PPOINT ppt)
        !           444: {
        !           445:     /*
        !           446:      * Scale the point down (this gridizes it at the same time).
        !           447:      */
        !           448:     ppt->x = ppt->x / gZoomFactor;
        !           449:     ppt->y = ppt->y / gZoomFactor;
        !           450: 
        !           451:     /*
        !           452:      * Limit the point to within the image.
        !           453:      */
        !           454:     if (ppt->x < 0)
        !           455:         ppt->x = 0;
        !           456: 
        !           457:     if (ppt->y < 0)
        !           458:         ppt->y = 0;
        !           459: 
        !           460:     if (ppt->x >= gcxImage)
        !           461:         ppt->x = gcxImage - 1;
        !           462: 
        !           463:     if (ppt->y >= gcyImage)
        !           464:         ppt->y = gcyImage - 1;
        !           465: 
        !           466:     /*
        !           467:      * Finally, scale it back up to the workspace window size.
        !           468:      */
        !           469:     ppt->x *= gZoomFactor;
        !           470:     ppt->y *= gZoomFactor;
        !           471: }
        !           472: 
        !           473: 
        !           474: 
        !           475: /************************************************************************
        !           476: * PencilDP
        !           477: *
        !           478: *
        !           479: *
        !           480: * Arguments:
        !           481: *
        !           482: * History:
        !           483: *
        !           484: ************************************************************************/
        !           485: 
        !           486: VOID PencilDP(
        !           487:     HWND hwnd,
        !           488:     UINT msg,
        !           489:     POINT ptNew)
        !           490: {
        !           491:     switch (msg) {
        !           492:         case WM_LBUTTONDOWN:
        !           493:         case WM_RBUTTONDOWN:
        !           494:             DrawPoint(hwnd, &ptNew, FALSE);
        !           495:             break;
        !           496: 
        !           497:         case WM_MOUSEMOVE:
        !           498:             if (fDrawing)
        !           499:                 DrawToPoint(hwnd, &ptNew, FALSE);
        !           500: 
        !           501:             break;
        !           502:     }
        !           503: }
        !           504: 
        !           505: 
        !           506: 
        !           507: /************************************************************************
        !           508: * BrushDP
        !           509: *
        !           510: *
        !           511: *
        !           512: * Arguments:
        !           513: *
        !           514: * History:
        !           515: *
        !           516: ************************************************************************/
        !           517: 
        !           518: VOID BrushDP(
        !           519:     HWND hwnd,
        !           520:     UINT msg,
        !           521:     POINT ptNew)
        !           522: {
        !           523:     switch (msg) {
        !           524:         case WM_LBUTTONDOWN:
        !           525:         case WM_RBUTTONDOWN:
        !           526:             DrawPoint(hwnd, &ptNew, TRUE);
        !           527:             break;
        !           528: 
        !           529:         case WM_MOUSEMOVE:
        !           530:             if (fDrawing)
        !           531:                 DrawToPoint(hwnd, &ptNew, TRUE);
        !           532: 
        !           533:             break;
        !           534:     }
        !           535: }
        !           536: 
        !           537: 
        !           538: 
        !           539: /************************************************************************
        !           540: * DrawToPoint
        !           541: *
        !           542: * This function draws from the previous point to the given point.
        !           543: * This includes all points between.
        !           544: *
        !           545: * The global ptPrev must have been initialized prior to the  first time
        !           546: * this function is called during a drawing operation.
        !           547: *
        !           548: * Arguments:
        !           549: *
        !           550: * History:
        !           551: *
        !           552: ************************************************************************/
        !           553: 
        !           554: STATICFN VOID DrawToPoint(
        !           555:     HWND hwnd,
        !           556:     PPOINT ppt,
        !           557:     BOOL fBrush)
        !           558: {
        !           559:     DELTAGEN dg;
        !           560:     BOOL fContinue;
        !           561:     POINT pt;
        !           562:     INT x;
        !           563:     INT y;
        !           564: 
        !           565:     x = ppt->x / gZoomFactor;
        !           566:     y = ppt->y / gZoomFactor;
        !           567:     DeltaGenInit(&dg, ptPrev.x / gZoomFactor, ptPrev.y / gZoomFactor,
        !           568:             ppt->x / gZoomFactor, ppt->y / gZoomFactor, &x, &y);
        !           569:     do {
        !           570:         pt.x = x * gZoomFactor;
        !           571:         pt.y = y * gZoomFactor;
        !           572:         DrawPoint(hwnd, &pt, fBrush);
        !           573:         fContinue = DeltaGen(&dg, &x, &y);
        !           574:     } while (fContinue);
        !           575: }
        !           576: 
        !           577: 
        !           578: 
        !           579: /***************************** Public  Function ****************************\
        !           580: * DeltaGenInit
        !           581: *
        !           582: * This routine initializes the pdg, px and py in preparation for using
        !           583: * DeltaGen().  Returns fContinue.
        !           584: *
        !           585: * Algorithm derived from BRESENHAM line algorighm on p. 435 of Fund. of
        !           586: * interactive computer graphics, Foley/VanDam, addison-wesley 1983.
        !           587: *
        !           588: * History:
        !           589: *       3/7/89  sanfords        created
        !           590: \***************************************************************************/
        !           591: 
        !           592: STATICFN BOOL NEAR DeltaGenInit(
        !           593:     PDELTAGEN pdg,
        !           594:     INT x0,
        !           595:     INT y0,
        !           596:     INT xf,
        !           597:     INT yf,
        !           598:     PINT px,
        !           599:     PINT py)
        !           600: {
        !           601:     INT nT;
        !           602: 
        !           603:     pdg->xf = xf;
        !           604:     pdg->yf = yf;
        !           605: 
        !           606:     if (x0 == xf && y0 == yf)
        !           607:         return FALSE;
        !           608: 
        !           609:     if (xf >= x0)
        !           610:         pdg->incx = 1;
        !           611:     else
        !           612:         pdg->incx = -1;
        !           613: 
        !           614:     if (yf >= y0)        pdg->incy = 1;
        !           615:     else
        !           616:         pdg->incy = -1;
        !           617: 
        !           618:     pdg->dx = (xf - x0) * pdg->incx;
        !           619:     pdg->dy = (yf - y0) * pdg->incy;
        !           620: 
        !           621:     if (pdg->dy > pdg->dx) {
        !           622:         nT = pdg->dy;
        !           623:         pdg->dy = pdg->dx;
        !           624:         pdg->dx = nT;
        !           625:         nT = pdg->incx;
        !           626:         pdg->incx = pdg->incy;
        !           627:         pdg->incy = nT;
        !           628:         pdg->fSwap = TRUE;
        !           629:     }
        !           630:     else {
        !           631:         pdg->fSwap = FALSE;
        !           632:     }
        !           633: 
        !           634:     pdg->inc1 = pdg->dy * 2;
        !           635:     pdg->inc2 = (pdg->dy - pdg->dx) * 2;
        !           636:     pdg->d = pdg->inc1 - pdg->dx;
        !           637: 
        !           638:     pdg->xf = xf;
        !           639:     pdg->yf = yf;
        !           640: 
        !           641:     *px = x0;
        !           642:     *py = y0;
        !           643: 
        !           644:     return TRUE;
        !           645: }
        !           646: 
        !           647: 
        !           648: 
        !           649: /***************************** Public  Function ****************************\
        !           650: * DeltaGen
        !           651: *
        !           652: * This routine generates the next coordinates for px,py assuming that this
        !           653: * point is proceeding linearly from x0,y0 to xf, yf.  It returns FALSE only
        !           654: * if *px == xf and *py == yf on entry.  (ie returns fContinue)  pdg should
        !           655: * have been previously set by DeltaGenInit().
        !           656: *
        !           657: * Algorithm derived from BRESENHAM line algorighm on p. 435 of Fund. of
        !           658: * interactive computer graphics, Foley/VanDam, addison-wesley 1983.
        !           659: *
        !           660: * History:
        !           661: *       3/7/89  sanfords        created
        !           662: \***************************************************************************/
        !           663: 
        !           664: STATICFN BOOL NEAR DeltaGen(
        !           665:     PDELTAGEN pdg,
        !           666:     PINT px,
        !           667:     PINT py)
        !           668: {
        !           669:     PINT pnT;
        !           670: 
        !           671:     if ((*px == pdg->xf) && (*py == pdg->yf))
        !           672:         return FALSE;
        !           673: 
        !           674:     if (pdg->fSwap) {
        !           675:         pnT = px;
        !           676:         px = py;
        !           677:         py = pnT;
        !           678:     }
        !           679: 
        !           680:     *px += pdg->incx;
        !           681:     if (pdg->d < 0) {
        !           682:         pdg->d += pdg->inc1;
        !           683:     }
        !           684:     else {
        !           685:         *py += pdg->incy;
        !           686:         pdg->d += pdg->inc2;
        !           687:     }
        !           688: 
        !           689:     return TRUE;
        !           690: }
        !           691: 
        !           692: 
        !           693: 
        !           694: /************************************************************************
        !           695: * DrawPoint
        !           696: *
        !           697: * This function is called to draw a point on the image.  It is used
        !           698: * by the Pencil and Brush tools.
        !           699: *
        !           700: * Arguments:
        !           701: *
        !           702: * History:
        !           703: *
        !           704: ************************************************************************/
        !           705: 
        !           706: STATICFN VOID DrawPoint(    HWND hwnd,
        !           707:     PPOINT ppt,
        !           708:     BOOL fBrush)
        !           709: {
        !           710:     HDC hDC;
        !           711:     HBRUSH hbrOld;
        !           712:     INT wx;
        !           713:     INT wy;
        !           714:     INT iStartY;
        !           715:     INT wStep;
        !           716:     INT i;
        !           717:     INT j;
        !           718:     INT nBrushSize;
        !           719: 
        !           720:     if (ppt->x < 0 || ppt->y < 0)
        !           721:         return;
        !           722: 
        !           723:     hDC = GetDC(hwnd);
        !           724: 
        !           725:     /*
        !           726:      * If this is a point from the brush tool, use the current
        !           727:      * brush width.  Otherwise, draw a single pixel point.
        !           728:      */
        !           729:     if (fBrush)
        !           730:         nBrushSize = gnBrushSize;
        !           731:     else
        !           732:         nBrushSize = 1;
        !           733: 
        !           734:     /*     * Determine some starting factors, then draw the point in
        !           735:      * the workspace window.
        !           736:      */
        !           737:     hbrOld = SelectObject(hDC, ghbrDrawSolid);
        !           738:     wy = iStartY = ppt->y - (ppt->y % gZoomFactor)
        !           739:             -(nBrushSize / 2) * gZoomFactor;
        !           740:     wx = ppt->x - (ppt->x % gZoomFactor)
        !           741:             -(nBrushSize / 2) * gZoomFactor;
        !           742:     wStep = gZoomFactor;
        !           743: 
        !           744:     if (gfGrid && gZoomFactor > 1)
        !           745:         wStep -= 1;
        !           746: 
        !           747:     for (i = 0; i < nBrushSize; i++, wx += gZoomFactor) {
        !           748:         wy = iStartY;
        !           749:         for (j = 0; j < nBrushSize; j++, wy += gZoomFactor)
        !           750:             PatBlt(hDC, wx, wy, wStep, wStep, PATCOPY);
        !           751:     }
        !           752: 
        !           753:     SelectObject(hDC, hbrOld);
        !           754:     ReleaseDC(hwnd, hDC);
        !           755: 
        !           756:     /*
        !           757:      * Set the point in the bitmap directly as an optimization.
        !           758:      */
        !           759:     wx = ppt->x / gZoomFactor;
        !           760:     wy = ppt->y / gZoomFactor;
        !           761:     if (wx < gcxImage && wy < gcyImage) {
        !           762:         hbrOld = SelectObject(ghdcImage, ghbrDrawSolid);
        !           763:         PatBlt(ghdcImage, wx - nBrushSize / 2, wy - nBrushSize / 2,
        !           764:                 nBrushSize, nBrushSize, PATCOPY);
        !           765: 
        !           766:         if (giType != FT_BITMAP) {
        !           767:             /*
        !           768:              * If in color mode, set the mask bits black.  Otherwise make
        !           769:              * them white.
        !           770:              */
        !           771:             PatBlt(ghdcANDMask, wx - nBrushSize / 2, wy - nBrushSize / 2,
        !           772:                     nBrushSize, nBrushSize,
        !           773:                     (gfDrawMode == MODE_COLOR) ? BLACKNESS : WHITENESS);
        !           774:         }
        !           775: 
        !           776:         SelectObject(ghdcImage, hbrOld);
        !           777: 
        !           778:         /*
        !           779:          * Draw the point in the view window directly as an optimization.
        !           780:          */
        !           781:         if (ghwndView)
        !           782:             ViewSetPixel(wx, wy, nBrushSize);
        !           783:     }
        !           784: 
        !           785:     /*
        !           786:      * Mark the image as changed.
        !           787:      */
        !           788:     fImageDirty = TRUE;
        !           789: }
        !           790: 
        !           791: 
        !           792: 
        !           793: /************************************************************************
        !           794: * PickDP
        !           795: *
        !           796: * Drawing proc that selects a rectangular portion of the image.
        !           797: * It updates the global picking rectangle.
        !           798: *
        !           799: * Arguments:
        !           800: *
        !           801: * History:
        !           802: *
        !           803: ************************************************************************/
        !           804: 
        !           805: VOID PickDP(
        !           806:     HWND hwnd,
        !           807:     UINT msg,
        !           808:     POINT ptNew)
        !           809: {
        !           810:     POINT ptTL;         // Top-Left point.
        !           811:     POINT ptBR;         // Bottom-Right point
        !           812: 
        !           813:     switch (msg) {
        !           814:         case WM_LBUTTONDOWN:
        !           815:         case WM_RBUTTONDOWN:
        !           816:             /* erase any previous ghost rectangle */
        !           817:             WorkUpdate();
        !           818:             UpdateWindow(ghwndWork);
        !           819: 
        !           820:             /*
        !           821:              * Initialize the pick rectangle to cover the entire screen.
        !           822:              */
        !           823:             PickSetRect(0, 0, gcxImage - 1, gcyImage - 1);
        !           824: 
        !           825:             StartRubberBanding(hwnd);
        !           826:             RubberBandRect(TRUE);
        !           827:             break;
        !           828: 
        !           829:         case WM_MOUSEMOVE:
        !           830:             if (fRubberBanding)
        !           831:                 RubberBandRect(FALSE);
        !           832: 
        !           833:             break;
        !           834: 
        !           835:         case WM_LBUTTONUP:
        !           836:         case WM_RBUTTONUP:
        !           837:             EndRubberBanding(hwnd);
        !           838: 
        !           839:             /*
        !           840:              * Flip the points (if needed) and scale down.
        !           841:              */
        !           842:             ptTL = ptStart;
        !           843:             ptBR = ptEnd;
        !           844:             NormalizePoints(&ptTL, &ptBR);
        !           845:             ptTL.x /= gZoomFactor;
        !           846:             ptTL.y /= gZoomFactor;
        !           847:             ptBR.x /= gZoomFactor;
        !           848:             ptBR.y /= gZoomFactor;
        !           849: 
        !           850:             PickSetRect(ptTL.x, ptTL.y, ptBR.x, ptBR.y);
        !           851: 
        !           852:             break;
        !           853:     }
        !           854: }
        !           855: 
        !           856: 
        !           857: 
        !           858: /******************************************************************************
        !           859:  * VOID LineDP(hwnd, msg, ptNew)
        !           860:  *
        !           861:  * PURPOSE: Draw a straight line according to tracking line.
        !           862:  *
        !           863:  * PARAMS : HWND   hwnd : handle to dest. DC
        !           864:  *          unsigned msg  : Upper left corner of rect;
        !           865:  *          POINT  ptNew   : end pt. of line
        !           866:  *
        !           867:  * SIDE EFFECTS: may change bits in image DC
        !           868:  *
        !           869:  *****************************************************************************/
        !           870: 
        !           871: VOID LineDP(
        !           872:     HWND hwnd,
        !           873:     UINT msg,
        !           874:     POINT ptNew)
        !           875: {
        !           876:     INT sx;
        !           877:     INT sy;
        !           878:     INT ex;
        !           879:     INT ey;
        !           880:     HPEN hpen;
        !           881:     HPEN hpenOld;
        !           882:     HBRUSH hbrOld;
        !           883: 
        !           884:     switch (msg) {
        !           885:         case WM_RBUTTONDOWN:
        !           886:         case WM_LBUTTONDOWN:
        !           887:             StartRubberBanding(hwnd);
        !           888:             RubberBandLine(TRUE);
        !           889:             break;
        !           890: 
        !           891:         case WM_MOUSEMOVE:
        !           892:             if (fRubberBanding)
        !           893:                 RubberBandLine(FALSE);
        !           894: 
        !           895:             break;
        !           896: 
        !           897:         case WM_LBUTTONUP:
        !           898:         case WM_RBUTTONUP:
        !           899:             EndRubberBanding(hwnd);
        !           900: 
        !           901:             /* transform selected coordinates to those of actual image */
        !           902:             sx = ptStart.x / gZoomFactor;
        !           903:             sy = ptStart.y / gZoomFactor;
        !           904:             ex = ptEnd.x / gZoomFactor;
        !           905:             ey = ptEnd.y / gZoomFactor;
        !           906: 
        !           907:             hpenOld = SelectObject(ghdcImage, ghpenDraw);
        !           908:             MoveToEx(ghdcImage, sx, sy, NULL);
        !           909:             LineTo(ghdcImage, ex, ey);
        !           910:             SelectObject(ghdcImage, hpenOld);
        !           911: 
        !           912:             if (giType != FT_BITMAP) {
        !           913:                 /* for icons and cursors draw the line on the AND DC (memory)
        !           914:                  * in black (if in color mode) or white (otherwise)
        !           915:                  */
        !           916:                 hpen = CreatePen(PS_INSIDEFRAME, 1,
        !           917:                         (gfDrawMode == MODE_COLOR) ? RGB_BLACK : RGB_WHITE);
        !           918:                 hpenOld = SelectObject(ghdcANDMask, hpen);
        !           919:                 hbrOld = SelectObject(ghdcANDMask, GetStockObject(NULL_BRUSH));
        !           920:                 MoveToEx(ghdcANDMask, sx, sy, NULL);
        !           921:                 LineTo(ghdcANDMask, ex, ey);
        !           922:                 SelectObject(ghdcANDMask, hbrOld);
        !           923:                 SelectObject(ghdcANDMask, hpenOld);
        !           924:                 DeleteObject(hpen);
        !           925:             }
        !           926: 
        !           927:             /*
        !           928:              * Because the LineTo function does not draw the ending
        !           929:              * point, we must do it manually here.
        !           930:              */
        !           931:             DrawPoint(hwnd, &ptEnd, FALSE);
        !           932: 
        !           933:             fImageDirty = TRUE;
        !           934: 
        !           935:             ViewUpdate();
        !           936: 
        !           937:             break;
        !           938:     }
        !           939: }
        !           940: 
        !           941: 
        !           942: 
        !           943: /************************************************************************
        !           944: * RubberBandLine
        !           945: *
        !           946: * This function erases the old line and draws the new tracking line
        !           947: * when using the "Line" tool.
        !           948: *
        !           949: * Arguments:
        !           950: *   BOOL fFirstTime - TRUE if starting to track the line (it doesn't
        !           951: *                     need to erase the old line).
        !           952: *
        !           953: * History:
        !           954: *
        !           955: ************************************************************************/
        !           956: 
        !           957: STATICFN VOID NEAR RubberBandLine(
        !           958:     BOOL fFirstTime)
        !           959: {
        !           960:     INT nOffset;
        !           961: 
        !           962:     /*
        !           963:      * Set the raster-op to invert.
        !           964:      */
        !           965:     SetROP2(hdcRubberBand, R2_NOT);
        !           966: 
        !           967:     /*
        !           968:      * If we are magnifying the image at all, the line needs to be
        !           969:      * slightly offset so that it will be draw exactly in between
        !           970:      * the grid lines.
        !           971:      */
        !           972:     if (gZoomFactor > 1)
        !           973:         nOffset = -1;
        !           974:     else
        !           975:         nOffset = 0;
        !           976: 
        !           977:     if (!fFirstTime) {
        !           978:         /*
        !           979:          * Erase the old line.
        !           980:          */
        !           981:         
        !           982: MoveToEx(hdcRubberBand, ptStart.x + (gZoomFactor / 2) + nOffset, ptStart.y + (gZoomFactor / 2) + nOffset, NULL);
        !           983:         LineTo(hdcRubberBand, ptPrev.x + (gZoomFactor / 2) + nOffset,
        !           984:                 ptPrev.y + (gZoomFactor / 2) + nOffset);
        !           985:     }
        !           986: 
        !           987:     /*
        !           988:      * Draw the new one.
        !           989:      */
        !           990:     
        !           991: MoveToEx(hdcRubberBand, ptStart.x + (gZoomFactor / 2) + nOffset, ptStart.y + (gZoomFactor / 2) + nOffset, NULL);
        !           992:     LineTo(hdcRubberBand, ptEnd.x + (gZoomFactor / 2) + nOffset,
        !           993:             ptEnd.y + (gZoomFactor / 2) + nOffset);
        !           994: }
        !           995: 
        !           996: 
        !           997: 
        !           998: /******************************************************************************
        !           999:  * VOID RectDP(hwnd, msg, ptNew)
        !          1000:  *
        !          1001:  * PURPOSE: Draw a rectangle (filled/hollow) in the area specified
        !          1002:  *
        !          1003:  * PARAMS : HWND   hwnd : handle to dest. DC
        !          1004:  *          WORD   msg  :
        !          1005:  *          POINT  ptNew   : end pt. of line
        !          1006:  *
        !          1007:  * SIDE EFFECTS: may change bits in image DC
        !          1008:  *
        !          1009:  *****************************************************************************/
        !          1010: 
        !          1011: VOID RectDP(
        !          1012:     HWND hwnd,
        !          1013:     UINT msg,
        !          1014:     POINT ptNew)
        !          1015: {
        !          1016:     switch (msg) {
        !          1017:         case WM_RBUTTONDOWN:
        !          1018:         case WM_LBUTTONDOWN:
        !          1019:             StartRubberBanding(hwnd);
        !          1020:             RubberBandRect(TRUE);
        !          1021:             break;
        !          1022: 
        !          1023:         case WM_MOUSEMOVE:
        !          1024:             if (fRubberBanding)
        !          1025:                 RubberBandRect(FALSE);
        !          1026: 
        !          1027:             break;
        !          1028: 
        !          1029:         case WM_LBUTTONUP:
        !          1030:         case WM_RBUTTONUP:
        !          1031:             RectDPDraw(hwnd);
        !          1032:             break;
        !          1033:     }
        !          1034: }
        !          1035: 
        !          1036: 
        !          1037: 
        !          1038: /************************************************************************
        !          1039: * RectDPDraw
        !          1040: *
        !          1041: * Does the final drawing of a rectangle when using the Rectangle tool.
        !          1042: *
        !          1043: * Arguments:
        !          1044: *   HWND hwnd - Window handle to the workspace.
        !          1045: *
        !          1046: * History:
        !          1047: *
        !          1048: ************************************************************************/
        !          1049: 
        !          1050: STATICFN VOID NEAR RectDPDraw(
        !          1051:     HWND hwnd)
        !          1052: {
        !          1053:     POINT ptTL;         // Top-Left point.
        !          1054:     POINT ptBR;         // Bottom-Right point
        !          1055:     HBRUSH hbr;
        !          1056:     HBRUSH hbrOld;
        !          1057:     HPEN hpen;
        !          1058:     HPEN hpenOld;
        !          1059:     INT nOutset;
        !          1060: 
        !          1061:     EndRubberBanding(hwnd);
        !          1062: 
        !          1063:     /*
        !          1064:      * Flip the points (if needed) and scale down.
        !          1065:      */
        !          1066:     ptTL = ptStart;
        !          1067:     ptBR = ptEnd;
        !          1068:     NormalizePoints(&ptTL, &ptBR);
        !          1069:     ptTL.x /= gZoomFactor;
        !          1070:     ptTL.y /= gZoomFactor;
        !          1071:     ptBR.x /= gZoomFactor;
        !          1072:     ptBR.y /= gZoomFactor;
        !          1073: 
        !          1074:     if (gCurTool == TOOL_RECT) {
        !          1075:         hpen = ghpenDraw;
        !          1076:         hbr = GetStockObject(NULL_BRUSH);
        !          1077:         nOutset = 1;
        !          1078:     }
        !          1079:     else {
        !          1080:         hpen = GetStockObject(NULL_PEN);
        !          1081:         hbr = ghbrDraw;
        !          1082:         nOutset = 2;
        !          1083:     }
        !          1084: 
        !          1085:     hpenOld = SelectObject(ghdcImage, hpen);
        !          1086:     hbrOld = SelectObject(ghdcImage, hbr);
        !          1087:     Rectangle(ghdcImage, ptTL.x, ptTL.y,
        !          1088:             ptBR.x + nOutset, ptBR.y + nOutset);
        !          1089:     SelectObject(ghdcImage, hpenOld);
        !          1090:     SelectObject(ghdcImage, hbrOld);
        !          1091: 
        !          1092:     if (giType != FT_BITMAP) {
        !          1093:         /* for icons and cursors draw the shape on the AND DC (memory)
        !          1094:          * in black (if in color mode) or white (otherwise)
        !          1095:          */
        !          1096:         if (gCurTool == TOOL_RECT) {
        !          1097:             hpen = CreatePen(PS_INSIDEFRAME, 1,
        !          1098:                     (gfDrawMode == MODE_COLOR) ? RGB_BLACK : RGB_WHITE);
        !          1099:             hbr = GetStockObject(NULL_BRUSH);
        !          1100:         }
        !          1101:         else {
        !          1102:             hpen = GetStockObject(NULL_PEN);
        !          1103:             hbr = GetStockObject((gfDrawMode == MODE_COLOR) ?
        !          1104:                     BLACK_BRUSH : WHITE_BRUSH);
        !          1105:         }
        !          1106: 
        !          1107:         hpenOld = SelectObject(ghdcANDMask, hpen);
        !          1108:         hbrOld = SelectObject(ghdcANDMask, hbr);
        !          1109:         Rectangle(ghdcANDMask, ptTL.x, ptTL.y,
        !          1110:                 ptBR.x + nOutset, ptBR.y + nOutset);
        !          1111:         SelectObject(ghdcANDMask, hpenOld);
        !          1112:         SelectObject(ghdcANDMask, hbrOld);
        !          1113: 
        !          1114:         if (gCurTool == TOOL_RECT)
        !          1115:             DeleteObject(hpen);
        !          1116:     }
        !          1117: 
        !          1118:     fImageDirty = TRUE;
        !          1119: 
        !          1120:     ViewUpdate();
        !          1121: }
        !          1122: 
        !          1123: 
        !          1124: 
        !          1125: /******************************************************************************
        !          1126:  * VOID PASCAL RubberBandRect()
        !          1127:  *
        !          1128:  * PURPOSE: Draw rubberbanding rect.
        !          1129:  *
        !          1130:  * PARAMS : HANDLE hDst : handle to dest. DC
        !          1131:  *
        !          1132:  *****************************************************************************/
        !          1133: 
        !          1134: STATICFN VOID NEAR RubberBandRect(
        !          1135:     BOOL fFirstTime)
        !          1136: {
        !          1137:     POINT ptTL;         // Top-Left point.
        !          1138:     POINT ptBR;         // Bottom-Right point
        !          1139: 
        !          1140:     /*
        !          1141:      * Set the raster-op to invert.
        !          1142:      */
        !          1143:     SetROP2(hdcRubberBand, R2_NOT);
        !          1144: 
        !          1145:     if (!fFirstTime) {
        !          1146:         /*
        !          1147:          * Erase the old rectangle.
        !          1148:          */
        !          1149:         ptTL = ptStart;
        !          1150:         ptBR = ptPrev;
        !          1151:         NormalizePoints(&ptTL, &ptBR);
        !          1152:         Rectangle(hdcRubberBand, ptTL.x, ptTL.y,
        !          1153:                 ptBR.x + gZoomFactor, ptBR.y + gZoomFactor);
        !          1154:     }
        !          1155: 
        !          1156: 
        !          1157:     /*
        !          1158:      * Draw the new one.
        !          1159:      */
        !          1160:     ptTL = ptStart;
        !          1161:     ptBR = ptEnd;
        !          1162:     NormalizePoints(&ptTL, &ptBR);
        !          1163:     Rectangle(hdcRubberBand, ptTL.x, ptTL.y,
        !          1164:             ptBR.x + gZoomFactor, ptBR.y + gZoomFactor);
        !          1165: }
        !          1166: 
        !          1167: 
        !          1168: 
        !          1169: /******************************************************************************
        !          1170:  * VOID CircleDP(hwnd, msg, ptNew)
        !          1171:  *
        !          1172:  * PURPOSE: Draw an ellipse (filled/hollow) in the area specified.
        !          1173:  *
        !          1174:  * PARAMS : HWND   hwnd : handle to dest. DC
        !          1175:  *          unsigned msg  : Upper left corner of rect;
        !          1176:  *          POINT  ptNew   : end pt. of line
        !          1177:  *
        !          1178:  * SIDE EFFECTS: may change bits in image DC
        !          1179:  *
        !          1180:  *****************************************************************************/
        !          1181: 
        !          1182: VOID CircleDP(
        !          1183:     HWND hwnd,
        !          1184:     UINT msg,
        !          1185:     POINT ptNew)
        !          1186: {
        !          1187:     switch (msg) {
        !          1188:         case WM_RBUTTONDOWN:
        !          1189:         case WM_LBUTTONDOWN:
        !          1190:             StartRubberBanding(hwnd);
        !          1191:             RubberBandCircle(TRUE);
        !          1192:             break;
        !          1193: 
        !          1194:         case WM_MOUSEMOVE:
        !          1195:             if (fRubberBanding)
        !          1196:                 RubberBandCircle(FALSE);
        !          1197: 
        !          1198:             break;
        !          1199: 
        !          1200:         case WM_LBUTTONUP:
        !          1201:         case WM_RBUTTONUP:
        !          1202:             CircleDPDraw(hwnd);
        !          1203:             break;
        !          1204:     }
        !          1205: }
        !          1206: 
        !          1207: 
        !          1208: 
        !          1209: /************************************************************************
        !          1210: * CircleDPDraw
        !          1211: *
        !          1212: * Does the final drawing of an ellipse when using the Ellipse tool.
        !          1213: *
        !          1214: * Arguments:
        !          1215: *   HWND hwnd - Window handle to the workspace.
        !          1216: *
        !          1217: * History:
        !          1218: *
        !          1219: ************************************************************************/
        !          1220: 
        !          1221: STATICFN VOID NEAR CircleDPDraw(
        !          1222:     HWND hwnd)
        !          1223: {
        !          1224:     POINT ptTL;         // Top-Left point.
        !          1225:     POINT ptBR;         // Bottom-Right point
        !          1226:     HBRUSH hbr;
        !          1227:     HBRUSH hbrOld;
        !          1228:     HPEN hpen;
        !          1229:     HPEN hpenOld;
        !          1230:     INT nOutset;
        !          1231: 
        !          1232:     EndRubberBanding(hwnd);
        !          1233: 
        !          1234:     /*
        !          1235:      * Flip the points (if needed) and scale down.
        !          1236:      */
        !          1237:     ptTL = ptStart;
        !          1238:     ptBR = ptEnd;
        !          1239:     NormalizePoints(&ptTL, &ptBR);
        !          1240:     ptTL.x /= gZoomFactor;
        !          1241:     ptTL.y /= gZoomFactor;
        !          1242:     ptBR.x /= gZoomFactor;
        !          1243:     ptBR.y /= gZoomFactor;
        !          1244: 
        !          1245: #ifdef WIN16
        !          1246:     /*
        !          1247:      * The win 3.x code does not properly draw an ellipse if it
        !          1248:      * has a NULL pen selected in (to not draw the border).  For
        !          1249:      * this platform, we must select in the drawing pen.  This is
        !          1250:      * not necessary for NT (we can use a NULL pen to avoid
        !          1251:      * drawing the solid border).
        !          1252:      */
        !          1253: 
        !          1254:     if (gCurTool == TOOL_CIRCLE)
        !          1255:         hbr = GetStockObject(NULL_BRUSH);
        !          1256:     else
        !          1257:         hbr = ghbrDraw;
        !          1258: 
        !          1259:     hpenOld = SelectObject(ghdcImage, ghpenDraw);
        !          1260:     hbrOld = SelectObject(ghdcImage, hbr);
        !          1261:     Ellipse(ghdcImage, ptTL.x, ptTL.y, ptBR.x + 1, ptBR.y + 1);
        !          1262:     SelectObject(ghdcImage, hbrOld);
        !          1263:     SelectObject(ghdcImage, hpenOld);
        !          1264: 
        !          1265:     if (giType != FT_BITMAP) {
        !          1266:         /* for icons and cursors draw the shape on the AND DC (memory)
        !          1267:          * in black (if in color mode) or white (otherwise)
        !          1268:          */
        !          1269:         hpen = CreatePen(PS_INSIDEFRAME, 1,
        !          1270:                 (gfDrawMode == MODE_COLOR) ? RGB_BLACK : RGB_WHITE);
        !          1271: 
        !          1272:         if (gCurTool == TOOL_CIRCLE)
        !          1273:             hbr = GetStockObject(NULL_BRUSH);
        !          1274:         else
        !          1275:             hbr = GetStockObject((gfDrawMode == MODE_COLOR) ?
        !          1276:                     BLACK_BRUSH : WHITE_BRUSH);
        !          1277: 
        !          1278:         hpenOld = SelectObject(ghdcANDMask, hpen);
        !          1279:         hbrOld = SelectObject(ghdcANDMask, hbr);
        !          1280:         Ellipse(ghdcANDMask, ptTL.x, ptTL.y, ptBR.x + 1, ptBR.y + 1);
        !          1281:         SelectObject(ghdcANDMask, hpenOld);
        !          1282:         SelectObject(ghdcANDMask, hbrOld);
        !          1283:         DeleteObject(hpen);
        !          1284:     }
        !          1285: 
        !          1286: #else
        !          1287: 
        !          1288:     if (gCurTool == TOOL_CIRCLE) {
        !          1289:         hpen = ghpenDraw;
        !          1290:         hbr = GetStockObject(NULL_BRUSH);
        !          1291:         nOutset = 1;
        !          1292:     }
        !          1293:     else {
        !          1294:         hpen = GetStockObject(NULL_PEN);
        !          1295:         hbr = ghbrDraw;
        !          1296:         nOutset = 2;
        !          1297:     }
        !          1298: 
        !          1299:     hpenOld = SelectObject(ghdcImage, hpen);
        !          1300:     hbrOld = SelectObject(ghdcImage, hbr);
        !          1301:     Ellipse(ghdcImage, ptTL.x, ptTL.y, ptBR.x + nOutset, ptBR.y + nOutset);
        !          1302:     SelectObject(ghdcImage, hpenOld);
        !          1303:     SelectObject(ghdcImage, hbrOld);
        !          1304: 
        !          1305:     if (giType != FT_BITMAP) {
        !          1306:         /* for icons and cursors draw the shape on the AND DC (memory)
        !          1307:          * in black (if in color mode) or white (otherwise)
        !          1308:          */
        !          1309:         if (gCurTool == TOOL_CIRCLE) {
        !          1310:             hpen = CreatePen(PS_INSIDEFRAME, 1,
        !          1311:                     (gfDrawMode == MODE_COLOR) ? RGB_BLACK : RGB_WHITE);
        !          1312:             hbr = GetStockObject(NULL_BRUSH);
        !          1313:         }
        !          1314:         else {
        !          1315:             hpen = GetStockObject(NULL_PEN);
        !          1316:             hbr = GetStockObject((gfDrawMode == MODE_COLOR) ?
        !          1317:                     BLACK_BRUSH : WHITE_BRUSH);
        !          1318:         }
        !          1319: 
        !          1320:         hpenOld = SelectObject(ghdcANDMask, hpen);
        !          1321:         hbrOld = SelectObject(ghdcANDMask, hbr);
        !          1322:         Ellipse(ghdcANDMask, ptTL.x, ptTL.y, ptBR.x + nOutset, ptBR.y + nOutset);
        !          1323:         SelectObject(ghdcANDMask, hpenOld);
        !          1324:         SelectObject(ghdcANDMask, hbrOld);
        !          1325: 
        !          1326:         if (gCurTool == TOOL_CIRCLE)
        !          1327:             DeleteObject(hpen);
        !          1328:     }
        !          1329: 
        !          1330: #endif
        !          1331: 
        !          1332:     fImageDirty = TRUE;
        !          1333: 
        !          1334:     ViewUpdate();
        !          1335: }
        !          1336: 
        !          1337: 
        !          1338: 
        !          1339: /******************************************************************************
        !          1340:  * VOID PASCAL RubberBandCircle()
        !          1341:  *
        !          1342:  * PURPOSE: Draw rubberbanding circle
        !          1343:  *
        !          1344:  *
        !          1345:  *****************************************************************************/
        !          1346: 
        !          1347: STATICFN VOID NEAR RubberBandCircle(
        !          1348:     BOOL fFirstTime)
        !          1349: {
        !          1350:     POINT ptTL;         // Top-Left point.
        !          1351:     POINT ptBR;         // Bottom-Right point
        !          1352: 
        !          1353:     /*
        !          1354:      * Set the raster-op to invert.
        !          1355:      */
        !          1356:     SetROP2(hdcRubberBand, R2_NOT);
        !          1357: 
        !          1358:     if (!fFirstTime) {
        !          1359:         /*
        !          1360:          * Erase the old circle.
        !          1361:          */
        !          1362:         ptTL = ptStart;
        !          1363:         ptBR = ptPrev;
        !          1364:         NormalizePoints(&ptTL, &ptBR);
        !          1365:         Ellipse(hdcRubberBand, ptTL.x, ptTL.y,
        !          1366:                 ptBR.x + gZoomFactor, ptBR.y + gZoomFactor);
        !          1367:     }
        !          1368: 
        !          1369: 
        !          1370:     /*
        !          1371:      * Draw the new one.
        !          1372:      */
        !          1373:     ptTL = ptStart;
        !          1374:     ptBR = ptEnd;
        !          1375:     NormalizePoints(&ptTL, &ptBR);
        !          1376:     Ellipse(hdcRubberBand, ptTL.x, ptTL.y,
        !          1377:             ptBR.x + gZoomFactor, ptBR.y + gZoomFactor);
        !          1378: }
        !          1379: 
        !          1380: 
        !          1381: 
        !          1382: /************************************************************************
        !          1383: * FloodDP
        !          1384: *
        !          1385: *
        !          1386: *
        !          1387: * Arguments:
        !          1388: *
        !          1389: * History:
        !          1390: *
        !          1391: ************************************************************************/
        !          1392: 
        !          1393: VOID FloodDP(
        !          1394:     HWND hwnd,
        !          1395:     UINT msg,
        !          1396:     POINT ptNew)
        !          1397: {
        !          1398:     HDC dc;
        !          1399:     HDC bwdc;
        !          1400:     HBRUSH hbrOld;
        !          1401:     HBITMAP bwbit;
        !          1402:     HCURSOR hcurSave;
        !          1403: 
        !          1404:     switch (msg) {
        !          1405:         case WM_RBUTTONDOWN:
        !          1406:         case WM_LBUTTONDOWN:
        !          1407:             hcurSave = SetCursor(hcurWait);
        !          1408: 
        !          1409:             dc = GetDC(hwnd);
        !          1410:             /* create temporary DC */
        !          1411:             bwdc = CreateCompatibleDC(dc);
        !          1412: 
        !          1413:             /* create temporary monochrome bitmap */
        !          1414:             if (!(bwbit = CreateBitmap(gcxImage, gcyImage, 1, 1, NULL))) {
        !          1415:                 DeleteDC(bwdc);
        !          1416:                 ReleaseDC(hwnd, dc);
        !          1417:                 Message(MSG_OUTOFMEMORY);
        !          1418:                 return;
        !          1419:             }
        !          1420:             SelectObject(bwdc, bwbit);
        !          1421: 
        !          1422:             /*  Set background color of image DC to desired floodfill color.*/
        !          1423:             SetBkColor(ghdcImage,
        !          1424:                     GetPixel(ghdcImage, (ptNew.x / gZoomFactor),
        !          1425:                     (ptNew.y / gZoomFactor)));
        !          1426: 
        !          1427:             /******* OPERATION 0 ******/
        !          1428:             /* First create a monochrome mask of the image after setting background
        !          1429:              * color to the floodfill color. This will make the region to be
        !          1430:              * flooded white(background), and it's boundary black (foreground) in the
        !          1431:              * mask.
        !          1432:              */
        !          1433:             BitBlt(bwdc, 0, 0, gcxImage, gcyImage, ghdcImage, 0, 0, SRCCOPY);
        !          1434: 
        !          1435:             /******* OPERATION 1 ******/
        !          1436:             /* floodfill selected region in mask (which is white bounded by black)
        !          1437:              * with black.
        !          1438:              */
        !          1439:             SelectObject(bwdc, GetStockObject(BLACK_BRUSH));
        !          1440:             ExtFloodFill(bwdc, ptNew.x / gZoomFactor,
        !          1441:                     ptNew.y / gZoomFactor, RGB_BLACK, FLOODFILLBORDER);
        !          1442: 
        !          1443:             /******* OPERATION 2 ******/
        !          1444:             /* Now XOR the original image on the mask , inverting the
        !          1445:              * flood-filled pixels on mask (black --> white).
        !          1446:              */
        !          1447:             BitBlt(bwdc, 0, 0, gcxImage, gcyImage, ghdcImage, 0, 0, SRCINVERT);
        !          1448: 
        !          1449:             /* the AND mask needs to be updated only if in screen or inverse mode */
        !          1450:             if ((giType == FT_CURSOR) || (giType == FT_ICON)) {
        !          1451:                 if (gfDrawMode == MODE_COLOR) {
        !          1452:                     SetBkColor(ghdcANDMask, RGB(0, 0, 0));
        !          1453:                     BitBlt(ghdcANDMask, 0, 0, gcxImage, gcyImage, bwdc,
        !          1454:                             0, 0, ROP_DSna);
        !          1455:                     SelectObject(ghdcANDMask, GetStockObject(BLACK_BRUSH));
        !          1456:                     BitBlt(ghdcANDMask, 0, 0, gcxImage, gcyImage, bwdc,
        !          1457:                             0, 0, ROP_DSPao);
        !          1458:                 }
        !          1459:                 else {
        !          1460:                     SetBkColor(ghdcANDMask, RGB(0xff, 0xff, 0xff));                    BitBlt(ghdcANDMask, 0, 0, gcxImage, gcyImage, bwdc,
        !          1461:                             0, 0, ROP_DSna);
        !          1462:                     SelectObject(ghdcANDMask, GetStockObject(WHITE_BRUSH));
        !          1463:                     BitBlt(ghdcANDMask, 0, 0, gcxImage, gcyImage, bwdc,
        !          1464:                             0, 0, ROP_DSPao);
        !          1465:                 }
        !          1466:             }
        !          1467: 
        !          1468:             SetBkColor(ghdcImage, RGB_WHITE);
        !          1469:             /****** OPERATION 3 ******/
        !          1470:             /* The following operation turns the flooded area on-screen black,
        !          1471:              * on the image, preserving the rest of the it.
        !          1472:              */
        !          1473:             BitBlt(ghdcImage, 0, 0, gcxImage, gcyImage, bwdc, 0, 0, ROP_DSna);
        !          1474: 
        !          1475:             /****** OPERATION 4 ******/
        !          1476:             /* Rop_DSPao ANDs the pattern (current brush which is the floodfill
        !          1477:              * color) on the source making flooded area (which was white as a
        !          1478:              * result of operation 2 ) the current brush color, and keeps the rest
        !          1479:              * of the source black. The source is then ORed into the original image
        !          1480:              * (whose flooded area is black as a result of operation 3) to get
        !          1481:              * the desired end result.
        !          1482:              */
        !          1483:             hbrOld = SelectObject(ghdcImage, ghbrDraw);
        !          1484:             BitBlt(ghdcImage, 0, 0, gcxImage, gcyImage, bwdc, 0, 0, ROP_DSPao);
        !          1485:             SelectObject(ghdcImage, hbrOld);
        !          1486: 
        !          1487:             /* clean up */
        !          1488:             DeleteDC(bwdc);
        !          1489:             DeleteObject(bwbit);
        !          1490:             ReleaseDC(hwnd, dc);
        !          1491: 
        !          1492:             /*
        !          1493:              * Mark the image as changed.
        !          1494:              */
        !          1495:             fImageDirty = TRUE;
        !          1496: 
        !          1497:             ViewUpdate();
        !          1498: 
        !          1499:             SetCursor(hcurSave);
        !          1500: 
        !          1501:             break;
        !          1502:     }
        !          1503: }
        !          1504: 
        !          1505: 
        !          1506: 
        !          1507: /******************************************************************************
        !          1508:  * VOID HotSpotDP(hwnd, msg, ptNew)
        !          1509:  *
        !          1510:  * PURPOSE: Sets the hotspot.
        !          1511:  *
        !          1512:  * PARAMS : HWND   hwnd : handle to dest. DC
        !          1513:  *          WORD   msg  :
        !          1514:  *          POINT  ptNew   : end pt.
        !          1515:  *
        !          1516:  *****************************************************************************/
        !          1517: 
        !          1518: VOID HotSpotDP(
        !          1519:     HWND hwnd,
        !          1520:     UINT msg,
        !          1521:     POINT ptNew)
        !          1522: {
        !          1523:     switch (msg) {
        !          1524:         case WM_LBUTTONDOWN:
        !          1525:             PropBarSetHotSpot(ptNew.x / gZoomFactor, ptNew.y / gZoomFactor);
        !          1526:             break;
        !          1527: 
        !          1528:         case WM_MOUSEMOVE:
        !          1529:             if (fDrawing && fLeftButtonDown)
        !          1530:                 PropBarSetHotSpot(ptNew.x / gZoomFactor,
        !          1531:                         ptNew.y / gZoomFactor);
        !          1532: 
        !          1533:             break;
        !          1534: 
        !          1535:         case WM_LBUTTONUP:
        !          1536:             MarkHotSpotPosition(ptNew.x / gZoomFactor, ptNew.y / gZoomFactor);
        !          1537:             break;
        !          1538:     }
        !          1539: }
        !          1540: 
        !          1541: 
        !          1542: 
        !          1543: /************************************************************************
        !          1544: * MarkHotSpotPosition
        !          1545: *
        !          1546: * Updates the hotspot location in the currently selected cursor image.
        !          1547: *
        !          1548: * Arguments:
        !          1549: *
        !          1550: * History:
        !          1551: *
        !          1552: ************************************************************************/
        !          1553: 
        !          1554: STATICFN VOID NEAR MarkHotSpotPosition(
        !          1555:     INT x,
        !          1556:     INT y)
        !          1557: {
        !          1558:     gpImageCur->iHotspotX = x;
        !          1559:     gpImageCur->iHotspotY = y;
        !          1560:     PropBarSetHotSpot(x, y);
        !          1561: 
        !          1562:     /*
        !          1563:      * Mark the image as changed.
        !          1564:      */
        !          1565:     fImageDirty = TRUE;
        !          1566: }
        !          1567: 
        !          1568: 
        !          1569: 
        !          1570: /******************************************************************************
        !          1571:  * NormalizePoints
        !          1572:  *
        !          1573:  * PURPOSE : interchange start and end pts
        !          1574:  *           if start point is > end point.
        !          1575:  *
        !          1576:  *****************************************************************************/
        !          1577: 
        !          1578: VOID NormalizePoints(
        !          1579:     PPOINT pptStart,
        !          1580:     PPOINT pptEnd)
        !          1581: {
        !          1582:     INT n;
        !          1583: 
        !          1584:     if (pptStart->x > pptEnd->x) {
        !          1585:         n = pptEnd->x;
        !          1586:         pptEnd->x = pptStart->x;
        !          1587:         pptStart->x = n;
        !          1588:     }
        !          1589: 
        !          1590:     if (pptStart->y > pptEnd->y) {
        !          1591:         n = pptEnd->y;
        !          1592:         pptEnd->y = pptStart->y;
        !          1593:         pptStart->y = n;
        !          1594:     }
        !          1595: }
        !          1596: 
        !          1597: 
        !          1598: 
        !          1599: /******************************************************************************
        !          1600:  * HDC PASCAL StartRubberBanding(hwnd)
        !          1601:  *
        !          1602:  * PURPOSE: Sets up rubberbanding for all tools.
        !          1603:  *
        !          1604:  * PARAMS : HANDLE hDst : handle to box DC
        !          1605:  *
        !          1606:  * RETURNS :handle to destination display context
        !          1607:  *
        !          1608:  * SIDE EFFECTS: alters a few global flags for tracking
        !          1609:  *
        !          1610:  *****************************************************************************/
        !          1611: 
        !          1612: STATICFN VOID NEAR StartRubberBanding(
        !          1613:     HWND hwnd)
        !          1614: {
        !          1615:     hdcRubberBand = GetDC(hwnd);
        !          1616: 
        !          1617:     /*
        !          1618:      * Select a white pen, and a null brush (prevents drawing the
        !          1619:      * interior of rectangles and ellipses).
        !          1620:      */
        !          1621:     SelectObject(hdcRubberBand, GetStockObject(WHITE_PEN));
        !          1622:     SelectObject(hdcRubberBand, GetStockObject(NULL_BRUSH));
        !          1623: 
        !          1624:     fRubberBanding = TRUE;
        !          1625: }
        !          1626: 
        !          1627: 
        !          1628: 
        !          1629: /******************************************************************************
        !          1630:  * VOID PASCAL EndRubberBanding()
        !          1631:  *
        !          1632:  * PURPOSE: Stops rubberbanding rect. and cleans up
        !          1633:  *
        !          1634:  *****************************************************************************/
        !          1635: 
        !          1636: STATICFN VOID NEAR EndRubberBanding(
        !          1637:     HWND hwnd)
        !          1638: {
        !          1639:     ReleaseDC(hwnd, hdcRubberBand);
        !          1640:     fRubberBanding = FALSE;
        !          1641: }

unix.superglobalmegacorp.com

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