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