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