Annotation of os232sdk/toolkt20/c/samples/fatpel/fatpel.c, revision 1.1

1.1     ! root        1: /************************************************************************
        !             2: *
        !             3: *   fatpel.c -- The Diamond Metric, Theory vs. Practice
        !             4: *
        !             5: *   Created by Microsoft, IBM Corporation, 1990
        !             6: *
        !             7: *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is 
        !             8: *      sample code created by Microsoft Corporation and/or IBM 
        !             9: *      Corporation. This sample code is not part of any standard 
        !            10: *      Microsoft or IBM product and is provided to you solely for 
        !            11: *      the purpose of assisting you in the development of your 
        !            12: *      applications.  The code is provided "AS IS", without 
        !            13: *      warranty of any kind.  Neither Microsoft nor IBM shall be 
        !            14: *      liable for any damages arising out of your use of the sample 
        !            15: *      code, even if they have been advised of the possibility of 
        !            16: *      such damages.
        !            17: *
        !            18: ************************************************************************/
        !            19: 
        !            20: #define INCL_WINFRAMEMGR
        !            21: #define INCL_WINWINDOWMGR
        !            22: #define INCL_WINMESSAGEMGR
        !            23: #define        INCL_WINPOINTERS
        !            24: #define INCL_WINSWITCHLIST
        !            25: #define INCL_WINTRACKRECT
        !            26: #define INCL_WINDIALOGS
        !            27: #define INCL_WINBUTTONS
        !            28: #define INCL_GPILOGCOLORTABLE
        !            29: #define INCL_GPIBITMAPS
        !            30: #define        INCL_GPITRANSFORMS
        !            31: #define INCL_DOSMEMMGR
        !            32: #define INCL_DOSFILEMGR
        !            33: #define INCL_BITMAPFILEFORMAT
        !            34: #define INCL_GPIPRIMITIVES
        !            35: #define INCL_WINMENUS
        !            36: #define INCL_GPIREGIONS
        !            37: #define INCL_WINPOINTERS
        !            38: #define INCL_WININPUT
        !            39: #include <os2.h>
        !            40: 
        !            41: #include <stdio.h>
        !            42: #include <stdlib.h>
        !            43: #include <string.h>
        !            44: 
        !            45: #include "..\opendlg\opendlg.h"
        !            46: #include "fatpel.h"
        !            47: 
        !            48: 
        !            49: 
        !            50: 
        !            51: /************************************************************************
        !            52: *
        !            53: *   Function declarations
        !            54: *
        !            55: ************************************************************************/
        !            56: 
        !            57: /* Private functions */
        !            58: 
        !            59: VOID  cdecl main(VOID);
        !            60: BOOL  FAR InitGlobals(VOID);
        !            61: BOOL  FAR InitApp(VOID);
        !            62: VOID  Close(HWND);
        !            63: VOID  Command(HWND, USHORT);
        !            64: VOID  Paint(HPS, USHORT);
        !            65: VOID  EraseBackground(HPS);
        !            66: VOID  DrawGrid(HPS);
        !            67: VOID  DisplayRenderedPels(HPS, USHORT);
        !            68: VOID  DisplayControlPoints(HPS, LONG, PPOINTL, USHORT);
        !            69: VOID  DisplayMathematicalObject(HPS, USHORT);
        !            70: VOID  DrawFatPels(HPS);
        !            71: VOID  DrawOneFatPel(HPS, PPOINTL, COLOR);
        !            72: VOID  GetFatPelFromPt(PPOINTL, PPOINTL);
        !            73: VOID  SetFatPel(PPOINTL, COLOR);
        !            74: VOID  RoundControlPoints(HPS, LONG, PPOINTL, PPOINTL, LONG, LONG);
        !            75: VOID  ComputeTransform(PRECTL, PRECTL);
        !            76: VOID  DrawPrimitive(HPS, LONG, PPOINTL);
        !            77: VOID  UpdateSurfaceDims(VOID);
        !            78: VOID  MySetWindowLong  (HWND, USHORT, LONG);
        !            79: VOID  MySetWindowLongHex(HWND, USHORT, LONG);
        !            80: LONG  MyGetWindowLong  (HWND, USHORT);
        !            81: VOID  MouseMove(HWND, MPARAM);
        !            82: VOID  ButtonUp(HWND, USHORT);
        !            83: VOID  ButtonDown(HWND, USHORT, MPARAM);
        !            84: VOID  DragPelSize(HWND, POINTS);
        !            85: VOID  WriteFile(HWND, HPS);
        !            86: BOOL  WriteBMP(HFILE, HPS, PBITMAPINFOHEADER2);
        !            87: VOID  MyMessageBox(HWND, PSZ);
        !            88: VOID  SaveWindowToFile(HWND);
        !            89: SHORT IsPtInList(PPOINTL);
        !            90: SHORT AddPtToList(PPOINTL);
        !            91: BOOL  IsPtCloseToLine(PPOINTL, PPOINTL, PPOINTL);
        !            92: VOID  SwapLong(PLONG, PLONG);
        !            93: 
        !            94: 
        !            95: /* Exported functions */
        !            96: 
        !            97: MRESULT EXPENTRY WndProc        (HWND, USHORT, MPARAM, MPARAM);
        !            98: MRESULT EXPENTRY AboutDlg  (HWND, USHORT, MPARAM, MPARAM);
        !            99: MRESULT EXPENTRY ColorsDlg (HWND, USHORT, MPARAM, MPARAM);
        !           100: MRESULT EXPENTRY PelSizeDlg(HWND, USHORT, MPARAM, MPARAM);
        !           101: 
        !           102: 
        !           103: 
        !           104: 
        !           105: /************************************************************************
        !           106: *
        !           107: *   Global Variables
        !           108: *
        !           109: ************************************************************************/
        !           110: 
        !           111: /* compute absolute value for arbitrary (in my case, LONG) number */
        !           112: /* this is to avoid compiler warnings about data conversion */
        !           113: #define L_ABS(x)       (((x) > 0) ? (x) : (-(x)))
        !           114: 
        !           115: typedef struct
        !           116: {
        !           117:     HAB      hab;
        !           118:     HMQ      hMsgQ;
        !           119:     HWND     hwndFrame;
        !           120:     HWND     hwnd;
        !           121: 
        !           122:     BOOL     fFirstTime;   /* TRUE --> first time initialization of rcl */
        !           123:     RECTL    rcl;         /* dimensions of client rectangle */
        !           124: 
        !           125:     HPS      hpsFat;
        !           126:     HDC      hdcFat;
        !           127:     HBITMAP  hbmFat;
        !           128:     HPS      hpsFatShadow;
        !           129:     HDC      hdcFatShadow;
        !           130:     HBITMAP  hbmFatShadow;
        !           131: 
        !           132:     RECTL    rclFatBM;    /* dimensions of fatbits bitmap */
        !           133:     RECTL    rclFat;      /* dimensions of active fat bits grid */
        !           134:     LONG     cxFatPel;     /* width of fat pel */
        !           135:     LONG     cyFatPel;     /* height of fat pel */
        !           136:     LONG     cxHalfFatPel;
        !           137:     LONG     cyHalfFatPel;
        !           138:     USHORT   usPelShape;
        !           139: 
        !           140:     MATRIXLF matlf;    /* goes from window coords to fatpel coords */
        !           141: 
        !           142:     BOOL     fRGB;        /* TRUE --> color mode is RGB */
        !           143:     COLOR    clrMathObj;
        !           144:     COLOR    clrRenderedObj;
        !           145:     COLOR    clrField;
        !           146:     COLOR    clrCrossHair;
        !           147:     COLOR    clrInterstice;
        !           148:     COLOR    clrControlPoints;
        !           149: 
        !           150:     COLOR    clrBlackIndex;
        !           151:     COLOR    clrEditPel;
        !           152: 
        !           153:     USHORT   usControlPointSymbol;
        !           154: 
        !           155:     BOOL     fDisplayRenderedObj;
        !           156:     BOOL     fDisplayMathObj;
        !           157:     BOOL     fDisplayControlPoints;
        !           158:     BOOL     fDisplayCrossHairs;
        !           159:     BOOL     fDisplayPelBorder;
        !           160:     BOOL     fRoundControlPoints;
        !           161:     BOOL     fAutoRedraw;
        !           162:     USHORT   usCurPrim;
        !           163:     USHORT   usMix;
        !           164: 
        !           165:     LONG     cptl;
        !           166:     PPOINTL  pptl;
        !           167:     PPOINTL  pptlTmp;
        !           168: 
        !           169:     BOOL     fDraggingPelSize;
        !           170:     HPOINTER hptrDragSize;
        !           171: 
        !           172:     BOOL     fDraggingPelColor;
        !           173:     HPOINTER hptrDragColor;
        !           174: 
        !           175:     SHORT    sPtGrabbed;
        !           176:     BOOL     fDraggingControlPoint;
        !           177:     LONG     lHitPrecision;
        !           178: 
        !           179:     BOOL     fEditPelColors;
        !           180: 
        !           181: } GLOBALDATA;
        !           182: GLOBALDATA global;
        !           183: 
        !           184: 
        !           185: 
        !           186: 
        !           187: /************************************************************************
        !           188: *
        !           189: *   main
        !           190: *
        !           191: *   WinInitialize resizes our ring 2 stack, among other things, so
        !           192: *   we won't GP fault trying to do graphics.  WinCreateMsgQueue defines
        !           193: *   us as a REAL PM app. (WINDOWAPI in .DEF file does also).
        !           194: *   Call a sub to register our window class and create a window.
        !           195: *   Loop over messages.  Exit cleanly.
        !           196: *
        !           197: ************************************************************************/
        !           198: 
        !           199: VOID cdecl
        !           200: main()
        !           201: {
        !           202:     QMSG qMsg;
        !           203:     int iRet = 0;
        !           204: 
        !           205: 
        !           206:     global.hab  = WinInitialize(NULL);
        !           207:     global.hMsgQ = WinCreateMsgQueue(global.hab, 0);
        !           208: 
        !           209:     if (InitApp())
        !           210:        while (WinGetMsg( global.hab, (PQMSG)&qMsg, (HWND)NULL, 0, 0 ))
        !           211:            WinDispatchMsg( global.hab, (PQMSG)&qMsg );
        !           212:     else
        !           213:        iRet = -1;
        !           214: 
        !           215:     WinDestroyWindow( global.hwndFrame );
        !           216:     WinDestroyMsgQueue( global.hMsgQ );
        !           217:     WinTerminate( global.hab );
        !           218:     DosExit(EXIT_PROCESS, iRet);
        !           219: }
        !           220: 
        !           221: 
        !           222: 
        !           223: 
        !           224: /****************************************************************************
        !           225: *
        !           226: *   InitGlobals
        !           227: *
        !           228: *   Initialize global variables.
        !           229: *
        !           230: ****************************************************************************/
        !           231: 
        !           232: BOOL FAR
        !           233: InitGlobals()
        !           234: {
        !           235:     global.fFirstTime           = TRUE;
        !           236: 
        !           237:     global.rcl.xLeft            = 0L;
        !           238:     global.rcl.yBottom          = 0L;
        !           239:     global.rcl.xRight           = 0L;
        !           240:     global.rcl.yTop             = 0L;
        !           241: 
        !           242:     global.hpsFat               = NULL;
        !           243:     global.hdcFat               = NULL;
        !           244:     global.hbmFat               = NULL;
        !           245:     global.hpsFatShadow         = NULL;
        !           246:     global.hdcFatShadow         = NULL;
        !           247:     global.hbmFatShadow         = NULL;
        !           248:     global.rclFatBM.xLeft       = 0L;
        !           249:     global.rclFatBM.yBottom     = 0L;
        !           250:     global.rclFatBM.xRight      = 0L;
        !           251:     global.rclFatBM.yTop        = 0L;
        !           252: 
        !           253:     global.cxFatPel             = 32L;
        !           254:     global.cyFatPel             = 32L;
        !           255:     global.cxHalfFatPel         = global.cxFatPel / 2L;
        !           256:     global.cyHalfFatPel         = global.cyFatPel / 2L;
        !           257:     global.usPelShape           = IDC_CIRCLE;
        !           258: 
        !           259:     global.fRGB                 = FALSE;
        !           260:     global.clrMathObj           = CLR_BLUE;
        !           261:     global.clrRenderedObj       = CLR_NEUTRAL;
        !           262:     global.clrField             = CLR_CYAN;
        !           263:     global.clrCrossHair         = CLR_DARKCYAN;
        !           264:     global.clrInterstice        = CLR_BACKGROUND;
        !           265:     global.clrControlPoints     = CLR_YELLOW;
        !           266: 
        !           267:     global.clrBlackIndex        = CLR_ERROR;
        !           268:     global.clrEditPel           = CLR_ERROR;
        !           269: 
        !           270:     global.usControlPointSymbol  = MARKSYM_SOLIDDIAMOND;
        !           271: 
        !           272:     global.fDisplayRenderedObj  = TRUE;
        !           273:     global.fDisplayMathObj      = TRUE;
        !           274:     global.fDisplayControlPoints = TRUE;
        !           275:     global.fDisplayCrossHairs   = TRUE;
        !           276:     global.fDisplayPelBorder    = TRUE;
        !           277:     global.fRoundControlPoints  = FALSE;
        !           278:     global.fAutoRedraw          = TRUE;
        !           279:     global.usCurPrim            = IDM_POLYLINE;
        !           280:     global.usMix                = FM_OVERPAINT;
        !           281: 
        !           282:     global.fDraggingPelSize     = FALSE;
        !           283:     global.fDraggingPelColor    = FALSE;
        !           284:     global.fDraggingControlPoint = FALSE;
        !           285:     global.sPtGrabbed           = NO_POINT;
        !           286:     global.lHitPrecision        = 0L;
        !           287: 
        !           288:     global.fEditPelColors       = FALSE;
        !           289: 
        !           290:     global.cptl = 0L;
        !           291:     global.pptl = global.pptlTmp = NULL;
        !           292:     if (DosAllocMem(&global.pptl, CPTLMAX * sizeof(POINTL), fPERM|PAG_COMMIT))
        !           293:        return FALSE;
        !           294:     if (DosAllocMem(&global.pptlTmp, CPTLMAX * sizeof(POINTL), fPERM|PAG_COMMIT))
        !           295:        return FALSE;
        !           296: 
        !           297:     return TRUE;
        !           298: }
        !           299: 
        !           300: 
        !           301: 
        !           302: 
        !           303: /****************************************************************************
        !           304: *
        !           305: *   InitApp
        !           306: *
        !           307: *   Register application window class and creates standard window.
        !           308: *
        !           309: ****************************************************************************/
        !           310: 
        !           311: #define INIT_MENU_ITEM(val, var)     \
        !           312:        TOGGLE_MENU_ITEM(global.hwndFrame, (val), (var))
        !           313: 
        !           314: BOOL FAR
        !           315: InitApp()
        !           316: {
        !           317:     char szTitle[24];
        !           318:     ULONG ctldata;
        !           319:     PID pid;
        !           320:     TID tid;
        !           321:     HSWITCH hsw;
        !           322:     static SWCNTRL swctl = { 0, 0, 0, 0, 0, SWL_VISIBLE,
        !           323:                             SWL_JUMPABLE, "FatPels", 0 };
        !           324: 
        !           325:     if (!InitGlobals())
        !           326:        return FALSE;
        !           327: 
        !           328: 
        !           329:     /*  Register Application Window Class  */
        !           330: 
        !           331:     WinLoadString( global.hab, NULL, IDS_TITLE, sizeof(szTitle), (PCH)szTitle );
        !           332:     if ( !WinRegisterClass( global.hab, (PCH)szTitle, (PFNWP)WndProc,
        !           333:            CS_SIZEREDRAW, 0 ))
        !           334:        return FALSE;
        !           335: 
        !           336: 
        !           337:     /* Load the pointer to use when dragging pel size. */
        !           338:     if (!(global.hptrDragSize = WinLoadPointer( HWND_DESKTOP, NULL, IDR_DRAGSIZEPTR )))
        !           339:        return FALSE;
        !           340: 
        !           341:     /* Load the pointer to use when dragging pel color. */
        !           342:     if (!(global.hptrDragColor = WinLoadPointer( HWND_DESKTOP, NULL, IDR_DRAGCOLORPTR )))
        !           343:        return FALSE;
        !           344: 
        !           345: 
        !           346:     /* Create a window instance of class "FatPel" */
        !           347: 
        !           348:     ctldata = FCF_STANDARD &
        !           349:      ~(ULONG)(FCF_ACCELTABLE | FCF_TASKLIST);
        !           350: 
        !           351:     if (global.hwndFrame = WinCreateStdWindow(
        !           352:        HWND_DESKTOP,              /* specify desktop as parent window      */
        !           353:        WS_VISIBLE,                /* window styles                         */
        !           354:        &ctldata,                  /* frame creation flags                  */
        !           355:        (PCH)szTitle,              /* window class name                     */
        !           356:        (PCH)szTitle,              /* name appearing in window caption      */
        !           357:        0L,                        /*                                       */
        !           358:        (HMODULE)NULL,             /* use current executable module id      */
        !           359:        IDW_FATPEL,                /* menu id                               */
        !           360:        (HWND FAR *)&global.hwnd   /* window handle                         */
        !           361:        ))
        !           362:     {
        !           363:        INIT_MENU_ITEM(IDM_RENDEREDOBJ,  global.fDisplayRenderedObj);
        !           364:        INIT_MENU_ITEM(IDM_MATHOBJ,      global.fDisplayMathObj);
        !           365:        INIT_MENU_ITEM(IDM_CTLPOINTS,    global.fDisplayControlPoints);
        !           366:        INIT_MENU_ITEM(IDM_CROSSHAIRS,   global.fDisplayCrossHairs);
        !           367:        INIT_MENU_ITEM(IDM_PELBORDER,    global.fDisplayPelBorder);
        !           368:        INIT_MENU_ITEM(IDM_ROUNDPOINTS,  global.fRoundControlPoints);
        !           369:        INIT_MENU_ITEM(IDM_AUTOREDRAW,   global.fAutoRedraw);
        !           370:        INIT_MENU_ITEM(IDM_EDITPELCOLORS, global.fEditPelColors);
        !           371: 
        !           372:        CHECK_MENU_ITEM(global.hwndFrame, global.usCurPrim);
        !           373: 
        !           374: 
        !           375:        /* Add ourselves to the switch list. */
        !           376: 
        !           377:        WinQueryWindowProcess(global.hwndFrame, &pid, &tid);
        !           378:        swctl.hwnd      = global.hwndFrame;
        !           379:        swctl.idProcess = pid;
        !           380:        hsw = WinAddSwitchEntry(&swctl);
        !           381: 
        !           382:        return TRUE;
        !           383:     }
        !           384:     return FALSE;
        !           385: }
        !           386: 
        !           387: 
        !           388: 
        !           389: 
        !           390: /*************************************************************************
        !           391: *
        !           392: *   WndProc
        !           393: *
        !           394: *   Process messages for the window class.
        !           395: *
        !           396: ************************************************************************/
        !           397: 
        !           398: MRESULT EXPENTRY
        !           399: WndProc( hwnd, usMsg, mp1, mp2 )
        !           400: HWND   hwnd;
        !           401: USHORT usMsg;
        !           402: MPARAM  mp1;
        !           403: MPARAM  mp2;
        !           404: {
        !           405:     switch (usMsg)
        !           406:     {
        !           407:     case WM_CLOSE:
        !           408:        Close(hwnd);
        !           409:        break;
        !           410: 
        !           411:     case WM_COMMAND:
        !           412:        Command(hwnd, LOUSHORT(mp1));
        !           413:        break;
        !           414: 
        !           415:     case WM_PAINT:
        !           416:        {
        !           417:            HPS   hps;
        !           418: 
        !           419:            if (global.fFirstTime)
        !           420:            {
        !           421:                SIZEF sizfx;
        !           422: 
        !           423:                hps = WinGetPS(hwnd);
        !           424:                GpiQueryMarkerBox(hps, &sizfx);
        !           425:                global.lHitPrecision = sizfx.cx / 0x20000L + 1L;
        !           426:                WinReleasePS(hps);
        !           427: 
        !           428:                UpdateSurfaceDims();
        !           429:                global.fFirstTime = FALSE;
        !           430:            }
        !           431: 
        !           432:            /* The small bitmap may have been resized since we last
        !           433:             * painted, in which case it will have been initialized to
        !           434:             * the field color.  Therefore, we will render the mathematical
        !           435:             * object to make sure the right fatpels are there.
        !           436:             */
        !           437:            global.usMix = FM_OVERPAINT;
        !           438:            hps = WinBeginPaint(global.hwnd, NULL, NULL);
        !           439:            Paint(hps, CLEAR_BACKGROUND|RENDER_MATH_OBJ);
        !           440:            WinEndPaint(hps);
        !           441:        }
        !           442:        break;
        !           443: 
        !           444:     case WM_BUTTON1DOWN:
        !           445:     case WM_BUTTON2DOWN:
        !           446:        ButtonDown(hwnd, usMsg, mp1);
        !           447:        break;
        !           448: 
        !           449:     case WM_BUTTON1UP:
        !           450:     case WM_BUTTON2UP:
        !           451:        ButtonUp(hwnd, usMsg);
        !           452:        break;
        !           453: 
        !           454:     case WM_MOUSEMOVE:
        !           455:        MouseMove(hwnd, mp1);
        !           456:        break;
        !           457: 
        !           458:     case WM_SIZE:
        !           459:        UpdateSurfaceDims();
        !           460:        return( (MRESULT)WinDefWindowProc(hwnd, usMsg, mp1, mp2));
        !           461:        break;
        !           462: 
        !           463:     default:
        !           464:        return( (MRESULT)WinDefWindowProc(hwnd, usMsg, mp1, mp2));
        !           465:        break;
        !           466:     }
        !           467: 
        !           468:     return FALSE;
        !           469: }
        !           470: 
        !           471: 
        !           472: 
        !           473: 
        !           474: /************************************************************************
        !           475: *
        !           476: *   MouseMove
        !           477: *
        !           478: ************************************************************************/
        !           479: 
        !           480: VOID
        !           481: MouseMove(hwnd, mp1)
        !           482: HWND hwnd;
        !           483: MPARAM mp1;
        !           484: {
        !           485:     POINTL ptl;
        !           486:     HPS hps;
        !           487: 
        !           488: 
        !           489:     /* make sure we still have our pointer */
        !           490:     /* notice the hierarchy of pointer modes */
        !           491: 
        !           492:     if (global.fDraggingPelSize)
        !           493:     {
        !           494:        if (global.hptrDragSize)
        !           495:            WinSetPointer(HWND_DESKTOP,global.hptrDragSize);
        !           496:     }
        !           497:     else if (global.fEditPelColors)
        !           498:     {
        !           499:        if (global.hptrDragColor)
        !           500:            WinSetPointer(HWND_DESKTOP,global.hptrDragColor);
        !           501:     }
        !           502:     else
        !           503:        WinSetPointer(HWND_DESKTOP,
        !           504:                  WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,FALSE));
        !           505: 
        !           506: 
        !           507:     if (global.fDraggingPelColor)
        !           508:     {
        !           509:        POINTL ptl, ptlFat;
        !           510:        HPS hps;
        !           511: 
        !           512: 
        !           513:        ptl.x = (LONG) LOUSHORT(mp1);
        !           514:        ptl.y = (LONG) HIUSHORT(mp1);
        !           515: 
        !           516:        /* letting the point go negative causes overflow errors */
        !           517:        if (ptl.x < 0)
        !           518:            ptl.x = 0;
        !           519:        if (ptl.y < 0)
        !           520:            ptl.y = 0;
        !           521: 
        !           522:        GetFatPelFromPt(&ptl, &ptlFat);
        !           523:        SetFatPel(&ptlFat, global.clrEditPel);
        !           524: 
        !           525:        hps = WinGetPS(hwnd);
        !           526:        Paint(hps, OVERRIDE_RENDERED_OBJ);
        !           527:        Paint(hps, IGNORED);    /* this call just copies fatpels to the screen */
        !           528:        WinReleasePS(hps);
        !           529:     }
        !           530:     else if (global.fDraggingControlPoint)
        !           531:     {
        !           532:        ptl.x = (LONG) LOUSHORT(mp1);
        !           533:        ptl.y = (LONG) HIUSHORT(mp1);
        !           534: 
        !           535:        /* letting the point go negative causes overflow errors */
        !           536:        if (ptl.x < 0)
        !           537:            ptl.x = 0;
        !           538:        if (ptl.y < 0)
        !           539:            ptl.y = 0;
        !           540: 
        !           541:        if (global.sPtGrabbed != NO_POINT)
        !           542:        {
        !           543:            hps = WinGetPS(hwnd);
        !           544:            Paint(hps, OVERRIDE_RENDERED_OBJ);
        !           545: 
        !           546:            global.pptl[global.sPtGrabbed] = ptl;
        !           547: 
        !           548:            Paint(hps, CLEAR_FAT_BITMAP|RENDER_MATH_OBJ);
        !           549:            WinReleasePS(hps);
        !           550:        }
        !           551:     }
        !           552: }
        !           553: 
        !           554: 
        !           555: 
        !           556: 
        !           557: /************************************************************************
        !           558: *
        !           559: *   ButtonUp
        !           560: *
        !           561: ************************************************************************/
        !           562: 
        !           563: VOID
        !           564: ButtonUp(hwnd, usMsg)
        !           565: HWND hwnd;
        !           566: USHORT usMsg;
        !           567: {
        !           568:     SHORT i;
        !           569:     HPS hps;
        !           570: 
        !           571: 
        !           572:     if (global.fDraggingPelColor)
        !           573:     {
        !           574:        global.fDraggingPelColor = FALSE;
        !           575:        WinSetCapture(HWND_DESKTOP, NULL);
        !           576:     }
        !           577:     else if (global.fDraggingControlPoint)
        !           578:     {
        !           579:        global.fDraggingControlPoint = FALSE;
        !           580:        WinSetCapture(HWND_DESKTOP, NULL);
        !           581:        if (global.sPtGrabbed != NO_POINT)
        !           582:        {
        !           583:            if (usMsg == WM_BUTTON2UP)  /* remove point? */
        !           584:            {
        !           585:                hps = WinGetPS(hwnd);
        !           586:                Paint(hps, OVERRIDE_RENDERED_OBJ);
        !           587: 
        !           588:                /* squeeze out selected point */
        !           589:                if ((i = global.sPtGrabbed) < (SHORT)(global.cptl-1))
        !           590:                    while (i < (SHORT)(global.cptl-1))
        !           591:                    {
        !           592:                        global.pptl[i] = global.pptl[i+1];
        !           593:                        ++i;
        !           594:                    }
        !           595: 
        !           596:                --global.cptl;
        !           597:                global.sPtGrabbed = NO_POINT;
        !           598: 
        !           599:                Paint(hps, CLEAR_FAT_BITMAP|RENDER_MATH_OBJ);
        !           600:                WinReleasePS(hps);
        !           601:            }
        !           602:            else    /* WM_BUTTON1UP */
        !           603:                global.sPtGrabbed = NO_POINT;
        !           604:        }
        !           605:     }
        !           606: }
        !           607: 
        !           608: 
        !           609: 
        !           610: 
        !           611: /************************************************************************
        !           612: *
        !           613: *   ButtonDown
        !           614: *
        !           615: ************************************************************************/
        !           616: 
        !           617: VOID
        !           618: ButtonDown(hwnd, usMsg, mp1)
        !           619: HWND hwnd;
        !           620: USHORT usMsg;
        !           621: MPARAM mp1;
        !           622: {
        !           623:     if (global.fDraggingPelSize)
        !           624:     {
        !           625:        POINTS pt;
        !           626:        HPS hps;
        !           627: 
        !           628:        pt.x = LOUSHORT(mp1);
        !           629:        pt.y = HIUSHORT(mp1);
        !           630:        DragPelSize(hwnd, pt);
        !           631:        global.fDraggingPelSize = FALSE;
        !           632: 
        !           633:        WinSetPointer(HWND_DESKTOP,
        !           634:                      WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,FALSE));
        !           635: 
        !           636:        hps = WinGetPS(hwnd);
        !           637:        global.usMix = FM_OVERPAINT;
        !           638:        Paint(hps, CLEAR_BACKGROUND|CLEAR_FAT_BITMAP|RENDER_MATH_OBJ);
        !           639:        WinReleasePS(hps);
        !           640:     }
        !           641:     else if (global.fEditPelColors)
        !           642:     {
        !           643:        POINTL ptl, ptlFat;
        !           644:        HPS hps;
        !           645: 
        !           646:        global.fDraggingPelColor = TRUE;
        !           647:        WinSetCapture(HWND_DESKTOP, hwnd);
        !           648: 
        !           649:        ptl.x = (LONG) LOUSHORT(mp1);
        !           650:        ptl.y = (LONG) HIUSHORT(mp1);
        !           651: 
        !           652:        if (global.usMix != FM_XOR)
        !           653:        {
        !           654:            hps = WinGetPS(hwnd);
        !           655:            global.usMix = FM_XOR;
        !           656:            Paint(hps, CLEAR_BACKGROUND);
        !           657:            WinReleasePS(hps);
        !           658:        }
        !           659: 
        !           660:        if (usMsg == WM_BUTTON1DOWN)
        !           661:            global.clrEditPel = global.clrRenderedObj;
        !           662:        else
        !           663:            global.clrEditPel = global.clrField;
        !           664: 
        !           665:        GetFatPelFromPt(&ptl, &ptlFat);
        !           666:        SetFatPel(&ptlFat, global.clrEditPel);
        !           667: 
        !           668:        hps = WinGetPS(hwnd);
        !           669:        Paint(hps, OVERRIDE_RENDERED_OBJ);
        !           670:        Paint(hps, IGNORED);    /* this call just copies fatpels to the screen */
        !           671:        WinReleasePS(hps);
        !           672:     }
        !           673:     else if (!global.fDraggingControlPoint)
        !           674:     {
        !           675:        POINTL ptl;
        !           676:        SHORT sNewPtGrabbed;
        !           677:        HPS hps;
        !           678: 
        !           679:        global.fDraggingControlPoint = TRUE;
        !           680:        WinSetCapture(HWND_DESKTOP, hwnd);
        !           681: 
        !           682:        ptl.x = (LONG) LOUSHORT(mp1);
        !           683:        ptl.y = (LONG) HIUSHORT(mp1);
        !           684: 
        !           685:        sNewPtGrabbed = IsPtInList(&ptl);
        !           686: 
        !           687:        if (global.usMix != FM_XOR)
        !           688:        {
        !           689:            hps = WinGetPS(hwnd);
        !           690:            global.usMix = FM_XOR;
        !           691:            Paint(hps, CLEAR_BACKGROUND);
        !           692:            WinReleasePS(hps);
        !           693:        }
        !           694: 
        !           695:        if (usMsg == WM_BUTTON1DOWN)    /* add/move point? */
        !           696:        {
        !           697:            hps = WinGetPS(hwnd);
        !           698: 
        !           699:            if (sNewPtGrabbed != NO_POINT)
        !           700:                global.sPtGrabbed = sNewPtGrabbed;
        !           701:            Paint(hps, OVERRIDE_RENDERED_OBJ);
        !           702: 
        !           703:            if (sNewPtGrabbed == NO_POINT)
        !           704:                global.sPtGrabbed = AddPtToList(&ptl);
        !           705:            else
        !           706:                global.sPtGrabbed = sNewPtGrabbed;
        !           707: 
        !           708:            Paint(hps, CLEAR_FAT_BITMAP|RENDER_MATH_OBJ);
        !           709:            WinReleasePS(hps);
        !           710: 
        !           711:            if (global.sPtGrabbed == NO_POINT)
        !           712:                MyMessageBox(global.hwnd, "Cannot add any more points.");
        !           713:        }
        !           714:        else if (sNewPtGrabbed != NO_POINT)
        !           715:            global.sPtGrabbed = sNewPtGrabbed;
        !           716:     }
        !           717: }
        !           718: 
        !           719: 
        !           720: 
        !           721: 
        !           722: /************************************************************************
        !           723: *
        !           724: *   GetFatPelFromPt
        !           725: *
        !           726: ************************************************************************/
        !           727: 
        !           728: VOID
        !           729: GetFatPelFromPt(pptl, pptlFat)
        !           730: PPOINTL pptl;
        !           731: PPOINTL pptlFat;
        !           732: {
        !           733:     pptlFat->x = pptl->x / global.cxFatPel;
        !           734:     pptlFat->y = pptl->y / global.cyFatPel;
        !           735: }
        !           736: 
        !           737: 
        !           738: 
        !           739: 
        !           740: /************************************************************************
        !           741: *
        !           742: *   SetFatPel
        !           743: *
        !           744: ************************************************************************/
        !           745: 
        !           746: VOID
        !           747: SetFatPel(pptl, clr)
        !           748: PPOINTL pptl;
        !           749: COLOR clr;
        !           750: {
        !           751:     LINEBUNDLE lb;
        !           752: 
        !           753:     if (global.hpsFat)
        !           754:     {
        !           755:        lb.lColor = clr;
        !           756:        GpiSetAttrs(global.hpsFat, PRIM_LINE, LBB_COLOR, 0L, &lb);
        !           757:        GpiSetPel(global.hpsFat, pptl);
        !           758:     }
        !           759: }
        !           760: 
        !           761: 
        !           762: 
        !           763: 
        !           764: /************************************************************************
        !           765: *
        !           766: *   IsPtInList
        !           767: *
        !           768: ************************************************************************/
        !           769: 
        !           770: SHORT
        !           771: IsPtInList(pptl)
        !           772: PPOINTL pptl;
        !           773: {
        !           774:     SHORT i;
        !           775: 
        !           776: 
        !           777:     /* try to find pptl in the points we already have */
        !           778:     for (i = 0; i < (SHORT)global.cptl; ++i)
        !           779:        if (((L_ABS(pptl->x - global.pptl[i].x)) <= global.lHitPrecision) &&
        !           780:            ((L_ABS(pptl->y - global.pptl[i].y)) <= global.lHitPrecision))
        !           781:                return i;
        !           782: 
        !           783:     /* couldn't find it */
        !           784:     return NO_POINT;
        !           785: }
        !           786: 
        !           787: 
        !           788: 
        !           789: 
        !           790: /************************************************************************
        !           791: *
        !           792: *   AddPtToList
        !           793: *
        !           794: ************************************************************************/
        !           795: 
        !           796: SHORT
        !           797: AddPtToList(pptl)
        !           798: PPOINTL pptl;
        !           799: {
        !           800:     SHORT i, j;
        !           801: 
        !           802:     if (global.cptl < CPTLMAX)
        !           803:     {
        !           804:        /* check for new points lying on a line segment */
        !           805:        for (i = 0; i < (SHORT)(global.cptl-1L); ++i)
        !           806:            if (IsPtCloseToLine(&global.pptl[i], &global.pptl[i+1], pptl))
        !           807:            {
        !           808:                /* insert point between endpoints of nearest line segment */
        !           809:                for (j = (SHORT)global.cptl; j > i+1; --j)
        !           810:                    global.pptl[j] = global.pptl[j - 1];
        !           811:                global.pptl[i+1] = *pptl;
        !           812:                ++global.cptl;
        !           813:                return i+1;
        !           814:            }
        !           815: 
        !           816:        /* append the point */
        !           817: 
        !           818:        i = (SHORT) global.cptl;
        !           819:        global.pptl[i] = *pptl;
        !           820:        ++global.cptl;
        !           821:        return i;
        !           822:     }
        !           823: 
        !           824:     return NO_POINT;
        !           825: }
        !           826: 
        !           827: 
        !           828: 
        !           829: 
        !           830: /************************************************************************
        !           831: *
        !           832: *   IsPtCloseToLine
        !           833: *
        !           834: ************************************************************************/
        !           835: 
        !           836: BOOL
        !           837: IsPtCloseToLine(pptl1, pptl2, pptlTest)
        !           838: PPOINTL pptl1;
        !           839: PPOINTL pptl2;
        !           840: PPOINTL pptlTest;
        !           841: {
        !           842:     POINTL ptlLL, ptlUR;
        !           843:     LONG dx, dy, yIntercept, error;
        !           844:     LONG lBoxAdjustment;
        !           845: 
        !           846: 
        !           847:     /* find the bounding box of the line segment */
        !           848: 
        !           849:     ptlLL = *pptl1;    /* assume line goes lower left to upper right */
        !           850:     ptlUR = *pptl2;
        !           851:     if (pptl1->x > pptl2->x)
        !           852:        SwapLong(&ptlLL.x, &ptlUR.x);
        !           853:     if (pptl1->y > pptl2->y)
        !           854:        SwapLong(&ptlLL.y, &ptlUR.y);
        !           855: 
        !           856: 
        !           857:     /* adjust the bounding box if it's too narrow */
        !           858: 
        !           859:     lBoxAdjustment = global.lHitPrecision/2L;
        !           860: 
        !           861:     dx = pptl2->x - pptl1->x;
        !           862:     if (L_ABS(dx) <= global.lHitPrecision)
        !           863:     {
        !           864:        ptlLL.x -= lBoxAdjustment;
        !           865:        ptlUR.x += lBoxAdjustment;
        !           866:     }
        !           867:     dy = pptl2->y - pptl1->y;
        !           868:     if (L_ABS(dy) <= global.lHitPrecision)
        !           869:     {
        !           870:        ptlLL.y -= lBoxAdjustment;
        !           871:        ptlUR.y += lBoxAdjustment;
        !           872:     }
        !           873: 
        !           874: 
        !           875:     /* see if the test point is in the bounding box of the line segment */
        !           876: 
        !           877:     if ((pptlTest->x >= ptlLL.x) &&
        !           878:        (pptlTest->x <= ptlUR.x) &&
        !           879:        (pptlTest->y >= ptlLL.y) &&
        !           880:        (pptlTest->y <= ptlUR.y))
        !           881:     {
        !           882:        /* test for special cases */
        !           883: 
        !           884:        if (dx == 0)    /* vertical line */
        !           885:        {
        !           886:            return (L_ABS(pptlTest->x - pptl1->x) <= global.lHitPrecision);
        !           887:        }
        !           888: 
        !           889:        if (dy == 0)    /* horizontal line */
        !           890:        {
        !           891:            return (L_ABS(pptlTest->y - pptl1->y) <= global.lHitPrecision);
        !           892:        }
        !           893: 
        !           894: 
        !           895:        /* test for general case */
        !           896: 
        !           897:        yIntercept = pptl1->y - (pptl1->x * dy) / dx;
        !           898: 
        !           899:        error = pptlTest->y - (pptlTest->x * dy / dx) - yIntercept;
        !           900:        if (L_ABS(error) <= global.lHitPrecision)
        !           901:            return TRUE;
        !           902:     }
        !           903: 
        !           904:     return FALSE;
        !           905: }
        !           906: 
        !           907: 
        !           908: 
        !           909: 
        !           910: /************************************************************************
        !           911: *
        !           912: *   SwapLong
        !           913: *
        !           914: ************************************************************************/
        !           915: 
        !           916: VOID
        !           917: SwapLong(pl1, pl2)
        !           918: PLONG pl1, pl2;
        !           919: {
        !           920:     LONG lTmp;
        !           921: 
        !           922:     lTmp = *pl1;
        !           923:     *pl1 = *pl2;
        !           924:     *pl2 = lTmp;
        !           925: }
        !           926: 
        !           927: 
        !           928: 
        !           929: 
        !           930: /************************************************************************
        !           931: *
        !           932: *   DragPelSize
        !           933: *
        !           934: *   Set the dimensions of a fat pel by dragging a rectangle
        !           935: *   on the screen.
        !           936: *
        !           937: ************************************************************************/
        !           938: 
        !           939: VOID
        !           940: DragPelSize(hwnd, pt)
        !           941: HWND hwnd;
        !           942: POINTS pt;
        !           943: {
        !           944:     TRACKINFO ti;
        !           945: 
        !           946:     WinSendMsg(global.hwndFrame, WM_QUERYTRACKINFO, (MPARAM)TF_MOVE, (MPARAM)&ti);
        !           947: 
        !           948:     ti.cxBorder   = 1;
        !           949:     ti.cyBorder   = 1;
        !           950:     ti.rclTrack.xLeft  = (LONG)pt.x;
        !           951:     ti.rclTrack.yBottom = (LONG)pt.y;
        !           952:     ti.rclTrack.xRight = (LONG)pt.x;
        !           953:     ti.rclTrack.yTop   = (LONG)pt.y;
        !           954:     ti.fs = TF_RIGHT | TF_TOP;
        !           955:     ti.ptlMinTrackSize.x = 1L;
        !           956:     ti.ptlMinTrackSize.y = 1L;
        !           957: 
        !           958:     if (WinTrackRect(hwnd, NULL, &ti))
        !           959:     {
        !           960:        global.cxFatPel = (ti.rclTrack.xRight - ti.rclTrack.xLeft)  ;
        !           961:        global.cyFatPel = (ti.rclTrack.yTop   - ti.rclTrack.yBottom);
        !           962: 
        !           963:        if (global.cxFatPel < 1L)
        !           964:            global.cxFatPel = 1L;
        !           965: 
        !           966:        if (global.cyFatPel < 1L)
        !           967:            global.cyFatPel = 1L;
        !           968: 
        !           969:        global.cxHalfFatPel = global.cxFatPel / 2L;
        !           970:        global.cyHalfFatPel = global.cyFatPel / 2L;
        !           971: 
        !           972:        UpdateSurfaceDims();
        !           973:     }
        !           974: }
        !           975: 
        !           976: 
        !           977: 
        !           978: 
        !           979: /************************************************************************
        !           980: *
        !           981: *   Close
        !           982: *
        !           983: ************************************************************************/
        !           984: 
        !           985: VOID
        !           986: Close(hwnd)
        !           987: HWND hwnd;
        !           988: {
        !           989:     if (global.hptrDragSize)
        !           990:        WinDestroyPointer(global.hptrDragSize);
        !           991:     WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
        !           992: }
        !           993: 
        !           994: 
        !           995: 
        !           996: 
        !           997: /************************************************************************
        !           998: *
        !           999: *   Command
        !          1000: *
        !          1001: *   Dispatches menu commands to the proper handlers.
        !          1002: *
        !          1003: ************************************************************************/
        !          1004: 
        !          1005: #define UPDATE_MENU_BOOL(var, val)                             \
        !          1006:        {                                                       \
        !          1007:            TOGGLE_BOOL((var));                                 \
        !          1008:            TOGGLE_MENU_ITEM(global.hwndFrame, (val), (var));   \
        !          1009:        }
        !          1010: 
        !          1011: #define UPDATE_MENU_LIST(var, val)                             \
        !          1012:        {                                                       \
        !          1013:            UNCHECK_MENU_ITEM(global.hwndFrame, (var));         \
        !          1014:            (var) = (val);                                      \
        !          1015:            CHECK_MENU_ITEM(global.hwndFrame, (var));           \
        !          1016:        }
        !          1017: 
        !          1018: VOID
        !          1019: Command(hwnd, id)
        !          1020: HWND hwnd;
        !          1021: USHORT id;
        !          1022: {
        !          1023:     BOOL fRedraw = FALSE;
        !          1024:     USHORT fsCmd = IGNORED;
        !          1025: 
        !          1026: 
        !          1027:     switch (id)
        !          1028:     {
        !          1029:     case IDM_SAVE:
        !          1030:        SaveWindowToFile(hwnd);
        !          1031:        break;
        !          1032: 
        !          1033:     case IDM_ABOUT:
        !          1034:        WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)AboutDlg, NULL,
        !          1035:                       IDD_ABOUTDLG, NULL );
        !          1036:        break;
        !          1037: 
        !          1038:     case IDM_REDRAW:
        !          1039:        fsCmd = CLEAR_BACKGROUND|CLEAR_FAT_BITMAP|RENDER_MATH_OBJ;
        !          1040:        break;
        !          1041: 
        !          1042:     case IDM_SETPELSIZE:
        !          1043:        {
        !          1044:            LONG cxFatPel, cyFatPel;
        !          1045: 
        !          1046:            cxFatPel = global.cxFatPel;
        !          1047:            cyFatPel = global.cyFatPel;
        !          1048: 
        !          1049:            if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)PelSizeDlg, NULL,
        !          1050:                           IDD_PELSIZEDLG, NULL ))
        !          1051:            {
        !          1052:                if ((cxFatPel == global.cxFatPel) &&
        !          1053:                    (cyFatPel == global.cyFatPel))
        !          1054:                    fsCmd = CLEAR_BACKGROUND;
        !          1055:                else
        !          1056:                    fsCmd = CLEAR_BACKGROUND|CLEAR_FAT_BITMAP|RENDER_MATH_OBJ;
        !          1057:                fRedraw = TRUE;
        !          1058:            }
        !          1059:        }
        !          1060:        break;
        !          1061: 
        !          1062:     case IDM_DRAGPELSIZE:
        !          1063:        global.fDraggingPelSize = TRUE;
        !          1064:        break;
        !          1065: 
        !          1066:     case IDM_RENDEREDOBJ:
        !          1067:        UPDATE_MENU_BOOL(global.fDisplayRenderedObj, IDM_RENDEREDOBJ);
        !          1068:        fsCmd = CLEAR_BACKGROUND|CLEAR_FAT_BITMAP|RENDER_MATH_OBJ;
        !          1069:        fRedraw = TRUE;
        !          1070:        break;
        !          1071: 
        !          1072:     case IDM_MATHOBJ:
        !          1073:        UPDATE_MENU_BOOL(global.fDisplayMathObj, IDM_MATHOBJ);
        !          1074:        fsCmd = CLEAR_BACKGROUND;
        !          1075:        fRedraw = TRUE;
        !          1076:        break;
        !          1077: 
        !          1078:     case IDM_CTLPOINTS:
        !          1079:        UPDATE_MENU_BOOL(global.fDisplayControlPoints, IDM_CTLPOINTS);
        !          1080:        fsCmd = CLEAR_BACKGROUND;
        !          1081:        fRedraw = TRUE;
        !          1082:        break;
        !          1083: 
        !          1084:     case IDM_CROSSHAIRS:
        !          1085:        UPDATE_MENU_BOOL(global.fDisplayCrossHairs, IDM_CROSSHAIRS);
        !          1086:        fsCmd = CLEAR_BACKGROUND;
        !          1087:        fRedraw = TRUE;
        !          1088:        break;
        !          1089: 
        !          1090:     case IDM_PELBORDER:
        !          1091:        UPDATE_MENU_BOOL(global.fDisplayPelBorder, IDM_PELBORDER);
        !          1092:        fsCmd = CLEAR_BACKGROUND;
        !          1093:        fRedraw = TRUE;
        !          1094:        break;
        !          1095: 
        !          1096:     case IDM_ROUNDPOINTS:
        !          1097:        UPDATE_MENU_BOOL(global.fRoundControlPoints, IDM_ROUNDPOINTS);
        !          1098:        fsCmd = CLEAR_BACKGROUND;
        !          1099:        fRedraw = TRUE;
        !          1100:        break;
        !          1101: 
        !          1102:     case IDM_AUTOREDRAW:
        !          1103:        UPDATE_MENU_BOOL(global.fAutoRedraw, IDM_AUTOREDRAW);
        !          1104:        break;
        !          1105: 
        !          1106:     case IDM_NOPRIM:
        !          1107:     case IDM_POLYLINE:
        !          1108:     case IDM_POLYFILLET:
        !          1109:     case IDM_POLYSPLINE:
        !          1110:     case IDM_POINTARC:
        !          1111:        UPDATE_MENU_LIST(global.usCurPrim, id);
        !          1112:        fsCmd = CLEAR_BACKGROUND|CLEAR_FAT_BITMAP|RENDER_MATH_OBJ;
        !          1113:        fRedraw = TRUE;
        !          1114:        break;
        !          1115: 
        !          1116:     case IDM_SETCOLORS:
        !          1117:        if (WinDlgBox( HWND_DESKTOP, hwnd, (PFNWP)ColorsDlg, NULL,
        !          1118:                       IDD_COLORSDLG, NULL ))
        !          1119:        {
        !          1120:            fsCmd = CLEAR_BACKGROUND|RENDER_MATH_OBJ;
        !          1121:            fRedraw = TRUE;
        !          1122:        }
        !          1123:        break;
        !          1124: 
        !          1125:     case IDM_EDITPELCOLORS:
        !          1126:        UPDATE_MENU_BOOL(global.fEditPelColors, IDM_EDITPELCOLORS);
        !          1127:        break;
        !          1128: 
        !          1129:     case IDM_CLEARALL:
        !          1130:        global.cptl = 0L;
        !          1131:        fsCmd = CLEAR_BACKGROUND|CLEAR_FAT_BITMAP|RENDER_MATH_OBJ;
        !          1132:        fRedraw = TRUE;
        !          1133:        break;
        !          1134:     }
        !          1135: 
        !          1136:     if ((global.fAutoRedraw && fRedraw) || (id == IDM_REDRAW))
        !          1137:     {
        !          1138:        HPS hps;
        !          1139: 
        !          1140:        hps = WinGetPS(hwnd);
        !          1141:        global.usMix = FM_OVERPAINT;
        !          1142:        Paint(hps, fsCmd);
        !          1143:        WinReleasePS(hps);
        !          1144:     }
        !          1145: }
        !          1146: 
        !          1147: 
        !          1148: 
        !          1149: 
        !          1150: /************************************************************************
        !          1151: *
        !          1152: *   Paint
        !          1153: *
        !          1154: ************************************************************************/
        !          1155: 
        !          1156: VOID
        !          1157: Paint(hps, fsCmd)
        !          1158: HPS  hps;
        !          1159: USHORT fsCmd;
        !          1160: {
        !          1161:     HRGN hrgn, hrgnClipOld, hrgnT;
        !          1162: 
        !          1163: 
        !          1164:     /* Clear the unused part of the client rectangle to a hatch pattern. */
        !          1165:     if (fsCmd & CLEAR_BACKGROUND)
        !          1166:        EraseBackground(hps);
        !          1167: 
        !          1168: 
        !          1169:     /* Set up the color mode as the user has requested */
        !          1170: 
        !          1171:     if (global.fRGB)
        !          1172:     {
        !          1173:        GpiCreateLogColorTable(hps, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL);
        !          1174:        if (global.hpsFat)
        !          1175:        {
        !          1176:            GpiCreateLogColorTable(global.hpsFat, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL);
        !          1177:            GpiCreateLogColorTable(global.hpsFatShadow, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL);
        !          1178:        }
        !          1179:     }
        !          1180:     else
        !          1181:        if (global.hpsFat)
        !          1182:        {
        !          1183:            GpiCreateLogColorTable(global.hpsFat, LCOL_RESET, LCOLF_INDRGB, 0L, 0L, NULL);
        !          1184:            GpiCreateLogColorTable(global.hpsFatShadow, LCOL_RESET, LCOLF_INDRGB, 0L, 0L, NULL);
        !          1185:            global.clrBlackIndex = GpiQueryColorIndex(hps, 0L, 0x000000L);
        !          1186:        }
        !          1187: 
        !          1188: 
        !          1189:     if (global.usPelShape == IDC_CIRCLE)
        !          1190:     {
        !          1191:        ARCPARAMS arcp;
        !          1192: 
        !          1193:        arcp.lP = global.cxFatPel / 2L;
        !          1194:        arcp.lQ = global.cyFatPel / 2L;
        !          1195:        arcp.lR = 0L;
        !          1196:        arcp.lS = 0L;
        !          1197: 
        !          1198:        GpiSetArcParams(hps, &arcp);
        !          1199:     }
        !          1200: 
        !          1201: 
        !          1202:     /* set clipping rectangle to the fatbit surface */
        !          1203: 
        !          1204:     if ((hrgn = GpiCreateRegion(hps, 1L, &global.rcl)) != HRGN_ERROR)
        !          1205:        GpiSetClipRegion(hps, hrgn, &hrgnClipOld);
        !          1206: 
        !          1207: 
        !          1208:     if (fsCmd & CLEAR_BACKGROUND)
        !          1209:     {
        !          1210:        DrawGrid(hps);
        !          1211: 
        !          1212:        if (global.hpsFatShadow)
        !          1213:        {
        !          1214:            AREABUNDLE ab;
        !          1215: 
        !          1216:            /* clear shadow fatpel surface to background color */
        !          1217:            ab.lColor = global.clrField;
        !          1218:            GpiSetAttrs(global.hpsFatShadow, PRIM_AREA, ABB_COLOR, 0L, &ab);
        !          1219:            GpiBitBlt(global.hpsFatShadow, NULL, 2L, (PPOINTL)&global.rclFat, ROP_PATCOPY, NULL);
        !          1220:        }
        !          1221:     }
        !          1222: 
        !          1223:     if (global.fDisplayRenderedObj && !(fsCmd & OVERRIDE_RENDERED_OBJ))
        !          1224:        DisplayRenderedPels(hps, fsCmd);
        !          1225: 
        !          1226:     if (global.fDisplayControlPoints)
        !          1227:     {
        !          1228:        /* when rubberbanding with the rendered obj, newly drawn fatpels
        !          1229:         * can wipe out stationary control point markers, so we have to
        !          1230:         * redraw them all each time
        !          1231:         */
        !          1232: 
        !          1233:        if (global.fDisplayRenderedObj || (fsCmd & CLEAR_BACKGROUND))
        !          1234:            DisplayControlPoints(hps, global.cptl, global.pptl, global.usMix);
        !          1235:        else if (global.sPtGrabbed != NO_POINT)
        !          1236:            /* draw just the control point that moved */
        !          1237:            DisplayControlPoints(hps, 1L, global.pptl+global.sPtGrabbed, global.usMix);
        !          1238:     }
        !          1239: 
        !          1240:     if (global.fDisplayMathObj)
        !          1241:        DisplayMathematicalObject(hps, global.usMix);
        !          1242: 
        !          1243:     /* delete the clip region we set up */
        !          1244: 
        !          1245:     if (hrgnClipOld != HRGN_ERROR)
        !          1246:        GpiSetClipRegion(hps, hrgnClipOld, &hrgnT);
        !          1247:     if (hrgn != HRGN_ERROR)
        !          1248:        GpiDestroyRegion(hps, hrgn);
        !          1249: }
        !          1250: 
        !          1251: 
        !          1252: 
        !          1253: 
        !          1254: /************************************************************************
        !          1255: *
        !          1256: *   DisplayMathematicalObject
        !          1257: *
        !          1258: ************************************************************************/
        !          1259: 
        !          1260: VOID
        !          1261: DisplayMathematicalObject(hps, usMix)
        !          1262: HPS hps;
        !          1263: USHORT usMix;
        !          1264: {
        !          1265:     PPOINTL pptl;
        !          1266:     LINEBUNDLE lb;
        !          1267: 
        !          1268:     if (global.cptl > 0)
        !          1269:     {
        !          1270:        if (global.fRoundControlPoints)
        !          1271:        {
        !          1272:            RoundControlPoints(hps, global.cptl, global.pptl, global.pptlTmp,
        !          1273:                               global.cxFatPel, global.cyFatPel);
        !          1274:            pptl = global.pptlTmp;
        !          1275:        }
        !          1276:        else
        !          1277:            pptl = global.pptl;
        !          1278: 
        !          1279:        /* draw line */
        !          1280:        lb.lColor    = global.clrMathObj;
        !          1281:        lb.usMixMode = usMix;
        !          1282:        GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR|LBB_MIX_MODE, 0L, &lb);
        !          1283:        DrawPrimitive(hps, global.cptl, pptl);
        !          1284:     }
        !          1285: }
        !          1286: 
        !          1287: 
        !          1288: 
        !          1289: 
        !          1290: /************************************************************************
        !          1291: *
        !          1292: *   DisplayControlPoints
        !          1293: *
        !          1294: ************************************************************************/
        !          1295: 
        !          1296: VOID
        !          1297: DisplayControlPoints(hps, cptl, pptl, usMix)
        !          1298: HPS hps;
        !          1299: LONG cptl;
        !          1300: PPOINTL pptl;
        !          1301: USHORT usMix;
        !          1302: {
        !          1303:     PPOINTL pptlT;
        !          1304:     MARKERBUNDLE mb;
        !          1305: 
        !          1306:     if (cptl > 0)
        !          1307:     {
        !          1308:        if (global.fRoundControlPoints)
        !          1309:        {
        !          1310:            RoundControlPoints(hps, cptl, pptl, global.pptlTmp,
        !          1311:                               global.cxFatPel, global.cyFatPel);
        !          1312:            pptlT = global.pptlTmp;
        !          1313:        }
        !          1314:        else
        !          1315:            pptlT = pptl;
        !          1316: 
        !          1317: 
        !          1318:        mb.lColor    = global.clrControlPoints;
        !          1319:        mb.usMixMode = usMix;
        !          1320:        mb.usSymbol  = global.usControlPointSymbol;
        !          1321:        GpiSetAttrs(hps, PRIM_MARKER, MBB_COLOR|MBB_MIX_MODE|MBB_SYMBOL, 0L, &mb);
        !          1322: 
        !          1323:        GpiPolyMarker(hps, cptl, pptlT);
        !          1324:     }
        !          1325: }
        !          1326: 
        !          1327: 
        !          1328: 
        !          1329: 
        !          1330: /************************************************************************
        !          1331: *
        !          1332: *   EraseBackground
        !          1333: *
        !          1334: *   Erase the unused part of the window to a hatch pattern.
        !          1335: *
        !          1336: ************************************************************************/
        !          1337: 
        !          1338: VOID
        !          1339: EraseBackground(hps)
        !          1340: HPS hps;
        !          1341: {
        !          1342:     RECTL rclClient, rclT;
        !          1343:     AREABUNDLE ab;
        !          1344: 
        !          1345: 
        !          1346:     WinQueryWindowRect(global.hwnd, &rclClient);
        !          1347: 
        !          1348:     ab.lColor    = CLR_BLACK;
        !          1349:     ab.lBackColor = CLR_WHITE;
        !          1350:     ab.usSymbol   = PATSYM_DIAG1;
        !          1351:     GpiSetAttrs(hps, PRIM_AREA, ABB_COLOR|ABB_BACK_COLOR|ABB_SYMBOL,
        !          1352:                0L, (PBUNDLE)&ab);
        !          1353: 
        !          1354:     if (global.rcl.yTop < rclClient.yTop)
        !          1355:     {
        !          1356:        rclT.xLeft   = rclClient.xLeft;
        !          1357:        rclT.yBottom = global.rcl.yBottom;
        !          1358:        rclT.xRight  = rclClient.xRight;
        !          1359:        rclT.yTop    = rclClient.yTop;
        !          1360:        GpiBitBlt(hps, NULL, 2L, (PPOINTL)&rclT, ROP_PATCOPY, NULL);
        !          1361:     }
        !          1362: 
        !          1363:     if (global.rcl.xRight < rclClient.xRight)
        !          1364:     {
        !          1365:        rclT.xLeft   = global.rcl.xRight;
        !          1366:        rclT.yBottom = rclClient.yBottom;
        !          1367:        rclT.xRight  = rclClient.xRight;
        !          1368:        rclT.yTop    = global.rcl.yTop;
        !          1369:        GpiBitBlt(hps, NULL, 2L, (PPOINTL)&rclT, ROP_PATCOPY, NULL);
        !          1370:     }
        !          1371: 
        !          1372:     ab.usSymbol   = PATSYM_SOLID;
        !          1373:     GpiSetAttrs(hps, PRIM_AREA, ABB_SYMBOL, 0L, (PBUNDLE)&ab);
        !          1374: }
        !          1375: 
        !          1376: 
        !          1377: 
        !          1378: 
        !          1379: /************************************************************************
        !          1380: *
        !          1381: *   DrawGrid
        !          1382: *
        !          1383: ************************************************************************/
        !          1384: 
        !          1385: VOID
        !          1386: DrawGrid(hps)
        !          1387: HPS  hps;
        !          1388: {
        !          1389:     AREABUNDLE ab;
        !          1390:     POINTL ptl;
        !          1391:     POINTL aptl[3];
        !          1392: 
        !          1393: 
        !          1394:     /* clear fatpel surface to background color */
        !          1395:     ab.lColor = global.clrInterstice;
        !          1396:     GpiSetAttrs(hps, PRIM_AREA, ABB_COLOR, 0L, &ab);
        !          1397:     GpiBitBlt(hps, NULL, 2L, (PPOINTL)&global.rcl, ROP_PATCOPY, NULL);
        !          1398: 
        !          1399: 
        !          1400:     /* draw one pel in lower left corner */
        !          1401: 
        !          1402:     ptl.x = global.cxFatPel / 2L;
        !          1403:     ptl.y = global.cyFatPel / 2L;
        !          1404:     DrawOneFatPel(hps, &ptl, global.clrField);
        !          1405: 
        !          1406: 
        !          1407:     /* blt up first column then across -- we don't have to worry
        !          1408:      * about the edges because a clip region has been setup to do that.
        !          1409:      */
        !          1410: 
        !          1411:     aptl[0].x = 0L;
        !          1412:     aptl[0].y = global.cyFatPel;
        !          1413:     aptl[1].x = global.cxFatPel;
        !          1414:     aptl[2].x = 0L;
        !          1415:     aptl[2].y = 0L;
        !          1416: 
        !          1417:     while (aptl[0].y <= global.rcl.yTop)
        !          1418:     {
        !          1419:        aptl[1].y  = aptl[0].y + aptl[0].y;
        !          1420:        GpiBitBlt(hps, hps, 3L, aptl, ROP_SRCCOPY, (LONG)NULL);
        !          1421:        aptl[0].y += aptl[1].y - aptl[0].y;
        !          1422:     }
        !          1423: 
        !          1424:     aptl[0].x = global.cxFatPel;
        !          1425:     aptl[0].y = 0L;
        !          1426:     aptl[1].y = global.rcl.yTop;
        !          1427:     aptl[2].x = 0L;
        !          1428:     aptl[2].y = 0L;
        !          1429: 
        !          1430:     while (aptl[0].x <= global.rcl.xRight)
        !          1431:     {
        !          1432:        aptl[1].x  = aptl[0].x + aptl[0].x;
        !          1433:        GpiBitBlt(hps, hps, 3L, aptl, ROP_SRCCOPY, (LONG)NULL);
        !          1434:        aptl[0].x += aptl[1].x - aptl[0].x;
        !          1435:     }
        !          1436: }
        !          1437: 
        !          1438: 
        !          1439: 
        !          1440: 
        !          1441: /************************************************************************
        !          1442: *
        !          1443: *   DisplayRenderedPels
        !          1444: *
        !          1445: ************************************************************************/
        !          1446: 
        !          1447: VOID
        !          1448: DisplayRenderedPels(hps, fsCmd)
        !          1449: HPS hps;
        !          1450: USHORT fsCmd;
        !          1451: {
        !          1452:     LINEBUNDLE lb;
        !          1453:     AREABUNDLE ab;
        !          1454:     POINTL aptl[3];
        !          1455: 
        !          1456:     /* Call GPI to draw the current primitive into the small bitmap,
        !          1457:      * then fatbit it to the display.
        !          1458:      */
        !          1459: 
        !          1460:     if (global.hbmFat)
        !          1461:     {
        !          1462:        if (fsCmd & CLEAR_FAT_BITMAP)
        !          1463:        {
        !          1464:            /* clear fatpel surface to background color */
        !          1465:            ab.lColor = global.clrField;
        !          1466:            GpiSetAttrs(global.hpsFat, PRIM_AREA, ABB_COLOR, 0L, &ab);
        !          1467:            GpiBitBlt(global.hpsFat, NULL, 2L, (PPOINTL)&global.rclFat, ROP_PATCOPY, NULL);
        !          1468:        }
        !          1469: 
        !          1470:        if (fsCmd & RENDER_MATH_OBJ)
        !          1471:        {
        !          1472:            if (global.cptl > 0)
        !          1473:            {
        !          1474:                /* draw line */
        !          1475:                lb.lColor = global.clrRenderedObj;
        !          1476:                GpiSetAttrs(global.hpsFat, PRIM_LINE, LBB_COLOR, 0L, &lb);
        !          1477:                GpiSetModelTransformMatrix(global.hpsFat, 9L,
        !          1478:                                          &global.matlf, TRANSFORM_REPLACE);
        !          1479:                DrawPrimitive(global.hpsFat, global.cptl, global.pptl);
        !          1480:                GpiSetModelTransformMatrix(global.hpsFat, 0L, NULL, TRANSFORM_REPLACE);
        !          1481:            }
        !          1482:        }
        !          1483: 
        !          1484:        /* xor the new rendered bitmap into the shadow bitmap */
        !          1485:        *((PRECTL)&aptl[0]) = global.rclFat;
        !          1486:        aptl[2].x = 0L;
        !          1487:        aptl[2].y = 0L;
        !          1488:        GpiBitBlt(global.hpsFatShadow, global.hpsFat, 3L, aptl, ROP_SRCINVERT, NULL);
        !          1489: 
        !          1490:        /* fatbit object to the display */
        !          1491:        DrawFatPels(hps);
        !          1492: 
        !          1493:        /* get the new shadow bitmap */
        !          1494:        GpiBitBlt(global.hpsFatShadow, global.hpsFat, 3L, aptl, ROP_SRCCOPY, NULL);
        !          1495:     }
        !          1496: }
        !          1497: 
        !          1498: 
        !          1499: 
        !          1500: 
        !          1501: /************************************************************************
        !          1502: *
        !          1503: *   DrawFatPels
        !          1504: *
        !          1505: ************************************************************************/
        !          1506: 
        !          1507: VOID
        !          1508: DrawFatPels(hps)
        !          1509: HPS hps;
        !          1510: {
        !          1511:     POINTL ptl, ptlCenter;
        !          1512:     LONG i, j;
        !          1513:     COLOR clr;
        !          1514: 
        !          1515: 
        !          1516:     /* if the pel size is 1,1, then just blt the small bitmap to the
        !          1517:      * display.
        !          1518:      */
        !          1519: 
        !          1520:     if ((global.cxFatPel == 1L) && (global.cyFatPel == 1L))
        !          1521:     {
        !          1522:        POINTL aptl[3];
        !          1523: 
        !          1524:        *((PRECTL)&aptl[0]) = global.rcl;
        !          1525:        aptl[2].x = 0L;
        !          1526:        aptl[2].y = 0L;
        !          1527:        GpiBitBlt(hps, global.hpsFat, 3L, aptl, ROP_SRCCOPY, 0L);
        !          1528: 
        !          1529:        return;
        !          1530:     }
        !          1531: 
        !          1532:     for (i = 0; i < global.rclFat.xRight; ++i)
        !          1533:        for (j = 0; j < global.rclFat.yTop; ++j)
        !          1534:        {
        !          1535:            ptl.x = i;
        !          1536:            ptl.y = j;
        !          1537: 
        !          1538:            clr = GpiQueryPel(global.hpsFatShadow, &ptl);
        !          1539:            if ((global.fRGB && (clr != 0x000000L)) ||
        !          1540:               (!global.fRGB && (clr != global.clrBlackIndex)))
        !          1541:            {
        !          1542:                clr = GpiQueryPel(global.hpsFat, &ptl);
        !          1543:                ptlCenter.x = (i * global.cxFatPel) + global.cxHalfFatPel;
        !          1544:                ptlCenter.y = (j * global.cyFatPel) + global.cyHalfFatPel;
        !          1545:                DrawOneFatPel(hps, &ptlCenter, clr);
        !          1546:            }
        !          1547:        }
        !          1548: }
        !          1549: 
        !          1550: 
        !          1551: 
        !          1552: 
        !          1553: /************************************************************************
        !          1554: *
        !          1555: *   DrawOneFatPel
        !          1556: *
        !          1557: ************************************************************************/
        !          1558: 
        !          1559: VOID
        !          1560: DrawOneFatPel(hps, pptl, clr)
        !          1561: HPS hps;
        !          1562: PPOINTL pptl;
        !          1563: COLOR clr;
        !          1564: {
        !          1565:     POINTL ptl;
        !          1566:     LINEBUNDLE lb;
        !          1567:     AREABUNDLE ab;
        !          1568: 
        !          1569: 
        !          1570:     if (global.fDisplayPelBorder || global.fDisplayCrossHairs)
        !          1571:     {
        !          1572:        lb.lColor = global.clrCrossHair;
        !          1573:        GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR, 0L, &lb);
        !          1574:     }
        !          1575: 
        !          1576:     ab.lColor = clr;
        !          1577:     GpiSetAttrs(hps, PRIM_AREA, ABB_COLOR, 0L, &ab);
        !          1578: 
        !          1579: 
        !          1580:     switch (global.usPelShape)
        !          1581:     {
        !          1582:     case IDC_SQUARE:
        !          1583:        {
        !          1584:            POINTL ptlT;
        !          1585:            ULONG flCmd;
        !          1586: 
        !          1587:            if (global.fDisplayPelBorder)
        !          1588:                flCmd = DRO_OUTLINEFILL;
        !          1589:            else
        !          1590:                flCmd = DRO_FILL;
        !          1591: 
        !          1592:            ptlT.x = pptl->x - global.cxHalfFatPel;
        !          1593:            ptlT.y = pptl->y - global.cyHalfFatPel;
        !          1594:            GpiSetCurrentPosition(hps, &ptlT);
        !          1595:            ptlT.x = pptl->x + global.cxHalfFatPel;
        !          1596:            ptlT.y = pptl->y + global.cyHalfFatPel;
        !          1597:            GpiBox(hps, flCmd, &ptlT, 0L, 0L);
        !          1598:        }
        !          1599:        break;
        !          1600: 
        !          1601:     case IDC_DIAMOND:
        !          1602:        {
        !          1603:            POINTL aptlT[4];
        !          1604:            ULONG flCmd;
        !          1605: 
        !          1606:            if (global.fDisplayPelBorder)
        !          1607:                flCmd = BA_BOUNDARY;
        !          1608:            else
        !          1609:                flCmd = 0L;
        !          1610: 
        !          1611:            aptlT[0].x = pptl->x;
        !          1612:            aptlT[0].y = pptl->y - global.cyHalfFatPel;
        !          1613:            aptlT[1].x = pptl->x - global.cxHalfFatPel;
        !          1614:            aptlT[1].y = pptl->y;
        !          1615:            aptlT[2].x = pptl->x;
        !          1616:            aptlT[2].y = pptl->y + global.cyHalfFatPel;
        !          1617:            aptlT[3].x = pptl->x + global.cxHalfFatPel;
        !          1618:            aptlT[3].y = pptl->y;
        !          1619: 
        !          1620:            GpiSetCurrentPosition(hps, &aptlT[3]);
        !          1621:            GpiBeginArea(hps, flCmd);
        !          1622:            GpiPolyLine(hps, 4L, aptlT);
        !          1623:            GpiEndArea(hps);
        !          1624:        }
        !          1625: 
        !          1626:        break;
        !          1627: 
        !          1628:     case IDC_CIRCLE:
        !          1629:        {
        !          1630:            ULONG flCmd;
        !          1631: 
        !          1632:            if (global.fDisplayPelBorder)
        !          1633:                flCmd = DRO_OUTLINEFILL;
        !          1634:            else
        !          1635:                flCmd = DRO_FILL;
        !          1636: 
        !          1637:            GpiSetCurrentPosition(hps, pptl);
        !          1638:            GpiFullArc(hps, flCmd, 0x10000L);
        !          1639:        }
        !          1640:        break;
        !          1641:     }
        !          1642: 
        !          1643: 
        !          1644:     if (global.fDisplayCrossHairs)
        !          1645:     {
        !          1646:        /* draw cross in center of pel */
        !          1647: 
        !          1648:        ptl.x = pptl->x - global.cxHalfFatPel;
        !          1649:        ptl.y = pptl->y;
        !          1650:        GpiSetCurrentPosition(hps, &ptl);
        !          1651:        ptl.x = pptl->x + global.cxHalfFatPel;
        !          1652:        GpiPolyLine(hps, 1L, &ptl);
        !          1653: 
        !          1654:        ptl.x = pptl->x;
        !          1655:        ptl.y = pptl->y - global.cyHalfFatPel;
        !          1656:        GpiSetCurrentPosition(hps, &ptl);
        !          1657:        ptl.y = pptl->y + global.cyHalfFatPel;
        !          1658:        GpiPolyLine(hps, 1L, &ptl);
        !          1659:     }
        !          1660: }
        !          1661: 
        !          1662: 
        !          1663: 
        !          1664: 
        !          1665: /************************************************************************
        !          1666: *
        !          1667: *   RoundControlPoints
        !          1668: *
        !          1669: ************************************************************************/
        !          1670: 
        !          1671: VOID
        !          1672: RoundControlPoints(hps, cptl, pptl1, pptl2, cx, cy)
        !          1673: HPS hps;
        !          1674: LONG cptl;
        !          1675: PPOINTL pptl1;
        !          1676: PPOINTL pptl2;
        !          1677: LONG cx;
        !          1678: LONG cy;
        !          1679: {
        !          1680:     LONG cx2, cy2;
        !          1681:     LONG i;
        !          1682:     MATRIXLF matlf;
        !          1683: 
        !          1684: 
        !          1685:     /* copy the input buffer to the output/scratch buffer */
        !          1686:     for (i = 0; i < cptl; ++i)
        !          1687:        pptl2[i] = pptl1[i];
        !          1688: 
        !          1689: 
        !          1690:     /* set the transform, transform the points to device space (i.e. to
        !          1691:      * hpsFat dimensions), then restore the original transform
        !          1692:      */
        !          1693:     GpiQueryModelTransformMatrix(hps, 9L, &matlf);
        !          1694:     GpiSetModelTransformMatrix(hps, 9L, &global.matlf, TRANSFORM_REPLACE);
        !          1695:     GpiConvert(hps, CVTC_WORLD, CVTC_DEVICE, cptl, pptl2);
        !          1696:     GpiSetModelTransformMatrix(hps, 9L, &matlf, TRANSFORM_REPLACE);
        !          1697: 
        !          1698: 
        !          1699:     /* position each point in the center of its fatpel */
        !          1700: 
        !          1701:     cx2 = cx / 2L;
        !          1702:     cy2 = cy / 2L;
        !          1703: 
        !          1704:     for (i = 0; i < cptl; ++i, ++pptl2)
        !          1705:     {
        !          1706:        pptl2->x = pptl2->x * cx + cx2;
        !          1707:        pptl2->y = pptl2->y * cy + cy2;
        !          1708:     }
        !          1709: }
        !          1710: 
        !          1711: 
        !          1712: 
        !          1713: 
        !          1714: /************************************************************************
        !          1715: *
        !          1716: *   ComputeTransform
        !          1717: *
        !          1718: ************************************************************************/
        !          1719: 
        !          1720: VOID
        !          1721: ComputeTransform(prcl1, prcl2)
        !          1722: PRECTL prcl1;
        !          1723: PRECTL prcl2;
        !          1724: {
        !          1725:     LONG xExt1, yExt1;
        !          1726:     LONG xExt2, yExt2;
        !          1727:     FIXED xScale, yScale;
        !          1728: 
        !          1729: 
        !          1730:     xExt1 = prcl1->xRight - prcl1->xLeft;
        !          1731:     yExt1 = prcl1->yTop   - prcl1->yBottom;
        !          1732:     xExt2 = prcl2->xRight - prcl2->xLeft;
        !          1733:     yExt2 = prcl2->yTop   - prcl2->yBottom;
        !          1734: 
        !          1735: 
        !          1736:     /* If the rectangles are of exactly the same dimensions, then
        !          1737:      * set the unity transform.  If not, compute the x and y scale
        !          1738:      * factors.  Note that in world coordinates rectangles are
        !          1739:      * inclusive-inclusive, whereas in device coordinates they are
        !          1740:      * inclusive-exclusive.  The extents of the destination are
        !          1741:      * therefore one pel too large as computed, so we subtract one
        !          1742:      * in the scale factor computation.
        !          1743:      */
        !          1744: 
        !          1745:     if (xExt1 == xExt2)
        !          1746:        xScale = 0x10000L;
        !          1747:     else
        !          1748:        xScale = ((xExt2-1L) * 0x10000L) / xExt1;
        !          1749: 
        !          1750:     if (yExt1 == yExt2)
        !          1751:        yScale = 0x10000L;
        !          1752:     else
        !          1753:        yScale = ((yExt2-1L) * 0x10000L) / yExt1;
        !          1754: 
        !          1755: 
        !          1756:     /* store the transform matrix for easy access */
        !          1757: 
        !          1758:     global.matlf.fxM11 = xScale;
        !          1759:     global.matlf.fxM12 = 0L;
        !          1760:     global.matlf. lM13 = 0L;
        !          1761:     global.matlf.fxM21 = 0L;
        !          1762:     global.matlf.fxM22 = yScale;
        !          1763:     global.matlf. lM23 = 0L;
        !          1764:     global.matlf. lM31 = 0L;
        !          1765:     global.matlf. lM32 = 0L;
        !          1766:     global.matlf. lM33 = 1L;
        !          1767: }
        !          1768: 
        !          1769: 
        !          1770: 
        !          1771: 
        !          1772: /************************************************************************
        !          1773: *
        !          1774: *   DrawPrimitive
        !          1775: *
        !          1776: ************************************************************************/
        !          1777: 
        !          1778: VOID
        !          1779: DrawPrimitive(hps, cptl, pptl)
        !          1780: HPS hps;
        !          1781: LONG cptl;
        !          1782: PPOINTL pptl;
        !          1783: {
        !          1784:     switch (global.usCurPrim)
        !          1785:     {
        !          1786:     case IDM_NOPRIM:
        !          1787:        break;
        !          1788: 
        !          1789:     case IDM_POLYLINE:
        !          1790:        GpiSetCurrentPosition(hps, pptl);
        !          1791:        GpiPolyLine(hps, cptl-1L, pptl + 1);
        !          1792:        break;
        !          1793: 
        !          1794:     case IDM_POLYFILLET:
        !          1795:        if (cptl >= 3L)
        !          1796:        {
        !          1797:            GpiSetCurrentPosition(hps, pptl);
        !          1798:            GpiPolyFillet(hps, cptl-1L, pptl + 1);
        !          1799:        }
        !          1800:        break;
        !          1801: 
        !          1802:     case IDM_POLYSPLINE:
        !          1803:        if (cptl >= 4L)
        !          1804:        {
        !          1805:            LONG cptSlack;    /* # points in pptl not usable by PolySpline */
        !          1806: 
        !          1807:            cptSlack = ((cptl-1L) % 3) + 1;
        !          1808:            GpiSetCurrentPosition( hps, pptl );
        !          1809:            GpiPolySpline( hps, cptl-cptSlack, pptl+1 );
        !          1810:        }
        !          1811:        break;
        !          1812: 
        !          1813:     case IDM_POINTARC:
        !          1814:        if (cptl >= 3L)
        !          1815:        {
        !          1816:            GpiSetCurrentPosition( hps, pptl );
        !          1817:            GpiPointArc( hps, pptl+1 );
        !          1818:        }
        !          1819:        break;
        !          1820:     }
        !          1821: }
        !          1822: 
        !          1823: 
        !          1824: 
        !          1825: 
        !          1826: /************************************************************************
        !          1827: *
        !          1828: *   UpdateSurfaceDims
        !          1829: *
        !          1830: ************************************************************************/
        !          1831: 
        !          1832: VOID
        !          1833: UpdateSurfaceDims()
        !          1834: {
        !          1835:     SIZEL size;
        !          1836:     static BITMAPINFOHEADER2 bminfo;
        !          1837:     AREABUNDLE ab;
        !          1838: 
        !          1839: 
        !          1840:     WinQueryWindowRect(global.hwnd, &global.rcl);
        !          1841: 
        !          1842:     /* compute size of small surface */
        !          1843:     global.rclFat.xLeft   = 0L;
        !          1844:     global.rclFat.yBottom = 0L;
        !          1845:     global.rclFat.xRight  = global.rcl.xRight / global.cxFatPel;
        !          1846:     global.rclFat.yTop   = global.rcl.yTop   / global.cyFatPel;
        !          1847: 
        !          1848:     /* compute size of fatpel version of small surface */
        !          1849:     global.rcl.xLeft   = 0L;
        !          1850:     global.rcl.yBottom = 0L;
        !          1851:     global.rcl.xRight  = global.rclFat.xRight * global.cxFatPel;
        !          1852:     global.rcl.yTop    = global.rclFat.yTop   * global.cyFatPel;
        !          1853: 
        !          1854:     ComputeTransform(&global.rcl, &global.rclFat);
        !          1855: 
        !          1856:     if ((global.rclFat.xRight <= global.rclFatBM.xRight) &&
        !          1857:        (global.rclFat.yTop   <= global.rclFatBM.yTop))
        !          1858:        return;
        !          1859: 
        !          1860: 
        !          1861: 
        !          1862:     /* The new fatbits surface doesn't fit in the bitmap, so we
        !          1863:      * have to make a new one. If we don't have a DC or PS, make
        !          1864:      * those before making the bitmap. If we do have a bitmap,
        !          1865:      * delete it before making the new one.
        !          1866:      */
        !          1867: 
        !          1868:     global.rclFatBM = global.rclFat;
        !          1869: 
        !          1870:     if (global.hbmFat)
        !          1871:     {
        !          1872:        GpiSetBitmap(global.hpsFat, NULL);
        !          1873:        GpiDeleteBitmap(global.hbmFat);
        !          1874:        GpiSetBitmap(global.hpsFatShadow, NULL);
        !          1875:        GpiDeleteBitmap(global.hbmFatShadow);
        !          1876:     }
        !          1877: 
        !          1878:     if (!global.hdcFat)
        !          1879:     {
        !          1880:        global.hdcFat = DevOpenDC(global.hab, OD_MEMORY, "*", 0L, NULL, NULL);
        !          1881:        if (!global.hdcFat)
        !          1882:            goto usd_error;
        !          1883: 
        !          1884:        global.hdcFatShadow = DevOpenDC(global.hab, OD_MEMORY, "*", 0L, NULL, NULL);
        !          1885:        if (!global.hdcFatShadow)
        !          1886:            goto usd_error;
        !          1887:     }
        !          1888: 
        !          1889:     if (!global.hpsFat)
        !          1890:     {
        !          1891:        size.cx = 0L;
        !          1892:        size.cy = 0L;
        !          1893:        global.hpsFat = GpiCreatePS(global.hab, global.hdcFat, &size,
        !          1894:                                 PU_PELS|GPIT_MICRO|GPIA_ASSOC);
        !          1895:        if (!global.hpsFat)
        !          1896:            goto usd_error;
        !          1897: 
        !          1898:        global.hpsFatShadow = GpiCreatePS(global.hab, global.hdcFatShadow, &size,
        !          1899:                                 PU_PELS|GPIT_MICRO|GPIA_ASSOC);
        !          1900:        if (!global.hpsFatShadow)
        !          1901:            goto usd_error;
        !          1902:     }
        !          1903: 
        !          1904:     /* create bitmap with maximum color resolution (24-bit color) */
        !          1905:     bminfo.cbFix = sizeof(BITMAPINFOHEADER2);
        !          1906:     bminfo.cx = (USHORT) (global.rclFatBM.xRight - global.rclFatBM.xLeft);
        !          1907:     bminfo.cy = (USHORT) (global.rclFatBM.yTop  - global.rclFatBM.yBottom);
        !          1908:     bminfo.cPlanes   = 1L;
        !          1909:     bminfo.cBitCount = 24L;
        !          1910:     global.hbmFat = GpiCreateBitmap(global.hpsFat, &bminfo, 0L, 0L, 0L);
        !          1911:     if (!global.hbmFat)
        !          1912:        goto usd_error;
        !          1913:     GpiSetBitmap(global.hpsFat, global.hbmFat);
        !          1914: 
        !          1915:     /* create a shadow bitmap of the one we just created */
        !          1916:     bminfo.cbFix = sizeof(BITMAPINFOHEADER2);
        !          1917:     bminfo.cx = (USHORT) (global.rclFatBM.xRight - global.rclFatBM.xLeft);
        !          1918:     bminfo.cy = (USHORT) (global.rclFatBM.yTop  - global.rclFatBM.yBottom);
        !          1919:     bminfo.cPlanes   = 1L;
        !          1920:     bminfo.cBitCount = 24L;
        !          1921:     global.hbmFatShadow = GpiCreateBitmap(global.hpsFatShadow, &bminfo, 0L, 0L, 0L);
        !          1922:     if (!global.hbmFat)
        !          1923:        goto usd_error;
        !          1924:     GpiSetBitmap(global.hpsFatShadow, global.hbmFatShadow);
        !          1925: 
        !          1926:     /* clear bitmap surface to field color */
        !          1927:     ab.lColor = global.clrField;
        !          1928:     GpiSetAttrs(global.hpsFat, PRIM_AREA, ABB_COLOR, 0L, &ab);
        !          1929:     GpiBitBlt(global.hpsFat, NULL, 2L, (PPOINTL)&global.rclFat, ROP_PATCOPY, NULL);
        !          1930: 
        !          1931:     return;
        !          1932: 
        !          1933: 
        !          1934: /* error exit point */
        !          1935: 
        !          1936: usd_error:
        !          1937:     if (global.hpsFat)
        !          1938:        GpiDestroyPS(global.hpsFat);
        !          1939:     if (global.hpsFatShadow)
        !          1940:        GpiDestroyPS(global.hpsFatShadow);
        !          1941:     if (global.hdcFat)
        !          1942:        DevCloseDC(global.hdcFat);
        !          1943:     if (global.hdcFatShadow)
        !          1944:        DevCloseDC(global.hdcFatShadow);
        !          1945: 
        !          1946:     global.hpsFat      = NULL;
        !          1947:     global.hdcFat      = NULL;
        !          1948:     global.hpsFatShadow = NULL;
        !          1949:     global.hdcFatShadow = NULL;
        !          1950: }
        !          1951: 
        !          1952: 
        !          1953: 
        !          1954: 
        !          1955: /************************************************************************
        !          1956: *
        !          1957: *   AboutDlg
        !          1958: *
        !          1959: *   Process messages for the About box.
        !          1960: *
        !          1961: ************************************************************************/
        !          1962: 
        !          1963: MRESULT EXPENTRY
        !          1964: AboutDlg(hwnd, usMsg, mp1, mp2)
        !          1965: HWND   hwnd;
        !          1966: USHORT usMsg;
        !          1967: MPARAM mp1;
        !          1968: MPARAM mp2;
        !          1969: {
        !          1970:     switch (usMsg)
        !          1971:     {
        !          1972:     case WM_COMMAND:
        !          1973:        if (SHORT1FROMMP(mp1) == DID_OK)
        !          1974:            WinDismissDlg(hwnd, TRUE);
        !          1975:        else
        !          1976:            return FALSE;
        !          1977:        break;
        !          1978: 
        !          1979:     default:
        !          1980:        return (MRESULT)WinDefDlgProc(hwnd, usMsg, mp1, mp2);
        !          1981:     }
        !          1982:     return FALSE;
        !          1983: }
        !          1984: 
        !          1985: 
        !          1986: 
        !          1987: 
        !          1988: /************************************************************************
        !          1989: *
        !          1990: *   PelSizeDlg
        !          1991: *
        !          1992: *   Process messages for the Pel Size dialog box.
        !          1993: *
        !          1994: ************************************************************************/
        !          1995: 
        !          1996: MRESULT EXPENTRY
        !          1997: PelSizeDlg(hwnd, usMsg, mp1, mp2)
        !          1998: HWND   hwnd;
        !          1999: USHORT usMsg;
        !          2000: MPARAM mp1;
        !          2001: MPARAM mp2;
        !          2002: {
        !          2003:     BOOL fRet = FALSE;
        !          2004: 
        !          2005:     switch (usMsg)
        !          2006:     {
        !          2007:     case WM_INITDLG:
        !          2008:        MySetWindowLong(hwnd, IDC_PELWIDTH,  global.cxFatPel);
        !          2009:        MySetWindowLong(hwnd, IDC_PELHEIGHT, global.cyFatPel);
        !          2010:        WinSendDlgItemMsg(hwnd, global.usPelShape,
        !          2011:                          BM_SETCHECK, (MPARAM)TRUE, 0L);
        !          2012:        return FALSE;
        !          2013:        break;
        !          2014: 
        !          2015:     case WM_COMMAND:
        !          2016:        switch (SHORT1FROMMP(mp1))
        !          2017:        {
        !          2018:        case DID_OK:
        !          2019:            global.cxFatPel = MyGetWindowLong(hwnd, IDC_PELWIDTH);
        !          2020:            global.cyFatPel = MyGetWindowLong(hwnd, IDC_PELHEIGHT);
        !          2021: 
        !          2022:            if (global.cxFatPel < 1L)
        !          2023:                global.cxFatPel = 1L;
        !          2024: 
        !          2025:            if (global.cyFatPel < 1L)
        !          2026:                global.cyFatPel = 1L;
        !          2027: 
        !          2028:            global.cxHalfFatPel = global.cxFatPel / 2L;
        !          2029:            global.cyHalfFatPel = global.cyFatPel / 2L;
        !          2030: 
        !          2031:            global.usPelShape = (USHORT) WinSendDlgItemMsg(hwnd, IDC_SQUARE,
        !          2032:                                   BM_QUERYCHECKINDEX, 0L, 0L) + IDC_SQUARE;
        !          2033: 
        !          2034: 
        !          2035:            UpdateSurfaceDims();
        !          2036: 
        !          2037:            fRet = TRUE;
        !          2038: 
        !          2039:            /* fall through to some common code */
        !          2040: 
        !          2041:        case DID_CANCEL:
        !          2042:            WinDismissDlg(hwnd, fRet);
        !          2043:            break;
        !          2044: 
        !          2045:        default:
        !          2046:            return FALSE;
        !          2047:        }
        !          2048:        break;
        !          2049: 
        !          2050:     default:
        !          2051:        return (MRESULT)WinDefDlgProc(hwnd, usMsg, mp1, mp2);
        !          2052:     }
        !          2053:     return FALSE;
        !          2054: }
        !          2055: 
        !          2056: 
        !          2057: 
        !          2058: 
        !          2059: /************************************************************************
        !          2060: *
        !          2061: *   ColorsDlg
        !          2062: *
        !          2063: *   Process messages for the Set Colors dialog box.
        !          2064: *
        !          2065: ************************************************************************/
        !          2066: 
        !          2067: MRESULT EXPENTRY
        !          2068: ColorsDlg(hwnd, usMsg, mp1, mp2)
        !          2069: HWND   hwnd;
        !          2070: USHORT usMsg;
        !          2071: MPARAM mp1;
        !          2072: MPARAM mp2;
        !          2073: {
        !          2074:     BOOL fRet = FALSE;
        !          2075:     BOOL fRGB;
        !          2076:     COLOR clrMathObj;
        !          2077:     COLOR clrRenderedObj;
        !          2078:     COLOR clrField;
        !          2079:     COLOR clrCrossHair;
        !          2080:     COLOR clrInterstice;
        !          2081:     COLOR clrControlPoints;
        !          2082: 
        !          2083:     switch (usMsg)
        !          2084:     {
        !          2085:     case WM_INITDLG:
        !          2086:        if (global.fRGB)
        !          2087:        {
        !          2088:            MySetWindowLongHex(hwnd, IDC_MATHOBJ,     global.clrMathObj);
        !          2089:            MySetWindowLongHex(hwnd, IDC_RENDEREDOBJ, global.clrRenderedObj);
        !          2090:            MySetWindowLongHex(hwnd, IDC_FIELD,      global.clrField);
        !          2091:            MySetWindowLongHex(hwnd, IDC_CROSSHAIRS,  global.clrCrossHair);
        !          2092:            MySetWindowLongHex(hwnd, IDC_INTERSTICE,  global.clrInterstice);
        !          2093:            MySetWindowLongHex(hwnd, IDC_CTLPOINTS,   global.clrControlPoints);
        !          2094:        }
        !          2095:        else
        !          2096:        {
        !          2097:            MySetWindowLong   (hwnd, IDC_MATHOBJ,     global.clrMathObj);
        !          2098:            MySetWindowLong   (hwnd, IDC_RENDEREDOBJ, global.clrRenderedObj);
        !          2099:            MySetWindowLong   (hwnd, IDC_FIELD,      global.clrField);
        !          2100:            MySetWindowLong   (hwnd, IDC_CROSSHAIRS,  global.clrCrossHair);
        !          2101:            MySetWindowLong   (hwnd, IDC_INTERSTICE,  global.clrInterstice);
        !          2102:            MySetWindowLong   (hwnd, IDC_CTLPOINTS,   global.clrControlPoints);
        !          2103:        }
        !          2104:        WinSendDlgItemMsg(hwnd, IDC_RGB, BM_SETCHECK, MPFROM2SHORT(global.fRGB,0), 0L);
        !          2105:        return FALSE;
        !          2106:        break;
        !          2107: 
        !          2108:     case WM_CONTROL:
        !          2109:        if ((SHORT1FROMMP(mp1) == IDC_RGB) && (SHORT2FROMMP(mp1)== BN_CLICKED))
        !          2110:        {
        !          2111:            fRGB = !(SHORT)WinSendDlgItemMsg(hwnd, IDC_RGB, BM_QUERYCHECK, 0L, 0L);
        !          2112:            WinSendDlgItemMsg(hwnd, IDC_RGB, BM_SETCHECK, MPFROM2SHORT(fRGB,0), 0L);
        !          2113: 
        !          2114:            clrMathObj       = MyGetWindowLong(hwnd, IDC_MATHOBJ);
        !          2115:            clrRenderedObj   = MyGetWindowLong(hwnd, IDC_RENDEREDOBJ);
        !          2116:            clrField         = MyGetWindowLong(hwnd, IDC_FIELD);
        !          2117:            clrCrossHair     = MyGetWindowLong(hwnd, IDC_CROSSHAIRS);
        !          2118:            clrInterstice    = MyGetWindowLong(hwnd, IDC_INTERSTICE);
        !          2119:            clrControlPoints = MyGetWindowLong(hwnd, IDC_CTLPOINTS);
        !          2120: 
        !          2121:            if (fRGB)
        !          2122:            {
        !          2123:                HPS hps;
        !          2124: 
        !          2125:                /* for each color, get rgb value from index */
        !          2126: 
        !          2127:                hps = WinGetPS(hwnd);
        !          2128: 
        !          2129:                clrMathObj       = GpiQueryRGBColor(hps, 0L, clrMathObj);
        !          2130:                clrRenderedObj   = GpiQueryRGBColor(hps, 0L, clrRenderedObj);
        !          2131:                clrField         = GpiQueryRGBColor(hps, 0L, clrField);
        !          2132:                clrCrossHair     = GpiQueryRGBColor(hps, 0L, clrCrossHair);
        !          2133:                clrInterstice    = GpiQueryRGBColor(hps, 0L, clrInterstice);
        !          2134:                clrControlPoints = GpiQueryRGBColor(hps, 0L, clrControlPoints);
        !          2135: 
        !          2136:                WinReleasePS(hps);
        !          2137: 
        !          2138:                MySetWindowLongHex(hwnd, IDC_MATHOBJ,    clrMathObj);
        !          2139:                MySetWindowLongHex(hwnd, IDC_RENDEREDOBJ, clrRenderedObj);
        !          2140:                MySetWindowLongHex(hwnd, IDC_FIELD,      clrField);
        !          2141:                MySetWindowLongHex(hwnd, IDC_CROSSHAIRS,  clrCrossHair);
        !          2142:                MySetWindowLongHex(hwnd, IDC_INTERSTICE,  clrInterstice);
        !          2143:                MySetWindowLongHex(hwnd, IDC_CTLPOINTS,  clrControlPoints);
        !          2144:            }
        !          2145:            else
        !          2146:            {
        !          2147:                HPS hps;
        !          2148: 
        !          2149:                /* for each color, get nearest index value from rgb */
        !          2150: 
        !          2151:                hps = WinGetPS(hwnd);
        !          2152: 
        !          2153:                clrMathObj       = GpiQueryColorIndex(hps, 0L, clrMathObj);
        !          2154:                clrRenderedObj   = GpiQueryColorIndex(hps, 0L, clrRenderedObj);
        !          2155:                clrField         = GpiQueryColorIndex(hps, 0L, clrField);
        !          2156:                clrCrossHair     = GpiQueryColorIndex(hps, 0L, clrCrossHair);
        !          2157:                clrInterstice    = GpiQueryColorIndex(hps, 0L, clrInterstice);
        !          2158:                clrControlPoints = GpiQueryColorIndex(hps, 0L, clrControlPoints);
        !          2159: 
        !          2160:                WinReleasePS(hps);
        !          2161: 
        !          2162:                MySetWindowLong   (hwnd, IDC_MATHOBJ,    clrMathObj);
        !          2163:                MySetWindowLong   (hwnd, IDC_RENDEREDOBJ, clrRenderedObj);
        !          2164:                MySetWindowLong   (hwnd, IDC_FIELD,      clrField);
        !          2165:                MySetWindowLong   (hwnd, IDC_CROSSHAIRS,  clrCrossHair);
        !          2166:                MySetWindowLong   (hwnd, IDC_INTERSTICE,  clrInterstice);
        !          2167:                MySetWindowLong   (hwnd, IDC_CTLPOINTS,  clrControlPoints);
        !          2168:            }
        !          2169:        }
        !          2170:        return (MRESULT)WinDefDlgProc(hwnd, usMsg, mp1, mp2);
        !          2171:        break;
        !          2172: 
        !          2173:     case WM_COMMAND:
        !          2174:        switch (SHORT1FROMMP(mp1))
        !          2175:        {
        !          2176:        case DID_OK:
        !          2177:            global.clrMathObj       = MyGetWindowLong(hwnd, IDC_MATHOBJ);
        !          2178:            global.clrRenderedObj   = MyGetWindowLong(hwnd, IDC_RENDEREDOBJ);
        !          2179:            global.clrField         = MyGetWindowLong(hwnd, IDC_FIELD);
        !          2180:            global.clrCrossHair     = MyGetWindowLong(hwnd, IDC_CROSSHAIRS);
        !          2181:            global.clrInterstice    = MyGetWindowLong(hwnd, IDC_INTERSTICE);
        !          2182:            global.clrControlPoints = MyGetWindowLong(hwnd, IDC_CTLPOINTS);
        !          2183: 
        !          2184:            global.fRGB = (SHORT)WinSendDlgItemMsg(hwnd, IDC_RGB, BM_QUERYCHECK, 0L, 0L);
        !          2185: 
        !          2186:            fRet = TRUE;
        !          2187: 
        !          2188:            /* fall through to some common code */
        !          2189: 
        !          2190:        case DID_CANCEL:
        !          2191:            WinDismissDlg(hwnd, fRet);
        !          2192:            break;
        !          2193: 
        !          2194:        default:
        !          2195:            return FALSE;
        !          2196:        }
        !          2197:        break;
        !          2198: 
        !          2199:     default:
        !          2200:        return (MRESULT)WinDefDlgProc(hwnd, usMsg, mp1, mp2);
        !          2201:     }
        !          2202:     return FALSE;
        !          2203: }
        !          2204: 
        !          2205: 
        !          2206: 
        !          2207: 
        !          2208: /************************************************************************
        !          2209: *
        !          2210: *   MySetWindowLong
        !          2211: *
        !          2212: *   Sets the given control id to the value specified.
        !          2213: *
        !          2214: ************************************************************************/
        !          2215: 
        !          2216: VOID
        !          2217: MySetWindowLong(hWnd, id, num)
        !          2218: HWND hWnd;
        !          2219: USHORT id;
        !          2220: LONG num;
        !          2221: {
        !          2222:     char szStr[CCHSTR];
        !          2223: 
        !          2224:     sprintf((NPCH)szStr, "%ld", num);
        !          2225:     WinSetWindowText(WinWindowFromID(hWnd, id), (PCH)szStr);
        !          2226: }
        !          2227: 
        !          2228: 
        !          2229: 
        !          2230: 
        !          2231: /************************************************************************
        !          2232: *
        !          2233: *   MySetWindowLongHex
        !          2234: *
        !          2235: *   Sets the given control id to the value specified, in hexadecimal
        !          2236: *   notation.
        !          2237: *
        !          2238: ************************************************************************/
        !          2239: 
        !          2240: VOID
        !          2241: MySetWindowLongHex(hWnd, id, num)
        !          2242: HWND hWnd;
        !          2243: USHORT id;
        !          2244: LONG num;
        !          2245: {
        !          2246:     char szStr[CCHSTR];
        !          2247: 
        !          2248:     sprintf((NPCH)szStr, "0x%06lX", num);
        !          2249:     WinSetWindowText(WinWindowFromID(hWnd, id), (PCH)szStr);
        !          2250: }
        !          2251: 
        !          2252: 
        !          2253: 
        !          2254: 
        !          2255: /************************************************************************
        !          2256: *
        !          2257: *   MyGetWindowLong
        !          2258: *
        !          2259: *   Returns the value from the given control id.
        !          2260: *
        !          2261: ************************************************************************/
        !          2262: 
        !          2263: LONG
        !          2264: MyGetWindowLong(hWnd, id)
        !          2265: HWND hWnd;
        !          2266: USHORT id;
        !          2267: {
        !          2268:     char szStr[CCHSTR];
        !          2269:     LONG num;
        !          2270: 
        !          2271:     WinQueryWindowText(WinWindowFromID(hWnd, id), CCHSTR, (PCH)szStr);
        !          2272: 
        !          2273:     if (strchr(szStr, 'x'))
        !          2274:        sscanf((NPCH)szStr, "0x%lx", &num);
        !          2275:     else if (strchr(szStr, 'X'))
        !          2276:        sscanf((NPCH)szStr, "0X%lx", &num);
        !          2277:     else
        !          2278:        sscanf((NPCH)szStr, "%ld", &num);
        !          2279: 
        !          2280:     return num;
        !          2281: }
        !          2282: 
        !          2283: 
        !          2284: 
        !          2285: 
        !          2286: /************************************************************************
        !          2287: *
        !          2288: *   SaveWindowToFile
        !          2289: *
        !          2290: *   Copy the bits from the client rectangle (actually, just the fatpel
        !          2291: *   area) into a bitmap, then save that bitmap.
        !          2292: *
        !          2293: ************************************************************************/
        !          2294: 
        !          2295: VOID
        !          2296: SaveWindowToFile(hwnd)
        !          2297: HWND hwnd;
        !          2298: {
        !          2299:     static BITMAPINFOHEADER2 bminfo;
        !          2300:     HBITMAP hbm;
        !          2301:     HPS hps;
        !          2302:     POINTL aptl[3];
        !          2303: 
        !          2304:     /* create bitmap in display's favorite format */
        !          2305:     bminfo.cbFix = sizeof(BITMAPINFOHEADER2);
        !          2306:     bminfo.cx = (USHORT) (global.rcl.xRight - global.rcl.xLeft);
        !          2307:     bminfo.cy = (USHORT) (global.rcl.yTop   - global.rcl.yBottom);
        !          2308:     bminfo.cPlanes   = 0L;
        !          2309:     bminfo.cBitCount = 0L;
        !          2310:     if (hbm = GpiCreateBitmap(global.hpsFat, &bminfo, 0L, 0L, 0L))
        !          2311:     {
        !          2312:        /* select it into the small bitmap's PS */
        !          2313:        GpiSetBitmap(global.hpsFat, hbm);
        !          2314: 
        !          2315:        /* GpiBitBlt from the window to the bitmap */
        !          2316:        hps = WinGetPS(hwnd);
        !          2317: 
        !          2318:        *((PRECTL)&aptl[0]) = global.rcl;
        !          2319:        aptl[2].x = 0L;
        !          2320:        aptl[2].y = 0L;
        !          2321:        GpiBitBlt(global.hpsFat, hps, 3L, aptl, ROP_SRCCOPY, 0L);
        !          2322: 
        !          2323:        WinReleasePS(hps);
        !          2324: 
        !          2325:        /* save the bitmap */
        !          2326:        WriteFile(hwnd, global.hpsFat);
        !          2327:     }
        !          2328: 
        !          2329:     /* deselect the bitmap and delete it */
        !          2330:     GpiSetBitmap(global.hpsFat, global.hbmFat);
        !          2331:     if (hbm)
        !          2332:        GpiDeleteBitmap(hbm);
        !          2333: }
        !          2334: 
        !          2335: 
        !          2336: 
        !          2337: 
        !          2338: /************************************************************************
        !          2339: *
        !          2340: *   WriteFile
        !          2341: *
        !          2342: *   Calls the OpenDlg's DlgFile function to ask the user what file name to
        !          2343: *   save under.
        !          2344: *
        !          2345: ************************************************************************/
        !          2346: 
        !          2347: VOID
        !          2348: WriteFile(hwnd, hps)
        !          2349: HWND hwnd;
        !          2350: HPS hps;
        !          2351: {
        !          2352:     HFILE hfile;
        !          2353:     DLF dlf;
        !          2354:     BITMAPINFOHEADER2 bmih;
        !          2355: 
        !          2356:     dlf.rgbAction      = DLG_SAVEDLG;
        !          2357:     dlf.rgbFlags       = 0;
        !          2358:     dlf.phFile         = &hfile;
        !          2359:     dlf.pszExt         = "";
        !          2360:     dlf.pszAppName     = "FatPel";
        !          2361:     dlf.pszInstructions = NULL;
        !          2362:     dlf.szFileName[0]  = '\0';
        !          2363:     dlf.szOpenFile[0]  = '\0';
        !          2364:     dlf.pszTitle       = "Save Bitmap";
        !          2365: 
        !          2366: 
        !          2367:     switch (DlgFile(hwnd,&dlf))
        !          2368:     {
        !          2369:     case TDF_ERRMEM:
        !          2370:     case TDF_INVALID:
        !          2371:        MyMessageBox(hwnd, "Error opening file.");
        !          2372:        break;
        !          2373: 
        !          2374:     case TDF_NOSAVE:
        !          2375:        break;
        !          2376: 
        !          2377:     default:
        !          2378:        bmih.cbFix     = sizeof(BITMAPINFOHEADER2);
        !          2379:        bmih.cx        = (USHORT) global.rcl.xRight;
        !          2380:        bmih.cy        = (USHORT) global.rcl.yTop;
        !          2381:        bmih.cPlanes   = 0L;
        !          2382:        bmih.cBitCount = 0L;
        !          2383: 
        !          2384:        if (!WriteBMP(hfile, hps, &bmih))
        !          2385:            MyMessageBox(hwnd, "Error writing file.");
        !          2386:     }
        !          2387: }
        !          2388: 
        !          2389: 
        !          2390: 
        !          2391: 
        !          2392: /************************************************************************
        !          2393: *
        !          2394: *   WriteBMP
        !          2395: *
        !          2396: *   Write the bitmap out to a BMP format file. Write the file
        !          2397: *   header first, then the bitmap bits.  Space for the header
        !          2398: *   and the bits is allocated.  The file
        !          2399: *   will have been opened by the time this function is called,
        !          2400: *   and the file handle will be in the *pdlf structure.
        !          2401: *
        !          2402: ************************************************************************/
        !          2403: 
        !          2404: BOOL
        !          2405: WriteBMP(hfile, hps, pbmih)
        !          2406: HFILE hfile;
        !          2407: HPS hps;                /* hps from which to get bitmap bits.     */
        !          2408: PBITMAPINFOHEADER2 pbmih; /* Bitmap information.                  */
        !          2409: {
        !          2410:     ULONG cScans;
        !          2411:     ULONG ulSize;       /* Number of bytes occupied by bitmap bits.         */
        !          2412:     ULONG cbBMHdr;      /* Size of bitmap header.                           */
        !          2413:     PBITMAPFILEHEADER2 pbfh; /* Pointer to private copy of bitmap info data.   */
        !          2414:     ULONG cbWritten;    /* Number of bytes written by DosWrite.             */
        !          2415:     BOOL fRet = FALSE;  /* Function return code.                            */
        !          2416:     PVOID      pBits;
        !          2417:     int i;              /* Generic loop index.                              */
        !          2418:     struct
        !          2419:     {
        !          2420:        LONG cPlanes;
        !          2421:        LONG cBitCount;
        !          2422:     } bmFmt;
        !          2423: 
        !          2424: 
        !          2425:     /*******************************************************************
        !          2426:     * If the bitmap was created with either 0 planes or 0 bits per
        !          2427:     * pixel, then query the format to write with.  By asking for just
        !          2428:     * one format (two LONGs, or one instance of structure of bmFmt),
        !          2429:     * we'll get the device's favored format.
        !          2430:     *******************************************************************/
        !          2431: 
        !          2432:     if ((pbmih->cPlanes == 0) || (pbmih->cBitCount == 0))
        !          2433:     {
        !          2434:        if (!GpiQueryDeviceBitmapFormats(hps, 2L, (PLONG)&bmFmt))
        !          2435:            goto lfwrite_error_close_file;
        !          2436:     }
        !          2437:     else
        !          2438:     {
        !          2439:        bmFmt.cPlanes   = pbmih->cPlanes;
        !          2440:        bmFmt.cBitCount = pbmih->cBitCount;
        !          2441:     }
        !          2442: 
        !          2443: 
        !          2444:     /*******************************************************************
        !          2445:     * Determine size of bitmap header. The header consists of a
        !          2446:     * a fixed-size part and a variable-length color table.  The
        !          2447:     * latter has  2^cBitCount  entries, each of which is sizeof(RGB)
        !          2448:     * bytes long.  The exception is when cBitCount is 24, in which
        !          2449:     * case the color table is omitted because the pixels are direct
        !          2450:     * rgb values.
        !          2451:     *******************************************************************/
        !          2452: 
        !          2453:     i = (int) bmFmt.cBitCount;
        !          2454:     if (i == 24)
        !          2455:        cbBMHdr = 0;
        !          2456:     else
        !          2457:        for (cbBMHdr = sizeof(RGB); i > 0; --i)
        !          2458:            cbBMHdr *= 2;
        !          2459:     cbBMHdr += sizeof(BITMAPFILEHEADER);
        !          2460: 
        !          2461: 
        !          2462:     /*******************************************************************
        !          2463:     * Copy structure from input to work buffer.  The call to
        !          2464:     * GpiQueryBitmapBits will have write-access to this, so we won't
        !          2465:     * let it have the user's data.
        !          2466:     *******************************************************************/
        !          2467: 
        !          2468:     pbfh = NULL;
        !          2469:     if (DosAllocMem((PPVOID)&pbfh, cbBMHdr, fPERM|PAG_COMMIT))
        !          2470:        goto lfwrite_error_close_file;
        !          2471:     pbfh->bmp2 = *pbmih;
        !          2472:     if ((pbmih->cPlanes == 0) || (pbmih->cBitCount))
        !          2473:     {
        !          2474:        pbfh->bmp2.cPlanes   = (USHORT) bmFmt.cPlanes;
        !          2475:        pbfh->bmp2.cBitCount = (USHORT) bmFmt.cBitCount;
        !          2476:     }
        !          2477: 
        !          2478: 
        !          2479:     /*******************************************************************
        !          2480:     * Allocate space for the bitmap bits -- all of them at once.
        !          2481:     * The extra ULONG casts are there to force all the arithmetic
        !          2482:     * to be done in 32 bits.
        !          2483:     *******************************************************************/
        !          2484: 
        !          2485:     ulSize = (
        !          2486:               (
        !          2487:                 (
        !          2488:                   (ULONG)pbfh->bmp2.cBitCount
        !          2489:                   * (ULONG)pbfh->bmp2.cx
        !          2490:                   + 31L
        !          2491:                 ) / 32L
        !          2492:               ) * (ULONG)pbfh->bmp2.cPlanes * 4L
        !          2493:             ) * (ULONG)pbfh->bmp2.cy;
        !          2494: 
        !          2495:     if (DosAllocMem((PPVOID)&pBits, ulSize, fPERM|PAG_COMMIT))
        !          2496:        goto lfwrite_error_free_header;
        !          2497: 
        !          2498: 
        !          2499:     /*******************************************************************
        !          2500:     * Tell GPI to give us the bits. The function returns the number
        !          2501:     * of scan lines of the bitmap that were copied.  We want all of
        !          2502:     * them at once.
        !          2503:     *******************************************************************/
        !          2504: 
        !          2505:     cScans = GpiQueryBitmapBits( hps
        !          2506:                               , 0L
        !          2507:                               , (ULONG)pbfh->bmp2.cy
        !          2508:                               , (PBYTE)pBits
        !          2509:                               , (PBITMAPINFO2)&pbfh->bmp2);
        !          2510:     if (cScans != pbfh->bmp2.cy)  /* compare with original number of scans */
        !          2511:        goto lfwrite_error_free_bits;
        !          2512: 
        !          2513: 
        !          2514:     /*******************************************************************
        !          2515:     * Fill in the extra header fields and write the header out to
        !          2516:     * the file.
        !          2517:     *******************************************************************/
        !          2518: 
        !          2519:     pbfh->usType    = BFT_BMAP;
        !          2520:     pbfh->cbSize    = ulSize + cbBMHdr;
        !          2521:     pbfh->xHotspot  = pbfh->bmp2.cx / 2;
        !          2522:     pbfh->yHotspot  = pbfh->bmp2.cy / 2;
        !          2523:     pbfh->offBits   = cbBMHdr;
        !          2524: 
        !          2525:     if (DosWrite( hfile, (PVOID)pbfh, cbBMHdr, &cbWritten))
        !          2526:        goto lfwrite_error_free_bits;
        !          2527:     if (cbWritten != cbBMHdr)
        !          2528:        goto lfwrite_error_free_bits;
        !          2529: 
        !          2530: 
        !          2531:     /*******************************************************************
        !          2532:     * Write the bits out to the file.
        !          2533:     *******************************************************************/
        !          2534: 
        !          2535:     if (DosWrite( hfile, (PVOID)pBits, ulSize, &cbWritten))
        !          2536:        goto lfwrite_error_free_bits;
        !          2537:     if (cbWritten != ulSize)
        !          2538:        goto lfwrite_error_free_bits;
        !          2539: 
        !          2540:     fRet = TRUE;     /* The bits are on the disk. */
        !          2541: 
        !          2542: 
        !          2543:     /*******************************************************************
        !          2544:     * Close the file, free the buffer space and leave. This is a
        !          2545:     * common exit point from the function.  Since the same cleanup
        !          2546:     * operations need to be performed for such a large number of
        !          2547:     * possible error conditions, this is concise way to do the right
        !          2548:     * thing.
        !          2549:     *******************************************************************/
        !          2550: 
        !          2551: lfwrite_error_free_bits:
        !          2552:     DosFreeMem(pBits);
        !          2553: lfwrite_error_free_header:
        !          2554:     DosFreeMem(&pbfh);
        !          2555: lfwrite_error_close_file:
        !          2556:     DosClose(hfile);
        !          2557:     return fRet;
        !          2558: }
        !          2559: 
        !          2560: 
        !          2561: 
        !          2562: 
        !          2563: /************************************************************************
        !          2564: *
        !          2565: *   MyMessageBox
        !          2566: *
        !          2567: *   Displays a message box with the given string.  To simplify matters,
        !          2568: *   the box will always have the same title ("FatPel"), will always
        !          2569: *   have a single button ("Ok"), will always have an exclamation point
        !          2570: *   icon, and will always be application modal.
        !          2571: *
        !          2572: ************************************************************************/
        !          2573: 
        !          2574: VOID
        !          2575: MyMessageBox(hWnd, sz)
        !          2576: HWND hWnd;
        !          2577: PSZ sz;
        !          2578: {
        !          2579:     static char *szTitle = "FatPel Application";
        !          2580: 
        !          2581:     WinMessageBox(HWND_DESKTOP, hWnd, sz, szTitle, NULL,
        !          2582:                  MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
        !          2583: }

unix.superglobalmegacorp.com

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