home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * *
- * Name: STROKE.C *
- * *
- * Copyright : COPYRIGHT IBM CORPORATION, 1993 *
- * LICENSED MATERIAL - PROGRAM PROPERTY OF IBM *
- * *
- * Description: This program processes all of the ink related functions *
- * for the application. *
- * *
- * 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. *
- * *
- ******************************************************************************/
-
- #define INCL_PM
- #define INCL_DOS
-
- /******************************************************************************
- * System include files *
- ******************************************************************************/
- #include <os2.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <penpm.h>
-
- /******************************************************************************
- * Application specific include file *
- ******************************************************************************/
- #include "stroke.h"
-
- /******************************************************************************
- * Exported routines *
- ******************************************************************************/
- HWND APIENTRY InitTimedInk ( HWND, MMTIME * );
- BOOL APIENTRY PlayTimedInk ( HWND );
- BOOL APIENTRY StopTimedInk ( HWND );
- BOOL APIENTRY RecordTimedInk ( HWND );
- BOOL APIENTRY PurgeTimedInk ( HWND );
- BOOL APIENTRY DestroyTimeInk ( HWND );
- MRESULT EXPENTRY InkWinProc ( HWND, ULONG, MRESULT, MRESULT );
- BOOL APIENTRY InkTimedInk ( HWND, MMTIME );
-
- /******************************************************************************
- * Internal routines *
- ******************************************************************************/
- ULONG TimeToPoints ( PMYWINDOWDATA, MMTIME );
- BOOL InkStroke ( PMYWINDOWDATA, ULONG );
- BOOL AppendStrokes ( PMYWINDOWDATA, PSTROKEDATA );
- BOOL ScaleStrokeData ( PMYWINDOWDATA );
- BOOL EraseTimedInk ( PMYWINDOWDATA );
-
- /******************************************************************************
- * Used to track the current time reported from Multimedia. *
- ******************************************************************************/
- MMTIME *pCurrMMTime;
-
- /******************************************************************************
- * *
- * Subroutine: InitTimedInk *
- * *
- * Function: This function performs the initialization for the inking *
- * window. It allocates a block of memory for the data structure *
- * used by the inking window. It then creates a transparent window *
- * to ink into. *
- * *
- * Parameters: hwndParent - is the window handle to the parent window. The *
- * parent window will be the window containing the *
- * image to be annotated. *
- * *
- * Internal *
- * References: None *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- HWND APIENTRY InitTimedInk ( HWND hwndParent, MMTIME *pMMTime )
- {
- PMYWINDOWDATA pMyWindowData;
- APIRET rc;
- HAB hab;
- HMQ hmq;
- QMSG qmsg;
- HWND hwndInking;
- static BOOL WindowClassRegistered = FALSE;
- RECTL rcl;
-
- pMyWindowData = (PMYWINDOWDATA) malloc ( sizeof ( MYWINDOWDATA ) );
-
- /***************************************************************************
- * Verify that the memory for the data structure has been allocated. If not *
- * return a NULLHANDLE to signify an error condition. *
- ***************************************************************************/
- if ( pMyWindowData == NULL )
- {
- return ( NULLHANDLE );
- };
-
- pCurrMMTime = pMMTime;
-
- pMyWindowData->hwndParent = hwndParent;
- pMyWindowData->hab = WinQueryAnchorBlock ( hwndParent );
-
- /***************************************************************************
- * Register the window class for the inking window, if it has not already *
- * been done. *
- ***************************************************************************/
- if ( !WindowClassRegistered )
- {
- /************************************************************************
- * When the class is registered, reserve 4 more bytes to keep the *
- * pointer to pMyWindowData structure. *
- ************************************************************************/
- if ( !WinRegisterClass ( pMyWindowData->hab,
- WC_INK_WINDOW,
- InkWinProc,
- CS_SYNCPAINT,
- sizeof ( PMYWINDOWDATA ) ) )
- {
- /*********************************************************************
- * If the class has not been registered return a NULLHANDLE to *
- * signify an error condition. *
- *********************************************************************/
- free ( pMyWindowData );
- return ( NULLHANDLE );
- };
-
- /************************************************************************
- * If all goes well, set flag to indicate that the class has been *
- * already been registered. *
- ************************************************************************/
- WindowClassRegistered = TRUE;
- };
-
- /***************************************************************************
- * Determine the size of the window, then create then inking window. *
- ***************************************************************************/
- WinQueryWindowRect ( pMyWindowData->hwndParent, &rcl );
- hwndInking = WinCreateWindow ( pMyWindowData->hwndParent,
- WC_INK_WINDOW,
- NULL,
- 0,
- 0,
- 0,
- rcl.xRight,
- rcl.yTop,
- pMyWindowData->hwndParent,
- HWND_TOP,
- ID_INK_WINDOW,
- (PVOID) pMyWindowData,
- NULL );
-
- /***************************************************************************
- * Verify that the window has been created. If not return NULLHANDLE to *
- * signify an error condition, else return the handle to the inking window. *
- ***************************************************************************/
- if ( !hwndInking )
- {
- free ( pMyWindowData );
- return ( NULLHANDLE );
- };
- return ( hwndInking );
- }
-
- /******************************************************************************
- * *
- * Subroutine: DestroyTimedInk *
- * *
- * Function: This function performs the cleanup for the inking window and *
- * the associated memory. *
- * *
- * Parameters: hwndParent - is the window handle to the parent window. The *
- * parent window will be the window containing the *
- * image to be annotated. *
- * *
- * Internal *
- * References: EraseTimedInk - Cleans up display of window *
- * PurgeTimedInk - Purge previous recording *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL APIENTRY DestroyTimedInk ( HWND hWnd )
- {
- PMYWINDOWDATA pMyWindowData;
- HWND hwndAudio;
-
- /***************************************************************************
- * Get pointer to the window data. *
- ***************************************************************************/
- pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
-
- /*****************************************************************
- * Close the audio dialog window along with this window. *
- *****************************************************************/
- if (hwndAudio = WinWindowFromID(pMyWindowData->hwndParent,
- IDD_AUDIO))
- {
- WinSendMsg(hwndAudio,
- WM_CLOSE,
- (MPARAM) NULL,
- (MPARAM) NULL);
- };
-
- EraseTimedInk ( pMyWindowData );
- PurgeTimedInk ( pMyWindowData->hwnd );
- WinDestroyWindow ( pMyWindowData->hwnd );
-
- free ( pMyWindowData );
- pMyWindowData = (PMYWINDOWDATA) NULL;
- return ( IME_NO_ERROR );
- }
-
- /******************************************************************************
- * *
- * Subroutine: ScaleStrokeData *
- * *
- * Function: Converts stroke data in high resolution to screen resolution. *
- * *
- * Parameters: hWnd - Window handle for the inking window. *
- * *
- * Internal *
- * References: AppendStrokes - Appends new stroke to linked list pointer to by *
- * pStrokeHead *
- * *
- * Pen For OS2 *
- * References: WrtMapPointLong - Scales stroke data from one resolution to *
- * another. *
- * *
- ******************************************************************************/
- BOOL ScaleStrokeData ( PMYWINDOWDATA pMyWindowData )
- {
- PSTROKEDATA pTempStrokeHead;
- PSTROKEDATA pTempCurrStroke;
- PSTROKEDATA pStrokeScaled;
- RECTL rcl;
-
- /***************************************************************************
- * If the high resolution stroke data hasn't been scaled yet, then allocate *
- * memory for the scaled stroke data. *
- ***************************************************************************/
- if ( !pMyWindowData->pScaledHead )
- {
-
- /************************************************************************
- * Start off by saving the pointer to the high resolution stroke data, *
- * setting the pointer to the current stroke to convert, and then *
- * resetting the stroke head pointer to null. *
- ************************************************************************/
- pTempStrokeHead = pMyWindowData->pStrokeHead;
- pTempCurrStroke = pMyWindowData->pStrokeHead;
- pMyWindowData->pStrokeHead = NULL;
-
- /************************************************************************
- * For every stroke in the high resolution stroke data linked list, *
- * allocate memory for the scaled stroke, copy high resolution stroke *
- * information to the scaled stroke structure, allocate memory for the *
- * scaled point information, and append new stroke to linked list. *
- ************************************************************************/
- while ( pTempCurrStroke )
- {
- pStrokeScaled = (PSTROKEDATA) malloc ( sizeof(STROKEDATA) );
- memcpy ( pStrokeScaled,
- pTempCurrStroke,
- sizeof(STROKEDATA) );
- pStrokeScaled->pXY = (PPOINTL) malloc ( sizeof(POINTL) *
- pStrokeScaled->ulNumPoints );
- AppendStrokes ( pMyWindowData, pStrokeScaled );
- pTempCurrStroke = pTempCurrStroke->psdFwd;
- };
-
- /************************************************************************
- * pStrokeHead now points to a linked list of stroke headers for the *
- * scaled stroke data. Each stroke in this list has a pointer to an *
- * array of POINTL data structures, however the points in the array have *
- * not yet been set. Save the pointer to the new linked list and restore *
- * the pointer to the high resolution linked list. *
- ************************************************************************/
- pMyWindowData->pScaledHead = pMyWindowData->pStrokeHead;
- pMyWindowData->pStrokeHead = pTempStrokeHead;
- };
-
- /***************************************************************************
- * For each stroke in the linked list, copy the high resolution point data, *
- * and then scale it to the appropriate size. *
- ***************************************************************************/
- WinQueryWindowRect ( pMyWindowData->hwnd, &rcl );
- pTempCurrStroke = pMyWindowData->pStrokeHead;
- pStrokeScaled = pMyWindowData->pScaledHead;
- while ( pTempCurrStroke )
- {
- memcpy ( pStrokeScaled->pXY,
- pTempCurrStroke->pXY,
- sizeof(POINTL) * pStrokeScaled->ulNumPoints );
-
- /************************************************************************
- * WrtMapPointLong will convert the input points to a new resolution. *
- * The things to note here are that: 1) NULLHANDLE is used as the input *
- * window handle; and 2) the calculation for the extents. The NULLHANDLE *
- * is used since we have already asked for the coordinates to be *
- * adjusted relative to the window at liftoff time. The documentation *
- * can be confusing on this point. If we were to provide the window *
- * for this window, then all of the points would be offset by the *
- * position of the window relative to the desktop origin. The extents *
- * are adjusted for changes in the window size. There is an inverse *
- * relationship between the extents and ink. Increase the extents and *
- * ink will be shrink. Decrease the extents and the ink will expand. *
- ************************************************************************/
- WrtMapPointLong(NULLHANDLE,
- pStrokeScaled->pXY,
- MP_SCALE,
- ((pStrokeScaled->ulXExtent * pMyWindowData->OrgWindowSize.cx) / rcl.xRight),
- ((pStrokeScaled->ulYExtent * pMyWindowData->OrgWindowSize.cy) / rcl.yTop ),
- 0UL,
- 0UL,
- pStrokeScaled->ulNumPoints);
- pTempCurrStroke = pTempCurrStroke->psdFwd;
- pStrokeScaled = pStrokeScaled->psdFwd;
- };
- return ( IME_NO_ERROR );
- }
-
- /******************************************************************************
- * *
- * Subroutine: PlayTimedInk *
- * *
- * Function: Initializes data structure for playback of a recording. *
- * *
- * Parameters: hWnd - Window handle for the inking window. *
- * *
- * Internal *
- * References: EraseTimedInk - Cleanup display of window *
- * ScaleStrokeData - Scale data from high resolution *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL APIENTRY PlayTimedInk ( HWND hWnd )
- {
- PMYWINDOWDATA pMyWindowData;
-
- /***************************************************************************
- * Get pointer to the window data. *
- ***************************************************************************/
- pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
-
- EraseTimedInk ( pMyWindowData );
-
- /***************************************************************************
- * Convert high resolution stroke data to screen resolution *
- ***************************************************************************/
- if ( !pMyWindowData->pScaledHead )
- {
- ScaleStrokeData ( pMyWindowData );
- };
-
- /***************************************************************************
- * Prepare to playback the timed ink by setting current stroke to first *
- * stroke in linked list. If the first stroke exists set pointer to current *
- * point and set the number of points remaining to be inked for the current *
- * stroke. *
- ***************************************************************************/
- pMyWindowData->pCurrStroke = pMyWindowData->pScaledHead;
- if ( pMyWindowData->pCurrStroke != NULL )
- {
- pMyWindowData->NumPointsLeft = pMyWindowData->pCurrStroke->ulNumPoints;
- pMyWindowData->pCurrPoint = pMyWindowData->pCurrStroke->pXY;
- };
-
- /***************************************************************************
- * Set flags to indicate current state. *
- ***************************************************************************/
- pMyWindowData->fPlay = TRUE;
- pMyWindowData->fRecord = FALSE;
-
- return ( IME_NO_ERROR );
- }
-
-
- /******************************************************************************
- * *
- * Subroutine: RecordTimedInk *
- * *
- * Function: Initializes application in preparation to record timed ink. *
- * *
- * Parameters: hWnd - Window handle for inking window *
- * *
- * Internal *
- * References: EraseTimedInk - Cleanup display of window *
- * PurgeTimedInk - Purge previous recording *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL APIENTRY RecordTimedInk ( HWND hWnd )
- {
- PMYWINDOWDATA pMyWindowData;
- APIRET rc;
-
- /***************************************************************************
- * Get pointer to the window data. *
- ***************************************************************************/
- pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
-
- /***************************************************************************
- * Cleanup the window for the next recording. *
- ***************************************************************************/
- EraseTimedInk ( pMyWindowData );
-
- /***************************************************************************
- * Free all of the old stroke data. *
- ***************************************************************************/
- if ( pMyWindowData->pStrokeHead != NULL )
- {
- PurgeTimedInk ( hWnd );
- }
-
- /***************************************************************************
- * Set flags to indicate current state. *
- ***************************************************************************/
- pMyWindowData->fPlay = FALSE;
- pMyWindowData->fRecord = TRUE;
-
- return ( IME_NO_ERROR );
- }
-
- /******************************************************************************
- * *
- * Subroutine: EraseTimedInk *
- * *
- * Function: Removes ink from the transparent inking window. *
- * *
- * Parameters: pMyWindowData - Pointer to windon specific information *
- * *
- * Internal *
- * References: None *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL EraseTimedInk ( PMYWINDOWDATA pMyWindowData )
- {
- RECTL rcl;
-
- /***************************************************************************
- * Force the window to be repainted but without showing handwritten part. *
- ***************************************************************************/
- GpiDeleteSegments ( pMyWindowData->hps, 1, pMyWindowData->NumSegments );
- pMyWindowData->NumSegments = 0;
-
- WinQueryWindowRect ( pMyWindowData->hwndParent, &rcl );
- WinInvalidateRect ( pMyWindowData->hwndParent, &rcl, TRUE);
-
- /***************************************************************************
- * Set flags to indicate current state. *
- ***************************************************************************/
- pMyWindowData->fPlay = FALSE;
- pMyWindowData->fRecord = FALSE;
-
- return ( IME_NO_ERROR );
- }
-
- /******************************************************************************
- * *
- * Subroutine: StopTimedInk *
- * *
- * Function: Stops recording of timed ink. *
- * *
- * Parameters: hWnd - Window handle for inking window *
- * *
- * Internal *
- * References: None *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL APIENTRY StopTimedInk ( HWND hWnd )
- {
- RECTL rcl;
- PMYWINDOWDATA pMyWindowData;
-
- /***************************************************************************
- * Get pointer to the window data. *
- ***************************************************************************/
- pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
-
- /***************************************************************************
- * Set flags to indicate current state. *
- ***************************************************************************/
- pMyWindowData->fPlay = FALSE;
- pMyWindowData->fRecord = FALSE;
-
- return ( IME_NO_ERROR );
- }
-
- /******************************************************************************
- * *
- * Subroutine: PurgeTimedInk *
- * *
- * Function: Purges all strokes from memory. *
- * *
- * Parameters: hWnd - Window handle for inking window *
- * *
- * Internal *
- * References: None *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL APIENTRY PurgeTimedInk ( HWND hWnd )
- {
- PMYWINDOWDATA pMyWindowData;
- PSTROKEDATA pTempStroke;
-
- /***************************************************************************
- * Get pointer to the window data. *
- ***************************************************************************/
- pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
-
- /***************************************************************************
- * Set flags to indicate current state. *
- ***************************************************************************/
- pMyWindowData->fPlay = FALSE;
- pMyWindowData->fRecord = FALSE;
-
- pMyWindowData->pCurrStroke = pMyWindowData->pStrokeHead;
- while ( pMyWindowData->pCurrStroke != NULL )
- {
- pTempStroke = pMyWindowData->pCurrStroke->psdFwd;
-
- free ( pMyWindowData->pCurrStroke->pXY );
- free ( pMyWindowData->pCurrStroke );
-
- pMyWindowData->pCurrStroke = pTempStroke;
- };
- pMyWindowData->pStrokeHead = NULL;
-
- pMyWindowData->pCurrStroke = pMyWindowData->pScaledHead;
- while ( pMyWindowData->pCurrStroke != NULL )
- {
- pTempStroke = pMyWindowData->pCurrStroke->psdFwd;
-
- free ( pMyWindowData->pCurrStroke->pXY );
- free ( pMyWindowData->pCurrStroke );
-
- pMyWindowData->pCurrStroke = pTempStroke;
- };
- pMyWindowData->pScaledHead = NULL;
-
- return ( IME_NO_ERROR );
- }
-
-
- /******************************************************************************
- * *
- * Subroutine: AppendStrokes *
- * *
- * Function: Append a new stroke to the linked list of strokes for the *
- * current recording.
- * *
- * Parameters: pMyWindowData - Pointer to window instance data *
- * pStrokeData - Pointer to the stroke data of the stroke to be *
- * appended to the linked list of strokes *
- * *
- * Internal *
- * References: None *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL AppendStrokes ( PMYWINDOWDATA pMyWindowData, PSTROKEDATA pStrokeData )
- {
- /***************************************************************************
- * If the stroke head pointer is null, then this is the first stroke in the *
- * linked list of strokes. *
- ***************************************************************************/
- if ( pMyWindowData->pStrokeHead == NULL )
- {
- pMyWindowData->pStrokeHead = pStrokeData;
- pMyWindowData->pCurrStroke = pStrokeData;
- return ( IME_NO_ERROR );
- };
-
- /***************************************************************************
- * Otherwise, append the new stroke to the end of the linked list. *
- ***************************************************************************/
- pMyWindowData->pCurrStroke->psdFwd = pStrokeData;
- pStrokeData->psdBack = pMyWindowData->pCurrStroke;
- pMyWindowData->pCurrStroke = pStrokeData;
- return ( IME_NO_ERROR );
- }
-
- /******************************************************************************
- * *
- * Subroutine: InkTimedInk *
- * *
- * Function: This is a recursive routine that determines the strokes and *
- * points that need to be inked for this time interval. *
- * *
- * Parameters: hWnd - Window handle to inking window *
- * ElapsedTime - This is the elapsed time ,in MMTIME units, from *
- * the start of the recording *
- * *
- * Internal *
- * References: TimeToPoints - Convert a time duration to the number of points *
- * to ink for the time duration *
- * InkStroke - Draw the stroke to the window *
- * InkTimedInk - Determine how much more to ink *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL APIENTRY InkTimedInk ( HWND hWnd, MMTIME ElapsedTime )
- {
- ULONG PointsToInk;
- static MMTIME LastElapsedTime;
- PMYWINDOWDATA pMyWindowData;
-
- /***************************************************************************
- * Get pointer to the window data. *
- ***************************************************************************/
- pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
-
- /***************************************************************************
- * If the pointer to the window data is null return FALSE to indicate an *
- * error condition. *
- ***************************************************************************/
- if ( pMyWindowData == NULL )
- return ( IME_INVALID_POINTER );
-
- /***************************************************************************
- * If the pointer to the current stroke is null then there are no more *
- * strokes remaining to be inked, so return TRUE to indicate things are ok. *
- ***************************************************************************/
- if ( pMyWindowData->pCurrStroke == NULL )
- {
- return ( IME_NO_ERROR );
- };
-
- /***************************************************************************
- * ulUser1 contains the start time for the stroke. If the current elapsed *
- * time is less than the start time for the current stroke, then there are *
- * aren't any points to ink for this time period. Save the elapsed time for *
- * this call and TRUE to indicate things are ok. *
- ***************************************************************************/
- if ( ElapsedTime < pMyWindowData->pCurrStroke->ulUser1 )
- {
- LastElapsedTime = ElapsedTime;
- return ( IME_NO_ERROR );
- };
-
- /***************************************************************************
- * ulUser2 contains the end time for the stroke. If the current elapsed *
- * time is greater than or equal to the end time for the current stroke, *
- * then the rest of the current stroke needs to be inked and perhaps more. *
- * Thus ink the rest of this stroke, set the last elapsed time, move to the *
- * next stroke and make the recursive call to determine if more points need *
- * to be inked, and return. *
- ***************************************************************************/
- if ( ElapsedTime >= pMyWindowData->pCurrStroke->ulUser2 )
- {
- InkStroke ( pMyWindowData, pMyWindowData->NumPointsLeft );
- LastElapsedTime = pMyWindowData->pCurrStroke->ulUser2;
- pMyWindowData->pCurrStroke = pMyWindowData->pCurrStroke->psdFwd;
-
- /************************************************************************
- * If there are more strokes in the linked list then move to next stroke *
- ************************************************************************/
- if ( pMyWindowData->pCurrStroke != NULL )
- {
- pMyWindowData->NumPointsLeft = pMyWindowData->pCurrStroke->ulNumPoints;
- pMyWindowData->pCurrPoint = pMyWindowData->pCurrStroke->pXY;
- InkTimedInk ( hWnd, ElapsedTime );
- };
- return ( IME_NO_ERROR );
- };
-
- /***************************************************************************
- * If we get to this point then only a portion of the current stroke needs *
- * to be inked at this time. Determine how many points to ink, ink the *
- * points, set the elapsed time, and return. *
- ***************************************************************************/
- PointsToInk = TimeToPoints ( pMyWindowData, ElapsedTime - LastElapsedTime );
- InkStroke ( pMyWindowData, PointsToInk );
- LastElapsedTime = ElapsedTime;
- return ( IME_NO_ERROR );
- }
-
- /******************************************************************************
- * *
- * Subroutine: TimeToPoints *
- * *
- * Function: This function calcualates and returns the number of points to *
- * be inked for a given amount of time. *
- * *
- * Parameters: pMyWindowData - Pointer to window data *
- * DeltaTime - The amount of time that needs to be inked *
- * *
- * Internal *
- * References: None *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- ULONG TimeToPoints ( PMYWINDOWDATA pMyWindowData, MMTIME DeltaTime )
- {
- ULONG NumOfPoints;
-
- /***************************************************************************
- * MMTIME is 1/3000 of a second. The sample rate is given in points per *
- * second. Thus the number of points to ink is calculated by: *
- * *
- * 1 SECOND NUM OF POINTS *
- * ---------------- X DeltaTime MMTIMEUNITS X ------------- *
- * 3000 MMTIMEUNITS SECOND *
- * *
- * Once the estimate of the number of points has been made, check to see if *
- * it exceeds the number of points remaining to be inked in the current *
- * stroke. Return the minimum of these two numbers. *
- ***************************************************************************/
- NumOfPoints = DeltaTime * pMyWindowData->pCurrStroke->ulSampleRate / 3000 ;
- if ( pMyWindowData->NumPointsLeft < NumOfPoints )
- {
- NumOfPoints = pMyWindowData->NumPointsLeft;
- };
- return ( NumOfPoints );
- }
-
-
- /******************************************************************************
- * *
- * Subroutine: InkStroke *
- * *
- * Function: This function draws the ink to the display during playback. It *
- * uses paths to draw 2 pel wide geometric lines. It then updates *
- * the number of points still waiting to be drawn, and moves the *
- * current point pointer to the next point to be drawn. *
- * *
- * Parameters: pMyWindowData - Pointer to window data *
- * NumOfPoints - Number of points to ink from the current stroke *
- * *
- * Internal *
- * References: None *
- * *
- * Pen For OS2 *
- * References: None *
- * *
- ******************************************************************************/
- BOOL InkStroke ( PMYWINDOWDATA pMyWindowData, ULONG NumOfPoints )
- {
- /***************************************************************************
- * If the current point is the first point in the stroke then the stroke *
- * not been inked yet. So move to the first point in the presentation space *
- * in preparation for the polyline. *
- ***************************************************************************/
- if ( pMyWindowData->pCurrPoint == pMyWindowData->pCurrStroke->pXY )
- {
- GpiOpenSegment ( pMyWindowData->hps, ++pMyWindowData->NumSegments );
- GpiMove ( pMyWindowData->hps, pMyWindowData->pCurrPoint );
- };
-
- /***************************************************************************
- * Now draw the stroke on the screen *
- ***************************************************************************/
- GpiBeginPath ( pMyWindowData->hps, 1 );
- GpiPolyLine ( pMyWindowData->hps, NumOfPoints, pMyWindowData->pCurrPoint );
- GpiEndPath ( pMyWindowData->hps );
- GpiStrokePath ( pMyWindowData->hps, 1, 0 );
-
- /***************************************************************************
- * Update the window data to indicate the number of points yet to be inked *
- * in the current stroke and move the current point pointer to the next *
- * next point to the last point inked. *
- ***************************************************************************/
- pMyWindowData->NumPointsLeft -= NumOfPoints;
- pMyWindowData->pCurrPoint += NumOfPoints;
-
- /***************************************************************************
- * If last point in stroke has been inked, then close the graphic segment. *
- ***************************************************************************/
- if ( pMyWindowData->pCurrPoint == NULL )
- {
- GpiCloseSegment ( pMyWindowData->hps );
- };
-
- return ( IME_NO_ERROR );
- }
-
- /******************************************************************************
- * *
- * Subroutine: InkWinProc *
- * *
- * Function: Window procedure for inking window. The inking window is a *
- * transparent window that we will be inking to during the capture *
- * and playback of stroke data. *
- * *
- * Parameters: hWnd - Window handle *
- * msg - Message Id *
- * mp1 - Message Parameter 1 *
- * mp2 - Message Parameter 2 *
- * *
- * Internal *
- * References: AppendStrokes - Append strokes to linked list *
- * ScaleStrokeData - Scale strokes from high resolution *
- * PlayTimedInk - Prepare to playback recording *
- * InkTimedInk - Draw ink to window *
- * StopTimedInk - Stop playback or recording *
- * *
- * Pen For OS2 *
- * References: WrtQueryEventData - Get the event data from Pen for OS/2 *
- * WrtQueryStrokeData - Get stroke data *
- * *
- ******************************************************************************/
- MRESULT EXPENTRY InkWinProc ( HWND hWnd,
- ULONG msg,
- MRESULT mp1,
- MRESULT mp2 )
- {
- SIZEL PageSize;
- PMYWINDOWDATA pMyWindowData;
- ULONG buflen;
- PSTROKEDATA pStrokeData;
- static MMTIME TouchdownTime = 0;
- static MMTIME LiftoffTime = 0;
- APIRET rc;
- static USHORT PointCounter = 0;
- static POINTL pPoint[8];
- static BOOL StrokeBufferOverrun = FALSE;
- RECTL rcl;
- HPS hpspaint;
- WRTEVENTDATA EventData;
-
- /***************************************************************************
- * Get pointer to the window data. *
- ***************************************************************************/
- pMyWindowData = (PMYWINDOWDATA) WinQueryWindowPtr ( hWnd, 0 );
- switch ( msg )
- {
- /************************************************************************
- * Create this transparent window and setup the pMyWindowData. This *
- * structure is kept in reserved area. *
- ************************************************************************/
- case WM_CREATE:
- {
- /*********************************************************************
- * Initialize window instance data *
- *********************************************************************/
- pMyWindowData = (PMYWINDOWDATA) PVOIDFROMMP ( mp1 );
- if ( !WinSetWindowPtr ( hWnd, 0, (PVOID) pMyWindowData ) )
- return ( (MPARAM) TRUE );
-
- pMyWindowData->hwnd = hWnd;
-
- /*********************************************************************
- * Create the presentation space for the window *
- *********************************************************************/
- pMyWindowData->hab = WinQueryAnchorBlock ( hWnd );
- pMyWindowData->hdc = WinOpenWindowDC ( hWnd );
- DevQueryCaps ( pMyWindowData->hdc, CAPS_WIDTH, 1L, &PageSize.cx );
- DevQueryCaps ( pMyWindowData->hdc, CAPS_HEIGHT, 1L, &PageSize.cy );
- pMyWindowData->hps = GpiCreatePS ( pMyWindowData->hab,
- pMyWindowData->hdc,
- &PageSize,
- ( PU_PELS |
- GPIT_NORMAL |
- GPIF_LONG |
- GPIA_ASSOC ) );
- if ( pMyWindowData->hps == GPI_ERROR )
- {
- return ( (MPARAM) TRUE );
- };
-
- /*********************************************************************
- * Prepare the presentation space for drawing and retaining *
- * the graphic primatives *
- *********************************************************************/
- GpiSetDrawingMode ( pMyWindowData->hps, DM_DRAWANDRETAIN );
- GpiSetDrawControl ( pMyWindowData->hps,
- DCTL_ERASE,
- DCTL_OFF );
- pMyWindowData->NumSegments = 0;
-
- /*********************************************************************
- * Set initial presentation space attributes *
- *********************************************************************/
- pMyWindowData->CurrentColor = CLR_RED;
- GpiSetColor ( pMyWindowData->hps,
- pMyWindowData->CurrentColor );
- GpiSetLineWidthGeom ( pMyWindowData->hps, 2L );
- GpiSetLineEnd ( pMyWindowData->hps, LINEEND_ROUND );
- GpiSetLineJoin ( pMyWindowData->hps, LINEJOIN_ROUND );
-
- /*********************************************************************
- * Set flags to initial state *
- *********************************************************************/
- pMyWindowData->td = FALSE;
- pMyWindowData->fPlay = FALSE;
- pMyWindowData->fRecord = FALSE;
-
- /*********************************************************************
- * Make the window visible and return *
- *********************************************************************/
- WinShowWindow ( hWnd, TRUE );
- return ( (MRESULT) FALSE );
- break;
- }
-
- /************************************************************************
- * Get the start time of stroke, Capture mouse messages, move to *
- * the point where the pen touches the workpad to ink. *
- ************************************************************************/
- case WM_TOUCHDOWN:
- {
- /*********************************************************************
- * Only process this message if we are in the process of creating *
- * a new recording. *
- *********************************************************************/
- if ( pMyWindowData->fRecord )
- {
- /******************************************************************
- * Get the current time in MMTIME *
- ******************************************************************/
- TouchdownTime = *(pCurrMMTime);
- GpiOpenSegment ( pMyWindowData->hps, ++pMyWindowData->NumSegments );
- WinQueryWindowRect ( hWnd, &rcl );
- pMyWindowData->OrgWindowSize.cx = rcl.xRight;
- pMyWindowData->OrgWindowSize.cy = rcl.yTop;
-
- PointCounter = 0;
-
- pMyWindowData->td = TRUE;
- WinSetCapture ( HWND_DESKTOP, hWnd );
-
- /******************************************************************
- * Note that the (SHORT) cast is required in order to maintain *
- * sign. *
- ******************************************************************/
- pMyWindowData->points.x = (SHORT) SHORT1FROMMP ( mp1 );
- pMyWindowData->points.y = (SHORT) SHORT2FROMMP ( mp1 );
-
- GpiMove ( pMyWindowData->hps, &pMyWindowData->points );
-
- /******************************************************************
- * TDN_INFINTE: Inform Pen for OS/2 that the mouse button down *
- * is not required. *
- * TDN_HIFREQ_MOUSEMOVE: Inform Pen for OS/2 to report the points *
- * as mousemoves but at the sensor sample rate. *
- * TDN_NO_INK_STROKE: Inform Pen for OS/2 not to ink the points *
- * since we will be doing our inking. *
- ******************************************************************/
- return ( (MRESULT) ( TDN_INFINITE |
- TDN_HIFREQ_MOUSEMOVE |
- TDN_NO_INK_STROKE ));
- };
- break;
- }
-
- /************************************************************************
- * For this message, the inking is done to show the stroke. *
- ************************************************************************/
- case WM_MOUSEMOVE:
- {
- if ( pMyWindowData != NULL )
- {
- if ( pMyWindowData->td && pMyWindowData->fRecord )
- {
- /***************************************************************
- * This release of Pen for OS/2 has a maximum limit to the size *
- * of the stroke buffer. It is limited to 1024 points or eight *
- * seconds per stroke. If the maximum size of the stroke buffer *
- * is reached, then inform the user via a tone. *
- ***************************************************************/
- if ( StrokeBufferOverrun )
- {
- DosBeep ( 4000, 16 );
- return ( (MRESULT) TRUE );
- };
-
- /***************************************************************
- * Get the event data to see if the stroke buffer has been *
- * been filled. *
- ***************************************************************/
- EventData.cbStructSize = sizeof(EventData);
- WrtQueryEventData ( &EventData );
- if ( EventData.flEventStatus & WRT_BUFFER_OVERRUN )
- {
- DosBeep ( 4000, 16 );
-
- /************************************************************
- * Force the inking for all of the remaining points. *
- ************************************************************/
- GpiBeginPath ( pMyWindowData->hps, 1 );
- GpiPolyLine ( pMyWindowData->hps, PointCounter, pPoint );
- GpiEndPath ( pMyWindowData->hps );
- GpiStrokePath ( pMyWindowData->hps, 1, 0 );
- GpiCloseSegment ( pMyWindowData->hps );
- StrokeBufferOverrun = TRUE;
- return ( (MRESULT) TRUE );
- };
-
- /***************************************************************
- * Keep the (x,y) coordinate in a buffer of 8 entries. *
- * Note that the (SHORT) cast is required in order to maintain *
- * sign. *
- ***************************************************************/
- pPoint[PointCounter].x = (SHORT) SHORT1FROMMP( mp1 );
- pPoint[PointCounter].y = (SHORT) SHORT2FROMMP( mp1 );
- PointCounter++;
- if (PointCounter == 8)
- {
- GpiBeginPath ( pMyWindowData->hps, 1 );
- GpiPolyLine ( pMyWindowData->hps, 8L, pPoint );
- GpiEndPath ( pMyWindowData->hps );
- GpiStrokePath ( pMyWindowData->hps, 1, 0 );
- PointCounter = 0;
- }
- return ( (MRESULT) TRUE );
- };
- };
- break;
- }
-
- /************************************************************************
- * Stroke ends. Collect stroke end time, No more mouse message *
- * capture, Get the stroke data and Call AppendStrokes to adjust *
- * the stroke linked list in pMyWindowData. *
- ************************************************************************/
- case WM_LIFTOFF:
- {
- if ( pMyWindowData->td && pMyWindowData->fRecord )
- {
- /******************************************************************
- * Get the current time in MMTIME *
- ******************************************************************/
- LiftoffTime = *(pCurrMMTime);
- WinSetCapture ( HWND_DESKTOP, NULLHANDLE );
- pMyWindowData->td = FALSE;
-
- /******************************************************************
- * If the buffer was overrun, then the points have already been *
- * displayed. *
- ******************************************************************/
- if ( !StrokeBufferOverrun )
- {
- /******************************************************************
- * Force the inking for all of the remaining points. *
- * Note that the (SHORT) cast is required in order to maintain *
- * sign. *
- ******************************************************************/
- pPoint[PointCounter].x = (SHORT) SHORT1FROMMP( mp1 );
- pPoint[PointCounter].y = (SHORT) SHORT2FROMMP( mp1 );
- PointCounter++;
- GpiBeginPath ( pMyWindowData->hps, 1 );
- GpiPolyLine ( pMyWindowData->hps, PointCounter, pPoint );
- GpiEndPath ( pMyWindowData->hps );
- GpiStrokePath ( pMyWindowData->hps, 1, 0 );
- GpiCloseSegment ( pMyWindowData->hps );
- };
-
- /******************************************************************
- * Get the size of the stroke buffer. *
- ******************************************************************/
- buflen = 0;
- pStrokeData = NULL;
- rc = WrtQueryStrokeData ( (PBYTE) pStrokeData, &buflen, hWnd, QSD_SCALE, 0, 0, 0 );
- if ( rc )
- return (MRESULT) TRUE;
-
- if ( !buflen )
- return (MRESULT) TRUE;
-
- /******************************************************************
- * Allocate memory for the stroke buffer. *
- ******************************************************************/
- pStrokeData = (PSTROKEDATA) malloc ( buflen );
- if ( !pStrokeData )
- {
- return ( (MRESULT) TRUE );
- };
-
- /******************************************************************
- * Get the stroke data *
- ******************************************************************/
- pStrokeData->cbStructSize = sizeof ( STROKEDATA );
- if ( WrtQueryStrokeData ( (PBYTE) pStrokeData,
- &buflen,
- pMyWindowData->hwnd,
- QSD_STANDARDIZED_RES,
- 0,
- 0,
- 0 ) )
- return ( (MRESULT) LO_STROKE_PROCESSED );
-
- /******************************************************************
- * Append current stroke to linked list *
- ******************************************************************/
- AppendStrokes ( pMyWindowData, pStrokeData );
-
- /******************************************************************
- * Use existing structure entries for the stroke to hold the *
- * touchdown and liftoff times for the current stroke *
- ******************************************************************/
- pStrokeData->ulUser1 = TouchdownTime;
- pStrokeData->ulUser2 = LiftoffTime;
-
- StrokeBufferOverrun = FALSE;
-
- return ( (MRESULT) LO_STROKE_PROCESSED );
-
- }
- else
- {
- return ( (MRESULT) LO_DEFAULT );
- };
- return ( (MRESULT) FALSE );
- }
-
- /************************************************************************
- * Repaint the window, let the default window procedure handle. *
- ************************************************************************/
- case WM_PAINT:
- {
- hpspaint = WinBeginPaint ( hWnd, pMyWindowData->hps, &rcl );
- GpiDrawChain ( hpspaint );
- WinEndPaint ( hpspaint );
- return ( (MRESULT) TRUE );
- }
-
- /************************************************************************
- * Clean up before we close the window *
- ************************************************************************/
- case WM_DESTROY:
- {
- GpiDestroyPS ( pMyWindowData->hps );
- return ( (MRESULT) FALSE );
- }
-
- /************************************************************************
- * When the parent window is resized, this window is resized. Scale the *
- * data to the new size, and playback the ink into the window at the new *
- * scale. *
- ************************************************************************/
- case WM_SIZE:
- {
- if ( pMyWindowData != NULL )
- {
- if ( pMyWindowData->pStrokeHead )
- {
- WinShowWindow ( pMyWindowData->hwnd, FALSE );
- ScaleStrokeData ( pMyWindowData );
- PlayTimedInk ( pMyWindowData->hwnd );
- InkTimedInk ( pMyWindowData->hwnd, *(pCurrMMTime) );
- StopTimedInk ( pMyWindowData->hwnd );
- WinShowWindow ( pMyWindowData->hwnd, TRUE );
- }
- else
- EraseTimedInk ( pMyWindowData );
- };
- return ( (MRESULT) FALSE );
- }
-
- default:
- break;
- };
-
- return( (MRESULT) WinDefWindowProc ( hWnd, msg, mp1, mp2 ) );
- };
-