Annotation of os232sdk/toolkt20/c/samples/jigsaw/jigsaw.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

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