home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *
- * File Name : JIGSAW.C
- *
- * Description : main function and code for the Jigsaw application
- *
- * This program provides a jigsaw puzzle, based on a decomposition of an
- * arbitrary bitmap loaded from a file. The user can jumble the pieces,
- * then drag them individually by means of the mouse. The image can be
- * zoomed in and out and scrolled up/down and left/right.
- *
- * JIGSAW uses GpiBitBlt with clip paths to create a collection of picture
- * fragments which are the puzzle pieces. In earlier versions of the
- * program, each of these pieces was associated with a single retain-mode
- * graphics segment. The retain-mode technique, however, proved to be
- * too slow, so subsequent versions of the program used retain-mode APIs
- * for fewer and fewer operations. The current version eliminates
- * retain-mode graphics altogether. Instead, the drawing data for each
- * piece is stored in _SEGLIST data structure defined in JIGSAW.H.
- * This structure contains all the data needed to draw a piece, including
- * pointers to the previous and next pieces. The _SEGLIST nodes are
- * arranged in drawing priority order, so the picture can be reconstructed
- * by traversing the list in sequence, drawing each piece as its
- * corresponding structure is encountered. Where the comments in the
- * rest of the program refer to a "segment," they are simply referring to
- * a piece of the puzzle as defined by a record in this data structure.
- *
- * To retain responsiveness to user requests, the real work is done in a
- * second thread, with work requests transmitted from the main thread in
- * the form of messages. This arrangement makes it possible for the user
- * to override lengthy drawing operations with a higher-priority request
- * (eg. program termination, magnification change, etc.).
- *
- * Individual pieces are made to "move" by changing their model transforms.
- * Scrolling and zooming of the whole picture is done by changing the
- * default viewing transform. The points in model space associated with
- * each piece (control points for the bounding curve, corners of the
- * bounding box, etc.) are converted via GpiConvert into points in device
- * space prior to use with GpiBitBlt, etc.
- *
- * Concepts : Illustrates the use of GPI
- * Illustrates the use of off-screen bitmaps
- *
- * Entry Points:
- * CalcSize()
- * CheckMenu()
- * CheckPsl()
- * CreatePicture()
- * DispErrorMsg()
- * DoHorzScroll()
- * DosGetThreadInfo()
- * DoVertScroll()
- * DumpPicture()
- * EnableMenu()
- * NewThread()
- * Finalize()
- * Initialize()
- * Jumble()
- * LeftDown()
- * LeftUp()
- * Load()
- * main()
- * MouseMove()
- * PrepareBitmap()
- * ReadBitmap()
- * ReportError()
- * ResetScrollBars()
- * SegListCheck()
- * ToBottom()
- * Zoom()
- *
- * API's : GpiBeginPath
- * GpiEndPath
- * GpiFillPath
- * GpiSetClipPath
- * GpiSetClipRegion
- *
- * GpiCreateBitmap
- * GpiDeleteBitmap
- * GpiSetBitmap
- * GpiSetBitmapBits
- * GpiBitBlt
- *
- * GpiConvert
- *
- * GpiCreateRegion
- * GpiCombineRegion
- * GpiSetRegion
- * GpiDestroyRegion
- * GpiQueryRegionBox
- *
- * GpiSetAttrMode
- * GpiSetColor
- *
- * GpiQueryDefaultViewMatrix
- * GpiSetDefaultViewMatrix
- *
- * Copyright (C) 1992 IBM Corporation
- *
- * DISCLAIMER OF WARRANTIES. The following [enclosed] code is
- * sample code created by IBM Corporation. This sample code is not
- * part of any standard or IBM product and is provided to you solely
- * for the purpose of assisting you in the development of your
- * applications. The code is provided "AS IS", without
- * warranty of any kind. IBM shall not be liable for any damages
- * arising out of your use of the sample code, even if they have been
- * advised of the possibility of such damages. *
- *
- ******************************************************************************/
-
- #include "jigsaw.h"
- #include "globals.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- /******************************************************************************
- *
- * Name : main
- *
- * Description : Main thread will initialize the process for PM services and
- * process the application message queue until a WM_QUIT message
- * is received. It will then destroy all PM resources and
- * terminate. Any error during initialization will be reported
- * and the process terminated.
- *
- * Concepts :
- *
- * API's :
- *
- * Parameters : VOID
- *
- * Return :
- *
- ******************************************************************************/
-
- VOID main(VOID)
- {
- QMSG qmsg;
-
- if( Initialize())
- while( WinGetMsg( habMain, &qmsg, NULLHANDLE, 0, 0))
- WinDispatchMsg( habMain, &qmsg);
- else
- ReportError( habMain);
- Finalize();
-
- } /* end main() */
-
- /******************************************************************************
- *
- * Name : Initialize
- *
- * Description :
- *
- * The Initialize function will initialize the PM interface,
- * create an application message queue, a standard frame window and a new
- * thread to control drawing operations. It will also initialize static
- * strings.
- *
- * Concepts :
- *
- * API's :
- *
- * Parameters : VOID
- *
- * Return : BOOL
- *
- ******************************************************************************/
-
- BOOL Initialize(VOID)
- {
- ULONG flCreate;
- PID pid;
- TID tid;
-
- /*
- * create all semaphores for mutual exclusion and event timing
- */
- /* (anonomous, , private, reset) */
-
- if (DosCreateEventSem( NULL, &hevDrawOn, 0, FALSE) ||
- DosCreateEventSem( NULL, &hevMouse, 0, FALSE) ||
- DosCreateEventSem( NULL, &hevLoadingBitmap, 0, FALSE) ||
- DosCreateEventSem( NULL, &hevTerminate, 0, FALSE) ||
- DosCreateEventSem( NULL, &hevKillDraw, 0, FALSE))
- {
- return (FALSE); /* failed to create a semaphore */
- }
-
- WinShowPointer( HWND_DESKTOP, TRUE);
- habMain = WinInitialize( 0);
- if( !habMain)
- return( FALSE);
-
- hmqMain = WinCreateMsgQueue( habMain,0);
- if( !hmqMain)
- return( FALSE);
-
- WinLoadString( habMain, 0, IDS_TITLEBAR, sizeof(szTitle), szTitle);
- WinLoadString( habMain, 0, IDS_ERROR_TITLE, sizeof(szErrorTitle), szErrorTitle);
- if( !WinRegisterClass( habMain
- , (PCH)szTitle
- , ClientWndProc
- , CS_SIZEREDRAW
- , 0 ))
- return( FALSE);
-
- flCreate = (FCF_STANDARD | FCF_VERTSCROLL | FCF_HORZSCROLL)
- & ~(ULONG)FCF_TASKLIST;
- hwndFrame =
- WinCreateStdWindow(
- HWND_DESKTOP, /* handle of the parent window */
- WS_VISIBLE, /* frame-window style */
- &flCreate, /* creation flags */
- szTitle, /* client-window class name */
- szTitle, /* address of title-bar text */
- WS_VISIBLE, /* client-window style */
- 0, /* handle of the resource module */
- IDR_MAIN, /* frame-window identifier */
- &hwndClient); /* address of client-window handle */
-
- if( !hwndFrame)
- return( FALSE);
-
- sizlMaxClient.cx = WinQuerySysValue( HWND_DESKTOP, SV_CXFULLSCREEN);
- sizlMaxClient.cy = WinQuerySysValue( HWND_DESKTOP, SV_CYFULLSCREEN);
-
- lByteAlignX = WinQuerySysValue( HWND_DESKTOP, SV_CXBYTEALIGN);
- lByteAlignY = WinQuerySysValue( HWND_DESKTOP, SV_CYBYTEALIGN);
-
- hdcClient = WinOpenWindowDC( hwndClient);
- hpsClient = GpiCreatePS( habMain
- , hdcClient
- , &sizlMaxClient
- , GPIA_ASSOC | PU_PELS );
- if( !hpsClient)
- {
- DispError(habMain,hwndClient);
- return( TRUE);
- }
- if (GpiSetAttrMode( hpsClient, AM_PRESERVE) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- hwndHorzScroll = WinWindowFromID( hwndFrame, FID_HORZSCROLL);
-
- hwndVertScroll = WinWindowFromID( hwndFrame, FID_VERTSCROLL);
-
- if ((hpsPaint = GpiCreatePS( habMain, NULLHANDLE, &sizlMaxClient, PU_PELS)) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- hrgnInvalid = GpiCreateRegion( hpsClient, 0L, NULL);
-
- WinQueryWindowProcess( hwndFrame, &pid, &tid);
- swctl.hwnd = hwndFrame;
- swctl.idProcess = pid;
- strcpy( swctl.szSwtitle, szTitle);
- hsw = WinAddSwitchEntry( &swctl);
-
- hwndMenu = WinWindowFromID( hwndFrame, FID_MENU);
-
- if(DosCreateThread(&tidAsync,
- (PFNTHREAD) NewThread,
- 0,
- 0,
- STACKSIZE )) {
- return( FALSE);
- } /* create async thread */
- if( !CreateBitmapHdcHps( &hdcBitmapFile, &hpsBitmapFile))
- return( FALSE);
- if( !CreateBitmapHdcHps( &hdcBitmapSize, &hpsBitmapSize))
- return( FALSE);
- if( !CreateBitmapHdcHps( &hdcBitmapBuff, &hpsBitmapBuff))
- return( FALSE);
- if( !CreateBitmapHdcHps( &hdcBitmapSave, &hpsBitmapSave))
- return( FALSE);
-
- ResetScrollBars();
- /*
- * initialise help mechanism
- */
-
- HelpInit();
- return( TRUE);
-
- } /* end Initialize() */
-
- /******************************************************************************
- *
- * Name : Finalize
- *
- * Description :
- *
- * Finalize will destroy the asynchronous drawing thread, all Presentation
- * Manager resources, and terminate the process.
- *
- * Concepts :
- *
- * API's :
- *
- * Parameters : VOID
- *
- * Return : VOID
- *
- ******************************************************************************/
-
- VOID Finalize(VOID)
- {
- ULONG ulPostCt;
-
- if( tidAsync)
- {
- DosResetEventSem( hevDrawOn, &ulPostCt);
- DosPostEventSem( hevKillDraw);
- DosPostEventSem( hevTerminate);
- SendCommand( UM_DIE, (MPARAM)NULL, (MPARAM)NULL);
- }
-
- while( pslHead != NULL )
- {
- if (GpiSetBitmap( pslHead->hpsFill, NULLHANDLE) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDeleteBitmap( pslHead->hbmFill) == GPI_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDestroyPS( pslHead->hpsFill) == GPI_ERROR)
- DispError(habMain,hwndClient);
- DevCloseDC( pslHead->hdcFill);
-
- if (GpiSetBitmap( pslHead->hpsHole, NULLHANDLE)== (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDeleteBitmap( pslHead->hbmHole) == GPI_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDestroyPS( pslHead->hpsHole) == GPI_ERROR)
- DispError(habMain,hwndClient);
- DevCloseDC( pslHead->hdcHole);
-
- SegListUpdate( DEL_SEG, pslHead);
- }
-
- if( hrgnInvalid)
- GpiDestroyRegion( hpsClient, hrgnInvalid);
- if( hpsClient)
- {
- GpiAssociate( hpsClient, NULLHANDLE);
- GpiDestroyPS( hpsClient);
- }
- if( hpsPaint)
- GpiDestroyPS( hpsPaint);
-
- if( hpsBitmapFile)
- {
- GpiSetBitmap( hpsBitmapFile, NULLHANDLE);
- GpiDeleteBitmap( hbmBitmapFile);
- GpiDestroyPS( hpsBitmapFile);
- DevCloseDC( hdcBitmapFile);
- }
- if( hpsBitmapSize)
- {
- GpiSetBitmap( hpsBitmapSize, NULLHANDLE);
- GpiDeleteBitmap( hbmBitmapSize);
- GpiDestroyPS( hpsBitmapSize);
- DevCloseDC( hdcBitmapSize);
- }
- if( hpsBitmapBuff)
- {
- GpiSetBitmap( hpsBitmapBuff, NULLHANDLE);
- GpiDeleteBitmap( hbmBitmapBuff);
- GpiDestroyPS( hpsBitmapBuff);
- DevCloseDC( hdcBitmapBuff);
- }
- if( hpsBitmapSave)
- {
- GpiSetBitmap( hpsBitmapSave, NULLHANDLE);
- GpiDeleteBitmap( hbmBitmapSave);
- GpiDestroyPS( hpsBitmapSave);
- DevCloseDC( hdcBitmapSave);
- }
-
- DestroyHelpInstance();
-
- if( hwndFrame)
- WinDestroyWindow( hwndFrame);
- if( hmqMain)
- WinDestroyMsgQueue( hmqMain);
- if( habMain)
- WinTerminate( habMain);
-
- DosExit( EXIT_PROCESS, 0);
-
- } /* end Finalize() */
-
- /******************************************************************************
- *
- * Name : ReportError
- *
- * Description :
- *
- * ReportError will display the latest error information for the required
- * thread. No resources to be loaded if out of memory error.
- *
- * Concepts :
- *
- * API's :
- *
- * Parameters : HAB hab
- *
- * Return : VOID
- *
- ******************************************************************************/
-
- VOID ReportError(HAB hab)
- {
- PERRINFO perriBlk;
- PSZ pszErrMsg;
- PSZ pszOffSet;
-
- if (!fErrMem){
- if ((perriBlk = WinGetErrorInfo(hab)) != (PERRINFO)NULL){
- pszOffSet = ((PSZ)perriBlk) + perriBlk->offaoffszMsg;
- pszErrMsg = ((PSZ)perriBlk) + *((PULONG)pszOffSet);
- WinMessageBox(HWND_DESKTOP,
- hwndFrame,
- (PSZ)(pszErrMsg),
- (PSZ)szTitle,
- 0,
- MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL );
- WinFreeErrorInfo(perriBlk);
- return;
- }
- } /* endif */
-
- MessageBox( /* ERROR */
- hwndFrame,
- IDS_ERROR_OUTOFMEMORY,
- MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL,
- TRUE);
-
- } /* end ReportError() */
-
- /******************************************************************************
- *
- * Name : ResetScrollBars
- *
- * Description :
- *
- * Reset the scroll bars to be in the middle of their range
- *
- * Concepts :
- *
- * API's :
- *
- * Parameters : VOID
- *
- * Return : VOID
- *
- ******************************************************************************/
-
- VOID ResetScrollBars(VOID)
- {
- RECTL rclClient;
-
- WinQueryWindowRect( hwndClient, &rclClient);
- ptsScrollMax.x = (SHORT)(rclClient.xRight - rclClient.xLeft);
- ptsHalfScrollMax.x = ptsScrollMax.x >> 1;
- ptsScrollPage.x = ptsScrollMax.x >> 3;
- ROUND_DOWN_MOD( ptsScrollPage.x, (SHORT)lByteAlignX);
- ptsScrollLine.x = ptsScrollMax.x >> 5;
- ROUND_DOWN_MOD( ptsScrollLine.x, (SHORT)lByteAlignX);
- ptsScrollPos.x = ptsHalfScrollMax.x;
- ptsOldScrollPos.x = ptsHalfScrollMax.x;
- WinSendMsg( hwndHorzScroll
- , SBM_SETSCROLLBAR
- , MPFROMSHORT( ptsScrollPos.x)
- , MPFROM2SHORT( 1, ptsScrollMax.x) );
-
- ptsScrollMax.y = (SHORT)(rclClient.yTop - rclClient.yBottom);
- ptsHalfScrollMax.y = ptsScrollMax.y >> 1;
- ptsScrollPage.y = ptsScrollMax.y >> 3;
- ROUND_DOWN_MOD( ptsScrollPage.y, (SHORT)lByteAlignY);
- ptsScrollLine.y = ptsScrollMax.y >> 5;
- ROUND_DOWN_MOD( ptsScrollLine.y, (SHORT)lByteAlignY);
- ptsScrollPos.y = ptsHalfScrollMax.y;
- ptsOldScrollPos.y = ptsHalfScrollMax.y;
- WinSendMsg( hwndVertScroll
- , SBM_SETSCROLLBAR
- , MPFROMSHORT( ptsScrollPos.y)
- , MPFROM2SHORT( 1, ptsScrollMax.y) );
-
- WinSendMsg( hwndHorzScroll
- , SBM_SETTHUMBSIZE
- , MPFROM2SHORT(ptsScrollPage.x, ptsScrollMax.x)
- , 0 );
-
- WinSendMsg( hwndVertScroll
- , SBM_SETTHUMBSIZE
- , MPFROM2SHORT(ptsScrollPage.y, ptsScrollMax.y)
- , NULL );
-
- } /* end ResetScrollBars() */
-
- /******************************************************************************
- *
- * Name : Load
- *
- * Description : Load a bitmap
- *
- * Parameters : PLOADINFO pli - pointer to file information (name, handle...)
- *
- * Return : VOID
- *
- ******************************************************************************/
-
- VOID Load(PLOADINFO pli)
- {
- ULONG ulPostCt;
- PUCHAR pFilename;
- UCHAR szWindowText[CCHMAXPATH];
-
- DosResetEventSem( hevLoadingBitmap, &ulPostCt); /* begin loading bitmap */
-
- /*
- * Disable bitmap manipulation submenus
- */
-
- EnableMenu(IDM_SIZE_MENU, FALSE);
- EnableMenu(IDM_SIZE_SMALL, FALSE);
- EnableMenu(IDM_SIZE_MEDIUM, FALSE);
- EnableMenu(IDM_SIZE_LARGE, FALSE);
- EnableMenu(IDM_SIZE_FULL, FALSE);
- EnableMenu(IDM_JUMBLE, FALSE);
-
- CheckMenu(Currentchecked, FALSE); /* uncheck old menu */
-
- if( hbmBitmapFile)
- {
- if (GpiSetBitmap( hpsBitmapFile, NULLHANDLE) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDeleteBitmap( hbmBitmapFile) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
-
- if (!ReadBitmap( pli->hf))
- {
- MessageBox(hwndClient, IDS_ERROR_READ, MB_OK | MB_ERROR, TRUE);
- DosPostEventSem( hevLoadingBitmap); /* end loading bitmap */
- if (!fFirstLoad)
- {
- /*
- * Re-Enable bitmap manipulation submenus
- */
-
- EnableMenu(IDM_SIZE_MENU, TRUE);
- EnableMenu(IDM_SIZE_SMALL, TRUE);
- EnableMenu(IDM_SIZE_MEDIUM, TRUE);
- EnableMenu(IDM_SIZE_LARGE, TRUE);
- EnableMenu(IDM_SIZE_FULL, TRUE);
- EnableMenu(IDM_JUMBLE, TRUE);
-
- CheckMenu(Currentchecked, TRUE); /* recheck old menu */
-
- } /* end if (!fFirstLoad) */
-
- return;
- }
-
- /*
- * Change Title Bar text and Window List text to include filename.
- */
-
- strcpy(swctl.szSwtitle, szTitle);
- strcat(swctl.szSwtitle, " - ");
- strcpy(szWindowText, swctl.szSwtitle); /* save duplicate part */
- pFilename = strrchr(pli->szFileName, '\\'); /* contain pathname? */
-
- if (pFilename == NULL)
- pFilename = pli->szFileName; /* filename doesn't contain path */
- else
- ++pFilename; /* point past last back-slash */
- strcat( swctl.szSwtitle, pFilename);
- WinChangeSwitchEntry( hsw, &swctl);
-
- strcat(szWindowText, pli->szFileName); /* use full filename in window */
- WinSetWindowText( hwndFrame, szWindowText);
- ResetScrollBars();
-
- if (fFirstLoad ||
- (PBMP1(pbmp2BitmapFile)->cx > PBMP1(pbmp2BitmapFileRef)->cx ||
- PBMP1(pbmp2BitmapFile)->cy > PBMP1(pbmp2BitmapFileRef)->cy ||
- PBMP1(pbmp2BitmapFile)->cPlanes != PBMP1(pbmp2BitmapFileRef)->cPlanes ||
- PBMP1(pbmp2BitmapFile)->cBitCount != PBMP1(pbmp2BitmapFileRef)->cBitCount))
- {
- if( !fFirstLoad)
- DumpPicture();
- if( !PrepareBitmap() )
- {
- MessageBox(hwndClient, IDS_ERROR_READ, MB_OK | MB_ERROR, TRUE);
- DosPostEventSem( hevLoadingBitmap); /* end loading bitmap */
- if (!fFirstLoad)
- {
- /*
- * Re-Enable bitmap manipulation submenus
- */
-
- EnableMenu(IDM_SIZE_MENU, TRUE);
- EnableMenu(IDM_SIZE_SMALL, TRUE);
- EnableMenu(IDM_SIZE_MEDIUM, TRUE);
- EnableMenu(IDM_SIZE_LARGE, TRUE);
- EnableMenu(IDM_SIZE_FULL, TRUE);
- EnableMenu(IDM_JUMBLE, TRUE);
-
- CheckMenu(Currentchecked, TRUE); /* recheck old menu */
-
- } /* end if (!fFirstLoad) */
-
- return;
- }
- CreatePicture( PICTURE_CREATE);
- bmp2BitmapFileRef = bmp2BitmapFile;
- } else
- {
- CreatePicture( PICTURE_UPDATE);
- }
-
- lScale = 0;
-
- CalcBounds();
- ptlScaleRef.x = ptlScaleRef.y = 0L;
- CalcTransform( hwndClient);
-
- DosPostEventSem( hevLoadingBitmap); /* end loading bitmap */
-
- fFirstLoad = FALSE;
- fPictureAssembled = TRUE;
- BmpLoaded = TRUE;
-
- /*
- * Enable bitmap manipulation submenus
- */
- EnableMenu(IDM_SIZE_MENU, TRUE);
- EnableMenu(IDM_SIZE_SMALL, TRUE);
- EnableMenu(IDM_SIZE_MEDIUM, TRUE);
- EnableMenu(IDM_SIZE_LARGE, TRUE);
- EnableMenu(IDM_SIZE_FULL, TRUE);
- EnableMenu(IDM_JUMBLE, TRUE);
-
- CheckMenu(IDM_SIZE_FULL, TRUE); /* check full size */
- Currentchecked = IDM_SIZE_FULL;
-
- } /* end Load() */
-
- /******************************************************************************/
- /* Throw the pieces around the screen. */
- /******************************************************************************/
- VOID Jumble(VOID)
- {
- LONG lWidth, lHeight;
- DATETIME date;
- POINTL ptl;
- RECTL rclClient;
- PSEGLIST psl;
-
- if( WinQueryWindowRect( hwndClient, &rclClient) )
- {
- lWidth = rclClient.xRight - rclClient.xLeft;
- lHeight = rclClient.yTop - rclClient.yBottom;
- if( (lWidth > 0) && (lHeight > 0) )
- {
- DosGetDateTime( &date);
- srand( (USHORT)date.hundredths);
- for( psl = pslHead; psl != NULL; psl = psl->pslNext)
- {
- psl->pslNextIsland = psl; /* reset island pointer */
- psl->fIslandMark = FALSE; /* clear island mark */
- ptl.x = rclClient.xLeft + (rand() % lWidth);
- ptl.y = rclClient.yBottom + (rand() % lHeight);
- if (GpiConvert( hpsClient, CVTC_DEVICE, CVTC_MODEL, 1L, &ptl) == GPI_ERROR)
- DispError(habMain,hwndClient);
- ptl.x = 50 * (ptl.x / 50) - 250;
- ptl.y = 50 * (ptl.y / 50) - 250;
- psl->ptlModelXlate.x = ptl.x - psl->ptlLocation.x;
- psl->ptlModelXlate.y = ptl.y - psl->ptlLocation.y;
- SetRect( psl);
- }
- }
- fPictureAssembled = FALSE;
- }
- }
-
- /******************************************************************************/
- /* */
- /* */
- /* */
- /******************************************************************************/
- VOID ToBottom( pslDown)
- PSEGLIST pslDown;
- {
- BOOL fFirst;
- PSEGLIST psl;
-
- for( psl = pslDown, fFirst = TRUE
- ; (psl != pslDown) || fFirst
- ; psl = psl->pslNextIsland, fFirst = FALSE )
- SegListUpdate( MAKE_HEAD_SEG, psl); /* at head => lowest priority */
- }
-
-
- /******************************************************************************/
- /* */
- /* NewThread is the asynchronous drawing thread. It is responsible for all */
- /* drawing. It will initialize its PM interface and create an application */
- /* message queue. It will then monitor its message queue and process any */
- /* commands received. */
- /* */
- /******************************************************************************/
- VOID NewThread(VOID)
- {
- QMSG qmsgAsync, qmsgPeek;
- BOOL fDone;
- POINTL aptlDraw[3];
- USHORT usChar, fsKeyFlags;
- PSEGLIST psl;
- ULONG ulPostCt;
-
- /****************************************************************************/
- /* Initialize the PM interface. If it fails, terminate both threads. */
- /****************************************************************************/
- habAsync = WinInitialize( 0);
- if( !habAsync)
- {
- WinPostMsg( hwndClient, WM_QUIT, NULL, NULL);
- DosExit( EXIT_THREAD, 0);
- }
-
- /****************************************************************************/
- /* Create a message queue. If it fails, terminate both threads. */
- /****************************************************************************/
- hmqAsync = WinCreateMsgQueue( habAsync, 150);
- if( !hmqAsync)
- {
- WinPostMsg( hwndClient, WM_QUIT, NULL, NULL);
- WinTerminate( habAsync);
- DosExit( EXIT_THREAD, 0);
- }
- else
- {
- WinCancelShutdown( hmqAsync, TRUE); /* don't wait around for shutdown */
- }
-
- DosSetPriority( PRTYS_THREAD, PRTYC_NOCHANGE, sPrty, (TID)NULL);
-
-
- while( TRUE)
- {
- WinGetMsg( habAsync, &qmsgAsync, NULLHANDLE, 0, 0);
-
- /*
- * If we're exiting, give that message highest priority.
- */
-
- if( WinPeekMsg(habAsync, &qmsgPeek, NULLHANDLE, UM_DIE, UM_DIE, PM_NOREMOVE))
- qmsgAsync = qmsgPeek;
- /*
- * Disallow drawing and mouse tracking as needed
- */
-
- if( (qmsgAsync.msg < UM_SIZING) || (qmsgAsync.msg > UM_LOAD))
- DosPostEventSem( hevMouse); /* enable mouse tracking */
- else
- DosResetEventSem( hevMouse, &ulPostCt); /* disable mouse tracking */
-
- if( WinPeekMsg( habAsync, &qmsgPeek, NULLHANDLE, UM_SIZING, UM_LOAD, PM_NOREMOVE))
- {
- DosResetEventSem( hevDrawOn, &ulPostCt); /* disable drawing */
- DosResetEventSem( hevMouse, &ulPostCt); /* disable mouse tracking */
- }
- else
- {
- DosPostEventSem( hevDrawOn); /* enable drawing */
- DosPostEventSem( hevMouse); /* enable mouse tracking */
- }
-
- /**************************************************************************/
- /* process the commands */
- /**************************************************************************/
-
- switch( qmsgAsync.msg)
- {
- /************************************************************************/
- case UM_CHAR:
- fsKeyFlags = (USHORT)SHORT1FROMMP(qmsgAsync.mp1);
- usChar = (USHORT)SHORT1FROMMP(qmsgAsync.mp2);
- if( (fsKeyFlags & KC_CHAR)
- && ((usChar == 'b') || (usChar == 'B')))
- {
- if( psl = Correlate( &ptlMouse))
- {
- ToBottom( psl);
- Redraw();
- }
- }
- break;
-
- /************************************************************************/
- case UM_LOAD:
- Load( (PLOADINFO)qmsgAsync.mp1);
- Redraw();
- break;
-
- /************************************************************************/
- case UM_JUMBLE:
- Jumble();
- Redraw();
- break;
-
- /************************************************************************/
- case UM_REDRAW:
- Redraw();
- break;
-
- /************************************************************************/
- /* DRAW will use the passed region containing the invalidated area of */
- /* the screen, repaint it and then destroy the region. */
- /************************************************************************/
- case UM_DRAW:
-
- if (!BmpLoaded)
- break;
- if( qmsgAsync.mp1)
- {
- DoDraw( hpsBitmapBuff, (HRGN)qmsgAsync.mp1, TRUE);
- if (GpiQueryRegionBox( hpsClient, (HRGN)qmsgAsync.mp1, (PRECTL)aptlDraw) == RGN_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDestroyRegion( hpsClient, (HRGN)qmsgAsync.mp1) == GPI_ERROR)
- DispError(habMain,hwndClient);
- WinMapWindowPoints( hwndClient, HWND_DESKTOP, aptlDraw, 3);
- ROUND_DOWN_MOD( aptlDraw[0].x, lByteAlignX); /* round down */
- ROUND_DOWN_MOD( aptlDraw[0].y, lByteAlignY); /* round down */
- ROUND_UP_MOD( aptlDraw[1].x, lByteAlignX); /* round up */
- ROUND_UP_MOD( aptlDraw[1].y, lByteAlignY); /* round up */
- WinMapWindowPoints( HWND_DESKTOP, hwndClient, aptlDraw, 3);
- aptlDraw[2] = aptlDraw[0];
- if (GpiBitBlt( hpsClient
- , hpsBitmapBuff
- , 3L
- , aptlDraw
- , ROP_SRCCOPY
- , BBO_IGNORE ) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
- break;
-
-
- /************************************************************************/
- /* Get new scroll posn from command ( i.e. +/-1 +/-page) or new */
- /* absolute position from parameter, update scroll posn, change the */
- /* transform and update the thumb posn. Finally update the window. */
- /************************************************************************/
- case UM_HSCROLL:
- switch( SHORT2FROMMP( qmsgAsync.mp1) )
- {
- case SB_LINEUP:
- ptsScrollPos.x -= ptsScrollLine.x;
- break;
- case SB_LINEDOWN:
- ptsScrollPos.x += ptsScrollLine.x;
- break;
- case SB_SLIDERTRACK:
- case SB_SLIDERPOSITION:
- for( fDone = FALSE; !fDone ;)
- {
- if( WinPeekMsg( habAsync
- , &qmsgPeek
- , NULLHANDLE
- , UM_HSCROLL
- , UM_HSCROLL
- , PM_NOREMOVE))
- if( (SHORT2FROMMP( qmsgPeek.mp1) == SB_SLIDERTRACK)
- ||(SHORT2FROMMP( qmsgPeek.mp1) == SB_SLIDERPOSITION))
- WinPeekMsg( habAsync
- , &qmsgAsync
- , NULLHANDLE
- , UM_HSCROLL
- , UM_HSCROLL
- , PM_REMOVE);
- else
- fDone = TRUE;
- else
- fDone = TRUE;
- }
- ptsScrollPos.x = SHORT1FROMMP( qmsgAsync.mp1);
- ROUND_DOWN_MOD( ptsScrollPos.x, (SHORT)lByteAlignX);
- break;
- case SB_PAGEUP:
- ptsScrollPos.x -= ptsScrollPage.x;
- break;
- case SB_PAGEDOWN:
- ptsScrollPos.x += ptsScrollPage.x;
- break;
- case SB_ENDSCROLL:
- break;
- default:
- break;
- }
- DoHorzScroll();
- break;
-
- case UM_VSCROLL:
- switch( SHORT2FROMMP( qmsgAsync.mp1) )
- {
- case SB_LINEUP:
- ptsScrollPos.y -= ptsScrollLine.y;
- break;
- case SB_LINEDOWN:
- ptsScrollPos.y += ptsScrollLine.y;
- break;
- case SB_SLIDERTRACK:
- case SB_SLIDERPOSITION:
- for( fDone = FALSE; !fDone ;)
- {
- if( WinPeekMsg( habAsync
- , &qmsgPeek
- , NULLHANDLE
- , UM_VSCROLL
- , UM_VSCROLL
- , PM_NOREMOVE))
- if( (SHORT2FROMMP( qmsgPeek.mp1) == SB_SLIDERTRACK)
- ||(SHORT2FROMMP( qmsgPeek.mp1) == SB_SLIDERPOSITION))
- WinPeekMsg( habAsync
- , &qmsgAsync
- , NULLHANDLE
- , UM_VSCROLL
- , UM_VSCROLL
- , PM_REMOVE);
- else
- fDone = TRUE;
- else
- fDone = TRUE;
- }
- ptsScrollPos.y = SHORT1FROMMP( qmsgAsync.mp1);
- ROUND_DOWN_MOD( ptsScrollPos.y, (SHORT)lByteAlignY);
- break;
- case SB_PAGEUP:
- ptsScrollPos.y -= ptsScrollPage.y;
- break;
- case SB_PAGEDOWN:
- ptsScrollPos.y += ptsScrollPage.y;
- break;
- case SB_ENDSCROLL:
- break;
- default:
- break;
- }
- DoVertScroll();
- break;
-
- /************************************************************************/
- /* the window is being resized */
- /************************************************************************/
- case UM_SIZING:
- CalcBounds();
- CalcTransform( hwndClient);
- break;
-
- /************************************************************************/
- /* adjust zoom factor */
- /************************************************************************/
- case UM_ZOOM:
- if( WinPeekMsg( habAsync
- , &qmsgPeek
- , NULLHANDLE
- , UM_SIZING
- , UM_LOAD
- , PM_NOREMOVE))
- DosResetEventSem( hevDrawOn, &ulPostCt);
- else {
- DosPostEventSem( hevDrawOn);
- }
-
- Zoom();
- break;
-
- /************************************************************************/
- /* Button down will cause a correlate on the picture to test for a hit. */
- /* Any selected segment will be highlighted and redrawn as dynamic. */
- /************************************************************************/
- case UM_LEFTDOWN:
- if( !fButtonDownAsync)
- {
- fButtonDownAsync = TRUE;
- if(!fPictureAssembled)
- LeftDown( qmsgAsync.mp1);
- }
- break;
-
- /************************************************************************/
- /* if a segment is being dragged it will be redrawn in a new posn */
- /************************************************************************/
- case UM_MOUSEMOVE:
- #ifdef fred
- if( !fButtonDownAsync)
- break;
- #endif
- for( fDone = FALSE; !fDone ;)
- {
- if( WinPeekMsg( habAsync /* look through first button-up */
- , &qmsgPeek
- , NULLHANDLE
- , UM_MOUSEMOVE
- , UM_LEFTUP
- , PM_NOREMOVE))
- if( qmsgPeek.msg == UM_MOUSEMOVE) /* only collapse move msgs */
- WinPeekMsg( habAsync
- , &qmsgAsync
- , NULLHANDLE
- , UM_MOUSEMOVE
- , UM_MOUSEMOVE
- , PM_REMOVE);
- else
- fDone = TRUE;
- else
- fDone = TRUE;
- }
- MouseMove( qmsgAsync.mp1); /* process last move before button-up */
- break;
-
- /************************************************************************/
- /* if a segment is being dragged it will be redrawn as normal */
- /************************************************************************/
- case UM_LEFTUP:
- if( fButtonDownAsync)
- {
- LeftUp();
- fButtonDownAsync = FALSE;
- }
- break;
-
- /************************************************************************/
- /* destroy resources and terminate */
- /************************************************************************/
- case UM_DIE:
- WinDestroyMsgQueue( hmqAsync);
- WinTerminate( habAsync);
- DosExit( EXIT_THREAD, 0);
- break;
-
- /************************************************************************/
- default:
- break;
- }
- }
- }
-
- /******************************************************************************/
- /* */
- /******************************************************************************/
- VOID CalcSize( mp1, mp2)
- MPARAM mp1;
- MPARAM mp2;
- {
- ptsScrollMax.y = SHORT2FROMMP( mp2);
- ptsHalfScrollMax.y = ptsScrollMax.y >> 1;
- ptsScrollPage.x = ptsScrollMax.x >> 3;
- ROUND_DOWN_MOD( ptsScrollPage.x, (SHORT)lByteAlignX);
- ptsScrollLine.x = ptsScrollMax.x >> 5;
- ROUND_DOWN_MOD( ptsScrollLine.x, (SHORT)lByteAlignX);
- ptsScrollPos.y = (SHORT)(
- ( (LONG)ptsScrollPos.y
- * (LONG)SHORT2FROMMP(mp2)
- )/ (LONG)SHORT2FROMMP(mp1)
- );
- ptsOldScrollPos.y = (SHORT)(
- ( (LONG)ptsOldScrollPos.y
- * (LONG)SHORT2FROMMP(mp2)
- )/ (LONG)SHORT2FROMMP(mp1)
- );
- WinSendMsg( hwndVertScroll
- , SBM_SETSCROLLBAR
- , MPFROMSHORT( ptsScrollPos.y)
- , MPFROM2SHORT( 1, ptsScrollMax.y) );
-
- ptsScrollMax.x = SHORT1FROMMP( mp2);
- ptsHalfScrollMax.x = ptsScrollMax.x >> 1;
- ptsScrollPage.y = ptsScrollMax.y >> 3;
- ROUND_DOWN_MOD( ptsScrollPage.y, (SHORT)lByteAlignY);
- ptsScrollLine.y = ptsScrollMax.y >> 5;
- ROUND_DOWN_MOD( ptsScrollLine.y, (SHORT)lByteAlignY);
- ptsScrollPos.x = (SHORT)(
- ( (LONG)ptsScrollPos.x
- * (LONG)SHORT1FROMMP(mp2)
- )/(LONG)SHORT1FROMMP(mp1)
- );
- ptsOldScrollPos.x = (SHORT)(
- ( (LONG)ptsOldScrollPos.x
- * (LONG)SHORT1FROMMP(mp2)
- )/ (LONG)SHORT1FROMMP(mp1)
- );
- WinSendMsg( hwndHorzScroll
- , SBM_SETSCROLLBAR
- , MPFROMSHORT( ptsScrollPos.x)
- , MPFROM2SHORT( 1, ptsScrollMax.x) );
- WinSendMsg( hwndHorzScroll
- , SBM_SETTHUMBSIZE
- , MPFROM2SHORT(ptsScrollPage.x, ptsScrollMax.x)
- , NULL );
-
- WinSendMsg( hwndVertScroll
- , SBM_SETTHUMBSIZE
- , MPFROM2SHORT(ptsScrollPage.y, ptsScrollMax.y)
- , NULL );
-
- }
-
- /******************************************************************************/
- /* button down will cause one segment to be indicated and made dynamic */
- /******************************************************************************/
- VOID LeftDown(MPARAM mp)
- {
- POINTL ptl;
- HRGN hrgn, hrgnUpdt, hrgnUpdtDrag;
- RECTL rcl;
- BOOL fFirst;
- PSEGLIST psl;
-
- ptl.x = (LONG)(SHORT)SHORT1FROMMP( mp);
- ptl.y = (LONG)(SHORT)SHORT2FROMMP( mp);
-
- /****************************************************************************/
- pslPicked = Correlate( &ptl);
- if( pslPicked)
- lPickedSeg = pslPicked->lSegId;
- else
- {
- fButtonDownAsync = FALSE;
- return;
- }
- if( (lPickedSeg < 1) || (lPickedSeg > lLastSegId) )
- {
- #if defined(DEBUG)
- {
- CHAR szMsg[40];
-
- sprintf( szMsg, "Segment id out of range: %x", lPickedSeg);
- WinMessageBox(HWND_DESKTOP, hwndFrame, szMsg, szErrorTitle, 0,
- MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
- }
- #endif
-
- fButtonDownAsync = FALSE;
- return;
- }
-
- /****************************************************************************/
- ptlOffStart = pslPicked->ptlModelXlate;
- ptlMoveStart = ptl;
- if (GpiConvert( hpsClient, CVTC_DEVICE, CVTC_MODEL, 1L, &ptlMoveStart) == GPI_ERROR)
- DispError(habMain,hwndClient);
- ptlMoveStart.x = (ptlMoveStart.x / 50) * 50;
- ptlMoveStart.y = (ptlMoveStart.y / 50) * 50;
- ptlUpdtRef = ptlMoveStart;
- if (GpiConvert( hpsClient, CVTC_MODEL, CVTC_DEVICE, 1L, &ptlUpdtRef) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- /****************************************************************************/
- hrgnUpdt = GpiCreateRegion( hpsClient, 0L, NULL);
- for( psl = pslPicked, fFirst = TRUE
- ; (psl != pslPicked) || fFirst
- ; psl = psl->pslNextIsland, fFirst = FALSE )
- {
- rcl = psl->rclCurrent; /* get model space bounding box of piece */
- if (GpiConvert( hpsClient, CVTC_MODEL, CVTC_DEVICE, 2L, (PPOINTL)&rcl) == GPI_ERROR)
- DispError(habMain,hwndClient);
- rcl.xRight++; /* adjust rectangle for conversion to dev space */
- rcl.yTop++;
- rcl.xRight += 2; /* should not need */
- rcl.yTop += 2; /* should not need */
- rcl.xLeft -= 4; /* should not need */
- rcl.yBottom -= 4; /* should not need */
- hrgn = GpiCreateRegion( hpsClient, 1L, &rcl);
- if (GpiCombineRegion( hpsClient, hrgnUpdt, hrgnUpdt, hrgn, CRGN_OR) == RGN_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDestroyRegion( hpsClient, hrgn) == GPI_ERROR)
- DispError(habMain,hwndClient);
- psl->fVisible = FALSE;
- }
-
- if (GpiQueryRegionBox( hpsClient, hrgnUpdt, (PRECTL)aptlUpdt) == GPI_ERROR)
- DispError(habMain,hwndClient);
- WinMapWindowPoints( hwndClient, HWND_DESKTOP, aptlUpdt, 3);
- ROUND_DOWN_MOD( aptlUpdt[0].x, lByteAlignX); /* round down */
- ROUND_DOWN_MOD( aptlUpdt[0].y, lByteAlignY); /* round down */
- ROUND_UP_MOD( aptlUpdt[1].x, lByteAlignX); /* round up */
- ROUND_UP_MOD( aptlUpdt[1].y, lByteAlignY); /* round up */
- WinMapWindowPoints( HWND_DESKTOP, hwndClient, aptlUpdt, 3);
- hrgnUpdtDrag = GpiCreateRegion( hpsBitmapBuff, 1L, (PRECTL)aptlUpdt);
-
- aptlUpdt[2] = aptlUpdt[0];
- DoDraw( hpsBitmapBuff, hrgnUpdtDrag, TRUE);
- if (GpiDestroyRegion( hpsClient, hrgnUpdt) == GPI_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDestroyRegion( hpsBitmapBuff, hrgnUpdtDrag) == GPI_ERROR)
- DispError(habMain,hwndClient);
- if (GpiBitBlt( hpsBitmapSave
- , hpsBitmapBuff
- , 3L
- , aptlUpdt
- , ROP_SRCCOPY
- , BBO_IGNORE ) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- /****************************************************************************/
- for( psl = pslPicked, fFirst = TRUE
- ; (psl != pslPicked) || fFirst
- ; psl = psl->pslNextIsland, fFirst = FALSE )
- {
- psl->fVisible = TRUE;
- DrawPiece( hpsBitmapBuff, psl, TRUE);
- }
- if (GpiBitBlt( hpsClient
- , hpsBitmapBuff
- , 3L
- , aptlUpdt
- , ROP_SRCCOPY
- , BBO_IGNORE ) == GPI_ERROR)
- DispError(habMain,hwndClient);
- WinSetCapture( HWND_DESKTOP, hwndClient);
- }
-
-
-
-
- /******************************************************************************/
- /* */
- /* move the segment */
- /* */
- /******************************************************************************/
- VOID MouseMove( mp)
- MPARAM mp;
- {
- RECTL rcl;
- POINTL ptl, ptlModel, ptlDevice;
- POINTL aptlUpdtRef[3], aptlUpdtNew[3];
- PSEGLIST psl;
- BOOL fFirst;
-
- ptl.x = (LONG)(SHORT)SHORT1FROMMP( mp);
- ptl.y = (LONG)(SHORT)SHORT2FROMMP( mp);
-
- /****************************************************************************/
- /* clip mouse coords to client window */
- /****************************************************************************/
- WinQueryWindowRect( hwndClient, &rcl);
- if (rcl.xLeft > ptl.x)
- ptl.x = rcl.xLeft;
- if (rcl.xRight <= ptl.x)
- ptl.x = rcl.xRight;
- if (rcl.yBottom > ptl.y)
- ptl.y = rcl.yBottom;
- if (rcl.yTop <= ptl.y)
- ptl.y = rcl.yTop;
- ptlMouse = ptl;
-
- if( !lPickedSeg || !pslPicked || !fButtonDownAsync)
- return;
-
- ptlModel = ptl;
- if (GpiConvert( hpsClient, CVTC_DEVICE, CVTC_MODEL, 1L, &ptlModel) == GPI_ERROR)
- DispError(habMain,hwndClient);
- ptlModel.x = 50 * (ptlModel.x / 50);
- ptlModel.y = 50 * (ptlModel.y / 50);
- if( (ptlModel.x == ptlOldMouse.x) && (ptlModel.y == ptlOldMouse.y))
- return;
- ptlOldMouse.x = ptlModel.x;
- ptlOldMouse.y = ptlModel.y;
- ptlDevice = ptlModel;
- if (GpiConvert( hpsClient, CVTC_MODEL, CVTC_DEVICE, 1L, &ptlDevice) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- if (GpiBitBlt( hpsBitmapBuff
- , hpsBitmapSave
- , 3L
- , aptlUpdt
- , ROP_SRCCOPY
- , BBO_IGNORE ) == GPI_ERROR)
- DispError(habMain,hwndClient);
- aptlUpdtRef[0] = aptlUpdt[0];
- aptlUpdtRef[1] = aptlUpdt[1];
-
- aptlUpdt[0].x += ptlDevice.x - ptlUpdtRef.x;
- aptlUpdt[0].y += ptlDevice.y - ptlUpdtRef.y;
- aptlUpdt[1].x += ptlDevice.x - ptlUpdtRef.x;
- aptlUpdt[1].y += ptlDevice.y - ptlUpdtRef.y;
- WinMapWindowPoints( hwndClient, HWND_DESKTOP, aptlUpdt, 3);
- ROUND_DOWN_MOD( aptlUpdt[0].x, lByteAlignX); /* round down */
- ROUND_DOWN_MOD( aptlUpdt[0].y, lByteAlignY); /* round down */
- ROUND_UP_MOD( aptlUpdt[1].x, lByteAlignX); /* round up */
- ROUND_UP_MOD( aptlUpdt[1].y, lByteAlignY); /* round up */
- WinMapWindowPoints( HWND_DESKTOP, hwndClient, aptlUpdt, 3);
- aptlUpdt[2] = aptlUpdt[0];
- ptlUpdtRef = ptlDevice;
- if (GpiBitBlt( hpsBitmapSave
- , hpsBitmapBuff
- , 3L
- , aptlUpdt
- , ROP_SRCCOPY
- , BBO_IGNORE ) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
-
- pslPicked->ptlModelXlate.x = ptlOffStart.x + ptlModel.x - ptlMoveStart.x;
- pslPicked->ptlModelXlate.y = ptlOffStart.y + ptlModel.y - ptlMoveStart.y;
-
- for( psl = pslPicked, fFirst = TRUE
- ; (psl != pslPicked) || fFirst
- ; psl = psl->pslNextIsland, fFirst = FALSE )
- {
- psl->ptlModelXlate = pslPicked->ptlModelXlate;
- DrawPiece( hpsBitmapBuff, psl, TRUE);
- }
-
- WinUnionRect( habMain
- , (PRECTL)aptlUpdtNew
- , (PRECTL)aptlUpdt
- , (PRECTL)aptlUpdtRef);
- WinMapWindowPoints( hwndClient, HWND_DESKTOP, aptlUpdtNew, 2);
- ROUND_DOWN_MOD( aptlUpdtNew[0].x, lByteAlignX); /* round down */
- ROUND_DOWN_MOD( aptlUpdtNew[0].y, lByteAlignY); /* round down */
- ROUND_UP_MOD( aptlUpdtNew[1].x, lByteAlignX); /* round up */
- ROUND_UP_MOD( aptlUpdtNew[1].y, lByteAlignY); /* round up */
- WinMapWindowPoints( HWND_DESKTOP, hwndClient, aptlUpdtNew, 2);
- aptlUpdtNew[2] = aptlUpdtNew[0];
- if (GpiBitBlt( hpsClient
- , hpsBitmapBuff
- , 3L
- , aptlUpdtNew
- , ROP_SRCCOPY
- , BBO_IGNORE ) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
-
-
- /******************************************************************************/
- /* */
- /* The dragged segment is being unselected. Return it to its normal state. */
- /* */
- /******************************************************************************/
- VOID LeftUp(VOID)
- {
- PSEGLIST psl, pslTemp;
- POINTL ptlShift;
- BOOL fFirst;
- LONG l;
-
- if (!BmpLoaded)
- {
- MessageBox(hwndFrame, IDS_LOADBITMAP, MB_OK | MB_INFORMATION, TRUE);
- return;
- }
- else if(fPictureAssembled)
- {
- MessageBox(hwndFrame, IDS_OPTIONJUMBLE, MB_OK | MB_INFORMATION, TRUE);
- return;
- }
-
- if( !lPickedSeg || !pslPicked)
- return;
-
- for( psl = pslPicked, fFirst = TRUE
- ; (psl != pslPicked) || fFirst
- ; psl = psl->pslNextIsland, fFirst = FALSE )
- {
-
- SetRect( psl);
- SegListUpdate( MAKE_TAIL_SEG, psl); /* at tail => highest priority */
- psl->fIslandMark = TRUE; /* mark as island member */
- }
- ptlShift = pslPicked->ptlModelXlate;
-
- for( psl = pslHead; psl != NULL; psl = psl->pslNext)
- if( !psl->fIslandMark)
- for( l = 0; l < 8; l++)
- if( pslPicked->lAdjacent[l] == psl->lSegId)
- if( (ptlShift.x == psl->ptlModelXlate.x)
- && (ptlShift.y == psl->ptlModelXlate.y))
- {
- DosBeep( 600, 100);
- DosBeep( 1200, 50);
- MarkIsland( psl, TRUE); /* mark the whole new island */
- pslTemp = psl->pslNextIsland; /* swap island ptrs */
- psl->pslNextIsland = pslPicked->pslNextIsland;
- pslPicked->pslNextIsland = pslTemp;
- }
- MarkIsland( pslPicked, FALSE); /* unmark the island */
-
- pslPicked = NULL;
- lPickedSeg = 0;
-
- WinSetCapture( HWND_DESKTOP, (HWND)NULL);
- }
-
-
- /******************************************************************************/
- /* */
- /* DoHorzScroll will horizontally scroll the current contents of */
- /* the client area and redraw the invalidated area */
- /* */
- /******************************************************************************/
- VOID DoHorzScroll(VOID)
- {
- POINTL aptlClient[3];
- HRGN hrgn;
- MATRIXLF matlf;
-
- if( ptsScrollPos.x > ptsScrollMax.x) /* clip to range of scroll param */
- ptsScrollPos.x = ptsScrollMax.x;
- if( ptsScrollPos.x < 0)
- ptsScrollPos.x = 0;
-
- if( ptsOldScrollPos.x != ptsScrollPos.x) /* only process change in position */
- WinSendMsg( hwndHorzScroll
- , SBM_SETPOS
- , MPFROM2SHORT( ptsScrollPos.x, 0)
- , MPFROMLONG( NULL));
-
- /****************************************************************************/
- /* Scroll the window the reqd amount, using bitblt'ing (ScrollWindow) */
- /* if any of the screen still in view, and paint into uncovered region; */
- /* else repaint the whole client area. */
- /****************************************************************************/
- hrgn = GpiCreateRegion( hpsClient, 0L, NULL);
- WinQueryWindowRect( hwndClient, (PRECTL)aptlClient);
- if( abs( ptsScrollPos.x - ptsOldScrollPos.x) <= ptsScrollMax.x)
- {
- WinScrollWindow( hwndClient
- , (SHORT) (ptsOldScrollPos.x - ptsScrollPos.x)
- , (SHORT) 0
- , (PRECTL) NULL
- , (PRECTL) NULL
- , (HRGN) hrgn
- , (PRECTL) NULL
- , 0);
- } else
- {
- if (GpiSetRegion( hpsClient, hrgn, 1L, (PRECTL)aptlClient) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
- /****************************************************************************/
- /* adjust the default view matrix */
- /****************************************************************************/
- if (GpiQueryDefaultViewMatrix( hpsClient, 9L, &matlf ) == GPI_ERROR)
- DispError(habMain,hwndClient);
- matlf.lM31 -= ptsScrollPos.x - ptsOldScrollPos.x;
- if (GpiSetDefaultViewMatrix( hpsClient, 9L, &matlf, TRANSFORM_REPLACE) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- DoDraw( hpsClient, hrgn, TRUE); /* paint into the client area */
- ptsOldScrollPos.x = ptsScrollPos.x;
- if (GpiDestroyRegion( hpsClient, hrgn) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- aptlClient[2] = aptlClient[0];
- if (!fFirstLoad) /* don't bother if no bitmap was read in */
- {
- if (GpiBitBlt( hpsBitmapBuff /* update the off-screen client image */
- , hpsClient
- , 3L
- , aptlClient
- , ROP_SRCCOPY
- , BBO_IGNORE ) == GPI_ERROR)
- DispError(habMain,hwndClient);
- } /* end if () */
- }
-
- /******************************************************************************/
- /* */
- /* DoVertScroll will vertically scroll the current contents of */
- /* the client area and redraw the invalidated area */
- /* */
- /******************************************************************************/
- VOID DoVertScroll(VOID)
- {
- POINTL aptlClient[3];
- HRGN hrgn;
- MATRIXLF matlf;
-
- if( ptsScrollPos.y > ptsScrollMax.y)
- ptsScrollPos.y = ptsScrollMax.y;
- if( ptsScrollPos.y < 0)
- ptsScrollPos.y = 0;
-
- if( ptsOldScrollPos.y != ptsScrollPos.y)
- WinSendMsg( hwndVertScroll
- , SBM_SETPOS
- , MPFROM2SHORT( ptsScrollPos.y, 0)
- , MPFROMLONG( NULL));
-
- /****************************************************************************/
- /* Scroll the window the reqd amount, using bitblt'ing (ScrollWindow) */
- /* if any of the screen still in view, and paint into uncovered region; */
- /* else repaint the whole client area. */
- /****************************************************************************/
- hrgn = GpiCreateRegion( hpsClient, 0L, NULL);
- WinQueryWindowRect( hwndClient, (PRECTL)aptlClient);
- if( abs( ptsScrollPos.y - ptsOldScrollPos.y) <= ptsScrollMax.y)
- {
- WinScrollWindow( hwndClient
- , 0
- , (SHORT) (ptsScrollPos.y - ptsOldScrollPos.y)
- , (PRECTL) NULL
- , (PRECTL) NULL
- , (HRGN) hrgn
- , (PRECTL) NULL
- , 0);
- } else
- {
- if (GpiSetRegion( hpsClient, hrgn, 1L, (PRECTL)aptlClient) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
- if (GpiQueryDefaultViewMatrix( hpsClient, 9L, &matlf ) == GPI_ERROR)
- DispError(habMain,hwndClient);
- matlf.lM32 += ptsScrollPos.y - ptsOldScrollPos.y;
- if (GpiSetDefaultViewMatrix( hpsClient, 9L, &matlf, TRANSFORM_REPLACE) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- DoDraw( hpsClient, hrgn, TRUE);
- ptsOldScrollPos.y = ptsScrollPos.y;
- if (GpiDestroyRegion( hpsClient, hrgn) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- aptlClient[2] = aptlClient[0];
- if (!fFirstLoad) /* don't bother if no bitmap was read in */
- {
- if (GpiBitBlt( hpsBitmapBuff
- , hpsClient
- , 3L
- , aptlClient
- , ROP_SRCCOPY
- , BBO_IGNORE ) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
- }
-
- /******************************************************************************
- *
- * Name : EnableMenu
- *
- * Description : Enable/Disable bitmap size submenus
- *
- * Parameters : ULONG id - menu id (ASSUME: id = submenu of FID_MAIN
- * BOOL fEnable - enable/disable?
- *
- * Return : VOID
- *
- ******************************************************************************/
-
- VOID EnableMenu(ULONG id, BOOL fEnable)
- {
- WinSendMsg(hwndMenu, /* global main menu handle */
- MM_SETITEMATTR, /* set menu attribute */
- MPFROM2SHORT(id, TRUE), /* menu id */
- MPFROM2SHORT(MIA_DISABLED, /* mask = disable bit */
- fEnable ? ~MIA_DISABLED : MIA_DISABLED)); /* turn off/on */
-
- } /* end EnableMenu() */
-
- /******************************************************************************
- *
- * Name : CheckMenu
- *
- * Description : Check/Uncheck bitmap size submenus
- *
- * Parameters : ULONG id - menu id (ASSUME: id = submenu of FID_MAIN
- * BOOL fCheck - check/unckeck?
- *
- * Return : VOID
- *
- ******************************************************************************/
-
- VOID CheckMenu(ULONG id, BOOL fCheck)
- {
- WinSendMsg(hwndMenu, /* global main menu handle */
- MM_SETITEMATTR, /* set menu attribute */
- MPFROM2SHORT(id, TRUE), /* menu id */
- MPFROM2SHORT(MIA_CHECKED, /* mask = check bit */
- fCheck ? MIA_CHECKED : ~MIA_CHECKED)); /* turn on/off */
-
- } /* end CheckMenu() */
-
-
- /******************************************************************************/
- /* */
- /* adjust zoom factor and recalc the picture transform, then do a redraw of */
- /* whole screen */
- /* */
- /******************************************************************************/
- VOID Zoom( VOID )
- {
- ULONG ulPostKillDraw, ulPostCt;
-
- DosQueryEventSem(hevKillDraw, &ulPostKillDraw);
-
- CalcBounds();
- DosQueryEventSem(hevKillDraw, &ulPostCt);
- if (ulPostKillDraw != ulPostCt)
- {
- DosResetEventSem(hevKillDraw, &ulPostCt);
- return;
- }
- CalcTransform( hwndClient);
- DosQueryEventSem(hevKillDraw, &ulPostCt);
- if (ulPostKillDraw != ulPostCt)
- {
- DosResetEventSem(hevKillDraw, &ulPostCt);
- return;
- }
- Redraw();
- }
-
- /******************************************************************************/
- /* */
- /* Check the segment list for obvious errors. */
- /* */
- /******************************************************************************/
- BOOL SegListCheck(INT iLoc)
- {
- PSEGLIST psl;
- CHAR szMsg[50];
-
- szMsg[0] = '\0';
- for( psl = pslHead; psl != NULL; psl = psl->pslNext)
- if( (psl->lSegId < 1) || (psl->lSegId > lLastSegId) )
- {
- #if defined(DEBUG)
-
- sprintf( szMsg, "Bad head segment list, location %d", iLoc);
- WinMessageBox(HWND_DESKTOP, hwndFrame, szMsg, szErrorTitle, 0,
- MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
- #endif
-
- return( FALSE);
- }
- for( psl = pslTail; psl != NULL; psl = psl->pslPrev)
- if( (psl->lSegId < 1) || (psl->lSegId > lLastSegId) )
- {
- #if defined(DEBUG)
-
- sprintf( szMsg, "Bad head segment list, location %d", iLoc);
- WinMessageBox(HWND_DESKTOP, hwndFrame, szMsg, szErrorTitle, 0,
- MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
- #endif
-
- return( FALSE);
- }
- return( TRUE);
- }
-
- /******************************************************************************/
- /* */
- /* DumpPicture will free the list and segment store for the picture */
- /* */
- /******************************************************************************/
- BOOL DumpPicture(VOID)
- {
- while( pslHead != NULL )
- {
- if (GpiSetBitmap( pslHead->hpsFill, NULLHANDLE) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDeleteBitmap( pslHead->hbmFill) == GPI_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDestroyPS( pslHead->hpsFill) == GPI_ERROR)
- DispError(habMain,hwndClient);
- DevCloseDC( pslHead->hdcFill);
-
- if (GpiSetBitmap( pslHead->hpsHole, NULLHANDLE) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDeleteBitmap( pslHead->hbmHole) == GPI_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDestroyPS( pslHead->hpsHole) == GPI_ERROR)
- DispError(habMain,hwndClient);
- DevCloseDC( pslHead->hdcHole);
-
- SegListUpdate( DEL_SEG, pslHead);
- }
-
- if( hbmBitmapSize)
- {
- if (GpiSetBitmap( hpsBitmapSize, NULLHANDLE) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDeleteBitmap( hbmBitmapSize) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
- if( hbmBitmapBuff)
- {
- if (GpiSetBitmap( hpsBitmapBuff, NULLHANDLE) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDeleteBitmap( hbmBitmapBuff) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
- if( hbmBitmapSave)
- {
- if (GpiSetBitmap( hpsBitmapSave, NULLHANDLE) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- if (GpiDeleteBitmap( hbmBitmapSave) == GPI_ERROR)
- DispError(habMain,hwndClient);
- }
-
- return( TRUE);
- }
-
- /******************************************************************************/
- /* */
- /* Draw the picture into segment store. */
- /* */
- /******************************************************************************/
- BOOL CreatePicture(SHORT sUpdate)
- {
- POINTL ptl, aptlSides[12], aptlControl[12];
- SEGLIST sl;
- PSEGLIST psl;
- LONG l, lMinor, lNeighbor, alFuzz[36][4];
- SIZEL sizl;
- BITMAPINFOHEADER2 bmp2;
- PBITMAPINFOHEADER2 pbmp2 = &bmp2;
- DATETIME date;
- ULONG ulPostCt;
-
- /****************************************************************************/
- /* compute some fuzz for the control points */
- /****************************************************************************/
- DosGetDateTime( &date);
- srand( (USHORT)date.hundredths);
- for( l = 0; l < 36; l++)
- for( lMinor = 0; lMinor < 4; lMinor++)
- alFuzz[l][lMinor] = 50 * (rand() % 10);
-
- /****************************************************************************/
- /* reset the default viewing transform to identity */
- /****************************************************************************/
- SetDVTransform( (FIXED)UNITY
- , (FIXED)0
- , (FIXED)0
- , (FIXED)UNITY
- , 0L
- , 0L
- , TRANSFORM_REPLACE);
-
- /****************************************************************************/
- /* draw the pieces */
- /****************************************************************************/
- lLastSegId = 0;
- for( ptl.x = ptlBotLeft.x; ptl.x < ptlTopRight.x; ptl.x += 500)
- {
- DosQueryEventSem( hevTerminate, &ulPostCt);
- if( ulPostCt)
- break;
- for( ptl.y = ptlBotLeft.y; ptl.y < ptlTopRight.y; ptl.y += 500)
- {
- DosQueryEventSem( hevTerminate, &ulPostCt);
- if( ulPostCt)
- break;
- lLastSegId++;
-
- /************************************************************************/
- /* compute the piece outline control points */
- /************************************************************************/
- aptlControl[0].x = 250L;
- aptlControl[0].y = 500L;
- aptlControl[1].x = 250;
- aptlControl[1].y = -500L;
- aptlControl[2].x = 500L;
- aptlControl[2].y = 0L;
-
- aptlControl[3].x = 0L;
- aptlControl[3].y = 250L;
- aptlControl[4].x = 1000L;
- aptlControl[4].y = 250L;
- aptlControl[5].x = 500L;
- aptlControl[5].y = 500L;
-
- aptlControl[6].x = 250L;
- aptlControl[6].y = 0L;
- aptlControl[7].x = 250L;
- aptlControl[7].y = 1000L;
- aptlControl[8].x = 0L;
- aptlControl[8].y = 500L;
-
- aptlControl[9].x = 500L;
- aptlControl[9].y = 250L;
- aptlControl[10].x = -500L;
- aptlControl[10].y = 250L;
- aptlControl[11].x = 0L;
- aptlControl[11].y = 0L;
-
- if( ptl.y == ptlBotLeft.y)
- {
- aptlControl[0].y = 0L;
- aptlControl[1].y = 0L;
- }
-
- if( (ptl.x + 500) == ptlTopRight.x)
- {
- aptlControl[3].x = 500L;
- aptlControl[4].x = 500L;
- }
-
- if( (ptl.y + 500) == ptlTopRight.y)
- {
- aptlControl[6].y = 500L;
- aptlControl[7].y = 500L;
- }
-
- if( ptl.x == ptlBotLeft.x)
- {
- aptlControl[ 9].x = 0L;
- aptlControl[10].x = 0L;
- }
-
- /************************************************************************/
- /* compute the adjacent segments */
- /************************************************************************/
- sl.lAdjacent[0] = lLastSegId - 7;
- sl.lAdjacent[1] = lLastSegId - 6;
- sl.lAdjacent[2] = lLastSegId - 5;
- sl.lAdjacent[3] = lLastSegId - 1;
- sl.lAdjacent[4] = lLastSegId + 1;
- sl.lAdjacent[5] = lLastSegId + 5;
- sl.lAdjacent[6] = lLastSegId + 6;
- sl.lAdjacent[7] = lLastSegId + 7;
- if( ptl.x == ptlBotLeft.x)
- {
- sl.lAdjacent[0] = 0;
- sl.lAdjacent[1] = 0;
- sl.lAdjacent[2] = 0;
- }
- if( ptl.y == ptlBotLeft.y)
- {
- sl.lAdjacent[0] = 0;
- sl.lAdjacent[3] = 0;
- sl.lAdjacent[5] = 0;
- }
- if( (ptl.x + 500) == ptlTopRight.x)
- {
- sl.lAdjacent[5] = 0;
- sl.lAdjacent[6] = 0;
- sl.lAdjacent[7] = 0;
- }
- if( (ptl.y + 500) == ptlTopRight.y)
- {
- sl.lAdjacent[2] = 0;
- sl.lAdjacent[4] = 0;
- sl.lAdjacent[7] = 0;
- }
-
- /************************************************************************/
- /* throw in some fuzz */
- /************************************************************************/
- if( sl.lAdjacent[3])
- {
- aptlControl[0].y -= alFuzz[lLastSegId - 1][0];
- aptlControl[1].y += alFuzz[lLastSegId - 1][1];
- }
-
- if( sl.lAdjacent[1])
- {
- aptlControl[9].x -= alFuzz[lLastSegId - 1][2];
- aptlControl[10].x += alFuzz[lLastSegId - 1][3];
- }
-
- if( lNeighbor = sl.lAdjacent[4])
- {
- aptlControl[7].y -= alFuzz[lNeighbor - 1][0];
- aptlControl[6].y += alFuzz[lNeighbor - 1][1];
- }
-
- if( lNeighbor = sl.lAdjacent[6])
- {
- aptlControl[4].x -= alFuzz[lNeighbor - 1][2];
- aptlControl[3].x += alFuzz[lNeighbor - 1][3];
- }
-
- /************************************************************************/
- /* compute the piece control points in world coordinates */
- /************************************************************************/
- for( l=0; l<12; l++)
- {
- aptlSides[l].x = ptl.x + aptlControl[l].x;
- aptlSides[l].y = ptl.y + aptlControl[l].y;
- sl.aptlSides[l] = aptlSides[l];
- }
-
- /************************************************************************/
- /* compute the dimensions of the matching rects for BitBlt */
- /************************************************************************/
- sl.rclBitBlt.xLeft = ptl.x - 250;
- sl.rclBitBlt.yBottom = ptl.y - 250;
- sl.rclBitBlt.xRight = ptl.x + 750;
- sl.rclBitBlt.yTop = ptl.y + 750;
- if( ptl.x == ptlBotLeft.x)
- sl.rclBitBlt.xLeft += 250;
- if( ptl.y == ptlBotLeft.y)
- sl.rclBitBlt.yBottom += 250;
- if( (ptl.x + 500) == ptlTopRight.x)
- sl.rclBitBlt.xRight -= 250;
- if( (ptl.y + 500) == ptlTopRight.y)
- sl.rclBitBlt.yTop -= 250;
-
- /************************************************************************/
- /* store the piece location */
- /************************************************************************/
- sl.ptlLocation = ptl;
-
- /************************************************************************/
- /* create the masks */
- /************************************************************************/
- if( sUpdate == PICTURE_CREATE)
- {
- bmp2 = bmp2BitmapFile;
- if (bmp2.cbFix == sizeof(BITMAPINFOHEADER))
- {
- sizl.cx = 2 + ((PBITMAPINFOHEADER)pbmp2BitmapFile)->cx
- * (sl.rclBitBlt.xRight - sl.rclBitBlt.xLeft)
- / (ptlTopRight.x - ptlBotLeft.x);
- sizl.cy = 2 + ((PBITMAPINFOHEADER)pbmp2BitmapFile)->cy
- * (sl.rclBitBlt.yTop - sl.rclBitBlt.yBottom)
- / (ptlTopRight.y - ptlBotLeft.y);
- ((PBITMAPINFOHEADER)pbmp2)->cx = LOUSHORT( sizl.cx);
- ((PBITMAPINFOHEADER)pbmp2)->cy = LOUSHORT( sizl.cy);
- }
- else
- {
- sizl.cx = 2 + ((pbmp2BitmapFile->cx
- * (sl.rclBitBlt.xRight - sl.rclBitBlt.xLeft))
- / (ptlTopRight.x - ptlBotLeft.x));
- sizl.cy = 2 + ((pbmp2BitmapFile->cy
- * (sl.rclBitBlt.yTop - sl.rclBitBlt.yBottom))
- / (ptlTopRight.y - ptlBotLeft.y));
- (pbmp2)->cx = LOUSHORT( sizl.cx);
- (pbmp2)->cy = LOUSHORT( sizl.cy);
- }
-
- if ((sl.hdcHole = DevOpenDC( habMain
- , OD_MEMORY
- , "*"
- , 3L
- , (PDEVOPENDATA)&dop
- , NULLHANDLE)) == DEV_ERROR)
- DispError(habMain,hwndClient);
- if ((sl.hpsHole = GpiCreatePS( habMain
- , sl.hdcHole
- , &sizl
- , PU_PELS | GPIA_ASSOC | GPIT_MICRO )) == GPI_ERROR)
- DispError(habMain,hwndClient);
-
- if ((sl.hbmHole = GpiCreateBitmap( sl.hpsHole
- , pbmp2
- , 0L
- , NULL
- , NULL)) == (HBITMAP)GPI_ERROR)
- DispError(habMain,hwndClient);
-
-
- if ((GpiSetBitmap( sl.hpsHole, sl.hbmHole)) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
-
-
- if ((sl.hdcFill = DevOpenDC( habMain
- , OD_MEMORY
- , "*"
- , 3L
- , (PDEVOPENDATA)&dop
- , NULLHANDLE)) == DEV_ERROR)
- DispError(habMain,hwndClient);
- if ((sl.hpsFill = GpiCreatePS( habMain
- , sl.hdcFill
- , &sizl
- , PU_PELS | GPIA_ASSOC | GPIT_MICRO )) == GPI_ERROR)
- DispError(habMain,hwndClient);
- if ((sl.hbmFill = GpiCreateBitmap( sl.hpsFill
- , pbmp2
- , 0L
- , NULL
- , NULL)) == (HBITMAP)GPI_ERROR)
- DispError(habMain,hwndClient);
-
- if ((GpiSetBitmap( sl.hpsFill, sl.hbmFill)) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
- }
-
-
- sl.fVisible = TRUE;
- sl.lSegId = lLastSegId;
- sl.fIslandMark = FALSE;
- sl.ptlModelXlate.x = sl.ptlModelXlate.y = 0L;
- if( sUpdate == PICTURE_CREATE)
- {
- sl.pslNext = NULL;
- sl.pslPrev = NULL;
- SetRect( &sl);
- psl = SegListUpdate( ADD_TAIL_SEG, &sl);
- } else
- {
- psl = SegListGet( lLastSegId);
- psl->fIslandMark = FALSE;
- for( l=0; l<12; l++)
- psl->aptlSides[l] = aptlSides[l];
- psl->ptlModelXlate = sl.ptlModelXlate;
- SetRect( psl);
- }
- psl->pslNextIsland = psl; /* point to self ==> island of one */
- }
- }
- if( ulPostCt)
- SendCommand( UM_DIE, (MPARAM)NULL, (MPARAM)NULL);
-
- return( TRUE);
- }
-
- /******************************************************************************/
- /******************************************************************************/
- /******************************************************************************/
- VOID CheckPsl( psl)
- PSEGLIST psl;
- {
- SHORT s;
-
- for( s=2; s<12; s+=3)
- if( !WinPtInRect( habAsync, &psl->rclBitBlt, &psl->aptlSides[s]))
- break;
- }
-
- /******************************************************************************/
- /* */
- /* Create the Size, Save and Buff bitmaps. */
- /* */
- /******************************************************************************/
- BOOL PrepareBitmap(VOID)
- {
- hbmBitmapSize = GpiCreateBitmap( hpsBitmapSize
- , pbmp2BitmapFile
- , 0L
- , NULL
- , NULL);
- if( !hbmBitmapSize)
- {
- DispError(habMain,hwndClient);
- return( FALSE);
- }
- if (GpiSetBitmap( hpsBitmapSize, hbmBitmapSize) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
-
- bmp2BitmapSave = bmp2BitmapFile;
- if (pbmp2BitmapSave->cbFix == sizeof(BITMAPINFOHEADER))
- {
- ((PBITMAPINFOHEADER)pbmp2BitmapSave)->cx = LOUSHORT( sizlMaxClient.cx);
- ((PBITMAPINFOHEADER)pbmp2BitmapSave)->cy = LOUSHORT( sizlMaxClient.cy);
- }
- else
- {
- (pbmp2BitmapSave)->cx = LOUSHORT(sizlMaxClient.cx);
- (pbmp2BitmapSave)->cy = LOUSHORT(sizlMaxClient.cy);
- }
- hbmBitmapSave = GpiCreateBitmap( hpsBitmapSave
- , pbmp2BitmapSave
- , 0L
- , NULL
- , NULL);
- if( !hbmBitmapSave)
- {
- DispError(habMain,hwndClient);
- return( FALSE);
- }
- if (GpiSetBitmap( hpsBitmapSave, hbmBitmapSave) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
-
-
- hbmBitmapBuff = GpiCreateBitmap( hpsBitmapBuff
- , pbmp2BitmapSave
- , 0L
- , NULL
- , NULL);
- if( !hbmBitmapBuff)
- {
- DispError(habMain,hwndClient);
- return( FALSE);
- }
- if (GpiSetBitmap( hpsBitmapBuff, hbmBitmapBuff) == (HBITMAP)BMB_ERROR)
- DispError(habMain,hwndClient);
-
- return( TRUE);
- }
-
- /******************************************************************************
- *
- * Name : ReadBitmap
- *
- * Description :
- *
- * Get the bitmap from disk.
- * Note that there are 2 formats for bitmap files, one of which is archaic.
- * Both formats are supported here. All new bitmaps should follow the format
- * in BITMAPFILEHEADER.
- *
- * Concepts :
- *
- * API's :
- *
- * Parameters : HFILE hfile
- *
- * Return : BOOL
- *
- * Notes:
- *
- * File Layout - size and layout of following map are dependent on the
- * type of bitmap. The cbFix field of the structures is used to determine
- * the size of the structures which in turn identifies them.
- *
- *
- * SINGLE BITMAP FILE FORMAT
- *
- * ┌─────────────────────────────────────────┐ offset 0
- * │ Bitmap File Header (bfh2) │ pbfh2->offBits contains data ─┐
- * │ │ offset (from begin of file) │
- * ├─────────────────────────────────────────┤ │
- * │ Bitmap Information Header (bmp2) │ │
- * ├─────────────────────────────────────────┤ │
- * │ Color Table of RGB Structures (argb2) │ │
- * ├─────────────────────────────────────────┤ <─────────────────────────────┘
- * │ Bitmap Data (scan lines) │
- * │ . │
- * │ . │
- * │ . │
- * └─────────────────────────────────────────┘
- *
- *
- * BITMAP-ARRAY FILE FORMAT
- *
- * ┌─────────────────────────────────────────┐ offset 0
- * │ Bitmap Array File Header (baf2) │
- * │ (only for bitmap arrays) │
- * ├─────────────────────────────────────────┤
- * │ Bitmap File Header (bfh2) │ pbfh2->offBits contains data ─┐
- * │ │ offset (from begin of file) │
- * ├─────────────────────────────────────────┤ │
- * │ Bitmap Information Header (bmp2) │ │
- * ├─────────────────────────────────────────┤ │
- * │ Color Table of RGB Structures (argb2) │ │
- * ├─────────────────────────────────────────┤ │
- * │ next Bitmap Array File Header │ │
- * │ . │ │
- * │ . │ │
- * │ . │ │
- * ├─────────────────────────────────────────┤ <─────────────────────────────┘
- * │ 1st Bitmap Data (scan lines) │
- * │ │
- * │ │
- * ├─────────────────────────────────────────┤
- * │ next Bitmap Data (scan lines) │
- * │ . │
- * │ . │
- * │ . │
- * └─────────────────────────────────────────┘
- *
- ******************************************************************************/
-
- BOOL ReadBitmap(HFILE hfile)
- {
- APIRET rc; /* API return code */
- BOOL fRet = FALSE; /* Function return code. */
- FILESTATUS fsts;
- PBITMAPFILEHEADER2 pbfh2; /* can address any file types */
- PBITMAPINFOHEADER2 pbmp2; /* address any info headers */
- PBYTE pFileBegin = NULL; /* beginning of bitmap file data */
- ULONG cbRead; /* Number of bytes read by DosRead. */
- ULONG cScans, cScansRet; /* number of scan lines in bitmap (cy) */
-
- /*
- * Use Loop to avoid duplicate cleanup code. If any errors, a break
- * statement will jump directly to error cleanup code.
- */
-
- do
- {
- /*
- * Find out how big the file is, allocate that much memory, and read
- * in the entire bitmap.
- */
-
- rc =
- DosQueryFileInfo(hfile, 1, &fsts, sizeof(fsts));
- if (rc)
- break; /* jump to error code outside of loop */
-
- rc =
- DosAllocMem(
- (PPVOID) &pFileBegin,
- (ULONG) fsts.cbFile,
- (ULONG) PAG_READ | PAG_WRITE | PAG_COMMIT);
-
- if (rc)
- break; /* jump to error code outside of loop */
-
- if (DosRead( hfile, (PVOID)pFileBegin, fsts.cbFile, &cbRead))
- break; /* jump to error code outside of loop */
-
- /*
- * If it's a bitmap-array, point to common file header. Otherwise,
- * point to beginning of file.
- */
-
- pbfh2 = (PBITMAPFILEHEADER2) pFileBegin;
- pbmp2 = NULL; /* only set this when we validate type */
-
- switch (pbfh2->usType)
- {
- case BFT_BITMAPARRAY:
-
- /*
- * If this is a Bitmap-Array, adjust pointer to the normal
- * file header. We'll just use the first bitmap in the
- * array and ignore other device forms.
- */
-
- pbfh2 = &(((PBITMAPARRAYFILEHEADER2) pFileBegin)->bfh2);
- pbmp2 = &pbfh2->bmp2; /* pointer to info header (readability) */
- break;
-
- case BFT_BMAP:
-
- pbmp2 = &pbfh2->bmp2; /* pointer to info header (readability) */
- break;
-
- default: /* these formats aren't supported; don't set any ptrs */
- case BFT_ICON:
- case BFT_POINTER:
- case BFT_COLORICON:
- case BFT_COLORPOINTER:
-
- break;
-
- } /* end switch (pbfh2->usType) */
-
- if (pbmp2 == NULL)
- break; /* File format NOT SUPPORTED: break out to error code */
-
- /*
- * Check to see if BMP file has an old structure, a new structure, or
- * Windows structure. Capture the common data and treat all bitmaps
- * generically with pointer to new format. API's will determine format
- * using cbFixed field.
- *
- * Windows bitmaps have the new format, but with less data fields
- * than PM. The old strucuture has some different size fields,
- * though the field names are the same.
- *
- *
- * NOTE: bitmap data is located by offsetting the beginning of the file
- * by the offset contained in pbfh2->offBits. This value is in
- * the same relatie location for different format bitmap files.
- */
-
- if (pbmp2->cbFix == sizeof(BITMAPINFOHEADER)) /* old format? */
- {
- cScans = (ULONG) ((PBITMAPINFOHEADER)pbmp2)->cy;
- }
- else /* new PM format, Windows, or other */
- {
- cScans = pbmp2->cy;
- }
-
- memcpy( /* copy bitmap info into global structure */
- (PVOID) pbmp2BitmapFile,
- (PVOID) pbmp2,
- pbmp2->cbFix); /* only copy specified size (varies per format) */
-
- hbmBitmapFile =
- GpiCreateBitmap(
- hpsBitmapFile, /* presentation-space handle */
- pbmp2BitmapFile, /* address of structure for format data */
- 0L, /* options */
- NULL, /* address of buffer of image data */
- NULL); /* address of structure for color and format */
-
- if (!hbmBitmapFile)
- {
- DispError(habMain,hwndClient);
- break; /* jump to error code outside of loop */
- }
-
- if (GpiSetBitmap( hpsBitmapFile, hbmBitmapFile) == (HBITMAP)BMB_ERROR)
- {
- DispError(habMain,hwndClient);
- break; /* jump to error code outside of loop */
- }
-
- /*
- * Tell GPI to put the bits into the thread's PS. The function returns
- * the number of scan lines of the bitmap that were copied. We want
- * all of them at once.
- */
-
- cScansRet =
- GpiSetBitmapBits(
- hpsBitmapFile, /* presentation-space handle */
- 0L, /* index of first scan line */
- cScans, /* number of scan lines */
- pFileBegin + pbfh2->offBits, /* address of bitmap data */
- (PBITMAPINFO2) pbmp2); /* address of bitmap header table */
-
- if (cScansRet != cScans) /* original # of scans? */
- {
- DispError(habMain,hwndClient);
- break; /* jump to error code outside of loop */
- }
-
- DosFreeMem( pFileBegin);
- DosClose( hfile);
- return TRUE; /* function successful */
-
- } while (FALSE); /* fall through loop first time */
-
- /*
- * Close the file, free the buffer space and leave. This is an error exit
- * point from the function. Cleanup code is here to avoid duplicate code
- * after each operation.
- */
-
- if (pFileBegin != NULL)
- DosFreeMem( pFileBegin);
- DosClose( hfile);
-
- return FALSE; /* function failed */
-
- } /* end ReadBitmap() */
-
-
- /**************************************************************************/
- /* DispError -- report an error returned from an API service. */
- /* */
- /* The error message is displayed using a message box */
- /* */
- /**************************************************************************/
- VOID DispErrorMsg(HAB hab, HWND hwndFrame, PCH FileName, LONG LineNum)
- {
- PERRINFO pErrInfoBlk;
- PSZ pszOffSet, pszErrMsg;
- ERRORID ErrorId;
- PCH ErrorStr;
- CHAR szbuff[125];
-
- DosBeep(800,10);
- #if defined(DEBUG)
- DosBeep(800,10);
- DosBeep(800,10);
- DosBeep(800,10);
- DosBeep(800,10);
- DosBeep(800,10);
- #endif /* defined(DEBUG) */
-
- if (!hab)
- { /* Non-PM Error */
- WinLoadString( habMain,0, IDS_UNKNOWNMSG, sizeof(szbuff), (PSZ)szbuff);
- ErrorStr = malloc(strlen(szbuff)+strlen(FileName)+10);
- sprintf(ErrorStr, szbuff, FileName, LineNum);
- WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */
- hwndFrame, /* Owner window is our frame */
- (PSZ)ErrorStr, /* PMWIN Error message */
- szErrorTitle, /* Title bar message */
- MSGBOXID, /* Message identifier */
- MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL ); /* Flags */
- free(ErrorStr);
- return;
- }
-
- ErrorId = WinGetLastError(hab);
-
- if ((pErrInfoBlk = WinGetErrorInfo(hab)) != (PERRINFO)NULL)
- {
- pszOffSet = ((PSZ)pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
- pszErrMsg = ((PSZ)pErrInfoBlk) + *((PULONG)pszOffSet);
-
- WinLoadString( habMain,0, IDS_ERRORMSG, sizeof(szbuff), (PSZ)szbuff);
- ErrorStr = malloc(strlen(szbuff)+strlen(pszErrMsg)+strlen(FileName)+10);
- sprintf(ErrorStr, szbuff, pszErrMsg, FileName, LineNum);
-
- WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */
- hwndFrame, /* Owner window is our frame */
- (PSZ)ErrorStr, /* PMWIN Error message */
- szErrorTitle, /* Title bar message */
- MSGBOXID, /* Message identifier */
- MB_MOVEABLE | MB_CUACRITICAL | MB_CANCEL ); /* Flags */
-
- free(ErrorStr);
-
- WinFreeErrorInfo(pErrInfoBlk);
- }
- }
-
-
- /********************************************************************/
-
- /* DosGetThreadInfo Call Only Temp Call for the LX Toronto Compiler */
-
- /********************************************************************/
-
- APIRET DosGetThreadInfo(PTIB *pptib,PPIB *pppib)
- {
-
- return( DosGetInfoBlocks(pptib,pppib) );
- }
-
- /******************************* END JIGSAW.C ******************************/
-