|
|
1.1 ! root 1: /************************* JIGSAW.C *************************************\ ! 2: * ! 3: * PROGRAM NAME: JIGSAW ! 4: * ------------- ! 5: * ! 6: * Created by Microsoft, IBM Corporation, 1990 ! 7: * ! 8: * DISCLAIMER OF WARRANTIES. The following [enclosed] code is ! 9: * sample code created by Microsoft Corporation and/or IBM ! 10: * Corporation. This sample code is not part of any standard ! 11: * Microsoft or IBM product and is provided to you solely for ! 12: * the purpose of assisting you in the development of your ! 13: * applications. The code is provided "AS IS", without ! 14: * warranty of any kind. Neither Microsoft nor IBM shall be ! 15: * liable for any damages arising out of your use of the sample ! 16: * code, even if they have been advised of the possibility of ! 17: * such damages. ! 18: * ! 19: * REVISION HISTORY: ! 20: * ----------------- ! 21: * Original version, 1988 ! 22: * Updated for flat model, 1990 ! 23: * ! 24: * WHAT THIS PROGRAM DOES: ! 25: * ----------------------- ! 26: * This program provides a jigsaw puzzle, based on a decomposition ! 27: * of an arbitrary bitmap loaded from a file. The user can jumble the ! 28: * pieces, then drag them individually by means of the mouse. The image ! 29: * can be zoomed in and out and scrolled up/down and left/right. ! 30: * ! 31: * JIGSAW uses GpiBitBlt with clip paths to create a collection of picture ! 32: * fragments which are the puzzle pieces. In earlier versions of the ! 33: * program, each of these pieces was associated with a single retain-mode ! 34: * graphics segment. The retain-mode technique, however, proved to be ! 35: * too slow, so subsequent versions of the program used retain-mode APIs ! 36: * for fewer and fewer operations. The current version eliminates ! 37: * retain-mode graphics altogether. Instead, the drawing data for each ! 38: * piece is stored in _SEGLIST data structure defined in JIGSAW.H. ! 39: * This structure contains all the data needed to draw a piece, including ! 40: * pointers to the previous and next pieces. The _SEGLIST nodes are ! 41: * arranged in drawing priority order, so the picture can be reconstructed ! 42: * by traversing the list in sequence, drawing each piece as its ! 43: * corresponding structure is encountered. Where the comments in the ! 44: * rest of the program refer to a "segment," they are simply referring to ! 45: * a piece of the puzzle as defined by a record in this data structure. ! 46: * ! 47: * To retain responsiveness to user requests, the real work is done in a ! 48: * second thread, with work requests transmitted from the main thread in ! 49: * the form of messages. This arrangement makes it possible for the user ! 50: * to override lengthy drawing operations with a higher-priority request ! 51: * (eg. program termination, magnification change, etc.). ! 52: * ! 53: * Individual pieces are made to "move" by changing their model transforms. ! 54: * Scrolling and zooming of the whole picture is done by changing the ! 55: * default viewing transform. The points in model space associated with ! 56: * each piece (control points for the bounding curve, corners of the ! 57: * bounding box, etc.) are converted via GpiConvert into points in device ! 58: * space prior to use with GpiBitBlt, etc. ! 59: * ! 60: * ! 61: * WHAT THIS PROGRAM DEMONSTRATES: ! 62: * ------------------------------- ! 63: * Illustrates the use of GPI ! 64: * Illustrates the use of off-screen bitmaps ! 65: * ! 66: * API CALLS FEATURED: ! 67: * ------------------- ! 68: * GpiBeginPath ! 69: * GpiEndPath ! 70: * GpiFillPath ! 71: * GpiSetClipPath ! 72: * GpiSetClipRegion ! 73: * ! 74: * GpiCreateBitmap ! 75: * GpiDeleteBitmap ! 76: * GpiSetBitmap ! 77: * GpiSetBitmapBits ! 78: * GpiBitBlt ! 79: * ! 80: * GpiConvert ! 81: * ! 82: * GpiCreateRegion ! 83: * GpiCombineRegion ! 84: * GpiSetRegion ! 85: * GpiDestroyRegion ! 86: * GpiQueryRegionBox ! 87: * ! 88: * GpiSetAttrMode ! 89: * GpiSetColor ! 90: * ! 91: * GpiQueryDefaultViewMatrix ! 92: * GpiSetDefaultViewMatrix ! 93: * ! 94: * ! 95: * WHAT YOU NEED TO COMPILE AND LINK THIS PROGRAM: ! 96: * ----------------------------------------------- ! 97: * ! 98: * REQUIRED FILES: ! 99: * --------------- ! 100: * JIGSAW.MAK ! 101: * JIGSAW.C ! 102: * JIGSAW.H ! 103: * JIGSAW.RC ! 104: * JIGSAW.DEF ! 105: * JIGSAW.ICO ! 106: * GLOBALS.C ! 107: * GLOBALS.H ! 108: * STATWND.DLG ! 109: * STATWND.H ! 110: * CHEAP.DLG ! 111: * OPENDLG.H ! 112: * CHEAP.H ! 113: * MISC.C ! 114: * PROCS.C ! 115: * ! 116: * REQUIRED LIBRARIES: ! 117: * ------------------- ! 118: * ! 119: * OS2386.LIB ! 120: * LIBC.LIB ! 121: * ! 122: * REQUIRED PROGRAMS: ! 123: * ------------------ ! 124: * ! 125: * Microsoft C386 Compiler ! 126: * Microsoft LINK386 Linker ! 127: * Resource Compiler ! 128: * ! 129: * ! 130: \*************************************************************************/ ! 131: ! 132: #include "jigsaw.h" ! 133: #include "opendlg.h" ! 134: #include "globals.h" ! 135: #include <stdlib.h> ! 136: #include <stdio.h> ! 137: #include <string.h> ! 138: ! 139: /******************************************************************************/ ! 140: /* */ ! 141: /* Main thread will initialize the process for PM services and process */ ! 142: /* the application message queue until a WM_QUIT message is received. It will */ ! 143: /* then destroy all PM resources and terminate. Any error during */ ! 144: /* initialization will be reported and the process terminated. */ ! 145: /* */ ! 146: /******************************************************************************/ ! 147: VOID cdecl main(VOID) ! 148: { ! 149: QMSG qmsg; ! 150: ! 151: if( Initialize()) ! 152: while( WinGetMsg( habMain, &qmsg, NULL, NULL, NULL)) ! 153: WinDispatchMsg( habMain, &qmsg); ! 154: else ! 155: ReportError( habMain); ! 156: Finalize(); ! 157: } ! 158: ! 159: ! 160: /******************************************************************************/ ! 161: /* */ ! 162: /* The Initialize function will initialize the PM interface, */ ! 163: /* create an application message queue, a standard frame window and a new */ ! 164: /* thread to control drawing operations. It will also initialize static */ ! 165: /* strings. */ ! 166: /* */ ! 167: /******************************************************************************/ ! 168: BOOL Initialize(VOID) ! 169: { ! 170: ULONG flCreate; ! 171: PID pid; ! 172: TID tid; ! 173: MENUITEM mi; ! 174: ! 175: ! 176: ! 177: /* ! 178: * create all semaphores for mutual exclusion and event timing ! 179: */ ! 180: if (DosCreateMutexSem(NULL, &hmtxSzFmt, DC_SEM_SHARED, FALSE) || ! 181: DosCreateEventSem(NULL, &hevDrawOn, DC_SEM_SHARED, FALSE) || ! 182: DosCreateEventSem(NULL, &hevMouse, DC_SEM_SHARED, FALSE) || ! 183: DosCreateEventSem(NULL, &hevLoadMsg, DC_SEM_SHARED, FALSE) || ! 184: DosCreateEventSem(NULL, &hevTerminate, DC_SEM_SHARED, FALSE) || ! 185: DosCreateEventSem(NULL, &hevKillDraw, DC_SEM_SHARED, FALSE)) { ! 186: return (FALSE); ! 187: } ! 188: ! 189: WinShowPointer( HWND_DESKTOP, TRUE); ! 190: habMain = WinInitialize( NULL); ! 191: if( !habMain) ! 192: return( FALSE); ! 193: ! 194: hmqMain = WinCreateMsgQueue( habMain,0); ! 195: if( !hmqMain) ! 196: return( FALSE); ! 197: ! 198: WinLoadString( habMain, NULL, TITLEBAR, sizeof(szTitle), szTitle); ! 199: if( !WinRegisterClass( habMain ! 200: , (PCH)szTitle ! 201: , (PFNWP)ClientWndProc ! 202: , CS_SIZEREDRAW ! 203: , 0 )) ! 204: return( FALSE); ! 205: ! 206: flCreate = (FCF_STANDARD | FCF_VERTSCROLL | FCF_HORZSCROLL) ! 207: & ~(ULONG)FCF_TASKLIST; ! 208: hwndFrame = WinCreateStdWindow( HWND_DESKTOP ! 209: , WS_VISIBLE ! 210: , &flCreate ! 211: , szTitle ! 212: , szTitle ! 213: , WS_VISIBLE ! 214: , NULL ! 215: , APPMENU ! 216: , &hwndClient); ! 217: ! 218: if( !hwndFrame) ! 219: return( FALSE); ! 220: ! 221: ! 222: ! 223: ! 224: sizlMaxClient.cx = WinQuerySysValue( HWND_DESKTOP, SV_CXFULLSCREEN); ! 225: sizlMaxClient.cy = WinQuerySysValue( HWND_DESKTOP, SV_CYFULLSCREEN); ! 226: ! 227: lByteAlignX = WinQuerySysValue( HWND_DESKTOP, SV_CXBYTEALIGN); ! 228: lByteAlignY = WinQuerySysValue( HWND_DESKTOP, SV_CYBYTEALIGN); ! 229: ! 230: hdcClient = WinOpenWindowDC( hwndClient); ! 231: hpsClient = GpiCreatePS( habMain ! 232: , hdcClient ! 233: , &sizlMaxClient ! 234: , GPIA_ASSOC | PU_PELS ); ! 235: if( !hpsClient) ! 236: return( ( MRESULT) TRUE); ! 237: GpiSetAttrMode( hpsClient, AM_PRESERVE); ! 238: ! 239: hwndHorzScroll = WinWindowFromID( hwndFrame, FID_HORZSCROLL); ! 240: ! 241: hwndVertScroll = WinWindowFromID( hwndFrame, FID_VERTSCROLL); ! 242: ! 243: hpsPaint = GpiCreatePS( habMain, NULL, &sizlMaxClient, PU_PELS); ! 244: ! 245: hrgnInvalid = GpiCreateRegion( hpsClient, 0L, NULL); ! 246: ! 247: hwndStatus = WinLoadDlg(HWND_DESKTOP, hwndClient, StatusDlgProc, ! 248: NULL, IDD_STATUS, NULL); ! 249: ! 250: WinQueryWindowProcess( hwndFrame, &pid, &tid); ! 251: swctl.hwnd = hwndFrame; ! 252: swctl.idProcess = pid; ! 253: strcpy( swctl.szSwtitle, szTitle); ! 254: hsw = WinAddSwitchEntry( &swctl); ! 255: ! 256: hwndMenu = WinWindowFromID( hwndFrame, FID_MENU); ! 257: WinSendMsg( hwndMenu ! 258: , MM_QUERYITEM ! 259: , MPFROM2SHORT( MENU_STATUS, FALSE) ! 260: , MPFROMP( (PMENUITEM)&mi)); ! 261: hwndStatusOption = mi.hwndSubMenu; ! 262: ! 263: ! 264: STATUS_SHOW(FALSE); ! 265: STATUS_HIDE(TRUE); ! 266: ! 267: if(DosCreateThread(&tidAsync, ! 268: (PFNTHREAD) NewThread, ! 269: NULL, ! 270: 0, ! 271: STACKSIZE )) { ! 272: return( FALSE); ! 273: } /* create async thread */ ! 274: if( !CreateBitmapHdcHps( &hdcBitmapFile, &hpsBitmapFile)) ! 275: return( FALSE); ! 276: if( !CreateBitmapHdcHps( &hdcBitmapSize, &hpsBitmapSize)) ! 277: return( FALSE); ! 278: if( !CreateBitmapHdcHps( &hdcBitmapBuff, &hpsBitmapBuff)) ! 279: return( FALSE); ! 280: if( !CreateBitmapHdcHps( &hdcBitmapSave, &hpsBitmapSave)) ! 281: return( FALSE); ! 282: ! 283: return( TRUE); ! 284: } ! 285: ! 286: /******************************************************************************/ ! 287: /* */ ! 288: /* Finalize will destroy the asynchronous drawing thread, all Presentation */ ! 289: /* Manager resources, and terminate the process. */ ! 290: /* */ ! 291: /******************************************************************************/ ! 292: VOID Finalize(VOID) ! 293: { ! 294: ULONG ulPostCt; ! 295: ! 296: if( tidAsync) ! 297: { ! 298: DosResetEventSem( hevDrawOn, &ulPostCt); ! 299: DosPostEventSem( hevTerminate); ! 300: } ! 301: ! 302: while( pslHead != NULL ) ! 303: { ! 304: GpiSetBitmap( pslHead->hpsFill, NULL); ! 305: GpiDeleteBitmap( pslHead->hbmFill); ! 306: GpiDestroyPS( pslHead->hpsFill); ! 307: DevCloseDC( pslHead->hdcFill); ! 308: ! 309: GpiSetBitmap( pslHead->hpsHole, NULL); ! 310: GpiDeleteBitmap( pslHead->hbmHole); ! 311: GpiDestroyPS( pslHead->hpsHole); ! 312: DevCloseDC( pslHead->hdcHole); ! 313: ! 314: SegListUpdate( DEL_SEG, pslHead); ! 315: } ! 316: ! 317: if( hrgnInvalid) ! 318: GpiDestroyRegion( hpsClient, hrgnInvalid); ! 319: if( hpsClient) ! 320: { ! 321: GpiAssociate( hpsClient, NULL); ! 322: GpiDestroyPS( hpsClient); ! 323: } ! 324: if( hpsPaint) ! 325: GpiDestroyPS( hpsPaint); ! 326: ! 327: if( hpsBitmapFile) ! 328: { ! 329: GpiSetBitmap( hpsBitmapFile, NULL); ! 330: GpiDeleteBitmap( hbmBitmapFile); ! 331: GpiDestroyPS( hpsBitmapFile); ! 332: DevCloseDC( hdcBitmapFile); ! 333: } ! 334: if( hpsBitmapSize) ! 335: { ! 336: GpiSetBitmap( hpsBitmapSize, NULL); ! 337: GpiDeleteBitmap( hbmBitmapSize); ! 338: GpiDestroyPS( hpsBitmapSize); ! 339: DevCloseDC( hdcBitmapSize); ! 340: } ! 341: if( hpsBitmapBuff) ! 342: { ! 343: GpiSetBitmap( hpsBitmapBuff, NULL); ! 344: GpiDeleteBitmap( hbmBitmapBuff); ! 345: GpiDestroyPS( hpsBitmapBuff); ! 346: DevCloseDC( hdcBitmapBuff); ! 347: } ! 348: if( hpsBitmapSave) ! 349: { ! 350: GpiSetBitmap( hpsBitmapSave, NULL); ! 351: GpiDeleteBitmap( hbmBitmapSave); ! 352: GpiDestroyPS( hpsBitmapSave); ! 353: DevCloseDC( hdcBitmapSave); ! 354: } ! 355: ! 356: ! 357: if( hwndStatus != NULL) { ! 358: WinDestroyWindow( hwndStatus); ! 359: } ! 360: if( hwndFrame) ! 361: WinDestroyWindow( hwndFrame); ! 362: if( hmqMain) ! 363: WinDestroyMsgQueue( hmqMain); ! 364: if( habMain) ! 365: WinTerminate( habMain); ! 366: ! 367: DosExit( EXIT_PROCESS, 0); ! 368: } ! 369: ! 370: ! 371: /******************************************************************************/ ! 372: /* */ ! 373: /* ReportError will display the latest error information for the required */ ! 374: /* thread. No resources to be loaded if out of memory error. */ ! 375: /* */ ! 376: /******************************************************************************/ ! 377: VOID ReportError( hab) ! 378: HAB hab; ! 379: { ! 380: PERRINFO perriBlk; ! 381: PSZ pszErrMsg; ! 382: USHORT * TempPtr; ! 383: ! 384: if( !hwndFrame) ! 385: return; ! 386: if( !fErrMem) ! 387: { ! 388: perriBlk = WinGetErrorInfo(hab); ! 389: if( !perriBlk) ! 390: return; ! 391: SELECTOROF( pszErrMsg) = SELECTOROF(perriBlk); ! 392: SELECTOROF( TempPtr) = SELECTOROF(perriBlk); ! 393: OFFSETOF( TempPtr) = perriBlk->offaoffszMsg; ! 394: OFFSETOF( pszErrMsg) = *TempPtr; ! 395: WinMessageBox( HWND_DESKTOP ! 396: , hwndFrame ! 397: , pszErrMsg ! 398: , szTitle ! 399: , 0 ! 400: , MB_CUACRITICAL | MB_ENTER); ! 401: WinFreeErrorInfo( perriBlk); ! 402: } else ! 403: WinMessageBox( HWND_DESKTOP ! 404: , hwndFrame ! 405: , "ERROR - Out Of Memory" ! 406: , szTitle ! 407: , 0 ! 408: , MB_CUACRITICAL | MB_ENTER); ! 409: } ! 410: ! 411: ! 412: /******************************************************************************/ ! 413: /* Reset the scroll bars to be in the middle of their range */ ! 414: /******************************************************************************/ ! 415: VOID ResetScrollBars(VOID) ! 416: { ! 417: RECTL rclClient; ! 418: ! 419: WinQueryWindowRect( hwndClient, &rclClient); ! 420: ptsScrollMax.x = (SHORT)(rclClient.xRight - rclClient.xLeft); ! 421: ptsHalfScrollMax.x = ptsScrollMax.x >> 1; ! 422: ptsScrollPage.x = ptsScrollMax.x >> 3; ! 423: ROUND_DOWN_MOD( ptsScrollPage.x, (SHORT)lByteAlignX); ! 424: ptsScrollLine.x = ptsScrollMax.x >> 5; ! 425: ROUND_DOWN_MOD( ptsScrollLine.x, (SHORT)lByteAlignX); ! 426: ptsScrollPos.x = ptsHalfScrollMax.x; ! 427: ptsOldScrollPos.x = ptsHalfScrollMax.x; ! 428: WinSendMsg( hwndHorzScroll ! 429: , SBM_SETSCROLLBAR ! 430: , MPFROMSHORT( ptsScrollPos.x) ! 431: , MPFROM2SHORT( 1, ptsScrollMax.x) ); ! 432: ptsScrollMax.y = (SHORT)(rclClient.yTop - rclClient.yBottom); ! 433: ptsHalfScrollMax.y = ptsScrollMax.y >> 1; ! 434: ptsScrollPage.y = ptsScrollMax.y >> 3; ! 435: ROUND_DOWN_MOD( ptsScrollPage.y, (SHORT)lByteAlignY); ! 436: ptsScrollLine.y = ptsScrollMax.y >> 5; ! 437: ROUND_DOWN_MOD( ptsScrollLine.y, (SHORT)lByteAlignY); ! 438: ptsScrollPos.y = ptsHalfScrollMax.y; ! 439: ptsOldScrollPos.y = ptsHalfScrollMax.y; ! 440: WinSendMsg( hwndVertScroll ! 441: , SBM_SETSCROLLBAR ! 442: , MPFROMSHORT( ptsScrollPos.y) ! 443: , MPFROM2SHORT( 1, ptsScrollMax.y) ); ! 444: } ! 445: ! 446: ! 447: /******************************************************************************/ ! 448: /* Load a bitmap */ ! 449: /******************************************************************************/ ! 450: VOID Load( pli) ! 451: PLOADINFO pli; ! 452: { ! 453: ULONG ulPostCt; ! 454: ! 455: /* ! 456: * disable status window scrollbar ! 457: */ ! 458: WinEnableWindow(hwndZoomScrollBar, FALSE); ! 459: ! 460: WinSetDlgItemText(hwndStatus, SID_STATUS, pszLoadMsg); ! 461: DosPostEventSem( hevLoadMsg); ! 462: ! 463: if( hbmBitmapFile) ! 464: { ! 465: GpiSetBitmap( hpsBitmapFile, NULL); ! 466: GpiDeleteBitmap( hbmBitmapFile); ! 467: } ! 468: ! 469: if( !ReadBitmap( pli->hf) ) ! 470: { ! 471: MyMessageBox( hwndClient, pszError); ! 472: DosResetEventSem( hevLoadMsg, &ulPostCt); ! 473: return; ! 474: } ! 475: ! 476: strcpy( swctl.szSwtitle, szTitle); ! 477: strcat( swctl.szSwtitle, ": "); ! 478: strcat( swctl.szSwtitle, pli->szFileName); ! 479: WinChangeSwitchEntry( hsw, &swctl); ! 480: WinSetWindowText( hwndFrame, swctl.szSwtitle); ! 481: ResetScrollBars(); ! 482: ! 483: if( fFirstLoad ! 484: || ( (ADJUSTED_PBMP(pbmp2BitmapFile)->cx > ! 485: ADJUSTED_PBMP(pbmp2BitmapFileRef)->cx) ! 486: || (ADJUSTED_PBMP(pbmp2BitmapFile)->cy > ! 487: ADJUSTED_PBMP(pbmp2BitmapFileRef)->cy) ! 488: || (ADJUSTED_PBMP(pbmp2BitmapFile)->cPlanes != ! 489: ADJUSTED_PBMP(pbmp2BitmapFileRef)->cPlanes) ! 490: || (ADJUSTED_PBMP(pbmp2BitmapFile)->cBitCount != ! 491: ADJUSTED_PBMP(pbmp2BitmapFileRef)->cBitCount) ) ) ! 492: { ! 493: if( !fFirstLoad) ! 494: DumpPicture(); ! 495: if( !PrepareBitmap() ) ! 496: { ! 497: MyMessageBox( hwndClient, pszError); ! 498: DosResetEventSem( hevLoadMsg, &ulPostCt); ! 499: return; ! 500: } ! 501: CreatePicture( PICTURE_CREATE); ! 502: bmp2BitmapFileRef = bmp2BitmapFile; ! 503: } else ! 504: { ! 505: CreatePicture( PICTURE_UPDATE); ! 506: } ! 507: ! 508: lScale = 0; ! 509: ! 510: CalcBounds(); ! 511: ptlScaleRef.x = ptlScaleRef.y = 0L; ! 512: CalcTransform( hwndClient); ! 513: ! 514: fFirstLoad = FALSE; ! 515: DosResetEventSem( hevLoadMsg, &ulPostCt); ! 516: ! 517: WinEnableWindow(hwndZoomScrollBar, TRUE); ! 518: DisplayZoomFactor(lScale); ! 519: WinSetDlgItemText(hwndStatus, SID_STATUS, pszBlankMsg); ! 520: } ! 521: ! 522: /******************************************************************************/ ! 523: /* Throw the pieces around the screen. */ ! 524: /******************************************************************************/ ! 525: VOID Jumble(VOID) ! 526: { ! 527: LONG lWidth, lHeight; ! 528: DATETIME date; ! 529: POINTL ptl; ! 530: RECTL rclClient; ! 531: PSEGLIST psl; ! 532: ! 533: if( WinQueryWindowRect( hwndClient, &rclClient) ) ! 534: { ! 535: lWidth = rclClient.xRight - rclClient.xLeft; ! 536: lHeight = rclClient.yTop - rclClient.yBottom; ! 537: if( (lWidth > 0) && (lHeight > 0) ) ! 538: { ! 539: DosGetDateTime( &date); ! 540: srand( (USHORT)date.hundredths); ! 541: for( psl = pslHead; psl != NULL; psl = psl->pslNext) ! 542: { ! 543: psl->pslNextIsland = psl; /* reset island pointer */ ! 544: psl->fIslandMark = FALSE; /* clear island mark */ ! 545: ptl.x = rclClient.xLeft + (rand() % lWidth); ! 546: ptl.y = rclClient.yBottom + (rand() % lHeight); ! 547: GpiConvert( hpsClient, CVTC_DEVICE, CVTC_MODEL, 1L, &ptl); ! 548: ptl.x = 50 * (ptl.x / 50) - 250; ! 549: ptl.y = 50 * (ptl.y / 50) - 250; ! 550: psl->ptlModelXlate.x = ptl.x - psl->ptlLocation.x; ! 551: psl->ptlModelXlate.y = ptl.y - psl->ptlLocation.y; ! 552: SetRect( psl); ! 553: } ! 554: } ! 555: } ! 556: } ! 557: ! 558: /******************************************************************************/ ! 559: /* */ ! 560: /* */ ! 561: /* */ ! 562: /******************************************************************************/ ! 563: VOID ToBottom( pslDown) ! 564: PSEGLIST pslDown; ! 565: { ! 566: BOOL fFirst; ! 567: PSEGLIST psl; ! 568: ! 569: for( psl = pslDown, fFirst = TRUE ! 570: ; (psl != pslDown) || fFirst ! 571: ; psl = psl->pslNextIsland, fFirst = FALSE ) ! 572: SegListUpdate( MAKE_HEAD_SEG, psl); /* at head => lowest priority */ ! 573: } ! 574: ! 575: ! 576: /******************************************************************************/ ! 577: /* */ ! 578: /* NewThread is the asynchronous drawing thread. It is responsible for all */ ! 579: /* drawing. It will initialize its PM interface and create an application */ ! 580: /* message queue. It will then monitor its message queue and process any */ ! 581: /* commands received. */ ! 582: /* */ ! 583: /******************************************************************************/ ! 584: VOID FAR NewThread(VOID) ! 585: { ! 586: QMSG qmsgAsync, qmsgPeek; ! 587: BOOL fDone; ! 588: POINTL aptlDraw[3]; ! 589: USHORT usChar, fsKeyFlags; ! 590: PSEGLIST psl; ! 591: ULONG ulPostCt; ! 592: ! 593: /****************************************************************************/ ! 594: /* Initialize the PM interface. If it fails, terminate both threads. */ ! 595: /****************************************************************************/ ! 596: habAsync = WinInitialize( NULL); ! 597: if( !habAsync) ! 598: { ! 599: WinPostMsg( hwndClient, WM_QUIT, NULL, NULL); ! 600: DosExit( EXIT_THREAD, 0); ! 601: } ! 602: ! 603: /****************************************************************************/ ! 604: /* Create a message queue. If it fails, terminate both threads. */ ! 605: /****************************************************************************/ ! 606: hmqAsync = WinCreateMsgQueue( habAsync, 150); ! 607: if( !hmqAsync) ! 608: { ! 609: WinPostMsg( hwndClient, WM_QUIT, NULL, NULL); ! 610: WinTerminate( habAsync); ! 611: DosExit( EXIT_THREAD, 0); ! 612: } ! 613: ! 614: DosSetPrty( PRTYS_THREAD, PRTYC_NOCHANGE, sPrty, (TID)NULL); ! 615: ! 616: ! 617: while( TRUE) ! 618: { ! 619: WinGetMsg( habAsync, &qmsgAsync, NULL, 0, 0); ! 620: ! 621: if( WinPeekMsg( habAsync, &qmsgPeek, NULL, UM_DIE, UM_DIE, PM_NOREMOVE)) ! 622: qmsgAsync = qmsgPeek; ! 623: ! 624: if( WinPeekMsg( habAsync, &qmsgPeek, NULL, UM_SIZING, UM_LOAD, PM_NOREMOVE)) ! 625: { ! 626: DosResetEventSem( hevDrawOn, &ulPostCt); ! 627: DosResetEventSem( hevMouse, &ulPostCt); ! 628: } ! 629: else ! 630: { ! 631: DosPostEventSem( hevDrawOn); ! 632: DosPostEventSem( hevMouse); ! 633: } ! 634: if( (qmsgAsync.msg < UM_SIZING) || (qmsgAsync.msg > UM_LOAD)) ! 635: DosPostEventSem( hevMouse); ! 636: else ! 637: DosResetEventSem( hevMouse, &ulPostCt); ! 638: ! 639: ! 640: /**************************************************************************/ ! 641: /* process the commands */ ! 642: /**************************************************************************/ ! 643: switch( qmsgAsync.msg) ! 644: { ! 645: ! 646: /************************************************************************/ ! 647: case UM_CHAR: ! 648: fsKeyFlags = (USHORT)SHORT1FROMMP(qmsgAsync.mp1); ! 649: usChar = (USHORT)SHORT1FROMMP(qmsgAsync.mp2); ! 650: if( (fsKeyFlags & KC_CHAR) ! 651: && ((usChar == 'b') || (usChar == 'B'))) ! 652: { ! 653: if( psl = Correlate( &ptlMouse)) ! 654: { ! 655: ToBottom( psl); ! 656: Redraw(); ! 657: } ! 658: } ! 659: break; ! 660: ! 661: /************************************************************************/ ! 662: case UM_LOAD: ! 663: Load( (PLOADINFO)qmsgAsync.mp1); ! 664: Redraw(); ! 665: break; ! 666: ! 667: /************************************************************************/ ! 668: case UM_JUMBLE: ! 669: Jumble(); ! 670: Redraw(); ! 671: break; ! 672: ! 673: /************************************************************************/ ! 674: case UM_REDRAW: ! 675: Redraw(); ! 676: break; ! 677: ! 678: /************************************************************************/ ! 679: /* DRAW will use the passed region containing the invalidated area of */ ! 680: /* the screen, repaint it and then destroy the region. */ ! 681: /************************************************************************/ ! 682: case UM_DRAW: ! 683: ! 684: if( qmsgAsync.mp1) ! 685: { ! 686: DoDraw( hpsBitmapBuff, (HRGN)qmsgAsync.mp1, TRUE); ! 687: GpiQueryRegionBox( hpsClient, (HRGN)qmsgAsync.mp1, (PRECTL)aptlDraw); ! 688: GpiDestroyRegion( hpsClient, (HRGN)qmsgAsync.mp1); ! 689: WinMapWindowPoints( hwndClient, HWND_DESKTOP, aptlDraw, 3); ! 690: ROUND_DOWN_MOD( aptlDraw[0].x, lByteAlignX); /* round down */ ! 691: ROUND_DOWN_MOD( aptlDraw[0].y, lByteAlignY); /* round down */ ! 692: ROUND_UP_MOD( aptlDraw[1].x, lByteAlignX); /* round up */ ! 693: ROUND_UP_MOD( aptlDraw[1].y, lByteAlignY); /* round up */ ! 694: WinMapWindowPoints( HWND_DESKTOP, hwndClient, aptlDraw, 3); ! 695: aptlDraw[2] = aptlDraw[0]; ! 696: GpiBitBlt( hpsClient ! 697: , hpsBitmapBuff ! 698: , 3L ! 699: , aptlDraw ! 700: , ROP_SRCCOPY ! 701: , BBO_IGNORE ); ! 702: } ! 703: break; ! 704: ! 705: ! 706: /************************************************************************/ ! 707: /* Get new scroll posn from command ( i.e. +/-1 +/-page) or new */ ! 708: /* absolute position from parameter, update scroll posn, change the */ ! 709: /* transform and update the thumb posn. Finally update the window. */ ! 710: /************************************************************************/ ! 711: case UM_HSCROLL: ! 712: switch( SHORT2FROMMP( qmsgAsync.mp1) ) ! 713: { ! 714: case SB_LINEUP: ! 715: ptsScrollPos.x -= ptsScrollLine.x; ! 716: break; ! 717: case SB_LINEDOWN: ! 718: ptsScrollPos.x += ptsScrollLine.x; ! 719: break; ! 720: case SB_SLIDERTRACK: ! 721: case SB_SLIDERPOSITION: ! 722: for( fDone = FALSE; !fDone ;) ! 723: { ! 724: if( WinPeekMsg( habAsync ! 725: , &qmsgPeek ! 726: , NULL ! 727: , UM_HSCROLL ! 728: , UM_HSCROLL ! 729: , PM_NOREMOVE)) ! 730: if( (SHORT2FROMMP( qmsgPeek.mp1) == SB_SLIDERTRACK) ! 731: ||(SHORT2FROMMP( qmsgPeek.mp1) == SB_SLIDERPOSITION)) ! 732: WinPeekMsg( habAsync ! 733: , &qmsgAsync ! 734: , NULL ! 735: , UM_HSCROLL ! 736: , UM_HSCROLL ! 737: , PM_REMOVE); ! 738: else ! 739: fDone = TRUE; ! 740: else ! 741: fDone = TRUE; ! 742: } ! 743: ptsScrollPos.x = SHORT1FROMMP( qmsgAsync.mp1); ! 744: ROUND_DOWN_MOD( ptsScrollPos.x, (SHORT)lByteAlignX); ! 745: break; ! 746: case SB_PAGEUP: ! 747: ptsScrollPos.x -= ptsScrollPage.x; ! 748: break; ! 749: case SB_PAGEDOWN: ! 750: ptsScrollPos.x += ptsScrollPage.x; ! 751: break; ! 752: case SB_ENDSCROLL: ! 753: break; ! 754: default: ! 755: break; ! 756: } ! 757: DoHorzScroll(); ! 758: break; ! 759: ! 760: case UM_VSCROLL: ! 761: switch( SHORT2FROMMP( qmsgAsync.mp1) ) ! 762: { ! 763: case SB_LINEUP: ! 764: ptsScrollPos.y -= ptsScrollLine.y; ! 765: break; ! 766: case SB_LINEDOWN: ! 767: ptsScrollPos.y += ptsScrollLine.y; ! 768: break; ! 769: case SB_SLIDERTRACK: ! 770: case SB_SLIDERPOSITION: ! 771: for( fDone = FALSE; !fDone ;) ! 772: { ! 773: if( WinPeekMsg( habAsync ! 774: , &qmsgPeek ! 775: , NULL ! 776: , UM_VSCROLL ! 777: , UM_VSCROLL ! 778: , PM_NOREMOVE)) ! 779: if( (SHORT2FROMMP( qmsgPeek.mp1) == SB_SLIDERTRACK) ! 780: ||(SHORT2FROMMP( qmsgPeek.mp1) == SB_SLIDERPOSITION)) ! 781: WinPeekMsg( habAsync ! 782: , &qmsgAsync ! 783: , NULL ! 784: , UM_VSCROLL ! 785: , UM_VSCROLL ! 786: , PM_REMOVE); ! 787: else ! 788: fDone = TRUE; ! 789: else ! 790: fDone = TRUE; ! 791: } ! 792: ptsScrollPos.y = SHORT1FROMMP( qmsgAsync.mp1); ! 793: ROUND_DOWN_MOD( ptsScrollPos.y, (SHORT)lByteAlignY); ! 794: break; ! 795: case SB_PAGEUP: ! 796: ptsScrollPos.y -= ptsScrollPage.y; ! 797: break; ! 798: case SB_PAGEDOWN: ! 799: ptsScrollPos.y += ptsScrollPage.y; ! 800: break; ! 801: case SB_ENDSCROLL: ! 802: break; ! 803: default: ! 804: break; ! 805: } ! 806: DoVertScroll(); ! 807: break; ! 808: ! 809: /************************************************************************/ ! 810: /* the window is being resized */ ! 811: /************************************************************************/ ! 812: case UM_SIZING: ! 813: CalcBounds(); ! 814: CalcTransform( hwndClient); ! 815: break; ! 816: ! 817: /************************************************************************/ ! 818: /* adjust zoom factor */ ! 819: /************************************************************************/ ! 820: case UM_ZOOM: ! 821: if( WinPeekMsg( habAsync ! 822: , &qmsgPeek ! 823: , NULL ! 824: , UM_SIZING ! 825: , UM_LOAD ! 826: , PM_NOREMOVE)) ! 827: DosResetEventSem( hevDrawOn, &ulPostCt); ! 828: else { ! 829: DosPostEventSem( hevDrawOn); ! 830: } ! 831: ! 832: WinSetDlgItemText(hwndStatus, SID_STATUS, "Zooming"); ! 833: Zoom(); ! 834: WinSetDlgItemText(hwndStatus, SID_STATUS, ""); ! 835: break; ! 836: ! 837: /************************************************************************/ ! 838: /* Button down will cause a correlate on the picture to test for a hit. */ ! 839: /* Any selected segment will be highlighted and redrawn as dynamic. */ ! 840: /************************************************************************/ ! 841: case UM_LEFTDOWN: ! 842: if( !fButtonDownAsync) ! 843: { ! 844: fButtonDownAsync = TRUE; ! 845: LeftDown( qmsgAsync.mp1); ! 846: } ! 847: break; ! 848: ! 849: /************************************************************************/ ! 850: /* if a segment is being dragged it will be redrawn in a new posn */ ! 851: /************************************************************************/ ! 852: case UM_MOUSEMOVE: ! 853: #ifdef fred ! 854: if( !fButtonDownAsync) ! 855: break; ! 856: #endif ! 857: for( fDone = FALSE; !fDone ;) ! 858: { ! 859: if( WinPeekMsg( habAsync /* look through first button-up */ ! 860: , &qmsgPeek ! 861: , NULL ! 862: , UM_MOUSEMOVE ! 863: , UM_LEFTUP ! 864: , PM_NOREMOVE)) ! 865: if( qmsgPeek.msg == UM_MOUSEMOVE) /* only collapse move msgs */ ! 866: WinPeekMsg( habAsync ! 867: , &qmsgAsync ! 868: , NULL ! 869: , UM_MOUSEMOVE ! 870: , UM_MOUSEMOVE ! 871: , PM_REMOVE); ! 872: else ! 873: fDone = TRUE; ! 874: else ! 875: fDone = TRUE; ! 876: } ! 877: MouseMove( qmsgAsync.mp1); /* process last move before button-up */ ! 878: break; ! 879: ! 880: /************************************************************************/ ! 881: /* if a segment is being dragged it will be redrawn as normal */ ! 882: /************************************************************************/ ! 883: case UM_LEFTUP: ! 884: if( fButtonDownAsync) ! 885: { ! 886: LeftUp(); ! 887: fButtonDownAsync = FALSE; ! 888: } ! 889: break; ! 890: ! 891: /************************************************************************/ ! 892: /* destroy resources and terminate */ ! 893: /************************************************************************/ ! 894: case UM_DIE: ! 895: WinDestroyMsgQueue( hmqAsync); ! 896: WinTerminate( habAsync); ! 897: DosExit( EXIT_THREAD, 0); ! 898: break; ! 899: ! 900: /************************************************************************/ ! 901: default: ! 902: break; ! 903: } ! 904: } ! 905: } ! 906: ! 907: /******************************************************************************/ ! 908: /* */ ! 909: /******************************************************************************/ ! 910: VOID CalcSize( mp1, mp2) ! 911: MPARAM mp1; ! 912: MPARAM mp2; ! 913: { ! 914: ptsScrollMax.y = SHORT2FROMMP( mp2); ! 915: ptsHalfScrollMax.y = ptsScrollMax.y >> 1; ! 916: ptsScrollPage.x = ptsScrollMax.x >> 3; ! 917: ROUND_DOWN_MOD( ptsScrollPage.x, (SHORT)lByteAlignX); ! 918: ptsScrollLine.x = ptsScrollMax.x >> 5; ! 919: ROUND_DOWN_MOD( ptsScrollLine.x, (SHORT)lByteAlignX); ! 920: ptsScrollPos.y = (SHORT)( ! 921: ( (LONG)ptsScrollPos.y ! 922: * (LONG)SHORT2FROMMP(mp2) ! 923: )/ (LONG)SHORT2FROMMP(mp1) ! 924: ); ! 925: ptsOldScrollPos.y = (SHORT)( ! 926: ( (LONG)ptsOldScrollPos.y ! 927: * (LONG)SHORT2FROMMP(mp2) ! 928: )/ (LONG)SHORT2FROMMP(mp1) ! 929: ); ! 930: WinSendMsg( hwndVertScroll ! 931: , SBM_SETSCROLLBAR ! 932: , MPFROMSHORT( ptsScrollPos.y) ! 933: , MPFROM2SHORT( 1, ptsScrollMax.y) ); ! 934: ! 935: ptsScrollMax.x = SHORT1FROMMP( mp2); ! 936: ptsHalfScrollMax.x = ptsScrollMax.x >> 1; ! 937: ptsScrollPage.y = ptsScrollMax.y >> 3; ! 938: ROUND_DOWN_MOD( ptsScrollPage.y, (SHORT)lByteAlignY); ! 939: ptsScrollLine.y = ptsScrollMax.y >> 5; ! 940: ROUND_DOWN_MOD( ptsScrollLine.y, (SHORT)lByteAlignY); ! 941: ptsScrollPos.x = (SHORT)( ! 942: ( (LONG)ptsScrollPos.x ! 943: * (LONG)SHORT1FROMMP(mp2) ! 944: )/(LONG)SHORT1FROMMP(mp1) ! 945: ); ! 946: ptsOldScrollPos.x = (SHORT)( ! 947: ( (LONG)ptsOldScrollPos.x ! 948: * (LONG)SHORT1FROMMP(mp2) ! 949: )/ (LONG)SHORT1FROMMP(mp1) ! 950: ); ! 951: WinSendMsg( hwndHorzScroll ! 952: , SBM_SETSCROLLBAR ! 953: , MPFROMSHORT( ptsScrollPos.x) ! 954: , MPFROM2SHORT( 1, ptsScrollMax.x) ); ! 955: } ! 956: ! 957: /******************************************************************************/ ! 958: /* button down will cause one segment to be indicated and made dynamic */ ! 959: /******************************************************************************/ ! 960: VOID LeftDown( mp) ! 961: MPARAM mp; ! 962: { ! 963: POINTL ptl; ! 964: HRGN hrgn, hrgnUpdt, hrgnUpdtDrag; ! 965: RECTL rcl; ! 966: CHAR pszMsg[40]; ! 967: PSZ psz1, psz2; ! 968: BOOL fFirst; ! 969: PSEGLIST psl; ! 970: ! 971: ptl.x = (LONG)(SHORT)SHORT1FROMMP( mp); ! 972: ptl.y = (LONG)(SHORT)SHORT2FROMMP( mp); ! 973: ! 974: /****************************************************************************/ ! 975: /****************************************************************************/ ! 976: pslPicked = Correlate( &ptl); ! 977: if( pslPicked) ! 978: lPickedSeg = pslPicked->lSegId; ! 979: else ! 980: { ! 981: fButtonDownAsync = FALSE; ! 982: return; ! 983: } ! 984: if( (lPickedSeg < 1) || (lPickedSeg > lLastSegId) ) ! 985: { ! 986: ! 987: DosRequestMutexSem( hmtxSzFmt, SEM_INDEFINITE_WAIT); ! 988: ! 989: sprintf( szFmt, "Segment id out of range: %x", lPickedSeg); ! 990: for( psz1 = szFmt, psz2 = pszMsg; *psz2++ = *psz1++; ) ! 991: ; ! 992: ! 993: DosReleaseMutexSem( hmtxSzFmt); ! 994: ! 995: MyMessageBox( hwndClient, pszMsg); ! 996: fButtonDownAsync = FALSE; ! 997: return; ! 998: } ! 999: ! 1000: /****************************************************************************/ ! 1001: ptlOffStart = pslPicked->ptlModelXlate; ! 1002: ptlMoveStart = ptl; ! 1003: GpiConvert( hpsClient, CVTC_DEVICE, CVTC_MODEL, 1L, &ptlMoveStart); ! 1004: ptlMoveStart.x = (ptlMoveStart.x / 50) * 50; ! 1005: ptlMoveStart.y = (ptlMoveStart.y / 50) * 50; ! 1006: ptlUpdtRef = ptlMoveStart; ! 1007: GpiConvert( hpsClient, CVTC_MODEL, CVTC_DEVICE, 1L, &ptlUpdtRef); ! 1008: ! 1009: /****************************************************************************/ ! 1010: hrgnUpdt = GpiCreateRegion( hpsClient, 0L, NULL); ! 1011: for( psl = pslPicked, fFirst = TRUE ! 1012: ; (psl != pslPicked) || fFirst ! 1013: ; psl = psl->pslNextIsland, fFirst = FALSE ) ! 1014: { ! 1015: rcl = psl->rclCurrent; /* get model space bounding box of piece */ ! 1016: GpiConvert( hpsClient, CVTC_MODEL, CVTC_DEVICE, 2L, (PPOINTL)&rcl); ! 1017: rcl.xRight++; /* adjust rectangle for conversion to dev space */ ! 1018: rcl.yTop++; ! 1019: rcl.xRight += 2; /* should not need */ ! 1020: rcl.yTop += 2; /* should not need */ ! 1021: rcl.xLeft -= 4; /* should not need */ ! 1022: rcl.yBottom -= 4; /* should not need */ ! 1023: hrgn = GpiCreateRegion( hpsClient, 1L, &rcl); ! 1024: GpiCombineRegion( hpsClient, hrgnUpdt, hrgnUpdt, hrgn, CRGN_OR); ! 1025: GpiDestroyRegion( hpsClient, hrgn); ! 1026: psl->fVisible = FALSE; ! 1027: } ! 1028: ! 1029: GpiQueryRegionBox( hpsClient, hrgnUpdt, (PRECTL)aptlUpdt); ! 1030: WinMapWindowPoints( hwndClient, HWND_DESKTOP, aptlUpdt, 3); ! 1031: ROUND_DOWN_MOD( aptlUpdt[0].x, lByteAlignX); /* round down */ ! 1032: ROUND_DOWN_MOD( aptlUpdt[0].y, lByteAlignY); /* round down */ ! 1033: ROUND_UP_MOD( aptlUpdt[1].x, lByteAlignX); /* round up */ ! 1034: ROUND_UP_MOD( aptlUpdt[1].y, lByteAlignY); /* round up */ ! 1035: WinMapWindowPoints( HWND_DESKTOP, hwndClient, aptlUpdt, 3); ! 1036: hrgnUpdtDrag = GpiCreateRegion( hpsBitmapBuff, 1L, (PRECTL)aptlUpdt); ! 1037: ! 1038: aptlUpdt[2] = aptlUpdt[0]; ! 1039: DoDraw( hpsBitmapBuff, hrgnUpdtDrag, TRUE); ! 1040: GpiDestroyRegion( hpsClient, hrgnUpdt); ! 1041: GpiDestroyRegion( hpsBitmapBuff, hrgnUpdtDrag); ! 1042: GpiBitBlt( hpsBitmapSave ! 1043: , hpsBitmapBuff ! 1044: , 3L ! 1045: , aptlUpdt ! 1046: , ROP_SRCCOPY ! 1047: , BBO_IGNORE ); ! 1048: ! 1049: /****************************************************************************/ ! 1050: for( psl = pslPicked, fFirst = TRUE ! 1051: ; (psl != pslPicked) || fFirst ! 1052: ; psl = psl->pslNextIsland, fFirst = FALSE ) ! 1053: { ! 1054: psl->fVisible = TRUE; ! 1055: DrawPiece( hpsBitmapBuff, psl, TRUE); ! 1056: } ! 1057: GpiBitBlt( hpsClient ! 1058: , hpsBitmapBuff ! 1059: , 3L ! 1060: , aptlUpdt ! 1061: , ROP_SRCCOPY ! 1062: , BBO_IGNORE ); ! 1063: WinSetCapture( HWND_DESKTOP, hwndClient); ! 1064: } ! 1065: ! 1066: ! 1067: ! 1068: ! 1069: /******************************************************************************/ ! 1070: /* */ ! 1071: /* move the segment */ ! 1072: /* */ ! 1073: /******************************************************************************/ ! 1074: VOID MouseMove( mp) ! 1075: MPARAM mp; ! 1076: { ! 1077: RECTL rcl; ! 1078: POINTL ptl, ptlModel, ptlDevice; ! 1079: POINTL aptlUpdtRef[3], aptlUpdtNew[3]; ! 1080: PSEGLIST psl; ! 1081: BOOL fFirst; ! 1082: ! 1083: ptl.x = (LONG)(SHORT)SHORT1FROMMP( mp); ! 1084: ptl.y = (LONG)(SHORT)SHORT2FROMMP( mp); ! 1085: ! 1086: /****************************************************************************/ ! 1087: /* clip mouse coords to client window */ ! 1088: /****************************************************************************/ ! 1089: WinQueryWindowRect( hwndClient, &rcl); ! 1090: if (rcl.xLeft > ptl.x) ! 1091: ptl.x = rcl.xLeft; ! 1092: if (rcl.xRight <= ptl.x) ! 1093: ptl.x = rcl.xRight; ! 1094: if (rcl.yBottom > ptl.y) ! 1095: ptl.y = rcl.yBottom; ! 1096: if (rcl.yTop <= ptl.y) ! 1097: ptl.y = rcl.yTop; ! 1098: ptlMouse = ptl; ! 1099: ! 1100: if( !lPickedSeg || !pslPicked || !fButtonDownAsync) ! 1101: return; ! 1102: ! 1103: ptlModel = ptl; ! 1104: GpiConvert( hpsClient, CVTC_DEVICE, CVTC_MODEL, 1L, &ptlModel); ! 1105: ptlModel.x = 50 * (ptlModel.x / 50); ! 1106: ptlModel.y = 50 * (ptlModel.y / 50); ! 1107: if( (ptlModel.x == ptlOldMouse.x) && (ptlModel.y == ptlOldMouse.y)) ! 1108: return; ! 1109: ptlOldMouse.x = ptlModel.x; ! 1110: ptlOldMouse.y = ptlModel.y; ! 1111: ptlDevice = ptlModel; ! 1112: GpiConvert( hpsClient, CVTC_MODEL, CVTC_DEVICE, 1L, &ptlDevice); ! 1113: ! 1114: GpiBitBlt( hpsBitmapBuff ! 1115: , hpsBitmapSave ! 1116: , 3L ! 1117: , aptlUpdt ! 1118: , ROP_SRCCOPY ! 1119: , BBO_IGNORE ); ! 1120: aptlUpdtRef[0] = aptlUpdt[0]; ! 1121: aptlUpdtRef[1] = aptlUpdt[1]; ! 1122: ! 1123: aptlUpdt[0].x += ptlDevice.x - ptlUpdtRef.x; ! 1124: aptlUpdt[0].y += ptlDevice.y - ptlUpdtRef.y; ! 1125: aptlUpdt[1].x += ptlDevice.x - ptlUpdtRef.x; ! 1126: aptlUpdt[1].y += ptlDevice.y - ptlUpdtRef.y; ! 1127: WinMapWindowPoints( hwndClient, HWND_DESKTOP, aptlUpdt, 3); ! 1128: ROUND_DOWN_MOD( aptlUpdt[0].x, lByteAlignX); /* round down */ ! 1129: ROUND_DOWN_MOD( aptlUpdt[0].y, lByteAlignY); /* round down */ ! 1130: ROUND_UP_MOD( aptlUpdt[1].x, lByteAlignX); /* round up */ ! 1131: ROUND_UP_MOD( aptlUpdt[1].y, lByteAlignY); /* round up */ ! 1132: WinMapWindowPoints( HWND_DESKTOP, hwndClient, aptlUpdt, 3); ! 1133: aptlUpdt[2] = aptlUpdt[0]; ! 1134: ptlUpdtRef = ptlDevice; ! 1135: GpiBitBlt( hpsBitmapSave ! 1136: , hpsBitmapBuff ! 1137: , 3L ! 1138: , aptlUpdt ! 1139: , ROP_SRCCOPY ! 1140: , BBO_IGNORE ); ! 1141: ! 1142: ! 1143: pslPicked->ptlModelXlate.x = ptlOffStart.x + ptlModel.x - ptlMoveStart.x; ! 1144: pslPicked->ptlModelXlate.y = ptlOffStart.y + ptlModel.y - ptlMoveStart.y; ! 1145: ! 1146: for( psl = pslPicked, fFirst = TRUE ! 1147: ; (psl != pslPicked) || fFirst ! 1148: ; psl = psl->pslNextIsland, fFirst = FALSE ) ! 1149: { ! 1150: psl->ptlModelXlate = pslPicked->ptlModelXlate; ! 1151: DrawPiece( hpsBitmapBuff, psl, TRUE); ! 1152: } ! 1153: ! 1154: WinUnionRect( habMain ! 1155: , (PRECTL)aptlUpdtNew ! 1156: , (PRECTL)aptlUpdt ! 1157: , (PRECTL)aptlUpdtRef); ! 1158: WinMapWindowPoints( hwndClient, HWND_DESKTOP, aptlUpdtNew, 2); ! 1159: ROUND_DOWN_MOD( aptlUpdtNew[0].x, lByteAlignX); /* round down */ ! 1160: ROUND_DOWN_MOD( aptlUpdtNew[0].y, lByteAlignY); /* round down */ ! 1161: ROUND_UP_MOD( aptlUpdtNew[1].x, lByteAlignX); /* round up */ ! 1162: ROUND_UP_MOD( aptlUpdtNew[1].y, lByteAlignY); /* round up */ ! 1163: WinMapWindowPoints( HWND_DESKTOP, hwndClient, aptlUpdtNew, 2); ! 1164: aptlUpdtNew[2] = aptlUpdtNew[0]; ! 1165: GpiBitBlt( hpsClient ! 1166: , hpsBitmapBuff ! 1167: , 3L ! 1168: , aptlUpdtNew ! 1169: , ROP_SRCCOPY ! 1170: , BBO_IGNORE ); ! 1171: } ! 1172: ! 1173: ! 1174: /******************************************************************************/ ! 1175: /* */ ! 1176: /* The dragged segment is being unselected. Return it to its normal state. */ ! 1177: /* */ ! 1178: /******************************************************************************/ ! 1179: VOID LeftUp(VOID) ! 1180: { ! 1181: PSEGLIST psl, pslTemp; ! 1182: POINTL ptlShift; ! 1183: BOOL fFirst; ! 1184: LONG l; ! 1185: ! 1186: if( !lPickedSeg || !pslPicked) ! 1187: return; ! 1188: ! 1189: for( psl = pslPicked, fFirst = TRUE ! 1190: ; (psl != pslPicked) || fFirst ! 1191: ; psl = psl->pslNextIsland, fFirst = FALSE ) ! 1192: { ! 1193: ! 1194: SetRect( psl); ! 1195: SegListUpdate( MAKE_TAIL_SEG, psl); /* at tail => highest priority */ ! 1196: psl->fIslandMark = TRUE; /* mark as island member */ ! 1197: } ! 1198: ptlShift = pslPicked->ptlModelXlate; ! 1199: ! 1200: for( psl = pslHead; psl != NULL; psl = psl->pslNext) ! 1201: if( !psl->fIslandMark) ! 1202: for( l = 0; l < 8; l++) ! 1203: if( pslPicked->lAdjacent[l] == psl->lSegId) ! 1204: if( (ptlShift.x == psl->ptlModelXlate.x) ! 1205: && (ptlShift.y == psl->ptlModelXlate.y)) ! 1206: { ! 1207: DosBeep( 600, 100); ! 1208: DosBeep( 1200, 50); ! 1209: MarkIsland( psl, TRUE); /* mark the whole new island */ ! 1210: pslTemp = psl->pslNextIsland; /* swap island ptrs */ ! 1211: psl->pslNextIsland = pslPicked->pslNextIsland; ! 1212: pslPicked->pslNextIsland = pslTemp; ! 1213: } ! 1214: MarkIsland( pslPicked, FALSE); /* unmark the island */ ! 1215: ! 1216: pslPicked = NULL; ! 1217: lPickedSeg = NULL; ! 1218: ! 1219: WinSetCapture( HWND_DESKTOP, (HWND)NULL); ! 1220: } ! 1221: ! 1222: ! 1223: /******************************************************************************/ ! 1224: /* */ ! 1225: /* DoHorzScroll will horizontally scroll the current contents of */ ! 1226: /* the client area and redraw the invalidated area */ ! 1227: /* */ ! 1228: /******************************************************************************/ ! 1229: VOID DoHorzScroll(VOID) ! 1230: { ! 1231: POINTL aptlClient[3]; ! 1232: HRGN hrgn; ! 1233: MATRIXLF matlf; ! 1234: ! 1235: if( ptsScrollPos.x > ptsScrollMax.x) /* clip to range of scroll param */ ! 1236: ptsScrollPos.x = ptsScrollMax.x; ! 1237: if( ptsScrollPos.x < 0) ! 1238: ptsScrollPos.x = 0; ! 1239: ! 1240: if( ptsOldScrollPos.x != ptsScrollPos.x) /* only process change in position */ ! 1241: WinSendMsg( hwndHorzScroll ! 1242: , SBM_SETPOS ! 1243: , MPFROM2SHORT( ptsScrollPos.x, 0) ! 1244: , MPFROMLONG( NULL)); ! 1245: ! 1246: /****************************************************************************/ ! 1247: /* Scroll the window the reqd amount, using bitblt'ing (ScrollWindow) */ ! 1248: /* if any of the screen still in view, and paint into uncovered region; */ ! 1249: /* else repaint the whole client area. */ ! 1250: /****************************************************************************/ ! 1251: hrgn = GpiCreateRegion( hpsClient, 0L, NULL); ! 1252: WinQueryWindowRect( hwndClient, (PRECTL)aptlClient); ! 1253: if( abs( ptsScrollPos.x - ptsOldScrollPos.x) <= ptsScrollMax.x) ! 1254: { ! 1255: WinScrollWindow( hwndClient ! 1256: , ptsOldScrollPos.x - ptsScrollPos.x ! 1257: , 0 ! 1258: , NULL ! 1259: , NULL ! 1260: , hrgn ! 1261: , NULL ! 1262: , 0); ! 1263: } else ! 1264: { ! 1265: GpiSetRegion( hpsClient, hrgn, 1L, (PRECTL)aptlClient); ! 1266: } ! 1267: /****************************************************************************/ ! 1268: /* adjust the default view matrix */ ! 1269: /****************************************************************************/ ! 1270: GpiQueryDefaultViewMatrix( hpsClient, 9L, &matlf ); ! 1271: matlf.lM31 -= ptsScrollPos.x - ptsOldScrollPos.x; ! 1272: GpiSetDefaultViewMatrix( hpsClient, 9L, &matlf, TRANSFORM_REPLACE); ! 1273: ! 1274: DoDraw( hpsClient, hrgn, TRUE); /* paint into the client area */ ! 1275: ptsOldScrollPos.x = ptsScrollPos.x; ! 1276: GpiDestroyRegion( hpsClient, hrgn); ! 1277: ! 1278: aptlClient[2] = aptlClient[0]; ! 1279: GpiBitBlt( hpsBitmapBuff /* update the off-screen client image */ ! 1280: , hpsClient ! 1281: , 3L ! 1282: , aptlClient ! 1283: , ROP_SRCCOPY ! 1284: , BBO_IGNORE ); ! 1285: } ! 1286: ! 1287: /******************************************************************************/ ! 1288: /* */ ! 1289: /* DoVertScroll will vertically scroll the current contents of */ ! 1290: /* the client area and redraw the invalidated area */ ! 1291: /* */ ! 1292: /******************************************************************************/ ! 1293: VOID DoVertScroll(VOID) ! 1294: { ! 1295: POINTL aptlClient[3]; ! 1296: HRGN hrgn; ! 1297: MATRIXLF matlf; ! 1298: ! 1299: if( ptsScrollPos.y > ptsScrollMax.y) ! 1300: ptsScrollPos.y = ptsScrollMax.y; ! 1301: if( ptsScrollPos.y < 0) ! 1302: ptsScrollPos.y = 0; ! 1303: ! 1304: if( ptsOldScrollPos.y != ptsScrollPos.y) ! 1305: WinSendMsg( hwndVertScroll ! 1306: , SBM_SETPOS ! 1307: , MPFROM2SHORT( ptsScrollPos.y, 0) ! 1308: , MPFROMLONG( NULL)); ! 1309: ! 1310: /****************************************************************************/ ! 1311: /* Scroll the window the reqd amount, using bitblt'ing (ScrollWindow) */ ! 1312: /* if any of the screen still in view, and paint into uncovered region; */ ! 1313: /* else repaint the whole client area. */ ! 1314: /****************************************************************************/ ! 1315: hrgn = GpiCreateRegion( hpsClient, 0L, NULL); ! 1316: WinQueryWindowRect( hwndClient, (PRECTL)aptlClient); ! 1317: if( abs( ptsScrollPos.y - ptsOldScrollPos.y) <= ptsScrollMax.y) ! 1318: { ! 1319: WinScrollWindow( hwndClient ! 1320: , 0 ! 1321: , ptsScrollPos.y - ptsOldScrollPos.y ! 1322: , NULL ! 1323: , NULL ! 1324: , hrgn ! 1325: , NULL ! 1326: , 0); ! 1327: } else ! 1328: { ! 1329: GpiSetRegion( hpsClient, hrgn, 1L, (PRECTL)aptlClient); ! 1330: } ! 1331: GpiQueryDefaultViewMatrix( hpsClient, 9L, &matlf ); ! 1332: matlf.lM32 += ptsScrollPos.y - ptsOldScrollPos.y; ! 1333: GpiSetDefaultViewMatrix( hpsClient, 9L, &matlf, TRANSFORM_REPLACE); ! 1334: ! 1335: DoDraw( hpsClient, hrgn, TRUE); ! 1336: ptsOldScrollPos.y = ptsScrollPos.y; ! 1337: GpiDestroyRegion( hpsClient, hrgn); ! 1338: ! 1339: aptlClient[2] = aptlClient[0]; ! 1340: GpiBitBlt( hpsBitmapBuff ! 1341: , hpsClient ! 1342: , 3L ! 1343: , aptlClient ! 1344: , ROP_SRCCOPY ! 1345: , BBO_IGNORE ); ! 1346: } ! 1347: ! 1348: /******************************************************************************/ ! 1349: /* */ ! 1350: /* toggle a flag and update the menu check-box */ ! 1351: /* */ ! 1352: /******************************************************************************/ ! 1353: VOID ToggleMenuItem( usMenuMajor, usMenuMinor, pfFlag) ! 1354: USHORT usMenuMajor; ! 1355: USHORT usMenuMinor; ! 1356: PBOOL pfFlag; ! 1357: { ! 1358: MENUITEM mi; ! 1359: ! 1360: WinSendMsg( WinWindowFromID( hwndFrame, FID_MENU) ! 1361: , MM_QUERYITEM ! 1362: , MPFROM2SHORT( usMenuMajor, FALSE) ! 1363: , MPFROMP( (PMENUITEM)&mi)); ! 1364: ! 1365: if( *pfFlag) ! 1366: { ! 1367: *pfFlag = FALSE; ! 1368: WinSendMsg( mi.hwndSubMenu ! 1369: , MM_SETITEMATTR ! 1370: , MPFROM2SHORT( usMenuMinor, TRUE) ! 1371: , MPFROM2SHORT( MIA_CHECKED, ~MIA_CHECKED) ); ! 1372: } ! 1373: else ! 1374: { ! 1375: *pfFlag = TRUE; ! 1376: WinSendMsg( mi.hwndSubMenu ! 1377: , MM_SETITEMATTR ! 1378: , MPFROM2SHORT( usMenuMinor, TRUE) ! 1379: , MPFROM2SHORT( MIA_CHECKED, MIA_CHECKED) ); ! 1380: } ! 1381: } ! 1382: ! 1383: /******************************************************************************/ ! 1384: /* */ ! 1385: /* adjust zoom factor and recalc the picture transform, then do a redraw of */ ! 1386: /* whole screen */ ! 1387: /* */ ! 1388: /******************************************************************************/ ! 1389: VOID Zoom( VOID ) ! 1390: { ! 1391: ULONG ulPostKillDraw, ulPostCt; ! 1392: ! 1393: DosQueryEventSem(hevKillDraw, &ulPostKillDraw); ! 1394: ! 1395: CalcBounds(); ! 1396: DosQueryEventSem(hevKillDraw, &ulPostCt); ! 1397: if (ulPostKillDraw != ulPostCt) { ! 1398: DosResetEventSem(hevKillDraw, &ulPostCt); ! 1399: return; ! 1400: } ! 1401: CalcTransform( hwndClient); ! 1402: DosQueryEventSem(hevKillDraw, &ulPostCt); ! 1403: if (ulPostKillDraw != ulPostCt) { ! 1404: DosResetEventSem(hevKillDraw, &ulPostCt); ! 1405: return; ! 1406: } ! 1407: Redraw(); ! 1408: } ! 1409: ! 1410: /******************************************************************************/ ! 1411: /* */ ! 1412: /* Check the segment list for obvious errors. */ ! 1413: /* */ ! 1414: /******************************************************************************/ ! 1415: BOOL SegListCheck( iLoc) ! 1416: INT iLoc; ! 1417: { ! 1418: PSEGLIST psl; ! 1419: CHAR pszMsg[50]; ! 1420: PSZ psz1, psz2; ! 1421: ! 1422: pszMsg[0] = '\0'; ! 1423: for( psl = pslHead; psl != NULL; psl = psl->pslNext) ! 1424: if( (psl->lSegId < 1) || (psl->lSegId > lLastSegId) ) ! 1425: { ! 1426: ! 1427: DosRequestMutexSem( hmtxSzFmt, SEM_INDEFINITE_WAIT); ! 1428: ! 1429: sprintf( szFmt, "Bad head segment list, location %d", iLoc); ! 1430: for( psz1 = szFmt, psz2 = pszMsg; *psz2++ = *psz1++; ) ! 1431: ; ! 1432: ! 1433: DosReleaseMutexSem( hmtxSzFmt); ! 1434: ! 1435: MyMessageBox( hwndClient, pszMsg); ! 1436: return( FALSE); ! 1437: } ! 1438: for( psl = pslTail; psl != NULL; psl = psl->pslPrev) ! 1439: if( (psl->lSegId < 1) || (psl->lSegId > lLastSegId) ) ! 1440: { ! 1441: ! 1442: DosRequestMutexSem( hmtxSzFmt, SEM_INDEFINITE_WAIT); ! 1443: ! 1444: sprintf( szFmt, "Bad head segment list, location %d", iLoc); ! 1445: for( psz1 = szFmt, psz2 = pszMsg; *psz2++ = *psz1++; ) ! 1446: ; ! 1447: ! 1448: DosReleaseMutexSem( hmtxSzFmt); ! 1449: ! 1450: MyMessageBox( hwndClient, pszMsg); ! 1451: return( FALSE); ! 1452: } ! 1453: return( TRUE); ! 1454: } ! 1455: ! 1456: /******************************************************************************/ ! 1457: /* */ ! 1458: /* DumpPicture will free the list and segment store for the picture */ ! 1459: /* */ ! 1460: /******************************************************************************/ ! 1461: BOOL DumpPicture(VOID) ! 1462: { ! 1463: while( pslHead != NULL ) ! 1464: { ! 1465: GpiSetBitmap( pslHead->hpsFill, NULL); ! 1466: GpiDeleteBitmap( pslHead->hbmFill); ! 1467: GpiDestroyPS( pslHead->hpsFill); ! 1468: DevCloseDC( pslHead->hdcFill); ! 1469: ! 1470: GpiSetBitmap( pslHead->hpsHole, NULL); ! 1471: GpiDeleteBitmap( pslHead->hbmHole); ! 1472: GpiDestroyPS( pslHead->hpsHole); ! 1473: DevCloseDC( pslHead->hdcHole); ! 1474: ! 1475: SegListUpdate( DEL_SEG, pslHead); ! 1476: } ! 1477: ! 1478: if( hbmBitmapSize) ! 1479: { ! 1480: GpiSetBitmap( hpsBitmapSize, NULL); ! 1481: GpiDeleteBitmap( hbmBitmapSize); ! 1482: } ! 1483: if( hbmBitmapBuff) ! 1484: { ! 1485: GpiSetBitmap( hpsBitmapBuff, NULL); ! 1486: GpiDeleteBitmap( hbmBitmapBuff); ! 1487: } ! 1488: if( hbmBitmapSave) ! 1489: { ! 1490: GpiSetBitmap( hpsBitmapSave, NULL); ! 1491: GpiDeleteBitmap( hbmBitmapSave); ! 1492: } ! 1493: ! 1494: return( TRUE); ! 1495: } ! 1496: ! 1497: /******************************************************************************/ ! 1498: /* */ ! 1499: /* Draw the picture into segment store. */ ! 1500: /* */ ! 1501: /******************************************************************************/ ! 1502: BOOL CreatePicture( sUpdate) ! 1503: SHORT sUpdate; ! 1504: { ! 1505: POINTL ptl, aptlSides[12], aptlControl[12]; ! 1506: SEGLIST sl; ! 1507: PSEGLIST psl; ! 1508: LONG l, lMinor, lNeighbor, alFuzz[36][4]; ! 1509: SIZEL sizl; ! 1510: BITMAPINFOHEADER2 bmp2; ! 1511: PBITMAPINFOHEADER2 pbmp2 = &bmp2; ! 1512: DATETIME date; ! 1513: ULONG ulPostCt; ! 1514: ! 1515: /****************************************************************************/ ! 1516: /* compute some fuzz for the control points */ ! 1517: /****************************************************************************/ ! 1518: DosGetDateTime( &date); ! 1519: srand( (USHORT)date.hundredths); ! 1520: for( l = 0; l < 36; l++) ! 1521: for( lMinor = 0; lMinor < 4; lMinor++) ! 1522: alFuzz[l][lMinor] = 50 * (rand() % 10); ! 1523: ! 1524: /****************************************************************************/ ! 1525: /* reset the default viewing transform to identity */ ! 1526: /****************************************************************************/ ! 1527: SetDVTransform( (FIXED)UNITY ! 1528: , (FIXED)0 ! 1529: , (FIXED)0 ! 1530: , (FIXED)UNITY ! 1531: , 0L ! 1532: , 0L ! 1533: , TRANSFORM_REPLACE); ! 1534: ! 1535: /****************************************************************************/ ! 1536: /* draw the pieces */ ! 1537: /****************************************************************************/ ! 1538: lLastSegId = 0; ! 1539: for( ptl.x = ptlBotLeft.x; ptl.x < ptlTopRight.x; ptl.x += 500) ! 1540: { ! 1541: DosQueryEventSem( hevTerminate, &ulPostCt); ! 1542: if( ulPostCt) ! 1543: break; ! 1544: for( ptl.y = ptlBotLeft.y; ptl.y < ptlTopRight.y; ptl.y += 500) ! 1545: { ! 1546: DosQueryEventSem( hevTerminate, &ulPostCt); ! 1547: if( ulPostCt) ! 1548: break; ! 1549: lLastSegId++; ! 1550: ! 1551: /************************************************************************/ ! 1552: /* compute the piece outline control points */ ! 1553: /************************************************************************/ ! 1554: aptlControl[0].x = 250L; ! 1555: aptlControl[0].y = 500L; ! 1556: aptlControl[1].x = 250; ! 1557: aptlControl[1].y = -500L; ! 1558: aptlControl[2].x = 500L; ! 1559: aptlControl[2].y = 0L; ! 1560: ! 1561: aptlControl[3].x = 0L; ! 1562: aptlControl[3].y = 250L; ! 1563: aptlControl[4].x = 1000L; ! 1564: aptlControl[4].y = 250L; ! 1565: aptlControl[5].x = 500L; ! 1566: aptlControl[5].y = 500L; ! 1567: ! 1568: aptlControl[6].x = 250L; ! 1569: aptlControl[6].y = 0L; ! 1570: aptlControl[7].x = 250L; ! 1571: aptlControl[7].y = 1000L; ! 1572: aptlControl[8].x = 0L; ! 1573: aptlControl[8].y = 500L; ! 1574: ! 1575: aptlControl[9].x = 500L; ! 1576: aptlControl[9].y = 250L; ! 1577: aptlControl[10].x = -500L; ! 1578: aptlControl[10].y = 250L; ! 1579: aptlControl[11].x = 0L; ! 1580: aptlControl[11].y = 0L; ! 1581: ! 1582: if( ptl.y == ptlBotLeft.y) ! 1583: { ! 1584: aptlControl[0].y = 0L; ! 1585: aptlControl[1].y = 0L; ! 1586: } ! 1587: ! 1588: if( (ptl.x + 500) == ptlTopRight.x) ! 1589: { ! 1590: aptlControl[3].x = 500L; ! 1591: aptlControl[4].x = 500L; ! 1592: } ! 1593: ! 1594: if( (ptl.y + 500) == ptlTopRight.y) ! 1595: { ! 1596: aptlControl[6].y = 500L; ! 1597: aptlControl[7].y = 500L; ! 1598: } ! 1599: ! 1600: if( ptl.x == ptlBotLeft.x) ! 1601: { ! 1602: aptlControl[ 9].x = 0L; ! 1603: aptlControl[10].x = 0L; ! 1604: } ! 1605: ! 1606: /************************************************************************/ ! 1607: /* compute the adjacent segments */ ! 1608: /************************************************************************/ ! 1609: sl.lAdjacent[0] = lLastSegId - 7; ! 1610: sl.lAdjacent[1] = lLastSegId - 6; ! 1611: sl.lAdjacent[2] = lLastSegId - 5; ! 1612: sl.lAdjacent[3] = lLastSegId - 1; ! 1613: sl.lAdjacent[4] = lLastSegId + 1; ! 1614: sl.lAdjacent[5] = lLastSegId + 5; ! 1615: sl.lAdjacent[6] = lLastSegId + 6; ! 1616: sl.lAdjacent[7] = lLastSegId + 7; ! 1617: if( ptl.x == ptlBotLeft.x) ! 1618: { ! 1619: sl.lAdjacent[0] = 0; ! 1620: sl.lAdjacent[1] = 0; ! 1621: sl.lAdjacent[2] = 0; ! 1622: } ! 1623: if( ptl.y == ptlBotLeft.y) ! 1624: { ! 1625: sl.lAdjacent[0] = 0; ! 1626: sl.lAdjacent[3] = 0; ! 1627: sl.lAdjacent[5] = 0; ! 1628: } ! 1629: if( (ptl.x + 500) == ptlTopRight.x) ! 1630: { ! 1631: sl.lAdjacent[5] = 0; ! 1632: sl.lAdjacent[6] = 0; ! 1633: sl.lAdjacent[7] = 0; ! 1634: } ! 1635: if( (ptl.y + 500) == ptlTopRight.y) ! 1636: { ! 1637: sl.lAdjacent[2] = 0; ! 1638: sl.lAdjacent[4] = 0; ! 1639: sl.lAdjacent[7] = 0; ! 1640: } ! 1641: ! 1642: /************************************************************************/ ! 1643: /* throw in some fuzz */ ! 1644: /************************************************************************/ ! 1645: if( sl.lAdjacent[3]) ! 1646: { ! 1647: aptlControl[0].y -= alFuzz[lLastSegId - 1][0]; ! 1648: aptlControl[1].y += alFuzz[lLastSegId - 1][1]; ! 1649: } ! 1650: ! 1651: if( sl.lAdjacent[1]) ! 1652: { ! 1653: aptlControl[9].x -= alFuzz[lLastSegId - 1][2]; ! 1654: aptlControl[10].x += alFuzz[lLastSegId - 1][3]; ! 1655: } ! 1656: ! 1657: if( lNeighbor = sl.lAdjacent[4]) ! 1658: { ! 1659: aptlControl[7].y -= alFuzz[lNeighbor - 1][0]; ! 1660: aptlControl[6].y += alFuzz[lNeighbor - 1][1]; ! 1661: } ! 1662: ! 1663: if( lNeighbor = sl.lAdjacent[6]) ! 1664: { ! 1665: aptlControl[4].x -= alFuzz[lNeighbor - 1][2]; ! 1666: aptlControl[3].x += alFuzz[lNeighbor - 1][3]; ! 1667: } ! 1668: ! 1669: /************************************************************************/ ! 1670: /* compute the piece control points in world coordinates */ ! 1671: /************************************************************************/ ! 1672: for( l=0; l<12; l++) ! 1673: { ! 1674: aptlSides[l].x = ptl.x + aptlControl[l].x; ! 1675: aptlSides[l].y = ptl.y + aptlControl[l].y; ! 1676: sl.aptlSides[l] = aptlSides[l]; ! 1677: } ! 1678: ! 1679: /************************************************************************/ ! 1680: /* compute the dimensions of the matching rects for BitBlt */ ! 1681: /************************************************************************/ ! 1682: sl.rclBitBlt.xLeft = ptl.x - 250; ! 1683: sl.rclBitBlt.yBottom = ptl.y - 250; ! 1684: sl.rclBitBlt.xRight = ptl.x + 750; ! 1685: sl.rclBitBlt.yTop = ptl.y + 750; ! 1686: if( ptl.x == ptlBotLeft.x) ! 1687: sl.rclBitBlt.xLeft += 250; ! 1688: if( ptl.y == ptlBotLeft.y) ! 1689: sl.rclBitBlt.yBottom += 250; ! 1690: if( (ptl.x + 500) == ptlTopRight.x) ! 1691: sl.rclBitBlt.xRight -= 250; ! 1692: if( (ptl.y + 500) == ptlTopRight.y) ! 1693: sl.rclBitBlt.yTop -= 250; ! 1694: ! 1695: /************************************************************************/ ! 1696: /* store the piece location */ ! 1697: /************************************************************************/ ! 1698: sl.ptlLocation = ptl; ! 1699: ! 1700: /************************************************************************/ ! 1701: /* create the masks */ ! 1702: /************************************************************************/ ! 1703: if( sUpdate == PICTURE_CREATE) ! 1704: { ! 1705: sizl.cx = 2 + ((ADJUSTED_PBMP(pbmp2BitmapFile)->cx ! 1706: * (sl.rclBitBlt.xRight - sl.rclBitBlt.xLeft)) ! 1707: / (ptlTopRight.x - ptlBotLeft.x)); ! 1708: sizl.cy = 2 + ((ADJUSTED_PBMP(pbmp2BitmapFile)->cy ! 1709: * (sl.rclBitBlt.yTop - sl.rclBitBlt.yBottom)) ! 1710: / (ptlTopRight.y - ptlBotLeft.y)); ! 1711: ! 1712: bmp2 = bmp2BitmapFile; ! 1713: ADJUSTED_PBMP(pbmp2)->cx = LOUSHORT( sizl.cx); ! 1714: ADJUSTED_PBMP(pbmp2)->cy = LOUSHORT( sizl.cy); ! 1715: ! 1716: sl.hdcHole = DevOpenDC( habMain ! 1717: , OD_MEMORY ! 1718: , "*" ! 1719: , 3L ! 1720: , (PDEVOPENDATA)&dop ! 1721: , NULL); ! 1722: sl.hpsHole = GpiCreatePS( habMain ! 1723: , sl.hdcHole ! 1724: , &sizl ! 1725: , PU_PELS | GPIA_ASSOC | GPIT_MICRO ); ! 1726: sl.hbmHole = GpiCreateBitmap( sl.hpsHole ! 1727: , pbmp2 ! 1728: , 0L ! 1729: , NULL ! 1730: , NULL); ! 1731: GpiSetBitmap( sl.hpsHole, sl.hbmHole); ! 1732: ! 1733: ! 1734: sl.hdcFill = DevOpenDC( habMain ! 1735: , OD_MEMORY ! 1736: , "*" ! 1737: , 3L ! 1738: , (PDEVOPENDATA)&dop ! 1739: , NULL); ! 1740: sl.hpsFill = GpiCreatePS( habMain ! 1741: , sl.hdcFill ! 1742: , &sizl ! 1743: , PU_PELS | GPIA_ASSOC | GPIT_MICRO ); ! 1744: sl.hbmFill = GpiCreateBitmap( sl.hpsFill ! 1745: , pbmp2 ! 1746: , 0L ! 1747: , NULL ! 1748: , NULL); ! 1749: GpiSetBitmap( sl.hpsFill, sl.hbmFill); ! 1750: } ! 1751: ! 1752: ! 1753: sl.fVisible = TRUE; ! 1754: sl.lSegId = lLastSegId; ! 1755: sl.fIslandMark = FALSE; ! 1756: sl.ptlModelXlate.x = sl.ptlModelXlate.y = 0L; ! 1757: if( sUpdate == PICTURE_CREATE) ! 1758: { ! 1759: sl.pslNext = NULL; ! 1760: sl.pslPrev = NULL; ! 1761: SetRect( &sl); ! 1762: psl = SegListUpdate( ADD_TAIL_SEG, &sl); ! 1763: } else ! 1764: { ! 1765: psl = SegListGet( lLastSegId); ! 1766: psl->fIslandMark = FALSE; ! 1767: for( l=0; l<12; l++) ! 1768: psl->aptlSides[l] = aptlSides[l]; ! 1769: psl->ptlModelXlate = sl.ptlModelXlate; ! 1770: SetRect( psl); ! 1771: } ! 1772: psl->pslNextIsland = psl; /* point to self ==> island of one */ ! 1773: } ! 1774: } ! 1775: return( TRUE); ! 1776: } ! 1777: ! 1778: /******************************************************************************/ ! 1779: /******************************************************************************/ ! 1780: /******************************************************************************/ ! 1781: VOID CheckPsl( psl) ! 1782: PSEGLIST psl; ! 1783: { ! 1784: SHORT s; ! 1785: ! 1786: for( s=2; s<12; s+=3) ! 1787: if( !WinPtInRect( habAsync, &psl->rclBitBlt, &psl->aptlSides[s])) ! 1788: break; ! 1789: } ! 1790: ! 1791: /******************************************************************************/ ! 1792: /* */ ! 1793: /* Create the Size, Save and Buff bitmaps. */ ! 1794: /* */ ! 1795: /******************************************************************************/ ! 1796: BOOL PrepareBitmap(VOID) ! 1797: { ! 1798: hbmBitmapSize = GpiCreateBitmap( hpsBitmapSize ! 1799: , pbmp2BitmapFile ! 1800: , 0L ! 1801: , NULL ! 1802: , NULL); ! 1803: if( !hbmBitmapSize) ! 1804: return( FALSE); ! 1805: GpiSetBitmap( hpsBitmapSize, hbmBitmapSize); ! 1806: ! 1807: ! 1808: bmp2BitmapSave = bmp2BitmapFile; ! 1809: ADJUSTED_PBMP(pbmp2BitmapSave)->cx = LOUSHORT( sizlMaxClient.cx); ! 1810: ADJUSTED_PBMP(pbmp2BitmapSave)->cy = LOUSHORT( sizlMaxClient.cy); ! 1811: hbmBitmapSave = GpiCreateBitmap( hpsBitmapSave ! 1812: , pbmp2BitmapSave ! 1813: , 0L ! 1814: , NULL ! 1815: , NULL); ! 1816: if( !hbmBitmapSave) ! 1817: return( FALSE); ! 1818: GpiSetBitmap( hpsBitmapSave, hbmBitmapSave); ! 1819: ! 1820: ! 1821: hbmBitmapBuff = GpiCreateBitmap( hpsBitmapBuff ! 1822: , pbmp2BitmapSave ! 1823: , 0L ! 1824: , NULL ! 1825: , NULL); ! 1826: if( !hbmBitmapBuff) ! 1827: return( FALSE); ! 1828: GpiSetBitmap( hpsBitmapBuff, hbmBitmapBuff); ! 1829: ! 1830: return( TRUE); ! 1831: } ! 1832: ! 1833: /******************************************************************************/ ! 1834: /* */ ! 1835: /* Get the bitmap from disk. */ ! 1836: /* Note that there are 2 formats for bitmap files, one of which is archaic. */ ! 1837: /* Both formats are supported here. All new bitmaps should follow the format */ ! 1838: /* in BITMAPFILEHEADER. */ ! 1839: /* */ ! 1840: /******************************************************************************/ ! 1841: BOOL ReadBitmap( hfile) ! 1842: HFILE hfile; ! 1843: { ! 1844: ULONG cScans; ! 1845: ULONG cbRead; /* Number of bytes read by DosRead. */ ! 1846: BOOL fRet = FALSE; /* Function return code. */ ! 1847: FILESTATUS fsts; ! 1848: PBITMAPFILEHEADER2 pbfh2; ! 1849: ! 1850: /**************************************************************************/ ! 1851: /* Find out how big the file is so we can read the whole thing in. */ ! 1852: /**************************************************************************/ ! 1853: ! 1854: if( DosQueryFileInfo( hfile, 1, &fsts, sizeof(FILESTATUS))) ! 1855: goto ReadBitmap_close_file; ! 1856: ! 1857: if( DosAllocMem( &pbfh2, fsts.cbFile, PAG_READ | PAG_WRITE | PAG_COMMIT)) ! 1858: goto ReadBitmap_close_file; ! 1859: ! 1860: /**************************************************************************/ ! 1861: /* Read the bits in from the file. */ ! 1862: /**************************************************************************/ ! 1863: ! 1864: if( DosRead( hfile, (PVOID)pbfh2, fsts.cbFile, &cbRead)) ! 1865: goto ReadBitmap_free_bits; ! 1866: ! 1867: /**************************************************************************/ ! 1868: /* Tell GPI to put the bits into the thread's PS. The function returns */ ! 1869: /* the number of scan lines of the bitmap that were copied. We want */ ! 1870: /* all of them at once. */ ! 1871: /**************************************************************************/ ! 1872: ! 1873: ADJUSTED_PBMP(pbmp2BitmapFile)->cbFix = pbfh2->bmp2.cbFix; ! 1874: /* check to see if BMP file was an old structure or a new structure */ ! 1875: if (pbfh2->bmp2.cbFix == sizeof(BITMAPINFOHEADER)) { ! 1876: PBMP1(pbmp2BitmapFile)->cx = PBFH1(pbfh2)->bmp.cx; ! 1877: PBMP1(pbmp2BitmapFile)->cy = PBFH1(pbfh2)->bmp.cy; ! 1878: PBMP1(pbmp2BitmapFile)->cPlanes = PBFH1(pbfh2)->bmp.cPlanes; ! 1879: PBMP1(pbmp2BitmapFile)->cBitCount = PBFH1(pbfh2)->bmp.cBitCount; ! 1880: } ! 1881: else { ! 1882: pbmp2BitmapFile->cx = pbfh2->bmp2.cx; ! 1883: pbmp2BitmapFile->cy = pbfh2->bmp2.cy; ! 1884: pbmp2BitmapFile->cPlanes = pbfh2->bmp2.cPlanes; ! 1885: pbmp2BitmapFile->cBitCount = pbfh2->bmp2.cBitCount; ! 1886: } ! 1887: hbmBitmapFile = GpiCreateBitmap( hpsBitmapFile ! 1888: , pbmp2BitmapFile ! 1889: , 0L ! 1890: , NULL ! 1891: , NULL); ! 1892: if( !hbmBitmapFile) ! 1893: goto ReadBitmap_free_bits; ! 1894: if (GpiSetBitmap( hpsBitmapFile, hbmBitmapFile) == HBM_ERROR) { ! 1895: goto ReadBitmap_free_bits; ! 1896: } ! 1897: ! 1898: /* check to see if BMP file was an old structure or a new structure */ ! 1899: if (pbfh2->bmp2.cbFix == sizeof(BITMAPINFOHEADER)) { ! 1900: cScans = GpiSetBitmapBits( hpsBitmapFile ! 1901: , 0L ! 1902: , (LONG) PBFH1(pbfh2)->bmp.cy ! 1903: , ((PBYTE)(pbfh2)) + pbfh2->offBits ! 1904: , (PBITMAPINFO2)&(PBFH1(pbfh2)->bmp)); ! 1905: if (cScans != (LONG)PBFH1(pbfh2)->bmp.cy) /* original number ! 1906: of scans ? */ ! 1907: goto ReadBitmap_free_bits; ! 1908: } ! 1909: else { ! 1910: cScans = GpiSetBitmapBits( hpsBitmapFile ! 1911: , 0L ! 1912: , (LONG) pbfh2->bmp2.cy ! 1913: , ((PBYTE)(pbfh2)) + pbfh2->offBits ! 1914: , (PBITMAPINFO2)&(pbfh2->bmp2)); ! 1915: if (cScans != (LONG)pbfh2->bmp2.cy) /* original number of scans ? */ ! 1916: goto ReadBitmap_free_bits; ! 1917: } ! 1918: ! 1919: fRet = TRUE; ! 1920: ! 1921: ! 1922: /**************************************************************************/ ! 1923: /* Close the file, free the buffer space and leave. This is a */ ! 1924: /* common exit point from the function. Since the same cleanup */ ! 1925: /* operations need to be performed for such a large number of */ ! 1926: /* possible error conditions, this is concise way to do the right */ ! 1927: /* thing. */ ! 1928: /**************************************************************************/ ! 1929: ! 1930: ReadBitmap_free_bits: ! 1931: DosFreeMem( pbfh2); ! 1932: ! 1933: ReadBitmap_close_file: ! 1934: DosClose( hfile); ! 1935: return fRet; ! 1936: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.