|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.